summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_session_spdy2_unittest.cc
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-23 02:43:25 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-23 02:43:25 +0000
commit49769d31820e00ee35c4a554e9e557023d8948ce (patch)
treedd1987b66d80668fc41f1d826264c429b6248a71 /net/spdy/spdy_session_spdy2_unittest.cc
parent089df8eba039306e50da494446c5ea7ee5cdbb54 (diff)
downloadchromium_src-49769d31820e00ee35c4a554e9e557023d8948ce.zip
chromium_src-49769d31820e00ee35c4a554e9e557023d8948ce.tar.gz
chromium_src-49769d31820e00ee35c4a554e9e557023d8948ce.tar.bz2
SPDY - handle stalled spdy streams properly when number of concurrent
streams go over 100. Changed create_stream_queues_ to pending_create_stream_queues_ for readability (jar). When a spdy_stream is closed or a created stream which didn't have stream_id is cancelled, handle how many streams get unstalled (or new streams that are created) properly. Fix is not to go over the max concurrent streams limit. Bug=170491 R=rch@chromium.org,jar@chromium.org TESTS=network unit tests Review URL: https://chromiumcodereview.appspot.com/12033016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@178218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy/spdy_session_spdy2_unittest.cc')
-rw-r--r--net/spdy/spdy_session_spdy2_unittest.cc282
1 files changed, 282 insertions, 0 deletions
diff --git a/net/spdy/spdy_session_spdy2_unittest.cc b/net/spdy/spdy_session_spdy2_unittest.cc
index d9401c8..54b8722 100644
--- a/net/spdy/spdy_session_spdy2_unittest.cc
+++ b/net/spdy/spdy_session_spdy2_unittest.cc
@@ -1586,4 +1586,286 @@ TEST_F(SpdySessionSpdy2Test, CloseSessionWithTwoCreatedStreams) {
spdy_stream2 = NULL;
}
+TEST_F(SpdySessionSpdy2Test, CloseTwoStalledCreateStream) {
+ // TODO(rtenneti): Define a helper class/methods and move the common code in
+ // this file.
+ MockConnect connect_data(SYNCHRONOUS, OK);
+
+ SettingsMap new_settings;
+ const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
+ const uint32 max_concurrent_streams = 1;
+ new_settings[kSpdySettingsIds1] =
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+
+ scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
+ scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
+ scoped_ptr<SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
+ MockWrite writes[] = {
+ CreateMockWrite(*req1, 1),
+ CreateMockWrite(*req2, 4),
+ CreateMockWrite(*req3, 7),
+ };
+
+ // Set up the socket so we read a SETTINGS frame that sets max concurrent
+ // streams to 1.
+ scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(new_settings));
+
+ scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true));
+
+ scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true));
+
+ scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
+ scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, true));
+
+ MockRead reads[] = {
+ CreateMockRead(*settings_frame),
+ CreateMockRead(*resp1, 2),
+ CreateMockRead(*body1, 3),
+ CreateMockRead(*resp2, 5),
+ CreateMockRead(*body2, 6),
+ CreateMockRead(*resp3, 8),
+ CreateMockRead(*body3, 9),
+ MockRead(ASYNC, 0, 10) // EOF
+ };
+
+ SpdySessionDependencies session_deps;
+ session_deps.host_resolver->set_synchronous_mode(true);
+
+ 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);
+
+ scoped_refptr<HttpNetworkSession> http_session(
+ SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps));
+
+ const std::string kTestHost("www.foo.com");
+ const int kTestPort = 80;
+ HostPortPair test_host_port_pair(kTestHost, kTestPort);
+ HostPortProxyPair pair(test_host_port_pair, ProxyServer::Direct());
+
+ SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool());
+
+ // Create a session.
+ EXPECT_FALSE(spdy_session_pool->HasSession(pair));
+ scoped_refptr<SpdySession> session =
+ spdy_session_pool->Get(pair, BoundNetLog());
+ ASSERT_TRUE(spdy_session_pool->HasSession(pair));
+
+ scoped_refptr<TransportSocketParams> transport_params(
+ new TransportSocketParams(test_host_port_pair,
+ LOWEST,
+ false,
+ false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+ EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(),
+ transport_params, LOWEST, CompletionCallback(),
+ http_session->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+ EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK));
+
+ // Read the settings frame.
+ data.RunFor(1);
+
+ scoped_refptr<SpdyStream> spdy_stream1;
+ TestCompletionCallback callback1;
+ GURL url1("http://www.google.com");
+ EXPECT_EQ(OK, session->CreateStream(url1,
+ LOWEST,
+ &spdy_stream1,
+ BoundNetLog(),
+ callback1.callback()));
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+
+ scoped_refptr<SpdyStream> spdy_stream2;
+ TestCompletionCallback callback2;
+ GURL url2("http://www.google.com");
+ EXPECT_EQ(ERR_IO_PENDING,
+ session->CreateStream(url2,
+ LOWEST,
+ &spdy_stream2,
+ BoundNetLog(),
+ callback2.callback()));
+
+ scoped_refptr<SpdyStream> spdy_stream3;
+ TestCompletionCallback callback3;
+ GURL url3("http://www.google.com");
+ EXPECT_EQ(ERR_IO_PENDING,
+ session->CreateStream(url3,
+ LOWEST,
+ &spdy_stream3,
+ BoundNetLog(),
+ callback3.callback()));
+
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST));
+
+ scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
+ (*headers)["method"] = "GET";
+ (*headers)["scheme"] = url1.scheme();
+ (*headers)["host"] = url1.host();
+ (*headers)["url"] = url1.path();
+ (*headers)["version"] = "HTTP/1.1";
+ scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock);
+ *headers2 = *headers;
+ scoped_ptr<SpdyHeaderBlock> headers3(new SpdyHeaderBlock);
+ *headers3 = *headers;
+
+ spdy_stream1->set_spdy_headers(headers.Pass());
+ EXPECT_TRUE(spdy_stream1->HasUrl());
+ spdy_stream1->SendRequest(false);
+
+ // Run until 1st stream is closed.
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+ data.RunFor(3);
+ EXPECT_EQ(1u, spdy_stream1->stream_id());
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(1u, session->pending_create_stream_queues(LOWEST));
+
+ EXPECT_TRUE(spdy_stream2.get() != NULL);
+ spdy_stream2->set_spdy_headers(headers2.Pass());
+ EXPECT_TRUE(spdy_stream2->HasUrl());
+ spdy_stream2->SendRequest(false);
+
+ // Run until 2nd stream is closed.
+ EXPECT_EQ(0u, spdy_stream2->stream_id());
+ data.RunFor(3);
+ EXPECT_EQ(3u, spdy_stream2->stream_id());
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST));
+
+ EXPECT_TRUE(spdy_stream3.get() != NULL);
+ spdy_stream3->set_spdy_headers(headers3.Pass());
+ EXPECT_TRUE(spdy_stream3->HasUrl());
+ spdy_stream3->SendRequest(false);
+
+ EXPECT_EQ(0u, spdy_stream3->stream_id());
+ data.RunFor(4);
+ EXPECT_EQ(5u, spdy_stream3->stream_id());
+ EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST));
+}
+
+TEST_F(SpdySessionSpdy2Test, CancelTwoStalledCreateStream) {
+ SpdySessionDependencies session_deps;
+ session_deps.host_resolver->set_synchronous_mode(true);
+
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
+ };
+
+ StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
+ MockConnect connect_data(SYNCHRONOUS, OK);
+
+ data.set_connect_data(connect_data);
+ session_deps.socket_factory->AddSocketDataProvider(&data);
+
+ SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
+ session_deps.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ scoped_refptr<HttpNetworkSession> http_session(
+ SpdySessionDependencies::SpdyCreateSession(&session_deps));
+
+ const std::string kTestHost("www.foo.com");
+ const int kTestPort = 80;
+ HostPortPair test_host_port_pair(kTestHost, kTestPort);
+ HostPortProxyPair pair(test_host_port_pair, ProxyServer::Direct());
+
+ SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool());
+
+ // Initialize the SpdySetting with 1 max concurrent streams.
+ spdy_session_pool->http_server_properties()->SetSpdySetting(
+ test_host_port_pair,
+ SETTINGS_MAX_CONCURRENT_STREAMS,
+ SETTINGS_FLAG_PLEASE_PERSIST,
+ 1);
+
+ // Create a session.
+ EXPECT_FALSE(spdy_session_pool->HasSession(pair));
+ scoped_refptr<SpdySession> session =
+ spdy_session_pool->Get(pair, BoundNetLog());
+ ASSERT_TRUE(spdy_session_pool->HasSession(pair));
+
+ scoped_refptr<TransportSocketParams> transport_params(
+ new TransportSocketParams(test_host_port_pair,
+ LOWEST,
+ false,
+ false,
+ OnHostResolutionCallback()));
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+ EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(),
+ transport_params,
+ LOWEST,
+ CompletionCallback(),
+ http_session->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+ EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK));
+
+ scoped_refptr<SpdyStream> spdy_stream1;
+ TestCompletionCallback callback1;
+ GURL url1("http://www.google.com");
+ ASSERT_EQ(OK,
+ session->CreateStream(url1,
+ LOWEST,
+ &spdy_stream1,
+ BoundNetLog(),
+ callback1.callback()));
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+
+ scoped_refptr<SpdyStream> spdy_stream2;
+ TestCompletionCallback callback2;
+ GURL url2("http://www.google.com");
+ ASSERT_EQ(ERR_IO_PENDING,
+ session->CreateStream(url2,
+ LOWEST,
+ &spdy_stream2,
+ BoundNetLog(),
+ callback2.callback()));
+
+ scoped_refptr<SpdyStream> spdy_stream3;
+ TestCompletionCallback callback3;
+ GURL url3("http://www.google.com");
+ ASSERT_EQ(ERR_IO_PENDING,
+ session->CreateStream(url3,
+ LOWEST,
+ &spdy_stream3,
+ BoundNetLog(),
+ callback3.callback()));
+
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST));
+
+ // Cancel the first stream, this will allow the second stream to be created.
+ EXPECT_TRUE(spdy_stream1.get() != NULL);
+ spdy_stream1->Cancel();
+ spdy_stream1 = NULL;
+ session->CancelPendingCreateStreams(&spdy_stream1);
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(1u, session->pending_create_stream_queues(LOWEST));
+
+ // Cancel the second stream, this will allow the third stream to be created.
+ EXPECT_TRUE(spdy_stream2.get() != NULL);
+ spdy_stream2->Cancel();
+ spdy_stream2 = NULL;
+ session->CancelPendingCreateStreams(&spdy_stream2);
+ EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST));
+
+ // Cancel the third stream.
+ EXPECT_TRUE(spdy_stream3.get() != NULL);
+ spdy_stream3->Cancel();
+ spdy_stream3 = NULL;
+ session->CancelPendingCreateStreams(&spdy_stream3);
+ EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams());
+ EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST));
+}
+
} // namespace net