15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/run_loop.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_data_directory.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/test_data_stream.h" 17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "net/socket/client_socket_pool_manager.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/socket/socket_test_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_session_test_util.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_stream_test_util.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/cert_test_util.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestUrl[] = "http://www.example.org/"; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestHost[] = "www.example.org"; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kTestPort = 80; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kBodyData[] = "Body data"; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kBodyDataSize = arraysize(kBodyData); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic base::TimeDelta g_time_delta; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeTicks TheNearFuture() { 44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return base::TimeTicks::Now() + g_time_delta; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class SpdySessionTest : public PlatformTest, 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) public ::testing::WithParamInterface<NextProto> { 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Functions used with RunResumeAfterUnstallTest(). 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StallSessionOnly(SpdySession* session, SpdyStream* stream) { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallSessionSend(session); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StallStreamOnly(SpdySession* session, SpdyStream* stream) { 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallStreamSend(stream); 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StallSessionStream(SpdySession* session, SpdyStream* stream) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallSessionSend(session); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallStreamSend(stream); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StallStreamSession(SpdySession* session, SpdyStream* stream) { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallStreamSend(stream); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StallSessionSend(session); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void UnstallSessionOnly(SpdySession* session, 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyStream* stream, 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32 delta_window_size) { 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallSessionSend(session, delta_window_size); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void UnstallStreamOnly(SpdySession* session, 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyStream* stream, 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32 delta_window_size) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallStreamSend(stream, delta_window_size); 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void UnstallSessionStream(SpdySession* session, 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyStream* stream, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32 delta_window_size) { 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallSessionSend(session, delta_window_size); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallStreamSend(stream, delta_window_size); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void UnstallStreamSession(SpdySession* session, 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyStream* stream, 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32 delta_window_size) { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallStreamSend(stream, delta_window_size); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UnstallSessionSend(session, delta_window_size); 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SpdySessionTest() 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) HttpNetworkSession::NORMAL_SOCKET_POOL)), 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) HttpNetworkSession::NORMAL_SOCKET_POOL)), 1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_(GetParam()), 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session_deps_(GetParam()), 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spdy_session_pool_(NULL), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_url_(kTestUrl), 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_(kTestHost, kTestPort), 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) key_(test_host_port_pair_, ProxyServer::Direct(), 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) virtual ~SpdySessionTest() { 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Important to restore the per-pool limit first, since the pool limit must 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // always be greater than group limit, and the tests reduce both limits. 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ClientSocketPoolManager::set_max_sockets_per_pool( 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ClientSocketPoolManager::set_max_sockets_per_group( 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) virtual void SetUp() OVERRIDE { 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch g_time_delta = base::TimeDelta(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateDeterministicNetworkSession() { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http_session_ = 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_ = http_session_->spdy_session_pool(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateNetworkSession() { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http_session_ = 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies::SpdyCreateSession(&session_deps_); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_ = http_session_->spdy_session_pool(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StallSessionSend(SpdySession* session) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reduce the send window size to 0 to stall. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (session->session_send_window_size_ > 0) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->DecreaseSendWindowSize( 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_)); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void UnstallSessionSend(SpdySession* session, int32 delta_window_size) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->IncreaseSendWindowSize(delta_window_size); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StallStreamSend(SpdyStream* stream) { 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reduce the send window size to 0 to stall. 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (stream->send_window_size() > 0) { 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->DecreaseSendWindowSize( 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) { 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->IncreaseSendWindowSize(delta_window_size); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void RunResumeAfterUnstallTest( 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function, 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Callback<void(SpdySession*, SpdyStream*, int32)>& 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unstall_function); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Original socket limits. Some tests set these. Safest to always restore 168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // them once each test has been run. 169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int old_max_group_sockets_; 170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int old_max_pool_sockets_; 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyTestUtil spdy_util_; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies session_deps_; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<HttpNetworkSession> http_session_; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionPool* spdy_session_pool_; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL test_url_; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HostPortPair test_host_port_pair_; 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdySessionKey key_; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NextProto, 1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SpdySessionTest, 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) testing::Values(kProtoDeprecatedSPDY2, 185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kProtoSPDY3, kProtoSPDY31, kProtoSPDY4)); 1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a SPDY session that will fail during 188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// initialization. Nothing should blow up. 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, InitialReadError) { 190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure( 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_session_pool_, key_, ERR_CONNECTION_CLOSED); 194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_TRUE(session); 195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Flush the read. 196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::RunLoop().RunUntilIdle(); 197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_FALSE(session); 198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace { 2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// A helper class that vends a callback that, when fired, destroys a 2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// given SpdyStreamRequest. 2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class StreamRequestDestroyingCallback : public TestCompletionCallbackBase { 2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public: 2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) StreamRequestDestroyingCallback() {} 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual ~StreamRequestDestroyingCallback() {} 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) { 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request_ = request.Pass(); 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CompletionCallback MakeCallback() { 2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return base::Bind(&StreamRequestDestroyingCallback::OnComplete, 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Unretained(this)); 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private: 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void OnComplete(int result) { 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request_.reset(); 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SetResult(result); 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<SpdyStreamRequest> request_; 2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} // namespace 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Request kInitialMaxConcurrentStreams streams. Request two more 2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// streams, but have the callback for one destroy the second stream 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// request. Close the session. Nothing should blow up. This is a 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// regression test for http://crbug.com/250841 . 2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, PendingStreamCancellingAnother) { 2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MockRead reads[] = {MockRead(ASYNC, 0, 0), }; 2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) data.set_connect_data(connect_data); 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CreateDeterministicNetworkSession(); 2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdySession> session = 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Create the maximum number of concurrent streams. 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) { 2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously( 2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); 2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_TRUE(spdy_stream != NULL); 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SpdyStreamRequest request1; 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest); 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) StreamRequestDestroyingCallback callback1; 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_EQ(ERR_IO_PENDING, 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session, 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) test_url_, 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MEDIUM, 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BoundNetLog(), 2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback1.MakeCallback())); 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // |callback2| is never called. 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) TestCompletionCallback callback2; 2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_EQ(ERR_IO_PENDING, 2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM, 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session, 2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) test_url_, 2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MEDIUM, 2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BoundNetLog(), 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback2.callback())); 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback1.SetRequestToDestroy(request2.Pass()); 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session->CloseSessionOnError(ERR_ABORTED, "Aborting session"); 2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult()); 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A session receiving a GOAWAY frame with no active streams should close. 286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) { 287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway, 0), 293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the GOAWAY frame. 308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 312ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame immediately with no active 315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// streams should then close. 316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) { 317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway, 0, SYNCHRONOUS), 323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.StopAfter(1); 331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::WeakPtr<SpdySession> session = 333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch TryCreateInsecureSpdySessionExpectingFailure( 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog()); 335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::RunLoop().RunUntilIdle(); 336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_FALSE(session); 338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame with active streams should close 342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// when the last active stream is closed. 343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreams) { 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateMockRead(*goaway, 2), 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead(ASYNC, 0, 3) // EOF 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req2( 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWrite writes[] = { 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateMockWrite(*req1, 0), 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateMockWrite(*req2, 1), 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) writes, arraysize(writes)); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateDeterministicNetworkSession(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 373a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 379a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream2 = 38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateDoNothing delegate2(spdy_stream2); 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream2->SetDelegate(&delegate2); 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers)); 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.RunFor(2); 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(1u, spdy_stream1->stream_id()); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(3u, spdy_stream2->stream_id()); 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Read and process the GOAWAY frame. 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.RunFor(1); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(session->IsStreamActive(3)); 407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session->IsStreamActive(1)); 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session->IsGoingAway()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Should close the session. 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spdy_stream1->Close(); 414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session receive two GOAWAY frames, with the last one causing 421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the last active stream to be closed. The session should then be 422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// closed after the second GOAWAY frame. 423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayTwice) { 424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1)); 428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0)); 429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway1, 2), 431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway2, 3), 432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 4) // EOF 433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req1( 435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req2( 437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockWrite writes[] = { 439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req1, 0), 440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req2, 1), 441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch writes, arraysize(writes)); 444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate1(spdy_stream1); 459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream1->SetDelegate(&delegate1); 460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate2(spdy_stream2); 465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream2->SetDelegate(&delegate2); 466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers)); 470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(2); 477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(1u, spdy_stream1->stream_id()); 479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(3u, spdy_stream2->stream_id()); 480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the first GOAWAY frame. 484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(session->IsStreamActive(3)); 489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream2.get()); 490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session->IsStreamActive(1)); 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session->IsGoingAway()); 492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the second GOAWAY frame, which should close the 494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // session. 495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session with active streams receive a GOAWAY frame and then 501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// close it. It should handle the close properly (i.e., not try to 502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// make itself unavailable in its pool twice). 503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) { 504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway, 2), 510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 3) // EOF 511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req1( 513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req2( 515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockWrite writes[] = { 517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req1, 0), 518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req2, 1), 519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch writes, arraysize(writes)); 522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate1(spdy_stream1); 537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream1->SetDelegate(&delegate1); 538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate2(spdy_stream2); 543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream2->SetDelegate(&delegate2); 544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers)); 548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(2); 555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(1u, spdy_stream1->stream_id()); 557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(3u, spdy_stream2->stream_id()); 558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the GOAWAY frame. 562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(session->IsStreamActive(3)); 567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session->IsStreamActive(1)); 569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session->IsGoingAway()); 570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, "Aborting session"); 572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 57846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Process a joint read buffer which causes the session to begin draining, and 57946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// then processes a GOAWAY. The session should gracefully drain. Regression test 58046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// for crbug.com/379469 58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_P(SpdySessionTest, GoAwayWhileDraining) { 58246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 58346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MockWrite writes[] = { 58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateMockWrite(*req, 0), 58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) }; 58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t joint_size = goaway->size() * 2 + body->size(); 59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Compose interleaved |goaway| and |body| frames into a single read. 59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<char[]> buffer(new char[joint_size]); 59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) { 59846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t out = 0; 59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) memcpy(&buffer[out], goaway->data(), goaway->size()); 60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) out += goaway->size(); 60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) memcpy(&buffer[out], body->data(), body->size()); 60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) out += body->size(); 60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) memcpy(&buffer[out], goaway->data(), goaway->size()); 60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) out += goaway->size(); 60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(out, joint_size); 60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SpdyFrame joint_frames(buffer.get(), joint_size, false); 60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MockRead reads[] = { 61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2), 61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MockRead(ASYNC, 0, 3) // EOF 61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) }; 61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DeterministicSocketData data( 61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) data.set_connect_data(connect_data); 61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateDeterministicNetworkSession(); 62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WeakPtr<SpdySession> session = 62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GURL url(kDefaultURL); 62546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously( 62646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) test::StreamDelegateDoNothing delegate(spdy_stream); 62846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) spdy_stream->SetDelegate(&delegate); 62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 63046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 63146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 63246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 63346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 63446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 63546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) data.RunFor(3); 63646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Stream and session closed gracefully. 63946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(delegate.StreamIsClosed()); 64046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(OK, delegate.WaitForClose()); 64146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(kUploadData, delegate.TakeReceivedData()); 64246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(session == NULL); 64346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 64446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a stream after receiving a GOAWAY frame. It should 646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// fail. 647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, CreateStreamAfterGoAway) { 648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 653ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway, 1), 654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 2) // EOF 655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req( 657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockWrite writes[] = { 659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req, 0), 660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch writes, arraysize(writes)); 663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream = 675ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate(spdy_stream); 678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SetDelegate(&delegate); 679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 680ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(1u, spdy_stream->stream_id()); 688ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the GOAWAY frame. 692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session->IsStreamActive(1)); 696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyStreamRequest stream_request; 698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int rv = stream_request.StartRequest( 699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(), 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CompletionCallback()); 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(ERR_FAILED, rv); 702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process EOF. 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Receiving a SYN_STREAM frame after a GOAWAY frame should result in 710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the stream being refused. 711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, SynStreamAfterGoAway) { 712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 715ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL)); 718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 719ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*goaway, 1), 720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*push, 2), 721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 4) // EOF 722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req( 724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> rst( 726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockWrite writes[] = { 728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req, 0), 729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*rst, 3) 730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch writes, arraysize(writes)); 733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 739ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream = 745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, MEDIUM, BoundNetLog()); 747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate(spdy_stream); 748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SetDelegate(&delegate); 749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(1u, spdy_stream->stream_id()); 758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the GOAWAY frame. 762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session->IsStreamActive(1)); 766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read and process the SYN_STREAM frame, the subsequent RST_STREAM, 768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // and EOF. 769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(3); 770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A session observing a network change with active streams should close 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when the last active stream is closed. 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) { 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead reads[] = { 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead(ASYNC, 0, 1) // EOF 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> req1( 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWrite writes[] = { 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateMockWrite(*req1, 0), 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) writes, arraysize(writes)); 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.set_connect_data(connect_data); 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateDeterministicNetworkSession(); 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WeakPtr<SpdySession> session = 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session, 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL(kDefaultURL), MEDIUM, BoundNetLog()); 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) test::StreamDelegateDoNothing delegate(spdy_stream); 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_stream->SetDelegate(&delegate); 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(kDefaultURL)); 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.RunFor(1); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1u, spdy_stream->stream_id()); 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_session_pool_->OnIPAddressChanged(); 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The SpdySessionPool behavior differs based on how the OSs reacts to 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // network changes; see comment in SpdySessionPool::OnIPAddressChanged(). 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS) 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For OSs where the TCP connections will close upon relevant network 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // changes, SpdySessionPool doesn't need to force them to close, so in these 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // cases verify the session has become unavailable but remains open and the 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // pre-existing stream is still active. 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session->IsGoingAway()); 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(session->IsStreamActive(1)); 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should close the session. 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_stream->Close(); 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(NULL, spdy_stream.get()); 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(session == NULL); 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClientPing) { 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.enable_ping = true; 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 847a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true)); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockRead(*read_ping, 1), 850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 0, 2) // EOF 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 852a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false)); 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*write_ping, 0), 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data( 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 8647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 866a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks before_ping_time = base::TimeTicks::Now(); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->set_connection_at_risk_of_loss_time( 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromSeconds(-1)); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->set_hung_interval(base::TimeDelta::FromMilliseconds(50)); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->SendPrefacePingIfNoneInFlight(); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(2); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->CheckPingStatus(before_ping_time); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, session->pings_in_flight()); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(session->check_ping_status_pending()); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(session->last_activity_time(), before_ping_time); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 890ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 891ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ServerPing) { 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 902a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false)); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateMockRead(*read_ping), 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead(SYNCHRONOUS, 0, 0) // EOF 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 907a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true)); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateMockWrite(*write_ping), 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StaticSocketDataProvider data( 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 918ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 9197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 921a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 928ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Flush the read completion task. 92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Cause a ping to be sent out while producing a write. The write loop 938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// should handle this properly, i.e. another DoWriteLoop task should 939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// not be posted. This is a regression test for 940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// http://crbug.com/261043 . 941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, PingAndWriteLoop) { 942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.enable_ping = true; 943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.time_func = TheNearFuture; 944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 946a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false)); 947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyFrame> req( 948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockWrite writes[] = { 950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*req, 0), 951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateMockWrite(*write_ping, 1), 952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 953ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead reads[] = { 955ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockRead(ASYNC, 0, 2) // EOF 956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch writes, arraysize(writes)); 962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.set_connect_data(connect_data); 963ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 971ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream = 972ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session, url, LOWEST, BoundNetLog()); 974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch test::StreamDelegateDoNothing delegate(spdy_stream); 975ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SetDelegate(&delegate); 976ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 977ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Shift time so that a ping will be sent out. 982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch g_time_delta = base::TimeDelta::FromSeconds(11); 983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(2); 985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, "Aborting"); 987ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 988ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, StreamIdSpaceExhausted) { 990cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const SpdyStreamId kLastStreamId = 0x7fffffff; 991cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 992cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are 994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // fixed to allow for two stream ID assignments, and three concurrent 995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // streams. Four streams are started, and two are activated. Verify the 996cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // session goes away, and that the created (but not activated) and 997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // stalled streams are aborted. Also verify the activated streams complete, 998cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // at which point the session closes. 999cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet( 1001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NULL, 0, false, kLastStreamId - 2, MEDIUM, true)); 1002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> req2( 1003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true)); 1004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockWrite writes[] = { 1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1), 1007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 1008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1009cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1( 1010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2)); 1011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> resp2( 1012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId)); 1013cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> body1( 1015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true)); 1016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> body2( 1017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true)); 1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead reads[] = { 1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3), 1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*body1, 4), CreateMockRead(*body2, 5), 1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead(ASYNC, 0, 6) // EOF 1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DeterministicSocketData data( 1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.set_connect_data(connect_data); 1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateDeterministicNetworkSession(); 1033cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdySession> session = 1034cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1036cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fix stream_hi_water_mark_ to allow for two stream activations. 1037cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session->stream_hi_water_mark_ = kLastStreamId - 2; 1038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fix max_concurrent_streams to allow for three stream creations. 1039cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session->max_concurrent_streams_ = 3; 1040cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Create three streams synchronously, and begin a fourth (which is stalled). 1042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL url(kDefaultURL); 1043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously( 1044cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 1045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test::StreamDelegateDoNothing delegate1(stream1); 1046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream1->SetDelegate(&delegate1); 1047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously( 1049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 1050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test::StreamDelegateDoNothing delegate2(stream2); 1051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream2->SetDelegate(&delegate2); 1052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously( 1054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 1055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test::StreamDelegateDoNothing delegate3(stream3); 1056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream3->SetDelegate(&delegate3); 1057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpdyStreamRequest request4; 1059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestCompletionCallback callback4; 1060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 1061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, 1062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session, 1063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) url, 1064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MEDIUM, 1065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BoundNetLog(), 1066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback4.callback())); 1067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Streams 1-3 were created. 4th is stalled. No streams are active yet. 1069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(3u, session->num_created_streams()); 1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM)); 1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Activate stream 1. One ID remains available. 1074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream1->SendRequestHeaders( 1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock>( 1076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())), 1077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NO_MORE_DATA_TO_SEND); 1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(1); 1079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id()); 1081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->num_active_streams()); 1082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2u, session->num_created_streams()); 1083cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM)); 1084cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1085cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Activate stream 2. ID space is exhausted. 1086cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream2->SendRequestHeaders( 1087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock>( 1088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())), 1089cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NO_MORE_DATA_TO_SEND); 1090cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(1); 1091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Active streams remain active. 1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(kLastStreamId, stream2->stream_id()); 1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2u, session->num_active_streams()); 1095cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Session is going away. Created and stalled streams were aborted. 1097cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_); 1098cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose()); 1099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult()); 1100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->num_created_streams()); 1101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM)); 1102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Read responses on remaining active streams. 1104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(4); 1105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(OK, delegate1.WaitForClose()); 1106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(kUploadData, delegate1.TakeReceivedData()); 1107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(OK, delegate2.WaitForClose()); 1108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(kUploadData, delegate2.TakeReceivedData()); 1109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Session was destroyed. 1111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(session.get()); 1113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that an unstalled pending stream creation racing with a new stream 1116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// creation doesn't violate the maximum stream concurrency. Regression test for 1117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// crbug.com/373858. 1118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) { 1119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 1120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead reads[] = { 1122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 1123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 1124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.set_connect_data(connect_data); 1129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 1130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateNetworkSession(); 1132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdySession> session = 1133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fix max_concurrent_streams to allow for one open stream. 1136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session->max_concurrent_streams_ = 1; 1137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Create two streams: one synchronously, and one which stalls. 1139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL url(kDefaultURL); 1140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously( 1141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 1142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpdyStreamRequest request2; 1144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestCompletionCallback callback2; 1145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 1146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, 1147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session, 1148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) url, 1149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MEDIUM, 1150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BoundNetLog(), 1151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback2.callback())); 1152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 1154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM)); 1155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cancel the first stream. A callback to unstall the second stream was 1157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // posted. Don't run it yet. 1158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream1->Cancel(); 1159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->num_created_streams()); 1161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM)); 1162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Create a third stream prior to the second stream's callback. 1164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously( 1165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 1166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 1168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM)); 1169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // NOW run the message loop. The unstalled stream will re-stall itself. 1171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 1173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM)); 1174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cancel the third stream and run the message loop. Verify that the second 1176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // stream creation now completes. 1177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stream3->Cancel(); 1178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 1181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM)); 1182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(OK, callback2.WaitForResult()); 1183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, DeleteExpiredPushStreams) { 11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.time_func = TheNearFuture; 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> req( 11905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> rst( 11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush( 11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 0, 2, 1, "http://www.google.com/a.dat")); 11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> push_a_body( 11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(2, false)); 11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush( 11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 0, 4, 1, "http://www.google.com/b.dat")); 12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)}; 12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead reads[] = { 12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2), 12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF 12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeterministicSocketData data( 12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.set_connect_data(connect_data); 12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateDeterministicNetworkSession(); 1213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Process the principal request, and the first push stream request & body. 12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously( 12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog()); 12205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) test::StreamDelegateDoNothing delegate(spdy_stream); 12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_stream->SetDelegate(&delegate); 12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.RunFor(3); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that there is one unclaimed push stream. 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); 123190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdySession::PushedStreamMap::iterator iter = 1232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session->unclaimed_pushed_streams_.find( 1233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GURL("http://www.google.com/a.dat")); 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (session->flow_control_state_ == 12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) { 12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Unclaimed push body consumed bytes from the session window. 12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize, 12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session->session_recv_window_size_); 12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Shift time to expire the push stream. Read the second SYN_STREAM, 12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and verify a RST_STREAM was written. 12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_time_delta = base::TimeDelta::FromSeconds(301); 12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.RunFor(2); 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the second pushed stream evicted the first pushed stream. 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); 1251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch iter = session->unclaimed_pushed_streams_.find( 1252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GURL("http://www.google.com/b.dat")); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); 12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (session->flow_control_state_ == 12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) { 12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Verify that the session window reclaimed the evicted stream body. 12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, 12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session->session_recv_window_size_); 12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_); 12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Read and process EOF. 12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.RunFor(1); 1265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(session == NULL); 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, FailedPing) { 12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 1274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false)); 1277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> goaway( 1278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping.")); 1279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)}; 1280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StaticSocketDataProvider data( 1281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 1283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateNetworkSession(); 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 12887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 129190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 129290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 129490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate); 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0)); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->set_hung_interval(base::TimeDelta::FromSeconds(0)); 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a PING frame. 1301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session->WritePingFrame(1, false); 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(0, session->pings_in_flight()); 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(session->check_ping_status_pending()); 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assert session is not closed. 1307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session->IsAvailable()); 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams()); 13097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We set last time we have received any data in 1 sec less than now. 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CheckPingStatus will trigger timeout because hung interval is zero. 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks now = base::TimeTicks::Now(); 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1); 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->CheckPingStatus(now); 1316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 13197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 1320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Request kInitialMaxConcurrentStreams + 1 streams. Receive a 1324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1. Make 1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// sure nothing blows up. This is a regression test for 1326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/57331 . 13277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OnSettings) { 13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS; 1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsMap new_settings; 1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1; 1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_settings[kSpdySettingsIds] = 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 133690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> settings_frame( 133790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdySettings(new_settings)); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 1339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateMockRead(*settings_frame, 0), 1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) MockRead(ASYNC, 0, 1), 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck()); 1344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockWrite writes[] = { 1345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*settings_ack, 2), 1346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 1347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 1349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) writes, arraysize(writes)); 1350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 1352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 13577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Create the maximum number of concurrent streams. 1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) { 1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = 1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ASSERT_TRUE(spdy_stream != NULL); 1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1367a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) StreamReleaserCallback stream_releaser; 13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamRequest request; 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERR_IO_PENDING, 137090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request.StartRequest( 137190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 137290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BoundNetLog(), 137390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream_releaser.MakeCallback(&request))); 1374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) data.RunFor(1); 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_EQ(OK, stream_releaser.WaitForResult()); 1378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 1380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (spdy_util_.spdy_version() >= SPDY4) { 1381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Allow the SETTINGS+ACK to write, so the session finishes draining. 1382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(1); 1383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with a persisted value for max concurrent streams. Receive a 1389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1 and which 1390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// also clears the persisted data. Verify that persisted data is 1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// correct. 13927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettings) { 1393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (spdy_util_.spdy_version() >= SPDY4) { 1394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag. 1395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4. 1396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 1397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SettingsMap new_settings; 1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1; 1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 140490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> settings_frame( 140590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdySettings(new_settings)); 1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 1407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version()); 1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead reads[] = { 1409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateMockRead(*settings_frame, 0), 1410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) MockRead(ASYNC, 0, 1), 1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 1414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 1415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.set_connect_data(connect_data); 1416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateDeterministicNetworkSession(); 1419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Initialize the SpdySetting with the default. 1421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spdy_session_pool_->http_server_properties()->SetSpdySetting( 1422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) test_host_port_pair_, 1423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SETTINGS_MAX_CONCURRENT_STREAMS, 1424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SETTINGS_FLAG_PLEASE_PERSIST, 1425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kInitialMaxConcurrentStreams); 1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_FALSE( 1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) spdy_session_pool_->http_server_properties()->GetSpdySettings( 1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) test_host_port_pair_).empty()); 1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 14327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Create the maximum number of concurrent streams. 1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) { 1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = 1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ASSERT_TRUE(spdy_stream != NULL); 1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1442a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) StreamReleaserCallback stream_releaser; 1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyStreamRequest request; 1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(ERR_IO_PENDING, 144690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request.StartRequest( 144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BoundNetLog(), 144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream_releaser.MakeCallback(&request))); 1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) data.RunFor(1); 1452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 14539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_EQ(OK, stream_releaser.WaitForResult()); 1454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make sure that persisted data is cleared. 1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_TRUE( 1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) spdy_session_pool_->http_server_properties()->GetSpdySettings( 1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) test_host_port_pair_).empty()); 1459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Make sure session's max_concurrent_streams is correct. 1461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(kInitialMaxConcurrentStreams + 1, 1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session->max_concurrent_streams()); 14637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 1465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 1466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with max concurrent streams set to 1. Request two streams. 1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// When the first completes, have the callback close its stream, which 1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// should trigger the second stream creation. Then cancel that one 1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// immediately. Don't crash. This is a regression test for 1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/63532 . 14737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelPendingCreateStream) { 14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the SpdySetting with 1 max concurrent streams. 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_->http_server_properties()->SetSpdySetting( 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_, 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SETTINGS_MAX_CONCURRENT_STREAMS, 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SETTINGS_FLAG_PLEASE_PERSIST, 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 14967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Leave room for only one more stream to be created. 1499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) { 1500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = 1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ASSERT_TRUE(spdy_stream != NULL); 1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Create 2 more streams. First will succeed. Second will be pending. 1507a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 150890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 150990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use scoped_ptr to let us invalidate the memory when we want to, to trigger 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a valgrind error if the callback is invoked when it's not supposed to be. 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamRequest request; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERR_IO_PENDING, 151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request.StartRequest( 151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BoundNetLog(), 152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback->callback())); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release the first one, this will allow the second to be created. 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream1->Cancel(); 1525a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.CancelRequest(); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.reset(); 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should not crash when running the pending callback. 153190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_P(SpdySessionTest, SendInitialDataOnNewSession) { 15352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsMap settings; 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE; 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024; 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings[kSpdySettingsIds1] = 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); 15477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (spdy_util_.spdy_version() >= SPDY3) { 15487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) settings[kSpdySettingsIds2] = 15497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize); 15507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 155290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> settings_frame( 155390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdySettings(settings)); 1554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> initial_window_update( 1555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyWindowUpdate( 1556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSessionFlowControlStreamId, 1557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::vector<MockWrite> writes; 1559a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (GetParam() == kProtoSPDY4) { 1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) writes.push_back( 1561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) MockWrite(ASYNC, 1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kHttp2ConnectionHeaderPrefix, 1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kHttp2ConnectionHeaderPrefixSize)); 1564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) writes.push_back(CreateMockWrite(*settings_frame)); 1566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (GetParam() >= kProtoSPDY31) { 1567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) writes.push_back(CreateMockWrite(*initial_window_update)); 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsMap server_settings; 1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const uint32 initial_max_concurrent_streams = 1; 1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, 1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) initial_max_concurrent_streams); 1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<SpdyFrame> server_settings_frame( 1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) spdy_util_.ConstructSpdySettings(server_settings)); 1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) writes.push_back(CreateMockWrite(*server_settings_frame)); 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize; 1580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), 1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) vector_as_array(&writes), writes.size()); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 15842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_->http_server_properties()->SetSpdySetting( 15892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_, 1590a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SETTINGS_MAX_CONCURRENT_STREAMS, 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SETTINGS_FLAG_PLEASE_PERSIST, 1592a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) initial_max_concurrent_streams); 1593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SpdySessionPoolPeer pool_peer(spdy_session_pool_); 1595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pool_peer.SetEnableSendingInitialData(true); 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 15987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 160090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 16017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(data.at_write_eof()); 16022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) { 16052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<HttpServerProperties> test_http_server_properties = 16082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_->http_server_properties(); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_http_server_properties->SetSpdySetting( 16112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_, 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SETTINGS_MAX_CONCURRENT_STREAMS, 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SETTINGS_FLAG_PLEASE_PERSIST, 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2); 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_NE(0u, test_http_server_properties->GetSpdySettings( 16162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_).size()); 16172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_session_pool_->OnIPAddressChanged(); 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings( 16192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_host_port_pair_).size()); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, Initialize) { 1623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CapturingBoundNetLog log; 1624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.net_log = log.bound().net_log(); 1625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 1626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead reads[] = { 1629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead(ASYNC, 0, 0) // EOF 1630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 1631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.set_connect_data(connect_data); 1634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 1635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateNetworkSession(); 1637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 16397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, log.bound()); 16407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 1641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Flush the read completion task. 164390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::CapturingNetLog::CapturedEntryList entries; 1646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) log.GetEntries(&entries); 1647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_LT(0u, entries.size()); 1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly. 1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int pos = net::ExpectLogContainsSomewhere( 1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entries, 0, 1652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::NetLog::TYPE_SPDY_SESSION_INITIALIZED, 1653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::NetLog::PHASE_NONE); 1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_LT(0, pos); 1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CapturingNetLog::CapturedEntry entry = entries[pos]; 1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::Source socket_source; 1658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(), 1659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &socket_source)); 1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(socket_source.IsValid()); 1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_NE(log.bound().source().id, socket_source.id); 1662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionGoaway) { 16652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 166890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 16702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*goaway), 16712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead(SYNCHRONOUS, 0, 0) // EOF 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 16732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 16762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CapturingBoundNetLog log; 1681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 16827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, log.bound()); 16837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Flush the read completion task. 168690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 1689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check that the NetLog was filled reasonably. 16922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::CapturingNetLog::CapturedEntryList entries; 16932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) log.GetEntries(&entries); 16942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_LT(0u, entries.size()); 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check that we logged SPDY_SESSION_CLOSE correctly. 16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int pos = net::ExpectLogContainsSomewhere( 16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entries, 0, 16992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetLog::TYPE_SPDY_SESSION_CLOSE, 17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetLog::PHASE_NONE); 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pos < static_cast<int>(entries.size())) { 1703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CapturingNetLog::CapturedEntry entry = entries[pos]; 1704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int error_code = 0; 1705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); 1706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(OK, error_code); 1707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 1708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ADD_FAILURE(); 1709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionEOF) { 1713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 1714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead reads[] = { 1717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead(SYNCHRONOUS, 0, 0) // EOF 1718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 1719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.set_connect_data(connect_data); 1722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 1723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateNetworkSession(); 1725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CapturingBoundNetLog log; 1727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::WeakPtr<SpdySession> session = 1728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, log.bound()); 1729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 1730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Flush the read completion task. 1732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 1735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(session == NULL); 1736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check that the NetLog was filled reasonably. 1738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::CapturingNetLog::CapturedEntryList entries; 1739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) log.GetEntries(&entries); 1740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_LT(0u, entries.size()); 1741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check that we logged SPDY_SESSION_CLOSE correctly. 1743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int pos = 1744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::ExpectLogContainsSomewhere(entries, 1745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 0, 1746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::NetLog::TYPE_SPDY_SESSION_CLOSE, 1747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::NetLog::PHASE_NONE); 1748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pos < static_cast<int>(entries.size())) { 1750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CapturingNetLog::CapturedEntry entry = entries[pos]; 1751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int error_code = 0; 1752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); 1753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code); 1754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 1755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ADD_FAILURE(); 1756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Queue up a low-priority SYN_STREAM followed by a high-priority 1760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// one. The high priority one should still send first and receive 1761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// first. 17627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OutOfOrderSynStreams) { 17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Construct the request. 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req_highest( 176690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true)); 1767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req_lowest( 176890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 1770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req_highest, 0), 1771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req_lowest, 1), 17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp_highest( 1775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body_highest( 1777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyBodyFrame(1, true)); 1778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp_lowest( 1779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body_lowest( 1781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyBodyFrame(3, true)); 17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 1783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp_highest, 2), 1784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*body_highest, 3), 1785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp_lowest, 4), 1786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*body_lowest, 5), 1787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 6) // EOF 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 1793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 1795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 18007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream_lowest = 180590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 180690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, LOWEST, BoundNetLog()); 1807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream_lowest); 1808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream_lowest->stream_id()); 1809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest); 1810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream_lowest->SetDelegate(&delegate_lowest); 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream_highest = 181390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 181490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, HIGHEST, BoundNetLog()); 1815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream_highest); 1816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream_highest->stream_id()); 1817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest); 1818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream_highest->SetDelegate(&delegate_highest); 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Queue the lower priority one first. 1821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers_lowest( 1823b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 1824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream_lowest->SendRequestHeaders( 1825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch headers_lowest.Pass(), NO_MORE_DATA_TO_SEND); 1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders()); 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers_highest( 1829b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 1830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream_highest->SendRequestHeaders( 1831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch headers_highest.Pass(), NO_MORE_DATA_TO_SEND); 1832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders()); 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(7); 18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(spdy_stream_lowest); 1837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(spdy_stream_highest); 1838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(3u, delegate_lowest.stream_id()); 1839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, delegate_highest.stream_id()); 18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelStream) { 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Request 1, at HIGHEST priority, will be cancelled before it writes data. 18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Request 2, at LOWEST priority, will be a full request and will be id 1. 184690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req2( 184790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockWrite(*req2, 0), 18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 18537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*resp2, 1), 18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*body2, 2), 18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead(ASYNC, 0, 3) // EOF 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1869ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 18707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 1873a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 187490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 187590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url1, HIGHEST, BoundNetLog()); 18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 1878a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 1879a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 1882a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream2 = 188390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 188490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url2, LOWEST, BoundNetLog()); 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream2.get() != NULL); 18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream2->stream_id()); 1887a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateDoNothing delegate2(spdy_stream2); 1888a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream2->SetDelegate(&delegate2); 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 1891b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 189290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2( 1896b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url2.spec())); 189790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_stream1->Cancel(); 1903a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(0u, delegate1.stream_id()); 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.RunFor(1); 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1909a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(0u, delegate1.stream_id()); 1910a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(1u, delegate2.stream_id()); 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream2->Cancel(); 1913a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream2.get()); 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close, 1917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and then close the session. Nothing should blow up. Also a 1918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// regression test for http://crbug.com/139518 . 1919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) { 19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No actual data will be sent. 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite(ASYNC, 0, 1) // EOF 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead(ASYNC, 0, 0) // EOF 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writes, arraysize(writes)); 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 19407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 1943a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 194490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 194590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url1, HIGHEST, BoundNetLog()); 19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 1950a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream2 = 195190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 195290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url2, LOWEST, BoundNetLog()); 19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream2.get() != NULL); 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, spdy_stream2->stream_id()); 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate1(spdy_stream1); 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate2(spdy_stream2); 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream2->SetDelegate(&delegate2); 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 196290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 196390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 196490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 196690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 196790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2( 196890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url2.spec())); 196990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1970ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the streams have not yet been activated and assigned an id. 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, spdy_stream2->stream_id()); 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure we don't crash while closing the session. 19777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, std::string()); 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1979a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 1980a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream2.get()); 1981a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1982a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_TRUE(delegate1.StreamIsClosed()); 1983a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_TRUE(delegate2.StreamIsClosed()); 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close, and 1990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// then close the session. Nothing should blow up. 1991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) { 19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No actual data will be sent. 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite(ASYNC, 0, 1) // EOF 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead(ASYNC, 0, 0) // EOF 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writes, arraysize(writes)); 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2011ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 20127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 2016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, HIGHEST, BoundNetLog()); 2018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get() != NULL); 2019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 2022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 2023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url2, LOWEST, BoundNetLog()); 2025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream2.get() != NULL); 2026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Make |spdy_stream1| close |spdy_stream2|. 2029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate1(spdy_stream2); 2030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SetDelegate(&delegate1); 2031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Make |spdy_stream2| close |spdy_stream1|. 2033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate2(spdy_stream1); 2034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SetDelegate(&delegate2); 2035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 2037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 2039ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 2040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers2( 2042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url2.spec())); 2043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 2044ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 20457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure that the streams have not yet been activated and assigned an id. 2047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 2048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 2049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure we don't crash while closing the session. 20517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, std::string()); 2052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 2054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 2055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate1.StreamIsClosed()); 2057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate2.StreamIsClosed()); 2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2060ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 2061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close, 2064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up. 2065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) { 20662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 20672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req1( 2071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req2( 2073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockWrite writes[] = { 2075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 2076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req2, 1), 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockRead reads[] = { 2080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 2) // EOF 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writes, arraysize(writes)); 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 20862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2090ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 20917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, MEDIUM, BoundNetLog()); 2097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get() != NULL); 2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 2101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 2102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url2, MEDIUM, BoundNetLog()); 2104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream2.get() != NULL); 2105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 21067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate1(spdy_stream1); 2108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SetDelegate(&delegate1); 21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate2(spdy_stream2); 2111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SetDelegate(&delegate2); 21122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 2114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 2116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 21172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers2( 2119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url2.spec())); 2120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 2121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 21222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure that the streams have not yet been activated and assigned an id. 2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 21262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 21282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, spdy_stream1->stream_id()); 2130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(3u, spdy_stream2->stream_id()); 2131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure we don't crash while closing the session. 21337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, std::string()); 2134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 2136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 2137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate1.StreamIsClosed()); 2139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate2.StreamIsClosed()); 2140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 2143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close, 2146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up. 2147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) { 2148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 2149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 2151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req1( 2153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req2( 2155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 2156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite writes[] = { 2157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 2158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req2, 1), 2159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 21602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 2162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 2) // EOF 21632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 21642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 21662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 21672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 21682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 21692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 21712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 21737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 21742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 217790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, MEDIUM, BoundNetLog()); 21792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 21802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 2184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url2, MEDIUM, BoundNetLog()); 2186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream2.get() != NULL); 2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Make |spdy_stream1| close |spdy_stream2|. 2190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate1(spdy_stream2); 2191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SetDelegate(&delegate1); 21922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Make |spdy_stream2| close |spdy_stream1|. 2194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::ClosingDelegate delegate2(spdy_stream1); 2195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SetDelegate(&delegate2); 21962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 219790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 2198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 219990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 2200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 220290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2( 220390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url2.spec())); 2204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 2205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders()); 22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure that the streams have not yet been activated and assigned an id. 22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 2209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream2->stream_id()); 22102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, spdy_stream1->stream_id()); 2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(3u, spdy_stream2->stream_id()); 22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ensure we don't crash while closing the session. 22177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session->CloseSessionOnError(ERR_ABORTED, std::string()); 22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 2220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream2.get()); 22212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate1.StreamIsClosed()); 2223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate2.StreamIsClosed()); 2224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 22272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 22282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2229bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that closes a given session when the stream is closed. 2230bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass SessionClosingDelegate : public test::StreamDelegateDoNothing { 2231bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public: 2232bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream, 2233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch const base::WeakPtr<SpdySession>& session_to_close) 2234bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch : StreamDelegateDoNothing(stream), 2235bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_to_close_(session_to_close) {} 2236bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2237bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch virtual ~SessionClosingDelegate() {} 2238bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch virtual void OnClose(int status) OVERRIDE { 2240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error"); 2241bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 2242bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2243bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private: 2244bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdySession> session_to_close_; 2245bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}; 2246bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2247bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Close an activated stream that closes its session. Nothing should 2248bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// blow up. This is a regression test for http://crbug.com/263691 . 2249bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) { 2250bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 2251bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2252bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 2253bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2254bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch scoped_ptr<SpdyFrame> req( 2255bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> rst( 2257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 2258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> goaway( 2259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error")); 2260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The GOAWAY has higher-priority than the RST_STREAM, and is written first 2261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // despite being queued second. 2262bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockWrite writes[] = { 2263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1), 2264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateMockWrite(*rst, 2), 2265bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch }; 2266bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2267bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockRead reads[] = { 2268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MockRead(ASYNC, 0, 3) // EOF 2269bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch }; 2270bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 2271bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch writes, arraysize(writes)); 2272bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch data.set_connect_data(connect_data); 2273bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2274bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2275bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateDeterministicNetworkSession(); 2276bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2277bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdySession> session = 2278bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2279bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 22805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 2281bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream = 2282bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2283bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session, url, MEDIUM, BoundNetLog()); 2284bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ASSERT_TRUE(spdy_stream.get() != NULL); 2285bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(0u, spdy_stream->stream_id()); 2286bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2287bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch SessionClosingDelegate delegate(spdy_stream, session); 2288bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_stream->SetDelegate(&delegate); 2289bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2290bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 2291bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 2292bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 2293bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 2294bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2295bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(0u, spdy_stream->stream_id()); 2296bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2297bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch data.RunFor(1); 2298bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2299bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(1u, spdy_stream->stream_id()); 2300bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2301bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Ensure we don't crash while closing the stream (which closes the 2302bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // session). 2303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_stream->Cancel(); 2304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(NULL, spdy_stream.get()); 2306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_TRUE(delegate.StreamIsClosed()); 2307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data.RunFor(2); // Write the RST_STREAM & GOAWAY. 2309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_TRUE(session == NULL); 2311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 2312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 23139a3a4bc965704498ea9f22876627cda96ff9a77eBo LiuTEST_P(SpdySessionTest, DISABLED_VerifyDomainAuthentication) { 2314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 23157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 23162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 2317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // No actual data will be sent. 2319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite writes[] = { 2320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite(ASYNC, 0, 1) // EOF 2321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 2322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 23232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 2324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0) // EOF 23252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 2326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 2327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 23282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 2329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Load a cert that is valid for: 2332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // www.example.org 2333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // mail.example.org 2334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // www.example.com 2335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath certs_dir = GetTestCertsDirectory(); 2336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<X509Certificate> test_cert( 2337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ImportCertFromFile(certs_dir, "spdy_pooling.pem")); 2338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); 23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ssl.cert = test_cert; 2342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 23432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 23452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 23477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateSecureSpdySession(http_session_, key_, BoundNetLog()); 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); 2350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); 2351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com")); 2352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); 23532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 23542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23559a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu// TODO(rch): re-enable this. 23569a3a4bc965704498ea9f22876627cda96ff9a77eBo LiuTEST_P(SpdySessionTest, DISABLED_ConnectionPooledWithTlsChannelId) { 2357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 23587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 23592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 2360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // No actual data will be sent. 23622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 2363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite(ASYNC, 0, 1) // EOF 23642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 2365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 2367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0) // EOF 2368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 2369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 2370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 23712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 2372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Load a cert that is valid for: 2375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // www.example.org 2376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // mail.example.org 2377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // www.example.com 2378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath certs_dir = GetTestCertsDirectory(); 2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<X509Certificate> test_cert( 2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ImportCertFromFile(certs_dir, "spdy_pooling.pem")); 2381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); 23822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 23842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ssl.channel_id_sent = true; 2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ssl.cert = test_cert; 2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 23872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 23892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 23917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateSecureSpdySession(http_session_, key_, BoundNetLog()); 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); 2394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); 2395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com")); 2396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); 23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 23982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { 2400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(rtenneti): Define a helper class/methods and move the common code in 2401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // this file. 24022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 24037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SettingsMap new_settings; 2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 2406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const uint32 max_concurrent_streams = 1; 2407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new_settings[kSpdySettingsIds1] = 2408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 24092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck()); 241190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 2412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req2( 2414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 2415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req3( 2416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true)); 24172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 2418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*settings_ack, 1), 2419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*req1, 2), 2420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*req2, 5), 2421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*req3, 8), 24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 24232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set up the socket so we read a SETTINGS frame that sets max concurrent 2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // streams to 1. 2426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> settings_frame( 2427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdySettings(new_settings)); 24282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 2433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 2434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 2436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); 24372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 2439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*settings_frame), 2440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*resp1, 3), 2441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*body1, 4), 2442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*resp2, 6), 2443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*body2, 7), 2444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*resp3, 9), 2445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockRead(*body3, 10), 2446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockRead(ASYNC, 0, 11) // EOF 24472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 24482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 24552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 24577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 24582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Read the settings frame. 2460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 2461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 24625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2463a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 246490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, LOWEST, BoundNetLog()); 24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 24672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 2468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 2469a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 24702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback2; 24725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamRequest request2; 2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_EQ(ERR_IO_PENDING, 2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request2.StartRequest( 2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, 2477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url2, LOWEST, BoundNetLog(), callback2.callback())); 2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback3; 24805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url3(kDefaultURL); 2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamRequest request3; 2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_EQ(ERR_IO_PENDING, 2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request3.StartRequest( 2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, 2485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url3, LOWEST, BoundNetLog(), callback3.callback())); 2486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 24897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST)); 2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 2492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 2494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 24952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Run until 1st stream is activated and then closed. 2497a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(0u, delegate1.stream_id()); 2498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(4); 2499a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 2500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, delegate1.stream_id()); 2501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_created_streams()); 2504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); 2505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Pump loop for SpdySession::ProcessPendingStreamRequests() to 2507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // create the 2nd stream. 2508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 2512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); 25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream(); 2515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate2(stream2); 2516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream2->SetDelegate(&delegate2); 2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers2( 2518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url2.spec())); 2519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 2520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream2->HasUrlFromHeaders()); 2521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Run until 2nd stream is activated and then closed. 2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, delegate2.stream_id()); 2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(3); 2525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream2.get()); 2526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(3u, delegate2.stream_id()); 2527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_created_streams()); 2530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); 2531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Pump loop for SpdySession::ProcessPendingStreamRequests() to 2533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // create the 3rd stream. 2534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->num_created_streams()); 25387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); 2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream(); 2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate3(stream3); 2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream3->SetDelegate(&delegate3); 2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers3( 2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url3.spec())); 2545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND); 2546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream3->HasUrlFromHeaders()); 2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Run until 2nd stream is activated and then closed. 2549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, delegate3.stream_id()); 2550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(3); 2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream3.get()); 2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(5u, delegate3.stream_id()); 2553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_created_streams()); 25567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); 2557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { 2562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 2563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 2565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 2567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 2570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 2572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 2573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateNetworkSession(); 2575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 25777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Leave room for only one more stream to be created. 2580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) { 2581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = 2582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session, test_url_, MEDIUM, BoundNetLog()); 2584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ASSERT_TRUE(spdy_stream != NULL); 2585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 2586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 25875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 2589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, LOWEST, BoundNetLog()); 2591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get() != NULL); 2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback2; 25955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url2(kDefaultURL); 2596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamRequest request2; 2597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_EQ(ERR_IO_PENDING, 2598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request2.StartRequest( 2599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(), 2600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback2.callback())); 2601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback3; 26035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url3(kDefaultURL); 2604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamRequest request3; 2605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_EQ(ERR_IO_PENDING, 2606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request3.StartRequest( 2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(), 2608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback3.callback())); 2609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); 26127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST)); 2613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Cancel the first stream; this will allow the second stream to be created. 2615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(spdy_stream1.get() != NULL); 2616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->Cancel(); 2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 2618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(OK, callback2.WaitForResult()); 2620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); 2622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); 2623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2624a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Cancel the second stream; this will allow the third stream to be created. 2625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream(); 2626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->Cancel(); 2627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 2628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2629a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(OK, callback3.WaitForResult()); 2630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); 26327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); 2633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cancel the third stream. 2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream(); 2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream3->Cancel(); 2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream3.get()); 2638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0u, session->num_active_streams()); 2639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams()); 26407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); 2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop reads data from the socket 2644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// without yielding. This test makes 32k - 1 bytes of data available 2645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// on the socket for reading. It then verifies that it has read all 2646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the available data without yielding. 2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ReadDataWithoutYielding) { 2648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req1( 2652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite writes[] = { 2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 2655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Build buffer of size kMaxReadBytesWithoutYielding / 4 2658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // (-spdy_data_frame_size). 2659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 2660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int kPayloadSize = 2661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestDataStream test_stream; 2663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch char* payload_data = payload->data(); 2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test_stream.GetBytes(payload_data, kPayloadSize); 2666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> partial_data_frame( 2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> finish_data_frame( 2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); 2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k 2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // bytes. 2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp1, 1), 2678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*partial_data_frame, 2), 2679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 2680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS), 2682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 6) // EOF 2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create SpdySession and SpdyStream and send the request. 2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 2688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 2689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 26957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 26975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 2699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url1, MEDIUM, BoundNetLog()); 2701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get() != NULL); 2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, spdy_stream1->stream_id()); 2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate1(spdy_stream1); 2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SetDelegate(&delegate1); 2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers1( 2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't 2712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // post a task. 2713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 2714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Run until 1st read. 2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, delegate1.stream_id()); 2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, delegate1.stream_id()); 2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, observer.executed_count()); 2720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read all the data and verify SpdySession::DoReadLoop has not 2722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // posted a task. 2723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(4); 2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 2725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Verify task observer's executed_count is zero, which indicates DoRead read 2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // all the available data. 2728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0u, observer.executed_count()); 27292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 27302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 27312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 27322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop yields while reading the 2734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// data. This test makes 32k + 1 bytes of data available on the socket 2735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for reading. It then verifies that DoRead has yielded even though 2736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// there is data available for it to read (i.e, socket()->Read didn't 2737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// return ERR_IO_PENDING during socket reads). 27387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringReadData) { 27392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 27407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 27412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 274290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 274390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 27442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 27452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockWrite(*req1, 0), 27462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 27472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Build buffer of size kMaxReadBytesWithoutYielding / 4 2749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // (-spdy_data_frame_size). 2750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 27512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kPayloadSize = 2752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 27532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestDataStream test_stream; 27542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 27552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* payload_data = payload->data(); 27562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_stream.GetBytes(payload_data, kPayloadSize); 27572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> partial_data_frame( 27592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 27602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> finish_data_frame( 27612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); 27622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 27642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Write 1 byte more than kMaxReadBytes to check that DoRead yields. 27662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 27672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*resp1, 1), 27682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*partial_data_frame, 2), 27692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 27702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 27712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), 27722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), 27732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead(ASYNC, 0, 7) // EOF 27742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 27752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 27772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 27782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 27792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 27802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 27812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 27822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 27842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 27867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 27872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2789a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 279090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 279190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url1, MEDIUM, BoundNetLog()); 27922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 27932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 2794a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 2795a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 27962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 279790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers1( 2798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 279990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 28012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a 2803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // task. 2804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 28052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run until 1st read. 2807a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(0u, delegate1.stream_id()); 28082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(2); 2809a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(1u, delegate1.stream_id()); 28102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, observer.executed_count()); 28112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read all the data and verify SpdySession::DoReadLoop has posted a 2813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // task. 28142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(6); 2815a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 28162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify task observer's executed_count is 1, which indicates DoRead has 28182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // posted only one task and thus yielded though there is data available for it 28192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to read. 28202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1u, observer.executed_count()); 28212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 28222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 28232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 28242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop() tests interactions of yielding 2826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// + async, by doing the following MockReads. 28272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 28282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K 28292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K. 28302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The above reads 26K synchronously. Since that is less that 32K, we 2832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// will attempt to read again. However, that DoRead() will return 2833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ERR_IO_PENDING (because of async read), so DoReadLoop() will 2834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// yield. When we come back, DoRead() will read the results from the 2835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// async read, and rest of the data synchronously. 28367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) { 28372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 28387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 28392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 284090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 284190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 28422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 28432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockWrite(*req1, 0), 28442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 28452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Build buffer of size kMaxReadBytesWithoutYielding / 4 2847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // (-spdy_data_frame_size). 2848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 28492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestDataStream test_stream; 28502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kEightKPayloadSize = 2851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 28522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<net::IOBuffer> eightk_payload( 28532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new net::IOBuffer(kEightKPayloadSize)); 28542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* eightk_payload_data = eightk_payload->data(); 28552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); 28562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Build buffer of 2k size. 28582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestDataStream test_stream2; 28592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; 28602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<net::IOBuffer> twok_payload( 28612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new net::IOBuffer(kTwoKPayloadSize)); 28622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* twok_payload_data = twok_payload->data(); 28632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); 28642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( 28662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); 28672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( 28682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); 28692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( 28702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1, "h", 1, DATA_FLAG_FIN)); 28712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 28732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 28752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*resp1, 1), 28762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 2), 28772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), 28782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), 28792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), 28802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 6, ASYNC), 28812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), 28822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), 28832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), 28842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), 28852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), 28862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead(ASYNC, 0, 12) // EOF 28872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 28882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 28902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 28912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 28922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 28932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 28942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 28952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 28972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 28997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 29002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2902a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 290390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 290490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url1, MEDIUM, BoundNetLog()); 29052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 29062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 2907a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 2908a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 29092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 291090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers1( 2911b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 291290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2913ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 29142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Set up the TaskObserver to monitor SpdySession::DoReadLoop 2916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // posting of tasks. 2917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run until 1st read. 2920a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(0u, delegate1.stream_id()); 29212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(2); 2922a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(1u, delegate1.stream_id()); 29232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, observer.executed_count()); 29242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2925ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read all the data and verify SpdySession::DoReadLoop has posted a 2926ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // task. 29272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(12); 2928a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 29292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify task observer's executed_count is 1, which indicates DoRead has 29312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // posted only one task and thus yielded though there is data available for 29322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it to read. 29332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1u, observer.executed_count()); 29342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 29352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 29362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 29372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure 2939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// nothing blows up. 2940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) { 29412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 29427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 29432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 294490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 294590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 29462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 29472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockWrite(*req1, 0), 29482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 29492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 29517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 295290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); 29532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 29552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*resp1, 1), 29562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*body1, 2), 29572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateMockRead(*goaway, 3), 29582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 29592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 29612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 29622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 29632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 29642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 29652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 29662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 29682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 29707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 29712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 2973a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream1 = 297490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 297590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url1, MEDIUM, BoundNetLog()); 297690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateDoNothing delegate1(spdy_stream1); 297790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SetDelegate(&delegate1); 29782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(spdy_stream1.get() != NULL); 29792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 29802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 298190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers1( 2982b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url1.spec())); 298390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 29852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run until 1st read. 29872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, spdy_stream1->stream_id()); 29882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(1); 29892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1u, spdy_stream1->stream_id()); 29902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run until GoAway. 2992ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(3); 2993a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, spdy_stream1.get()); 29942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 29952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 2996ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 29972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 29982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Within this framework, a SpdySession should be initialized with 30007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// flow control disabled for protocol version 2, with flow control 30017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enabled only for streams for protocol version 3, and with flow 30027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// control enabled for streams and sessions for higher versions. 30037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ProtocolNegotiation) { 30042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 30052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 30072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 30082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead(SYNCHRONOUS, 0, 0) // EOF 30092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 30102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 30112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 30122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 30132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 3015ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 30167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateFakeSpdySession(spdy_session_pool_, key_); 30172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(spdy_util_.spdy_version(), 30197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session->buffered_spdy_framer_->protocol_version()); 30204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (GetParam() == kProtoDeprecatedSPDY2) { 30217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); 30227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(0, session->session_send_window_size_); 30237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(0, session->session_recv_window_size_); 30247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else if (GetParam() == kProtoSPDY3) { 30257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); 30267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(0, session->session_send_window_size_); 30277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(0, session->session_recv_window_size_); 30287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 30297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 30307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session->flow_control_state()); 30317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, 30327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session->session_send_window_size_); 3033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, 30347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session->session_recv_window_size_); 30357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 30362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 30372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 30382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no 3040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held. 3041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnection) { 3042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_group( 3043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_pool( 3045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 30462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 30482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 3049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 30502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 3051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 30522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 3053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 3054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 30552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateNetworkSession(); 30572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TransportClientSocketPool* pool = 3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch http_session_->GetTransportSocketPool( 3060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL); 30612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create an idle SPDY session. 3063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 3064e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED); 3065ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session1 = 30667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 3067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 30682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Trying to create a new connection should cause the pool to be stalled, and 3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // post a task asynchronously to try and close the session. 3071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback2; 3072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostPortPair host_port2("2.com", 80); 3073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<TransportSocketParams> params2( 30743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new TransportSocketParams(host_port2, false, false, 3075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OnHostResolutionCallback())); 3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback2.callback(), pool, BoundNetLog())); 3080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(pool->IsStalled()); 30812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // The socket pool should close the connection asynchronously and establish a 3083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // new connection. 3084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, callback2.WaitForResult()); 3085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 3086ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session1 == NULL); 30872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 30882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no 3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held, in the case the SPDY session 3091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// has an alias. 3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { 3093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_group( 3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_pool( 3096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 30972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 30992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 3100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 31012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 31022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 31032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 31042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->rules()->AddIPLiteralRule( 3109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "1.com", "192.168.0.2", std::string()); 3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->rules()->AddIPLiteralRule( 3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "2.com", "192.168.0.2", std::string()); 3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Not strictly needed. 3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->rules()->AddIPLiteralRule( 3114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "3.com", "192.168.0.3", std::string()); 31152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNetworkSession(); 31172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TransportClientSocketPool* pool = 3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch http_session_->GetTransportSocketPool( 3120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL); 31212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create an idle SPDY session. 3123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 3124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED); 3125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session1 = 31267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 3127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 31282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set up an alias for the idle SPDY session, increasing its ref count to 2. 3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(), 3131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED); 3132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostResolver::RequestInfo info(key2.host_port_pair()); 3133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddressList addresses; 3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Pre-populate the DNS cache, since a synchronous resolution is required in 3135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // order to create the alias. 31363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session_deps_.host_resolver->Resolve(info, 31373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DEFAULT_PRIORITY, 31383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &addresses, 31393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CompletionCallback(), 31403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NULL, 31413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BoundNetLog()); 3142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get a session for |key2|, which should return the session created earlier. 3143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session2 = 31447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch spdy_session_pool_->FindAvailableSession(key2, BoundNetLog()); 3145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_EQ(session1.get(), session2.get()); 3146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 31472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Trying to create a new connection should cause the pool to be stalled, and 3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // post a task asynchronously to try and close the session. 3150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback3; 3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostPortPair host_port3("3.com", 80); 3152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<TransportSocketParams> params3( 31533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new TransportSocketParams(host_port3, false, false, 3154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OnHostResolutionCallback())); 3155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); 3156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 3157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY, 3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback3.callback(), pool, BoundNetLog())); 3159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(pool->IsStalled()); 31607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // The socket pool should close the connection asynchronously and establish a 3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // new connection. 3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, callback3.WaitForResult()); 3164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 3165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session1 == NULL); 3166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session2 == NULL); 3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Tests that when a SPDY session becomes idle, it closes itself if there is 31703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// a lower layer pool stalled on the per-pool socket limit. 31713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) { 3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_group( 3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ClientSocketPoolManager::set_max_sockets_per_pool( 3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req1( 3182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> cancel1( 3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite writes[] = { 3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 1), 3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*cancel1, 1), 3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StaticSocketDataProvider data(reads, arraysize(reads), 31903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) writes, arraysize(writes)); 3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 3193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MockRead http_reads[] = { 31953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 31963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }; 31973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 31983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NULL, 0); 31993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) http_data.set_connect_data(connect_data); 32003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&http_data); 32013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 32023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateNetworkSession(); 3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TransportClientSocketPool* pool = 3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch http_session_->GetTransportSocketPool( 3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpNetworkSession::NORMAL_SOCKET_POOL); 3208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create a SPDY session. 32105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url1(kDefaultURL); 3211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key1(HostPortPair(url1.host(), 80), 3212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ProxyServer::Direct(), PRIVACY_MODE_DISABLED); 3213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session1 = 32147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 3215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(pool->IsStalled()); 3216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create a stream using the session, and send a request. 3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback1; 3220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 3221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session1, url1, DEFAULT_PRIORITY, 3223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BoundNetLog()); 3224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get()); 3225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateDoNothing delegate1(spdy_stream1); 3226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SetDelegate(&delegate1); 3227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers1( 3229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(url1.spec())); 3230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 3231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->SendRequestHeaders( 3232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch headers1.Pass(), NO_MORE_DATA_TO_SEND)); 3233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); 3234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 3236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Trying to create a new connection should cause the pool to be stalled, and 3238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // post a task asynchronously to try and close the session. 3239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback2; 3240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostPortPair host_port2("2.com", 80); 3241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<TransportSocketParams> params2( 32423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new TransportSocketParams(host_port2, false, false, 3243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OnHostResolutionCallback())); 3244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 3245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 3246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 3247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback2.callback(), pool, BoundNetLog())); 3248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(pool->IsStalled()); 3249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Running the message loop should cause the socket pool to ask the SPDY 3251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // session to close an idle socket, but since the socket is in use, nothing 3252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // happens. 3253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop().RunUntilIdle(); 3254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(pool->IsStalled()); 3255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(callback2.have_result()); 3256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Cancelling the request should result in the session's socket being 32583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // closed, since the pool is stalled. 3259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get()); 3260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->Cancel(); 3261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop().RunUntilIdle(); 32623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_FALSE(pool->IsStalled()); 32633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(OK, callback2.WaitForResult()); 3264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that SpdySessionKey and therefore SpdySession is different when 3267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// privacy mode is enabled or disabled. 3268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) { 3269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 3270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostPortPair host_port_pair("www.google.com", 443); 3272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(), 3273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_ENABLED); 3274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(), 3275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED); 3276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 32787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 3279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Add SpdySession with PrivacyMode Enabled to the pool. 3281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session_privacy_enabled = 32827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled); 3283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 32857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 3286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Add SpdySession with PrivacyMode Disabled to the pool. 3288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session_privacy_disabled = 32897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled); 3290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 32927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 3293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string()); 32957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 32967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 3297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string()); 32997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 33007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 3301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that creates another stream when its stream is closed. 3304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass StreamCreatingDelegate : public test::StreamDelegateDoNothing { 3305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public: 3306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream, 3307bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch const base::WeakPtr<SpdySession>& session) 3308bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch : StreamDelegateDoNothing(stream), 3309bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_(session) {} 3310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch virtual ~StreamCreatingDelegate() {} 3312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3313bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch virtual void OnClose(int status) OVERRIDE { 33145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 3315bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ignore_result( 3316bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3317bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_, url, MEDIUM, BoundNetLog())); 3318bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 3319bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3320bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private: 3321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch const base::WeakPtr<SpdySession> session_; 3322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}; 3323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Create another stream in response to a stream being reset. Nothing 3325bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// should blow up. This is a regression test for 3326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// http://crbug.com/263690 . 3327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CreateStreamOnStreamReset) { 3328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3330bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3332bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch scoped_ptr<SpdyFrame> req( 3333bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 3334bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockWrite writes[] = { 3335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateMockWrite(*req, 0), 3336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch }; 3337bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch scoped_ptr<SpdyFrame> rst( 3339bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM)); 3340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockRead reads[] = { 3341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateMockRead(*rst, 1), 3342bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch MockRead(ASYNC, 0, 2) // EOF 3343bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch }; 3344bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeterministicSocketData data(reads, arraysize(reads), 3345bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch writes, arraysize(writes)); 3346bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch data.set_connect_data(connect_data); 3347bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3348bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3349bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateDeterministicNetworkSession(); 3350bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3351bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdySession> session = 3352bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3353bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 33545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url(kDefaultURL); 3355bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdyStream> spdy_stream = 3356bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3357bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch session, url, MEDIUM, BoundNetLog()); 3358bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ASSERT_TRUE(spdy_stream.get() != NULL); 3359bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(0u, spdy_stream->stream_id()); 3360bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3361bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch StreamCreatingDelegate delegate(spdy_stream, session); 3362bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_stream->SetDelegate(&delegate); 3363bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3364bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch scoped_ptr<SpdyHeaderBlock> headers( 3365bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_util_.ConstructGetHeaderBlock(url.spec())); 3366bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 3367bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_TRUE(spdy_stream->HasUrlFromHeaders()); 3368bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3369bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(0u, spdy_stream->stream_id()); 3370bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3371bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch data.RunFor(1); 3372bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3373bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(1u, spdy_stream->stream_id()); 3374bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3375bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Cause the stream to be reset, which should cause another stream 3376bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // to be created. 3377bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch data.RunFor(1); 3378bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3379bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(NULL, spdy_stream.get()); 3380bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_TRUE(delegate.StreamIsClosed()); 3381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(0u, session->num_active_streams()); 3382bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EXPECT_EQ(1u, session->num_created_streams()); 3383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 3384bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above. 3386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { 3388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetParam() < kProtoSPDY3) 3389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 3390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE 3392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // gets sent. 3393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SettingsMap new_settings; 3394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int32 window_size = 1; 3395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 3396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size); 3397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set up the socket so we read a SETTINGS frame that sets 3399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // INITIAL_WINDOW_SIZE. 3400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> settings_frame( 3402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdySettings(new_settings)); 3403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 3404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*settings_frame, 0), 3405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 1) // EOF 3406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck()); 3409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MockWrite writes[] = { 3410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateMockWrite(*settings_ack, 2), 3411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 3412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 3416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) writes, arraysize(writes)); 3417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.set_connect_data(connect_data); 3418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 3421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 34237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream1 = 3425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 3426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, test_url_, MEDIUM, BoundNetLog()); 3427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream1.get() != NULL); 3428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TestCompletionCallback callback1; 3429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_NE(spdy_stream1->send_window_size(), window_size); 3430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data.RunFor(1); // Process the SETTINGS frame, but not the EOF 3432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 3433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(session->stream_initial_send_window_size(), window_size); 3434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(spdy_stream1->send_window_size(), window_size); 3435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Release the first one, this will allow the second to be created. 3437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream1->Cancel(); 3438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream1.get()); 3439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> spdy_stream2 = 3441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 3442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, test_url_, MEDIUM, BoundNetLog()); 3443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(spdy_stream2.get() != NULL); 3444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(spdy_stream2->send_window_size(), window_size); 3445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_stream2->Cancel(); 3446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, spdy_stream2.get()); 3447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3.1 and above. 3450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}RecvWindowSize should properly 3452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session receive window size for SPDY 3.1 and higher. In 3453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// addition, SpdySession::IncreaseRecvWindowSize should trigger 3454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// sending a WINDOW_UPDATE frame for a large enough delta. 3455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustRecvWindowSize) { 3456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetParam() < kProtoSPDY31) 3457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 3458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int32 delta_window_size = 100; 3462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 3465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 1) // EOF 3466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> window_update( 3468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyWindowUpdate( 3469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSessionFlowControlStreamId, 3470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSpdySessionInitialWindowSize + delta_window_size)); 3471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockWrite writes[] = { 3472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*window_update, 0), 3473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 3475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 3476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 3477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 3480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 34817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->flow_control_state()); 3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 3487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->IncreaseRecvWindowSize(delta_window_size); 3489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size, 3490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->session_recv_window_size_); 3491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_); 3492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Should trigger sending a WINDOW_UPDATE frame. 3494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize); 3495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size + 3496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSpdySessionInitialWindowSize, 3497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->session_recv_window_size_); 3498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 3501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // DecreaseRecvWindowSize() expects |in_io_loop_| to be true. 3503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session->in_io_loop_ = true; 3504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->DecreaseRecvWindowSize( 3505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSpdySessionInitialWindowSize + delta_window_size + 3506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kSpdySessionInitialWindowSize); 3507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session->in_io_loop_ = false; 3508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0, session->session_recv_window_size_); 3509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 3510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}SendWindowSize should properly 3513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session send window size when the "enable_spdy_31" flag 3514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is set. 3515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustSendWindowSize) { 3516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetParam() < kProtoSPDY31) 3517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 3523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(SYNCHRONOUS, 0, 0) // EOF 3524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 3526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 3527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.socket_factory->AddSocketDataProvider(&data); 3528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateNetworkSession(); 3530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 35317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateFakeSpdySession(spdy_session_pool_, key_); 3532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->flow_control_state()); 3534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int32 delta_window_size = 100; 3536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->IncreaseSendWindowSize(delta_window_size); 3540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size, 3541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->session_send_window_size_); 3542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->DecreaseSendWindowSize(delta_window_size); 3544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Incoming data for an inactive stream should not cause the session 3548c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// receive window size to decrease, but it should cause the unacked 3549c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// bytes to increase. 3550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SessionFlowControlInactiveStream) { 3551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetParam() < kProtoSPDY31) 3552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 3553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 3555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 3557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false)); 3558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 3559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp, 0), 3560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 1) // EOF 3561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 3563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 3564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 3567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 35687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->flow_control_state()); 3571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 3574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 3576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3578c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_); 3579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 3580ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data.RunFor(1); 3581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A delegate that drops any received data. 3584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { 3585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 3586a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream, 3587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::StringPiece data) 358890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : StreamDelegateSendImmediate(stream, data) {} 3589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~DropReceivedDataDelegate() {} 3591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Drop any received data. 3593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {} 3594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 3595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but use a delegate that drops its received 3597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data. The receive window should still increase to its original 3598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value, i.e. we shouldn't "leak" receive window bytes. 35997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) { 36007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 36017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 3602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 3604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int32 msg_data_size = 100; 3606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string msg_data(msg_data_size, 'a'); 3607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 3609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 36117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 36127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 3613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> msg( 36147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 36157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1, msg_data.data(), msg_data_size, false)); 3616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWrite writes[] = { 3617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req, 0), 3618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*msg, 2), 3619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 3620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> echo( 36237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 36247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1, msg_data.data(), msg_data_size, false)); 3625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> window_update( 362690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyWindowUpdate( 3627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kSessionFlowControlStreamId, msg_data_size)); 3628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead reads[] = { 3629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp, 1), 3630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*echo, 3), 3631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 4) // EOF 3632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 3633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 3635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 3636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) writes, arraysize(writes)); 3637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.set_connect_data(connect_data); 3638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 3639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateDeterministicNetworkSession(); 3642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 36447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url(kStreamUrl); 3647a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 364890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 364990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 3650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 3651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(0u, stream->stream_id()); 3652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DropReceivedDataDelegate delegate(stream, msg_data); 3654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->SetDelegate(&delegate); 3655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 365690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 3657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 365890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 365990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 3661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 3664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(4); 3666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 3668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 3669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 3672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->Close(); 3674a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, stream.get()); 3675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(OK, delegate.WaitForClose()); 3677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 3680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but close the stream before its data frame 3683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// can be written to the socket. The send window should then increase 3684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to its original value, i.e. we shouldn't "leak" send window bytes. 36857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) { 36867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 36877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 3688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 3690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int32 msg_data_size = 100; 3692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string msg_data(msg_data_size, 'a'); 3693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 3695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 36977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 36987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 3699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWrite writes[] = { 3700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req, 0), 3701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 3702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockRead reads[] = { 3705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp, 1), 3706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 2) // EOF 3707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 3708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 3710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 3711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) writes, arraysize(writes)); 3712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.set_connect_data(connect_data); 3713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 3714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateDeterministicNetworkSession(); 3717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 37197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url(kStreamUrl); 3722a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 372390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 372490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 3725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 3726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(0u, stream->stream_id()); 3727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 372890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateSendImmediate delegate(stream, msg_data); 3729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->SetDelegate(&delegate); 3730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 373190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 3732b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 373390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 373490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 3736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 3740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data.RunFor(1); 3744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 3746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 3747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 3749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session->session_send_window_size_); 3750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Closing the stream should increase the session's send window. 3752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->Close(); 3753a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, stream.get()); 3754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(OK, delegate.WaitForClose()); 3758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Send data back and forth; the send and receive windows should 37612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// change appropriately. 37627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { 37637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 37647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 37652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 37672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int32 msg_data_size = 100; 37692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string msg_data(msg_data_size, 'a'); 37702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 37722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 37747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 37757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 37762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> msg( 37777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 37787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1, msg_data.data(), msg_data_size, false)); 37792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 3780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req, 0), 3781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*msg, 2), 37822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 37832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 37852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> echo( 37867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 37877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1, msg_data.data(), msg_data_size, false)); 37882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> window_update( 378990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyWindowUpdate( 37902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kSessionFlowControlStreamId, msg_data_size)); 37912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 3792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp, 1), 3793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*echo, 3), 3794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*window_update, 4), 3795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 5) // EOF 37962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 37972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create SpdySession and SpdyStream and send the request. 37992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 38002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 38012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 38022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 38032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 38042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 38062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 38087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 38092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 3811a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 381290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 381390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 38142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 38152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, stream->stream_id()); 38162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 381790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateSendImmediate delegate(stream, msg_data); 38182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 38192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 3821b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 382290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 382390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 38252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 38282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 38312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 38342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(1); 38372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 38392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->session_send_window_size_); 3840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 38412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(1); 38442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 38462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->session_send_window_size_); 3847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 38482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(1); 38512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 38532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->session_send_window_size_); 3854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 38552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->session_recv_window_size_); 38562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(1); 38592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 38622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->session_recv_window_size_); 38632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 38642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 38662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(data.at_read_eof()); 38672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(msg_data, delegate.TakeReceivedData()); 38692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Draining the delegate's read queue should increase the session's 3871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // receive window. 3872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 38742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 38752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->Close(); 3877a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, stream.get()); 38782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(OK, delegate.WaitForClose()); 3880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 3883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 38842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 38852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Given a stall function and an unstall function, runs a test to make 3887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sure that a stream resumes after unstall. 38887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SpdySessionTest::RunResumeAfterUnstallTest( 38897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function, 389090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Callback<void(SpdySession*, SpdyStream*, int32)>& 389190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unstall_function) { 38922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 38932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 38942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 38962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 38987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 38997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 390090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> body( 39017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 39022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 3903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req, 0), 3904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*body, 1), 39052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 39062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp( 39087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 39092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> echo( 39107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 39112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 3912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp, 2), 3913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0, 3), // EOF 39142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 39152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 39172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 39182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 39192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 39202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 39222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 3924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 39257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 39262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 39272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->flow_control_state()); 39282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3929a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 393090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 393190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, LOWEST, BoundNetLog()); 39322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 39332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece); 39352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 39362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 393890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 39392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 394090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 3941b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 394290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 394390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 3945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 39462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stall_function.Run(session.get(), stream.get()); 39482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 39502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 39522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unstall_function.Run(session.get(), stream.get(), kBodyDataSize); 39542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 39562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(3); 39582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 39602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 39622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); 396390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 396490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 39652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 39662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Run the resume-after-unstall test with all possible stall and 3968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// unstall sequences. 3969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallSession) { 39717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 39727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 39737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 39747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 39757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallSessionOnly, 3976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 39777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallSessionOnly, 3978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 3979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Equivalent to 39827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease. 39837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallStream) { 39847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 39857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 39867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 39877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 39887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallStreamOnly, 3989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 39907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallStreamOnly, 3991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 3992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) { 39957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 39967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 39977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 39987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 39997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallSessionStream, 4000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 40017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallSessionStream, 4002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 4003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) { 40067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 40077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 40087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 40097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 40107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallStreamSession, 4011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 40127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallSessionStream, 4013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 4014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) { 40177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 40187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 40197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 40207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 40217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallStreamSession, 4022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 40237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallStreamSession, 4024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 4025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) { 40287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 40297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 40307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 40317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RunResumeAfterUnstallTest( 40327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::StallSessionStream, 4033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)), 40347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SpdySessionTest::UnstallStreamSession, 4035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 4036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4037c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 0. The 40392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// streams should resume in priority order when that window is then 40402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// increased. 40417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { 40427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 40437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 40447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 40452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 40462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 40472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 40492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 40517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 40527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 40532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req2( 40547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 40557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); 405690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> body1( 40577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 405890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> body2( 40597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 40602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 4061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 4062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req2, 1), 4063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*body2, 2), 4064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*body1, 3), 40652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 40662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 40687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 40692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 4070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp1, 4), 4071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp2, 5), 4072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0, 6), // EOF 40732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 40742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 40762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 40772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 40782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 40792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 40812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 4083ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 40847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 40852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 40862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->flow_control_state()); 40872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4088a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream1 = 408990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 409090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, LOWEST, BoundNetLog()); 40912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream1.get() != NULL); 40922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4093a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 40942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream1->SetDelegate(&delegate1); 40952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream1->HasUrlFromHeaders()); 40972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4098a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream2 = 409990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 410090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, MEDIUM, BoundNetLog()); 41012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream2.get() != NULL); 41022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 41042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream2->SetDelegate(&delegate2); 41052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream2->HasUrlFromHeaders()); 41072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 41092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 41102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StallSessionSend(session.get()); 41122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 411390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers1( 411490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 411590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 411690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 4117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream1->HasUrlFromHeaders()); 4118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec()); 41192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 412190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(1u, stream1->stream_id()); 41222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 412390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 412490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2( 412590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 412690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 412790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 4128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream2->HasUrlFromHeaders()); 4129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec()); 413090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 413190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 413290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(3u, stream2->stream_id()); 41332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 41342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This should unstall only stream2. 4136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UnstallSessionSend(session.get(), kBodyDataSize); 41372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 41392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 41402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 414190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 41422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 41442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 41452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This should then unstall stream1. 4147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UnstallSessionSend(session.get(), kBodyDataSize); 41482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 4150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 41512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(4); 41532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 41552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 41562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate1.send_headers_completed()); 4158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); 4159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 41602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate2.send_headers_completed()); 41622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 416390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 41642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 416590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 416690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 41672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Delegate that closes a given stream after sending its body. 4169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass StreamClosingDelegate : public test::StreamDelegateWithBody { 4170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 4171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream, 4172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPiece data) 4173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : StreamDelegateWithBody(stream, data) {} 4174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~StreamClosingDelegate() {} 4176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) { 4178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_to_close_ = stream_to_close; 4179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 4180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnDataSent() OVERRIDE { 4182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateWithBody::OnDataSent(); 4183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (stream_to_close_.get()) { 4184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_to_close_->Close(); 4185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream_to_close_.get()); 4186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 4187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 4188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 4190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream_to_close_; 4191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 4192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 41932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 4194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle deleted streams. 4195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { 41967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 41977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 41987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 41992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char kStreamUrl[] = "http://www.google.com/"; 42002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 42012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.host_resolver->set_synchronous_mode(true); 42032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 42057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 42067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 42072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req2( 42087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 42097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 4210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req3( 4211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyPost( 4212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); 4213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body2( 4214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 42152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockWrite writes[] = { 4216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 4217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req2, 1), 4218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req3, 2), 4219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*body2, 3), 42202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 42212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 42232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRead reads[] = { 4224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockRead(*resp2, 4), 4225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0, 5), // EOF 42262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 42272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeterministicSocketData data(reads, arraysize(reads), 42292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) writes, arraysize(writes)); 42302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 42312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 42322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 42342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeterministicNetworkSession(); 4236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 42377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 42382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 42392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session->flow_control_state()); 42402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream1 = 424290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 424390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, LOWEST, BoundNetLog()); 42442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream1.get() != NULL); 42452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 424690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 42472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream1->SetDelegate(&delegate1); 42482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream1->HasUrlFromHeaders()); 42502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream2 = 425290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 425390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session, url, LOWEST, BoundNetLog()); 42542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream2.get() != NULL); 42552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece); 42572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream2->SetDelegate(&delegate2); 42582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream2->HasUrlFromHeaders()); 42602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream3 = 4262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 4263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url, LOWEST, BoundNetLog()); 4264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream3.get() != NULL); 4265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece); 4267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream3->SetDelegate(&delegate3); 4268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream3->HasUrlFromHeaders()); 4270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 42712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 42722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 4273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream3->send_stalled_by_flow_control()); 42742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StallSessionSend(session.get()); 42762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 427790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers1( 427890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 427990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 428090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 4281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream1->HasUrlFromHeaders()); 4282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec()); 42832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 428590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(1u, stream1->stream_id()); 42862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 428790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 428890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers2( 428990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 429090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 429190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 4292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream2->HasUrlFromHeaders()); 4293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec()); 429490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 429590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 429690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(3u, stream2->stream_id()); 42972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 42982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers3( 4300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 4301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 4302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND)); 4303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream3->HasUrlFromHeaders()); 4304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec()); 4305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 4307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(5u, stream3->stream_id()); 4308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(stream3->send_stalled_by_flow_control()); 4309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamId stream_id1 = stream1->stream_id(); 4311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamId stream_id2 = stream2->stream_id(); 4312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamId stream_id3 = stream3->stream_id(); 4313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Close stream1 preemptively. 4315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED); 4316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream1.get()); 4317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->IsStreamActive(stream_id1)); 4319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->IsStreamActive(stream_id2)); 4320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->IsStreamActive(stream_id3)); 43217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Unstall stream2, which should then close stream3. 4323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate2.set_stream_to_close(stream3); 4324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UnstallSessionSend(session.get(), kBodyDataSize); 4325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 4327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream3.get()); 4328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 4330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->IsStreamActive(stream_id1)); 4331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(session->IsStreamActive(stream_id2)); 4332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(session->IsStreamActive(stream_id3)); 4333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 4335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(NULL, stream2.get()); 4336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 4339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, delegate3.WaitForClose()); 4340a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate1.send_headers_completed()); 4342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 4343a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate2.send_headers_completed()); 4345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 4346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 4347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate3.send_headers_completed()); 4349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(std::string(), delegate3.TakeReceivedData()); 4350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(data.at_write_eof()); 4352a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 4353a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Cause a stall by reducing the flow control send window to 4355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle the session itself 4356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// being closed. 4357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { 4358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetParam() < kProtoSPDY31) 43597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 43607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const char kStreamUrl[] = "http://www.google.com/"; 4362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GURL url(kStreamUrl); 4363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.host_resolver->set_synchronous_mode(true); 4365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 436690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req1( 4367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyPost( 4368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 4369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> req2( 4370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyPost( 4371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 4372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> body1( 4373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 4374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) MockWrite writes[] = { 4375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req1, 0), 4376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateMockWrite(*req2, 1), 4377a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }; 4378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead reads[] = { 4380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockRead(ASYNC, 0, 0, 2), // EOF 4381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 4382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(reads, arraysize(reads), 4384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch writes, arraysize(writes)); 4385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 4386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) data.set_connect_data(connect_data); 4387a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 4389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateDeterministicNetworkSession(); 4391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session = 43927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 4393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 4394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session->flow_control_state()); 4395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream1 = 4397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 4398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url, LOWEST, BoundNetLog()); 4399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream1.get() != NULL); 4400a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 4402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream1->SetDelegate(&delegate1); 4403a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream1->HasUrlFromHeaders()); 4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream2 = 440790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session, url, LOWEST, BoundNetLog()); 4409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream2.get() != NULL); 4410a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 4412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream2->SetDelegate(&delegate2); 4413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream2->HasUrlFromHeaders()); 4415a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 4417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 4418a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StallSessionSend(session.get()); 4420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers1( 4422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 4423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 4424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 4425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream1->HasUrlFromHeaders()); 4426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec()); 4427a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(1u, stream1->stream_id()); 4430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 4431a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers2( 4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 4435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 4436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream2->HasUrlFromHeaders()); 4437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec()); 4438a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 4440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(3u, stream2->stream_id()); 4441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 444290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 444490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Unstall stream1. 4446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UnstallSessionSend(session.get(), kBodyDataSize); 444790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Close the session (since we can't do it from within the delegate 4449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // method, since it's in the stream's loop). 44507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session"); 4451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 4452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(session == NULL); 445390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 445590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 4457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 445890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate1.send_headers_completed()); 4460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 446190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(delegate2.send_headers_completed()); 4463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 446490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(data.at_write_eof()); 446690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 446790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) { 4469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (GetParam() < kProtoSPDY31) 4470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 4471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 4473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> req( 4475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway( 4477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 0, 4478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GOAWAY_FLOW_CONTROL_ERROR, 4479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than " 4480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "the receive window size of 1")); 4481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MockWrite writes[] = { 4482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3), 4483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 4484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MockRead reads[] = { 4488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateMockRead(*resp, 1), CreateMockRead(*body, 2), 4489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 4490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DeterministicSocketData data( 4492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes)); 4493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data.set_connect_data(connect_data); 4494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 4495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateDeterministicNetworkSession(); 4497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::WeakPtr<SpdySession> session = 4499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 4500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GURL url(kDefaultURL); 4502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously( 4503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 4504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_TRUE(spdy_stream.get() != NULL); 4505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) test::StreamDelegateDoNothing delegate(spdy_stream); 4506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_stream->SetDelegate(&delegate); 4507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 4509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(url.spec())); 4510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 4511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data.RunFor(1); // Write request. 4513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Put session on the edge of overflowing it's recv window. 4515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session->session_recv_window_size_ = 1; 4516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Read response headers & body. Body overflows the session window, and a 4518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // goaway is written. 4519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data.RunFor(3); 4520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose()); 4523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(session == NULL); 4524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 4525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, SplitHeaders) { 4527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GURL kStreamUrl("http://www.google.com/foo.dat"); 4528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SpdyHeaderBlock headers; 4529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers); 4530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) headers["alpha"] = "beta"; 4531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SpdyHeaderBlock request_headers; 4533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SpdyHeaderBlock response_headers; 4534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SplitPushedHeadersToRequestAndResponse( 4536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) headers, spdy_util_.spdy_version(), &request_headers, &response_headers); 4537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SpdyHeaderBlock::const_iterator it = response_headers.find("alpha"); 4539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string alpha_val = 4540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (it == response_headers.end()) ? std::string() : it->second; 4541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ("beta", alpha_val); 4542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GURL request_url = 4544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true); 4545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(kStreamUrl, request_url); 4546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 4547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 45485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapFramerErrorToProtocolError, MapsValues) { 4549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ( 4550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SPDY_ERROR_INVALID_CONTROL_FRAME, 4551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); 4552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ( 4553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SPDY_ERROR_INVALID_DATA_FRAME_FLAGS, 4554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS)); 4555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ( 4556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SPDY_ERROR_GOAWAY_FRAME_CORRUPT, 4557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT)); 4558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME, 4559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME)); 4560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 4561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapFramerErrorToNetError, MapsValue) { 4563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR, 4564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); 4565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR, 4566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE)); 4567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR, 4568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE)); 4569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ( 4570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ERR_SPDY_FRAME_SIZE_ERROR, 4571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE)); 45725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 45735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 45745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapRstStreamStatusToProtocolError, MapsValues) { 45755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR, 4576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR)); 45775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR, 4578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR)); 45795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM, 4580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM)); 4581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 4582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapNetErrorToGoAwayStatus, MapsValue) { 4584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_INADEQUATE_SECURITY, 4585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY)); 4586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR, 4587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR)); 4588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_PROTOCOL_ERROR, 4589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR)); 4590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_COMPRESSION_ERROR, 4591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR)); 4592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR, 4593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR)); 4594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED)); 45955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 45965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 45975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 4598