| Index: net/tools/quic/quic_client_session_test.cc
|
| diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
|
| index b60833dab182b0f11ce02bf60e0872a0eb12952d..12061ae3daa01664e8ead24de4303b982940332b 100644
|
| --- a/net/tools/quic/quic_client_session_test.cc
|
| +++ b/net/tools/quic/quic_client_session_test.cc
|
| @@ -199,8 +199,8 @@ TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) {
|
|
|
| QuicSpdyClientStream* stream =
|
| session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| - ASSERT_TRUE(stream);
|
| - EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority));
|
| + ASSERT_NE(nullptr, stream);
|
| + EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority));
|
|
|
| // Close the stream and receive an RST frame to remove the unfinished stream
|
| session_->CloseStream(stream->id());
|
| @@ -209,7 +209,81 @@ TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) {
|
| // Check that a new one can be created.
|
| EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
|
| stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| - EXPECT_TRUE(stream);
|
| + EXPECT_NE(nullptr, stream);
|
| +}
|
| +
|
| +TEST_P(QuicClientSessionTest, ResetAndTrailers) {
|
| + // Tests the situation in which the client sends a RST at the same time that
|
| + // the server sends trailing headers (trailers). Receipt of the trailers by
|
| + // the client should result in all outstanding stream state being tidied up
|
| + // (including flow control, and number of available outgoing streams).
|
| + const uint32_t kServerMaxIncomingStreams = 1;
|
| + CompleteCryptoHandshake(kServerMaxIncomingStreams);
|
| +
|
| + QuicSpdyClientStream* stream =
|
| + session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| + ASSERT_NE(nullptr, stream);
|
| + EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority));
|
| +
|
| + QuicStreamId stream_id = stream->id();
|
| + EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(1);
|
| + session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
|
| +
|
| + // A new stream cannot be created as the reset stream still counts as an open
|
| + // outgoing stream until closed by the server.
|
| + EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
|
| + stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| + EXPECT_EQ(nullptr, stream);
|
| +
|
| + // The stream receives trailers with final byte offset: this is one of three
|
| + // ways that a peer can signal the end of a stream (the others being RST,
|
| + // stream data + FIN).
|
| + QuicHeaderList trailers;
|
| + trailers.OnHeaderBlockStart();
|
| + trailers.OnHeader(kFinalOffsetHeaderKey, "0");
|
| + trailers.OnHeaderBlockEnd(0);
|
| + session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers);
|
| +
|
| + if (FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers) {
|
| + // The stream is now complete from the client's perspective, and it should
|
| + // be able to create a new outgoing stream.
|
| + EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
|
| + stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| + EXPECT_NE(nullptr, stream);
|
| + } else {
|
| + // The old behavior: receiving trailers with final offset does not trigger
|
| + // cleanup of local stream state. New streams cannot be created.
|
| + EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
|
| + stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| + EXPECT_EQ(nullptr, stream);
|
| + }
|
| +}
|
| +
|
| +TEST_P(QuicClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) {
|
| + // Tests the situation where the client has sent a RST to the server, and has
|
| + // received trailing headers with a malformed final byte offset value.
|
| + FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers = true;
|
| + CompleteCryptoHandshake();
|
| +
|
| + QuicSpdyClientStream* stream =
|
| + session_->CreateOutgoingDynamicStream(kDefaultPriority);
|
| + ASSERT_NE(nullptr, stream);
|
| +
|
| + // Send the RST, which results in the stream being closed locally (but some
|
| + // state remains while the client waits for a response from the server).
|
| + QuicStreamId stream_id = stream->id();
|
| + EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(1);
|
| + session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
|
| +
|
| + // The stream receives trailers with final byte offset, but the header value
|
| + // is non-numeric and should be treated as malformed.
|
| + QuicHeaderList trailers;
|
| + trailers.OnHeaderBlockStart();
|
| + trailers.OnHeader(kFinalOffsetHeaderKey, "invalid non-numeric value");
|
| + trailers.OnHeaderBlockEnd(0);
|
| +
|
| + EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
|
| + session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers);
|
| }
|
|
|
| TEST_P(QuicClientSessionTest, GoAwayReceived) {
|
|
|