Adds a unit test demonstrating that CallbackVisitor revives stream state even for closed streams.

PiperOrigin-RevId: 592325925
diff --git a/quiche/http2/adapter/callback_visitor_test.cc b/quiche/http2/adapter/callback_visitor_test.cc
index 4d0355e..88856ee 100644
--- a/quiche/http2/adapter/callback_visitor_test.cc
+++ b/quiche/http2/adapter/callback_visitor_test.cc
@@ -530,6 +530,61 @@
   EXPECT_EQ(frames.size(), result);
 }
 
+TEST(ServerCallbackVisitorUnitTest, HeadersAfterFin) {
+  testing::StrictMock<MockNghttp2Callbacks> callbacks;
+  CallbackVisitor visitor(Perspective::kServer,
+                          *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+  testing::InSequence seq;
+
+  // HEADERS on stream 1
+  EXPECT_CALL(
+      callbacks,
+      OnBeginFrame(HasFrameHeader(
+          1, HEADERS, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM)));
+  visitor.OnFrameHeader(1, 23, HEADERS, 5);
+
+  EXPECT_CALL(callbacks,
+              OnBeginHeaders(IsHeaders(
+                  1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
+                  NGHTTP2_HCAT_REQUEST)));
+  visitor.OnBeginHeadersForStream(1);
+
+  EXPECT_EQ(visitor.stream_map_size(), 1);
+
+  EXPECT_CALL(callbacks, OnHeader).Times(5);
+  visitor.OnHeaderForStream(1, ":method", "POST");
+  visitor.OnHeaderForStream(1, ":path", "/example/path");
+  visitor.OnHeaderForStream(1, ":scheme", "https");
+  visitor.OnHeaderForStream(1, ":authority", "example.com");
+  visitor.OnHeaderForStream(1, "accept", "text/html");
+
+  EXPECT_CALL(callbacks,
+              OnFrameRecv(IsHeaders(
+                  1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
+                  NGHTTP2_HCAT_REQUEST)));
+  visitor.OnEndHeadersForStream(1);
+
+  EXPECT_TRUE(visitor.OnEndStream(1));
+
+  EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
+  visitor.OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR);
+
+  EXPECT_EQ(visitor.stream_map_size(), 0);
+
+  // Invalid repeat HEADERS on closed stream 1
+  EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
+                             1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
+  visitor.OnFrameHeader(1, 23, HEADERS, 4);
+
+  EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
+                                                  NGHTTP2_HCAT_REQUEST)));
+  visitor.OnBeginHeadersForStream(1);
+
+  // Bug: the visitor should not revive streams that have already been closed.
+  EXPECT_EQ(visitor.stream_map_size(), 1);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace adapter