diff options
Diffstat (limited to 'net/spdy/spdy_session_spdy3_unittest.cc')
-rw-r--r-- | net/spdy/spdy_session_spdy3_unittest.cc | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_spdy3_unittest.cc index f516ed2..a40834a 100644 --- a/net/spdy/spdy_session_spdy3_unittest.cc +++ b/net/spdy/spdy_session_spdy3_unittest.cc @@ -1152,4 +1152,144 @@ TEST_F(SpdySessionSpdy3Test, CloseSessionOnError) { EXPECT_EQ(ERR_CONNECTION_CLOSED, request_params->status()); } +TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnection) { + MockHostResolver host_resolver; + CapturingBoundNetLog log(CapturingNetLog::kUnbounded); + ClientSocketPoolHistograms tcp_histograms(""); + MockClientSocketFactory socket_factory; + MockConnect connect_data(SYNCHRONOUS, OK); + MockRead reads[] = { + MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. + }; + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + socket_factory.AddSocketDataProvider(&data); + socket_factory.AddSocketDataProvider(&data); + socket_factory.AddSocketDataProvider(&data); + socket_factory.AddSocketDataProvider(&data); + socket_factory.AddSocketDataProvider(&data); + socket_factory.AddSocketDataProvider(&data); + TransportClientSocketPool pool( + 3, 2, + &tcp_histograms, + &host_resolver, + &socket_factory, NULL); + // Now if I check out 1 socket from 3 different groups, the next request + // will leave us stalled. + + TestCompletionCallback callback1; + HostPortPair host_port1("1.com", 80); + scoped_refptr<TransportSocketParams> params1( + new TransportSocketParams(host_port1, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection1(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection1->Init(host_port1.ToString(), params1, MEDIUM, + callback1.callback(), &pool, log.bound())); + EXPECT_EQ(OK, callback1.WaitForResult()); + EXPECT_FALSE(pool.IsStalled()); + EXPECT_TRUE(connection1->is_initialized()); + EXPECT_TRUE(connection1->socket()); + + TestCompletionCallback callback2; + HostPortPair host_port2("2.com", 80); + scoped_refptr<TransportSocketParams> params2( + new TransportSocketParams(host_port2, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection2->Init(host_port2.ToString(), params2, MEDIUM, + callback2.callback(), &pool, log.bound())); + EXPECT_EQ(OK, callback2.WaitForResult()); + EXPECT_FALSE(pool.IsStalled()); + + TestCompletionCallback callback3; + HostPortPair host_port3("3.com", 80); + scoped_refptr<TransportSocketParams> params3( + new TransportSocketParams(host_port3, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection3->Init(host_port3.ToString(), params3, MEDIUM, + callback3.callback(), &pool, log.bound())); + EXPECT_EQ(OK, callback3.WaitForResult()); + EXPECT_FALSE(pool.IsStalled()); + + TestCompletionCallback callback4; + HostPortPair host_port4("4.com", 80); + scoped_refptr<TransportSocketParams> params4( + new TransportSocketParams(host_port4, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection4(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection4->Init(host_port4.ToString(), params4, MEDIUM, + callback4.callback(), &pool, log.bound())); + EXPECT_TRUE(pool.IsStalled()); + + // Return 1 socket to the pool so that we are no longer stalled + connection3->socket()->Disconnect(); + connection3->Reset(); + EXPECT_EQ(OK, callback4.WaitForResult()); + EXPECT_FALSE(pool.IsStalled()); + + // Now, wrap one of the sockets in a SpdySession + HttpServerPropertiesImpl props; + SpdySessionPool spdy_session_pool(&host_resolver, NULL, &props); + HostPortProxyPair pair1(host_port1, ProxyServer::Direct()); + EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); + scoped_refptr<SpdySession> session1 = + spdy_session_pool.Get(pair1, log.bound()); + EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); + EXPECT_EQ(OK, + session1->InitializeWithSocket(connection1.release(), false, OK)); + session1 = NULL; + EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); + + // The SpdySession is now idle. When we request the next socket from the + // transport pool, the session will be closed via CloseOneIdleConnection(). + TestCompletionCallback callback5; + HostPortPair host_port5("5.com", 80); + scoped_refptr<TransportSocketParams> params5( + new TransportSocketParams(host_port5, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection5(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection5->Init(host_port5.ToString(), params5, MEDIUM, + callback5.callback(), &pool, log.bound())); + EXPECT_FALSE(pool.IsStalled()); + EXPECT_EQ(OK, callback5.WaitForResult()); + EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); + EXPECT_FALSE(pool.IsStalled()); + + // Now, wrap one of the sockets in a SpdySession + HostPortProxyPair pair2(host_port2, ProxyServer::Direct()); + EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); + scoped_refptr<SpdySession> session2 = + spdy_session_pool.Get(pair2, log.bound()); + EXPECT_TRUE(spdy_session_pool.HasSession(pair2)); + EXPECT_EQ(OK, + session2->InitializeWithSocket(connection2.release(), false, OK)); + + // Manually remove the socket from the pool. This does *not* return the + // transport socket. It will be returned only when the SpdySession is + // destructed. + session2->RemoveFromPool(); + EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); + + // Although there are no active streams on the session, the pool does not + // hold a reference. This means that CloseOneIdleConnection should not + // return true, and this request should stall. + TestCompletionCallback callback6; + HostPortPair host_port6("6.com", 80); + scoped_refptr<TransportSocketParams> params6( + new TransportSocketParams(host_port5, MEDIUM, false, false)); + scoped_ptr<ClientSocketHandle> connection6(new ClientSocketHandle); + EXPECT_EQ(ERR_IO_PENDING, + connection6->Init(host_port6.ToString(), params6, MEDIUM, + callback6.callback(), &pool, log.bound())); + EXPECT_TRUE(pool.IsStalled()); + + // But now if we drop our reference to the session, it will be destructed + // and the transport socket will return to the pool, unblocking this + // request. + session2 = NULL; + EXPECT_EQ(OK, callback6.WaitForResult()); + EXPECT_FALSE(pool.IsStalled()); +} + } // namespace net |