Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(618)

Unified Diff: net/spdy/spdy_session_unittest.cc

Issue 17760008: [SPDY] Enable tests for SPDY/3.1 and SPDY/4 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix more tests Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/spdy/spdy_session_unittest.cc
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index fa4e12be8c4a0327d6e0b21147ee0c1518f1a36f..cce77ef1b197466cfb39aab31b16186299bdb2a5 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -219,13 +219,7 @@ INSTANTIATE_TEST_CASE_P(
SpdySessionTest,
testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2));
-// TODO(akalin): Don't early-exit in the tests below for values >
-// kProtoSPDY3.
-
TEST_P(SpdySessionTest, GoAway) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -308,9 +302,6 @@ TEST_P(SpdySessionTest, GoAway) {
}
TEST_P(SpdySessionTest, ClientPing) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.enable_ping = true;
session_deps_.host_resolver->set_synchronous_mode(true);
@@ -367,9 +358,6 @@ TEST_P(SpdySessionTest, ClientPing) {
}
TEST_P(SpdySessionTest, ServerPing) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -412,9 +400,6 @@ TEST_P(SpdySessionTest, ServerPing) {
}
TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
@@ -471,9 +456,6 @@ TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
}
TEST_P(SpdySessionTest, FailedPing) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -536,9 +518,6 @@ TEST_P(SpdySessionTest, FailedPing) {
}
TEST_P(SpdySessionTest, CloseIdleSessions) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
MockRead reads[] = {
MockRead(ASYNC, 0, 0) // EOF
@@ -662,9 +641,6 @@ TEST_P(SpdySessionTest, CloseIdleSessions) {
// Make sure nothing blows up.
// http://crbug.com/57331
TEST_P(SpdySessionTest, OnSettings) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
SettingsMap new_settings;
@@ -723,9 +699,6 @@ TEST_P(SpdySessionTest, OnSettings) {
// settings frame setting max concurrent streams to 2 and which also clears the
// persisted data. Verify that persisted data is correct.
TEST_P(SpdySessionTest, ClearSettings) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
SettingsMap new_settings;
@@ -740,7 +713,7 @@ TEST_P(SpdySessionTest, ClearSettings) {
scoped_ptr<SpdyFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
- test::SetFrameFlags(settings_frame.get(), flags, SPDY3);
+ test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
MockRead reads[] = {
CreateMockRead(*settings_frame),
MockRead(SYNCHRONOUS, 0, 0) // EOF
@@ -799,9 +772,6 @@ TEST_P(SpdySessionTest, ClearSettings) {
// second stream creation. Then cancel that one immediately. Don't crash.
// http://crbug.com/63532
TEST_P(SpdySessionTest, CancelPendingCreateStream) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockRead reads[] = {
@@ -857,9 +827,6 @@ TEST_P(SpdySessionTest, CancelPendingCreateStream) {
}
TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockRead reads[] = {
@@ -879,13 +846,22 @@ TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) {
MockConnect connect_data(SYNCHRONOUS, OK);
scoped_ptr<SpdyFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
+ scoped_ptr<SpdyFrame> initial_window_update(
+ spdy_util_.ConstructSpdyWindowUpdate(
+ kSessionFlowControlStreamId,
+ kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
MockWrite writes[] = {
CreateMockWrite(*settings_frame),
+ CreateMockWrite(*initial_window_update),
};
session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
+ int num_writes = arraysize(writes);
+ // We don't have session windows for SPDY versions less than 3.1.
+ if (spdy_util_.protocol() < kProtoSPDY31) {
+ --num_writes;
+ }
- StaticSocketDataProvider data(
- reads, arraysize(reads), writes, arraysize(writes));
+ StaticSocketDataProvider data(reads, arraysize(reads), writes, num_writes);
data.set_connect_data(connect_data);
session_deps_.socket_factory->AddSocketDataProvider(&data);
@@ -904,9 +880,6 @@ TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) {
}
TEST_P(SpdySessionTest, SendSettingsOnNewSession) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockRead reads[] = {
@@ -1204,9 +1177,6 @@ TEST_P(SpdySessionTest, IPPoolingCloseIdleSessions) {
}
TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
- if (GetParam() > kProtoSPDY3)
- return;
-
CreateNetworkSession();
HttpServerProperties* test_http_server_properties =
@@ -1225,9 +1195,6 @@ TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
}
TEST_P(SpdySessionTest, Initialize) {
- if (GetParam() > kProtoSPDY3)
- return;
-
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
session_deps_.host_resolver->set_synchronous_mode(true);
@@ -1277,9 +1244,6 @@ TEST_P(SpdySessionTest, Initialize) {
}
TEST_P(SpdySessionTest, CloseSessionOnError) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1333,9 +1297,6 @@ TEST_P(SpdySessionTest, CloseSessionOnError) {
// one. The high priority one should still send first and receive
// first.
TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
// Construct the request.
MockConnect connect_data(SYNCHRONOUS, OK);
scoped_ptr<SpdyFrame> req_highest(
@@ -1418,9 +1379,6 @@ TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
}
TEST_P(SpdySessionTest, CancelStream) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
// Request 1, at HIGHEST priority, will be cancelled before it writes data.
// Request 2, at LOWEST priority, will be a full request and will be id 1.
@@ -1500,9 +1458,6 @@ TEST_P(SpdySessionTest, CancelStream) {
// and then close the session. Nothing should blow up. Also a
// regression test for http://crbug.com/139518 .
TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1576,9 +1531,6 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
// Create two streams that are set to close each other on close, and
// then close the session. Nothing should blow up.
TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1654,9 +1606,6 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
// Create two streams that are set to re-close themselves on close,
// activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1740,9 +1689,6 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
// Create two streams that are set to close each other on close,
// activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1826,9 +1772,6 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
}
TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1897,9 +1840,6 @@ TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
}
TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -1969,9 +1909,6 @@ TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
}
TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
- if (GetParam() > kProtoSPDY3)
- return;
-
// TODO(rtenneti): Define a helper class/methods and move the common code in
// this file.
MockConnect connect_data(SYNCHRONOUS, OK);
@@ -2110,9 +2047,6 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
}
TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
- if (GetParam() > kProtoSPDY3)
- return;
-
session_deps_.host_resolver->set_synchronous_mode(true);
MockRead reads[] = {
@@ -2190,9 +2124,6 @@ TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
}
TEST_P(SpdySessionTest, NeedsCredentials) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
MockRead reads[] = {
MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
@@ -2251,141 +2182,10 @@ TEST_P(SpdySessionTest, NeedsCredentials) {
spdy_session_pool_->Remove(session);
}
-TEST_P(SpdySessionTest, SendCredentials) {
Ryan Hamilton 2013/06/27 17:23:50 More huge diffs in this file. Any chance they can
akalin 2013/06/27 20:00:06 moved back.
- if (GetParam() > kProtoSPDY3)
- return;
-
- MockConnect connect_data(SYNCHRONOUS, OK);
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
- };
- SettingsMap settings;
- scoped_ptr<SpdyFrame> settings_frame(
- spdy_util_.ConstructSpdySettings(settings));
- MockWrite writes[] = {
- CreateMockWrite(*settings_frame),
- };
- StaticSocketDataProvider data(reads, arraysize(reads),
- writes, arraysize(writes));
- data.set_connect_data(connect_data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.channel_id_sent = true;
- ssl.protocol_negotiated = kProtoSPDY3;
- session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
- CreateNetworkSession();
-
- const GURL kTestUrl("https://www.foo.com");
- HostPortPair test_host_port_pair(kTestUrl.host(), 443);
- SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
-
- scoped_refptr<SpdySession> session = GetSession(key);
-
- SSLConfig ssl_config;
- scoped_refptr<TransportSocketParams> transport_params(
- new TransportSocketParams(test_host_port_pair,
- MEDIUM,
- false,
- false,
- OnHostResolutionCallback()));
- scoped_refptr<SOCKSSocketParams> socks_params;
- scoped_refptr<HttpProxySocketParams> http_proxy_params;
- scoped_refptr<SSLSocketParams> ssl_params(
- new SSLSocketParams(transport_params,
- socks_params,
- http_proxy_params,
- ProxyServer::SCHEME_DIRECT,
- test_host_port_pair,
- ssl_config,
- 0,
- false,
- false));
- scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
- EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(),
- ssl_params, MEDIUM, CompletionCallback(),
- http_session_->GetSSLSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL),
- BoundNetLog()));
-
- EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK));
- EXPECT_TRUE(session->NeedsCredentials());
-
- // Flush the SpdySession::OnReadComplete() task.
- base::MessageLoop::current()->RunUntilIdle();
-
- spdy_session_pool_->Remove(session);
- EXPECT_FALSE(spdy_session_pool_->HasSession(key));
-}
-
-TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
- if (GetParam() != kProtoSPDY3)
- return;
-
- // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
- // gets sent.
- SettingsMap new_settings;
- int32 window_size = 1;
- new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
-
- // Set up the socket so we read a SETTINGS frame that sets
- // INITIAL_WINDOW_SIZE.
- MockConnect connect_data(SYNCHRONOUS, OK);
- scoped_ptr<SpdyFrame> settings_frame(
- spdy_util_.ConstructSpdySettings(new_settings));
- MockRead reads[] = {
- CreateMockRead(*settings_frame, 0),
- MockRead(ASYNC, 0, 1) // EOF
- };
-
- session_deps_.host_resolver->set_synchronous_mode(true);
-
- scoped_ptr<DeterministicSocketData> data(
- new DeterministicSocketData(reads, arraysize(reads), NULL, 0));
- data->set_connect_data(connect_data);
- session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get());
-
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
- CreateDeterministicNetworkSession();
-
- scoped_refptr<SpdySession> session = CreateInitializedSession();
- base::WeakPtr<SpdyStream> spdy_stream1 =
- CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
- session, test_url_, MEDIUM, BoundNetLog());
- ASSERT_TRUE(spdy_stream1.get() != NULL);
- TestCompletionCallback callback1;
- EXPECT_NE(spdy_stream1->send_window_size(), window_size);
-
- data->RunFor(1); // Process the SETTINGS frame, but not the EOF
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
- EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
-
- // Release the first one, this will allow the second to be created.
- spdy_stream1->Cancel();
- EXPECT_EQ(NULL, spdy_stream1.get());
-
- base::WeakPtr<SpdyStream> spdy_stream2 =
- CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
- session, test_url_, MEDIUM, BoundNetLog());
- ASSERT_TRUE(spdy_stream2.get() != NULL);
- EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
- spdy_stream2->Cancel();
- EXPECT_EQ(NULL, spdy_stream2.get());
-}
-
// Test that SpdySession::DoRead reads data from the socket without yielding.
// This test makes 32k - 1 bytes of data available on the socket for reading. It
// then verifies that it has read all the available data without yielding.
TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
@@ -2475,9 +2275,6 @@ TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
// that DoRead has yielded even though there is data available for it to read
// (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads).
TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
@@ -2575,9 +2372,6 @@ TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
// will read the results from the async read, and rest of the data
// synchronously.
TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
@@ -2683,9 +2477,6 @@ TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
// GoAway could delete the SpdySession from the SpdySessionPool and the last
// reference to SpdySession.
TEST_P(SpdySessionTest, GoAwayWhileInDoLoop) {
- if (GetParam() > kProtoSPDY3)
- return;
-
MockConnect connect_data(SYNCHRONOUS, OK);
BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
@@ -2793,75 +2584,531 @@ TEST_P(SpdySessionTest, ProtocolNegotiation) {
session->flow_control_state());
EXPECT_EQ(kSpdySessionInitialWindowSize,
session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize,
+ EXPECT_EQ(kSpdySessionInitialWindowSize,
session->session_recv_window_size_);
}
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
}
-// SpdySession::{Increase,Decrease}RecvWindowSize should properly
-// adjust the session receive window size when the "enable_spdy_31"
-// flag is set. In addition, SpdySession::IncreaseRecvWindowSize
-// should trigger sending a WINDOW_UPDATE frame for a large enough
-// delta.
-TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
- if (GetParam() < kProtoSPDY31)
- return;
-
- session_deps_.host_resolver->set_synchronous_mode(true);
-
- const int32 delta_window_size = 100;
+// Tests the case of a non-SPDY request closing an idle SPDY session when no
+// pointers to the idle session are currently held.
+TEST_P(SpdySessionTest, CloseOneIdleConnection) {
+ ClientSocketPoolManager::set_max_sockets_per_group(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ ClientSocketPoolManager::set_max_sockets_per_pool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
MockConnect connect_data(SYNCHRONOUS, OK);
MockRead reads[] = {
- MockRead(ASYNC, 0, 2) // EOF
- };
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
- scoped_ptr<SpdyFrame> window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kSpdySessionInitialWindowSize + delta_window_size));
- MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*window_update, 1),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
};
- DeterministicSocketData data(reads, arraysize(reads),
- writes, arraysize(writes));
+ StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
data.set_connect_data(connect_data);
- session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
-
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
- CreateDeterministicNetworkSession();
- scoped_refptr<SpdySession> session = GetSession(key_);
- InitializeSession(
- http_session_.get(), session.get(), test_host_port_pair_);
- EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
- session->flow_control_state());
+ CreateNetworkSession();
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
- EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
+ TransportClientSocketPool* pool =
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL);
- session->IncreaseRecvWindowSize(delta_window_size);
- EXPECT_EQ(kDefaultInitialRecvWindowSize + delta_window_size,
- session->session_recv_window_size_);
- EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
+ // Create an idle SPDY session.
+ SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+ scoped_refptr<SpdySession> session1 = GetSession(key1);
+ EXPECT_EQ(
+ OK,
+ InitializeSession(http_session_.get(), session1.get(),
+ key1.host_port_pair()));
+ EXPECT_FALSE(pool->IsStalled());
+ // Release the pointer to the session so it can be closed.
+ session1 = NULL;
- // Should trigger sending a WINDOW_UPDATE frame.
- session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
- EXPECT_EQ(kDefaultInitialRecvWindowSize + delta_window_size +
- kSpdySessionInitialWindowSize,
+ // Trying to create a new connection should cause the pool to be stalled, and
+ // post a task asynchronously to try and close the session.
+ TestCompletionCallback callback2;
+ HostPortPair host_port2("2.com", 80);
+ scoped_refptr<TransportSocketParams> params2(
+ new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
+ callback2.callback(), pool, BoundNetLog()));
+ EXPECT_TRUE(pool->IsStalled());
+
+ // The socket pool should close the connection asynchronously and establish a
+ // new connection.
+ EXPECT_EQ(OK, callback2.WaitForResult());
+ EXPECT_FALSE(pool->IsStalled());
+}
+
+// Tests the case of a non-SPDY request closing an idle SPDY session when no
+// pointers to the idle session are currently held, in the case the SPDY session
+// has an alias.
+TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
+ ClientSocketPoolManager::set_max_sockets_per_group(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ ClientSocketPoolManager::set_max_sockets_per_pool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+
+ 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);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ session_deps_.host_resolver->set_synchronous_mode(true);
+ session_deps_.host_resolver->rules()->AddIPLiteralRule(
+ "1.com", "192.168.0.2", std::string());
+ session_deps_.host_resolver->rules()->AddIPLiteralRule(
+ "2.com", "192.168.0.2", std::string());
+ // Not strictly needed.
+ session_deps_.host_resolver->rules()->AddIPLiteralRule(
+ "3.com", "192.168.0.3", std::string());
+
+ CreateNetworkSession();
+
+ TransportClientSocketPool* pool =
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL);
+
+ // Create an idle SPDY session.
+ SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+ scoped_refptr<SpdySession> session1 = GetSession(key1);
+ EXPECT_EQ(
+ OK,
+ InitializeSession(http_session_.get(), session1.get(),
+ key1.host_port_pair()));
+ EXPECT_FALSE(pool->IsStalled());
+
+ // Set up an alias for the idle SPDY session, increasing its ref count to 2.
+ SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+ SpdySessionPoolPeer pool_peer(spdy_session_pool_);
+ HostResolver::RequestInfo info(key2.host_port_pair());
+ AddressList addresses;
+ // Pre-populate the DNS cache, since a synchronous resolution is required in
+ // order to create the alias.
+ session_deps_.host_resolver->Resolve(
+ info, &addresses, CompletionCallback(), NULL, BoundNetLog());
+ // Add the alias for the first session's key. Has to be done manually since
+ // the usual process is bypassed.
+ pool_peer.AddAlias(addresses.front(), key1);
+ // Get a session for |key2|, which should return the session created earlier.
+ scoped_refptr<SpdySession> session2 =
+ spdy_session_pool_->Get(key2, BoundNetLog());
+ ASSERT_EQ(session1.get(), session2.get());
+ EXPECT_FALSE(pool->IsStalled());
+
+ // Release both the pointers to the session so it can be closed.
+ session1 = NULL;
+ session2 = NULL;
+
+ // Trying to create a new connection should cause the pool to be stalled, and
+ // post a task asynchronously to try and close the session.
+ TestCompletionCallback callback3;
+ HostPortPair host_port3("3.com", 80);
+ scoped_refptr<TransportSocketParams> params3(
+ new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
+ callback3.callback(), pool, BoundNetLog()));
+ EXPECT_TRUE(pool->IsStalled());
+
+ // The socket pool should close the connection asynchronously and establish a
+ // new connection.
+ EXPECT_EQ(OK, callback3.WaitForResult());
+ EXPECT_FALSE(pool->IsStalled());
+}
+
+// Tests the case of a non-SPDY request closing an idle SPDY session when a
+// pointer to the idle session is still held.
+TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) {
+ ClientSocketPoolManager::set_max_sockets_per_group(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ ClientSocketPoolManager::set_max_sockets_per_pool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+
+ 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);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ CreateNetworkSession();
+
+ TransportClientSocketPool* pool =
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL);
+
+ // Create an idle SPDY session.
+ SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+ scoped_refptr<SpdySession> session1 = GetSession(key1);
+ EXPECT_EQ(
+ OK,
+ InitializeSession(http_session_.get(), session1.get(),
+ key1.host_port_pair()));
+ EXPECT_FALSE(pool->IsStalled());
+
+ // Trying to create a new connection should cause the pool to be stalled, and
+ // post a task asynchronously to try and close the session.
+ TestCompletionCallback callback2;
+ HostPortPair host_port2("2.com", 80);
+ scoped_refptr<TransportSocketParams> params2(
+ new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
+ callback2.callback(), pool, BoundNetLog()));
+ EXPECT_TRUE(pool->IsStalled());
+
+ // Running the message loop should cause the session to prepare to be closed,
+ // but since there's still an outstanding reference, it should not be closed
+ // yet.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pool->IsStalled());
+ EXPECT_FALSE(callback2.have_result());
+
+ // Release the pointer to the session so it can be closed.
+ session1 = NULL;
+ EXPECT_EQ(OK, callback2.WaitForResult());
+ EXPECT_FALSE(pool->IsStalled());
+}
+
+// Tests that a non-SPDY request can't close a SPDY session that's currently in
+// use.
+TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) {
+ ClientSocketPoolManager::set_max_sockets_per_group(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ ClientSocketPoolManager::set_max_sockets_per_pool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
+ };
+ scoped_ptr<SpdyFrame> req1(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdyFrame> cancel1(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
+ MockWrite writes[] = {
+ CreateMockWrite(*req1, 1),
+ CreateMockWrite(*cancel1, 1),
+ };
+ StaticSocketDataProvider data(reads, arraysize(reads),
+ writes, arraysize(writes));
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ CreateNetworkSession();
+
+ TransportClientSocketPool* pool =
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL);
+
+ // Create a SPDY session.
+ GURL url1("http://www.google.com");
+ SpdySessionKey key1(HostPortPair(url1.host(), 80),
+ ProxyServer::Direct(), kPrivacyModeDisabled);
+ scoped_refptr<SpdySession> session1 = GetSession(key1);
+ EXPECT_EQ(
+ OK,
+ InitializeSession(http_session_.get(), session1.get(),
+ key1.host_port_pair()));
+ EXPECT_FALSE(pool->IsStalled());
+
+ // Create a stream using the session, and send a request.
+
+ TestCompletionCallback callback1;
+ base::WeakPtr<SpdyStream> spdy_stream1 =
+ CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
+ session1, url1, DEFAULT_PRIORITY,
+ BoundNetLog());
+ ASSERT_TRUE(spdy_stream1.get());
+ test::StreamDelegateDoNothing delegate1(spdy_stream1);
+ spdy_stream1->SetDelegate(&delegate1);
+
+ scoped_ptr<SpdyHeaderBlock> headers1(
+ spdy_util_.ConstructGetHeaderBlock(url1.spec()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ spdy_stream1->SendRequestHeaders(
+ headers1.Pass(), NO_MORE_DATA_TO_SEND));
+ EXPECT_TRUE(spdy_stream1->HasUrl());
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Release the session, so holding onto a pointer here does not affect
+ // anything.
+ session1 = NULL;
+
+ // Trying to create a new connection should cause the pool to be stalled, and
+ // post a task asynchronously to try and close the session.
+ TestCompletionCallback callback2;
+ HostPortPair host_port2("2.com", 80);
+ scoped_refptr<TransportSocketParams> params2(
+ new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
+ callback2.callback(), pool, BoundNetLog()));
+ EXPECT_TRUE(pool->IsStalled());
+
+ // Running the message loop should cause the socket pool to ask the SPDY
+ // session to close an idle socket, but since the socket is in use, nothing
+ // happens.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pool->IsStalled());
+ EXPECT_FALSE(callback2.have_result());
+
+ // Cancelling the request should still not release the session's socket,
+ // since the session is still kept alive by the SpdySessionPool.
+ ASSERT_TRUE(spdy_stream1.get());
+ spdy_stream1->Cancel();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pool->IsStalled());
+ EXPECT_FALSE(callback2.have_result());
+}
+
+// Verify that SpdySessionKey and therefore SpdySession is different when
+// privacy mode is enabled or disabled.
+TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
+ CreateDeterministicNetworkSession();
+
+ HostPortPair host_port_pair("www.google.com", 443);
+ SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
+ kPrivacyModeEnabled);
+ SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+
+ // Add SpdySession with PrivacyMode Enabled to the pool.
+ scoped_refptr<SpdySession> session_privacy_enabled =
+ spdy_session_pool_->Get(key_privacy_enabled, BoundNetLog());
+
+ EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled));
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+
+ // Add SpdySession with PrivacyMode Disabled to the pool.
+ scoped_refptr<SpdySession> session_privacy_disabled =
+ spdy_session_pool_->Get(key_privacy_disabled, BoundNetLog());
+
+ EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled));
+ EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled));
+
+ spdy_session_pool_->Remove(session_privacy_enabled);
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
+ EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled));
+
+ spdy_session_pool_->Remove(session_privacy_disabled);
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+}
+
+// The tests below are only for SPDY/3 and above.
+
+TEST_P(SpdySessionTest, SendCredentials) {
+ if (GetParam() < kProtoSPDY3)
+ return;
+
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
+ };
+ SettingsMap settings;
+ scoped_ptr<SpdyFrame> settings_frame(
+ spdy_util_.ConstructSpdySettings(settings));
+ MockWrite writes[] = {
+ CreateMockWrite(*settings_frame),
+ };
+ StaticSocketDataProvider data(reads, arraysize(reads),
+ writes, arraysize(writes));
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
+ ssl.channel_id_sent = true;
+ ssl.protocol_negotiated = GetParam();
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ CreateNetworkSession();
+
+ const GURL kTestUrl("https://www.foo.com");
+ HostPortPair test_host_port_pair(kTestUrl.host(), 443);
+ SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
+ kPrivacyModeDisabled);
+
+ scoped_refptr<SpdySession> session = GetSession(key);
+
+ SSLConfig ssl_config;
+ scoped_refptr<TransportSocketParams> transport_params(
+ new TransportSocketParams(test_host_port_pair,
+ MEDIUM,
+ false,
+ false,
+ OnHostResolutionCallback()));
+ scoped_refptr<SOCKSSocketParams> socks_params;
+ scoped_refptr<HttpProxySocketParams> http_proxy_params;
+ scoped_refptr<SSLSocketParams> ssl_params(
+ new SSLSocketParams(transport_params,
+ socks_params,
+ http_proxy_params,
+ ProxyServer::SCHEME_DIRECT,
+ test_host_port_pair,
+ ssl_config,
+ 0,
+ false,
+ false));
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+ EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(),
+ ssl_params, MEDIUM, CompletionCallback(),
+ http_session_->GetSSLSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+
+ EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK));
+ EXPECT_TRUE(session->NeedsCredentials());
+
+ // Flush the SpdySession::OnReadComplete() task.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ spdy_session_pool_->Remove(session);
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key));
+}
+
+TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
+ if (GetParam() < kProtoSPDY3)
+ return;
+
+ // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
+ // gets sent.
+ SettingsMap new_settings;
+ int32 window_size = 1;
+ new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
+
+ // Set up the socket so we read a SETTINGS frame that sets
+ // INITIAL_WINDOW_SIZE.
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ scoped_ptr<SpdyFrame> settings_frame(
+ spdy_util_.ConstructSpdySettings(new_settings));
+ MockRead reads[] = {
+ CreateMockRead(*settings_frame, 0),
+ MockRead(ASYNC, 0, 1) // EOF
+ };
+
+ session_deps_.host_resolver->set_synchronous_mode(true);
+
+ scoped_ptr<DeterministicSocketData> data(
+ new DeterministicSocketData(reads, arraysize(reads), NULL, 0));
+ data->set_connect_data(connect_data);
+ session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get());
+
+ SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ CreateDeterministicNetworkSession();
+
+ scoped_refptr<SpdySession> session = CreateInitializedSession();
+ base::WeakPtr<SpdyStream> spdy_stream1 =
+ CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
+ session, test_url_, MEDIUM, BoundNetLog());
+ ASSERT_TRUE(spdy_stream1.get() != NULL);
+ TestCompletionCallback callback1;
+ EXPECT_NE(spdy_stream1->send_window_size(), window_size);
+
+ data->RunFor(1); // Process the SETTINGS frame, but not the EOF
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
+ EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
+
+ // Release the first one, this will allow the second to be created.
+ spdy_stream1->Cancel();
+ EXPECT_EQ(NULL, spdy_stream1.get());
+
+ base::WeakPtr<SpdyStream> spdy_stream2 =
+ CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
+ session, test_url_, MEDIUM, BoundNetLog());
+ ASSERT_TRUE(spdy_stream2.get() != NULL);
+ EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
+ spdy_stream2->Cancel();
+ EXPECT_EQ(NULL, spdy_stream2.get());
+}
+
+// The tests below are only for SPDY/3.1 and above.
+
+// SpdySession::{Increase,Decrease}RecvWindowSize should properly
+// adjust the session receive window size for SPDY 3.1 and higher. In
+// addition, SpdySession::IncreaseRecvWindowSize should trigger
+// sending a WINDOW_UPDATE frame for a large enough delta.
+TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
+ if (GetParam() < kProtoSPDY31)
+ return;
+
+ session_deps_.host_resolver->set_synchronous_mode(true);
+
+ const int32 delta_window_size = 100;
+
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 1) // EOF
+ };
+ scoped_ptr<SpdyFrame> window_update(
+ spdy_util_.ConstructSpdyWindowUpdate(
+ kSessionFlowControlStreamId,
+ kSpdySessionInitialWindowSize + delta_window_size));
+ MockWrite writes[] = {
+ CreateMockWrite(*window_update, 0),
+ };
+ DeterministicSocketData data(reads, arraysize(reads),
+ writes, arraysize(writes));
+ data.set_connect_data(connect_data);
+ session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
+
+ SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
+ session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ CreateDeterministicNetworkSession();
+ scoped_refptr<SpdySession> session = GetSession(key_);
+ InitializeSession(
+ http_session_.get(), session.get(), test_host_port_pair_);
+ EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
+ session->flow_control_state());
+
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
+
+ session->IncreaseRecvWindowSize(delta_window_size);
+ EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
+ session->session_recv_window_size_);
+ EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
+
+ // Should trigger sending a WINDOW_UPDATE frame.
+ session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
+ EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
+ kSpdySessionInitialWindowSize,
session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
- data.RunFor(2);
+ data.RunFor(1);
session->DecreaseRecvWindowSize(
- kDefaultInitialRecvWindowSize + delta_window_size +
+ kSpdySessionInitialWindowSize + delta_window_size +
kSpdySessionInitialWindowSize);
EXPECT_EQ(0, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
@@ -2914,18 +3161,10 @@ TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
MockConnect connect_data(SYNCHRONOUS, OK);
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
MockRead reads[] = {
- CreateMockRead(*resp, 1),
- MockRead(ASYNC, 0, 2) // EOF
- };
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
- MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
+ CreateMockRead(*resp, 0),
+ MockRead(ASYNC, 0, 1) // EOF
};
- DeterministicSocketData data(reads, arraysize(reads),
- writes, arraysize(writes));
+ DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
data.set_connect_data(connect_data);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
@@ -2939,12 +3178,12 @@ TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
session->flow_control_state());
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
- data.RunFor(3);
+ data.RunFor(2);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
}
@@ -2975,10 +3214,6 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
MockConnect connect_data(SYNCHRONOUS, OK);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
@@ -2986,9 +3221,8 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), msg_data_size, false));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req, 1),
- CreateMockWrite(*msg, 3),
+ CreateMockWrite(*req, 0),
+ CreateMockWrite(*msg, 2),
};
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
@@ -2999,9 +3233,9 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
spdy_util_.ConstructSpdyWindowUpdate(
kSessionFlowControlStreamId, msg_data_size));
MockRead reads[] = {
- CreateMockRead(*resp, 2),
- CreateMockRead(*echo, 4),
- MockRead(ASYNC, 0, 5) // EOF
+ CreateMockRead(*resp, 1),
+ CreateMockRead(*echo, 3),
+ MockRead(ASYNC, 0, 4) // EOF
};
// Create SpdySession and SpdyStream and send the request.
@@ -3034,15 +3268,15 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
EXPECT_TRUE(stream->HasUrl());
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
- data.RunFor(5);
+ data.RunFor(4);
EXPECT_TRUE(data.at_write_eof());
EXPECT_TRUE(data.at_read_eof());
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
stream->Close();
@@ -3050,7 +3284,7 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
EXPECT_EQ(OK, delegate.WaitForClose());
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
}
@@ -3068,22 +3302,17 @@ TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
MockConnect connect_data(SYNCHRONOUS, OK);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req, 1),
+ CreateMockWrite(*req, 0),
};
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
- CreateMockRead(*resp, 2),
- MockRead(ASYNC, 0, 3) // EOF
+ CreateMockRead(*resp, 1),
+ MockRead(ASYNC, 0, 2) // EOF
};
// Create SpdySession and SpdyStream and send the request.
@@ -3118,7 +3347,7 @@ TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- data.RunFor(2);
+ data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
@@ -3152,10 +3381,6 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
MockConnect connect_data(SYNCHRONOUS, OK);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
@@ -3163,9 +3388,8 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), msg_data_size, false));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req, 1),
- CreateMockWrite(*msg, 3),
+ CreateMockWrite(*req, 0),
+ CreateMockWrite(*msg, 2),
};
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
@@ -3176,10 +3400,10 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
spdy_util_.ConstructSpdyWindowUpdate(
kSessionFlowControlStreamId, msg_data_size));
MockRead reads[] = {
- CreateMockRead(*resp, 2),
- CreateMockRead(*echo, 4),
- CreateMockRead(*window_update, 5),
- MockRead(ASYNC, 0, 6) // EOF
+ CreateMockRead(*resp, 1),
+ CreateMockRead(*echo, 3),
+ CreateMockRead(*window_update, 4),
+ MockRead(ASYNC, 0, 5) // EOF
};
// Create SpdySession and SpdyStream and send the request.
@@ -3213,41 +3437,41 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
EXPECT_TRUE(stream->HasUrl());
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
- data.RunFor(2);
+ data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size,
+ EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
data.RunFor(1);
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size,
+ EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
session->session_recv_window_size_);
EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
@@ -3259,7 +3483,7 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
// Draining the delegate's read queue should increase the session's
// receive window.
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
stream->Close();
@@ -3268,7 +3492,7 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
EXPECT_EQ(OK, delegate.WaitForClose());
EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
- EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_);
+ EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
}
@@ -3283,19 +3507,14 @@ void SpdySessionTest::RunResumeAfterUnstallTest(
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
scoped_ptr<SpdyFrame> body(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req, 1),
- CreateMockWrite(*body, 2),
+ CreateMockWrite(*req, 0),
+ CreateMockWrite(*body, 1),
};
scoped_ptr<SpdyFrame> resp(
@@ -3303,8 +3522,8 @@ void SpdySessionTest::RunResumeAfterUnstallTest(
scoped_ptr<SpdyFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
MockRead reads[] = {
- CreateMockRead(*resp, 3),
- MockRead(ASYNC, 0, 0, 4), // EOF
+ CreateMockRead(*resp, 2),
+ MockRead(ASYNC, 0, 0, 3), // EOF
};
DeterministicSocketData data(reads, arraysize(reads),
@@ -3341,7 +3560,7 @@ void SpdySessionTest::RunResumeAfterUnstallTest(
stall_fn.Run(session.get(), stream.get());
- data.RunFor(2);
+ data.RunFor(1);
EXPECT_TRUE(stream->send_stalled_by_flow_control());
@@ -3443,10 +3662,6 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
@@ -3458,19 +3673,18 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
scoped_ptr<SpdyFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req1, 1),
- CreateMockWrite(*req2, 2),
- CreateMockWrite(*body2, 3),
- CreateMockWrite(*body1, 4),
+ CreateMockWrite(*req1, 0),
+ CreateMockWrite(*req2, 1),
+ CreateMockWrite(*body2, 2),
+ CreateMockWrite(*body1, 3),
};
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
MockRead reads[] = {
- CreateMockRead(*resp1, 5),
- CreateMockRead(*resp2, 6),
- MockRead(ASYNC, 0, 0, 7), // EOF
+ CreateMockRead(*resp1, 4),
+ CreateMockRead(*resp2, 5),
+ MockRead(ASYNC, 0, 0, 6), // EOF
};
DeterministicSocketData data(reads, arraysize(reads),
@@ -3519,7 +3733,7 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
EXPECT_TRUE(stream1->HasUrl());
EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
- data.RunFor(2);
+ data.RunFor(1);
EXPECT_EQ(1u, stream1->stream_id());
EXPECT_TRUE(stream1->send_stalled_by_flow_control());
@@ -3548,207 +3762,17 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
// This should then unstall stream1.
UnstallSessionSend(session.get(), kBodyDataSize);
- EXPECT_FALSE(stream1->send_stalled_by_flow_control());
- EXPECT_FALSE(stream2->send_stalled_by_flow_control());
-
- data.RunFor(4);
-
- EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
- EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
-
- EXPECT_TRUE(delegate1.send_headers_completed());
- EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
- EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version"));
- EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
-
- EXPECT_TRUE(delegate2.send_headers_completed());
- EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
- EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
- EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
-
- EXPECT_TRUE(data.at_write_eof());
-}
-
-// Delegate that closes a given stream after sending its body.
-class StreamClosingDelegate : public test::StreamDelegateWithBody {
- public:
- StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
- base::StringPiece data)
- : StreamDelegateWithBody(stream, data) {}
-
- virtual ~StreamClosingDelegate() {}
-
- void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
- stream_to_close_ = stream_to_close;
- }
-
- virtual void OnDataSent() OVERRIDE {
- test::StreamDelegateWithBody::OnDataSent();
- if (stream_to_close_.get()) {
- stream_to_close_->Close();
- EXPECT_EQ(NULL, stream_to_close_.get());
- }
- }
-
- private:
- base::WeakPtr<SpdyStream> stream_to_close_;
-};
-
-// Cause a stall by reducing the flow control send window to
-// 0. Unstalling the session should properly handle deleted streams.
-TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
- if (GetParam() < kProtoSPDY31)
- return;
-
- const char kStreamUrl[] = "http://www.google.com/";
- GURL url(kStreamUrl);
-
- session_deps_.host_resolver->set_synchronous_mode(true);
-
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> body2(
- spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
- MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req1, 1),
- CreateMockWrite(*req2, 2),
- CreateMockWrite(*req3, 3),
- CreateMockWrite(*body2, 4),
- };
-
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- MockRead reads[] = {
- CreateMockRead(*resp2, 5),
- MockRead(ASYNC, 0, 0, 6), // EOF
- };
-
- DeterministicSocketData data(reads, arraysize(reads),
- writes, arraysize(writes));
- MockConnect connect_data(SYNCHRONOUS, OK);
- data.set_connect_data(connect_data);
-
- session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
-
- CreateDeterministicNetworkSession();
- scoped_refptr<SpdySession> session = GetSession(key_);
- InitializeSession(
- http_session_.get(), session.get(), test_host_port_pair_);
- EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
- session->flow_control_state());
-
- base::WeakPtr<SpdyStream> stream1 =
- CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
- session, url, LOWEST, BoundNetLog());
- ASSERT_TRUE(stream1.get() != NULL);
-
- test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
- stream1->SetDelegate(&delegate1);
-
- EXPECT_FALSE(stream1->HasUrl());
-
- base::WeakPtr<SpdyStream> stream2 =
- CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
- session, url, LOWEST, BoundNetLog());
- ASSERT_TRUE(stream2.get() != NULL);
-
- StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
- stream2->SetDelegate(&delegate2);
-
- EXPECT_FALSE(stream2->HasUrl());
-
- base::WeakPtr<SpdyStream> stream3 =
- CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
- session, url, LOWEST, BoundNetLog());
- ASSERT_TRUE(stream3.get() != NULL);
-
- test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
- stream3->SetDelegate(&delegate3);
-
- EXPECT_FALSE(stream3->HasUrl());
-
- EXPECT_FALSE(stream1->send_stalled_by_flow_control());
- EXPECT_FALSE(stream2->send_stalled_by_flow_control());
- EXPECT_FALSE(stream3->send_stalled_by_flow_control());
-
- StallSessionSend(session.get());
-
- scoped_ptr<SpdyHeaderBlock> headers1(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
- EXPECT_EQ(ERR_IO_PENDING,
- stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
- EXPECT_TRUE(stream1->HasUrl());
- EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
-
- data.RunFor(2);
- EXPECT_EQ(1u, stream1->stream_id());
- EXPECT_TRUE(stream1->send_stalled_by_flow_control());
-
- scoped_ptr<SpdyHeaderBlock> headers2(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
- EXPECT_EQ(ERR_IO_PENDING,
- stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
- EXPECT_TRUE(stream2->HasUrl());
- EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec());
-
- data.RunFor(1);
- EXPECT_EQ(3u, stream2->stream_id());
- EXPECT_TRUE(stream2->send_stalled_by_flow_control());
-
- scoped_ptr<SpdyHeaderBlock> headers3(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
- EXPECT_EQ(ERR_IO_PENDING,
- stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
- EXPECT_TRUE(stream3->HasUrl());
- EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec());
-
- data.RunFor(1);
- EXPECT_EQ(5u, stream3->stream_id());
- EXPECT_TRUE(stream3->send_stalled_by_flow_control());
-
- SpdyStreamId stream_id1 = stream1->stream_id();
- SpdyStreamId stream_id2 = stream2->stream_id();
- SpdyStreamId stream_id3 = stream3->stream_id();
-
- // Close stream1 preemptively.
- session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
- EXPECT_EQ(NULL, stream1.get());
-
- EXPECT_FALSE(session->IsStreamActive(stream_id1));
- EXPECT_TRUE(session->IsStreamActive(stream_id2));
- EXPECT_TRUE(session->IsStreamActive(stream_id3));
-
- // Unstall stream2, which should then close stream3.
- delegate2.set_stream_to_close(stream3);
- UnstallSessionSend(session.get(), kBodyDataSize);
-
- data.RunFor(1);
- EXPECT_EQ(NULL, stream3.get());
-
- EXPECT_FALSE(stream2->send_stalled_by_flow_control());
- EXPECT_FALSE(session->IsStreamActive(stream_id1));
- EXPECT_TRUE(session->IsStreamActive(stream_id2));
- EXPECT_FALSE(session->IsStreamActive(stream_id3));
+ EXPECT_FALSE(stream1->send_stalled_by_flow_control());
+ EXPECT_FALSE(stream2->send_stalled_by_flow_control());
- data.RunFor(2);
- EXPECT_EQ(NULL, stream2.get());
+ data.RunFor(4);
EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
- EXPECT_EQ(OK, delegate3.WaitForClose());
EXPECT_TRUE(delegate1.send_headers_completed());
+ EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
+ EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version"));
EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
EXPECT_TRUE(delegate2.send_headers_completed());
@@ -3756,16 +3780,37 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
- EXPECT_TRUE(delegate3.send_headers_completed());
- EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
-
EXPECT_TRUE(data.at_write_eof());
}
+// Delegate that closes a given stream after sending its body.
+class StreamClosingDelegate : public test::StreamDelegateWithBody {
+ public:
+ StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
+ base::StringPiece data)
+ : StreamDelegateWithBody(stream, data) {}
+
+ virtual ~StreamClosingDelegate() {}
+
+ void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
+ stream_to_close_ = stream_to_close;
+ }
+
+ virtual void OnDataSent() OVERRIDE {
+ test::StreamDelegateWithBody::OnDataSent();
+ if (stream_to_close_.get()) {
+ stream_to_close_->Close();
+ EXPECT_EQ(NULL, stream_to_close_.get());
+ }
+ }
+
+ private:
+ base::WeakPtr<SpdyStream> stream_to_close_;
+};
+
// Cause a stall by reducing the flow control send window to
-// 0. Unstalling the session should properly handle the session itself
-// being closed.
-TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
+// 0. Unstalling the session should properly handle deleted streams.
+TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
if (GetParam() < kProtoSPDY31)
return;
@@ -3774,26 +3819,28 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> initial_window_update(
- spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId,
- kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
scoped_ptr<SpdyFrame> req2(
spdy_util_.ConstructSpdyPost(
kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> body1(
- spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
+ scoped_ptr<SpdyFrame> req3(
+ spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
+ scoped_ptr<SpdyFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
- CreateMockWrite(*initial_window_update, 0),
- CreateMockWrite(*req1, 1),
- CreateMockWrite(*req2, 2),
+ CreateMockWrite(*req1, 0),
+ CreateMockWrite(*req2, 1),
+ CreateMockWrite(*req3, 2),
+ CreateMockWrite(*body2, 3),
};
+ scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
MockRead reads[] = {
- MockRead(ASYNC, 0, 0, 3), // EOF
+ CreateMockRead(*resp2, 4),
+ MockRead(ASYNC, 0, 0, 5), // EOF
};
DeterministicSocketData data(reads, arraysize(reads),
@@ -3825,13 +3872,24 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
session, url, LOWEST, BoundNetLog());
ASSERT_TRUE(stream2.get() != NULL);
- test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
+ StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
stream2->SetDelegate(&delegate2);
EXPECT_FALSE(stream2->HasUrl());
+ base::WeakPtr<SpdyStream> stream3 =
+ CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
+ session, url, LOWEST, BoundNetLog());
+ ASSERT_TRUE(stream3.get() != NULL);
+
+ test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
+ stream3->SetDelegate(&delegate3);
+
+ EXPECT_FALSE(stream3->HasUrl());
+
EXPECT_FALSE(stream1->send_stalled_by_flow_control());
EXPECT_FALSE(stream2->send_stalled_by_flow_control());
+ EXPECT_FALSE(stream3->send_stalled_by_flow_control());
StallSessionSend(session.get());
@@ -3842,7 +3900,7 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
EXPECT_TRUE(stream1->HasUrl());
EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
- data.RunFor(2);
+ data.RunFor(1);
EXPECT_EQ(1u, stream1->stream_id());
EXPECT_TRUE(stream1->send_stalled_by_flow_control());
@@ -3857,370 +3915,174 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
EXPECT_EQ(3u, stream2->stream_id());
EXPECT_TRUE(stream2->send_stalled_by_flow_control());
- EXPECT_TRUE(spdy_session_pool_->HasSession(key_));
-
- // Unstall stream1.
- UnstallSessionSend(session.get(), kBodyDataSize);
-
- // Close the session (since we can't do it from within the delegate
- // method, since it's in the stream's loop).
- session->CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "Closing session");
- session = NULL;
-
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_));
-
- EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
- EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
-
- EXPECT_TRUE(delegate1.send_headers_completed());
- EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
-
- EXPECT_TRUE(delegate2.send_headers_completed());
- EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
-
- EXPECT_TRUE(data.at_write_eof());
-}
-
-// Tests the case of a non-SPDY request closing an idle SPDY session when no
-// pointers to the idle session are currently held.
-TEST_P(SpdySessionTest, CloseOneIdleConnection) {
- if (GetParam() > kProtoSPDY3)
- return;
-
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- ClientSocketPoolManager::set_max_sockets_per_pool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
-
- 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);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- CreateNetworkSession();
-
- TransportClientSocketPool* pool =
- http_session_->GetTransportSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
-
- // Create an idle SPDY session.
- SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
- kPrivacyModeDisabled);
- scoped_refptr<SpdySession> session1 = GetSession(key1);
- EXPECT_EQ(
- OK,
- InitializeSession(http_session_.get(), session1.get(),
- key1.host_port_pair()));
- EXPECT_FALSE(pool->IsStalled());
- // Release the pointer to the session so it can be closed.
- session1 = NULL;
-
- // Trying to create a new connection should cause the pool to be stalled, and
- // post a task asynchronously to try and close the session.
- TestCompletionCallback callback2;
- HostPortPair host_port2("2.com", 80);
- scoped_refptr<TransportSocketParams> params2(
- new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
- OnHostResolutionCallback()));
- scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
+ scoped_ptr<SpdyHeaderBlock> headers3(
+ spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
EXPECT_EQ(ERR_IO_PENDING,
- connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
- callback2.callback(), pool, BoundNetLog()));
- EXPECT_TRUE(pool->IsStalled());
-
- // The socket pool should close the connection asynchronously and establish a
- // new connection.
- EXPECT_EQ(OK, callback2.WaitForResult());
- EXPECT_FALSE(pool->IsStalled());
-}
-
-// Tests the case of a non-SPDY request closing an idle SPDY session when no
-// pointers to the idle session are currently held, in the case the SPDY session
-// has an alias.
-TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
- if (GetParam() > kProtoSPDY3)
- return;
-
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- ClientSocketPoolManager::set_max_sockets_per_pool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
-
- 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);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- session_deps_.host_resolver->set_synchronous_mode(true);
- session_deps_.host_resolver->rules()->AddIPLiteralRule(
- "1.com", "192.168.0.2", std::string());
- session_deps_.host_resolver->rules()->AddIPLiteralRule(
- "2.com", "192.168.0.2", std::string());
- // Not strictly needed.
- session_deps_.host_resolver->rules()->AddIPLiteralRule(
- "3.com", "192.168.0.3", std::string());
-
- CreateNetworkSession();
-
- TransportClientSocketPool* pool =
- http_session_->GetTransportSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
-
- // Create an idle SPDY session.
- SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
- kPrivacyModeDisabled);
- scoped_refptr<SpdySession> session1 = GetSession(key1);
- EXPECT_EQ(
- OK,
- InitializeSession(http_session_.get(), session1.get(),
- key1.host_port_pair()));
- EXPECT_FALSE(pool->IsStalled());
-
- // Set up an alias for the idle SPDY session, increasing its ref count to 2.
- SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
- kPrivacyModeDisabled);
- SpdySessionPoolPeer pool_peer(spdy_session_pool_);
- HostResolver::RequestInfo info(key2.host_port_pair());
- AddressList addresses;
- // Pre-populate the DNS cache, since a synchronous resolution is required in
- // order to create the alias.
- session_deps_.host_resolver->Resolve(
- info, &addresses, CompletionCallback(), NULL, BoundNetLog());
- // Add the alias for the first session's key. Has to be done manually since
- // the usual process is bypassed.
- pool_peer.AddAlias(addresses.front(), key1);
- // Get a session for |key2|, which should return the session created earlier.
- scoped_refptr<SpdySession> session2 =
- spdy_session_pool_->Get(key2, BoundNetLog());
- ASSERT_EQ(session1.get(), session2.get());
- EXPECT_FALSE(pool->IsStalled());
+ stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
+ EXPECT_TRUE(stream3->HasUrl());
+ EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec());
- // Release both the pointers to the session so it can be closed.
- session1 = NULL;
- session2 = NULL;
+ data.RunFor(1);
+ EXPECT_EQ(5u, stream3->stream_id());
+ EXPECT_TRUE(stream3->send_stalled_by_flow_control());
- // Trying to create a new connection should cause the pool to be stalled, and
- // post a task asynchronously to try and close the session.
- TestCompletionCallback callback3;
- HostPortPair host_port3("3.com", 80);
- scoped_refptr<TransportSocketParams> params3(
- new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false,
- OnHostResolutionCallback()));
- scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
- EXPECT_EQ(ERR_IO_PENDING,
- connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
- callback3.callback(), pool, BoundNetLog()));
- EXPECT_TRUE(pool->IsStalled());
+ SpdyStreamId stream_id1 = stream1->stream_id();
+ SpdyStreamId stream_id2 = stream2->stream_id();
+ SpdyStreamId stream_id3 = stream3->stream_id();
- // The socket pool should close the connection asynchronously and establish a
- // new connection.
- EXPECT_EQ(OK, callback3.WaitForResult());
- EXPECT_FALSE(pool->IsStalled());
-}
+ // Close stream1 preemptively.
+ session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
+ EXPECT_EQ(NULL, stream1.get());
-// Tests the case of a non-SPDY request closing an idle SPDY session when a
-// pointer to the idle session is still held.
-TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) {
- if (GetParam() > kProtoSPDY3)
- return;
+ EXPECT_FALSE(session->IsStreamActive(stream_id1));
+ EXPECT_TRUE(session->IsStreamActive(stream_id2));
+ EXPECT_TRUE(session->IsStreamActive(stream_id3));
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- ClientSocketPoolManager::set_max_sockets_per_pool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ // Unstall stream2, which should then close stream3.
+ delegate2.set_stream_to_close(stream3);
+ UnstallSessionSend(session.get(), kBodyDataSize);
- 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);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
+ data.RunFor(1);
+ EXPECT_EQ(NULL, stream3.get());
- CreateNetworkSession();
+ EXPECT_FALSE(stream2->send_stalled_by_flow_control());
+ EXPECT_FALSE(session->IsStreamActive(stream_id1));
+ EXPECT_TRUE(session->IsStreamActive(stream_id2));
+ EXPECT_FALSE(session->IsStreamActive(stream_id3));
- TransportClientSocketPool* pool =
- http_session_->GetTransportSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
+ data.RunFor(2);
+ EXPECT_EQ(NULL, stream2.get());
- // Create an idle SPDY session.
- SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
- kPrivacyModeDisabled);
- scoped_refptr<SpdySession> session1 = GetSession(key1);
- EXPECT_EQ(
- OK,
- InitializeSession(http_session_.get(), session1.get(),
- key1.host_port_pair()));
- EXPECT_FALSE(pool->IsStalled());
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
+ EXPECT_EQ(OK, delegate3.WaitForClose());
- // Trying to create a new connection should cause the pool to be stalled, and
- // post a task asynchronously to try and close the session.
- TestCompletionCallback callback2;
- HostPortPair host_port2("2.com", 80);
- scoped_refptr<TransportSocketParams> params2(
- new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
- OnHostResolutionCallback()));
- scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
- EXPECT_EQ(ERR_IO_PENDING,
- connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
- callback2.callback(), pool, BoundNetLog()));
- EXPECT_TRUE(pool->IsStalled());
+ EXPECT_TRUE(delegate1.send_headers_completed());
+ EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
- // Running the message loop should cause the session to prepare to be closed,
- // but since there's still an outstanding reference, it should not be closed
- // yet.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(pool->IsStalled());
- EXPECT_FALSE(callback2.have_result());
+ EXPECT_TRUE(delegate2.send_headers_completed());
+ EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
+ EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
+ EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
- // Release the pointer to the session so it can be closed.
- session1 = NULL;
- EXPECT_EQ(OK, callback2.WaitForResult());
- EXPECT_FALSE(pool->IsStalled());
+ EXPECT_TRUE(delegate3.send_headers_completed());
+ EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
+
+ EXPECT_TRUE(data.at_write_eof());
}
-// Tests that a non-SPDY request can't close a SPDY session that's currently in
-// use.
-TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) {
- if (GetParam() > kProtoSPDY3)
+// Cause a stall by reducing the flow control send window to
+// 0. Unstalling the session should properly handle the session itself
+// being closed.
+TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
+ if (GetParam() < kProtoSPDY31)
return;
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- ClientSocketPoolManager::set_max_sockets_per_pool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
+ const char kStreamUrl[] = "http://www.google.com/";
+ GURL url(kStreamUrl);
+
+ session_deps_.host_resolver->set_synchronous_mode(true);
- MockConnect connect_data(SYNCHRONOUS, OK);
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
- };
scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> cancel1(
- spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
+ spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
+ scoped_ptr<SpdyFrame> req2(
+ spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
+ scoped_ptr<SpdyFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
MockWrite writes[] = {
- CreateMockWrite(*req1, 1),
- CreateMockWrite(*cancel1, 1),
+ CreateMockWrite(*req1, 0),
+ CreateMockWrite(*req2, 1),
};
- StaticSocketDataProvider data(reads, arraysize(reads),
- writes, arraysize(writes));
+
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 0, 2), // EOF
+ };
+
+ DeterministicSocketData data(reads, arraysize(reads),
+ writes, arraysize(writes));
+ MockConnect connect_data(SYNCHRONOUS, OK);
data.set_connect_data(connect_data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
- CreateNetworkSession();
+ session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
- TransportClientSocketPool* pool =
- http_session_->GetTransportSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
+ CreateDeterministicNetworkSession();
+ scoped_refptr<SpdySession> session = GetSession(key_);
+ InitializeSession(
+ http_session_.get(), session.get(), test_host_port_pair_);
+ EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
+ session->flow_control_state());
- // Create a SPDY session.
- GURL url1("http://www.google.com");
- SpdySessionKey key1(HostPortPair(url1.host(), 80),
- ProxyServer::Direct(), kPrivacyModeDisabled);
- scoped_refptr<SpdySession> session1 = GetSession(key1);
- EXPECT_EQ(
- OK,
- InitializeSession(http_session_.get(), session1.get(),
- key1.host_port_pair()));
- EXPECT_FALSE(pool->IsStalled());
+ base::WeakPtr<SpdyStream> stream1 =
+ CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
+ session, url, LOWEST, BoundNetLog());
+ ASSERT_TRUE(stream1.get() != NULL);
- // Create a stream using the session, and send a request.
+ test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
+ stream1->SetDelegate(&delegate1);
- TestCompletionCallback callback1;
- base::WeakPtr<SpdyStream> spdy_stream1 =
+ EXPECT_FALSE(stream1->HasUrl());
+
+ base::WeakPtr<SpdyStream> stream2 =
CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
- session1, url1, DEFAULT_PRIORITY,
- BoundNetLog());
- ASSERT_TRUE(spdy_stream1.get());
- test::StreamDelegateDoNothing delegate1(spdy_stream1);
- spdy_stream1->SetDelegate(&delegate1);
+ session, url, LOWEST, BoundNetLog());
+ ASSERT_TRUE(stream2.get() != NULL);
- scoped_ptr<SpdyHeaderBlock> headers1(
- spdy_util_.ConstructGetHeaderBlock(url1.spec()));
- EXPECT_EQ(ERR_IO_PENDING,
- spdy_stream1->SendRequestHeaders(
- headers1.Pass(), NO_MORE_DATA_TO_SEND));
- EXPECT_TRUE(spdy_stream1->HasUrl());
+ test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
+ stream2->SetDelegate(&delegate2);
- base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_FALSE(stream2->HasUrl());
- // Release the session, so holding onto a pointer here does not affect
- // anything.
- session1 = NULL;
+ EXPECT_FALSE(stream1->send_stalled_by_flow_control());
+ EXPECT_FALSE(stream2->send_stalled_by_flow_control());
- // Trying to create a new connection should cause the pool to be stalled, and
- // post a task asynchronously to try and close the session.
- TestCompletionCallback callback2;
- HostPortPair host_port2("2.com", 80);
- scoped_refptr<TransportSocketParams> params2(
- new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
- OnHostResolutionCallback()));
- scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
+ StallSessionSend(session.get());
+
+ scoped_ptr<SpdyHeaderBlock> headers1(
+ spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
EXPECT_EQ(ERR_IO_PENDING,
- connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
- callback2.callback(), pool, BoundNetLog()));
- EXPECT_TRUE(pool->IsStalled());
+ stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
+ EXPECT_TRUE(stream1->HasUrl());
+ EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
- // Running the message loop should cause the socket pool to ask the SPDY
- // session to close an idle socket, but since the socket is in use, nothing
- // happens.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(pool->IsStalled());
- EXPECT_FALSE(callback2.have_result());
+ data.RunFor(1);
+ EXPECT_EQ(1u, stream1->stream_id());
+ EXPECT_TRUE(stream1->send_stalled_by_flow_control());
- // Cancelling the request should still not release the session's socket,
- // since the session is still kept alive by the SpdySessionPool.
- ASSERT_TRUE(spdy_stream1.get());
- spdy_stream1->Cancel();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(pool->IsStalled());
- EXPECT_FALSE(callback2.have_result());
-}
+ scoped_ptr<SpdyHeaderBlock> headers2(
+ spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
+ EXPECT_EQ(ERR_IO_PENDING,
+ stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
+ EXPECT_TRUE(stream2->HasUrl());
+ EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec());
-// Verify that SpdySessionKey and therefore SpdySession is different when
-// privacy mode is enabled or disabled.
-TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
- CreateDeterministicNetworkSession();
+ data.RunFor(1);
+ EXPECT_EQ(3u, stream2->stream_id());
+ EXPECT_TRUE(stream2->send_stalled_by_flow_control());
- HostPortPair host_port_pair("www.google.com", 443);
- SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeEnabled);
- SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ EXPECT_TRUE(spdy_session_pool_->HasSession(key_));
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+ // Unstall stream1.
+ UnstallSessionSend(session.get(), kBodyDataSize);
- // Add SpdySession with PrivacyMode Enabled to the pool.
- scoped_refptr<SpdySession> session_privacy_enabled =
- spdy_session_pool_->Get(key_privacy_enabled, BoundNetLog());
+ // Close the session (since we can't do it from within the delegate
+ // method, since it's in the stream's loop).
+ session->CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "Closing session");
+ session = NULL;
- EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled));
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+ EXPECT_FALSE(spdy_session_pool_->HasSession(key_));
- // Add SpdySession with PrivacyMode Disabled to the pool.
- scoped_refptr<SpdySession> session_privacy_disabled =
- spdy_session_pool_->Get(key_privacy_disabled, BoundNetLog());
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
- EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled));
- EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled));
+ EXPECT_TRUE(delegate1.send_headers_completed());
+ EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
- spdy_session_pool_->Remove(session_privacy_enabled);
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
- EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled));
+ EXPECT_TRUE(delegate2.send_headers_completed());
+ EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
- spdy_session_pool_->Remove(session_privacy_disabled);
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled));
- EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled));
+ EXPECT_TRUE(data.at_write_eof());
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698