| Index: net/spdy/spdy_session_unittest.cc
|
| diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
|
| index 7115e54e5f413632390fe0b5f06a944f6b12261d..e6dd43974fd7ac7c25d49582dc6e4e1c3cdb3664 100644
|
| --- a/net/spdy/spdy_session_unittest.cc
|
| +++ b/net/spdy/spdy_session_unittest.cc
|
| @@ -1277,6 +1277,174 @@ TEST_F(SpdySessionTest, UnstallRacesWithStreamCreation) {
|
| EXPECT_THAT(callback2.WaitForResult(), IsOk());
|
| }
|
|
|
| +TEST_F(SpdySessionTest, CancelPushAfterExpired) {
|
| + base::HistogramTester histogram_tester;
|
| + session_deps_.host_resolver->set_synchronous_mode(true);
|
| + session_deps_.time_func = TheNearFuture;
|
| +
|
| + SpdySerializedFrame req(
|
| + spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
|
| + SpdySerializedFrame rst(
|
| + spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
|
| + MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
|
| +
|
| + SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
|
| + nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
|
| + SpdySerializedFrame push_a_body(spdy_util_.ConstructSpdyDataFrame(2, false));
|
| + // In ascii "0" < "a". We use it to verify that we properly handle std::map
|
| + // iterators inside. See http://crbug.com/443490
|
| + SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
|
| + nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
|
| + MockRead reads[] = {
|
| + CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
|
| + MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
|
| + MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
|
| + };
|
| +
|
| + SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
|
| + session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| +
|
| + AddSSLSocketData();
|
| +
|
| + CreateNetworkSession();
|
| + CreateSecureSpdySession();
|
| +
|
| + // Process the principal request, and the first push stream request & body.
|
| + base::WeakPtr<SpdyStream> spdy_stream =
|
| + CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
|
| + test_url_, MEDIUM, NetLogWithSource());
|
| + test::StreamDelegateDoNothing delegate(spdy_stream);
|
| + spdy_stream->SetDelegate(&delegate);
|
| +
|
| + SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
|
| + spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Verify that there is one unclaimed push stream.
|
| + EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
|
| + GURL("https://www.example.org/a.dat")));
|
| +
|
| + // Unclaimed push body consumed bytes from the session window.
|
| + EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
|
| + session_->session_recv_window_size_);
|
| + EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
|
| +
|
| + // Shift time to expire the push stream. Read the second HEADERS,
|
| + // and verify a RST_STREAM was written.
|
| + g_time_delta = base::TimeDelta::FromSeconds(301);
|
| + data.Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Verify that the second pushed stream evicted the first pushed stream.
|
| + EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
|
| + GURL("https://www.example.org/0.dat")));
|
| +
|
| + // Cancel the first push after its expiration.
|
| + session_->CancelPush(GURL("https://www.example.org/a.dat"));
|
| + EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_TRUE(session_);
|
| +
|
| + // Verify that the session window reclaimed the evicted stream body.
|
| + EXPECT_EQ(kDefaultInitialWindowSize, session_->session_recv_window_size_);
|
| + EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
|
| + EXPECT_TRUE(session_);
|
| +
|
| + // Read and process EOF.
|
| + data.Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(session_);
|
| + histogram_tester.ExpectBucketCount("Net.SpdySession.PushedBytes", 6, 1);
|
| + histogram_tester.ExpectBucketCount("Net.SpdySession.PushedAndUnclaimedBytes",
|
| + 6, 1);
|
| +}
|
| +
|
| +TEST_F(SpdySessionTest, CancelPushBeforeClaimed) {
|
| + base::HistogramTester histogram_tester;
|
| + session_deps_.host_resolver->set_synchronous_mode(true);
|
| + session_deps_.time_func = TheNearFuture;
|
| +
|
| + SpdySerializedFrame req(
|
| + spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
|
| + SpdySerializedFrame rst(
|
| + spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
|
| + MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
|
| +
|
| + SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
|
| + nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
|
| + SpdySerializedFrame push_a_body(spdy_util_.ConstructSpdyDataFrame(2, false));
|
| + // In ascii "0" < "a". We use it to verify that we properly handle std::map
|
| + // iterators inside. See http://crbug.com/443490
|
| + SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
|
| + nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
|
| + MockRead reads[] = {
|
| + CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
|
| + MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
|
| + MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
|
| + };
|
| +
|
| + SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
|
| + session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| +
|
| + AddSSLSocketData();
|
| +
|
| + CreateNetworkSession();
|
| + CreateSecureSpdySession();
|
| +
|
| + // Process the principal request, and the first push stream request & body.
|
| + base::WeakPtr<SpdyStream> spdy_stream =
|
| + CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
|
| + test_url_, MEDIUM, NetLogWithSource());
|
| + test::StreamDelegateDoNothing delegate(spdy_stream);
|
| + spdy_stream->SetDelegate(&delegate);
|
| +
|
| + SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
|
| + spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Verify that there is one unclaimed push stream.
|
| + EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
|
| + GURL("https://www.example.org/a.dat")));
|
| +
|
| + // Unclaimed push body consumed bytes from the session window.
|
| + EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
|
| + session_->session_recv_window_size_);
|
| + EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
|
| +
|
| + // Shift time to expire the push stream. Read the second HEADERS,
|
| + // and verify a RST_STREAM was written.
|
| + g_time_delta = base::TimeDelta::FromSeconds(301);
|
| + data.Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Verify that the second pushed stream evicted the first pushed stream.
|
| + GURL pushed_url("https://www.example.org/0.dat");
|
| + EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
|
| +
|
| + // Verify that the session window reclaimed the evicted stream body.
|
| + EXPECT_EQ(kDefaultInitialWindowSize, session_->session_recv_window_size_);
|
| + EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
|
| +
|
| + EXPECT_TRUE(session_);
|
| + // Cancel the push before it's claimed.
|
| + session_->CancelPush(pushed_url);
|
| + EXPECT_EQ(0u, session_->num_unclaimed_pushed_streams());
|
| + EXPECT_EQ(0u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
|
| +
|
| + // Read and process EOF.
|
| + data.Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(session_);
|
| + histogram_tester.ExpectBucketCount("Net.SpdySession.PushedBytes", 6, 1);
|
| + histogram_tester.ExpectBucketCount("Net.SpdySession.PushedAndUnclaimedBytes",
|
| + 6, 1);
|
| +}
|
| +
|
| TEST_F(SpdySessionTest, DeleteExpiredPushStreams) {
|
| base::HistogramTester histogram_tester;
|
| session_deps_.host_resolver->set_synchronous_mode(true);
|
|
|