Send correct STOP_SENDING/RESET_STREAM frames for different stream types.
Upon receiving RESET_STREAM for a write-only stream, the connection will be closed with error.
gfe-relnote: protected by disabled v99 flag.
PiperOrigin-RevId: 279850700
Change-Id: I9f0e6215a388dac226d430458a340e8934432662
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index d5d8321..4ee1230 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -389,24 +389,33 @@
}
void CloseStream(QuicStreamId id) {
- if (VersionHasIetfQuicFrames(session_.transport_version()) &&
- QuicUtils::GetStreamType(id, session_.perspective(),
- session_.IsIncomingStream(id)) ==
- READ_UNIDIRECTIONAL) {
- // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
- } else {
- // Verify reset IS sent for BIDIRECTIONAL streams.
- if (VersionHasIetfQuicFrames(session_.transport_version())) {
- // Once for the RST_STREAM, Once for the STOP_SENDING
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ if (QuicUtils::GetStreamType(id, session_.perspective(),
+ session_.IsIncomingStream(id)) ==
+ READ_UNIDIRECTIONAL) {
+ // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
+ } else if (QuicUtils::GetStreamType(id, session_.perspective(),
+ session_.IsIncomingStream(id)) ==
+ WRITE_UNIDIRECTIONAL) {
+ // Verify RESET_STREAM but not STOP_SENDING is sent for write-only
+ // stream.
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
+ } else {
+ // Verify RESET_STREAM and STOP_SENDING are sent for BIDIRECTIONAL
+ // streams.
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(2)
.WillRepeatedly(Invoke(&ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
}
+ } else {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
EXPECT_CALL(*connection_, OnStreamReset(id, _));
}
session_.CloseStream(id);
@@ -2753,6 +2762,41 @@
session_.OnStreamFrame(frame1);
}
+TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+
+ QuicStreamId read_only = GetNthClientInitiatedUnidirectionalId(0);
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
+ session_.SendRstStreamInner(read_only, QUIC_STREAM_CANCELLED, 0,
+ /*close_write_side_only = */ true);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
+ session_.SendRstStreamInner(read_only, QUIC_STREAM_CANCELLED, 0,
+ /*close_write_side_only = */ false);
+
+ QuicStreamId write_only = GetNthServerInitiatedUnidirectionalId(0);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(write_only, _));
+ session_.SendRstStreamInner(write_only, QUIC_STREAM_CANCELLED, 0,
+ /*close_write_side_only = */ false);
+
+ QuicStreamId bidirectional = GetNthClientInitiatedBidirectionalId(0);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(bidirectional, _));
+ session_.SendRstStreamInner(bidirectional, QUIC_STREAM_CANCELLED, 0,
+ /*close_write_side_only = */ false);
+}
+
// A client test class that can be used when the automatic configuration is not
// desired.
class QuicSessionTestClientUnconfigured : public QuicSessionTestBase {