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
23139a3a4bc965704498ea9f22876627cda96ff9a77eBo LiuTEST_P(SpdySessionTest, DISABLED_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)
23559a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu// TODO(rch): re-enable this.
23569a3a4bc965704498ea9f22876627cda96ff9a77eBo LiuTEST_P(SpdySessionTest, DISABLED_ConnectionPooledWithTlsChannelId) {
2357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
23587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
23622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
23642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
2368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
23712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
2375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
2376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
2377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
2378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
23822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
23842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssl.channel_id_sent = true;
2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
23872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
23892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
23917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
23982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(rtenneti): Define a helper class/methods and move the common code in
2401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // this file.
24022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
24037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32 max_concurrent_streams = 1;
2407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[kSpdySettingsIds1] =
2408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
24092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
241190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
2412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
2416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
24172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 1),
2419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req1, 2),
2420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req2, 5),
2421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req3, 8),
24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets max concurrent
2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // streams to 1.
2426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
2427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
24282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
24372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
2440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp1, 3),
2441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body1, 4),
2442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 6),
2443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body2, 7),
2444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp3, 9),
2445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body3, 10),
2446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockRead(ASYNC, 0, 11)  // EOF
24472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
24552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
24577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
24582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the settings frame.
2460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
2461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2463a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
246490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
24672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2469a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
24702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
24725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
24805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
24897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
24952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 1st stream is activated and then closed.
2497a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
2498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(4);
2499a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 2nd stream.
2508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
2512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate2(stream2);
2516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
2521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate2.stream_id());
2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
2525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
2526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate2.stream_id());
2527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 3rd stream.
2534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
25387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate3(stream3);
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate3.stream_id());
2550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, delegate3.stream_id());
2553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
25567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
25777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
2580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
2582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
2584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
25875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
2591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
25955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback2.callback()));
2601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
26035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback3.callback()));
2609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
26127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the first stream; this will allow the second stream to be created.
2615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_stream1.get() != NULL);
2616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
2620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2624a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the second stream; this will allow the third stream to be created.
2625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
2627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2629a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback3.WaitForResult());
2630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
26327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancel the third stream.
2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream3->Cancel();
2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream3.get());
2638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
26407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop reads data from the socket
2644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// without yielding.  This test makes 32k - 1 bytes of data available
2645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// on the socket for reading. It then verifies that it has read all
2646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the available data without yielding.
2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kPayloadSize =
2661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDataStream test_stream;
2663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  char* payload_data = payload->data();
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test_stream.GetBytes(payload_data, kPayloadSize);
2666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> partial_data_frame(
2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> finish_data_frame(
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // bytes.
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
2678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 2),
2679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create SpdySession and SpdyStream and send the request.
2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
2688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
26957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
26975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // post a task.
2713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until 1st read.
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
2720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has not
2722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posted a task.
2723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify task observer's executed_count is zero, which indicates DoRead read
2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // all the available data.
2728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
27292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
27302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
27312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
27322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop yields while reading the
2734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// data. This test makes 32k + 1 bytes of data available on the socket
2735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for reading. It then verifies that DoRead has yielded even though
2736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// there is data available for it to read (i.e, socket()->Read didn't
2737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// return ERR_IO_PENDING during socket reads).
27387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
27392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
27407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
27412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
274390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
27442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
27452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
27462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
27472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
27512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPayloadSize =
2752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
27532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
27542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
27552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* payload_data = payload->data();
27562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(payload_data, kPayloadSize);
27572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> partial_data_frame(
27592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
27602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(
27612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
27622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
27642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
27662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
27672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
27682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 2),
27692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
27702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
27712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
27722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
27732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 7)  // EOF
27742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
27752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
27772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
27782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
27792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
27802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
27812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
27822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
27842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
27867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
27872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2789a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
279090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
279190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
27922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
27932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2794a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2795a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
27962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
279790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
279990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
28012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
2804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
28052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2807a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
28082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2809a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
28102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
28112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
28142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(6);
2815a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
28162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
28182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for it
28192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to read.
28202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
28212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
28222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
28232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
28242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop() tests interactions of yielding
2826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// + async, by doing the following MockReads.
28272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
28282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
28292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
28302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The above reads 26K synchronously. Since that is less that 32K, we
2832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// will attempt to read again. However, that DoRead() will return
2833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ERR_IO_PENDING (because of async read), so DoReadLoop() will
2834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// yield. When we come back, DoRead() will read the results from the
2835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// async read, and rest of the data synchronously.
28367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
28372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
28387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
28392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
284090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
284190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
28422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
28432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
28442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
28492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
28502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kEightKPayloadSize =
2851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
28522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> eightk_payload(
28532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kEightKPayloadSize));
28542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* eightk_payload_data = eightk_payload->data();
28552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
28562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Build buffer of 2k size.
28582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream2;
28592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
28602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> twok_payload(
28612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kTwoKPayloadSize));
28622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* twok_payload_data = twok_payload->data();
28632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
28642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
28662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
28672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
28682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
28692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
28702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, "h", 1, DATA_FLAG_FIN));
28712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
28732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
28752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
28762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 2),
28772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
28782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
28792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
28802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 6, ASYNC),
28812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
28822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
28832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
28842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
28852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
28862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 12)  // EOF
28872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
28902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
28912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
28922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
28932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
28942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
28952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
28972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
28997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
29002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2902a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
290390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
290490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
29052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
29062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2907a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2908a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
29092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
291090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2911b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
291290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2913ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
29142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posting of tasks.
2917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2920a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
29212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2922a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
29232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
29242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2925ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2926ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
29272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(12);
2928a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
29292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
29312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for
29322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it to read.
29332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
29342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
29352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
29362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
29372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// nothing blows up.
2940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
29412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
29427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
29432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
294490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
294590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
29462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
29472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
29482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
29517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
295290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
29532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
29552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
29562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body1, 2),
29572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway, 3),
29582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
29612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
29622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
29632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
29642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
29652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
29662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
29682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
29707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
29712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2973a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
297490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
297590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
297690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
297790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
29782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
29792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
29802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
298190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2982b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
298390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
29852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
29872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
29882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
29892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
29902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until GoAway.
2992ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2993a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
29942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
29952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
2996ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
29972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
29982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Within this framework, a SpdySession should be initialized with
30007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// flow control disabled for protocol version 2, with flow control
30017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enabled only for streams for protocol version 3, and with flow
30027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// control enabled for streams and sessions for higher versions.
30037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ProtocolNegotiation) {
30042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
30052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
30082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
30092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
30102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
30112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
30122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
30132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
3015ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
30172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(),
30197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            session->buffered_spdy_framer_->protocol_version());
30204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (GetParam() == kProtoDeprecatedSPDY2) {
30217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
30227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (GetParam() == kProtoSPDY3) {
30257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
30267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
30297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
30307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->flow_control_state());
30317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
30327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_send_window_size_);
3033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSpdySessionInitialWindowSize,
30347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_recv_window_size_);
30357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
30362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
30372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held.
3041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnection) {
3042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
30462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
30502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
30522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
3053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
30552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
30572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
30612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3064e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3065ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
30667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
30682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
30743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port2, false, false,
3075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
30812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
3085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3086ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
30872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held, in the case the SPDY session
3091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// has an alias.
3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
30972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
31022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
31032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
31042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "1.com", "192.168.0.2", std::string());
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "2.com", "192.168.0.2", std::string());
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Not strictly needed.
3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "3.com", "192.168.0.3", std::string());
31152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
31172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
31212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
31267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostResolver::RequestInfo info(key2.host_port_pair());
3133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddressList addresses;
3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Pre-populate the DNS cache, since a synchronous resolution is required in
3135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // order to create the alias.
31363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.host_resolver->Resolve(info,
31373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       DEFAULT_PRIORITY,
31383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       &addresses,
31393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       CompletionCallback(),
31403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       NULL,
31413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       BoundNetLog());
3142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Get a session for |key2|, which should return the session created earlier.
3143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session2 =
31447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(session1.get(), session2.get());
3146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port3("3.com", 80);
3152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params3(
31533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port3, false, false,
3154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback3.callback(), pool, BoundNetLog()));
3159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
31607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
3164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
3166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session2 == NULL);
3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Tests that when a SPDY session becomes idle, it closes itself if there is
31703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// a lower layer pool stalled on the per-pool socket limit.
31713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
3182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> cancel1(
3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 1),
3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*cancel1, 1),
3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
31903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                writes, arraysize(writes));
3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockRead http_reads[] = {
31953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
31973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
31983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     NULL, 0);
31993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  http_data.set_connect_data(connect_data);
32003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
32013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
3208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a SPDY session.
32105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
3211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair(url1.host(), 80),
3212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
32147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a stream using the session, and send a request.
3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session1, url1, DEFAULT_PRIORITY,
3223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                BoundNetLog());
3224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
3226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
3227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
3229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            spdy_stream1->SendRequestHeaders(
3232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                headers1.Pass(), NO_MORE_DATA_TO_SEND));
3233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
32423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port2, false, false,
3243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Running the message loop should cause the socket pool to ask the SPDY
3251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session to close an idle socket, but since the socket is in use, nothing
3252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // happens.
3253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
3254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(callback2.have_result());
3256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Cancelling the request should result in the session's socket being
32583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // closed, since the pool is stalled.
3259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
32623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_FALSE(pool->IsStalled());
32633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
3264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that SpdySessionKey and therefore SpdySession is different when
3267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// privacy mode is enabled or disabled.
3268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", 443);
3272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_ENABLED);
3274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_DISABLED);
3276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Enabled to the pool.
3281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_enabled =
32827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Disabled to the pool.
3288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_disabled =
32897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
32957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
32997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that creates another stream when its stream is closed.
3304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
3306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3307bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session)
3308bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
3309bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_(session) {}
3310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~StreamCreatingDelegate() {}
3312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3313bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
33145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GURL url(kDefaultURL);
3315bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    ignore_result(
3316bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3317bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                  session_, url, MEDIUM, BoundNetLog()));
3318bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
3319bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3320bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
3321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const base::WeakPtr<SpdySession> session_;
3322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
3323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Create another stream in response to a stream being reset. Nothing
3325bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// should blow up. This is a regression test for
3326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// http://crbug.com/263690 .
3327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3330bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3332bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
3333bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3334bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
3335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockWrite(*req, 0),
3336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3337bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> rst(
3339bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
3341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockRead(*rst, 1),
3342bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3343bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3344bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3345bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
3346bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
3347bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3348bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3349bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
3350bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3351bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
3352bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3353bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
33545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
3355bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
3356bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3357bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
3358bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
3359bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3360bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3361bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate delegate(spdy_stream, session);
3362bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
3363bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3364bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
3365bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3366bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3367bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3368bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3369bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3370bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3371bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3372bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3373bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
3374bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3375bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Cause the stream to be reset, which should cause another stream
3376bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // to be created.
3377bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3378bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3379bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
3380bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
3381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
3382bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
3383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
3384bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
3386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY3)
3389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // gets sent.
3393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
3394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32 window_size = 1;
3395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets
3399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // INITIAL_WINDOW_SIZE.
3400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
3402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
3403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame, 0),
3405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
3410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
3411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
3412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               writes, arraysize(writes));
3417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
3418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
3428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);  // Process the SETTINGS frame, but not the EOF
3432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Release the first one, this will allow the second to be created.
3437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
3439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
3441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
3444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
3446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
3447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3.1 and above.
3450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}RecvWindowSize should properly
3452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session receive window size for SPDY 3.1 and higher. In
3453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// addition, SpdySession::IncreaseRecvWindowSize should trigger
3454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// sending a WINDOW_UPDATE frame for a large enough delta.
3455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
3468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
3469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
3470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSpdySessionInitialWindowSize + delta_window_size));
3471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*window_update, 0),
3473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
3476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(delta_window_size);
3489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Should trigger sending a WINDOW_UPDATE frame.
3494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kSpdySessionInitialWindowSize,
3497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
3504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseRecvWindowSize(
3505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize + delta_window_size +
3506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize);
3507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
3508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_recv_window_size_);
3509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}SendWindowSize should properly
3513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session send window size when the "enable_spdy_31" flag
3514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is set.
3515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustSendWindowSize) {
3516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
3532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseSendWindowSize(delta_window_size);
3540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_send_window_size_);
3542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseSendWindowSize(delta_window_size);
3544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Incoming data for an inactive stream should not cause the session
3548c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// receive window size to decrease, but it should cause the unacked
3549c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// bytes to increase.
3550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 0),
3560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3578c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3580ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A delegate that drops any received data.
3584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
3586a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           base::StringPiece data)
358890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : StreamDelegateSendImmediate(stream, data) {}
3589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DropReceivedDataDelegate() {}
3591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Drop any received data.
3593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
3595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but use a delegate that drops its received
3597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data. The receive window should still increase to its original
3598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value, i.e. we shouldn't "leak" receive window bytes.
35997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
36007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
36117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
36147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
3619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
36237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
362690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
3627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
3628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
3632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
36447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3647a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
364890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
364990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DropReceivedDataDelegate delegate(stream, msg_data);
3654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
365690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
365890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
365990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
3666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3674a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but close the stream before its data frame
3683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// can be written to the socket. The send window should then increase
3684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to its original value, i.e. we shouldn't "leak" send window bytes.
36857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
36867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
36977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
37197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3722a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
372390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
372490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
373190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3732b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
373390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
373490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
3744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            session->session_send_window_size_);
3750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Closing the stream should increase the session's send window.
3752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3753a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Send data back and forth; the send and receive windows should
37612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// change appropriately.
37627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
37637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
37647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
37652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
37672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int32 msg_data_size = 100;
37692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
37702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
37722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
37747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
37757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
37762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
37777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
37787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
37792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
37822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
37867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
37877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
37882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
378990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
37902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
37912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 4),
3795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
37962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
37992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
38002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
38012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
38022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
38042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
38062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
38087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
38092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
3811a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
381290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
381390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
38142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
38152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
38162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
38182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
38192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3821b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
382290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
382390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
38252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
38312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
38562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
38632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
38662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
38672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
38692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Draining the delegate's read queue should increase the session's
3871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // receive window.
3872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
38752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->Close();
3877a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
38782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
38842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
38852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Given a stall function and an unstall function, runs a test to make
3887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sure that a stream resumes after unstall.
38887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SpdySessionTest::RunResumeAfterUnstallTest(
38897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
389090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
389190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        unstall_function) {
38922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
38932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
38942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
38987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
38997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
390090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(
39017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
39022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
39052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(
39087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
39092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
39107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
39112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
3913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3), // EOF
39142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
39172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
39182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
39192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
39202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
39222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
39257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
39262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
39272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
39282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3929a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
393090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
393190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
39322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
39332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
39352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
39362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
393890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
39392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
394090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3941b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
394290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
394390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
39462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  stall_function.Run(session.get(), stream.get());
39482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
39502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
39522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
39542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
39562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
39582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
39602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
39622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
396390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
396490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
39652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
39662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Run the resume-after-unstall test with all possible stall and
3968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// unstall sequences.
3969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
39717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionOnly,
3976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
39777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionOnly,
3978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Equivalent to
39827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
39837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
39847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamOnly,
3989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
39907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamOnly,
3991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
39957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
4000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
40067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
40177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
40287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
4033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4037c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 0. The
40392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// streams should resume in priority order when that window is then
40402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// increased.
40417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
40427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
40462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
40472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
40492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
40517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
40527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
40532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
40547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
40557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
405690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
40577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
405890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
40597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
40602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 2),
4064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body1, 3),
40652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
40662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
40687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
40692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 4),
4071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
4072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6), // EOF
40732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
40742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
40762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
40772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
40782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
40792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
40812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4083ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
40847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
40852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
40862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
40872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4088a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
408990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
409090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
40912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
40922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4093a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
40942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
40952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
40972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4098a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
409990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
410090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
41012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
41022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
41042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
41052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
41072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
41092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
41122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
411390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
411490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
411590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
411690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
41192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
412190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
41222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
412390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
412490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
412590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
412690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
412790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
413090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
413190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
413290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
41332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
41342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should unstall only stream2.
4136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
41372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
41392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
414190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
41422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
41442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should then unstall stream1.
4147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
41482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
41532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
41552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
41562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate1.send_headers_completed());
4158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
41602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate2.send_headers_completed());
41622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
416390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
41642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
416590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
416690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Delegate that closes a given stream after sending its body.
4169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass StreamClosingDelegate : public test::StreamDelegateWithBody {
4170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
4171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        base::StringPiece data)
4173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : StreamDelegateWithBody(stream, data) {}
4174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~StreamClosingDelegate() {}
4176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    stream_to_close_ = stream_to_close;
4179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataSent() OVERRIDE {
4182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    test::StreamDelegateWithBody::OnDataSent();
4183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (stream_to_close_.get()) {
4184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream_to_close_->Close();
4185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(NULL, stream_to_close_.get());
4186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
4187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
4190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream_to_close_;
4191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
4192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
41932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to
4194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle deleted streams.
4195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
41967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
41977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
41987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
41992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
42002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
42012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
42032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
42057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
42072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
42087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
4211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
4214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
42152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 2),
4219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 3),
42202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
42232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 4),
4225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5), // EOF
42262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
42292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
42302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
42312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
42322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
42342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
42377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
42382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
42392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
42402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
424290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
424390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
42442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
42452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
424690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
42472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
42482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
42502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
425290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
425390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
42542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
42552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
42572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
42582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
42602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 =
4262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream3.get() != NULL);
4265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
4268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream3->HasUrlFromHeaders());
4270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
42722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
42742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
42762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
427790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
427890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
427990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
428090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
42832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
428590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
42862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
428790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
428890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
428990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
429090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
429190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
429490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
429590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
429690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
42972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
42982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
4300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
4304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, stream3->stream_id());
4308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id1 = stream1->stream_id();
4311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id2 = stream2->stream_id();
4312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id3 = stream3->stream_id();
4313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close stream1 preemptively.
4315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream1.get());
4317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id3));
43217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream2, which should then close stream3.
4323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delegate2.set_stream_to_close(stream3);
4324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
4325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
4328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id3));
4333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
4335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
4336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, delegate3.WaitForClose());
4340a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4343a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate3.send_headers_completed());
4349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
4352a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
4353a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Cause a stall by reducing the flow control send window to
4355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle the session itself
4356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// being closed.
4357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
43597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
43607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kStreamUrl[] = "http://www.google.com/";
4362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
4363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
4365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
436690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
4367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
4370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
4373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  MockWrite writes[] = {
4375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4377a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  };
4378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 2), // EOF
4381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
4384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
4385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.set_connect_data(connect_data);
4387a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
4391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
43927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
4395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream1 =
4397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream1.get() != NULL);
4400a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream1->SetDelegate(&delegate1);
4403a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 =
440790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream2.get() != NULL);
4410a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
4413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4415a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4418a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StallSessionSend(session.get());
4420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
4422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4427a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, stream1->stream_id());
4430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4431a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
4435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4438a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, stream2->stream_id());
4441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
444290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
444490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream1.
4446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
444790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close the session (since we can't do it from within the delegate
4449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // method, since it's in the stream's loop).
44507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
4452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
445390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
445590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
445890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
446190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
446490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
446690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
446790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
4470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
4471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
4473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
4475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0,
4478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GOAWAY_FLOW_CONTROL_ERROR,
4479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "the receive window size of 1"));
4481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {
4482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockRead reads[] = {
4488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DeterministicSocketData data(
4492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
4493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.set_connect_data(connect_data);
4494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CreateDeterministicNetworkSession();
4497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
4499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL url(kDefaultURL);
4502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_TRUE(spdy_stream.get() != NULL);
4505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
4506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
4507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
4509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
4510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(1);  // Write request.
4513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Put session on the edge of overflowing it's recv window.
4515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session->session_recv_window_size_ = 1;
4516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Read response headers & body. Body overflows the session window, and a
4518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // goaway is written.
4519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(3);
4520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
4521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
4524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, SplitHeaders) {
4527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL kStreamUrl("http://www.google.com/foo.dat");
4528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock headers;
4529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  headers["alpha"] = "beta";
4531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock request_headers;
4533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock response_headers;
4534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SplitPushedHeadersToRequestAndResponse(
4536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string alpha_val =
4540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (it == response_headers.end()) ? std::string() : it->second;
4541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ("beta", alpha_val);
4542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL request_url =
4544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(kStreamUrl, request_url);
4546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapFramerErrorToProtocolError, MapsValues) {
4549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_CONTROL_FRAME,
4551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapFramerErrorToNetError, MapsValue) {
4563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ERR_SPDY_FRAME_SIZE_ERROR,
4571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
45725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
45735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
45745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapRstStreamStatusToProtocolError, MapsValues) {
45755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
45775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
45795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
4581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapNetErrorToGoAwayStatus, MapsValue) {
4584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
4585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
4586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
4587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
4588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
4589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
4590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
4591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
4592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
4593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
4594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
45955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
45965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
45975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
4598