@@ -4591,6 +4591,102 @@ TEST_P(Http2CodecImplTest, ChunkProcessingShouldNotScheduleIfReadDisabled) {
45914591 }
45924592}
45934593
4594+ TEST_P (Http2CodecImplTest, ServerDispatchLoadShedPointCanCauseServerToSendGoAway) {
4595+ if (Runtime::runtimeFeatureEnabled (" envoy.reloadable_features.http2_fix_goaway_loadshed_point" )) {
4596+ GTEST_SKIP ();
4597+ }
4598+ initialize ();
4599+ ASSERT_EQ (0 , server_stats_store_.counter (" http2.goaway_sent" ).value ());
4600+
4601+ TestRequestHeaderMapImpl request_headers;
4602+ HttpTestUtility::addDefaultHeaders (request_headers);
4603+ EXPECT_CALL (server_->server_go_away_on_dispatch , shouldShedLoad ()).WillOnce (Return (true ));
4604+ EXPECT_CALL (client_callbacks_, onGoAway (_));
4605+
4606+ if (http2_implementation_ == Http2Impl::Oghttp2) {
4607+ EXPECT_CALL (request_decoder_, decodeHeaders_ (_, true ));
4608+ EXPECT_TRUE (request_encoder_->encodeHeaders (request_headers, true ).ok ());
4609+ } else {
4610+ // nghttp2 does not raise the headers to the decoder.
4611+ EXPECT_TRUE (request_encoder_->encodeHeaders (request_headers, true ).ok ());
4612+ }
4613+ driveToCompletion ();
4614+
4615+ EXPECT_EQ (1 , server_stats_store_.counter (" http2.goaway_sent" ).value ());
4616+ }
4617+
4618+ TEST_P (Http2CodecImplTest, ServerDispatchLoadShedPointSendGoAwayAndClose) {
4619+ if (Runtime::runtimeFeatureEnabled (" envoy.reloadable_features.http2_fix_goaway_loadshed_point" )) {
4620+ GTEST_SKIP ();
4621+ }
4622+ expect_buffered_data_on_teardown_ = true ;
4623+
4624+ initialize ();
4625+ ASSERT_EQ (0 , server_stats_store_.counter (" http2.goaway_sent" ).value ());
4626+
4627+ TestRequestHeaderMapImpl request_headers;
4628+ HttpTestUtility::addDefaultHeaders (request_headers);
4629+ EXPECT_CALL (server_->server_go_away_and_close_on_dispatch , shouldShedLoad ())
4630+ .WillOnce (Return (true ));
4631+ EXPECT_CALL (client_callbacks_, onGoAway (_));
4632+
4633+ EXPECT_CALL (request_decoder_, decodeHeaders_ (_, _)).Times (0 );
4634+ EXPECT_TRUE (request_encoder_->encodeHeaders (request_headers, true ).ok ());
4635+
4636+ driveToCompletion ();
4637+
4638+ EXPECT_EQ (1 , server_stats_store_.counter (" http2.goaway_sent" ).value ());
4639+ }
4640+
4641+ TEST_P (Http2CodecImplTest, ServerDispatchLoadShedPointsAreOnlyConsultedOncePerDispatch) {
4642+ if (Runtime::runtimeFeatureEnabled (" envoy.reloadable_features.http2_fix_goaway_loadshed_point" )) {
4643+ GTEST_SKIP ();
4644+ }
4645+
4646+ initialize ();
4647+
4648+ int times_shed_load_goaway_invoked = 0 ;
4649+ EXPECT_CALL (server_->server_go_away_on_dispatch , shouldShedLoad ())
4650+ .WillRepeatedly (Invoke ([×_shed_load_goaway_invoked]() {
4651+ ++times_shed_load_goaway_invoked;
4652+ return false ;
4653+ }));
4654+ int times_shed_load_goaway_and_close_invoked = 0 ;
4655+ EXPECT_CALL (server_->server_go_away_and_close_on_dispatch , shouldShedLoad ())
4656+ .WillRepeatedly (Invoke ([×_shed_load_goaway_and_close_invoked]() {
4657+ ++times_shed_load_goaway_and_close_invoked;
4658+ return false ;
4659+ }));
4660+
4661+ // Drive new streams to be created within a single server dispatch.
4662+ const int num_streams_to_create = 20 ;
4663+ TestRequestHeaderMapImpl request_headers;
4664+ HttpTestUtility::addDefaultHeaders (request_headers);
4665+
4666+ std::vector<RequestEncoder*> request_encoders;
4667+ std::vector<ResponseEncoder*> response_encoders;
4668+ request_encoders.reserve (num_streams_to_create);
4669+ response_encoders.reserve (num_streams_to_create);
4670+ for (int i = 0 ; i < num_streams_to_create; ++i) {
4671+ request_encoders.push_back (&client_->newStream (response_decoder_));
4672+ EXPECT_CALL (server_callbacks_, newStream (_, _))
4673+ .WillRepeatedly (Invoke ([&](ResponseEncoder& encoder, bool ) -> RequestDecoder& {
4674+ response_encoders.push_back (&encoder);
4675+ encoder.getStream ().addCallbacks (server_stream_callbacks_);
4676+ return request_decoder_;
4677+ }));
4678+
4679+ EXPECT_TRUE (request_encoders[i]->encodeHeaders (request_headers, true ).ok ());
4680+ }
4681+
4682+ // All the newly created streams are queued in the connection buffer.
4683+ EXPECT_CALL (request_decoder_, decodeHeaders_ (_, true )).Times (num_streams_to_create);
4684+ driveToCompletion ();
4685+ EXPECT_EQ (1 , times_shed_load_goaway_invoked);
4686+ EXPECT_EQ (1 , times_shed_load_goaway_and_close_invoked);
4687+ EXPECT_EQ (0 , server_stats_store_.counter (" http2.goaway_sent" ).value ());
4688+ }
4689+
45944690TEST_P (Http2CodecImplTest, CheckHeaderPaddedWhitespaceValidation) {
45954691 // Per https://datatracker.ietf.org/doc/html/rfc9113#section-8.2.1,
45964692 // leading & trailing whitespace characters in headers are not valid, but this is a new
0 commit comments