0

HttpStreamPool: Fix checking available SpdySession

AttemptManager has CHECK to ensure there is no available SpdySession
when attempting a TCP-based connection. It used
SpdySessionPool::HasAvailableSession() for the check. However, the
method didn't consider whether to enable or disable IP-based pooling.
The method could return true when there was an aliased SpdySession, even
when we disabled IP-based pooling, resulting in hitting CHECK failure.

This CL modifies HasAvailableSession() to take a flag that indicate
whether IP-based pooling is enabled or disabled. The method returns
false if IP-based pooling is disabled even when there is an aliased
SpdySession, in a way similar to FindAvailableSession().

Update HttpNetworkTransactionTest.RetryWithoutConnectionPooling
test to keep the first SpdySession to cover this case (Previously
the first SpdySession was closed before the second SpdySession
was created). Also use some actual NetLog sources so that we can
see NetLog events when `--log-net-log` command line flag is
specified (useful for debugging).

Bug: 397322724
Change-Id: Id52495d297661d2acce19c19057f6c5b25920fa8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6284467
Reviewed-by: mmenke <mmenke@chromium.org>
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1424264}
This commit is contained in:
Kenichi Ishibashi
2025-02-24 18:06:41 -08:00
committed by Chromium LUCI CQ
parent fbd60a65b8
commit cf6f56623e
9 changed files with 107 additions and 50 deletions

@ -464,7 +464,7 @@ class HttpNetworkTransactionTestBase : public PlatformTest,
/*ssl_client_context=*/nullptr,
/*socket_performance_watcher_factory=*/nullptr,
/*network_quality_estimator=*/nullptr,
/*net_log=*/nullptr,
/*net_log=*/NetLog::Get(),
/*websocket_endpoint_lock_manager=*/nullptr,
/*http_server_properties=*/nullptr,
/*alpn_protos=*/nullptr,
@ -20870,7 +20870,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
// Two requests on the first connection.
// Two requests on the first H2 connection.
spdy::SpdySerializedFrame req1(
spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
spdy_util_.UpdateWithStreamDestruction(1);
@ -20884,7 +20884,8 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
CreateMockWrite(rst, 6),
};
// The first one succeeds, the second gets error 421 Misdirected Request.
// The first request succeeds, the second request gets error 421 Misdirected
// Request. The first H2 connection remains available after getting 421.
spdy::SpdySerializedFrame resp1(
spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
@ -20892,8 +20893,10 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
response_headers[spdy::kHttp2StatusHeader] = "421";
spdy::SpdySerializedFrame resp2(
spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
MockRead reads1[] = {
CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
CreateMockRead(resp2, 4),
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) /* stalls forever */};
MockConnect connect1(ASYNC, OK, peer_addr);
SequencedSocketData data1(connect1, reads1, writes1);
@ -20901,7 +20904,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
AddSSLSocketData();
// Retry the second request on a second connection.
// Retry the second request on the second H2 connection.
SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
spdy::SpdySerializedFrame req3(
spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
@ -20936,7 +20939,8 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
TestCompletionCallback callback;
rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
rv = trans1.Start(&request1, callback.callback(),
NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
@ -20961,7 +20965,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
RecordingNetLogObserver net_log_observer;
rv = trans2.Start(&request2, callback.callback(),
NetLogWithSource::Make(NetLogSourceType::NONE));
NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());

@ -311,8 +311,9 @@ void HttpStreamFactory::Job::SetPriority(RequestPriority priority) {
bool HttpStreamFactory::Job::HasAvailableSpdySession() const {
return !using_quic_ && CanUseExistingSpdySession() &&
session_->spdy_session_pool()->HasAvailableSession(spdy_session_key_,
is_websocket_);
session_->spdy_session_pool()->HasAvailableSession(
spdy_session_key_,
/*enable_ip_based_pooling=*/true, is_websocket_);
}
bool HttpStreamFactory::Job::HasAvailableQuicSession() const {

@ -1739,8 +1739,8 @@ void HttpStreamPool::AttemptManager::CreateTextBasedStreamAndNotify(
}
bool HttpStreamPool::AttemptManager::HasAvailableSpdySession() const {
return spdy_session_pool()->HasAvailableSession(spdy_session_key(),
/*is_websocket=*/false);
return spdy_session_pool()->HasAvailableSession(
spdy_session_key(), IsIpBasedPoolingEnabled(), /*is_websocket=*/false);
}
void HttpStreamPool::AttemptManager::CreateSpdyStreamAndNotify(
@ -1943,7 +1943,6 @@ void HttpStreamPool::AttemptManager::OnInFlightAttemptComplete(
const auto reuse_type = StreamSocketHandle::SocketReuseType::kUnused;
if (stream_socket->GetNegotiatedProtocol() == NextProto::kProtoHTTP2) {
CHECK(!HasAvailableSpdySession());
std::unique_ptr<HttpStreamPoolHandle> handle = group_->CreateHandle(
std::move(stream_socket), reuse_type, std::move(connect_timing));
base::WeakPtr<SpdySession> spdy_session;

@ -524,8 +524,10 @@ class HttpStreamPoolAttemptManagerTest : public TestWithTaskEnvironment {
const HttpStreamKey& stream_key,
IPEndPoint peer_addr = IPEndPoint(IPAddress(192, 0, 2, 1), 443)) {
Group& group = pool().GetOrCreateGroupForTesting(stream_key);
CHECK(!spdy_session_pool()->HasAvailableSession(group.spdy_session_key(),
/*is_websocket=*/false));
CHECK(!spdy_session_pool()->HasAvailableSession(
group.spdy_session_key(),
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
auto socket = FakeStreamSocket::CreateForSpdy();
socket->set_peer_addr(peer_addr);
auto handle = group.CreateHandle(
@ -2854,7 +2856,9 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
requester1.WaitForResult();
EXPECT_THAT(requester1.result(), Optional(IsOk()));
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(),
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Disable HTTP/2.
http_server_properties()->SetHTTP11Required(
@ -2862,7 +2866,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
// At this point, the SPDY session is still available because it becomes
// unavailable after the next request is made.
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Request a stream again. The second request is paused because the first
// request is still alive and the corresponding attempt manager is still
@ -2873,7 +2878,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
ASSERT_FALSE(requester2.result().has_value());
// The SPDY session should become unavailable.
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Destroy the first request. It should resume the paused request.
requester1.ResetRequest();
@ -2902,7 +2908,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
RunUntilIdle();
EXPECT_THAT(requester1.result(), Optional(IsOk()));
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Disable HTTP/2.
http_server_properties()->SetHTTP11Required(
@ -2910,7 +2917,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
// At this point, the SPDY session is still available because it becomes
// unavailable after the next request is made.
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Destroy the first request.
requester1.ResetRequest();
@ -2932,7 +2940,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
RunUntilIdle();
EXPECT_THAT(requester2.result(), Optional(IsOk()));
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
}
TEST_F(HttpStreamPoolAttemptManagerTest, DoNotUseSpdySessionForHttpRequest) {
@ -2959,7 +2968,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, DoNotUseSpdySessionForHttpRequest) {
EXPECT_THAT(requester_https.result(), Optional(IsOk()));
EXPECT_EQ(requester_https.negotiated_protocol(), NextProto::kProtoHTTP2);
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Request a stream for http (not https). The second request should use
// HTTP/1.1 and should not use the existing SPDY session.
@ -2993,7 +3003,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, CloseIdleSpdySessionWhenPoolStalled) {
StreamKeyBuilder().set_destination(kDestinationA).Build();
CreateFakeSpdySession(stream_key_a);
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key_a.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key_a.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
resolver()
->AddFakeRequest()
@ -3015,9 +3026,11 @@ TEST_F(HttpStreamPoolAttemptManagerTest, CloseIdleSpdySessionWhenPoolStalled) {
EXPECT_EQ(requester_b.negotiated_protocol(), NextProto::kProtoHTTP2);
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
requester_b.GetStreamKey().CalculateSpdySessionKey(),
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
stream_key_a.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key_a.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
}
TEST_F(HttpStreamPoolAttemptManagerTest, SpdySessionBecomeUnavailable) {
@ -3139,7 +3152,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
RunUntilIdle();
EXPECT_THAT(preconnector1.result(), Optional(IsOk()));
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
// Disable HTTP/2.
http_server_properties()->SetHTTP11Required(
@ -3162,7 +3176,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
EXPECT_THAT(rv, IsError(ERR_HTTP_1_1_REQUIRED));
RunUntilIdle();
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
}
TEST_F(HttpStreamPoolAttemptManagerTest, SpdyReachedPoolLimit) {
@ -3325,8 +3340,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
// The session was already closed so it's not available.
ASSERT_FALSE(spdy_session_pool()->FindAvailableSession(
requester_b.GetStreamKey().CalculateSpdySessionKey(),
/*enable_ip_based_pooling=*/true, /*is_websocket=*/false,
NetLogWithSource()));
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false, NetLogWithSource()));
}
TEST_F(HttpStreamPoolAttemptManagerTest, SpdyPreconnectMatchingIpSession) {
@ -3931,7 +3946,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectMultipleStreamsHttp2) {
EXPECT_THAT(preconnector.result(), Optional(IsOk()));
ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
}
TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectRequireHttp1) {
@ -3972,7 +3988,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectRequireHttp1) {
EXPECT_THAT(preconnector.result(), Optional(IsOk()));
ASSERT_EQ(group.IdleStreamSocketCount(), 2u);
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
stream_key.CalculateSpdySessionKey(), false));
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
}
TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectMultipleStreamsOkAndFail) {

@ -249,7 +249,8 @@ int HttpStreamPool::JobController::Preconnect(
SpdySessionKey spdy_session_key =
origin_stream_key_.CalculateSpdySessionKey();
bool had_spdy_session = spdy_session_pool()->HasAvailableSession(
spdy_session_key, /*is_websocket=*/false);
spdy_session_key, /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false);
if (pool_->FindAvailableSpdySession(origin_stream_key_, spdy_session_key,
/*enable_ip_based_pooling=*/true)) {
net_log_.AddEvent(

@ -4253,11 +4253,13 @@ TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) {
SecureDnsPolicy::kAllow,
/*disable_cert_verification_network_fetches=*/false);
EXPECT_TRUE(
spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
spdy_session_pool->HasAvailableSession(key,
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
base::WeakPtr<SpdySession> spdy_session =
spdy_session_pool->FindAvailableSession(
key, /* enable_ip_based_pooling = */ true,
/* is_websocket = */ false, log_);
spdy_session_pool->FindAvailableSession(key,
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false, log_);
EXPECT_TRUE(spdy_session);
// Start second transaction.
@ -4290,7 +4292,9 @@ TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) {
// Graceful GOAWAY was received, SpdySession should be unavailable.
EXPECT_FALSE(
spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
spdy_session_pool->HasAvailableSession(key,
/*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
spdy_session = spdy_session_pool->FindAvailableSession(
key, /* enable_ip_based_pooling = */ true,
/* is_websocket = */ false, log_);
@ -7564,7 +7568,7 @@ TEST_P(SpdyNetworkTransactionTest,
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
/*disable_cert_verification_network_fetches=*/false);
EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
key1, /* is_websocket = */ false));
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
base::WeakPtr<SpdySession> spdy_session1 =
helper.session()->spdy_session_pool()->FindAvailableSession(
key1, /* enable_ip_based_pooling = */ true,
@ -7582,7 +7586,9 @@ TEST_P(SpdyNetworkTransactionTest,
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
/*disable_cert_verification_network_fetches=*/false);
EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
key2, /* is_websocket = */ true));
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/true));
EXPECT_FALSE(helper.session()->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
base::WeakPtr<SpdySession> spdy_session2 =
helper.session()->spdy_session_pool()->FindAvailableSession(
key1, /* enable_ip_based_pooling = */ true,

@ -235,7 +235,8 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint(
const SpdySessionKey& key,
const ServiceEndpoint& service_endpoint,
const std::set<std::string>& dns_aliases) {
CHECK(!HasAvailableSession(key, /*is_websocket=*/false));
CHECK(!HasAvailableSession(key, /*enable_ip_based_pooling=*/true,
/*is_websocket=*/false));
CHECK(key.socket_tag() == SocketTag());
base::WeakPtr<SpdySession> session =
@ -248,10 +249,15 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint(
}
bool SpdySessionPool::HasAvailableSession(const SpdySessionKey& key,
bool enable_ip_based_pooling,
bool is_websocket) const {
const auto it = available_sessions_.find(key);
return it != available_sessions_.end() &&
(!is_websocket || it->second->support_websocket());
auto it = available_sessions_.find(key);
if (it == available_sessions_.end() ||
(is_websocket && !it->second->support_websocket())) {
return false;
}
return enable_ip_based_pooling ? true : key == it->second->spdy_session_key();
}
base::WeakPtr<SpdySession> SpdySessionPool::RequestSession(

@ -214,8 +214,12 @@ class NET_EXPORT SpdySessionPool
const ServiceEndpoint& service_endpoint,
const std::set<std::string>& dns_aliases);
// Returns true if there is an available session for |key|.
bool HasAvailableSession(const SpdySessionKey& key, bool is_websocket) const;
// Returns true if there is an available session for `key`. Otherwise, if
// there is a session to pool to based on IP address, returns true if
// `enable_ip_based_pooling` is true. Otherwise returns false.
bool HasAvailableSession(const SpdySessionKey& key,
bool enable_ip_based_pooling,
bool is_websocket) const;
// Just like FindAvailableSession.
//

@ -3400,22 +3400,29 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
ClientSocketPool* pool = http_session_->GetSocketPool(
HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
// Create an idle SPDY session.
SpdySessionKey key1(HostPortPair("www.example.org", 80),
PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
SessionUsage::kDestination, SocketTag(),
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
/*disable_cert_verification_network_fetches=*/false);
base::WeakPtr<SpdySession> session1 =
::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
EXPECT_FALSE(pool->IsStalled());
// Set up an alias for the idle SPDY session, increasing its ref count to 2.
SpdySessionKey key2(HostPortPair("mail.example.org", 80),
PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
SessionUsage::kDestination, SocketTag(),
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
/*disable_cert_verification_network_fetches=*/false);
// Create an idle SPDY session.
base::WeakPtr<SpdySession> session1 =
::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
EXPECT_FALSE(pool->IsStalled());
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
// Set up an alias for the idle SPDY session, increasing its ref count to 2.
std::unique_ptr<SpdySessionPool::SpdySessionRequest> request;
bool is_blocking_request_for_session = false;
SpdySessionRequestDelegate request_delegate;
@ -3442,6 +3449,12 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
EXPECT_TRUE(session2);
ASSERT_EQ(session1.get(), session2.get());
EXPECT_FALSE(pool->IsStalled());
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
// Trying to create a new connection should cause the pool to be stalled, and
// post a task asynchronously to try and close the session.
@ -3468,6 +3481,12 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
EXPECT_FALSE(pool->IsStalled());
EXPECT_FALSE(session1);
EXPECT_FALSE(session2);
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
}
// Tests that when a SPDY session becomes idle, it closes itself if there is