Adds a test case that invokes nghttp2 directly to parse a sample frame sequence.
PiperOrigin-RevId: 374940755
diff --git a/http2/adapter/nghttp2_test.cc b/http2/adapter/nghttp2_test.cc
new file mode 100644
index 0000000..c9ccd0f
--- /dev/null
+++ b/http2/adapter/nghttp2_test.cc
@@ -0,0 +1,93 @@
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "http2/adapter/mock_nghttp2_callbacks.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+nghttp2_option* GetOptions() {
+ nghttp2_option* options;
+ nghttp2_option_new(&options);
+ // Set some common options for compatibility.
+ nghttp2_option_set_no_closed_streams(options, 1);
+ nghttp2_option_set_no_auto_window_update(options, 1);
+ nghttp2_option_set_max_send_header_block_length(options, 0x2000000);
+ nghttp2_option_set_max_outbound_ack(options, 10000);
+ return options;
+}
+
+// Verifies nghttp2 behavior when acting as a client.
+TEST(Nghttp2ClientTest, ClientReceivesUnexpectedHeaders) {
+ testing::StrictMock<MockNghttp2Callbacks> mock_callbacks;
+ auto nghttp2_callbacks = MockNghttp2Callbacks::GetCallbacks();
+ nghttp2_option* options = GetOptions();
+ nghttp2_session* ptr;
+ nghttp2_session_client_new2(&ptr, nghttp2_callbacks.get(), &mock_callbacks,
+ options);
+
+ auto client_session = MakeSessionPtr(ptr);
+
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+
+ testing::InSequence seq;
+ EXPECT_CALL(mock_callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, 0)));
+ EXPECT_CALL(mock_callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
+ EXPECT_CALL(mock_callbacks, OnBeginFrame(HasFrameHeader(0, PING, 0)));
+ EXPECT_CALL(mock_callbacks, OnFrameRecv(IsPing(42)));
+ EXPECT_CALL(mock_callbacks,
+ OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, 0)));
+ EXPECT_CALL(mock_callbacks, OnFrameRecv(IsWindowUpdate(1000)));
+
+ nghttp2_session_mem_recv(client_session.get(),
+ ToUint8Ptr(initial_frames.data()),
+ initial_frames.size());
+
+ const std::string unexpected_stream_frames =
+ TestFrameSequence()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
+ .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
+ .Serialize();
+
+ EXPECT_CALL(mock_callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
+ EXPECT_CALL(mock_callbacks, OnInvalidFrameRecv(IsHeaders(1, _, _), _));
+ // No events from the DATA, RST_STREAM or GOAWAY.
+
+ nghttp2_session_mem_recv(client_session.get(),
+ ToUint8Ptr(unexpected_stream_frames.data()),
+ unexpected_stream_frames.size());
+
+ nghttp2_option_del(options);
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2