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)
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/base64.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/run_loop.h"
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/test/histogram_tester.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_data_directory.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/test_data_stream.h"
19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "net/socket/client_socket_pool_manager.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/socket/socket_test_util.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_session_test_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_stream_test_util.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/cert_test_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestUrl[] = "http://www.example.org/";
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestHost[] = "www.example.org";
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kTestPort = 80;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kBodyData[] = "Body data";
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kBodyDataSize = arraysize(kBodyData);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic base::TimeDelta g_time_delta;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeTicks TheNearFuture() {
46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return base::TimeTicks::Now() + g_time_delta;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class SpdySessionTest : public PlatformTest,
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        public ::testing::WithParamInterface<NextProto> {
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Functions used with RunResumeAfterUnstallTest().
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallSessionOnly(SpdySession* session,
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          SpdyStream* stream,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          int32 delta_window_size) {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamOnly(SpdySession* session,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         SpdyStream* stream,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         int32 delta_window_size) {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallSessionStream(SpdySession* session,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            SpdyStream* stream,
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int32 delta_window_size) {
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamSession(SpdySession* session,
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            SpdyStream* stream,
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int32 delta_window_size) {
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdySessionTest()
102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)            HttpNetworkSession::NORMAL_SOCKET_POOL)),
104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)            HttpNetworkSession::NORMAL_SOCKET_POOL)),
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_(GetParam()),
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        session_deps_(GetParam()),
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        spdy_session_pool_(NULL),
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        test_url_(kTestUrl),
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        test_host_port_pair_(kTestHost, kTestPort),
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        key_(test_host_port_pair_, ProxyServer::Direct(),
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             PRIVACY_MODE_DISABLED) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual ~SpdySessionTest() {
116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Important to restore the per-pool limit first, since the pool limit must
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // always be greater than group limit, and the tests reduce both limits.
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ClientSocketPoolManager::set_max_sockets_per_pool(
119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ClientSocketPoolManager::set_max_sockets_per_group(
121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    g_time_delta = base::TimeDelta();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CreateDeterministicNetworkSession() {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_session_ =
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    spdy_session_pool_ = http_session_->spdy_session_pool();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CreateNetworkSession() {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_session_ =
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SpdySessionDependencies::SpdyCreateSession(&session_deps_);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    spdy_session_pool_ = http_session_->spdy_session_pool();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StallSessionSend(SpdySession* session) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Reduce the send window size to 0 to stall.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (session->session_send_window_size_ > 0) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->DecreaseSendWindowSize(
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session->IncreaseSendWindowSize(delta_window_size);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamSend(SpdyStream* stream) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Reduce the send window size to 0 to stall.
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (stream->send_window_size() > 0) {
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream->DecreaseSendWindowSize(
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream->IncreaseSendWindowSize(delta_window_size);
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void RunResumeAfterUnstallTest(
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          unstall_function);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Original socket limits.  Some tests set these.  Safest to always restore
170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // them once each test has been run.
171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int old_max_group_sockets_;
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int old_max_pool_sockets_;
173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  SpdyTestUtil spdy_util_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySessionDependencies session_deps_;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<HttpNetworkSession> http_session_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySessionPool* spdy_session_pool_;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL test_url_;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostPortPair test_host_port_pair_;
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySessionKey key_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NextProto,
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdySessionTest,
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    testing::Values(kProtoDeprecatedSPDY2,
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a SPDY session that will fail during
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// initialization. Nothing should blow up.
191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, InitialReadError) {
192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_TRUE(session);
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Flush the read.
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::RunLoop().RunUntilIdle();
199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_FALSE(session);
200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// A helper class that vends a callback that, when fired, destroys a
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// given SpdyStreamRequest.
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StreamRequestDestroyingCallback() {}
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual ~StreamRequestDestroyingCallback() {}
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    request_ = request.Pass();
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CompletionCallback MakeCallback() {
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                      base::Unretained(this));
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void OnComplete(int result) {
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    request_.reset();
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetResult(result);
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<SpdyStreamRequest> request_;
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Request kInitialMaxConcurrentStreams streams.  Request two more
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// streams, but have the callback for one destroy the second stream
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// request. Close the session. Nothing should blow up. This is a
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// regression test for http://crbug.com/250841 .
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockRead reads[] = {MockRead(ASYNC, 0, 0), };
2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  data.set_connect_data(connect_data);
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CreateDeterministicNetworkSession();
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create the maximum number of concurrent streams.
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SpdyStreamRequest request1;
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StreamRequestDestroyingCallback callback1;
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  session,
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  test_url_,
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  MEDIUM,
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  BoundNetLog(),
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  callback1.MakeCallback()));
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |callback2| is never called.
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  TestCompletionCallback callback2;
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   session,
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   test_url_,
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   MEDIUM,
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   BoundNetLog(),
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   callback2.callback()));
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callback1.SetRequestToDestroy(request2.Pass());
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A session receiving a GOAWAY frame with no active streams should close.
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0),
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame immediately with no active
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// streams should then close.
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0, SYNCHRONOUS),
325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.StopAfter(1);
333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::WeakPtr<SpdySession> session =
335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      TryCreateInsecureSpdySessionExpectingFailure(
336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::RunLoop().RunUntilIdle();
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_FALSE(session);
340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame with active streams should close
344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// when the last active stream is closed.
345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockRead(*goaway, 2),
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req1, 0),
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req2, 1),
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
375a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(2);
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(3u, spdy_stream2->stream_id());
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Read and process the GOAWAY frame.
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(session->IsStreamActive(3));
409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Should close the session.
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_stream1->Close();
416a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session receive two GOAWAY frames, with the last one causing
423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the last active stream to be closed. The session should then be
424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// closed after the second GOAWAY frame.
425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayTwice) {
426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway1, 2),
433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway2, 3),
434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req1(
437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req2(
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req1, 0),
442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req2, 1),
443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the first GOAWAY frame.
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
491a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the second GOAWAY frame, which should close the
496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // session.
497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session with active streams receive a GOAWAY frame and then
503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// close it. It should handle the close properly (i.e., not try to
504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// make itself unavailable in its pool twice).
505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 2),
512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 3)  // EOF
513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req1(
515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req2(
517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req1, 0),
520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req2, 1),
521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
573ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
58046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Process a joint read buffer which causes the session to begin draining, and
58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// then processes a GOAWAY. The session should gracefully drain. Regression test
58246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// for crbug.com/379469
58346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_P(SpdySessionTest, GoAwayWhileDraining) {
58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockWrite writes[] = {
58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateMockWrite(*req, 0),
59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  size_t joint_size = goaway->size() * 2 + body->size();
59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Compose interleaved |goaway| and |body| frames into a single read.
59846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<char[]> buffer(new char[joint_size]);
59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  {
60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    size_t out = 0;
60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], goaway->data(), goaway->size());
60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += goaway->size();
60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], body->data(), body->size());
60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += body->size();
60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], goaway->data(), goaway->size());
60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += goaway->size();
60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_EQ(out, joint_size);
60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SpdyFrame joint_frames(buffer.get(), joint_size, false);
61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockRead reads[] = {
61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MockRead(ASYNC, 0, 3)  // EOF
61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DeterministicSocketData data(
61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  data.set_connect_data(connect_data);
62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CreateDeterministicNetworkSession();
62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::WeakPtr<SpdySession> session =
62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
62546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GURL url(kDefaultURL);
62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
62846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
63046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
63146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
63246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
63346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
63446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
63546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
63646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  data.RunFor(3);
63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
63946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
64046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Stream and session closed gracefully.
64146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(delegate.StreamIsClosed());
64246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
64346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
64446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(session == NULL);
64546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
64646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a stream after receiving a GOAWAY frame. It should
648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// fail.
649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
653ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
673ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
680ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
688ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyStreamRequest stream_request;
700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rv = stream_request.StartRequest(
701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CompletionCallback());
703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_FAILED, rv);
704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process EOF.
706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Receiving a SYN_STREAM frame after a GOAWAY frame should result in
712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the stream being refused.
713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, SynStreamAfterGoAway) {
714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
715ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame>
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*push, 2),
723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> rst(
728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*rst, 3)
732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
739ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
743ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // and EOF.
771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
772cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A session observing a network change with active streams should close
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when the last active stream is closed.
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRead reads[] = {
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MockRead(ASYNC, 0, 1)  // EOF
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockWrite writes[] = {
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateMockWrite(*req1, 0),
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               writes, arraysize(writes));
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.set_connect_data(connect_data);
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CreateDeterministicNetworkSession();
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream =
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                GURL(kDefaultURL), MEDIUM, BoundNetLog());
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(1);
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1u, spdy_stream->stream_id());
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_session_pool_->OnIPAddressChanged();
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The SpdySessionPool behavior differs based on how the OSs reacts to
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For OSs where the TCP connections will close upon relevant network
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // changes, SpdySessionPool doesn't need to force them to close, so in these
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // cases verify the session has become unavailable but remains open and the
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // pre-existing stream is still active.
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session->IsStreamActive(1));
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Should close the session.
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->Close();
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream.get());
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClientPing) {
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.enable_ping = true;
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
849a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*read_ping, 1),
852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 0, 2)  // EOF
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
854a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 0),
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
8667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
868a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
86990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
87290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks before_ping_time = base::TimeTicks::Now();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session->set_connection_at_risk_of_loss_time(
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromSeconds(-1));
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->SendPrefacePingIfNoneInFlight();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
883ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(before_ping_time);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, session->pings_in_flight());
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(session->check_ping_status_pending());
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->last_activity_time(), before_ping_time);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ServerPing) {
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
904a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*read_ping),
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
909a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*write_ping),
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
920ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
9217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
923a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
92790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
930ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
93190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
936a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Cause a ping to be sent out while producing a write. The write loop
940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// should handle this properly, i.e. another DoWriteLoop task should
941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// not be posted. This is a regression test for
942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// http://crbug.com/261043 .
943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, PingAndWriteLoop) {
944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.enable_ping = true;
945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.time_func = TheNearFuture;
946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
948a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
953ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 1),
954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
955ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
963ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
970ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
971ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
9725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
975ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, LOWEST, BoundNetLog());
976ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
977ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Shift time so that a ping will be sent out.
984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  g_time_delta = base::TimeDelta::FromSeconds(11);
985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
987ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
988ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
990ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
991cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
992cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const SpdyStreamId kLastStreamId = 0x7fffffff;
993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
996cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // fixed to allow for two stream ID assignments, and three concurrent
997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // streams. Four streams are started, and two are activated. Verify the
998cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // session goes away, and that the created (but not activated) and
999cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stalled streams are aborted. Also verify the activated streams complete,
1000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // at which point the session closes.
1001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
1005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(
1012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1013cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(
1014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
1017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(ASYNC, 0, 6)  // EOF
1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(
1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1033cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1034cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateDeterministicNetworkSession();
1035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1036cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1037cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix stream_hi_water_mark_ to allow for two stream activations.
1039cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->stream_hi_water_mark_ = kLastStreamId - 2;
1040cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix max_concurrent_streams to allow for three stream creations.
1041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->max_concurrent_streams_ = 3;
1042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create three streams synchronously, and begin a fourth (which is stalled).
1044cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url(kDefaultURL);
1045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate1(stream1);
1048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->SetDelegate(&delegate1);
1049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate2(stream2);
1053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream2->SetDelegate(&delegate2);
1054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate3(stream3);
1058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream3->SetDelegate(&delegate3);
1059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyStreamRequest request4;
1061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestCompletionCallback callback4;
1062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
1063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  session,
1065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  url,
1066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  MEDIUM,
1067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  BoundNetLog(),
1068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  callback4.callback()));
1069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(3u, session->num_created_streams());
1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Activate stream 1. One ID remains available.
1076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->SendRequestHeaders(
1077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<SpdyHeaderBlock>(
1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NO_MORE_DATA_TO_SEND);
1080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);
1081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1083cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_active_streams());
1084cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(2u, session->num_created_streams());
1085cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1086cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Activate stream 2. ID space is exhausted.
1088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream2->SendRequestHeaders(
1089cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<SpdyHeaderBlock>(
1090cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NO_MORE_DATA_TO_SEND);
1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);
1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Active streams remain active.
1095cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kLastStreamId, stream2->stream_id());
1096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(2u, session->num_active_streams());
1097cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1098cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Session is going away. Created and stalled streams were aborted.
1099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
1103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Read responses on remaining active streams.
1106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(4);
1107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, delegate1.WaitForClose());
1108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, delegate2.WaitForClose());
1110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Session was destroyed.
1113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(session.get());
1115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that an unstalled pending stream creation racing with a new stream
1118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// creation doesn't violate the maximum stream concurrency. Regression test for
1119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// crbug.com/373858.
1120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
1134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix max_concurrent_streams to allow for one open stream.
1138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->max_concurrent_streams_ = 1;
1139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create two streams: one synchronously, and one which stalls.
1141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url(kDefaultURL);
1142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyStreamRequest request2;
1146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestCompletionCallback callback2;
1147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
1148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  session,
1150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  url,
1151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  MEDIUM,
1152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  BoundNetLog(),
1153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  callback2.callback()));
1154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Cancel the first stream. A callback to unstall the second stream was
1159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // posted. Don't run it yet.
1160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->Cancel();
1161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
1163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a third stream prior to the second stream's callback.
1166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // NOW run the message loop. The unstalled stream will re-stall itself.
1173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Cancel the third stream and run the message loop. Verify that the second
1178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stream creation now completes.
1179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream3->Cancel();
1180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
1185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.time_func = TheNearFuture;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_a_body(
11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(2, false));
12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, 0, 4, 1, "http://www.google.com/b.dat"));
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRead reads[] = {
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5),  // EOF
12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeterministicSocketData data(
12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.set_connect_data(connect_data);
12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CreateDeterministicNetworkSession();
1215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process the principal request, and the first push stream request & body.
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
12205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
12275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
12285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(3);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that there is one unclaimed push stream.
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
123390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySession::PushedStreamMap::iterator iter =
1234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      session->unclaimed_pushed_streams_.find(
1235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          GURL("http://www.google.com/a.dat"));
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session->flow_control_state_ ==
12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Unclaimed push body consumed bytes from the session window.
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              session->session_recv_window_size_);
12435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Shift time to expire the push stream. Read the second SYN_STREAM,
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and verify a RST_STREAM was written.
12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_time_delta = base::TimeDelta::FromSeconds(301);
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(2);
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the second pushed stream evicted the first pushed stream.
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iter = session->unclaimed_pushed_streams_.find(
1254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GURL("http://www.google.com/b.dat"));
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session->flow_control_state_ ==
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Verify that the session window reclaimed the evicted stream body.
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              session->session_recv_window_size_);
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Read and process EOF.
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(1);
1267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
12685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, FailedPing) {
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
1276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(
1280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(
1283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
129390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
129490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
129690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromSeconds(0));
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a PING frame.
1303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  session->WritePingFrame(1, false);
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0, session->pings_in_flight());
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->check_ping_status_pending());
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assert session is not closed.
1309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsAvailable());
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
13117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We set last time we have received any data in 1 sec less than now.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CheckPingStatus will trigger timeout because hung interval is zero.
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(now);
1318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
13217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Request kInitialMaxConcurrentStreams + 1 streams.  Receive a
1326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1.  Make
1327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// sure nothing blows up. This is a regression test for
1328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/57331 .
13297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OnSettings) {
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap new_settings;
1335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  new_settings[kSpdySettingsIds] =
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
133890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
133990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
1342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
1348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
1351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               writes, arraysize(writes));
1352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
13597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1369a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
137290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
137390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
137490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
137590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
1376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1381ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
1382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
1383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Allow the SETTINGS+ACK to write, so the session finishes draining.
1384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    data.RunFor(1);
1385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with a persisted value for max concurrent streams. Receive a
1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1 and which
1392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// also clears the persisted data. Verify that persisted data is
1393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// correct.
13947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettings) {
1395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
1396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
1399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SettingsMap new_settings;
1403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
140690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
140790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
1411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
1413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
1417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
1418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
1421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Initialize the SpdySetting with the default.
1423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      test_host_port_pair_,
1425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      kInitialMaxConcurrentStreams);
1428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_FALSE(
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1444a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyStreamRequest request;
1447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
145090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
145190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
1452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
1454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
14559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure that persisted data is cleared.
1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(
1459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Make sure session's max_concurrent_streams is correct.
1463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            session->max_concurrent_streams());
14657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
1467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
1468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with max concurrent streams set to 1.  Request two streams.
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// When the first completes, have the callback close its stream, which
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// should trigger the second stream creation.  Then cancel that one
1473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// immediately.  Don't crash.  This is a regression test for
1474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/63532 .
14757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelPendingCreateStream) {
14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
14862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the SpdySetting with 1 max concurrent streams.
14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
14922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1);
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create 2 more streams.  First will succeed.  Second will be pending.
1509a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
151090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
151190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
15122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a valgrind error if the callback is invoked when it's not supposed to be.
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
152290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
152390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                callback->callback()));
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the first one, this will allow the second to be created.
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->Cancel();
1527a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.CancelRequest();
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.reset();
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not crash when running the pending callback.
153390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
15372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[kSpdySettingsIds1] =
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
15497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY3) {
15507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    settings[kSpdySettingsIds2] =
15517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
15527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
155490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
155590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> initial_window_update(
1557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
1558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
1559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<MockWrite> writes;
1561a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetParam() == kProtoSPDY4) {
1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(
1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        MockWrite(ASYNC,
1564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefix,
1565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefixSize));
1566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_frame));
1568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetParam() >= kProtoSPDY31) {
1569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(CreateMockWrite(*initial_window_update));
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SettingsMap server_settings;
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 initial_max_concurrent_streams = 1;
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            initial_max_concurrent_streams);
1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<SpdyFrame> server_settings_frame(
1578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_util_.ConstructSpdySettings(server_settings));
15791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (GetParam() <= kProtoSPDY31) {
15801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    writes.push_back(CreateMockWrite(*server_settings_frame));
15811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads),
1586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                vector_as_array(&writes), writes.size());
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
15882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
15932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      initial_max_concurrent_streams);
1597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pool_peer.SetEnableSendingInitialData(true);
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
16057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(data.at_write_eof());
16062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
16092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<HttpServerProperties> test_http_server_properties =
16122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spdy_session_pool_->http_server_properties();
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_http_server_properties->SetSpdySetting(
16152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      2);
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
16202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
16212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->OnIPAddressChanged();
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
16232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, Initialize) {
1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingBoundNetLog log;
1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.net_log = log.bound().net_log();
1629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
1633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
1634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
1638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateNetworkSession();
1641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
16447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
164790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  log.GetEntries(&entries);
1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
1652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entries, 0,
1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::PHASE_NONE);
1658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0, pos);
1659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingNetLog::CapturedEntry entry = entries[pos];
1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NetLog::Source socket_source;
1662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  &socket_source));
1664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(socket_source.IsValid());
1665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_NE(log.bound().source().id, socket_source.id);
1666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
167290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
16742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway),
16752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CapturingBoundNetLog log;
1685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
16877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
169090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that the NetLog was filled reasonably.
16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  log.GetEntries(&entries);
16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that we logged SPDY_SESSION_CLOSE correctly.
17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
17022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entries, 0,
17032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::PHASE_NONE);
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pos < static_cast<int>(entries.size())) {
1707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CapturingNetLog::CapturedEntry entry = entries[pos];
1708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int error_code = 0;
1709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(OK, error_code);
1711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
1712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ADD_FAILURE();
1713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, 0, 0)  // EOF
1722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
1729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CapturingBoundNetLog log;
1731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, log.bound());
1733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Flush the read completion task.
1736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
1740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check that the NetLog was filled reasonably.
1742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
1743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  log.GetEntries(&entries);
1744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_LT(0u, entries.size());
1745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check that we logged SPDY_SESSION_CLOSE correctly.
1747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int pos =
1748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      net::ExpectLogContainsSomewhere(entries,
1749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      0,
1750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      net::NetLog::PHASE_NONE);
1752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (pos < static_cast<int>(entries.size())) {
1754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CapturingNetLog::CapturedEntry entry = entries[pos];
1755cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int error_code = 0;
1756cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ADD_FAILURE();
1760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1763116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(SpdySessionTest, SynCompressionHistograms) {
1764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.enable_compression = true;
1765116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1766116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
1767116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1768116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockWrite writes[] = {
1769116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CreateMockWrite(*req, 0),
1770116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
1771116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockRead reads[] = {
1772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    MockRead(ASYNC, 0, 1)  // EOF
1773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
1774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               writes, arraysize(writes));
1776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
1777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.set_connect_data(connect_data);
1778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CreateDeterministicNetworkSession();
1781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdySession> session =
1782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL url(kDefaultURL);
1785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
1786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
1788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
1789116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream->SetDelegate(&delegate);
1790116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1791116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
1792116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1794116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1795116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1796116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Write request headers & capture resulting histogram update.
179703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::HistogramTester histogram_tester;
1798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
179903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  data.RunFor(1);
1800116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Regression test of compression performance under the request fixture.
1801116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  switch (spdy_util_.spdy_version()) {
1802116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case SPDY2:
180303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      histogram_tester.ExpectBucketCount(
180403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "Net.SpdySynStreamCompressionPercentage", 0, 1);
1805116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
1806116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case SPDY3:
180703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      histogram_tester.ExpectBucketCount(
180803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "Net.SpdySynStreamCompressionPercentage", 30, 1);
1809116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
1810116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case SPDY4:
181103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      histogram_tester.ExpectBucketCount(
181203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "Net.SpdySynStreamCompressionPercentage", 82, 1);
1813116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
1814116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case SPDY5:
181503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      histogram_tester.ExpectBucketCount(
181603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "Net.SpdySynStreamCompressionPercentage", 82, 1);
1817116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
1818116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    default:
1819116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NOTREACHED();
1820116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1821116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1822116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read and process EOF.
1823116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
1824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::MessageLoop::current()->RunUntilIdle();
1825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(session == NULL);
1826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
1827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Queue up a low-priority SYN_STREAM followed by a high-priority
1829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// one. The high priority one should still send first and receive
1830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// first.
18317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Construct the request.
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_highest(
183590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_lowest(
183790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
1839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_highest, 0),
1840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_lowest, 1),
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_highest(
1844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_highest(
1846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
1847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_lowest(
1848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_lowest(
1850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, true));
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_highest, 2),
1853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_highest, 3),
1854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_lowest, 4),
1855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_lowest, 5),
1856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
18697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_lowest =
187490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
187590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
1876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_lowest);
1877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SetDelegate(&delegate_lowest);
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_highest =
188290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
188390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, HIGHEST, BoundNetLog());
1884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_highest);
1885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SetDelegate(&delegate_highest);
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Queue the lower priority one first.
1890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_lowest(
1892b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SendRequestHeaders(
1894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_highest(
1898b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SendRequestHeaders(
1900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1901ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(7);
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_lowest);
1906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_highest);
1907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate_lowest.stream_id());
1908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate_highest.stream_id());
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelStream) {
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 1, at HIGHEST priority, will be cancelled before it writes data.
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 2, at LOWEST priority, will be a full request and will be id 1.
191590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
191690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req2, 0),
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
19227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp2, 1),
19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body2, 2),
19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
19397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
1942a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
194390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
194490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
1947a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1948a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
1951a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
195290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
195390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
1956a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
1957a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
1960b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
196190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
1965b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
196690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->Cancel();
1972a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1974a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1978a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
1979a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate2.stream_id());
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->Cancel();
1982a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
1986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and then close the session. Nothing should blow up. Also a
1987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// regression test for http://crbug.com/139518 .
1988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2008ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
20097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2012a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
201390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
201490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2019a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
202090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
202190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
203290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
203390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2034ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
203590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
203690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
203790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
203890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2039ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the streams have not yet been activated and assigned an id.
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure we don't crash while closing the session.
20467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2048a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2049a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
2050a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2051a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate1.StreamIsClosed());
2052a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate2.StreamIsClosed());
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2055ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close, and
2059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// then close the session. Nothing should blow up.
2060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
20612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
20622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
20762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2080ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
20817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, HIGHEST, BoundNetLog());
2087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, LOWEST, BoundNetLog());
2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
2099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
2102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
2103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
2104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
21147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
2116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
2118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
21207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
2121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
2130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
2133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
2134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
21352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
21362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
21552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
21607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
21612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
21682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
2173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
21757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
2177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
21782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
2180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
21862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
21912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
2193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
21952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
21972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
2199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
2200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
22027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
2203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
2212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close,
2215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
22292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
22332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
22352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
22362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
22372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
22382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
22402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
22427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
22432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
224690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
22482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
22492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
22502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
2255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
22572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
2259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
2260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
22612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
2263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
2264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
22652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
226690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
2267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
226890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
22702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
227190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
227290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
22752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
22772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
22792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
22812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
2283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
22842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
22867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
22872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2289a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
22902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
22962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
22972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2298bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that closes a given session when the stream is closed.
2299bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass SessionClosingDelegate : public test::StreamDelegateDoNothing {
2300bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
2301bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2302bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session_to_close)
2303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
2304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_to_close_(session_to_close) {}
2305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~SessionClosingDelegate() {}
2307bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2308bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
2309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
2311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
2313bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session_to_close_;
2314bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
2315bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2316bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Close an activated stream that closes its session. Nothing should
2317bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// blow up. This is a regression test for http://crbug.com/263691 .
2318bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2319bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2320bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
2324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
2326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(
2328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // despite being queued second.
2331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
2332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*rst, 2),
2334bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
2337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockRead(ASYNC, 0, 3)  // EOF
2338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2339bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
2341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
2342bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2343bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2344bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
2345bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2346bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
2347bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2348bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
23495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
2350bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
2351bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2352bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
2353bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
2354bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2355bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2356bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate delegate(spdy_stream, session);
2357bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
2358bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2359bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2360bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
2361bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2362bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2363bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2364bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2365bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2366bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
2367bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2368bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
2369bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2370bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Ensure we don't crash while closing the stream (which closes the
2371bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // session).
2372bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->Cancel();
2373bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2374bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
2375bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
2376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(2);  // Write the RST_STREAM & GOAWAY.
2378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2379bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(session == NULL);
2380bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
2381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
238203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
23847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
2388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
2390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
23942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
2401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
2402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
2403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
2404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
2406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
24071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
24082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
2411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
24122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
24142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
24167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
24232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
24267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
24272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
24302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
24322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
2436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
24392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
2443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
2444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
2445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
2446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
2447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
2448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
24491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssl.channel_id_sent = true;
2453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
2454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
24552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
24572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
24597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
24652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(rtenneti): Define a helper class/methods and move the common code in
2469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // this file.
24702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
24717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32 max_concurrent_streams = 1;
2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[kSpdySettingsIds1] =
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
24772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
247990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
2480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
24852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 1),
2487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req1, 2),
2488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req2, 5),
2489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req3, 8),
24902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets max concurrent
2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // streams to 1.
2494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
2495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
24962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
25052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
2508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp1, 3),
2509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body1, 4),
2510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 6),
2511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body2, 7),
2512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp3, 9),
2513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body3, 10),
2514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockRead(ASYNC, 0, 11)  // EOF
25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
25162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
25182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
25257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
25262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the settings frame.
2528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
2529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2531a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
253290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
25342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
25352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2537a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
25382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
25405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
25485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
25577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 1st stream is activated and then closed.
2565a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
2566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(4);
2567a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 2nd stream.
2576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
2580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
25812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate2(stream2);
2584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
2585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2588ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
2589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2590a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate2.stream_id());
2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
2594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate2.stream_id());
2595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2600a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2601a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 3rd stream.
2602a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2603a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2604a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
26067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate3(stream3);
2610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
2611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
2612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
2615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate3.stream_id());
2618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
2620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, delegate3.stream_id());
2621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
26247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
2627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
26457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
2648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
2650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2651a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
2652a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2653a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2654a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
26555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
2659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
26635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback2.callback()));
2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
26715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback3.callback()));
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2678a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2679a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
26807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2682a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the first stream; this will allow the second stream to be created.
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_stream1.get() != NULL);
2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2687a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
2688a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2689a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2692a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the second stream; this will allow the third stream to be created.
2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
2695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback3.WaitForResult());
2698a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2699a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
27007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancel the third stream.
2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream3->Cancel();
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream3.get());
2706a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2707a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
27087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop reads data from the socket
2712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// without yielding.  This test makes 32k - 1 bytes of data available
2713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// on the socket for reading. It then verifies that it has read all
2714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the available data without yielding.
2715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kPayloadSize =
2729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDataStream test_stream;
2731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  char* payload_data = payload->data();
2733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test_stream.GetBytes(payload_data, kPayloadSize);
2734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> partial_data_frame(
2736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> finish_data_frame(
2738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // bytes.
2744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
2746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 2),
2747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
2751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create SpdySession and SpdyStream and send the request.
2754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
2756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
2761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
27637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
2775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // post a task.
2781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until 1st read.
2784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
2785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
2786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
2788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has not
2790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posted a task.
2791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
2792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify task observer's executed_count is zero, which indicates DoRead read
2795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // all the available data.
2796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
27972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
27982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
27992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
28002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop yields while reading the
2802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// data. This test makes 32k + 1 bytes of data available on the socket
2803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for reading. It then verifies that DoRead has yielded even though
2804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// there is data available for it to read (i.e, socket()->Read didn't
2805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// return ERR_IO_PENDING during socket reads).
28067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
28072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
28087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
28092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
281090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
281190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
28122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
28132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
28142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
28192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPayloadSize =
2820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
28212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
28222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
28232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* payload_data = payload->data();
28242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(payload_data, kPayloadSize);
28252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> partial_data_frame(
28272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
28282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(
28292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
28302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
28322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
28342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
28352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
28362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 2),
28372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
28382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
28392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
28402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
28412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 7)  // EOF
28422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
28452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
28462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
28472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
28482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
28492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
28502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
28522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
28547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
28552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2857a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
285890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
285990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
28602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
28612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2862a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2863a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
28642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
286790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
28692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2870ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
2872ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
28732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2875a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
28762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2877a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
28782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
28792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
28822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(6);
2883a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
28842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
28862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for it
28872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to read.
28882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
28892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
28902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
28912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
28922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop() tests interactions of yielding
2894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// + async, by doing the following MockReads.
28952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
28962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
28972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
28982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2899ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The above reads 26K synchronously. Since that is less that 32K, we
2900ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// will attempt to read again. However, that DoRead() will return
2901ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ERR_IO_PENDING (because of async read), so DoReadLoop() will
2902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// yield. When we come back, DoRead() will read the results from the
2903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// async read, and rest of the data synchronously.
29047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
29052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
29067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
29072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
290890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
290990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
29102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
29112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
29122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
29172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kEightKPayloadSize =
2919ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
29202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> eightk_payload(
29212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kEightKPayloadSize));
29222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* eightk_payload_data = eightk_payload->data();
29232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
29242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Build buffer of 2k size.
29262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream2;
29272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
29282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> twok_payload(
29292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kTwoKPayloadSize));
29302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* twok_payload_data = twok_payload->data();
29312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
29322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
29342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
29352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
29362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
29372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
29382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, "h", 1, DATA_FLAG_FIN));
29392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
29412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
29432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
29442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 2),
29452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
29462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
29472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
29482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 6, ASYNC),
29492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
29502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
29512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
29522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
29532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
29542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 12)  // EOF
29552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
29582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
29592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
29602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
29612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
29622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
29632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
29652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
29677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
29682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2970a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
297190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
297290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
29732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
29742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2975a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2976a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
29772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
297890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2979b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
298090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
29822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posting of tasks.
2985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
29862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2988a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
29892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2990a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
29912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
29922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2993ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2994ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
29952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(12);
2996a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
29972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
29992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for
30002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it to read.
30012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
30022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
30032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
30042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3006ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3007ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// nothing blows up.
3008ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
30092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
30112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
301290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
301390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
30142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
30152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
30162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
30172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
30197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
302090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
30212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
30232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
30242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body1, 2),
30252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway, 3),
30262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
30272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
30292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
30302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
30312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
30322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
30332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
30342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
30362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3037ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
30392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
3041a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
304290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
304390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
304490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
304590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
30462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
30472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
30482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
304990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
3050b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
305190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3052ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
30532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
30552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
30562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
30572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
30582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until GoAway.
3060ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
3061a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
30622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
30632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3064ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
30652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Within this framework, a SpdySession should be initialized with
30687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// flow control disabled for protocol version 2, with flow control
30697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enabled only for streams for protocol version 3, and with flow
30707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// control enabled for streams and sessions for higher versions.
30717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ProtocolNegotiation) {
30722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
30732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
30762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
30772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
30782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
30792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
30802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
30812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
3083ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
30852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(),
30877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            session->buffered_spdy_framer_->protocol_version());
30884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (GetParam() == kProtoDeprecatedSPDY2) {
30897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
30907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (GetParam() == kProtoSPDY3) {
30937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
30947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
30977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
30987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->flow_control_state());
30997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
31007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_send_window_size_);
3101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSpdySessionInitialWindowSize,
31027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_recv_window_size_);
31037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
31042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
31052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
31062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held.
3109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnection) {
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
31142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
31162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
31202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
3121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
31232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
31252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
31292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
31347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
31421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TransportSocketParams(
31431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          host_port2, false, false, OnHostResolutionCallback(),
31441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
31502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
3154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
31562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
31572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held, in the case the SPDY session
3160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// has an alias.
3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
31662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
31682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
31712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
31722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
31732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "1.com", "192.168.0.2", std::string());
3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "2.com", "192.168.0.2", std::string());
3181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Not strictly needed.
3182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "3.com", "192.168.0.3", std::string());
31842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
31862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
31902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
31957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostResolver::RequestInfo info(key2.host_port_pair());
3202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddressList addresses;
3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Pre-populate the DNS cache, since a synchronous resolution is required in
3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // order to create the alias.
32053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.host_resolver->Resolve(info,
32063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       DEFAULT_PRIORITY,
32073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       &addresses,
32083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       CompletionCallback(),
32093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       NULL,
32103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       BoundNetLog());
3211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Get a session for |key2|, which should return the session created earlier.
3212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session2 =
32137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(session1.get(), session2.get());
3215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
32162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
3220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port3("3.com", 80);
3221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params3(
32221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TransportSocketParams(
32231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          host_port3, false, false, OnHostResolutionCallback(),
32241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback3.callback(), pool, BoundNetLog()));
3229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
32307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
3234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
3236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session2 == NULL);
3237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Tests that when a SPDY session becomes idle, it closes itself if there is
32403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// a lower layer pool stalled on the per-pool socket limit.
32413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
3252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> cancel1(
3254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 1),
3257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*cancel1, 1),
3258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
32603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                writes, arraysize(writes));
3261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockRead http_reads[] = {
32653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
32663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
32673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
32683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     NULL, 0);
32693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  http_data.set_connect_data(connect_data);
32703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
32713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
3278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a SPDY session.
32805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
3281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair(url1.host(), 80),
3282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
32847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a stream using the session, and send a request.
3288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session1, url1, DEFAULT_PRIORITY,
3293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                BoundNetLog());
3294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
3296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
3297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
3299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            spdy_stream1->SendRequestHeaders(
3302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                headers1.Pass(), NO_MORE_DATA_TO_SEND));
3303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
33121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TransportSocketParams(
33131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          host_port2, false, false, OnHostResolutionCallback(),
33141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Running the message loop should cause the socket pool to ask the SPDY
3322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session to close an idle socket, but since the socket is in use, nothing
3323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // happens.
3324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
3325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(callback2.have_result());
3327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Cancelling the request should result in the session's socket being
33293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // closed, since the pool is stalled.
3330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
33333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_FALSE(pool->IsStalled());
33343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
3335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that SpdySessionKey and therefore SpdySession is different when
3338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// privacy mode is enabled or disabled.
3339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", 443);
3343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3344e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_ENABLED);
3345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3346e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_DISABLED);
3347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Enabled to the pool.
3352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_enabled =
33537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Disabled to the pool.
3359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_disabled =
33607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
33667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
33707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
33717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3374bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that creates another stream when its stream is closed.
3375bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3376bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
3377bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3378bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session)
3379bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
3380bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_(session) {}
3381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3382bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~StreamCreatingDelegate() {}
3383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3384bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
33855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GURL url(kDefaultURL);
3386bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    ignore_result(
3387bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3388bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                  session_, url, MEDIUM, BoundNetLog()));
3389bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
3390bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3391bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
3392bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const base::WeakPtr<SpdySession> session_;
3393bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
3394bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3395bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Create another stream in response to a stream being reset. Nothing
3396bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// should blow up. This is a regression test for
3397bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// http://crbug.com/263690 .
3398bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3399bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3400bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3401bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3402bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3403bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
3404bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3405bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
3406bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockWrite(*req, 0),
3407bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3408bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3409bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> rst(
3410bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3411bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
3412bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockRead(*rst, 1),
3413bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3414bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3415bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3416bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
3417bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
3418bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3419bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3420bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
3421bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3422bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
3423bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3424bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
34255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
3426bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
3427bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3428bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
3429bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
3430bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3431bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3432bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate delegate(spdy_stream, session);
3433bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
3434bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3435bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
3436bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3437bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3438bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3439bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3440bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3441bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3442bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3443bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3444bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
3445bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3446bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Cause the stream to be reset, which should cause another stream
3447bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // to be created.
3448bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3449bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3450bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
3451bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
3452bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
3453bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
3454bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
3455bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
3457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY3)
3460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // gets sent.
3464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
3465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32 window_size = 1;
3466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets
3470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // INITIAL_WINDOW_SIZE.
3471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
3473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
3474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame, 0),
3476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
3481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
3482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
3483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               writes, arraysize(writes));
3488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
3489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);  // Process the SETTINGS frame, but not the EOF
3503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Release the first one, this will allow the second to be created.
3508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
3510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
3512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
3515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
3517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3.1 and above.
3521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}RecvWindowSize should properly
3523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session receive window size for SPDY 3.1 and higher. In
3524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// addition, SpdySession::IncreaseRecvWindowSize should trigger
3525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// sending a WINDOW_UPDATE frame for a large enough delta.
3526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
3539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
3540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
3541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSpdySessionInitialWindowSize + delta_window_size));
3542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*window_update, 0),
3544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
3547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(delta_window_size);
3560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Should trigger sending a WINDOW_UPDATE frame.
3565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kSpdySessionInitialWindowSize,
3568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3573ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
3575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseRecvWindowSize(
3576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize + delta_window_size +
3577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize);
3578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
3579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_recv_window_size_);
3580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}SendWindowSize should properly
3584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session send window size when the "enable_spdy_31" flag
3585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is set.
3586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustSendWindowSize) {
3587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
36027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
3603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseSendWindowSize(delta_window_size);
3611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_send_window_size_);
3613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseSendWindowSize(delta_window_size);
3615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Incoming data for an inactive stream should not cause the session
3619c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// receive window size to decrease, but it should cause the unacked
3620c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// bytes to increase.
3621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 0),
3631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
36397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3649c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A delegate that drops any received data.
3655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
3657a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           base::StringPiece data)
365990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : StreamDelegateSendImmediate(stream, data) {}
3660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DropReceivedDataDelegate() {}
3662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Drop any received data.
3664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
3666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but use a delegate that drops its received
3668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data. The receive window should still increase to its original
3669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value, i.e. we shouldn't "leak" receive window bytes.
36707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
36717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
36827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
36857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
3690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
36947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
369790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
3698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
3699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
3703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
37157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3718a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
371990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
372090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DropReceivedDataDelegate delegate(stream, msg_data);
3725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3728b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
372990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
373090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
3737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3745a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but close the stream before its data frame
3754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// can be written to the socket. The send window should then increase
3755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to its original value, i.e. we shouldn't "leak" send window bytes.
37567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
37577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
37587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
37687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
37697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
37907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3793a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
379490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
379590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
379990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
380290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
380490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
380590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
3815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            session->session_send_window_size_);
3821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Closing the stream should increase the session's send window.
3823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3824a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Send data back and forth; the send and receive windows should
38322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// change appropriately.
38337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
38347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
38357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
38362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
38382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int32 msg_data_size = 100;
38402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
38412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
38432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
38457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
38467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
38472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
38487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
38497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
38532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
38542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
38562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
38577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
38587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
38592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
386090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
38612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
38622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 4),
3866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
38672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
38682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
38702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
38712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
38722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
38732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
38752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
38772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3878ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
38797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
38802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
3882a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
388390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
388490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
38852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
38862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
38872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
388890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
38892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
38902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3892b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
389390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
389490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
38962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
39022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
39052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
39082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
39102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
39122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
39152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
39172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
39192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
39222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
39242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
39262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
39272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
39302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
39332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
39342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
39352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
39372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
39382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
39402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Draining the delegate's read queue should increase the session's
3942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // receive window.
3943c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
39452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
39462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->Close();
3948a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
39492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
39552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
39562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Given a stall function and an unstall function, runs a test to make
3958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sure that a stream resumes after unstall.
39597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SpdySessionTest::RunResumeAfterUnstallTest(
39607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
396190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
396290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        unstall_function) {
39632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
39642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
39652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
39672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
39697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
39707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
397190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(
39727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
39732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
39762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(
39797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
39802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
39817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
39822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
3984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3), // EOF
39852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
39882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
39892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
39902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
39912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
39932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
39967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
39972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
39982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
39992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4000a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
400190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
400290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
40032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
40042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4005a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
40062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
40072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4008ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
400990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
40102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
401190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
4012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
401390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
401490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4015ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
4016ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
40172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  stall_function.Run(session.get(), stream.get());
40192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
40212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
40232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
40252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
40272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
40292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
40312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
40332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
403490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
403590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
40362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
40372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Run the resume-after-unstall test with all possible stall and
4039c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// unstall sequences.
4040c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
40427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionOnly,
4047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionOnly,
4049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Equivalent to
40537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
40547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
40557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamOnly,
4060c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamOnly,
4062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4064c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
40667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
4071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4073c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4075c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
40777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
40887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4096c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
40997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
41007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
41017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
41027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
41037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
4104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
41057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 0. The
41102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// streams should resume in priority order when that window is then
41112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// increased.
41127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
41137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
41147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
41157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
41162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
41172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
41182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
41202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
41227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
41237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
41242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
41257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
41267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
412790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
41287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
412990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
41307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
41312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 2),
4135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body1, 3),
41362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
41372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
41397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
41402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 4),
4142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
4143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6), // EOF
41442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
41452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
41472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
41482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
41492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
41502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
41522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
41557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
41562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
41572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
41582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
416090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
416190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
41622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
41632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
41652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
41662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
41682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
417090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
417190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
41722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
41732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
41752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
41762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
41782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
41802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
41832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
418490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
418590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
418690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
418790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
41902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
419290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
41932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
419490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
419590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
419690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
419790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
419890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
420190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
420290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
420390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
42042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
42052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should unstall only stream2.
4207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
42082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
42102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
42112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
421290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
42132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
42152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
42162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should then unstall stream1.
4218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
42192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
42222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
42242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
42262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
42272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate1.send_headers_completed());
4229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
42312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate2.send_headers_completed());
42332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
423490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
42352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
423690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
423790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
42382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Delegate that closes a given stream after sending its body.
4240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass StreamClosingDelegate : public test::StreamDelegateWithBody {
4241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
4242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        base::StringPiece data)
4244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : StreamDelegateWithBody(stream, data) {}
4245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~StreamClosingDelegate() {}
4247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    stream_to_close_ = stream_to_close;
4250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataSent() OVERRIDE {
4253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    test::StreamDelegateWithBody::OnDataSent();
4254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (stream_to_close_.get()) {
4255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream_to_close_->Close();
4256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(NULL, stream_to_close_.get());
4257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
4258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
4261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream_to_close_;
4262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
4263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to
4265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle deleted streams.
4266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
42677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
42687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
42697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
42702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
42712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
42722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
42742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
42767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
42782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
42797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
4282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
4285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
42862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 2),
4290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 3),
42912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
42942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 4),
4296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5), // EOF
42972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
43002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
43012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
43022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
43032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
43052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
43087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
43092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
43102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
43112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
431390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
431490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
43152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
43162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
431790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
43182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
43192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
43212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
432390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
432490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
43252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
43262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
43282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
43292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
43312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 =
4333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream3.get() != NULL);
4336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
4339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream3->HasUrlFromHeaders());
4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
43432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
43452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
43472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
434890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
434990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
435090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
435190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
43542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
435690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
43572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
435890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
435990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
436090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
436190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
436290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
436590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
436690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
436790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
43682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
43692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
4371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4372a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
4375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, stream3->stream_id());
4379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id1 = stream1->stream_id();
4382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id2 = stream2->stream_id();
4383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id3 = stream3->stream_id();
4384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close stream1 preemptively.
4386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream1.get());
4388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id3));
43927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream2, which should then close stream3.
4394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delegate2.set_stream_to_close(stream3);
4395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
4396a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
4399a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id3));
4404a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
4406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
4407a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, delegate3.WaitForClose());
4411a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4418a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate3.send_headers_completed());
4420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
4423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
4424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Cause a stall by reducing the flow control send window to
4426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle the session itself
4427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// being closed.
4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
44307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
44317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kStreamUrl[] = "http://www.google.com/";
4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
4436a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
443790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
4438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
4441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
4444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4445a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  MockWrite writes[] = {
4446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4448a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  };
4449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 2), // EOF
4452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
4455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4457a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.set_connect_data(connect_data);
4458a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
4462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
44637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
4466a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream1 =
4468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream1.get() != NULL);
4471a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream1->SetDelegate(&delegate1);
4474a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 =
447890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream2.get() != NULL);
4481a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
4484a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4486a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StallSessionSend(session.get());
4491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
4493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4494a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4498a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, stream1->stream_id());
4501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4502a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
4504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
4506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4509a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, stream2->stream_id());
4512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
451390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
451590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream1.
4517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
451890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close the session (since we can't do it from within the delegate
4520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // method, since it's in the stream's loop).
45217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
4523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
452490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
452690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
452990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
453290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
453590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
453790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
453890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
4541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
4542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
4544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
4546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0,
4549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GOAWAY_FLOW_CONTROL_ERROR,
4550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "the receive window size of 1"));
4552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {
4553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockRead reads[] = {
4559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DeterministicSocketData data(
4563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
4564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.set_connect_data(connect_data);
4565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CreateDeterministicNetworkSession();
4568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
4570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL url(kDefaultURL);
4573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_TRUE(spdy_stream.get() != NULL);
4576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
4577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
4578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
4580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
4581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(1);  // Write request.
4584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Put session on the edge of overflowing it's recv window.
4586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session->session_recv_window_size_ = 1;
4587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Read response headers & body. Body overflows the session window, and a
4589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // goaway is written.
4590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(3);
4591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
4592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
4595f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, SplitHeaders) {
4598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL kStreamUrl("http://www.google.com/foo.dat");
4599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock headers;
4600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4601f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  headers["alpha"] = "beta";
4602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4603f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock request_headers;
4604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock response_headers;
4605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SplitPushedHeadersToRequestAndResponse(
4607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4609f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string alpha_val =
4611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (it == response_headers.end()) ? std::string() : it->second;
4612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ("beta", alpha_val);
4613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL request_url =
4615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(kStreamUrl, request_url);
4617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Regression. Sorta. Push streams and client streams were sharing a single
4620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// limit for a long time.
4621116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SettingsMap new_settings;
4623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> settings_frame(
4626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
4627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockRead reads[] = {
4630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      MockRead(ASYNC, 0, 4),
4632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
4636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockWrite writes[] = {
4638116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DeterministicSocketData data(
4642116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reads, arraysize(reads), writes, arraysize(writes));
4643116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4644116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.set_connect_data(connect_data);
4645116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CreateDeterministicNetworkSession();
4648116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4649116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdySession> session =
4650116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4651116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read the settings frame.
4653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4654116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4655116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL url1(kDefaultURL);
4656116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4657116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4658116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
4659116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
4660116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4661116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
4662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4663116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
4664116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
4665116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4666116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4667116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4668116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
4669116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4672116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4673116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until 1st stream is activated.
4674116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
4675116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(2);
4676116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
4677116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_streams());
4678116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4679116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4680116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4681116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4682116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until pushed stream is created.
4683116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4684116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4685116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4686116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4687116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4688116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4689116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Second stream should not be stalled, although we have 2 active streams, but
4690116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // one of them is push stream and should not be taken into account when we
4691116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // create streams on the client.
4692116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4693116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4694116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream2.get() != NULL);
4695116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4696116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
4697116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4698116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4700116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read EOF.
4701116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
4703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4704116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4705116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4706116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4708116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4709116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockRead reads[] = {
4710116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      MockRead(ASYNC, 0, 4),
4712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4713116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4714116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
4715116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4716116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> rst(
4717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4718116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockWrite writes[] = {
4719116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4720116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4721116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4722116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DeterministicSocketData data(
4723116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reads, arraysize(reads), writes, arraysize(writes));
4724116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.set_connect_data(connect_data);
4726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4728116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CreateDeterministicNetworkSession();
4729116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdySession> session =
4731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session->set_max_concurrent_pushed_streams(1);
4733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL url1(kDefaultURL);
4735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
4738116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
4739116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4740116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
4741116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4742116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
4743116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
4744116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4745116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4746116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4747116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
4748116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4749116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4750116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4751116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4752116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until 1st stream is activated.
4753116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
4754116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
4756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_streams());
4757116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4759116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until pushed stream is created.
4762116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4763116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4765116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4766116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4767116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4768116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Reset incoming pushed stream.
4769116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(2);
4770116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4771116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read EOF.
4776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
4778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4779116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Streams in reserved remote state exist only in SPDY4.
4781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (spdy_util_.spdy_version() < SPDY4)
4782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
4783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 push_headers.get());
4789116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> push_b(
4790116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4791116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> headers_b(
4792116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockRead reads[] = {
4794116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4795116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4796116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4797116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
4799116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4800116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> rst(
4801116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4802116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockWrite writes[] = {
4803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4804116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4805116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4806116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DeterministicSocketData data(
4807116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reads, arraysize(reads), writes, arraysize(writes));
4808116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4809116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.set_connect_data(connect_data);
4810116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4811116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4812116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CreateDeterministicNetworkSession();
4813116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4814116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdySession> session =
4815116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4816116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session->set_max_concurrent_pushed_streams(1);
4817116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4818116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL url1(kDefaultURL);
4819116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4820116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4821116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
4822116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
4823116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
4825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
4827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
4828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4829116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4830116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4831116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
4832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4835116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until 1st stream is activated.
4837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
4838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
4840116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_streams());
4841116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4844116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until pushed stream is created.
4846116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4848116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Accept promised stream. It should not count towards pushed stream limit.
4853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4854116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(3u, session->num_active_streams());
4855116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4856116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_pushed_streams());
4857116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4858116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4859116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Reset last pushed stream upon headers reception as it is going to be 2nd,
4860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // while we accept only one.
4861116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(2);
4862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4864116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_pushed_streams());
4866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4867116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read EOF.
4868116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4869116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
4870116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4871116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Streams in reserved remote state exist only in SPDY4.
4873116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (spdy_util_.spdy_version() < SPDY4)
4874116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
4875116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4876116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const char kPushedUrl[] = "http://www.google.com/a.dat";
4877116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4879116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> push_promise(
4880116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4881116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> headers_frame(
4882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockRead reads[] = {
4884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      MockRead(ASYNC, 0, 4),
4886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
4889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> rst(
4891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockWrite writes[] = {
4893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
4895116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4896116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DeterministicSocketData data(
4897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reads, arraysize(reads), writes, arraysize(writes));
4898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4899116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.set_connect_data(connect_data);
4900116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4901116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4902116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CreateDeterministicNetworkSession();
4903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdySession> session =
4905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4906116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL url1(kDefaultURL);
4908116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4909116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
4911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
4912116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
4914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
4916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
4917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4920116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
4921116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4922116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4924116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until 1st stream is activated.
4926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
4927116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4928116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
4929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_streams());
4930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4931116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4932116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4933116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run until pushed stream is created.
4935116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4936116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(2u, session->num_active_streams());
4937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4938116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_pushed_streams());
4939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::WeakPtr<SpdyStream> pushed_stream;
4942116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int rv =
4943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4944116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_EQ(OK, rv);
4945116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_TRUE(pushed_stream.get() != NULL);
4946116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4947116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pushed_stream->SetDelegate(&delegate2);
4948116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4949116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4950116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // that all our counters are in consistent state.
4951116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(1);
4952116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(1u, session->num_active_streams());
4953116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_created_streams());
4954116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_pushed_streams());
4955116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(0u, session->num_active_pushed_streams());
4956116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4957116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Read EOF.
4958116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data.RunFor(2);
4959116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
4960116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
496103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
496203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
496303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
496403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MockRead reads[] = {
496503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
496603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
496703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
496803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
496903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
497003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
497103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  data.set_connect_data(connect_data);
497203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
497303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
497403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateNetworkSession();
497503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
497603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
497703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
497803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  session->stream_hi_water_mark_ = 5;
497903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Low client (odd) ids are fine.
498003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(session->OnUnknownFrame(3, 0));
498103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Client id exceeding watermark.
498203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(session->OnUnknownFrame(9, 0));
49831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
49841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  session->last_accepted_push_stream_id_ = 6;
49851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Low server (even) ids are fine.
498603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(session->OnUnknownFrame(2, 0));
49871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Server id exceeding last accepted id.
49881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(session->OnUnknownFrame(8, 0));
498903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
499003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapFramerErrorToProtocolError, MapsValues) {
4992f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4993f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_CONTROL_FRAME,
4994f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4995f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4996f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4997f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4998f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4999f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5000f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5001a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5002f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5003f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
5004f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5005f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapFramerErrorToNetError, MapsValue) {
5006f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5007f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5008f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5009f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5010f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5011f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5012f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
5013f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ERR_SPDY_FRAME_SIZE_ERROR,
5014f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
50155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
50165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
50175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapRstStreamStatusToProtocolError, MapsValues) {
50185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5019f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
50205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5021f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
50225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5023f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5024f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
5025f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5026f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5027f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5028f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5029f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5030f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5031f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5032f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5033f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5035f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5036f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5037f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
50385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
50395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
504003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanPool) {
504103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Load a cert that is valid for:
504203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.org
504303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   mail.example.org
504403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.com
504503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
504603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
504703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
504803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
504903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
505003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
505103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(SpdySession::CanPool(
505203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "www.example.org"));
505303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(SpdySession::CanPool(
505403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
505503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(SpdySession::CanPool(
505603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.com"));
505703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(SpdySession::CanPool(
505803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.google.com"));
505903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
506003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
506103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanNotPoolWithCertErrors) {
506203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Load a cert that is valid for:
506303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.org
506403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   mail.example.org
506503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.com
506603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
506703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
506803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
506903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
507003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
507103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert_status = CERT_STATUS_REVOKED;
507203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
507303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(SpdySession::CanPool(
507403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
507503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
507603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
507703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanNotPoolWithClientCerts) {
507803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Load a cert that is valid for:
507903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.org
508003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   mail.example.org
508103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.com
508203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
508303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
508403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
508503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
508603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
508703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.client_cert_sent = true;
508803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
508903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(SpdySession::CanPool(
509003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
509103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
509203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
509303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
509403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Load a cert that is valid for:
509503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.org
509603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   mail.example.org
509703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   www.example.com
509803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
509903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
510003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
510103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
510203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
510303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.channel_id_sent = true;
510403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
510503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(SpdySession::CanPool(
510603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
510703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(SpdySession::CanPool(
510803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "www.example.com"));
510903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
511003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
511103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanNotPoolWithBadPins) {
511203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint8 primary_pin = 1;
511303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint8 backup_pin = 2;
511403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint8 bad_pin = 3;
511503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
511603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
511703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
511803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
511903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
512003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
512103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.is_issued_by_known_root = true;
512203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
512303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
512403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(SpdySession::CanPool(
512503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
512603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
512703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
512803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST(CanPoolTest, CanPoolWithAcceptablePins) {
512903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint8 primary_pin = 1;
513003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint8 backup_pin = 2;
513103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState tss;
513203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
513303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
513403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
513503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
513603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     "spdy_pooling.pem");
513703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.is_issued_by_known_root = true;
513803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
513903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
514003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(SpdySession::CanPool(
514103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      &tss, ssl_info, "www.example.org", "mail.example.org"));
514203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
514303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
51445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
5145