Fixes accounting for DataFrameSources in NgHttp2Adapter. * Avoids adding a map entry that points to nullptr. * Fixes some related test expectations. PiperOrigin-RevId: 633734619
diff --git a/quiche/http2/adapter/nghttp2_adapter.cc b/quiche/http2/adapter/nghttp2_adapter.cc index 557bd82..cdea62b 100644 --- a/quiche/http2/adapter/nghttp2_adapter.cc +++ b/quiche/http2/adapter/nghttp2_adapter.cc
@@ -233,7 +233,9 @@ int32_t stream_id = nghttp2_submit_request(session_->raw_ptr(), nullptr, nvs.data(), nvs.size(), provider.get(), stream_user_data); - sources_.emplace(stream_id, std::move(data_source)); + if (data_source != nullptr) { + sources_.emplace(stream_id, std::move(data_source)); + } QUICHE_VLOG(1) << "Submitted request with " << nvs.size() << " request headers and user data " << stream_user_data << "; resulted in stream " << stream_id; @@ -249,7 +251,9 @@ std::unique_ptr<nghttp2_data_provider> provider = MakeDataProvider(data_source.get()); - sources_.emplace(stream_id, std::move(data_source)); + if (data_source != nullptr) { + sources_.emplace(stream_id, std::move(data_source)); + } int result = nghttp2_submit_response(session_->raw_ptr(), stream_id, nvs.data(), nvs.size(), provider.get());
diff --git a/quiche/http2/adapter/nghttp2_adapter_test.cc b/quiche/http2/adapter/nghttp2_adapter_test.cc index 1e66f03..c621176 100644 --- a/quiche/http2/adapter/nghttp2_adapter_test.cc +++ b/quiche/http2/adapter/nghttp2_adapter_test.cc
@@ -146,7 +146,9 @@ adapter->SetStreamUserData(stream_id2, const_cast<char*>(kSentinel2)); adapter->SetStreamUserData(stream_id3, nullptr); - EXPECT_EQ(adapter->sources_size(), 3); + // These requests did not include a body, so they do not have corresponding + // DataFrameSources. + EXPECT_EQ(adapter->sources_size(), 0); EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5)); EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0)); @@ -231,9 +233,6 @@ EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetStreamReceiveWindowSize(stream_id3)); - // One stream was closed. - EXPECT_EQ(adapter->sources_size(), 2); - // Connection window should be the same as the first stream. EXPECT_EQ(adapter->GetReceiveWindowSize(), adapter->GetStreamReceiveWindowSize(stream_id1)); @@ -279,7 +278,6 @@ // After receiving END_STREAM for 1 and RST_STREAM for 5, the session no // longer expects reads. EXPECT_FALSE(adapter->want_read()); - EXPECT_EQ(adapter->sources_size(), 0); // Client will not have anything else to write. EXPECT_FALSE(adapter->want_write()); @@ -904,6 +902,7 @@ adapter->SubmitRequest(headers1, std::move(body1), false, nullptr); ASSERT_GT(stream_id1, 0); EXPECT_EQ(stream_id1, kStreamId); + EXPECT_EQ(adapter->sources_size(), 1); EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4)); EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x4, 0)); @@ -5371,16 +5370,25 @@ std::move(body1), false); EXPECT_EQ(submit_result, 0); EXPECT_TRUE(adapter->want_write()); + EXPECT_EQ(adapter->sources_size(), 1); // 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)); + EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::CANCEL)) + .WillOnce( + [&adapter](Http2StreamId stream_id, Http2ErrorCode /*error_code*/) { + adapter->RemoveStream(stream_id); + return true; + }); const int64_t reset_result = adapter->ProcessBytes(reset); EXPECT_EQ(reset.size(), static_cast<size_t>(reset_result)); + // The stream's data source is dropped. + EXPECT_EQ(adapter->sources_size(), 0); + // Outbound HEADERS and DATA are dropped. EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, _)).Times(0); EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, _, _)).Times(0);