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