diff --git a/include/envoy/buffer/buffer.h b/include/envoy/buffer/buffer.h index 6c6463cb3ff4f..7aee43ab030f3 100644 --- a/include/envoy/buffer/buffer.h +++ b/include/envoy/buffer/buffer.h @@ -371,10 +371,13 @@ class WatermarkFactory { * low watermark. * @param above_high_watermark supplies a function to call if the buffer goes over a configured * high watermark. + * @param above_overflow_watermark supplies a function to call if the buffer goes over a + * configured "overflow" watermark. * @return a newly created InstancePtr. */ virtual InstancePtr create(std::function below_low_watermark, - std::function above_high_watermark) PURE; + std::function above_high_watermark, + std::function above_overflow_watermark) PURE; }; using WatermarkFactoryPtr = std::unique_ptr; diff --git a/include/envoy/http/filter.h b/include/envoy/http/filter.h index 53a10d8ebd455..bb785954f649b 100644 --- a/include/envoy/http/filter.h +++ b/include/envoy/http/filter.h @@ -377,7 +377,7 @@ class StreamDecoderFilterCallbacks : public virtual StreamFilterCallbacks { virtual void encodeMetadata(MetadataMapPtr&& metadata_map) PURE; /** - * Called when the buffer for a decoder filter or any buffers the filter sends data to go over + * Called when the buffer for a decoder filter, or any buffers the filter sends data to, go over * their high watermark. * * In the case of a filter such as the router filter, which spills into multiple buffers (codec, diff --git a/source/common/buffer/BUILD b/source/common/buffer/BUILD index 0b9acc3732abd..3a16b20469e44 100644 --- a/source/common/buffer/BUILD +++ b/source/common/buffer/BUILD @@ -13,6 +13,7 @@ envoy_cc_library( srcs = ["watermark_buffer.cc"], hdrs = ["watermark_buffer.h"], deps = [ + "//include/envoy/runtime:runtime_interface", "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", ], diff --git a/source/common/buffer/watermark_buffer.cc b/source/common/buffer/watermark_buffer.cc index 4f891d7c80293..2dea0e88b808b 100644 --- a/source/common/buffer/watermark_buffer.cc +++ b/source/common/buffer/watermark_buffer.cc @@ -7,32 +7,32 @@ namespace Buffer { void WatermarkBuffer::add(const void* data, uint64_t size) { OwnedImpl::add(data, size); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::add(absl::string_view data) { OwnedImpl::add(data); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::add(const Instance& data) { OwnedImpl::add(data); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::prepend(absl::string_view data) { OwnedImpl::prepend(data); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::prepend(Instance& data) { OwnedImpl::prepend(data); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::commit(RawSlice* iovecs, uint64_t num_iovecs) { OwnedImpl::commit(iovecs, num_iovecs); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::drain(uint64_t size) { @@ -42,23 +42,23 @@ void WatermarkBuffer::drain(uint64_t size) { void WatermarkBuffer::move(Instance& rhs) { OwnedImpl::move(rhs); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } void WatermarkBuffer::move(Instance& rhs, uint64_t length) { OwnedImpl::move(rhs, length); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); } Api::IoCallUint64Result WatermarkBuffer::read(Network::IoHandle& io_handle, uint64_t max_length) { Api::IoCallUint64Result result = OwnedImpl::read(io_handle, max_length); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); return result; } uint64_t WatermarkBuffer::reserve(uint64_t length, RawSlice* iovecs, uint64_t num_iovecs) { uint64_t bytes_reserved = OwnedImpl::reserve(length, iovecs, num_iovecs); - checkHighWatermark(); + checkHighAndOverflowWatermarks(); return bytes_reserved; } @@ -72,12 +72,16 @@ void WatermarkBuffer::setWatermarks(uint32_t low_watermark, uint32_t high_waterm ASSERT(low_watermark < high_watermark || (high_watermark == 0 && low_watermark == 0)); low_watermark_ = low_watermark; high_watermark_ = high_watermark; - checkHighWatermark(); + overflow_watermark_ = high_watermark * overflow_multiplier_; + // TODO(adip): What should be done if there's an overflow (overflow_watermark_ < + // overflow_watermark_)? should this be a release_assert? + ASSERT((high_watermark <= overflow_watermark_) || (overflow_multiplier_ == 0)); + checkHighAndOverflowWatermarks(); checkLowWatermark(); } void WatermarkBuffer::checkLowWatermark() { - if (!above_high_watermark_called_ || + if (above_overflow_watermark_called_ || !above_high_watermark_called_ || (high_watermark_ != 0 && OwnedImpl::length() > low_watermark_)) { return; } @@ -86,14 +90,19 @@ void WatermarkBuffer::checkLowWatermark() { below_low_watermark_(); } -void WatermarkBuffer::checkHighWatermark() { - if (above_high_watermark_called_ || high_watermark_ == 0 || - OwnedImpl::length() <= high_watermark_) { +void WatermarkBuffer::checkHighAndOverflowWatermarks() { + if (!above_overflow_watermark_called_ && overflow_watermark_ != 0 && + OwnedImpl::length() > overflow_watermark_) { + above_overflow_watermark_called_ = true; + above_overflow_watermark_(); return; } - above_high_watermark_called_ = true; - above_high_watermark_(); + if (!above_high_watermark_called_ && high_watermark_ != 0 && + OwnedImpl::length() > high_watermark_) { + above_high_watermark_called_ = true; + above_high_watermark_(); + } } } // namespace Buffer diff --git a/source/common/buffer/watermark_buffer.h b/source/common/buffer/watermark_buffer.h index 827d1a51bccfd..9e192afa63311 100644 --- a/source/common/buffer/watermark_buffer.h +++ b/source/common/buffer/watermark_buffer.h @@ -3,6 +3,8 @@ #include #include +#include "envoy/runtime/runtime.h" + #include "common/buffer/buffer_impl.h" namespace Envoy { @@ -16,8 +18,12 @@ namespace Buffer { class WatermarkBuffer : public OwnedImpl { public: WatermarkBuffer(std::function below_low_watermark, - std::function above_high_watermark) - : below_low_watermark_(below_low_watermark), above_high_watermark_(above_high_watermark) {} + std::function above_high_watermark, + std::function above_overflow_watermark) + : below_low_watermark_(below_low_watermark), above_high_watermark_(above_high_watermark), + above_overflow_watermark_(above_overflow_watermark), + overflow_multiplier_(Runtime::LoaderSingleton::get().threadsafeSnapshot()->getInteger( + "buffer.overflow.high_watermark_multiplier", 2)) {} // Override all functions from Instance which can result in changing the size // of the underlying buffer. @@ -40,20 +46,25 @@ class WatermarkBuffer : public OwnedImpl { uint32_t highWatermark() const { return high_watermark_; } private: - void checkHighWatermark(); + void checkHighAndOverflowWatermarks(); void checkLowWatermark(); std::function below_low_watermark_; std::function above_high_watermark_; + std::function above_overflow_watermark_; + const uint32_t overflow_multiplier_{0}; // Used for enforcing buffer limits (off by default). If these are set to non-zero by a call to // setWatermarks() the watermark callbacks will be called as described above. + uint32_t overflow_watermark_{0}; uint32_t high_watermark_{0}; uint32_t low_watermark_{0}; - // Tracks the latest state of watermark callbacks. - // True between the time above_high_watermark_ has been called until above_high_watermark_ has - // been called. + // Set to true after above_high_watermark_ has been called, and reset to false after + // below_low_watermark_ has been called. bool above_high_watermark_called_{false}; + // Set to true after above_overflow_watermark_ has been called. Never reset, because we expect + // the associated connection and/or stream will be closed immediately in response to an overflow. + bool above_overflow_watermark_called_{false}; }; using WatermarkBufferPtr = std::unique_ptr; @@ -62,8 +73,10 @@ class WatermarkBufferFactory : public WatermarkFactory { public: // Buffer::WatermarkFactory InstancePtr create(std::function below_low_watermark, - std::function above_high_watermark) override { - return InstancePtr{new WatermarkBuffer(below_low_watermark, above_high_watermark)}; + std::function above_high_watermark, + std::function above_overflow_watermark) override { + return InstancePtr{ + new WatermarkBuffer(below_low_watermark, above_high_watermark, above_overflow_watermark)}; } }; diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 946d61a779b7b..d41d500650d78 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -2219,9 +2219,9 @@ void ConnectionManagerImpl::ActiveStreamFilterBase::clearRouteCache() { } Buffer::WatermarkBufferPtr ConnectionManagerImpl::ActiveStreamDecoderFilter::createBuffer() { - auto buffer = - std::make_unique([this]() -> void { this->requestDataDrained(); }, - [this]() -> void { this->requestDataTooLarge(); }); + auto buffer = std::make_unique( + [this]() -> void { this->requestDataDrained(); }, + [this]() -> void { this->requestDataTooLarge(); }, [this]() -> void { this->resetStream(); }); buffer->setWatermarks(parent_.buffer_limit_); return buffer; } @@ -2388,8 +2388,10 @@ ConnectionManagerImpl::ActiveStreamDecoderFilter::routeConfig() { } Buffer::WatermarkBufferPtr ConnectionManagerImpl::ActiveStreamEncoderFilter::createBuffer() { - auto buffer = new Buffer::WatermarkBuffer([this]() -> void { this->responseDataDrained(); }, - [this]() -> void { this->responseDataTooLarge(); }); + auto buffer = new Buffer::WatermarkBuffer( + [this]() -> void { this->responseDataDrained(); }, + [this]() -> void { this->responseDataExceedsHighWatermark(); }, + [this]() -> void { this->responseDataExceedsOverflowWatermark(); }); buffer->setWatermarks(parent_.buffer_limit_); return Buffer::WatermarkBufferPtr{buffer}; } @@ -2441,43 +2443,49 @@ void ConnectionManagerImpl::ActiveStreamEncoderFilter:: void ConnectionManagerImpl::ActiveStreamEncoderFilter::continueEncoding() { commonContinue(); } -void ConnectionManagerImpl::ActiveStreamEncoderFilter::responseDataTooLarge() { +void ConnectionManagerImpl::ActiveStreamEncoderFilter::responseDataExceedsHighWatermark() { if (parent_.state_.encoder_filters_streaming_) { + // If we are streaming the response, there's still an opportunity to drain the response buffer. onEncoderFilterAboveWriteBufferHighWatermark(); } else { - parent_.connection_manager_.stats_.named_.rs_too_large_.inc(); - - // If headers have not been sent to the user, send a 500. - if (!headers_continued_) { - // Make sure we won't end up with nested watermark calls from the body buffer. - parent_.state_.encoder_filters_streaming_ = true; - allowIteration(); - - parent_.stream_info_.setResponseCodeDetails( - StreamInfo::ResponseCodeDetails::get().RequestHeadersTooLarge); - // This does not call the standard sendLocalReply because if there is already response data - // we do not want to pass a second set of response headers through the filter chain. - // Instead, call the encodeHeadersInternal / encodeDataInternal helpers - // directly, which maximizes shared code with the normal response path. - Http::Utility::sendLocalReply( - Grpc::Common::hasGrpcContentType(*parent_.request_headers_), - [&](ResponseHeaderMapPtr&& response_headers, bool end_stream) -> void { - parent_.response_headers_ = std::move(response_headers); - parent_.encodeHeadersInternal(*parent_.response_headers_, end_stream); - }, - [&](Buffer::Instance& data, bool end_stream) -> void { - parent_.encodeDataInternal(data, end_stream); - }, - parent_.state_.destroyed_, Http::Code::InternalServerError, - CodeUtility::toString(Http::Code::InternalServerError), absl::nullopt, - parent_.state_.is_head_request_); - parent_.maybeEndEncode(parent_.state_.local_complete_); - } else { - ENVOY_STREAM_LOG( - debug, "Resetting stream. Response data too large and headers have already been sent", - *this); - resetStream(); - } + // Otherwise, treat it as an overflow: send a 500 if possible and reset the stream. + responseDataExceedsOverflowWatermark(); + } +} + +void ConnectionManagerImpl::ActiveStreamEncoderFilter::responseDataExceedsOverflowWatermark() { + parent_.connection_manager_.stats_.named_.rs_too_large_.inc(); + + // If headers have not been sent to the user, send a 500. + if (!headers_continued_) { + // Make sure we won't end up with nested watermark calls from the body buffer. + parent_.state_.encoder_filters_streaming_ = true; + allowIteration(); + + parent_.stream_info_.setResponseCodeDetails( + StreamInfo::ResponseCodeDetails::get().RequestHeadersTooLarge); + // This does not call the standard sendLocalReply because if there is already response data + // we do not want to pass a second set of response headers through the filter chain. + // Instead, call the encodeHeadersInternal / encodeDataInternal helpers + // directly, which maximizes shared code with the normal response path. + Http::Utility::sendLocalReply( + Grpc::Common::hasGrpcContentType(*parent_.request_headers_), + [&](ResponseHeaderMapPtr&& response_headers, bool end_stream) -> void { + parent_.response_headers_ = std::move(response_headers); + parent_.encodeHeadersInternal(*parent_.response_headers_, end_stream); + }, + [&](Buffer::Instance& data, bool end_stream) -> void { + parent_.encodeDataInternal(data, end_stream); + }, + parent_.state_.destroyed_, Http::Code::InternalServerError, + CodeUtility::toString(Http::Code::InternalServerError), absl::nullopt, + parent_.state_.is_head_request_); + parent_.maybeEndEncode(parent_.state_.local_complete_); + } else { + ENVOY_STREAM_LOG(debug, + "Resetting stream. Response data too large and headers have already been sent", + *this); + resetStream(); } } diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h index 7b17dd46625ac..2dec48886f6ae 100644 --- a/source/common/http/conn_manager_impl.h +++ b/source/common/http/conn_manager_impl.h @@ -394,7 +394,8 @@ class ConnectionManagerImpl : Logger::Loggable, callback(*parent_.buffered_response_data_.get()); } - void responseDataTooLarge(); + void responseDataExceedsHighWatermark(); + void responseDataExceedsOverflowWatermark(); void responseDataDrained(); StreamEncoderFilterSharedPtr handle_; diff --git a/source/common/http/http1/codec_impl.cc b/source/common/http/http1/codec_impl.cc index 309cdab5e70fb..c10d5666212f3 100644 --- a/source/common/http/http1/codec_impl.cc +++ b/source/common/http/http1/codec_impl.cc @@ -295,6 +295,11 @@ void ConnectionImpl::copyToBuffer(const char* data, uint64_t length) { output_buffer_.add(data, length); } +void ConnectionImpl::onAboveOverflowWatermark() { + // TODO(mergeconflict): log and increment counter + connection_.close(Network::ConnectionCloseType::NoFlush); +} + void StreamEncoderImpl::resetStream(StreamResetReason reason) { connection_.onResetStreamBase(reason); } @@ -412,7 +417,8 @@ ConnectionImpl::ConnectionImpl(Network::Connection& connection, Stats::Scope& st "envoy.reloadable_features.connection_header_sanitization")), enable_trailers_(enable_trailers), output_buffer_([&]() -> void { this->onBelowLowWatermark(); }, - [&]() -> void { this->onAboveHighWatermark(); }), + [&]() -> void { this->onAboveHighWatermark(); }, + [&]() -> void { this->onAboveOverflowWatermark(); }), max_headers_kb_(max_headers_kb), max_headers_count_(max_headers_count) { output_buffer_.setWatermarks(connection.bufferLimit()); http_parser_init(&parser_, type); diff --git a/source/common/http/http1/codec_impl.h b/source/common/http/http1/codec_impl.h index c613a8221ca10..d3c1ae018db0b 100644 --- a/source/common/http/http1/codec_impl.h +++ b/source/common/http/http1/codec_impl.h @@ -303,6 +303,11 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable(headers_or_trailers_))); } +void ConnectionImpl::StreamImpl::pendingSendBufferOverflowWatermark() { + ENVOY_CONN_LOG(warn, "send buffer overflow ", parent_.connection_); + // TODO(mergeconflict): increment a counter + resetStream(StreamResetReason::Overflow); +} + void ConnectionImpl::StreamImpl::pendingSendBufferHighWatermark() { ENVOY_CONN_LOG(debug, "send buffer over limit ", parent_.connection_); ASSERT(!pending_send_buffer_high_watermark_called_); diff --git a/source/common/http/http2/codec_impl.h b/source/common/http/http2/codec_impl.h index 686250e5e1d35..2351f47f17615 100644 --- a/source/common/http/http2/codec_impl.h +++ b/source/common/http/http2/codec_impl.h @@ -195,12 +195,16 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable void { this->pendingRecvBufferLowWatermark(); }, - [this]() -> void { this->pendingRecvBufferHighWatermark(); }}; + [this]() -> void { this->pendingRecvBufferHighWatermark(); }, + [this]() -> void { this->pendingRecvBufferOverflowWatermark(); }}; Buffer::WatermarkBuffer pending_send_data_{ [this]() -> void { this->pendingSendBufferLowWatermark(); }, - [this]() -> void { this->pendingSendBufferHighWatermark(); }}; + [this]() -> void { this->pendingSendBufferHighWatermark(); }, + [this]() -> void { this->pendingSendBufferOverflowWatermark(); }}; HeaderMapPtr pending_trailers_to_encode_; std::unique_ptr metadata_decoder_; std::unique_ptr metadata_encoder_; diff --git a/source/common/network/connection_impl.cc b/source/common/network/connection_impl.cc index a79f7506ee847..cc0aa65dcd38a 100644 --- a/source/common/network/connection_impl.cc +++ b/source/common/network/connection_impl.cc @@ -47,9 +47,10 @@ ConnectionImpl::ConnectionImpl(Event::Dispatcher& dispatcher, ConnectionSocketPt : ConnectionImplBase(dispatcher, next_global_id_++), transport_socket_(std::move(transport_socket)), socket_(std::move(socket)), stream_info_(dispatcher.timeSource()), filter_manager_(*this), - write_buffer_( - dispatcher.getWatermarkFactory().create([this]() -> void { this->onLowWatermark(); }, - [this]() -> void { this->onHighWatermark(); })), + write_buffer_(dispatcher.getWatermarkFactory().create( + [this]() -> void { this->onLowWatermark(); }, + [this]() -> void { this->onHighWatermark(); }, + [this]() -> void { this->onOverflowWatermark(); })), read_enabled_(true), above_high_watermark_(false), detect_early_close_(true), enable_half_close_(false), read_end_stream_raised_(false), read_end_stream_(false), write_end_stream_(false), current_write_end_stream_(false), dispatch_buffered_data_(false) { @@ -434,12 +435,17 @@ void ConnectionImpl::write(Buffer::Instance& data, bool end_stream, bool through // might need to change if we ever copy here. write_buffer_->move(data); - // Activating a write event before the socket is connected has the side-effect of tricking - // doWriteReady into thinking the socket is connected. On macOS, the underlying write may fail - // with a connection error if a call to write(2) occurs before the connection is completed. - if (!connecting_) { - ASSERT(file_event_ != nullptr, "ConnectionImpl file event was unexpectedly reset"); - file_event_->activate(Event::FileReadyType::Write); + // If the writing to the buffer caused an overflow-watermark breach, the connection should be + // closed + // TODO(adip): what should be done if the state is Closing + if (state() != State::Closed) { + // Activating a write event before the socket is connected has the side-effect of tricking + // doWriteReady into thinking the socket is connected. On macOS, the underlying write may fail + // with a connection error if a call to write(2) occurs before the connection is completed. + if (!connecting_) { + ASSERT(file_event_ != nullptr, "ConnectionImpl file event was unexpectedly reset"); + file_event_->activate(Event::FileReadyType::Write); + } } } } @@ -488,6 +494,12 @@ void ConnectionImpl::onHighWatermark() { } } +void ConnectionImpl::onOverflowWatermark() { + ENVOY_CONN_LOG(debug, "onAboveWriteBufferOverflowWatermark", *this); + // TODO(mergeconflict): increment a counter + close(ConnectionCloseType::NoFlush); +} + void ConnectionImpl::onFileEvent(uint32_t events) { ENVOY_CONN_LOG(trace, "socket event: {}", *this, events); diff --git a/source/common/network/connection_impl.h b/source/common/network/connection_impl.h index 9042087853e98..d4e94fc95e82a 100644 --- a/source/common/network/connection_impl.h +++ b/source/common/network/connection_impl.h @@ -125,6 +125,7 @@ class ConnectionImpl : public ConnectionImplBase, public TransportSocketCallback void onLowWatermark(); void onHighWatermark(); + void onOverflowWatermark(); TransportSocketPtr transport_socket_; ConnectionSocketPtr socket_; diff --git a/source/common/router/upstream_request.cc b/source/common/router/upstream_request.cc index 400639a1e88e8..1b3f20b464fbd 100644 --- a/source/common/router/upstream_request.cc +++ b/source/common/router/upstream_request.cc @@ -180,7 +180,8 @@ void UpstreamRequest::encodeData(Buffer::Instance& data, bool end_stream) { if (!buffered_request_body_) { buffered_request_body_ = std::make_unique( [this]() -> void { this->enableDataFromDownstreamForFlowControl(); }, - [this]() -> void { this->disableDataFromDownstreamForFlowControl(); }); + [this]() -> void { this->disableDataFromDownstreamForFlowControl(); }, + [this]() -> void { this->resetStream(); }); buffered_request_body_->setWatermarks(parent_.callbacks_->decoderBufferLimit()); } diff --git a/source/extensions/filters/http/fault/fault_filter.cc b/source/extensions/filters/http/fault/fault_filter.cc index f396f5a12ff68..528b4b93d2459 100644 --- a/source/extensions/filters/http/fault/fault_filter.cc +++ b/source/extensions/filters/http/fault/fault_filter.cc @@ -197,6 +197,7 @@ void FaultFilter::maybeSetupResponseRateLimit(const Http::RequestHeaderMap& requ response_limiter_ = std::make_unique( rate_kbps.value(), encoder_callbacks_->encoderBufferLimit(), + [this] { encoder_callbacks_->resetStream(); }, [this] { encoder_callbacks_->onEncoderFilterAboveWriteBufferHighWatermark(); }, [this] { encoder_callbacks_->onEncoderFilterBelowWriteBufferLowWatermark(); }, [this](Buffer::Instance& data, bool end_stream) { @@ -441,6 +442,7 @@ Http::FilterTrailersStatus FaultFilter::encodeTrailers(Http::ResponseTrailerMap& } StreamRateLimiter::StreamRateLimiter(uint64_t max_kbps, uint64_t max_buffered_data, + std::function overflow_cb, std::function pause_data_cb, std::function resume_data_cb, std::function write_data_cb, @@ -454,7 +456,7 @@ StreamRateLimiter::StreamRateLimiter(uint64_t max_kbps, uint64_t max_buffered_da // ~63ms intervals. token_bucket_(SecondDivisor, time_source, SecondDivisor), token_timer_(dispatcher.createTimer([this] { onTokenTimer(); })), - buffer_(resume_data_cb, pause_data_cb) { + buffer_(resume_data_cb, pause_data_cb, overflow_cb) { ASSERT(bytes_per_time_slice_ > 0); ASSERT(max_buffered_data > 0); buffer_.setWatermarks(max_buffered_data); diff --git a/source/extensions/filters/http/fault/fault_filter.h b/source/extensions/filters/http/fault/fault_filter.h index 9572909a882f6..84342c2d1f367 100644 --- a/source/extensions/filters/http/fault/fault_filter.h +++ b/source/extensions/filters/http/fault/fault_filter.h @@ -150,7 +150,10 @@ class StreamRateLimiter : Logger::Loggable { /** * @param max_kbps maximum rate in KiB/s. * @param max_buffered_data maximum data to buffer before invoking the pause callback. - * @param pause_data_cb callback invoked when the limiter has buffered too much data. + * @param overflow_cb callback invoked when the limiter has buffered too much data despite + * previous backpressure. + * @param pause_data_cb callback invoked when the limiter has buffered enough data to necessitate + * backpressure. * @param resume_data_cb callback invoked when the limiter has gone under the buffer limit. * @param write_data_cb callback invoked to write data to the stream. * @param continue_cb callback invoked to continue the stream. This is only used to continue @@ -160,7 +163,8 @@ class StreamRateLimiter : Logger::Loggable { * @param scope the stream's scope */ StreamRateLimiter(uint64_t max_kbps, uint64_t max_buffered_data, - std::function pause_data_cb, std::function resume_data_cb, + std::function overflow_cb, std::function pause_data_cb, + std::function resume_data_cb, std::function write_data_cb, std::function continue_cb, TimeSource& time_source, Event::Dispatcher& dispatcher, const ScopeTrackedObject& scope); diff --git a/test/common/buffer/BUILD b/test/common/buffer/BUILD index 33c29e528b873..67c658a475190 100644 --- a/test/common/buffer/BUILD +++ b/test/common/buffer/BUILD @@ -78,6 +78,7 @@ envoy_cc_test( "//source/common/buffer:buffer_lib", "//source/common/buffer:watermark_buffer_lib", "//source/common/network:address_lib", + "//test/mocks/runtime:runtime_mocks", ], ) diff --git a/test/common/buffer/watermark_buffer_test.cc b/test/common/buffer/watermark_buffer_test.cc index be3cfedaf6719..64478234e1132 100644 --- a/test/common/buffer/watermark_buffer_test.cc +++ b/test/common/buffer/watermark_buffer_test.cc @@ -5,9 +5,13 @@ #include "common/network/io_socket_handle_impl.h" #include "test/common/buffer/utility.h" +#include "test/mocks/runtime/mocks.h" #include "gtest/gtest.h" +using ::testing::_; +using ::testing::Return; + namespace Envoy { namespace Buffer { namespace { @@ -18,10 +22,13 @@ class WatermarkBufferTest : public testing::Test { public: WatermarkBufferTest() { buffer_.setWatermarks(5, 10); } + Runtime::ScopedMockLoaderSingleton runtime_; Buffer::WatermarkBuffer buffer_{[&]() -> void { ++times_low_watermark_called_; }, - [&]() -> void { ++times_high_watermark_called_; }}; + [&]() -> void { ++times_high_watermark_called_; }, + [&]() -> void { ++times_overflow_watermark_called_; }}; uint32_t times_low_watermark_called_{0}; uint32_t times_high_watermark_called_{0}; + uint32_t times_overflow_watermark_called_{0}; }; TEST_F(WatermarkBufferTest, TestWatermark) { ASSERT_EQ(10, buffer_.highWatermark()); } @@ -45,6 +52,13 @@ TEST_F(WatermarkBufferTest, AddChar) { buffer_.add("a", 1); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(11, buffer_.length()); + + buffer_.add("bcdefghij"); + EXPECT_EQ(0, times_overflow_watermark_called_); + EXPECT_EQ(20, buffer_.length()); + buffer_.add("k", 1); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(21, buffer_.length()); } TEST_F(WatermarkBufferTest, AddString) { @@ -53,6 +67,10 @@ TEST_F(WatermarkBufferTest, AddString) { buffer_.add(std::string("a")); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(11, buffer_.length()); + + buffer_.add(std::string(TEN_BYTES)); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(21, buffer_.length()); } TEST_F(WatermarkBufferTest, AddBuffer) { @@ -63,6 +81,11 @@ TEST_F(WatermarkBufferTest, AddBuffer) { buffer_.add(second); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(11, buffer_.length()); + + OwnedImpl third(TEN_BYTES); + buffer_.add(third); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(21, buffer_.length()); } TEST_F(WatermarkBufferTest, Prepend) { @@ -73,6 +96,9 @@ TEST_F(WatermarkBufferTest, Prepend) { buffer_.prepend(prefix); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(suffix.size() + prefix.size(), buffer_.length()); + + buffer_.prepend(TEN_BYTES); + EXPECT_EQ(1, times_overflow_watermark_called_); } TEST_F(WatermarkBufferTest, PrependToEmptyBuffer) { @@ -97,7 +123,8 @@ TEST_F(WatermarkBufferTest, PrependBuffer) { uint32_t prefix_buffer_low_watermark_hits{0}; uint32_t prefix_buffer_high_watermark_hits{0}; WatermarkBuffer prefixBuffer{[&]() -> void { ++prefix_buffer_low_watermark_hits; }, - [&]() -> void { ++prefix_buffer_high_watermark_hits; }}; + [&]() -> void { ++prefix_buffer_high_watermark_hits; }, + [&]() -> void { /* not interesting in this case */ }}; prefixBuffer.setWatermarks(5, 10); prefixBuffer.add(prefix); prefixBuffer.add(suffix); @@ -115,13 +142,22 @@ TEST_F(WatermarkBufferTest, PrependBuffer) { TEST_F(WatermarkBufferTest, Commit) { buffer_.add(TEN_BYTES, 10); EXPECT_EQ(0, times_high_watermark_called_); - RawSlice out; - buffer_.reserve(10, &out, 1); - memcpy(out.mem_, &TEN_BYTES[0], 10); - out.len_ = 10; - buffer_.commit(&out, 1); + + const auto commit_ten_bytes = [this] { + RawSlice out; + buffer_.reserve(10, &out, 1); + memcpy(out.mem_, &TEN_BYTES[0], 10); + out.len_ = 10; + buffer_.commit(&out, 1); + }; + + commit_ten_bytes(); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(20, buffer_.length()); + + commit_ten_bytes(); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(30, buffer_.length()); } TEST_F(WatermarkBufferTest, Drain) { @@ -145,6 +181,14 @@ TEST_F(WatermarkBufferTest, Drain) { // Going back above should trigger the high again buffer_.add(TEN_BYTES, 10); EXPECT_EQ(2, times_high_watermark_called_); + + // Draining doesn't reset the overflow bit, so overflow should only be called once. + buffer_.add(TEN_BYTES, 10); + EXPECT_EQ(1, times_overflow_watermark_called_); + buffer_.drain(20); + buffer_.add(TEN_BYTES, 10); + buffer_.add(TEN_BYTES, 10); + EXPECT_EQ(1, times_overflow_watermark_called_); } // Verify that low watermark callback is called on drain in the case where the @@ -182,6 +226,11 @@ TEST_F(WatermarkBufferTest, MoveFullBuffer) { buffer_.move(data); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(11, buffer_.length()); + + OwnedImpl overflow_data(TEN_BYTES); + buffer_.move(overflow_data); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(21, buffer_.length()); } TEST_F(WatermarkBufferTest, MoveOneByte) { @@ -195,6 +244,12 @@ TEST_F(WatermarkBufferTest, MoveOneByte) { buffer_.move(data, 1); EXPECT_EQ(1, times_high_watermark_called_); EXPECT_EQ(11, buffer_.length()); + + buffer_.add(TEN_BYTES, 9); + OwnedImpl overflow_data("ab"); + buffer_.move(overflow_data, 1); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(21, buffer_.length()); } TEST_F(WatermarkBufferTest, WatermarkFdFunctions) { @@ -233,10 +288,13 @@ TEST_F(WatermarkBufferTest, WatermarkFdFunctions) { TEST_F(WatermarkBufferTest, MoveWatermarks) { buffer_.add(TEN_BYTES, 9); EXPECT_EQ(0, times_high_watermark_called_); + EXPECT_EQ(0, times_overflow_watermark_called_); buffer_.setWatermarks(1, 9); EXPECT_EQ(0, times_high_watermark_called_); + EXPECT_EQ(0, times_overflow_watermark_called_); buffer_.setWatermarks(1, 8); EXPECT_EQ(1, times_high_watermark_called_); + EXPECT_EQ(0, times_overflow_watermark_called_); buffer_.setWatermarks(8, 20); EXPECT_EQ(0, times_low_watermark_called_); @@ -248,20 +306,26 @@ TEST_F(WatermarkBufferTest, MoveWatermarks) { EXPECT_EQ(1, times_low_watermark_called_); EXPECT_EQ(1, times_high_watermark_called_); - buffer_.setWatermarks(2); + buffer_.setWatermarks(5); EXPECT_EQ(2, times_high_watermark_called_); EXPECT_EQ(1, times_low_watermark_called_); buffer_.setWatermarks(0); + EXPECT_EQ(0, times_overflow_watermark_called_); EXPECT_EQ(2, times_high_watermark_called_); EXPECT_EQ(2, times_low_watermark_called_); buffer_.setWatermarks(1); - EXPECT_EQ(3, times_high_watermark_called_); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(2, times_high_watermark_called_); EXPECT_EQ(2, times_low_watermark_called_); - // Fully drain the buffer. - buffer_.drain(9); - EXPECT_EQ(3, times_low_watermark_called_); - EXPECT_EQ(0, buffer_.length()); + buffer_.setWatermarks(4); + EXPECT_EQ(1, times_overflow_watermark_called_); + EXPECT_EQ(3, times_high_watermark_called_); + + // TODO(adip): should low_watermark be called after overflow? + // Fully drain the buffer (w/o triggering low_watermark). + EXPECT_EQ(2, times_low_watermark_called_); + // EXPECT_EQ(0, buffer_.length()); } TEST_F(WatermarkBufferTest, GetRawSlices) { @@ -293,10 +357,12 @@ TEST_F(WatermarkBufferTest, StartsWith) { } TEST_F(WatermarkBufferTest, MoveBackWithWatermarks) { + int overflow_watermark_buffer1 = 0; int high_watermark_buffer1 = 0; int low_watermark_buffer1 = 0; Buffer::WatermarkBuffer buffer1{[&]() -> void { ++low_watermark_buffer1; }, - [&]() -> void { ++high_watermark_buffer1; }}; + [&]() -> void { ++high_watermark_buffer1; }, + [&]() -> void { ++overflow_watermark_buffer1; }}; buffer1.setWatermarks(5, 10); // Stick 20 bytes in buffer_ and expect the high watermark is hit. @@ -318,6 +384,14 @@ TEST_F(WatermarkBufferTest, MoveBackWithWatermarks) { buffer_.move(buffer1); EXPECT_EQ(2, times_high_watermark_called_); EXPECT_EQ(1, low_watermark_buffer1); + + // Stick 10 more bytes in the original buffer, which should trigger the overflow watermark. + buffer_.add(TEN_BYTES, 10); + EXPECT_EQ(1, times_overflow_watermark_called_); + + // ... And finally move everything over to the new buffer, which should overflow there as well. + buffer1.move(buffer_, 30); + EXPECT_EQ(1, overflow_watermark_buffer1); } } // namespace diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index e276fc4d44cd4..c7cc4f6ec5ca0 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -290,8 +290,8 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { EXPECT_CALL(cm_, httpConnPoolForCluster(_, _, _, _)) .WillRepeatedly(Return(http_conn_pool_.get())); http_async_client_ = std::make_unique( - cluster_info_ptr_, *stats_store_, *dispatcher_, local_info_, cm_, runtime_, random_, - std::move(shadow_writer_ptr_), http_context_); + cluster_info_ptr_, *stats_store_, *dispatcher_, local_info_, cm_, runtime_.loader(), + random_, std::move(shadow_writer_ptr_), http_context_); EXPECT_CALL(cm_, httpAsyncClientForCluster(fake_cluster_name_)) .WillRepeatedly(ReturnRef(*http_async_client_)); EXPECT_CALL(cm_, get(Eq(fake_cluster_name_))).WillRepeatedly(Return(&thread_local_cluster_)); @@ -444,7 +444,7 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { Upstream::ClusterInfoConstSharedPtr cluster_info_ptr_{mock_cluster_info_}; Upstream::MockThreadLocalCluster thread_local_cluster_; NiceMock local_info_; - Runtime::MockLoader runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; Extensions::TransportSockets::Tls::ContextManagerImpl context_manager_{test_time_.timeSystem()}; NiceMock random_; Http::AsyncClientPtr http_async_client_; diff --git a/test/common/http/BUILD b/test/common/http/BUILD index 593d22653e689..6d2e2df73fa9d 100644 --- a/test/common/http/BUILD +++ b/test/common/http/BUILD @@ -53,6 +53,7 @@ envoy_cc_test( "//test/mocks/event:event_mocks", "//test/mocks/http:http_mocks", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/ssl:ssl_mocks", "//test/mocks/upstream:upstream_mocks", "//test/test_common:environment_lib", @@ -80,6 +81,8 @@ envoy_cc_fuzz_test( "//test/fuzz:utility_lib", "//test/mocks/http:http_mocks", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", + "//test/test_common:test_runtime_lib", ], ) @@ -165,6 +168,7 @@ envoy_cc_fuzz_test( "//test/mocks/tracing:tracing_mocks", "//test/mocks/upstream:upstream_mocks", "//test/test_common:simulated_time_system_lib", + "//test/test_common:test_runtime_lib", "@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto", ], ) diff --git a/test/common/http/codec_client_test.cc b/test/common/http/codec_client_test.cc index f0e7b5fc7c1a5..4f8a9f77c08ad 100644 --- a/test/common/http/codec_client_test.cc +++ b/test/common/http/codec_client_test.cc @@ -14,6 +14,7 @@ #include "test/mocks/event/mocks.h" #include "test/mocks/http/mocks.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/ssl/mocks.h" #include "test/mocks/upstream/mocks.h" #include "test/test_common/environment.h" @@ -365,6 +366,7 @@ class CodecNetworkTest : public testing::TestWithParam client_callbacks_; NiceMock inner_encoder_; NiceMock outer_decoder_; + Runtime::ScopedMockLoaderSingleton runtime_; }; // Send a block of data from upstream, and ensure it is received by the codec. diff --git a/test/common/http/codec_impl_fuzz_test.cc b/test/common/http/codec_impl_fuzz_test.cc index 260c886058eca..fc126fd0ff384 100644 --- a/test/common/http/codec_impl_fuzz_test.cc +++ b/test/common/http/codec_impl_fuzz_test.cc @@ -22,6 +22,8 @@ #include "test/fuzz/utility.h" #include "test/mocks/http/mocks.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" +#include "test/test_common/test_runtime.h" #include "gmock/gmock.h" @@ -389,6 +391,11 @@ void codecFuzz(const test::common::http::CodecImplFuzzTestCase& input, HttpVersi ClientConnectionPtr client; ServerConnectionPtr server; const bool http2 = http_version == HttpVersion::Http2; + TestScopedRuntime runtime; + + // TODO(adip): add tests to the overflow high watermark functionality + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"buffer.overflow.high_watermark_multiplier", "0"}}); if (http2) { client = std::make_unique( diff --git a/test/common/http/conn_manager_impl_fuzz_test.cc b/test/common/http/conn_manager_impl_fuzz_test.cc index 6e68da183de51..1a9a557cee816 100644 --- a/test/common/http/conn_manager_impl_fuzz_test.cc +++ b/test/common/http/conn_manager_impl_fuzz_test.cc @@ -37,6 +37,7 @@ #include "test/mocks/tracing/mocks.h" #include "test/mocks/upstream/mocks.h" #include "test/test_common/simulated_time_system.h" +#include "test/test_common/test_runtime.h" #include "gmock/gmock.h" @@ -434,12 +435,12 @@ DEFINE_PROTO_FUZZER(const test::common::http::ConnManagerImplTestCase& input) { NiceMock random; Stats::SymbolTablePtr symbol_table(Stats::SymbolTableCreator::makeSymbolTable()); Http::ContextImpl http_context(*symbol_table); - NiceMock runtime; NiceMock local_info; NiceMock cluster_manager; NiceMock filter_callbacks; auto ssl_connection = std::make_shared(); bool connection_alive = true; + TestScopedRuntime runtime; ON_CALL(filter_callbacks.connection_, ssl()).WillByDefault(Return(ssl_connection)); ON_CALL(Const(filter_callbacks.connection_), ssl()).WillByDefault(Return(ssl_connection)); @@ -450,8 +451,9 @@ DEFINE_PROTO_FUZZER(const test::common::http::ConnManagerImplTestCase& input) { filter_callbacks.connection_.remote_address_ = std::make_shared("0.0.0.0"); - ConnectionManagerImpl conn_manager(config, drain_close, random, http_context, runtime, local_info, - cluster_manager, nullptr, config.time_system_); + ConnectionManagerImpl conn_manager(config, drain_close, random, http_context, + Runtime::LoaderSingleton::get(), local_info, cluster_manager, + nullptr, config.time_system_); conn_manager.initializeReadFilterCallbacks(filter_callbacks); std::vector streams; diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index 560cdebb9e2e2..a291b5ff7b73e 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -129,8 +129,8 @@ class HttpConnectionManagerImplTest : public testing::Test, public ConnectionMan filter_callbacks_.connection_.remote_address_ = std::make_shared("0.0.0.0"); conn_manager_ = std::make_unique( - *this, drain_close_, random_, http_context_, runtime_, local_info_, cluster_manager_, - &overload_manager_, test_time_.timeSystem()); + *this, drain_close_, random_, http_context_, runtime_.loader(), local_info_, + cluster_manager_, &overload_manager_, test_time_.timeSystem()); conn_manager_->initializeReadFilterCallbacks(filter_callbacks_); if (tracing) { @@ -349,7 +349,7 @@ class HttpConnectionManagerImplTest : public testing::Test, public ConnectionMan NiceMock scoped_route_config_provider_; Stats::IsolatedStoreImpl fake_stats_; Http::ContextImpl http_context_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock log_manager_; std::string access_log_path_; std::list access_logs_; @@ -406,6 +406,20 @@ class HttpConnectionManagerImplTest : public testing::Test, public ConnectionMan std::vector encoder_filters_; }; +// A couple tests below, relating to buffer watermarks, should have the same results whether the +// overflow watermark is enabled or disabled. +class HttpConnectionManagerImplTestP : public HttpConnectionManagerImplTest, + public testing::WithParamInterface { +public: + HttpConnectionManagerImplTestP() { + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(GetParam())); + } +}; +// A value of 0 disables the overflow watermark, and 2 sets the overflow watermark to 2x the +// high watermark. +INSTANTIATE_TEST_SUITE_P(OverflowWatermark, HttpConnectionManagerImplTestP, testing::Values(0, 2)); + TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponse) { setup(false, "envoy-custom-server", false); @@ -918,7 +932,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { // Verify if the activeSpan interface returns reference to the current span. EXPECT_CALL(*span, setTag(Eq("service-cluster"), Eq("scoobydoo"))); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -986,7 +1000,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -1052,7 +1066,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -1116,7 +1130,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(Eq("testOp"))); @@ -1197,7 +1211,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -1279,7 +1293,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -1358,7 +1372,7 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(true)); // Verify that span operation overridden by value supplied in response header. @@ -1417,7 +1431,7 @@ TEST_F(HttpConnectionManagerImplTest, 256}); EXPECT_CALL( - runtime_.snapshot_, + runtime_.snapshot(), featureEnabled("tracing.global_enabled", An(), _)) .WillOnce(Return(false)); std::shared_ptr filter(new NiceMock()); @@ -1690,8 +1704,8 @@ TEST_F(HttpConnectionManagerImplTest, DoNotStartSpanIfTracingIsNotEnabled) { tracing_config_.reset(); EXPECT_CALL(*tracer_, startSpan_(_, _, _, _)).Times(0); - ON_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", - An(), _)) + ON_CALL(runtime_.snapshot(), featureEnabled("tracing.global_enabled", + An(), _)) .WillByDefault(Return(true)); std::shared_ptr filter(new NiceMock()); @@ -2833,7 +2847,7 @@ TEST_F(HttpConnectionManagerImplTest, FrameFloodErrorWithLog) { throw FrameFloodException("too many outbound frames."); })); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("http.connection_manager.log_flood_exception", Matcher(_))) .WillOnce(Return(true)); @@ -3877,7 +3891,11 @@ TEST_F(HttpConnectionManagerImplTest, AlterFilterWatermarkLimits) { EXPECT_EQ(100, decoder_filters_[0]->callbacks_->decoderBufferLimit()); } -TEST_F(HttpConnectionManagerImplTest, HitFilterWatermarkLimits) { +TEST_F(HttpConnectionManagerImplTest, HitFilterHighWatermark) { + // Disable overflow watermark for this test. + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(0)); + initial_buffer_limit_ = 1; streaming_filter_ = true; setup(false, ""); @@ -3924,6 +3942,25 @@ TEST_F(HttpConnectionManagerImplTest, HitFilterWatermarkLimits) { encoder_filters_[1]->callbacks_->setEncoderBufferLimit((buffer_len + 1) * 2); } +TEST_F(HttpConnectionManagerImplTest, HitFilterOverflowWatermark) { + initial_buffer_limit_ = 1; + streaming_filter_ = true; + setup(false, ""); + setUpEncoderAndDecoder(false, false); + + // The filter is a streaming filter. Sending 4 bytes should hit the + // watermark limit and disable reads on the stream. + EXPECT_CALL(stream_, resetStream(StreamResetReason::LocalReset)); + + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + + // Kick off the incoming data. |fake_input| is not sent, but instead kicks + // off sending the headers and |data| queued up in setUpEncoderAndDecoder(). + Buffer::OwnedImpl fake_input("asdf"); + conn_manager_->onData(fake_input, false); +} + TEST_F(HttpConnectionManagerImplTest, HitRequestBufferLimits) { initial_buffer_limit_ = 10; streaming_filter_ = false; @@ -3988,7 +4025,7 @@ TEST_F(HttpConnectionManagerImplTest, HitRequestBufferLimitsIntermediateFilter) conn_manager_->onData(fake_input, false); } -TEST_F(HttpConnectionManagerImplTest, HitResponseBufferLimitsBeforeHeaders) { +TEST_P(HttpConnectionManagerImplTestP, HitResponseBufferLimitsBeforeHeaders) { initial_buffer_limit_ = 10; setup(false, ""); setUpEncoderAndDecoder(false, false); @@ -4026,7 +4063,7 @@ TEST_F(HttpConnectionManagerImplTest, HitResponseBufferLimitsBeforeHeaders) { EXPECT_EQ(1U, stats_.named_.rs_too_large_.value()); } -TEST_F(HttpConnectionManagerImplTest, HitResponseBufferLimitsAfterHeaders) { +TEST_P(HttpConnectionManagerImplTestP, HitResponseBufferLimitsAfterHeaders) { initial_buffer_limit_ = 10; setup(false, ""); setUpEncoderAndDecoder(false, false); diff --git a/test/common/http/http1/codec_impl_test.cc b/test/common/http/http1/codec_impl_test.cc index cf3d3943b22fe..c35234f7121e2 100644 --- a/test/common/http/http1/codec_impl_test.cc +++ b/test/common/http/http1/codec_impl_test.cc @@ -90,6 +90,8 @@ class Http1ServerConnectionImplTest : public testing::Test { uint32_t max_request_headers_kb_{Http::DEFAULT_MAX_REQUEST_HEADERS_KB}; uint32_t max_request_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; Stats::IsolatedStoreImpl store_; + // Create a runtime loader, so that tests can manually manipulate runtime guarded features. + TestScopedRuntime scoped_runtime_; }; void Http1ServerConnectionImplTest::expect400(Protocol p, bool allow_absolute_url, @@ -679,7 +681,6 @@ TEST_F(Http1ServerConnectionImplTest, FloodProtection) { } TEST_F(Http1ServerConnectionImplTest, FloodProtectionOff) { - TestScopedRuntime scoped_runtime; Runtime::LoaderSingleton::getExisting()->mergeValues( {{"envoy.reloadable_features.http1_flood_protection", "false"}}); initialize(); @@ -732,7 +733,6 @@ TEST_F(Http1ServerConnectionImplTest, HostHeaderTranslation) { // Ensures that requests with invalid HTTP header values are not rejected // when the runtime guard is not enabled for the feature. TEST_F(Http1ServerConnectionImplTest, HeaderInvalidCharsRuntimeGuard) { - TestScopedRuntime scoped_runtime; // When the runtime-guarded feature is NOT enabled, invalid header values // should be accepted by the codec. Runtime::LoaderSingleton::getExisting()->mergeValues( @@ -751,7 +751,6 @@ TEST_F(Http1ServerConnectionImplTest, HeaderInvalidCharsRuntimeGuard) { // Ensures that requests with invalid HTTP header values are properly rejected // when the runtime guard is enabled for the feature. TEST_F(Http1ServerConnectionImplTest, HeaderInvalidCharsRejection) { - TestScopedRuntime scoped_runtime; // When the runtime-guarded feature is enabled, invalid header values // should result in a rejection. Runtime::LoaderSingleton::getExisting()->mergeValues( @@ -774,8 +773,6 @@ TEST_F(Http1ServerConnectionImplTest, HeaderInvalidCharsRejection) { } TEST_F(Http1ServerConnectionImplTest, HeaderInvalidAuthority) { - TestScopedRuntime scoped_runtime; - initialize(); MockRequestDecoder decoder; @@ -795,7 +792,6 @@ TEST_F(Http1ServerConnectionImplTest, HeaderInvalidAuthority) { // Regression test for http-parser allowing embedded NULs in header values, // verify we reject them. TEST_F(Http1ServerConnectionImplTest, HeaderEmbeddedNulRejection) { - TestScopedRuntime scoped_runtime; Runtime::LoaderSingleton::getExisting()->mergeValues( {{"envoy.reloadable_features.strict_header_validation", "false"}}); initialize(); @@ -1328,6 +1324,11 @@ TEST_F(Http1ServerConnectionImplTest, UpgradeRequestWithNoBody) { } TEST_F(Http1ServerConnectionImplTest, WatermarkTest) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"buffer.overflow.high_watermark_multiplier", "0"}}); + EXPECT_CALL(connection_, bufferLimit()).Times(1).WillOnce(Return(10)); initialize(); @@ -1376,6 +1377,8 @@ class Http1ClientConnectionImplTest : public testing::Test { protected: Stats::IsolatedStoreImpl store_; uint32_t max_response_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; + // Create a runtime loader, so that tests can manually manipulate runtime guarded features. + TestScopedRuntime scoped_runtime_; }; TEST_F(Http1ClientConnectionImplTest, SimpleGet) { @@ -1656,6 +1659,11 @@ TEST_F(Http1ClientConnectionImplTest, UpgradeResponseWithEarlyData) { } TEST_F(Http1ClientConnectionImplTest, WatermarkTest) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"buffer.overflow.high_watermark_multiplier", "0"}}); + EXPECT_CALL(connection_, bufferLimit()).Times(1).WillOnce(Return(10)); initialize(); diff --git a/test/common/http/http2/BUILD b/test/common/http/http2/BUILD index f4e2e4a6a370a..d8fe9b3e6d3df 100644 --- a/test/common/http/http2/BUILD +++ b/test/common/http/http2/BUILD @@ -29,6 +29,7 @@ envoy_cc_test( "//test/mocks/local_info:local_info_mocks", "//test/mocks/network:network_mocks", "//test/mocks/protobuf:protobuf_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/mocks/upstream:upstream_mocks", "//test/test_common:test_runtime_lib", @@ -118,7 +119,10 @@ envoy_cc_test( "response_header_corpus/simple_example_huffman", "response_header_corpus/simple_example_plain", ], - deps = [":frame_replay_lib"], + deps = [ + ":frame_replay_lib", + "//test/mocks/runtime:runtime_mocks", + ], ) envoy_cc_test( @@ -141,12 +145,18 @@ envoy_cc_fuzz_test( name = "response_header_fuzz_test", srcs = ["response_header_fuzz_test.cc"], corpus = "response_header_corpus", - deps = [":frame_replay_lib"], + deps = [ + ":frame_replay_lib", + "//test/mocks/runtime:runtime_mocks", + ], ) envoy_cc_fuzz_test( name = "request_header_fuzz_test", srcs = ["request_header_fuzz_test.cc"], corpus = "request_header_corpus", - deps = [":frame_replay_lib"], + deps = [ + ":frame_replay_lib", + "//test/mocks/runtime:runtime_mocks", + ], ) diff --git a/test/common/http/http2/codec_impl_test.cc b/test/common/http/http2/codec_impl_test.cc index cc0063b04e3e5..6f2fea44d86a4 100644 --- a/test/common/http/http2/codec_impl_test.cc +++ b/test/common/http/http2/codec_impl_test.cc @@ -159,6 +159,7 @@ class Http2CodecImplTestFixture { MockRequestDecoder request_decoder_; ResponseEncoder* response_encoder_{}; MockStreamCallbacks server_stream_callbacks_; + Runtime::ScopedMockLoaderSingleton runtime_; // Corrupt a metadata frame payload. bool corrupt_metadata_frame_ = false; @@ -657,6 +658,10 @@ TEST_P(Http2CodecImplTest, EncodeMetadataWhileDispatchingTest) { class Http2CodecImplDeferredResetTest : public Http2CodecImplTest {}; TEST_P(Http2CodecImplDeferredResetTest, DeferredResetClient) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(0)); initialize(); InSequence s; @@ -696,6 +701,10 @@ TEST_P(Http2CodecImplDeferredResetTest, DeferredResetClient) { } TEST_P(Http2CodecImplDeferredResetTest, DeferredResetServer) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(0)); initialize(); InSequence s; diff --git a/test/common/http/http2/frame_replay_test.cc b/test/common/http/http2/frame_replay_test.cc index c040f8adb1fc9..f02d317767b5e 100644 --- a/test/common/http/http2/frame_replay_test.cc +++ b/test/common/http/http2/frame_replay_test.cc @@ -2,6 +2,7 @@ #include "test/common/http/common.h" #include "test/common/http/http2/frame_replay.h" +#include "test/mocks/runtime/mocks.h" #include "gtest/gtest.h" @@ -22,8 +23,12 @@ namespace Http2 { namespace { // For organizational purposes only. -class RequestFrameCommentTest : public ::testing::Test {}; -class ResponseFrameCommentTest : public ::testing::Test {}; +class RequestFrameCommentTest : public ::testing::Test { + Runtime::ScopedMockLoaderSingleton runtime_; +}; +class ResponseFrameCommentTest : public ::testing::Test { + Runtime::ScopedMockLoaderSingleton runtime_; +}; // Creates and sets up a stream to reply to. void setupStream(ClientCodecFrameInjector& codec, TestClientConnectionImpl& connection) { diff --git a/test/common/http/http2/request_header_fuzz_test.cc b/test/common/http/http2/request_header_fuzz_test.cc index 440014afb648b..ad7a42b0d6086 100644 --- a/test/common/http/http2/request_header_fuzz_test.cc +++ b/test/common/http/http2/request_header_fuzz_test.cc @@ -6,6 +6,7 @@ #include "test/common/http/http2/frame_replay.h" #include "test/fuzz/fuzz_runner.h" +#include "test/mocks/runtime/mocks.h" using testing::AnyNumber; @@ -29,6 +30,7 @@ void Replay(const Frame& frame, ServerCodecFrameInjector& codec) { } DEFINE_FUZZER(const uint8_t* buf, size_t len) { + Runtime::ScopedMockLoaderSingleton runtime; // Create static objects. static ServerCodecFrameInjector codec; Frame frame; diff --git a/test/common/http/http2/response_header_fuzz_test.cc b/test/common/http/http2/response_header_fuzz_test.cc index 60586dc81e3b1..fcfa54f420335 100644 --- a/test/common/http/http2/response_header_fuzz_test.cc +++ b/test/common/http/http2/response_header_fuzz_test.cc @@ -7,6 +7,7 @@ #include "test/common/http/common.h" #include "test/common/http/http2/frame_replay.h" #include "test/fuzz/fuzz_runner.h" +#include "test/mocks/runtime/mocks.h" using testing::AnyNumber; @@ -38,6 +39,7 @@ void Replay(const Frame& frame, ClientCodecFrameInjector& codec) { } DEFINE_FUZZER(const uint8_t* buf, size_t len) { + Runtime::ScopedMockLoaderSingleton runtime; static ClientCodecFrameInjector codec; Frame frame; frame.assign(buf, buf + len); diff --git a/test/common/network/BUILD b/test/common/network/BUILD index 16186b79e3b33..4b77e7f57ccf3 100644 --- a/test/common/network/BUILD +++ b/test/common/network/BUILD @@ -78,6 +78,7 @@ envoy_cc_test( "//test/mocks/buffer:buffer_mocks", "//test/mocks/event:event_mocks", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/server:server_mocks", "//test/mocks/stats:stats_mocks", "//test/test_common:environment_lib", @@ -104,6 +105,7 @@ envoy_cc_test( "//source/common/network:listen_socket_lib", "//source/common/stats:stats_lib", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/test_common:environment_lib", "//test/test_common:network_utility_lib", "//test/test_common:utility_lib", @@ -177,6 +179,7 @@ envoy_cc_test( "//source/common/stats:stats_lib", "//test/common/network:listener_impl_test_base_lib", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/server:server_mocks", "//test/test_common:environment_lib", "//test/test_common:network_utility_lib", diff --git a/test/common/network/connection_impl_test.cc b/test/common/network/connection_impl_test.cc index 22f4d014111e7..f51d954a3763c 100644 --- a/test/common/network/connection_impl_test.cc +++ b/test/common/network/connection_impl_test.cc @@ -19,6 +19,7 @@ #include "test/mocks/buffer/mocks.h" #include "test/mocks/event/mocks.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/server/mocks.h" #include "test/mocks/stats/mocks.h" #include "test/test_common/environment.h" @@ -76,7 +77,9 @@ TEST(ConnectionImplUtility, updateBufferStats) { ConnectionImplUtility::updateBufferStats(3, 3, previous_total, counter, gauge); } -class ConnectionImplDeathTest : public testing::TestWithParam {}; +class ConnectionImplDeathTest : public testing::TestWithParam { + Runtime::ScopedMockLoaderSingleton runtime_; +}; INSTANTIATE_TEST_SUITE_P(IpVersions, ConnectionImplDeathTest, testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), TestUtility::ipTestParamsToString); @@ -165,16 +168,16 @@ class ConnectionImplTest : public testing::TestWithParam { dispatcher_ = api_->allocateDispatcher(Buffer::WatermarkFactoryPtr{factory}); // The first call to create a client session will get a MockBuffer. // Other calls for server sessions will by default get a normal OwnedImpl. - EXPECT_CALL(*factory, create_(_, _)) + EXPECT_CALL(*factory, create_(_, _, _)) .Times(AnyNumber()) - .WillOnce(Invoke([&](std::function below_low, - std::function above_high) -> Buffer::Instance* { - client_write_buffer_ = new MockWatermarkBuffer(below_low, above_high); + .WillOnce(Invoke([&](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + client_write_buffer_ = new MockWatermarkBuffer(below_low, above_high, above_overflow); return client_write_buffer_; })) - .WillRepeatedly(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high); + .WillRepeatedly(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); } @@ -189,12 +192,12 @@ class ConnectionImplTest : public testing::TestWithParam { ConnectionMocks createConnectionMocks() { auto dispatcher = std::make_unique>(); - EXPECT_CALL(dispatcher->buffer_factory_, create_(_, _)) - .WillRepeatedly(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { + EXPECT_CALL(dispatcher->buffer_factory_, create_(_, _, _)) + .WillRepeatedly(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { // ConnectionImpl calls Envoy::MockBufferFactory::create(), which calls create_() and // wraps the returned raw pointer below with a unique_ptr. - return new Buffer::WatermarkBuffer(below_low, above_high); + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); // This timer will be returned (transferring ownership) to the ConnectionImpl when createTimer() @@ -228,6 +231,7 @@ class ConnectionImplTest : public testing::TestWithParam { MockWatermarkBuffer* client_write_buffer_ = nullptr; Address::InstanceConstSharedPtr source_address_; Socket::OptionsSharedPtr socket_options_; + Runtime::ScopedMockLoaderSingleton runtime_; }; INSTANTIATE_TEST_SUITE_P(IpVersions, ConnectionImplTest, @@ -799,6 +803,10 @@ TEST_P(ConnectionImplTest, BasicWrite) { // Similar to BasicWrite, only with watermarks set. TEST_P(ConnectionImplTest, WriteWithWatermarks) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(0)); useMockBuffer(); setUpBasicConnection(); @@ -857,6 +865,10 @@ TEST_P(ConnectionImplTest, WriteWithWatermarks) { // Read and write random bytes and ensure we don't encounter issues. TEST_P(ConnectionImplTest, WatermarkFuzzing) { + // Disable overflow watermark for this test. + // TODO(mergeconflict): enable for a subsequent test. + EXPECT_CALL(runtime_.snapshot(), getInteger("buffer.overflow.high_watermark_multiplier", _)) + .WillRepeatedly(Return(0)); useMockBuffer(); setUpBasicConnection(); @@ -1265,10 +1277,10 @@ TEST_P(ConnectionImplTest, FlushWriteAndDelayConfigDisabledTest) { NiceMock callbacks; NiceMock dispatcher; - EXPECT_CALL(dispatcher.buffer_factory_, create_(_, _)) - .WillRepeatedly(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high); + EXPECT_CALL(dispatcher.buffer_factory_, create_(_, _, _)) + .WillRepeatedly(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); IoHandlePtr io_handle = std::make_unique(0); std::unique_ptr server_connection(new Network::ConnectionImpl( @@ -1453,10 +1465,10 @@ class FakeReadFilter : public Network::ReadFilter { class MockTransportConnectionImplTest : public testing::Test { public: MockTransportConnectionImplTest() { - EXPECT_CALL(dispatcher_.buffer_factory_, create_(_, _)) - .WillRepeatedly(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high); + EXPECT_CALL(dispatcher_.buffer_factory_, create_(_, _, _)) + .WillRepeatedly(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); file_event_ = new Event::MockFileEvent; @@ -1491,6 +1503,7 @@ class MockTransportConnectionImplTest : public testing::Test { Event::MockFileEvent* file_event_; Event::FileReadyCb file_ready_cb_; TransportSocketCallbacks* transport_socket_callbacks_; + Runtime::ScopedMockLoaderSingleton runtime_; }; // The purpose of this case is to verify the destructor order of the object. @@ -2062,6 +2075,7 @@ class TcpClientConnectionImplTest : public testing::TestWithParam { Api::ApiPtr api_; Event::DispatcherPtr dispatcher_; DnsResolverSharedPtr resolver_; + Runtime::ScopedMockLoaderSingleton runtime_; }; // Parameterize the DNS test server socket address. diff --git a/test/common/network/listener_impl_test.cc b/test/common/network/listener_impl_test.cc index 0ca9b283bf8a5..fe2eca5bfc665 100644 --- a/test/common/network/listener_impl_test.cc +++ b/test/common/network/listener_impl_test.cc @@ -6,6 +6,7 @@ #include "test/common/network/listener_impl_test_base.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/network_utility.h" @@ -51,7 +52,9 @@ static void errorCallbackTest(Address::IpVersion version) { dispatcher->run(Event::Dispatcher::RunType::Block); } -class ListenerImplDeathTest : public testing::TestWithParam {}; +class ListenerImplDeathTest : public testing::TestWithParam { + Runtime::ScopedMockLoaderSingleton runtime_; +}; INSTANTIATE_TEST_SUITE_P(IpVersions, ListenerImplDeathTest, testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), TestUtility::ipTestParamsToString); @@ -68,7 +71,9 @@ class TestListenerImpl : public ListenerImpl { MOCK_METHOD(Address::InstanceConstSharedPtr, getLocalAddress, (os_fd_t fd)); }; -using ListenerImplTest = ListenerImplTestBase; +class ListenerImplTest : public ListenerImplTestBase { + Runtime::ScopedMockLoaderSingleton runtime_; +}; INSTANTIATE_TEST_SUITE_P(IpVersions, ListenerImplTest, testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), TestUtility::ipTestParamsToString); diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index 208d01f0f68ef..3caf5789325c8 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -93,7 +93,7 @@ class RouterTestBase : public testing::Test { RouterTestBase(bool start_child_span, bool suppress_envoy_headers, Protobuf::RepeatedPtrField strict_headers_to_check) : http_context_(stats_store_.symbolTable()), shadow_writer_(new MockShadowWriter()), - config_("test.", local_info_, stats_store_, cm_, runtime_, random_, + config_("test.", local_info_, stats_store_, cm_, runtime_.loader(), random_, ShadowWriterPtr{shadow_writer_}, true, start_child_span, suppress_envoy_headers, false, std::move(strict_headers_to_check), test_time_.timeSystem(), http_context_), router_(config_) { @@ -261,7 +261,7 @@ class RouterTestBase : public testing::Test { envoy::config::core::v3::Locality upstream_locality_; NiceMock stats_store_; NiceMock cm_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock random_; Http::ConnectionPool::MockCancellable cancellable_; Http::ContextImpl http_context_; @@ -3615,8 +3615,8 @@ TEST_F(RouterTest, Shadow) { })); expectResponseTimerCreate(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("bar", 0, 43, 10000)).WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("buzz", 0, 43, 10000)).WillOnce(Return(true)); + EXPECT_CALL(runtime_.snapshot(), featureEnabled("bar", 0, 43, 10000)).WillOnce(Return(true)); + EXPECT_CALL(runtime_.snapshot(), featureEnabled("buzz", 0, 43, 10000)).WillOnce(Return(true)); Http::TestRequestHeaderMapImpl headers; HttpTestUtility::addDefaultHeaders(headers); diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index c53b8368e9ed9..74a108f75a7e5 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -35,6 +35,7 @@ envoy_cc_test( ], deps = [ ":test_cluster_manager", + "//test/test_common:test_runtime_lib", "@envoy_api//envoy/admin/v3:pkg_cc_proto", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index a6db18af064fe..8cadd59f59511 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -5,6 +5,7 @@ #include "envoy/config/core/v3/base.pb.h" #include "test/common/upstream/test_cluster_manager.h" +#include "test/test_common/test_runtime.h" using testing::_; using testing::Eq; @@ -732,6 +733,9 @@ TEST_F(ClusterManagerImplTest, TcpHealthChecker) { } TEST_F(ClusterManagerImplTest, HttpHealthChecker) { + // Create a runtime loader to initialize the watermark c'tor loader + TestScopedRuntime scoped_runtime; + const std::string yaml = R"EOF( static_resources: clusters: diff --git a/test/common/upstream/hds_test.cc b/test/common/upstream/hds_test.cc index df7b3ad51aab6..df3e6c6f1eb0a 100644 --- a/test/common/upstream/hds_test.cc +++ b/test/common/upstream/hds_test.cc @@ -70,7 +70,7 @@ class HdsTest : public testing::Test { })); hds_delegate_ = std::make_unique( stats_store_, Grpc::RawAsyncClientPtr(async_client_), - envoy::config::core::v3::ApiVersion::AUTO, dispatcher_, runtime_, stats_store_, + envoy::config::core::v3::ApiVersion::AUTO, dispatcher_, runtime_.loader(), stats_store_, ssl_context_manager_, random_, test_factory_, log_manager_, cm_, local_info_, admin_, singleton_manager_, tls_, validation_visitor_, *api_); } @@ -122,7 +122,7 @@ class HdsTest : public testing::Test { std::unique_ptr message; Grpc::MockAsyncStream async_stream_; Grpc::MockAsyncClient* async_client_; - Runtime::MockLoader runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock validation_visitor_; Api::ApiPtr api_; Extensions::TransportSockets::Tls::ContextManagerImpl ssl_context_manager_; diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc index a4823c3fafe42..346c2d8af7285 100644 --- a/test/common/upstream/health_checker_impl_test.cc +++ b/test/common/upstream/health_checker_impl_test.cc @@ -146,7 +146,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -170,7 +170,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -193,7 +193,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -216,7 +216,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -239,7 +239,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -263,7 +263,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -284,7 +284,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -310,7 +310,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -332,7 +332,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -355,7 +355,7 @@ class HttpHealthCheckerImplTest : public testing::Test { prefix); health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -377,7 +377,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -399,7 +399,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -423,7 +423,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -447,7 +447,7 @@ class HttpHealthCheckerImplTest : public testing::Test { host); health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -522,7 +522,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -547,7 +547,7 @@ class HttpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -701,7 +701,7 @@ class HttpHealthCheckerImplTest : public testing::Test { NiceMock dispatcher_; std::vector test_sessions_; std::shared_ptr health_checker_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock random_; MockHealthCheckEventLogger* event_logger_{}; std::list connection_index_{}; @@ -721,8 +721,8 @@ TEST_F(HttpHealthCheckerImplTest, Success) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -743,8 +743,8 @@ TEST_F(HttpHealthCheckerImplTest, Degraded) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillRepeatedly(Return(45000)); // We start off as healthy, and should go degraded after receiving the degraded health response. @@ -757,7 +757,7 @@ TEST_F(HttpHealthCheckerImplTest, Degraded) { // Then, after receiving a regular health check response we should go back to healthy. EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); expectStreamCreate(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); test_sessions_[0]->interval_timer_->invokeCallback(); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); @@ -897,8 +897,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessWithSpurious100Continue) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -925,8 +925,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessWithSpuriousMetadata) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -958,8 +958,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessWithMultipleHosts) { EXPECT_CALL(*test_sessions_[1]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).Times(2); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)).Times(2); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .Times(2) .WillRepeatedly(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, @@ -993,8 +993,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessWithMultipleHostSets) { EXPECT_CALL(*test_sessions_[1]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).Times(2); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)).Times(2); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .Times(2) .WillRepeatedly(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, @@ -1027,14 +1027,14 @@ TEST_F(HttpHealthCheckerImplTest, ZeroRetryInterval) { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { onHostStatus(host, changed_state); }); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1054,8 +1054,8 @@ TEST_F(HttpHealthCheckerImplTest, ZeroRetryInterval) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).WillOnce(Return(0)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)).WillOnce(Return(0)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)).WillOnce(Return(0)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)).WillOnce(Return(0)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(1), _)); EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); absl::optional health_checked_cluster("locations-production-iad"); @@ -1097,7 +1097,7 @@ TEST_F(HttpHealthCheckerImplTest, TlsOptions) { EXPECT_CALL(*socket_factory, createTransportSocket(ApplicationProtocolListEq("http1"))); health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); cluster_->prioritySet().getMockHostSet(0)->hosts_ = { @@ -1113,7 +1113,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheck) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupServiceValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1133,8 +1133,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheck) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1148,7 +1148,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServicePrefixPatternCheck) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupServicePrefixPatternValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1168,8 +1168,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServicePrefixPatternCheck) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1183,7 +1183,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceExactPatternCheck) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupServiceExactPatternValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1203,8 +1203,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceExactPatternCheck) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1218,7 +1218,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceRegexPatternCheck) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupServiceRegexPatternValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1238,8 +1238,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceRegexPatternCheck) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1254,7 +1254,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithCustomHostValue) { const std::string path = "/healthcheck"; setupServiceValidationWithCustomHostValueHC(host); // requires non-empty `service_name` in config. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1272,8 +1272,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithCustomHostValue) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1311,7 +1311,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithAdditionalHeaders) { setupServiceValidationWithAdditionalHeaders(); // requires non-empty `service_name` in config. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1354,8 +1354,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithAdditionalHeaders) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1372,7 +1372,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithAdditionalHeaders) { TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithoutUserAgent) { setupServiceValidationWithoutUserAgent(); // requires non-empty `service_name` in config. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1396,8 +1396,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithoutUserAgent) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1414,7 +1414,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithoutUserAgent) { TEST_F(HttpHealthCheckerImplTest, ServiceDoesNotMatchFail) { setupServiceValidationHC(); EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(1); @@ -1428,8 +1428,8 @@ TEST_F(HttpHealthCheckerImplTest, ServiceDoesNotMatchFail) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1445,7 +1445,7 @@ TEST_F(HttpHealthCheckerImplTest, ServiceDoesNotMatchFail) { TEST_F(HttpHealthCheckerImplTest, ServicePatternDoesNotMatchFail) { setupServiceRegexPatternValidationHC(); EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(1); @@ -1459,8 +1459,8 @@ TEST_F(HttpHealthCheckerImplTest, ServicePatternDoesNotMatchFail) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1476,7 +1476,7 @@ TEST_F(HttpHealthCheckerImplTest, ServicePatternDoesNotMatchFail) { TEST_F(HttpHealthCheckerImplTest, ServiceNotPresentInResponseFail) { setupServiceValidationHC(); EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(1); @@ -1490,8 +1490,8 @@ TEST_F(HttpHealthCheckerImplTest, ServiceNotPresentInResponseFail) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1505,7 +1505,7 @@ TEST_F(HttpHealthCheckerImplTest, ServiceNotPresentInResponseFail) { TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOff) { setupServiceValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(false)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1518,8 +1518,8 @@ TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOff) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1531,7 +1531,7 @@ TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOff) { TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOffWithStringPattern) { setupServicePrefixPatternValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(false)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -1544,8 +1544,8 @@ TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOffWithStringPattern) { EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -1557,7 +1557,7 @@ TEST_F(HttpHealthCheckerImplTest, ServiceCheckRuntimeOffWithStringPattern) { TEST_F(HttpHealthCheckerImplTest, SuccessStartFailedFailFirstServiceCheck) { setupNoServiceValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillRepeatedly(Return(true)); absl::optional health_checked_cluster("locations-production-iad"); expectSuccessStartFailedFailFirst(health_checked_cluster); @@ -1594,8 +1594,9 @@ TEST_F(HttpHealthCheckerImplTest, SuccessStartFailedSuccessFirst) { // Test fast success immediately moves us to healthy. EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(1); EXPECT_CALL(*event_logger_, logAddHealthy(_, _, true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).WillOnce(Return(500)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)) + .WillOnce(Return(500)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(500), _)); EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); respond(0, "200", false); @@ -2312,7 +2313,7 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithAltPort) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupServiceValidationHC(); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -2331,8 +2332,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithAltPort) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -2361,8 +2362,8 @@ TEST_F(HttpHealthCheckerImplTest, SuccessWithMultipleHostsAndAltPort) { EXPECT_CALL(*test_sessions_[1]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).Times(2); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)).Times(2); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .Times(2) .WillRepeatedly(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, @@ -2413,7 +2414,7 @@ class ProdHttpHealthCheckerTest : public HttpHealthCheckerImplTest { )EOF"; health_checker_.reset(new TestProdHttpHealthChecker(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -2436,7 +2437,7 @@ class ProdHttpHealthCheckerTest : public HttpHealthCheckerImplTest { )EOF"; health_checker_.reset(new TestProdHttpHealthChecker(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -2471,7 +2472,7 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(Http1CodecClient)) { )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -2492,11 +2493,11 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(Http2CodecClient)) { service_name_matcher: prefix: locations path: /healthcheck - use_http2: true + codec_client_type: 1 )EOF"; health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -2509,7 +2510,7 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(ServiceNameMatch)) { const std::string host = "fake_cluster"; const std::string path = "/healthcheck"; setupDeprecatedServiceNameValidationHC("locations"); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); @@ -2529,8 +2530,8 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(ServiceNameMatch)) { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -2543,7 +2544,7 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(ServiceNameMatch)) { TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(ServiceNameMismatch)) { setupDeprecatedServiceNameValidationHC("locations"); EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100)) + EXPECT_CALL(runtime_.snapshot(), featureEnabled("health_check.verify_cluster", 100)) .WillOnce(Return(true)); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(1); @@ -2557,8 +2558,8 @@ TEST_F(HttpHealthCheckerImplTest, DEPRECATED_FEATURE_TEST(ServiceNameMismatch)) EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000), _)); @@ -2842,9 +2843,9 @@ class TcpHealthCheckerImplTest : public testing::Test { - text: "02" )EOF"; - health_checker_.reset( - new TcpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml.str()), dispatcher_, - runtime_, random_, HealthCheckEventLoggerPtr(event_logger_))); + health_checker_.reset(new TcpHealthCheckerImpl( + *cluster_, parseHealthCheckFromV2Yaml(yaml.str()), dispatcher_, runtime_.loader(), random_, + HealthCheckEventLoggerPtr(event_logger_))); } void setupNoData() { @@ -2857,7 +2858,7 @@ class TcpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TcpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); } @@ -2876,7 +2877,7 @@ class TcpHealthCheckerImplTest : public testing::Test { )EOF"; health_checker_.reset(new TcpHealthCheckerImpl(*cluster_, parseHealthCheckFromV2Yaml(yaml), - dispatcher_, runtime_, random_, + dispatcher_, runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); } @@ -2899,7 +2900,7 @@ class TcpHealthCheckerImplTest : public testing::Test { Event::MockTimer* timeout_timer_{}; Event::MockTimer* interval_timer_{}; Network::ReadFilterSharedPtr read_filter_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock random_; }; @@ -3447,8 +3448,8 @@ class GrpcHealthCheckerImplTestBase { void setupHC() { const auto config = createGrpcHealthCheckConfig(); - health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, runtime_, - random_, + health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, + runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -3459,8 +3460,8 @@ class GrpcHealthCheckerImplTestBase { void setupHCWithUnhealthyThreshold(int value) { auto config = createGrpcHealthCheckConfig(); config.mutable_unhealthy_threshold()->set_value(value); - health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, runtime_, - random_, + health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, + runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -3474,8 +3475,8 @@ class GrpcHealthCheckerImplTestBase { if (authority.has_value()) { config.mutable_grpc_health_check()->set_authority(authority.value()); } - health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, runtime_, - random_, + health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, + runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -3486,8 +3487,8 @@ class GrpcHealthCheckerImplTestBase { void setupNoReuseConnectionHC() { auto config = createGrpcHealthCheckConfig(); config.mutable_reuse_connection()->set_value(false); - health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, runtime_, - random_, + health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, + runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -3505,8 +3506,8 @@ class GrpcHealthCheckerImplTestBase { config.mutable_interval_jitter()->set_seconds(0); config.mutable_unhealthy_threshold()->set_value(3); config.mutable_healthy_threshold()->set_value(3); - health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, runtime_, - random_, + health_checker_.reset(new TestGrpcHealthCheckerImpl(*cluster_, config, dispatcher_, + runtime_.loader(), random_, HealthCheckEventLoggerPtr(event_logger_))); health_checker_->addHostCheckCompleteCb( [this](HostSharedPtr host, HealthTransition changed_state) -> void { @@ -3575,9 +3576,9 @@ class GrpcHealthCheckerImplTestBase { } health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)) .Times(num_healthchecks); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .Times(num_healthchecks) .WillRepeatedly(Return(45000)); for (size_t i = 0; i < num_healthchecks; i++) { @@ -3699,8 +3700,8 @@ class GrpcHealthCheckerImplTestBase { })); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)) .WillOnce(Return(45000)); expectHealthcheckStop(0, 45000); @@ -3717,7 +3718,7 @@ class GrpcHealthCheckerImplTestBase { NiceMock dispatcher_; std::vector test_sessions_; std::shared_ptr health_checker_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; NiceMock random_; MockHealthCheckEventLogger* event_logger_{}; std::list connection_index_{}; @@ -3855,8 +3856,9 @@ TEST_F(GrpcHealthCheckerImplTest, SuccessStartFailedSuccessFirst) { expectHealthcheckStart(0); health_checker_->start(); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)).WillOnce(Return(500)); - EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.max_interval", _)) + .WillOnce(Return(500)); + EXPECT_CALL(runtime_.snapshot(), getInteger("health_check.min_interval", _)); expectHealthcheckStop(0, 500); // Fast success immediately moves us to healthy. EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)); diff --git a/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc b/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc index 4d6c551240b35..a8d234ec962f5 100644 --- a/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc +++ b/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc @@ -21,6 +21,8 @@ TEST_P(BufferIntegrationTest, RouterNotFoundBodyBuffer) { TEST_P(BufferIntegrationTest, RouterRequestAndResponseWithGiantBodyBuffer) { config_helper_.addFilter(ConfigHelper::DEFAULT_BUFFER_FILTER); + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); testRouterRequestAndResponseWithBody(4 * 1024 * 1024, 4 * 1024 * 1024, false); } @@ -97,6 +99,8 @@ TEST_P(BufferIntegrationTest, RouterRequestPopulateContentLengthOnTrailers) { TEST_P(BufferIntegrationTest, RouterRequestBufferLimitExceeded) { config_helper_.addFilter(ConfigHelper::SMALL_BUFFER_FILTER); + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); @@ -137,6 +141,8 @@ TEST_P(BufferIntegrationTest, RouteDisabled) { config_helper_.addConfigModifier(mod); config_helper_.addFilter(ConfigHelper::SMALL_BUFFER_FILTER); config_helper_.setBufferLimits(1024, 1024); + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); initialize(); diff --git a/test/extensions/filters/http/fault/fault_filter_test.cc b/test/extensions/filters/http/fault/fault_filter_test.cc index eb83202d83c85..f682795f6fd40 100644 --- a/test/extensions/filters/http/fault/fault_filter_test.cc +++ b/test/extensions/filters/http/fault/fault_filter_test.cc @@ -128,7 +128,7 @@ class FaultFilterTest : public testing::Test { const std::string v2_empty_fault_config_yaml = "{}"; void SetUpTest(const envoy::extensions::filters::http::fault::v3::HTTPFault fault) { - config_.reset(new FaultFilterConfig(fault, runtime_, "prefix.", stats_, time_system_)); + config_.reset(new FaultFilterConfig(fault, runtime_.loader(), "prefix.", stats_, time_system_)); filter_ = std::make_unique(config_); filter_->setDecoderFilterCallbacks(decoder_filter_callbacks_); filter_->setEncoderFilterCallbacks(encoder_filter_callbacks_); @@ -156,7 +156,7 @@ class FaultFilterTest : public testing::Test { Http::TestResponseHeaderMapImpl response_headers_; Http::TestResponseTrailerMapImpl response_trailers_; Buffer::OwnedImpl data_; - NiceMock runtime_; + Runtime::ScopedMockLoaderSingleton runtime_; Event::MockTimer* timer_{}; Event::SimulatedTimeSystem time_system_; }; @@ -237,7 +237,7 @@ TEST_F(FaultFilterTest, AbortWithHttpStatus) { fault.mutable_abort()->set_http_status(429); SetUpTest(fault); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); @@ -247,12 +247,12 @@ TEST_F(FaultFilterTest, AbortWithHttpStatus) { .Times(0); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 429)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 429)) .WillOnce(Return(429)); Http::TestResponseHeaderMapImpl response_headers{ @@ -284,7 +284,7 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { request_headers_.addCopy("x-envoy-fault-abort-request", "429"); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); @@ -294,12 +294,12 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { .Times(0); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 429)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 429)) .WillOnce(Return(429)); Http::TestResponseHeaderMapImpl response_headers{ @@ -329,21 +329,21 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { TEST_F(FaultFilterTest, FixedDelayZeroDuration) { SetUpTest(fixed_delay_only_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); // Return 0ms delay - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(0)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(_)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, continueDecoding()).Times(0); @@ -362,7 +362,7 @@ TEST_F(FaultFilterTest, Overflow) { fault.mutable_max_active_faults()->set_value(0); SetUpTest(fault); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", 0)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", 0)) .WillOnce(Return(0)); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers_, true)); @@ -378,17 +378,17 @@ TEST_F(FaultFilterTest, FixedDelayDeprecatedPercentAndNonZeroDuration) { fault.mutable_delay()->mutable_fixed_delay()->set_seconds(5); SetUpTest(fault); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(50)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("FixedDelayDeprecatedPercentAndNonZeroDuration"); @@ -400,7 +400,7 @@ TEST_F(FaultFilterTest, FixedDelayDeprecatedPercentAndNonZeroDuration) { filter_->decodeHeaders(request_headers_, false)); // Delay only case - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(StreamInfo::ResponseFlag::FaultInjected)) @@ -420,21 +420,21 @@ TEST_F(FaultFilterTest, FixedDelayDeprecatedPercentAndNonZeroDuration) { TEST_F(FaultFilterTest, DelayForDownstreamCluster) { SetUpTest(fixed_delay_only_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); request_headers_.addCopy("x-envoy-downstream-service-cluster", "cluster"); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.cluster.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(125UL)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.delay.fixed_duration_ms", 125UL)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.cluster.delay.fixed_duration_ms", 125UL)) .WillOnce(Return(500UL)); expectDelayTimer(500UL); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, @@ -444,8 +444,8 @@ TEST_F(FaultFilterTest, DelayForDownstreamCluster) { filter_->decodeHeaders(request_headers_, false)); // Delay only case, no aborts. - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.abort.http_status", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.cluster.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(StreamInfo::ResponseFlag::FaultInjected)) @@ -467,21 +467,21 @@ TEST_F(FaultFilterTest, DelayForDownstreamCluster) { TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { SetUpTest(fixed_delay_and_abort_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); request_headers_.addCopy("x-envoy-downstream-service-cluster", "cluster"); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.cluster.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(125UL)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.delay.fixed_duration_ms", 125UL)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.cluster.delay.fixed_duration_ms", 125UL)) .WillOnce(Return(500UL)); expectDelayTimer(500UL); @@ -494,14 +494,14 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { EXPECT_EQ(1UL, config_->stats().active_faults_.value()); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.cluster.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 503)) .WillOnce(Return(503)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.abort.http_status", 503)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.cluster.abort.http_status", 503)) .WillOnce(Return(500)); Http::TestResponseHeaderMapImpl response_headers{ @@ -531,17 +531,17 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { TEST_F(FaultFilterTest, FixedDelayAndAbort) { SetUpTest(fixed_delay_and_abort_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("FixedDelayAndAbort"); @@ -554,12 +554,12 @@ TEST_F(FaultFilterTest, FixedDelayAndAbort) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 503)) .WillOnce(Return(503)); Http::TestResponseHeaderMapImpl response_headers{ @@ -585,16 +585,16 @@ TEST_F(FaultFilterTest, FixedDelayAndAbort) { TEST_F(FaultFilterTest, FixedDelayAndAbortDownstreamNodes) { SetUpTest(fixed_delay_and_abort_nodes_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); expectDelayTimer(5000UL); @@ -607,11 +607,11 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstreamNodes) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls. - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 503)) .WillOnce(Return(503)); Http::TestResponseHeaderMapImpl response_headers{ @@ -637,7 +637,7 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstreamNodes) { TEST_F(FaultFilterTest, NoDownstreamMatch) { SetUpTest(fixed_delay_and_abort_nodes_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); @@ -649,17 +649,17 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchSuccess) { request_headers_.addCopy("x-foo1", "Bar"); request_headers_.addCopy("x-foo2", "RandomValue"); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("FixedDelayAndAbortHeaderMatchSuccess"); @@ -672,12 +672,12 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchSuccess) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", 503)) .WillOnce(Return(503)); Http::TestResponseHeaderMapImpl response_headers{ @@ -704,20 +704,20 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchFail) { request_headers_.addCopy("x-foo1", "Bar"); request_headers_.addCopy("x-foo3", "Baz"); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(_)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, continueDecoding()).Times(0); @@ -734,17 +734,17 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchFail) { TEST_F(FaultFilterTest, TimerResetAfterStreamReset) { SetUpTest(fixed_delay_only_yaml); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Prep up with a 5s delay - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("FixedDelayWithStreamReset"); @@ -764,11 +764,11 @@ TEST_F(FaultFilterTest, TimerResetAfterStreamReset) { EXPECT_CALL(*timer_, disableTimer()); // The timer callback should never be called. - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(StreamInfo::ResponseFlag::FaultInjected)) @@ -788,17 +788,17 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchSuccess) { EXPECT_CALL(decoder_filter_callbacks_.route_->route_entry_, clusterName()) .WillOnce(ReturnRef(upstream_cluster)); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("FaultWithTargetClusterMatchSuccess"); @@ -810,7 +810,7 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchSuccess) { filter_->decodeHeaders(request_headers_, false)); // Delay only case - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(StreamInfo::ResponseFlag::FaultInjected)) @@ -831,19 +831,19 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchFail) { EXPECT_CALL(decoder_filter_callbacks_.route_->route_entry_, clusterName()) .WillOnce(ReturnRef(upstream_cluster)); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(_)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, continueDecoding()).Times(0); @@ -861,19 +861,19 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterNullRoute) { const std::string upstream_cluster("www1"); EXPECT_CALL(*decoder_filter_callbacks_.route_, routeEntry()).WillRepeatedly(Return(nullptr)); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.abort.abort_percent", Matcher(_))) .Times(0); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(_)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, continueDecoding()).Times(0); @@ -902,17 +902,17 @@ void FaultFilterTest::TestPerFilterConfigFault( EXPECT_CALL(decoder_filter_callbacks_.route_->route_entry_, clusterName()) .WillOnce(ReturnRef(upstream_cluster)); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.delay.fixed_delay_percent", Matcher(Percent(100)))) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) + EXPECT_CALL(runtime_.snapshot(), getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); SCOPED_TRACE("PerFilterConfigFault"); @@ -969,7 +969,7 @@ class FaultFilterRateLimitTest : public FaultFilterTest { fault.mutable_response_rate_limit()->mutable_percentage()->set_numerator(100); SetUpTest(fault); - EXPECT_CALL(runtime_.snapshot_, + EXPECT_CALL(runtime_.snapshot(), featureEnabled("fault.http.rate_limit.response_percent", Matcher(Percent(100)))) .WillOnce(Return(enable_runtime)); diff --git a/test/extensions/filters/listener/proxy_protocol/BUILD b/test/extensions/filters/listener/proxy_protocol/BUILD index 0eb0eb4983ebd..4517a63165993 100644 --- a/test/extensions/filters/listener/proxy_protocol/BUILD +++ b/test/extensions/filters/listener/proxy_protocol/BUILD @@ -29,6 +29,7 @@ envoy_extension_cc_test( "//test/mocks/api:api_mocks", "//test/mocks/buffer:buffer_mocks", "//test/mocks/network:network_mocks", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/server:server_mocks", "//test/test_common:environment_lib", "//test/test_common:network_utility_lib", diff --git a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc index 9dd9b3118d481..23f0c9466bed5 100644 --- a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc +++ b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc @@ -22,6 +22,7 @@ #include "test/mocks/api/mocks.h" #include "test/mocks/buffer/mocks.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/network_utility.h" @@ -186,6 +187,7 @@ class ProxyProtocolTest : public testing::TestWithParam read_filter_; std::string name_; const Network::FilterChainSharedPtr filter_chain_; + Runtime::ScopedMockLoaderSingleton runtime_; }; // Parameterize the listener socket address version. diff --git a/test/extensions/quic_listeners/quiche/integration/quic_http_integration_test.cc b/test/extensions/quic_listeners/quiche/integration/quic_http_integration_test.cc index 0409e68257863..3f65830c8e0a6 100644 --- a/test/extensions/quic_listeners/quiche/integration/quic_http_integration_test.cc +++ b/test/extensions/quic_listeners/quiche/integration/quic_http_integration_test.cc @@ -187,6 +187,9 @@ TEST_P(QuicHttpIntegrationTest, UpstreamReadDisabledOnGiantResponseBody) { } TEST_P(QuicHttpIntegrationTest, DownstreamReadDisabledOnGiantPost) { + // TODO(adip): enable for subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(/*upstream_buffer_limit=*/1024, /*downstream_buffer_limit=*/1024); testRouterRequestAndResponseWithBody(/*request_size=*/1024 * 1024, /*response_size=*/1024, false); } diff --git a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc index bf55f47d034e8..a4568f1d789a1 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc @@ -86,6 +86,9 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, SslIntegrationTest, TestUtility::ipTestParamsToString); TEST_P(SslIntegrationTest, RouterRequestAndResponseWithGiantBodyBuffer) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection({}); }; diff --git a/test/extensions/transport_sockets/tls/ssl_socket_test.cc b/test/extensions/transport_sockets/tls/ssl_socket_test.cc index 0abe39e7b970c..edda90d8cff76 100644 --- a/test/extensions/transport_sockets/tls/ssl_socket_test.cc +++ b/test/extensions/transport_sockets/tls/ssl_socket_test.cc @@ -33,6 +33,7 @@ #include "test/extensions/transport_sockets/tls/test_private_key_method_provider.h" #include "test/mocks/buffer/mocks.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/secret/mocks.h" #include "test/mocks/server/mocks.h" #include "test/mocks/ssl/mocks.h" @@ -777,6 +778,7 @@ class SslSocketTest : public SslCertsTest, const Network::Address::IpVersion version); Event::DispatcherPtr dispatcher_; + Runtime::ScopedMockLoaderSingleton runtime_; }; INSTANTIATE_TEST_SUITE_P(IpVersions, SslSocketTest, @@ -4223,16 +4225,16 @@ class SslReadBufferLimitTest : public SslSocketTest { dispatcher_ = api_->allocateDispatcher(Buffer::WatermarkFactoryPtr{factory}); // By default, expect 4 buffers to be created - the client and server read and write buffers. - EXPECT_CALL(*factory, create_(_, _)) + EXPECT_CALL(*factory, create_(_, _, _)) .Times(2) - .WillOnce(Invoke([&](std::function below_low, - std::function above_high) -> Buffer::Instance* { - client_write_buffer = new MockWatermarkBuffer(below_low, above_high); + .WillOnce(Invoke([&](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + client_write_buffer = new MockWatermarkBuffer(below_low, above_high, above_overflow); return client_write_buffer; })) - .WillRepeatedly(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high); + .WillRepeatedly(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); initialize(); diff --git a/test/integration/http2_integration_test.cc b/test/integration/http2_integration_test.cc index 4a1340755b244..00c704b20680b 100644 --- a/test/integration/http2_integration_test.cc +++ b/test/integration/http2_integration_test.cc @@ -32,10 +32,18 @@ TEST_P(Http2IntegrationTest, RouterRequestAndResponseWithBodyNoBuffer) { } TEST_P(Http2IntegrationTest, FlowControlOnAndGiantBody) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. testRouterRequestAndResponseWithBody(1024 * 1024, 1024 * 1024, false); } +TEST_P(Http2IntegrationTest, FlowControlOnAndDownstreamOverflowBufferHeader) { + config_helper_.setBufferLimits(4096, 1024); // Set buffer limits upstream and downstream. + testRouterRequestAndResponseWithGiantHeader(2048); +} + TEST_P(Http2IntegrationTest, RouterHeaderOnlyRequestAndResponseNoBuffer) { testRouterHeaderOnlyRequestAndResponse(); } @@ -1088,6 +1096,9 @@ void Http2IntegrationTest::simultaneousRequest(int32_t request1_bytes, int32_t r TEST_P(Http2IntegrationTest, SimultaneousRequest) { simultaneousRequest(1024, 512); } TEST_P(Http2IntegrationTest, SimultaneousRequestWithBufferLimits) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. simultaneousRequest(1024 * 32, 1024 * 16); } diff --git a/test/integration/http2_upstream_integration_test.cc b/test/integration/http2_upstream_integration_test.cc index 70e05547cb1fa..e81e5c3f815d3 100644 --- a/test/integration/http2_upstream_integration_test.cc +++ b/test/integration/http2_upstream_integration_test.cc @@ -96,6 +96,9 @@ void Http2UpstreamIntegrationTest::bidirectionalStreaming(uint32_t bytes) { TEST_P(Http2UpstreamIntegrationTest, BidirectionalStreaming) { bidirectionalStreaming(1024); } TEST_P(Http2UpstreamIntegrationTest, LargeBidirectionalStreamingWithBufferLimits) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. bidirectionalStreaming(1024 * 32); } @@ -199,6 +202,9 @@ TEST_P(Http2UpstreamIntegrationTest, SimultaneousRequest) { } TEST_P(Http2UpstreamIntegrationTest, LargeSimultaneousRequestWithBufferLimits) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. simultaneousRequest(1024 * 20, 1024 * 14 + 2, 1024 * 10 + 5, 1024 * 16); } @@ -249,6 +255,9 @@ TEST_P(Http2UpstreamIntegrationTest, ManySimultaneousRequest) { } TEST_P(Http2UpstreamIntegrationTest, ManyLargeSimultaneousRequestWithBufferLimits) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. manySimultaneousRequests(1024 * 20, 1024 * 20); } @@ -264,6 +273,9 @@ TEST_P(Http2UpstreamIntegrationTest, ManyLargeSimultaneousRequestWithRandomBacku } TEST_P(Http2UpstreamIntegrationTest, UpstreamConnectionCloseWithManyStreams) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. const uint32_t num_requests = 20; std::vector encoders; diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 9a16749531a8d..3e0560d3387b1 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -629,6 +629,26 @@ void HttpIntegrationTest::testRouterUpstreamResponseBeforeRequestComplete() { EXPECT_EQ(512U, response->body().size()); } +void HttpIntegrationTest::testRouterRequestAndResponseWithGiantHeader(uint64_t response_size) { + initialize(); + codec_client_ = makeHttpConnection(lookupPort("http")); + fake_upstreams_[0]->set_allow_unexpected_disconnects(true); + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + + waitForNextUpstreamRequest(); + // Send response headers, and no end_stream (there's response body). + Http::TestResponseHeaderMapImpl response_headers_{{":status", "200"}, + {":big", std::string(response_size, 'a')}}; + upstream_request_->encodeHeaders(default_response_headers_, false); + // Send the response data, with end_stream true. + upstream_request_->encodeData(response_size, true); + + // Overflow should happen, and the response should be reset + // Wait for the response to be read by the codec client. + codec_client_->waitForDisconnect(); + EXPECT_FALSE(response->complete()); +} + void HttpIntegrationTest::testRetry() { initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); diff --git a/test/integration/http_integration.h b/test/integration/http_integration.h index 3fbace26ffe73..7a1d859210e3b 100644 --- a/test/integration/http_integration.h +++ b/test/integration/http_integration.h @@ -213,6 +213,9 @@ class HttpIntegrationTest : public BaseIntegrationTest { void testEnvoyProxying100Continue(bool continue_before_upstream_complete = false, bool with_encoder_filter = false); + // Overflow watermark tests + void testRouterRequestAndResponseWithGiantHeader(uint64_t response_size); + // HTTP/2 client tests. void testDownstreamResetBeforeResponseComplete(); // Test that trailers are sent. request_trailers_present and diff --git a/test/integration/http_timeout_integration_test.cc b/test/integration/http_timeout_integration_test.cc index 24e116eb7d13c..fa8ff1843e453 100644 --- a/test/integration/http_timeout_integration_test.cc +++ b/test/integration/http_timeout_integration_test.cc @@ -381,24 +381,36 @@ TEST_P(HttpTimeoutIntegrationTest, HedgedPerTryTimeoutWithBodyNoBufferSecondRequ TEST_P(HttpTimeoutIntegrationTest, HedgedPerTryTimeoutLowUpstreamBufferLimitLargeRequestFirstRequestWins) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024 * 1024); // Set buffer limits upstream and downstream. testRouterRequestAndResponseWithHedgedPerTryTimeout(1024 * 1024, 1024, true); } TEST_P(HttpTimeoutIntegrationTest, HedgedPerTryTimeoutLowUpstreamBufferLimitLargeRequestSecondRequestWins) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024 * 1024); // Set buffer limits upstream and downstream. testRouterRequestAndResponseWithHedgedPerTryTimeout(1024 * 1024, 1024, false); } TEST_P(HttpTimeoutIntegrationTest, HedgedPerTryTimeoutLowDownstreamBufferLimitLargeResponseFirstRequestWins) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024 * 1024, 1024); // Set buffer limits upstream and downstream. testRouterRequestAndResponseWithHedgedPerTryTimeout(1024, 1024 * 1024, true); } TEST_P(HttpTimeoutIntegrationTest, HedgedPerTryTimeoutLowDownstreamBufferLimitLargeResponseSecondRequestWins) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024 * 1024, 1024); // Set buffer limits upstream and downstream. testRouterRequestAndResponseWithHedgedPerTryTimeout(1024, 1024 * 1024, false); } diff --git a/test/integration/integration.cc b/test/integration/integration.cc index a12c5a51f3d54..18391453ef775 100644 --- a/test/integration/integration.cc +++ b/test/integration/integration.cc @@ -154,10 +154,11 @@ IntegrationTcpClient::IntegrationTcpClient(Event::Dispatcher& dispatcher, bool enable_half_close) : payload_reader_(new WaitForPayloadReader(dispatcher)), callbacks_(new ConnectionCallbacks(*this)) { - EXPECT_CALL(factory, create_(_, _)) - .WillOnce(Invoke([&](std::function below_low, - std::function above_high) -> Buffer::Instance* { - client_write_buffer_ = new NiceMock(below_low, above_high); + EXPECT_CALL(factory, create_(_, _, _)) + .WillOnce(Invoke([&](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + client_write_buffer_ = + new NiceMock(below_low, above_high, above_overflow); return client_write_buffer_; })); @@ -260,10 +261,10 @@ BaseIntegrationTest::BaseIntegrationTest(const InstanceConstSharedPtrFn& upstrea // complex test hooks to the server and/or spin waiting on stats, neither of which I think are // necessary right now. timeSystem().sleep(std::chrono::milliseconds(10)); - ON_CALL(*mock_buffer_factory_, create_(_, _)) - .WillByDefault(Invoke([](std::function below_low, - std::function above_high) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high); + ON_CALL(*mock_buffer_factory_, create_(_, _, _)) + .WillByDefault(Invoke([](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); ON_CALL(factory_context_, api()).WillByDefault(ReturnRef(*api_)); } @@ -379,6 +380,22 @@ void BaseIntegrationTest::setUpstreamProtocol(FakeHttpConnection::Type protocol) } } +void BaseIntegrationTest::clearBufferOverflowHighWatermarkMultiplier() { + config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + TestUtility::loadFromYaml(R"EOF( +layers: + - name: haha + admin_layer: {} + - name: hoho + static_layer: + buffer: + overflow: + high_watermark_multiplier: 0 + )EOF", + *bootstrap.mutable_layered_runtime()); + }); +} + IntegrationTcpClientPtr BaseIntegrationTest::makeTcpConnection(uint32_t port) { return std::make_unique(*dispatcher_, *mock_buffer_factory_, port, version_, enable_half_close_); diff --git a/test/integration/integration.h b/test/integration/integration.h index 034623bb06123..da2543ae5f0b9 100644 --- a/test/integration/integration.h +++ b/test/integration/integration.h @@ -184,6 +184,9 @@ class BaseIntegrationTest : protected Logger::Loggable { void skipPortUsageValidation() { config_helper_.skipPortUsageValidation(); } // Make test more deterministic by using a fixed RNG value. void setDeterministic() { deterministic_ = true; } + // Sets the runtime value `buffer.overflow.high_watermark_multiplier` to 0, disabling the + // overflow watermark feature for the scope of the test. + void clearBufferOverflowHighWatermarkMultiplier(); FakeHttpConnection::Type upstreamProtocol() const { return upstream_protocol_; } diff --git a/test/integration/integration_test.cc b/test/integration/integration_test.cc index 63a2e4f33f017..86878a5351a28 100644 --- a/test/integration/integration_test.cc +++ b/test/integration/integration_test.cc @@ -201,6 +201,9 @@ TEST_P(IntegrationTest, RouterRequestAndResponseWithBodyNoBuffer) { } TEST_P(IntegrationTest, FlowControlOnAndGiantBody) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); testRouterRequestAndResponseWithBody(1024 * 1024, 1024 * 1024, false); } @@ -223,6 +226,9 @@ TEST_P(IntegrationTest, RouterUpstreamDisconnectBeforeResponseComplete) { // Regression test for https://github.com/envoyproxy/envoy/issues/9508 TEST_P(IntegrationTest, ResponseFramedByConnectionCloseWithReadLimits) { + // TODO(adip): enable for subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + // Set a small buffer limit on the downstream in order to trigger a call to trigger readDisable on // the upstream when proxying the response. Upstream limit needs to be larger so that // RawBufferSocket::doRead reads the response body and detects the upstream close in the same call @@ -329,6 +335,9 @@ TEST_P(IntegrationTest, UpstreamDisconnectWithTwoRequests) { // Test hitting the bridge filter with too many response bytes to buffer. Given // the headers are not proxied, the connection manager will send a local error reply. TEST_P(IntegrationTest, HittingGrpcFilterLimitBufferingHeaders) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.addFilter( "{ name: grpc_http1_bridge, typed_config: { \"@type\": " "type.googleapis.com/envoy.config.filter.http.grpc_http1_bridge.v2.Config } }"); @@ -967,6 +976,9 @@ TEST_P(IntegrationTest, ViaAppendWith100Continue) { // sent by Envoy, it will wait for response acknowledgment (via FIN/RST) from the client before // closing the socket (with a timeout for ensuring cleanup). TEST_P(IntegrationTest, TestDelayedConnectionTeardownOnGracefulClose) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + // This test will trigger an early 413 Payload Too Large response due to buffer limits being // exceeded. The following filter is needed since the router filter will never trigger a 413. config_helper_.addFilter("{ name: http_dynamo_filter, typed_config: { \"@type\": " diff --git a/test/integration/protocol_integration_test.cc b/test/integration/protocol_integration_test.cc index 905e84a94a2af..a213e4faaab0e 100644 --- a/test/integration/protocol_integration_test.cc +++ b/test/integration/protocol_integration_test.cc @@ -479,6 +479,9 @@ TEST_P(DownstreamProtocolIntegrationTest, RetryHostPredicateFilter) { // Very similar set-up to testRetry but with a 16k request the request will not // be buffered and the 503 will be returned to the user. TEST_P(ProtocolIntegrationTest, RetryHittingBufferLimit) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); // Set buffer limits upstream and downstream. initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); @@ -569,6 +572,9 @@ TEST_P(DownstreamProtocolIntegrationTest, HittingDecoderFilterLimit) { // Test hitting the dynamo filter with too many response bytes to buffer. Given the request headers // are sent on early, the stream/connection will be reset. TEST_P(ProtocolIntegrationTest, HittingEncoderFilterLimit) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + useAccessLog(); config_helper_.addFilter("{ name: envoy.filters.http.dynamo, typed_config: { \"@type\": " "type.googleapis.com/google.protobuf.Empty } }"); @@ -1197,6 +1203,9 @@ name: passthrough-filter // Tests StopAllIterationAndWatermark. decode-headers-return-stop-all-watermark-filter sets buffer // limit to 100. Verifies data pause when limit is reached, and resume after iteration continues. TEST_P(DownstreamProtocolIntegrationTest, TestDecodeHeadersReturnsStopAllWatermark) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.addFilter(R"EOF( name: decode-headers-return-stop-all-filter )EOF"); @@ -1335,6 +1344,9 @@ name: encode-headers-return-stop-all-filter // Tests encodeHeaders() returns StopAllIterationAndWatermark. TEST_P(DownstreamProtocolIntegrationTest, TestEncodeHeadersReturnsStopAllWatermark) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.addFilter(R"EOF( name: encode-headers-return-stop-all-filter )EOF"); diff --git a/test/integration/sds_static_integration_test.cc b/test/integration/sds_static_integration_test.cc index 8b488b0f58e19..537d6ce857616 100644 --- a/test/integration/sds_static_integration_test.cc +++ b/test/integration/sds_static_integration_test.cc @@ -101,6 +101,9 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, SdsStaticDownstreamIntegrationTest, TestUtility::ipTestParamsToString); TEST_P(SdsStaticDownstreamIntegrationTest, RouterRequestAndResponseWithGiantBodyBuffer) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; @@ -160,6 +163,9 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, SdsStaticUpstreamIntegrationTest, TestUtility::ipTestParamsToString); TEST_P(SdsStaticUpstreamIntegrationTest, RouterRequestAndResponseWithGiantBodyBuffer) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + testRouterRequestAndResponseWithBody(16 * 1024 * 1024, 16 * 1024 * 1024, false, nullptr); } diff --git a/test/integration/tcp_proxy_integration_test.cc b/test/integration/tcp_proxy_integration_test.cc index 4ebaf52f50ad5..b460a25439bd6 100644 --- a/test/integration/tcp_proxy_integration_test.cc +++ b/test/integration/tcp_proxy_integration_test.cc @@ -105,6 +105,9 @@ TEST_P(TcpProxyIntegrationTest, TcpProxyDownstreamDisconnect) { } TEST_P(TcpProxyIntegrationTest, TcpProxyLargeWrite) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); initialize(); @@ -353,6 +356,9 @@ TEST_P(TcpProxyIntegrationTest, TestIdletimeoutWithNoData) { } TEST_P(TcpProxyIntegrationTest, TestIdletimeoutWithLargeOutstandingData) { + // TODO(mergeconflict): enable for a subsequent test. + clearBufferOverflowHighWatermarkMultiplier(); + config_helper_.setBufferLimits(1024, 1024); enable_half_close_ = false; config_helper_.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { @@ -685,11 +691,12 @@ void TcpProxySslIntegrationTest::setupConnections() { // Set up the mock buffer factory so the newly created SSL client will have a mock write // buffer. This allows us to track the bytes actually written to the socket. - EXPECT_CALL(*mock_buffer_factory_, create_(_, _)) + EXPECT_CALL(*mock_buffer_factory_, create_(_, _, _)) .Times(1) - .WillOnce(Invoke([&](std::function below_low, - std::function above_high) -> Buffer::Instance* { - client_write_buffer_ = new NiceMock(below_low, above_high); + .WillOnce(Invoke([&](std::function below_low, std::function above_high, + std::function above_overflow) -> Buffer::Instance* { + client_write_buffer_ = + new NiceMock(below_low, above_high, above_overflow); ON_CALL(*client_write_buffer_, move(_)) .WillByDefault(Invoke(client_write_buffer_, &MockWatermarkBuffer::baseMove)); ON_CALL(*client_write_buffer_, drain(_)) diff --git a/test/mocks/buffer/mocks.cc b/test/mocks/buffer/mocks.cc index 64459da03703f..8328f870b0632 100644 --- a/test/mocks/buffer/mocks.cc +++ b/test/mocks/buffer/mocks.cc @@ -6,16 +6,18 @@ namespace Envoy { template <> MockBufferBase::MockBufferBase(std::function below_low, - std::function above_high) - : Buffer::WatermarkBuffer(below_low, above_high) {} + std::function above_high, + std::function above_overflow) + : Buffer::WatermarkBuffer(below_low, above_high, above_overflow) {} template <> MockBufferBase::MockBufferBase() - : Buffer::WatermarkBuffer([&]() -> void {}, [&]() -> void {}) { + : Buffer::WatermarkBuffer([&]() -> void {}, [&]() -> void {}, [&]() -> void {}) { ASSERT(0); // This constructor is not supported for WatermarkBuffer. } template <> -MockBufferBase::MockBufferBase(std::function, std::function) +MockBufferBase::MockBufferBase(std::function, std::function, + std::function) : Buffer::OwnedImpl() { ASSERT(0); // This constructor is not supported for OwnedImpl. } diff --git a/test/mocks/buffer/mocks.h b/test/mocks/buffer/mocks.h index a37d6cc3a2973..76246f0dc4c3f 100644 --- a/test/mocks/buffer/mocks.h +++ b/test/mocks/buffer/mocks.h @@ -17,7 +17,8 @@ namespace Envoy { template class MockBufferBase : public BaseClass { public: MockBufferBase(); - MockBufferBase(std::function below_low, std::function above_high); + MockBufferBase(std::function below_low, std::function above_high, + std::function above_overflow); MOCK_METHOD(Api::IoCallUint64Result, write, (Network::IoHandle & io_handle)); MOCK_METHOD(void, move, (Buffer::Instance & rhs)); @@ -57,12 +58,14 @@ template class MockBufferBase : public BaseClass { template <> MockBufferBase::MockBufferBase(std::function below_low, - std::function above_high); + std::function above_high, + std::function above_overflow); template <> MockBufferBase::MockBufferBase(); template <> MockBufferBase::MockBufferBase(std::function below_low, - std::function above_high); + std::function above_high, + std::function above_overflow); template <> MockBufferBase::MockBufferBase(); class MockBuffer : public MockBufferBase { @@ -78,8 +81,9 @@ class MockWatermarkBuffer : public MockBufferBase { public: using BaseClass = MockBufferBase; - MockWatermarkBuffer(std::function below_low, std::function above_high) - : BaseClass(below_low, above_high) { + MockWatermarkBuffer(std::function below_low, std::function above_high, + std::function above_overflow) + : BaseClass(below_low, above_high, above_overflow) { ON_CALL(*this, write(testing::_)) .WillByDefault(testing::Invoke(this, &MockWatermarkBuffer::trackWrites)); ON_CALL(*this, move(testing::_)) @@ -92,13 +96,14 @@ class MockBufferFactory : public Buffer::WatermarkFactory { MockBufferFactory(); ~MockBufferFactory() override; - Buffer::InstancePtr create(std::function below_low, - std::function above_high) override { - return Buffer::InstancePtr{create_(below_low, above_high)}; + Buffer::InstancePtr create(std::function below_low, std::function above_high, + std::function above_overflow) override { + return Buffer::InstancePtr{create_(below_low, above_high, above_overflow)}; } MOCK_METHOD(Buffer::Instance*, create_, - (std::function below_low, std::function above_high)); + (std::function below_low, std::function above_high, + std::function above_overflow)); }; MATCHER_P(BufferEqual, rhs, testing::PrintToString(*rhs)) { diff --git a/test/mocks/runtime/mocks.cc b/test/mocks/runtime/mocks.cc index 9dda39b1087c9..2d067e4967e88 100644 --- a/test/mocks/runtime/mocks.cc +++ b/test/mocks/runtime/mocks.cc @@ -6,6 +6,7 @@ using testing::_; using testing::Return; using testing::ReturnArg; +using testing::ReturnRef; namespace Envoy { namespace Runtime { @@ -23,7 +24,12 @@ MockSnapshot::MockSnapshot() { MockSnapshot::~MockSnapshot() = default; -MockLoader::MockLoader() { ON_CALL(*this, snapshot()).WillByDefault(ReturnRef(snapshot_)); } +MockLoader::MockLoader() + : threadsafe_snapshot_(std::make_shared>()), + snapshot_(*threadsafe_snapshot_) { + ON_CALL(*this, snapshot()).WillByDefault(ReturnRef(snapshot_)); + ON_CALL(*this, threadsafeSnapshot()).WillByDefault(Return(threadsafe_snapshot_)); +} MockLoader::~MockLoader() = default; @@ -31,5 +37,13 @@ MockOverrideLayer::MockOverrideLayer() = default; MockOverrideLayer::~MockOverrideLayer() = default; +ScopedMockLoaderSingleton::ScopedMockLoaderSingleton() { LoaderSingleton::initialize(&loader_); } + +ScopedMockLoaderSingleton::~ScopedMockLoaderSingleton() { LoaderSingleton::clear(); } + +Runtime::MockLoader& ScopedMockLoaderSingleton::loader() { return loader_; } + +Runtime::MockSnapshot& ScopedMockLoaderSingleton::snapshot() { return loader_.snapshot_; } + } // namespace Runtime } // namespace Envoy diff --git a/test/mocks/runtime/mocks.h b/test/mocks/runtime/mocks.h index 532c5650e3a11..8349c719c2a64 100644 --- a/test/mocks/runtime/mocks.h +++ b/test/mocks/runtime/mocks.h @@ -10,6 +10,8 @@ #include "gmock/gmock.h" +using testing::NiceMock; + namespace Envoy { namespace Runtime { @@ -75,7 +77,8 @@ class MockLoader : public Loader { MOCK_METHOD(std::shared_ptr, threadsafeSnapshot, ()); MOCK_METHOD(void, mergeValues, ((const std::unordered_map&))); - testing::NiceMock snapshot_; + std::shared_ptr threadsafe_snapshot_; + MockSnapshot& snapshot_; }; class MockOverrideLayer : public Snapshot::OverrideLayer { @@ -87,5 +90,26 @@ class MockOverrideLayer : public Snapshot::OverrideLayer { MOCK_METHOD(const Snapshot::EntryMap&, values, (), (const)); }; +/** + * Convenience class for introducing a scoped mock loader singleton in tests, very similar to + * Runtime::ScopedLoaderSingleton. Intended usage: + * + * 1. Add `Runtime::ScopedMockLoaderSingleton runtime_` as a member of your test suite. + * 2. Set expectations on `runtime_.snapshot()`, and on `runtime_.loader()` if needed. + * + * Note: this could be implemented using ScopedLoaderSingleton directly, but it's a bit jankier + * that way. ScopedLoaderSingleton swallows the unique_ptr it's given, which makes it hard to mock. + */ +class ScopedMockLoaderSingleton { +public: + ScopedMockLoaderSingleton(); + ~ScopedMockLoaderSingleton(); + Runtime::MockLoader& loader(); + Runtime::MockSnapshot& snapshot(); + +private: + NiceMock loader_; +}; + } // namespace Runtime } // namespace Envoy diff --git a/test/server/BUILD b/test/server/BUILD index d409bcf0f2f01..fdbfe8d15d31d 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -25,6 +25,7 @@ envoy_cc_test( "//source/server:listener_lib", "//test/mocks/network:network_mocks", "//test/mocks/server:server_mocks", + "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", ], diff --git a/test/server/api_listener_test.cc b/test/server/api_listener_test.cc index f229823c59c32..dfc4582236f8f 100644 --- a/test/server/api_listener_test.cc +++ b/test/server/api_listener_test.cc @@ -8,6 +8,7 @@ #include "test/mocks/network/mocks.h" #include "test/mocks/server/mocks.h" #include "test/server/utility.h" +#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" #include "gmock/gmock.h" @@ -26,6 +27,8 @@ class ApiListenerTest : public testing::Test { NiceMock listener_factory_; NiceMock worker_factory_; std::unique_ptr listener_manager_; + // Create a runtime loader to initialize the watermark c'tor loader + TestScopedRuntime scoped_runtime; }; TEST_F(ApiListenerTest, HttpApiListener) { diff --git a/test/server/config_validation/BUILD b/test/server/config_validation/BUILD index e00f954dc3dfe..66bea5c8af5a0 100644 --- a/test/server/config_validation/BUILD +++ b/test/server/config_validation/BUILD @@ -78,6 +78,7 @@ envoy_cc_test( "//source/common/stats:isolated_store_lib", "//source/server/config_validation:api_lib", "//source/server/config_validation:dns_lib", + "//test/mocks/runtime:runtime_mocks", "//test/test_common:environment_lib", "//test/test_common:network_utility_lib", "//test/test_common:test_time_lib", @@ -93,6 +94,7 @@ envoy_cc_fuzz_test( "//source/server/config_validation:server_lib", "//source/server:proto_descriptors_lib", "//test/integration:integration_lib", + "//test/mocks/runtime:runtime_mocks", "//test/mocks/server:server_mocks", "//test/test_common:environment_lib", ] + envoy_all_extensions(), diff --git a/test/server/config_validation/config_fuzz_test.cc b/test/server/config_validation/config_fuzz_test.cc index bd40a453634a9..a0383257fb152 100644 --- a/test/server/config_validation/config_fuzz_test.cc +++ b/test/server/config_validation/config_fuzz_test.cc @@ -10,6 +10,7 @@ #include "test/fuzz/fuzz_runner.h" #include "test/integration/server.h" +#include "test/mocks/runtime/mocks.h" #include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" @@ -20,6 +21,7 @@ namespace { // Derived from //test/server:server_fuzz_test.cc, but starts the server in configuration validation // mode (quits upon validation of the given config) DEFINE_PROTO_FUZZER(const envoy::config::bootstrap::v3::Bootstrap& input) { + Runtime::ScopedMockLoaderSingleton runtime; testing::NiceMock options; TestComponentFactory component_factory; Fuzz::PerTestEnvironment test_env; diff --git a/test/server/config_validation/dispatcher_test.cc b/test/server/config_validation/dispatcher_test.cc index 3e19c50a2ff87..de82943c73541 100644 --- a/test/server/config_validation/dispatcher_test.cc +++ b/test/server/config_validation/dispatcher_test.cc @@ -9,6 +9,7 @@ #include "server/config_validation/api.h" +#include "test/mocks/runtime/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/network_utility.h" #include "test/test_common/test_time.h" @@ -35,6 +36,7 @@ class ConfigValidation : public testing::TestWithParam validation_; + Runtime::ScopedMockLoaderSingleton runtime_; }; // Simple test which creates a connection to fake upstream client. This is to test if diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 24ba7e79890ca..689db9e6660d8 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -658,6 +658,9 @@ istio istream istringstream iteratively +janky +jankier +jankiest javascript jitter jittered