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 {