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

Unified Diff: net/spdy/spdy_session_unittest.cc

Issue 367963003: Separate client and server pushed streams limits. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
« net/spdy/spdy_session.h ('K') | « net/spdy/spdy_session.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_session_unittest.cc
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 12fad9119471a687c2f1c471b6385a18e89dbd18..c4d4171684e26b2fb1804b46f25ef0bc785d0e48 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -4544,6 +4544,258 @@ TEST_P(SpdySessionTest, SplitHeaders) {
EXPECT_EQ(kStreamUrl, request_url);
}
+// Regression. Sorta. Push streams and client streams were sharing a single
+// limit for a long time.
+TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
+ SettingsMap new_settings;
+ new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
+ scoped_ptr<SpdyFrame> settings_frame(
+ spdy_util_.ConstructSpdySettings(new_settings));
+ scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 2, 1, "http://www.google.com/a.dat"));
+ MockRead reads[] = {
+ CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
+ MockRead(ASYNC, 0, 4),
+ };
+
+ scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdyFrame> req(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ MockWrite writes[] = {
+ CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
+ };
+
+ 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();
+
+ base::WeakPtr<SpdySession> session =
+ CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
+
+ // Read the settings frame.
+ data.RunFor(1);
+
+ GURL url1(kDefaultURL);
+ base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
+ ASSERT_TRUE(spdy_stream1.get() != NULL);
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+ test::StreamDelegateDoNothing delegate1(spdy_stream1);
+ spdy_stream1->SetDelegate(&delegate1);
+
+ EXPECT_EQ(0u, session->num_active_streams());
+ EXPECT_EQ(1u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ scoped_ptr<SpdyHeaderBlock> headers(
+ spdy_util_.ConstructGetHeaderBlock(url1.spec()));
+ spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
+ EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
+
+ // Run until 1st stream is activated.
+ EXPECT_EQ(0u, delegate1.stream_id());
+ data.RunFor(2);
+ EXPECT_EQ(1u, delegate1.stream_id());
+ EXPECT_EQ(1u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ // Run until pushed stream is created.
+ data.RunFor(1);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Second stream should not be stalled, although we have 2 active streams, but
+ // one of them is push stream and should not be taken into account when we
+ // create streams on the client.
Johnny 2014/07/07 19:58:50 Nice!
+ base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
+ EXPECT_TRUE(spdy_stream2.get() != NULL);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(1u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Read EOF.
+ data.RunFor(1);
+}
+
+TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
+ scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 2, 1, "http://www.google.com/a.dat"));
+ scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 4, 1, "http://www.google.com/b.dat"));
+ MockRead reads[] = {
+ CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
+ MockRead(ASYNC, 0, 4),
+ };
+
+ scoped_ptr<SpdyFrame> req(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdyFrame> rst(
+ spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
+ MockWrite writes[] = {
+ CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
+ };
+
+ 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();
+
+ base::WeakPtr<SpdySession> session =
+ CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
+ session->set_max_concurrent_pushed_streams(1);
+
+ GURL url1(kDefaultURL);
+ base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
+ ASSERT_TRUE(spdy_stream1.get() != NULL);
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+ test::StreamDelegateDoNothing delegate1(spdy_stream1);
+ spdy_stream1->SetDelegate(&delegate1);
+
+ EXPECT_EQ(0u, session->num_active_streams());
+ EXPECT_EQ(1u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ scoped_ptr<SpdyHeaderBlock> headers(
+ spdy_util_.ConstructGetHeaderBlock(url1.spec()));
+ spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
+ EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
+
+ // Run until 1st stream is activated.
+ EXPECT_EQ(0u, delegate1.stream_id());
+ data.RunFor(1);
+ EXPECT_EQ(1u, delegate1.stream_id());
+ EXPECT_EQ(1u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ // Run until pushed stream is created.
+ data.RunFor(1);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Reset incoming pushed stream.
+ data.RunFor(2);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Read EOF.
+ data.RunFor(1);
+}
+
+TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
+ // Streams in reserved remote state exist only in SPDY4.
+ if (spdy_util_.spdy_version() < SPDY4)
+ return;
+
+ scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 2, 1, "http://www.google.com/a.dat"));
+ scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
+ spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
+ push_headers.get());
+ scoped_ptr<SpdyFrame> push_b(
+ spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
+ scoped_ptr<SpdyFrame> headers_b(
+ spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
+ MockRead reads[] = {
+ CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
+ CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
+ };
+
+ scoped_ptr<SpdyFrame> req(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdyFrame> rst(
+ spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
+ MockWrite writes[] = {
+ CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
+ };
+
+ 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();
+
+ base::WeakPtr<SpdySession> session =
+ CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
+ session->set_max_concurrent_pushed_streams(1);
+
+ GURL url1(kDefaultURL);
+ base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
+ ASSERT_TRUE(spdy_stream1.get() != NULL);
+ EXPECT_EQ(0u, spdy_stream1->stream_id());
+ test::StreamDelegateDoNothing delegate1(spdy_stream1);
+ spdy_stream1->SetDelegate(&delegate1);
+
+ EXPECT_EQ(0u, session->num_active_streams());
+ EXPECT_EQ(1u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ scoped_ptr<SpdyHeaderBlock> headers(
+ spdy_util_.ConstructGetHeaderBlock(url1.spec()));
+ spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
+ EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
+
+ // Run until 1st stream is activated.
+ EXPECT_EQ(0u, delegate1.stream_id());
+ data.RunFor(1);
+ EXPECT_EQ(1u, delegate1.stream_id());
+ EXPECT_EQ(1u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(0u, session->num_pushed_streams());
+ EXPECT_EQ(0u, session->num_active_pushed_streams());
+
+ // Run until pushed stream is created.
+ data.RunFor(1);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Accept promised stream. It should not count towards pushed stream limit.
+ data.RunFor(1);
+ EXPECT_EQ(3u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(2u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Reset last pushed stream upon headers reception as it is going to be 2nd,
+ // while we accept only one.
+ data.RunFor(2);
+ EXPECT_EQ(2u, session->num_active_streams());
+ EXPECT_EQ(0u, session->num_created_streams());
+ EXPECT_EQ(1u, session->num_pushed_streams());
+ EXPECT_EQ(1u, session->num_active_pushed_streams());
+
+ // Read EOF.
+ data.RunFor(1);
+}
+
TEST(MapFramerErrorToProtocolError, MapsValues) {
CHECK_EQ(
SPDY_ERROR_INVALID_CONTROL_FRAME,
« net/spdy/spdy_session.h ('K') | « net/spdy/spdy_session.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698