| Index: net/spdy/spdy_network_transaction_unittest.cc
|
| diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
|
| index d1a80a9940c2c34e00af2481c90e8479f751a979..405176babff294f90b4234fd3b572d9fbb45b747 100644
|
| --- a/net/spdy/spdy_network_transaction_unittest.cc
|
| +++ b/net/spdy/spdy_network_transaction_unittest.cc
|
| @@ -4027,6 +4027,84 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
|
| EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
|
| }
|
|
|
| +// A server can gracefully shut down by sending a GOAWAY frame
|
| +// with maximum last-stream-id value.
|
| +// Transactions started before receiving such a GOAWAY frame should succeed,
|
| +// but SpdySession should be unavailable for new streams.
|
| +TEST_F(SpdyNetworkTransactionTest, GracefulGoaway) {
|
| + SpdySerializedFrame req1(
|
| + spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
|
| + spdy_util_.UpdateWithStreamDestruction(1);
|
| + SpdySerializedFrame req2(
|
| + spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST));
|
| + MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
|
| +
|
| + SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
|
| + SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
|
| + SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
|
| + 0x7fffffff, GOAWAY_NO_ERROR, "Graceful shutdown."));
|
| + SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
|
| + SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
|
| + MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
|
| + CreateMockRead(goaway, 4), CreateMockRead(resp2, 5),
|
| + CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7)};
|
| +
|
| + // Run first transaction.
|
| + SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
|
| + NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
|
| + NetLogWithSource(), nullptr);
|
| + helper.RunPreTestSetup();
|
| + helper.AddData(&data);
|
| + helper.RunDefaultTest();
|
| +
|
| + // Verify first response.
|
| + TransactionHelperResult out = helper.output();
|
| + EXPECT_THAT(out.rv, IsOk());
|
| + EXPECT_EQ("HTTP/1.1 200", out.status_line);
|
| + EXPECT_EQ("hello!", out.response_data);
|
| +
|
| + // GOAWAY frame has not yet been received, SpdySession should be available.
|
| + SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
|
| + SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
|
| + PRIVACY_MODE_DISABLED);
|
| + NetLogWithSource log;
|
| + base::WeakPtr<SpdySession> spdy_session =
|
| + spdy_session_pool->FindAvailableSession(key, GURL(), log);
|
| + EXPECT_TRUE(spdy_session);
|
| +
|
| + // Start second transaction.
|
| + HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
|
| + TestCompletionCallback callback;
|
| + HttpRequestInfo request2;
|
| + request2.method = "GET";
|
| + request2.url = GURL("https://www.example.org/foo");
|
| + int rv = trans2.Start(&request2, callback.callback(), log);
|
| + EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
|
| + rv = callback.WaitForResult();
|
| + EXPECT_THAT(rv, IsOk());
|
| +
|
| + // Verify second response.
|
| + const HttpResponseInfo* response = trans2.GetResponseInfo();
|
| + ASSERT_TRUE(response);
|
| + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, response->connection_info);
|
| + ASSERT_TRUE(response->headers);
|
| + EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
|
| + EXPECT_TRUE(response->was_fetched_via_spdy);
|
| + EXPECT_TRUE(response->was_alpn_negotiated);
|
| + EXPECT_EQ("127.0.0.1", response->socket_address.host());
|
| + EXPECT_EQ(443, response->socket_address.port());
|
| + std::string response_data;
|
| + rv = ReadTransaction(&trans2, &response_data);
|
| + EXPECT_THAT(rv, IsOk());
|
| + EXPECT_EQ("hello!", response_data);
|
| +
|
| + // Graceful GOAWAY was received, SpdySession should be unavailable.
|
| + spdy_session = spdy_session_pool->FindAvailableSession(key, GURL(), log);
|
| + EXPECT_FALSE(spdy_session);
|
| +
|
| + helper.VerifyDataConsumed();
|
| +}
|
| +
|
| TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
|
| SpdySerializedFrame req(
|
| spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
|
|
|