diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc')
-rw-r--r-- | chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc | 163 |
1 files changed, 161 insertions, 2 deletions
diff --git a/chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc b/chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc index 8647b027895..9bf5bd219fe 100644 --- a/chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter_test.cc @@ -4744,6 +4744,81 @@ TEST(NgHttp2AdapterTest, ServerSubmitResponse) { EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0); } +TEST(NgHttp2AdapterTest, ServerSubmitResponseWithResetFromClient) { + DataSavingVisitor visitor; + auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor); + EXPECT_FALSE(adapter->want_write()); + + const std::string frames = TestFrameSequence() + .ClientPreface() + .Headers(1, + {{":method", "GET"}, + {":scheme", "https"}, + {":authority", "example.com"}, + {":path", "/this/is/request/one"}}, + /*fin=*/true) + .Serialize(); + testing::InSequence s; + + // Client preface (empty SETTINGS) + EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0)); + EXPECT_CALL(visitor, OnSettingsStart()); + EXPECT_CALL(visitor, OnSettingsEnd()); + // Stream 1 + EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5)); + EXPECT_CALL(visitor, OnBeginHeadersForStream(1)); + EXPECT_CALL(visitor, OnHeaderForStream).Times(4); + EXPECT_CALL(visitor, OnEndHeadersForStream(1)); + EXPECT_CALL(visitor, OnEndStream(1)); + + const int64_t result = adapter->ProcessBytes(frames); + EXPECT_EQ(frames.size(), result); + + EXPECT_EQ(1, adapter->GetHighestReceivedStreamId()); + + // Server will want to send a SETTINGS ack. + EXPECT_TRUE(adapter->want_write()); + + EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1)); + EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0)); + + int send_result = adapter->Send(); + EXPECT_EQ(0, send_result); + EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS})); + visitor.Clear(); + + EXPECT_FALSE(adapter->want_write()); + const absl::string_view kBody = "This is an example response body."; + auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true); + body1->AppendPayload(kBody); + int submit_result = adapter->SubmitResponse( + 1, + ToHeaders({{":status", "404"}, + {"x-comment", "I have no idea what you're talking about."}}), + std::move(body1)); + EXPECT_EQ(submit_result, 0); + EXPECT_TRUE(adapter->want_write()); + + // Client resets the stream before the server can send the response. + const std::string reset = + TestFrameSequence().RstStream(1, Http2ErrorCode::CANCEL).Serialize(); + EXPECT_CALL(visitor, OnFrameHeader(1, 4, RST_STREAM, 0)); + EXPECT_CALL(visitor, OnRstStream(1, Http2ErrorCode::CANCEL)); + EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::CANCEL)); + const int64_t reset_result = adapter->ProcessBytes(reset); + EXPECT_EQ(reset.size(), static_cast<size_t>(reset_result)); + + // Outbound HEADERS and DATA are dropped. + EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, _)).Times(0); + EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, _, _)).Times(0); + EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, _, _)).Times(0); + + send_result = adapter->Send(); + EXPECT_EQ(0, send_result); + + EXPECT_THAT(visitor.data(), testing::IsEmpty()); +} + // Should also test: client attempts shutdown, server attempts shutdown after an // explicit GOAWAY. TEST(NgHttp2AdapterTest, ServerSendsShutdown) { @@ -5883,12 +5958,12 @@ TEST(NgHttp2AdapterTest, AutomaticPingAcksDisabled) { EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS})); } -TEST(NgHttp2AdapterTest, InvalidMaxFrameSize) { +TEST(NgHttp2AdapterTest, InvalidMaxFrameSizeSetting) { DataSavingVisitor visitor; auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor); const std::string frames = - TestFrameSequence().ClientPreface({{MAX_FRAME_SIZE, 3}}).Serialize(); + TestFrameSequence().ClientPreface({{MAX_FRAME_SIZE, 3u}}).Serialize(); testing::InSequence s; // Client preface @@ -5912,6 +5987,90 @@ TEST(NgHttp2AdapterTest, InvalidMaxFrameSize) { EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY})); } +TEST(OgHttp2AdapterTest, InvalidPushSetting) { + DataSavingVisitor visitor; + auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor); + + const std::string frames = + TestFrameSequence().ClientPreface({{ENABLE_PUSH, 3u}}).Serialize(); + testing::InSequence s; + + // Client preface + EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0)); + EXPECT_CALL(visitor, OnInvalidFrame(0, _)); + + const int64_t read_result = adapter->ProcessBytes(frames); + EXPECT_EQ(static_cast<size_t>(read_result), frames.size()); + + EXPECT_TRUE(adapter->want_write()); + + EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0)); + EXPECT_CALL(visitor, + OnFrameSent(GOAWAY, 0, _, 0x0, + static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR))); + + int send_result = adapter->Send(); + EXPECT_EQ(0, send_result); + EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY})); +} + +TEST(NgHttp2AdapterTest, InvalidConnectProtocolSetting) { + DataSavingVisitor visitor; + auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor); + + const std::string frames = TestFrameSequence() + .ClientPreface({{ENABLE_CONNECT_PROTOCOL, 3u}}) + .Serialize(); + testing::InSequence s; + + EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0)); + EXPECT_CALL( + visitor, + OnInvalidFrame(0, Http2VisitorInterface::InvalidFrameError::kProtocol)); + + int64_t read_result = adapter->ProcessBytes(frames); + EXPECT_EQ(static_cast<size_t>(read_result), frames.size()); + + EXPECT_TRUE(adapter->want_write()); + + EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0)); + EXPECT_CALL(visitor, + OnFrameSent(GOAWAY, 0, _, 0x0, + static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR))); + + int send_result = adapter->Send(); + EXPECT_EQ(0, send_result); + EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY})); + + auto adapter2 = NgHttp2Adapter::CreateServerAdapter(visitor); + const std::string frames2 = TestFrameSequence() + .ClientPreface({{ENABLE_CONNECT_PROTOCOL, 1}}) + .Settings({{ENABLE_CONNECT_PROTOCOL, 0}}) + .Serialize(); + + EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0)); + EXPECT_CALL(visitor, OnSettingsStart()); + EXPECT_CALL(visitor, OnSetting(Http2Setting{ENABLE_CONNECT_PROTOCOL, 1u})); + EXPECT_CALL(visitor, OnSettingsEnd()); + EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0)); + EXPECT_CALL(visitor, OnSettingsStart()); + // Surprisingly, nghttp2 allows this behavior, which is prohibited in RFC + // 8441. + EXPECT_CALL(visitor, OnSetting(Http2Setting{ENABLE_CONNECT_PROTOCOL, 0u})); + EXPECT_CALL(visitor, OnSettingsEnd()); + + read_result = adapter2->ProcessBytes(frames2); + EXPECT_EQ(static_cast<size_t>(read_result), frames2.size()); + + EXPECT_TRUE(adapter2->want_write()); + + EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1)); + EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0)); + EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1)); + EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0)); + adapter2->Send(); +} + TEST(NgHttp2AdapterTest, ServerForbidsProtocolPseudoheaderBeforeAck) { DataSavingVisitor visitor; auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor); |