diff --git a/include/envoy/http/filter.h b/include/envoy/http/filter.h index 11190bfc45c7d..9487ecdb32784 100644 --- a/include/envoy/http/filter.h +++ b/include/envoy/http/filter.h @@ -148,22 +148,30 @@ class StreamDecoderFilterCallbacks : public virtual StreamFilterCallbacks { virtual void continueDecoding() PURE; /** - * @return Buffer::InstancePtr& the currently buffered data as buffered by this filter or previous - * ones in the filter chain. May be nullptr if nothing has been buffered yet. Callers - * are free to remove, reallocate, and generally modify the buffered data. + * @return const Buffer::Instance* the currently buffered data as buffered by this filter or + * previous ones in the filter chain. May be nullptr if nothing has been buffered yet. + */ + virtual const Buffer::Instance* decodingBuffer() PURE; + + /** + * Add buffered body data. This method is used in advanced cases where returning + * StopIterationAndBuffer from decodeData() is not sufficient. * - * NOTE: For common buffering cases, there is no need for each filter to manually handle - * buffering. If decodeData() returns StopIterationAndBuffer, the filter manager will - * buffer the data passed to the callback on behalf of the filter. + * 1) If a headers only request needs to be turned into a request with a body, this method can + * be called to add body in the decodeHeaders() callback. Subsequent filters will receive + * decodeHeaders(..., false) followed by decodeData(..., true). This works both in the direct + * iteration as well as the continuation case. * - * NOTE: In complex cases, the filter may wish to manually modify the buffer. One example - * of this is switching a header only request to a request with body data. If a filter - * receives decodeHeaders(..., true), it has the option of filling decodingBuffer() with - * body data. Subsequent filters will receive decodeHeaders(..., false) followed by - * decodeData(..., true). This works both in the direct iteration as well as the - * continuation case. + * 2) If additional buffered body data needs to be added by a filter before continuation of + * data to further filters (outside of callback context). + * + * 3) If additional data needs to be added in the decodeTrailers() callback, this method can be + * called in the context of the callback. All further filters will receive decodeData(..., false) + * followed by decodeTrailers(). + * + * It is an error to call this method in any other case. */ - virtual Buffer::InstancePtr& decodingBuffer() PURE; + virtual void addDecodedData(Buffer::Instance& data) PURE; /** * Called with headers to be encoded, optionally indicating end of stream. @@ -246,22 +254,30 @@ class StreamEncoderFilterCallbacks : public virtual StreamFilterCallbacks { virtual void continueEncoding() PURE; /** - * @return Buffer::InstancePtr& the currently buffered data as buffered by this filter or previous - * ones in the filter chain. May be nullptr if nothing has been buffered yet. Callers - * are free to remove, reallocate, and generally modify the buffered data. + * @return const Buffer::Instance* the currently buffered data as buffered by this filter or + * previous ones in the filter chain. May be nullptr if nothing has been buffered yet. + */ + virtual const Buffer::Instance* encodingBuffer() PURE; + + /** + * Add buffered body data. This method is used in advanced cases where returning + * StopIterationAndBuffer from encodeData() is not sufficient. + * + * 1) If a headers only response needs to be turned into a response with a body, this method can + * be called to add body in the encodeHeaders() callback. Subsequent filters will receive + * encodeHeaders(..., false) followed by encodeData(..., true). This works both in the direct + * iteration as well as the continuation case. * - * NOTE: For common buffering cases, there is no need for each filter to manually handle - * buffering. If encodeData() returns StopIterationAndBuffer, the filter manager will - * buffer the data passed to the callback on behalf of the filter. + * 2) If additional buffered body data needs to be added by a filter before continuation of + * data to further filters (outside of callback context). * - * NOTE: In complex cases, the filter may wish to manually modify the buffer. One example - * of this is switching a header only request to a request with body data. If a filter - * receives encodeHeaders(..., true), it has the option of filling encodingBuffer() with - * body data. Subsequent filters will receive encodeHeaders(..., false) followed by - * encodeData(..., true). This works both in the direct iteration as well as the - * continuation case. - */ - virtual Buffer::InstancePtr& encodingBuffer() PURE; + * 3) If additional data needs to be added in the encodeTrailers() callback, this method can be + * called in the context of the callback. All further filters will receive encodeData(..., false) + * followed by encodeTrailers(). + * + * It is an error to call this method in any other case. + */ + virtual void addEncodedData(Buffer::Instance& data) PURE; }; /** diff --git a/source/common/dynamo/dynamo_filter.cc b/source/common/dynamo/dynamo_filter.cc index dda06863f1c11..b28dd8d134649 100644 --- a/source/common/dynamo/dynamo_filter.cc +++ b/source/common/dynamo/dynamo_filter.cc @@ -48,7 +48,7 @@ Http::FilterTrailersStatus DynamoFilter::decodeTrailers(Http::HeaderMap&) { } void DynamoFilter::onDecodeComplete(const Buffer::Instance& data) { - std::string body = buildBody(decoder_callbacks_->decodingBuffer().get(), data); + std::string body = buildBody(decoder_callbacks_->decodingBuffer(), data); if (!body.empty()) { try { Json::ObjectPtr json_body = Json::Factory::loadFromString(body); @@ -68,7 +68,7 @@ void DynamoFilter::onEncodeComplete(const Buffer::Instance& data) { uint64_t status = Http::Utility::getResponseStatus(*response_headers_); chargeBasicStats(status); - std::string body = buildBody(encoder_callbacks_->encodingBuffer().get(), data); + std::string body = buildBody(encoder_callbacks_->encodingBuffer(), data); if (!body.empty()) { try { Json::ObjectPtr json_body = Json::Factory::loadFromString(body); diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index 3ea1f14af8be7..9c427f2307244 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -189,7 +189,8 @@ class AsyncStreamImpl : public AsyncClient::Stream, Tracing::Span& activeSpan() override { return active_span_; } const std::string& downstreamAddress() override { return EMPTY_STRING; } void continueDecoding() override { NOT_IMPLEMENTED; } - Buffer::InstancePtr& decodingBuffer() override { + void addDecodedData(Buffer::Instance&) override { NOT_IMPLEMENTED; } + const Buffer::Instance* decodingBuffer() override { throw EnvoyException("buffering is not supported in streaming"); } void encodeHeaders(HeaderMapPtr&& headers, bool end_stream) override; @@ -229,7 +230,7 @@ class AsyncRequestImpl final : public AsyncClient::Request, void onReset() override; // Http::StreamDecoderFilterCallbacks - Buffer::InstancePtr& decodingBuffer() override { return request_->body(); } + const Buffer::Instance* decodingBuffer() override { return request_->body().get(); } MessagePtr request_; AsyncClient::Callbacks& callbacks_; diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 52045a617964f..10e8517877aa6 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -327,6 +327,8 @@ ConnectionManagerImpl::ActiveStream::~ActiveStream() { *this); } } + + ASSERT(state_.filter_call_state_ == 0); } void ConnectionManagerImpl::ActiveStream::addStreamDecoderFilter( @@ -482,8 +484,11 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(ActiveStreamDecoderFilte } for (; entry != decoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::DecodeHeaders)); + state_.filter_call_state_ |= FilterCallState::DecodeHeaders; FilterHeadersStatus status = (*entry)->handle_->decodeHeaders( headers, end_stream && continue_data_entry == decoder_filters_.end()); + state_.filter_call_state_ &= ~FilterCallState::DecodeHeaders; stream_log_trace("decode headers called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterHeadersCallback(status) && @@ -537,7 +542,10 @@ void ConnectionManagerImpl::ActiveStream::decodeData(ActiveStreamDecoderFilter* } for (; entry != decoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::DecodeData)); + state_.filter_call_state_ |= FilterCallState::DecodeData; FilterDataStatus status = (*entry)->handle_->decodeData(data, end_stream); + state_.filter_call_state_ &= ~FilterCallState::DecodeData; stream_log_trace("decode data called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterDataCallback(status, data)) { @@ -546,6 +554,24 @@ void ConnectionManagerImpl::ActiveStream::decodeData(ActiveStreamDecoderFilter* } } +void ConnectionManagerImpl::ActiveStream::addDecodedData(ActiveStreamDecoderFilter& filter, + Buffer::Instance& data) { + if (state_.filter_call_state_ == 0 || + (state_.filter_call_state_ & FilterCallState::DecodeHeaders)) { + // If no call is happening or we are in the decode headers callback, buffer the data. Inline + // processing happens in the decodeHeaders() callback if necessary. + filter.commonHandleBufferData(data); + } else if (state_.filter_call_state_ & FilterCallState::DecodeTrailers) { + // In this case we need to inline dispatch the data to further filters. If those filters + // choose to buffer/stop iteration that's fine. + decodeData(&filter, data, false); + } else { + // TODO(mattklein123): Formalize error handling for filters and add tests. Should probably + // throw an exception here. + NOT_IMPLEMENTED; + } +} + void ConnectionManagerImpl::ActiveStream::decodeTrailers(HeaderMapPtr&& trailers) { request_trailers_ = std::move(trailers); ASSERT(!state_.remote_complete_); @@ -568,7 +594,10 @@ void ConnectionManagerImpl::ActiveStream::decodeTrailers(ActiveStreamDecoderFilt } for (; entry != decoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::DecodeTrailers)); + state_.filter_call_state_ |= FilterCallState::DecodeTrailers; FilterTrailersStatus status = (*entry)->handle_->decodeTrailers(trailers); + state_.filter_call_state_ &= ~FilterCallState::DecodeTrailers; stream_log_trace("decode trailers called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterTrailersCallback(status)) { @@ -609,8 +638,11 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ActiveStreamEncoderFilte std::list::iterator continue_data_entry = encoder_filters_.end(); for (; entry != encoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeHeaders)); + state_.filter_call_state_ |= FilterCallState::EncodeHeaders; FilterHeadersStatus status = (*entry)->handle_->encodeHeaders( headers, end_stream && continue_data_entry == encoder_filters_.end()); + state_.filter_call_state_ &= ~FilterCallState::EncodeHeaders; stream_log_trace("encode headers called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterHeadersCallback(status)) { @@ -690,11 +722,32 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ActiveStreamEncoderFilte } } +void ConnectionManagerImpl::ActiveStream::addEncodedData(ActiveStreamEncoderFilter& filter, + Buffer::Instance& data) { + if (state_.filter_call_state_ == 0 || + (state_.filter_call_state_ & FilterCallState::EncodeHeaders)) { + // If no call is happening or we are in the decode headers callback, buffer the data. Inline + // processing happens in the decodeHeaders() callback if necessary. + filter.commonHandleBufferData(data); + } else if (state_.filter_call_state_ & FilterCallState::EncodeTrailers) { + // In this case we need to inline dispatch the data to further filters. If those filters + // choose to buffer/stop iteration that's fine. + encodeData(&filter, data, false); + } else { + // TODO(mattklein123): Formalize error handling for filters and add tests. Should probably + // throw an exception here. + NOT_IMPLEMENTED; + } +} + void ConnectionManagerImpl::ActiveStream::encodeData(ActiveStreamEncoderFilter* filter, Buffer::Instance& data, bool end_stream) { std::list::iterator entry = commonEncodePrefix(filter, end_stream); for (; entry != encoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeData)); + state_.filter_call_state_ |= FilterCallState::EncodeData; FilterDataStatus status = (*entry)->handle_->encodeData(data, end_stream); + state_.filter_call_state_ &= ~FilterCallState::EncodeData; stream_log_trace("encode data called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterDataCallback(status, data)) { @@ -714,7 +767,10 @@ void ConnectionManagerImpl::ActiveStream::encodeTrailers(ActiveStreamEncoderFilt HeaderMap& trailers) { std::list::iterator entry = commonEncodePrefix(filter, true); for (; entry != encoder_filters_.end(); entry++) { + ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeTrailers)); + state_.filter_call_state_ |= FilterCallState::EncodeTrailers; FilterTrailersStatus status = (*entry)->handle_->encodeTrailers(trailers); + state_.filter_call_state_ &= ~FilterCallState::EncodeTrailers; stream_log_trace("encode trailers called: filter={} status={}", *this, static_cast((*entry).get()), static_cast(status)); if (!(*entry)->commonHandleAfterTrailersCallback(status)) { @@ -772,6 +828,7 @@ void ConnectionManagerImpl::ActiveStreamFilterBase::addResetStreamCallback( } void ConnectionManagerImpl::ActiveStreamFilterBase::commonContinue() { + // TODO(mattklein123): Raise an error if this is called during a callback. stream_log_trace("continuing filter chain: filter={}", parent_, static_cast(this)); ASSERT(stopped_); stopped_ = false; @@ -895,6 +952,10 @@ Router::RouteConstSharedPtr ConnectionManagerImpl::ActiveStreamFilterBase::route return parent_.cached_route_.value(); } +void ConnectionManagerImpl::ActiveStreamDecoderFilter::addDecodedData(Buffer::Instance& data) { + parent_.addDecodedData(*this, data); +} + void ConnectionManagerImpl::ActiveStreamDecoderFilter::continueDecoding() { commonContinue(); } void ConnectionManagerImpl::ActiveStreamDecoderFilter::encodeHeaders(HeaderMapPtr&& headers, @@ -913,6 +974,10 @@ void ConnectionManagerImpl::ActiveStreamDecoderFilter::encodeTrailers(HeaderMapP parent_.encodeTrailers(nullptr, *parent_.response_trailers_); } +void ConnectionManagerImpl::ActiveStreamEncoderFilter::addEncodedData(Buffer::Instance& data) { + return parent_.addEncodedData(*this, data); +} + void ConnectionManagerImpl::ActiveStreamEncoderFilter::continueEncoding() { commonContinue(); } void ConnectionManagerImpl::ActiveStreamFilterBase::resetStream() { diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h index a5ce265f4fc74..497004eb6b907 100644 --- a/source/common/http/conn_manager_impl.h +++ b/source/common/http/conn_manager_impl.h @@ -312,8 +312,11 @@ class ConnectionManagerImpl : Logger::Loggable, const HeaderMapPtr& trailers() override { return parent_.request_trailers_; } // Http::StreamDecoderFilterCallbacks + void addDecodedData(Buffer::Instance& data) override; void continueDecoding() override; - Buffer::InstancePtr& decodingBuffer() override { return parent_.buffered_request_data_; } + const Buffer::Instance* decodingBuffer() override { + return parent_.buffered_request_data_.get(); + } void encodeHeaders(HeaderMapPtr&& headers, bool end_stream) override; void encodeData(Buffer::Instance& data, bool end_stream) override; void encodeTrailers(HeaderMapPtr&& trailers) override; @@ -345,8 +348,11 @@ class ConnectionManagerImpl : Logger::Loggable, const HeaderMapPtr& trailers() override { return parent_.response_trailers_; } // Http::StreamEncoderFilterCallbacks + void addEncodedData(Buffer::Instance& data) override; void continueEncoding() override; - Buffer::InstancePtr& encodingBuffer() override { return parent_.buffered_response_data_; } + const Buffer::Instance* encodingBuffer() override { + return parent_.buffered_response_data_.get(); + } StreamEncoderFilterSharedPtr handle_; }; @@ -371,9 +377,11 @@ class ConnectionManagerImpl : Logger::Loggable, commonEncodePrefix(ActiveStreamEncoderFilter* filter, bool end_stream); uint64_t connectionId(); Ssl::Connection* ssl(); + void addDecodedData(ActiveStreamDecoderFilter& filter, Buffer::Instance& data); void decodeHeaders(ActiveStreamDecoderFilter* filter, HeaderMap& headers, bool end_stream); void decodeData(ActiveStreamDecoderFilter* filter, Buffer::Instance& data, bool end_stream); void decodeTrailers(ActiveStreamDecoderFilter* filter, HeaderMap& trailers); + void addEncodedData(ActiveStreamEncoderFilter& filter, Buffer::Instance& data); void encodeHeaders(ActiveStreamEncoderFilter* filter, HeaderMap& headers, bool end_stream); void encodeData(ActiveStreamEncoderFilter* filter, Buffer::Instance& data, bool end_stream); void encodeTrailers(ActiveStreamEncoderFilter* filter, HeaderMap& trailers); @@ -398,11 +406,25 @@ class ConnectionManagerImpl : Logger::Loggable, virtual Tracing::OperationName operationName() const override; virtual const std::vector& requestHeadersForTags() const override; - // All state for the stream. Put here for readability. We could move this to a bit field - // eventually if we want. + /** + * Flags that keep track of which filter calls are currently in progress. + */ + // clang-format off + struct FilterCallState { + static constexpr uint32_t DecodeHeaders = 0x01; + static constexpr uint32_t DecodeData = 0x02; + static constexpr uint32_t DecodeTrailers = 0x04; + static constexpr uint32_t EncodeHeaders = 0x08; + static constexpr uint32_t EncodeData = 0x10; + static constexpr uint32_t EncodeTrailers = 0x20; + }; + // clang-format on + + // All state for the stream. Put here for readability. struct State { State() : remote_complete_(false), local_complete_(false), saw_connection_close_(false) {} + uint32_t filter_call_state_{0}; bool remote_complete_ : 1; bool local_complete_ : 1; bool saw_connection_close_ : 1; diff --git a/test/common/dynamo/dynamo_filter_test.cc b/test/common/dynamo/dynamo_filter_test.cc index d1f5cad1c70e1..0ec65d300108c 100644 --- a/test/common/dynamo/dynamo_filter_test.cc +++ b/test/common/dynamo/dynamo_filter_test.cc @@ -115,7 +115,7 @@ TEST_F(DynamoFilterTest, handleErrorTypeTableMissing) { error_data->add("}", 1); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->encodeData(*error_data, false)); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillRepeatedly(ReturnRef(error_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillRepeatedly(Return(error_data.get())); EXPECT_CALL(stats_, counter("prefix.dynamodb.invalid_resp_body")); EXPECT_CALL(stats_, counter("prefix.dynamodb.operation_missing")); EXPECT_CALL(stats_, counter("prefix.dynamodb.table_missing")); @@ -184,7 +184,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTables) { buffer->add(buffer_content); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(Return(buffer.get())); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_headers)); Http::TestHeaderMapImpl response_headers{{":status", "200"}}; @@ -223,7 +223,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesUnprocessedKeys) { buffer->add(buffer_content); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(Return(buffer.get())); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_headers)); Http::TestHeaderMapImpl response_headers{{":status", "200"}}; @@ -256,9 +256,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesUnprocessedKeys) { EXPECT_CALL(stats_, counter("prefix.dynamodb.error.table_1.BatchFailureUnprocessedKeys")); EXPECT_CALL(stats_, counter("prefix.dynamodb.error.table_2.BatchFailureUnprocessedKeys")); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()) - .Times(1) - .WillRepeatedly(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillRepeatedly(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } @@ -281,7 +279,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesNoUnprocessedKeys) { buffer->add(buffer_content); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(Return(buffer.get())); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_headers)); Http::TestHeaderMapImpl response_headers{{":status", "200"}}; @@ -310,7 +308,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesNoUnprocessedKeys) { )EOF"; response_data->add(response_content); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } @@ -333,7 +331,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesInvalidResponseBody) { buffer->add(buffer_content); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(Return(buffer.get())); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_headers)); Http::TestHeaderMapImpl response_headers{{":status", "200"}}; @@ -366,7 +364,7 @@ TEST_F(DynamoFilterTest, BatchMultipleTablesInvalidResponseBody) { response_data->add("}", 1); EXPECT_CALL(stats_, counter("prefix.dynamodb.invalid_resp_body")); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } @@ -377,7 +375,7 @@ TEST_F(DynamoFilterTest, bothOperationAndTableCorrect) { Buffer::InstancePtr buffer(new Buffer::OwnedImpl()); std::string buffer_content = "{\"TableName\":\"locations\""; buffer->add(buffer_content); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(Return(buffer.get())); Buffer::OwnedImpl data; data.add("}", 1); @@ -432,7 +430,7 @@ TEST_F(DynamoFilterTest, PartitionIdStats) { Buffer::InstancePtr buffer(new Buffer::OwnedImpl()); std::string buffer_content = "{\"TableName\":\"locations\""; buffer->add(buffer_content); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + ON_CALL(decoder_callbacks_, decodingBuffer()).WillByDefault(Return(buffer.get())); Buffer::OwnedImpl data; data.add("}", 1); @@ -486,7 +484,7 @@ TEST_F(DynamoFilterTest, PartitionIdStats) { response_data->add(response_content); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } @@ -504,7 +502,7 @@ TEST_F(DynamoFilterTest, NoPartitionIdStatsForMultipleTables) { } )EOF"; buffer->add(buffer_content); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + ON_CALL(decoder_callbacks_, decodingBuffer()).WillByDefault(Return(buffer.get())); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); @@ -550,7 +548,7 @@ TEST_F(DynamoFilterTest, NoPartitionIdStatsForMultipleTables) { response_data->add(response_content); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } @@ -567,7 +565,7 @@ TEST_F(DynamoFilterTest, PartitionIdStatsForSingleTableBatchOperation) { } )EOF"; buffer->add(buffer_content); - EXPECT_CALL(decoder_callbacks_, decodingBuffer()).WillRepeatedly(ReturnRef(buffer)); + ON_CALL(decoder_callbacks_, decodingBuffer()).WillByDefault(Return(buffer.get())); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, false)); EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(*buffer, false)); @@ -623,7 +621,7 @@ TEST_F(DynamoFilterTest, PartitionIdStatsForSingleTableBatchOperation) { response_data->add(response_content); - EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(ReturnRef(response_data)); + EXPECT_CALL(encoder_callbacks_, encodingBuffer()).WillOnce(Return(response_data.get())); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(empty_data, true)); } diff --git a/test/common/grpc/http1_bridge_filter_test.cc b/test/common/grpc/http1_bridge_filter_test.cc index 20ee6cbc9c9cb..5dccdd2fb3d87 100644 --- a/test/common/grpc/http1_bridge_filter_test.cc +++ b/test/common/grpc/http1_bridge_filter_test.cc @@ -141,7 +141,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, HandlingNormalResponse) { EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(request_trailers)); Buffer::InstancePtr buffer(new Buffer::OwnedImpl("hello")); - ON_CALL(encoder_callbacks_, encodingBuffer()).WillByDefault(ReturnRef(buffer)); + ON_CALL(encoder_callbacks_, encodingBuffer()).WillByDefault(Return(buffer.get())); Http::TestHeaderMapImpl response_headers{{":status", "200"}}; EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index 98c05828908fc..ce5bbdff8b16d 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -34,10 +34,12 @@ #include "gtest/gtest.h" using testing::_; +using testing::AtLeast; using testing::InSequence; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; +using testing::Ref; using testing::Return; using testing::ReturnRef; using testing::Sequence; @@ -56,17 +58,21 @@ class HttpConnectionManagerImplTest : public Test, public ConnectionManagerConfi HttpConnectionManagerImplTest() : access_log_path_("dummy_path"), - access_logs_{Http::AccessLog::InstanceSharedPtr{new Http::AccessLog::InstanceImpl( + access_logs_{AccessLog::InstanceSharedPtr{new AccessLog::InstanceImpl( access_log_path_, {}, AccessLog::AccessLogFormatUtils::defaultAccessLogFormatter(), log_manager_)}}, - codec_(new NiceMock()), + codec_(new NiceMock()), stats_{{ALL_HTTP_CONN_MAN_STATS(POOL_COUNTER(fake_stats_), POOL_GAUGE(fake_stats_), POOL_TIMER(fake_stats_))}, "", fake_stats_}, tracing_stats_{CONN_MAN_TRACING_STATS(POOL_COUNTER(fake_stats_))} { - tracing_config_.reset(new Http::TracingConnectionManagerConfig( - {Tracing::OperationName::Ingress, {Http::LowerCaseString(":method")}})); + tracing_config_.reset(new TracingConnectionManagerConfig( + {Tracing::OperationName::Ingress, {LowerCaseString(":method")}})); + + // response_encoder_ is not a NiceMock on purpose. This prevents complaining about this + // method only. + EXPECT_CALL(response_encoder_, getStream()).Times(AtLeast(0)); } ~HttpConnectionManagerImplTest() { @@ -86,40 +92,68 @@ class HttpConnectionManagerImplTest : public Test, public ConnectionManagerConfi conn_manager_->initializeReadFilterCallbacks(filter_callbacks_); } - // Http::ConnectionManagerConfig - const std::list& accessLogs() override { - return access_logs_; + void setupFilterChain(int num_decoder_filters, int num_encoder_filters) { + // NOTE: The length/repitition in this routine allows InSequence to work correctly in an outer + // scope. + for (int i = 0; i < num_decoder_filters; i++) { + decoder_filters_.push_back(new MockStreamDecoderFilter()); + } + + for (int i = 0; i < num_encoder_filters; i++) { + encoder_filters_.push_back(new MockStreamEncoderFilter()); + } + + EXPECT_CALL(filter_factory_, createFilterChain(_)) + .WillOnce(Invoke([num_decoder_filters, num_encoder_filters, this]( + FilterChainFactoryCallbacks& callbacks) -> void { + for (int i = 0; i < num_decoder_filters; i++) { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filters_[i]}); + } + + for (int i = 0; i < num_encoder_filters; i++) { + callbacks.addStreamEncoderFilter(StreamEncoderFilterSharedPtr{encoder_filters_[i]}); + } + })); + + for (int i = 0; i < num_decoder_filters; i++) { + EXPECT_CALL(*decoder_filters_[i], setDecoderFilterCallbacks(_)); + } + + for (int i = 0; i < num_encoder_filters; i++) { + EXPECT_CALL(*encoder_filters_[i], setEncoderFilterCallbacks(_)); + } } + + // Http::ConnectionManagerConfig + const std::list& accessLogs() override { return access_logs_; } ServerConnectionPtr createCodec(Network::Connection&, const Buffer::Instance&, ServerConnectionCallbacks&) override { return ServerConnectionPtr{codec_}; } - Http::DateProvider& dateProvider() override { return date_provider_; } + DateProvider& dateProvider() override { return date_provider_; } std::chrono::milliseconds drainTimeout() override { return std::chrono::milliseconds(100); } FilterChainFactory& filterFactory() override { return filter_factory_; } bool generateRequestId() override { return true; } const Optional& idleTimeout() override { return idle_timeout_; } Router::RouteConfigProvider& routeConfigProvider() override { return route_config_provider_; } const std::string& serverName() override { return server_name_; } - Http::ConnectionManagerStats& stats() override { return stats_; } - Http::ConnectionManagerTracingStats& tracingStats() override { return tracing_stats_; } + ConnectionManagerStats& stats() override { return stats_; } + ConnectionManagerTracingStats& tracingStats() override { return tracing_stats_; } bool useRemoteAddress() override { return use_remote_address_; } const Network::Address::Instance& localAddress() override { return local_address_; } const Optional& userAgent() override { return user_agent_; } - const Http::TracingConnectionManagerConfig* tracingConfig() override { - return tracing_config_.get(); - } + const TracingConnectionManagerConfig* tracingConfig() override { return tracing_config_.get(); } NiceMock tracer_; NiceMock runtime_; Event::MockDispatcher dispatcher_; NiceMock<::AccessLog::MockAccessLogManager> log_manager_; std::string access_log_path_; - std::list access_logs_; + std::list access_logs_; Stats::IsolatedStoreImpl fake_stats_; NiceMock filter_callbacks_; - Http::MockServerConnection* codec_; - NiceMock filter_factory_; + MockServerConnection* codec_; + NiceMock filter_factory_; ConnectionManagerStats stats_; ConnectionManagerTracingStats tracing_stats_; NiceMock drain_close_; @@ -133,16 +167,20 @@ class HttpConnectionManagerImplTest : public Test, public ConnectionManagerConfi NiceMock random_; std::unique_ptr ssl_connection_; RouteConfigProvider route_config_provider_; - Http::TracingConnectionManagerConfigPtr tracing_config_; - Http::SlowDateProviderImpl date_provider_; + TracingConnectionManagerConfigPtr tracing_config_; + SlowDateProviderImpl date_provider_; + + // TODO(mattklein123): Not all tests have been converted over to better setup. Convert the rest. + MockStreamEncoder response_encoder_; + std::vector decoder_filters_; + std::vector encoder_filters_; }; TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponse) { setup(false, "envoy-custom-server"); // Store the basic request encoder during filter chain setup. - std::shared_ptr filter( - new NiceMock()); + std::shared_ptr filter(new NiceMock()); EXPECT_CALL(filter->reset_stream_called_, ready()).Times(0); EXPECT_CALL(*filter, decodeHeaders(_, true)) @@ -161,15 +199,15 @@ TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponse) { EXPECT_CALL(filter_factory_, createFilterChain(_)) .Times(2) - .WillRepeatedly(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) + .WillRepeatedly(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(filter); })); EXPECT_CALL(filter_callbacks_.connection_.dispatcher_, deferredDelete_(_)).Times(2); // When dispatch is called on the codec, we pretend to get a new stream and then fire a headers // only request into it. Then we respond into the filter. - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .Times(2) .WillRepeatedly(Invoke([&](Buffer::Instance& data) -> void { @@ -177,15 +215,15 @@ TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponse) { // Test not charging stats on the second call. if (data.length() == 4) { - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), true); } else { - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":authority", "host"}, {":path", "/healthcheck"}}}; decoder->decodeHeaders(std::move(headers), true); } - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); // Drain 2 so that on the 2nd iteration we will hit zero. @@ -202,19 +240,19 @@ TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponse) { TEST_F(HttpConnectionManagerImplTest, InvalidPath) { setup(false, ""); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":authority", "host"}, {":path", "http://api.lyft.com/"}}}; decoder->decodeHeaders(std::move(headers), true); data.drain(4); })); EXPECT_CALL(encoder, encodeHeaders(_, true)) - .WillOnce(Invoke([](const Http::HeaderMap& headers, bool) + .WillOnce(Invoke([](const HeaderMap& headers, bool) -> void { EXPECT_STREQ("404", headers.Status()->value().c_str()); })); Buffer::OwnedImpl fake_input("1234"); @@ -226,8 +264,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { NiceMock* span = new NiceMock(); EXPECT_CALL(tracer_, startSpan_(_, _, _)) - .WillOnce(Invoke([&](const Tracing::Config& config, const Http::HeaderMap&, - const Http::AccessLog::RequestInfo&) -> Tracing::Span* { + .WillOnce(Invoke([&](const Tracing::Config& config, const HeaderMap&, + const AccessLog::RequestInfo&) -> Tracing::Span* { EXPECT_EQ(Tracing::OperationName::Ingress, config.operationName()); return span; @@ -241,27 +279,26 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) .WillOnce(Return(true)); - std::shared_ptr filter( - new NiceMock()); + std::shared_ptr filter(new NiceMock()); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillRepeatedly(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) + .WillRepeatedly(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(filter); })); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillRepeatedly(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":method", "GET"}, {":authority", "host"}, {":path", "/"}, {"x-request-id", "125a4afb-6f55-a4ba-ad80-413f09f48a28"}}}; decoder->decodeHeaders(std::move(headers), true); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); filter->callbacks_->activeSpan().setTag("service-cluster", "scoobydoo"); @@ -278,38 +315,36 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { TEST_F(HttpConnectionManagerImplTest, TestAccessLog) { setup(false, ""); - std::shared_ptr filter( - new NiceMock()); - std::shared_ptr handler( - new NiceMock()); + std::shared_ptr filter(new NiceMock()); + std::shared_ptr handler(new NiceMock()); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(filter); callbacks.addAccessLogHandler(handler); })); EXPECT_CALL(*handler, log(_, _, _)) - .WillOnce(Invoke([](const Http::HeaderMap*, const Http::HeaderMap*, - const Http::AccessLog::RequestInfo& request_info) { - EXPECT_TRUE(request_info.responseCode().valid()); - EXPECT_EQ(request_info.responseCode().value(), uint32_t(200)); - })); - - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + .WillOnce(Invoke( + [](const HeaderMap*, const HeaderMap*, const AccessLog::RequestInfo& request_info) { + EXPECT_TRUE(request_info.responseCode().valid()); + EXPECT_EQ(request_info.responseCode().value(), uint32_t(200)); + })); + + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillRepeatedly(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":method", "GET"}, {":authority", "host"}, {":path", "/"}, {"x-request-id", "125a4afb-6f55-a4ba-ad80-413f09f48a28"}}}; decoder->decodeHeaders(std::move(headers), true); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); data.drain(4); @@ -329,27 +364,26 @@ TEST_F(HttpConnectionManagerImplTest, DoNotStartSpanIfTracingIsNotEnabled) { ON_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) .WillByDefault(Return(true)); - std::shared_ptr filter( - new NiceMock()); + std::shared_ptr filter(new NiceMock()); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillRepeatedly(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) + .WillRepeatedly(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(filter); })); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillRepeatedly(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":method", "GET"}, {":authority", "host"}, {":path", "/"}, {"x-request-id", "125a4afb-6f55-a4ba-ad80-413f09f48a28"}}}; decoder->decodeHeaders(std::move(headers), true); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); data.drain(4); @@ -370,11 +404,10 @@ TEST_F(HttpConnectionManagerImplTest, StartSpanOnlyHealthCheckRequest) { EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) .WillOnce(Return(true)); - std::shared_ptr filter( - new NiceMock()); + std::shared_ptr filter(new NiceMock()); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillRepeatedly(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) + .WillRepeatedly(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(filter); })); EXPECT_CALL(*filter, decodeHeaders(_, true)) @@ -383,20 +416,20 @@ TEST_F(HttpConnectionManagerImplTest, StartSpanOnlyHealthCheckRequest) { return FilterHeadersStatus::StopIteration; })); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillRepeatedly(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ + HeaderMapPtr headers{ new TestHeaderMapImpl{{":method", "GET"}, {":authority", "host"}, {":path", "/healthcheck"}, {"x-request-id", "125a4afb-6f55-94ba-ad80-413f09f48a28"}}}; decoder->decodeHeaders(std::move(headers), true); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); data.drain(4); @@ -417,19 +450,18 @@ TEST_F(HttpConnectionManagerImplTest, StartSpanOnlyHealthCheckRequest) { TEST_F(HttpConnectionManagerImplTest, NoPath) { setup(false, ""); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance& data) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{ - new TestHeaderMapImpl{{":authority", "host"}, {":method", "CONNECT"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":method", "CONNECT"}}}; decoder->decodeHeaders(std::move(headers), true); data.drain(4); })); EXPECT_CALL(encoder, encodeHeaders(_, true)) - .WillOnce(Invoke([](const Http::HeaderMap& headers, bool) + .WillOnce(Invoke([](const HeaderMap& headers, bool) -> void { EXPECT_STREQ("404", headers.Status()->value().c_str()); })); Buffer::OwnedImpl fake_input("1234"); @@ -439,10 +471,10 @@ TEST_F(HttpConnectionManagerImplTest, NoPath) { TEST_F(HttpConnectionManagerImplTest, DrainClose) { setup(true, ""); - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); EXPECT_CALL(*filter, decodeHeaders(_, true)) @@ -452,19 +484,19 @@ TEST_F(HttpConnectionManagerImplTest, DrainClose) { return FilterHeadersStatus::StopIteration; })); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), true); })); Buffer::OwnedImpl fake_input; conn_manager_->onData(fake_input); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "300"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "300"}}}; Event::MockTimer* drain_timer = new Event::MockTimer(&filter_callbacks_.connection_.dispatcher_); EXPECT_CALL(*drain_timer, enableTimer(_)); EXPECT_CALL(drain_close_, drainClose()).WillOnce(Return(true)); @@ -484,32 +516,32 @@ TEST_F(HttpConnectionManagerImplTest, DrainClose) { TEST_F(HttpConnectionManagerImplTest, ResponseBeforeRequestComplete) { setup(false, "envoy-server-test"); - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); EXPECT_CALL(*filter, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); })); Buffer::OwnedImpl fake_input; conn_manager_->onData(fake_input); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; EXPECT_CALL(filter->reset_stream_called_, ready()); EXPECT_CALL(filter_callbacks_.connection_, close(Network::ConnectionCloseType::FlushWrite)); EXPECT_CALL(encoder, encodeHeaders(_, true)) - .WillOnce(Invoke([](const Http::HeaderMap& headers, bool) -> void { + .WillOnce(Invoke([](const HeaderMap& headers, bool) -> void { EXPECT_NE(nullptr, headers.Server()); EXPECT_STREQ("envoy-server-test", headers.Server()->value().c_str()); })); @@ -522,22 +554,22 @@ TEST_F(HttpConnectionManagerImplTest, ResponseStartBeforeRequestComplete) { // This is like ResponseBeforeRequestComplete, but it tests the case where we start the reply // before the request completes, but don't finish the reply until after the request completes. - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); EXPECT_CALL(*filter, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); // Start the request - Http::StreamDecoder* decoder = nullptr; - NiceMock encoder; + StreamDecoder* decoder = nullptr; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); })); @@ -545,9 +577,9 @@ TEST_F(HttpConnectionManagerImplTest, ResponseStartBeforeRequestComplete) { conn_manager_->onData(fake_input); // Start the response - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; EXPECT_CALL(encoder, encodeHeaders(_, false)) - .WillOnce(Invoke([](const Http::HeaderMap& headers, bool) -> void { + .WillOnce(Invoke([](const HeaderMap& headers, bool) -> void { EXPECT_NE(nullptr, headers.Server()); EXPECT_STREQ("", headers.Server()->value().c_str()); })); @@ -571,13 +603,13 @@ TEST_F(HttpConnectionManagerImplTest, ResponseStartBeforeRequestComplete) { TEST_F(HttpConnectionManagerImplTest, DownstreamDisconnect) { setup(false, ""); - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); - NiceMock encoder; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance& data) -> void { conn_manager_->newStream(encoder); @@ -597,10 +629,10 @@ TEST_F(HttpConnectionManagerImplTest, DownstreamDisconnect) { TEST_F(HttpConnectionManagerImplTest, DownstreamProtocolError) { setup(false, ""); - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); // A protocol exception should result in reset of the streams followed by a local close. @@ -609,7 +641,7 @@ TEST_F(HttpConnectionManagerImplTest, DownstreamProtocolError) { EXPECT_CALL(filter_callbacks_.connection_, close(Network::ConnectionCloseType::FlushWrite)) .InSequence(s); - NiceMock encoder; + NiceMock encoder; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { conn_manager_->newStream(encoder); @@ -643,18 +675,18 @@ TEST_F(HttpConnectionManagerImplTest, IdleTimeout) { EXPECT_CALL(*idle_timer, enableTimer(_)); setup(false, ""); - Http::MockStreamDecoderFilter* filter = new NiceMock(); + MockStreamDecoderFilter* filter = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{filter}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{filter}); })); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; + NiceMock encoder; + StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); Buffer::OwnedImpl fake_data("hello"); @@ -663,16 +695,16 @@ TEST_F(HttpConnectionManagerImplTest, IdleTimeout) { EXPECT_CALL(*idle_timer, disableTimer()); EXPECT_CALL(*filter, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); EXPECT_CALL(*filter, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationNoBuffer)); + .WillOnce(Return(FilterDataStatus::StopIterationNoBuffer)); // Kick off the incoming data. Buffer::OwnedImpl fake_input("1234"); conn_manager_->onData(fake_input); EXPECT_CALL(*idle_timer, enableTimer(_)); - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; filter->callbacks_->encodeHeaders(std::move(response_headers), true); Event::MockTimer* drain_timer = new Event::MockTimer(&filter_callbacks_.connection_.dispatcher_); @@ -691,25 +723,25 @@ TEST_F(HttpConnectionManagerImplTest, IdleTimeout) { TEST_F(HttpConnectionManagerImplTest, IntermediateBufferingEarlyResponse) { setup(false, ""); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); + MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); + MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filter1}); + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filter2}); })); EXPECT_CALL(*decoder_filter1, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); EXPECT_CALL(*decoder_filter1, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; + NiceMock encoder; + StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); Buffer::OwnedImpl fake_data("hello"); @@ -722,11 +754,11 @@ TEST_F(HttpConnectionManagerImplTest, IntermediateBufferingEarlyResponse) { // Mimic a decoder filter that trapped data and now sends on the headers. EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(Invoke([&](Http::HeaderMap&, bool) -> Http::FilterHeadersStatus { + .WillOnce(Invoke([&](HeaderMap&, bool) -> FilterHeadersStatus { // Now filter 2 will send a complete response. - Http::HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; + HeaderMapPtr response_headers{new TestHeaderMapImpl{{":status", "200"}}}; decoder_filter2->callbacks_->encodeHeaders(std::move(response_headers), true); - return Http::FilterHeadersStatus::StopIteration; + return FilterHeadersStatus::StopIteration; })); // Response is already complete so we drop buffered body data when we continue. @@ -737,23 +769,23 @@ TEST_F(HttpConnectionManagerImplTest, IntermediateBufferingEarlyResponse) { TEST_F(HttpConnectionManagerImplTest, DoubleBuffering) { setup(false, ""); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter3 = new NiceMock(); + MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); + MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); + MockStreamDecoderFilter* decoder_filter3 = new NiceMock(); EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter3}); + .WillOnce(Invoke([&](FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filter1}); + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filter2}); + callbacks.addStreamDecoderFilter(StreamDecoderFilterSharedPtr{decoder_filter3}); })); EXPECT_CALL(*decoder_filter1, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); EXPECT_CALL(*decoder_filter1, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; + NiceMock encoder; + StreamDecoder* decoder = nullptr; // The data will get moved so we need to have a copy to compare against. Buffer::OwnedImpl fake_data("hello"); @@ -761,7 +793,7 @@ TEST_F(HttpConnectionManagerImplTest, DoubleBuffering) { EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); decoder->decodeData(fake_data, true); })); @@ -772,230 +804,233 @@ TEST_F(HttpConnectionManagerImplTest, DoubleBuffering) { // Continue iteration and stop and buffer on the 2nd filter. EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); EXPECT_CALL(*decoder_filter2, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); decoder_filter1->callbacks_->continueDecoding(); // Continue iteration. We expect the 3rd filter to not receive double data but for the buffered // data to have been kept inline as it moves through. EXPECT_CALL(*decoder_filter3, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); + .WillOnce(Return(FilterHeadersStatus::StopIteration)); EXPECT_CALL(*decoder_filter3, decodeData(BufferEqual(&fake_data_copy), true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationNoBuffer)); + .WillOnce(Return(FilterDataStatus::StopIterationNoBuffer)); decoder_filter2->callbacks_->continueDecoding(); } TEST_F(HttpConnectionManagerImplTest, ZeroByteDataFiltering) { + InSequence s; setup(false, ""); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); - EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); - })); - - EXPECT_CALL(*decoder_filter1, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); - - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; + StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { - decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + decoder = &conn_manager_->newStream(response_encoder_); + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); })); + setupFilterChain(2, 0); + + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + // Kick off the incoming data. Buffer::OwnedImpl fake_input("1234"); conn_manager_->onData(fake_input); // Continue headers only of filter 1. - EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); - decoder_filter1->callbacks_->continueDecoding(); + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + decoder_filters_[0]->callbacks_->continueDecoding(); // Stop zero byte data. - EXPECT_CALL(*decoder_filter1, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); + EXPECT_CALL(*decoder_filters_[0], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); Buffer::OwnedImpl zero; decoder->decodeData(zero, true); // Continue. - EXPECT_CALL(*decoder_filter2, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationNoBuffer)); - decoder_filter1->callbacks_->continueDecoding(); + EXPECT_CALL(*decoder_filters_[1], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::StopIterationNoBuffer)); + decoder_filters_[0]->callbacks_->continueDecoding(); } -TEST_F(HttpConnectionManagerImplTest, FilterAddBodyInline) { +TEST_F(HttpConnectionManagerImplTest, FilterAddBodyInTrailersCallback) { InSequence s; - setup(false, ""); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { - decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; - decoder->decodeHeaders(std::move(headers), true); - })); + StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_); + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + decoder->decodeHeaders(std::move(headers), false); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter1 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter2 = new NiceMock(); - EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter1}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter2}); - })); + Buffer::OwnedImpl fake_data("hello"); + decoder->decodeData(fake_data, false); - EXPECT_CALL(*decoder_filter1, decodeHeaders(_, true)) - .WillOnce(InvokeWithoutArgs([&]() -> Http::FilterHeadersStatus { - decoder_filter1->callbacks_->decodingBuffer().reset(new Buffer::OwnedImpl("hello")); - return Http::FilterHeadersStatus::Continue; + HeaderMapPtr trailers{new TestHeaderMapImpl{{"foo", "bar"}}}; + decoder->decodeTrailers(std::move(trailers)); })); - EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::StopIteration; })); - - EXPECT_CALL(*decoder_filter2, decodeData(_, true)) - .WillOnce(InvokeWithoutArgs([&]() -> Http::FilterDataStatus { - return Http::FilterDataStatus::StopIterationAndBuffer; + setupFilterChain(2, 2); + + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + EXPECT_CALL(*decoder_filters_[0], decodeData(_, false)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(*decoder_filters_[1], decodeData(_, false)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); + Buffer::OwnedImpl trailers_data("hello"); + EXPECT_CALL(*decoder_filters_[0], decodeTrailers(_)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterTrailersStatus { + decoder_filters_[0]->callbacks_->addDecodedData(trailers_data); + return FilterTrailersStatus::Continue; })); + EXPECT_CALL(*decoder_filters_[1], decodeData(Ref(trailers_data), false)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); + EXPECT_CALL(*decoder_filters_[1], decodeTrailers(_)) + .WillOnce(Return(FilterTrailersStatus::StopIteration)); // Kick off the incoming data. Buffer::OwnedImpl fake_input("1234"); conn_manager_->onData(fake_input); - EXPECT_CALL(*encoder_filter1, encodeHeaders(_, true)) - .WillOnce(InvokeWithoutArgs([&]() -> Http::FilterHeadersStatus { - encoder_filter1->callbacks_->encodingBuffer().reset(new Buffer::OwnedImpl("hello")); - return Http::FilterHeadersStatus::Continue; - })); + EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeHeaders(_, false)); - EXPECT_CALL(*encoder_filter2, encodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::Continue; })); + decoder_filters_[1]->callbacks_->encodeHeaders( + HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, false); - EXPECT_CALL(*encoder_filter2, encodeData(_, true)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterDataStatus { return Http::FilterDataStatus::Continue; })); + EXPECT_CALL(*encoder_filters_[0], encodeData(_, false)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(*encoder_filters_[1], encodeData(_, false)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeData(_, false)); - decoder_filter2->callbacks_->encodeHeaders( - Http::HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, true); + Buffer::OwnedImpl response_body("response"); + decoder_filters_[1]->callbacks_->encodeData(response_body, false); + EXPECT_CALL(*encoder_filters_[0], encodeTrailers(_)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterTrailersStatus { + encoder_filters_[0]->callbacks_->addEncodedData(trailers_data); + return FilterTrailersStatus::Continue; + })); + EXPECT_CALL(*encoder_filters_[1], encodeData(Ref(trailers_data), false)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeData(_, false)); + EXPECT_CALL(*encoder_filters_[1], encodeTrailers(_)) + .WillOnce(Return(FilterTrailersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeTrailers(_)); + + decoder_filters_[1]->callbacks_->encodeTrailers( + HeaderMapPtr{new TestHeaderMapImpl{{"some", "trailer"}}}); } -TEST_F(HttpConnectionManagerImplTest, FilterAddBodyContinuation) { +TEST_F(HttpConnectionManagerImplTest, FilterAddBodyInline) { InSequence s; - setup(false, ""); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { - decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_); + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), true); })); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter1 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter2 = new NiceMock(); - EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter1}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter2}); - })); + setupFilterChain(2, 2); - EXPECT_CALL(*decoder_filter1, decodeHeaders(_, true)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::StopIteration; })); + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, true)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus { + Buffer::OwnedImpl data("hello"); + decoder_filters_[0]->callbacks_->addDecodedData(data); + return FilterHeadersStatus::Continue; + })); + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + EXPECT_CALL(*decoder_filters_[1], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); // Kick off the incoming data. Buffer::OwnedImpl fake_input("1234"); conn_manager_->onData(fake_input); - EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::Continue; })); + EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, true)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus { + Buffer::OwnedImpl data("hello"); + encoder_filters_[0]->callbacks_->addEncodedData(data); + return FilterHeadersStatus::Continue; + })); + EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeHeaders(_, false)); + EXPECT_CALL(*encoder_filters_[1], encodeData(_, true)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeData(_, true)); + + decoder_filters_[1]->callbacks_->encodeHeaders( + HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, true); +} - EXPECT_CALL(*decoder_filter2, decodeData(_, true)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterDataStatus { return Http::FilterDataStatus::Continue; })); +TEST_F(HttpConnectionManagerImplTest, FilterAddBodyContinuation) { + InSequence s; + setup(false, ""); - decoder_filter1->callbacks_->decodingBuffer().reset(new Buffer::OwnedImpl("hello")); - decoder_filter1->callbacks_->continueDecoding(); + EXPECT_CALL(*codec_, dispatch(_)) + .WillOnce(Invoke([&](Buffer::Instance&) -> void { + StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_); + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + decoder->decodeHeaders(std::move(headers), true); + })); - EXPECT_CALL(*encoder_filter1, encodeHeaders(_, true)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::StopIteration; })); + setupFilterChain(2, 2); - decoder_filter2->callbacks_->encodeHeaders( - Http::HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, true); + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, true)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); - EXPECT_CALL(*encoder_filter2, encodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterHeadersStatus { return Http::FilterHeadersStatus::Continue; })); + // Kick off the incoming data. + Buffer::OwnedImpl fake_input("1234"); + conn_manager_->onData(fake_input); - EXPECT_CALL(*encoder_filter2, encodeData(_, true)) - .WillOnce(InvokeWithoutArgs( - [&]() -> Http::FilterDataStatus { return Http::FilterDataStatus::Continue; })); + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(*decoder_filters_[1], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::Continue)); - encoder_filter1->callbacks_->encodingBuffer().reset(new Buffer::OwnedImpl("hello")); - encoder_filter1->callbacks_->continueEncoding(); -} + Buffer::OwnedImpl data("hello"); + decoder_filters_[0]->callbacks_->addDecodedData(data); + decoder_filters_[0]->callbacks_->continueDecoding(); -TEST_F(HttpConnectionManagerImplTest, MultipleFilters) { - setup(false, ""); + EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, true)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); - Http::MockStreamDecoderFilter* decoder_filter1 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter2 = new NiceMock(); - Http::MockStreamDecoderFilter* decoder_filter3 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter1 = new NiceMock(); - Http::MockStreamEncoderFilter* encoder_filter2 = new NiceMock(); - EXPECT_CALL(filter_factory_, createFilterChain(_)) - .WillOnce(Invoke([&](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter1}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter2}); - callbacks.addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr{decoder_filter3}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter1}); - callbacks.addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr{encoder_filter2}); - })); + decoder_filters_[1]->callbacks_->encodeHeaders( + HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, true); - // Test route caching. - EXPECT_CALL(*route_config_provider_.route_config_, route(_, _)); + EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeHeaders(_, false)); + EXPECT_CALL(*encoder_filters_[1], encodeData(_, true)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeData(_, true)); - EXPECT_CALL(*decoder_filter1, decodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs([&]() -> Http::FilterHeadersStatus { - EXPECT_EQ(route_config_provider_.route_config_->route_, - decoder_filter1->callbacks_->route()); - EXPECT_EQ(ssl_connection_.get(), decoder_filter1->callbacks_->ssl()); - return Http::FilterHeadersStatus::StopIteration; - })); + Buffer::OwnedImpl data2("hello"); + encoder_filters_[0]->callbacks_->addEncodedData(data2); + encoder_filters_[0]->callbacks_->continueEncoding(); +} - EXPECT_CALL(*decoder_filter1, decodeData(_, false)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); - EXPECT_CALL(*decoder_filter1, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); +TEST_F(HttpConnectionManagerImplTest, MultipleFilters) { + InSequence s; + setup(false, ""); - NiceMock encoder; - Http::StreamDecoder* decoder = nullptr; EXPECT_CALL(*codec_, dispatch(_)) .WillOnce(Invoke([&](Buffer::Instance&) -> void { - decoder = &conn_manager_->newStream(encoder); - Http::HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; + StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_); + HeaderMapPtr headers{new TestHeaderMapImpl{{":authority", "host"}, {":path", "/"}}}; decoder->decodeHeaders(std::move(headers), false); Buffer::OwnedImpl fake_data("hello"); @@ -1005,55 +1040,73 @@ TEST_F(HttpConnectionManagerImplTest, MultipleFilters) { decoder->decodeData(fake_data2, true); })); + setupFilterChain(3, 2); + + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus { + EXPECT_EQ(route_config_provider_.route_config_->route_, + decoder_filters_[0]->callbacks_->route()); + EXPECT_EQ(ssl_connection_.get(), decoder_filters_[0]->callbacks_->ssl()); + return FilterHeadersStatus::StopIteration; + })); + + // Test route caching. + EXPECT_CALL(*route_config_provider_.route_config_, route(_, _)); + + EXPECT_CALL(*decoder_filters_[0], decodeData(_, false)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); + EXPECT_CALL(*decoder_filters_[0], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); + // Kick off the incoming data. Buffer::OwnedImpl fake_input("1234"); conn_manager_->onData(fake_input); // Mimic a decoder filter that trapped data and now sends it on, since the data was buffered // by the first filter, we expect to get it in 1 decodeData() call. - EXPECT_CALL(*decoder_filter2, decodeHeaders(_, false)) - .WillOnce(InvokeWithoutArgs([&]() -> Http::FilterHeadersStatus { + EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, false)) + .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus { EXPECT_EQ(route_config_provider_.route_config_->route_, - decoder_filter2->callbacks_->route()); - EXPECT_EQ(ssl_connection_.get(), decoder_filter2->callbacks_->ssl()); - return Http::FilterHeadersStatus::StopIteration; + decoder_filters_[1]->callbacks_->route()); + EXPECT_EQ(ssl_connection_.get(), decoder_filters_[1]->callbacks_->ssl()); + return FilterHeadersStatus::StopIteration; })); - EXPECT_CALL(*decoder_filter2, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::Continue)); - EXPECT_CALL(*decoder_filter3, decodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); - EXPECT_CALL(*decoder_filter3, decodeData(_, true)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationNoBuffer)); - decoder_filter1->callbacks_->continueDecoding(); + EXPECT_CALL(*decoder_filters_[1], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(*decoder_filters_[2], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + EXPECT_CALL(*decoder_filters_[2], decodeData(_, true)) + .WillOnce(Return(FilterDataStatus::StopIterationNoBuffer)); + decoder_filters_[0]->callbacks_->continueDecoding(); // Now start encoding and mimic trapping in the encoding filter. - EXPECT_CALL(*encoder_filter1, encodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::StopIteration)); - EXPECT_CALL(*encoder_filter1, encodeData(_, false)) - .WillOnce(Return(Http::FilterDataStatus::StopIterationAndBuffer)); - EXPECT_CALL(*encoder_filter1, encodeTrailers(_)) - .WillOnce(Return(Http::FilterTrailersStatus::StopIteration)); - EXPECT_EQ(ssl_connection_.get(), encoder_filter1->callbacks_->ssl()); - decoder_filter3->callbacks_->encodeHeaders( - Http::HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, false); + EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + EXPECT_CALL(*encoder_filters_[0], encodeData(_, false)) + .WillOnce(Return(FilterDataStatus::StopIterationAndBuffer)); + EXPECT_CALL(*encoder_filters_[0], encodeTrailers(_)) + .WillOnce(Return(FilterTrailersStatus::StopIteration)); + EXPECT_EQ(ssl_connection_.get(), encoder_filters_[0]->callbacks_->ssl()); + decoder_filters_[2]->callbacks_->encodeHeaders( + HeaderMapPtr{new TestHeaderMapImpl{{":status", "200"}}}, false); Buffer::OwnedImpl response_body("response"); - decoder_filter3->callbacks_->encodeData(response_body, false); - decoder_filter3->callbacks_->encodeTrailers( - Http::HeaderMapPtr{new TestHeaderMapImpl{{"some", "trailer"}}}); - EXPECT_EQ(ssl_connection_.get(), decoder_filter3->callbacks_->ssl()); + decoder_filters_[2]->callbacks_->encodeData(response_body, false); + decoder_filters_[2]->callbacks_->encodeTrailers( + HeaderMapPtr{new TestHeaderMapImpl{{"some", "trailer"}}}); + EXPECT_EQ(ssl_connection_.get(), decoder_filters_[2]->callbacks_->ssl()); // Now finish the encode. - EXPECT_CALL(*encoder_filter2, encodeHeaders(_, false)) - .WillOnce(Return(Http::FilterHeadersStatus::Continue)); - EXPECT_CALL(encoder, encodeHeaders(_, false)); - EXPECT_CALL(*encoder_filter2, encodeData(_, false)) - .WillOnce(Return(Http::FilterDataStatus::Continue)); - EXPECT_CALL(encoder, encodeData(_, false)); - EXPECT_CALL(*encoder_filter2, encodeTrailers(_)) - .WillOnce(Return(Http::FilterTrailersStatus::Continue)); - EXPECT_CALL(encoder, encodeTrailers(_)); - encoder_filter1->callbacks_->continueEncoding(); - EXPECT_EQ(ssl_connection_.get(), encoder_filter2->callbacks_->ssl()); + EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeHeaders(_, false)); + EXPECT_CALL(*encoder_filters_[1], encodeData(_, false)) + .WillOnce(Return(FilterDataStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeData(_, false)); + EXPECT_CALL(*encoder_filters_[1], encodeTrailers(_)) + .WillOnce(Return(FilterTrailersStatus::Continue)); + EXPECT_CALL(response_encoder_, encodeTrailers(_)); + encoder_filters_[0]->callbacks_->continueEncoding(); + EXPECT_EQ(ssl_connection_.get(), encoder_filters_[1]->callbacks_->ssl()); } TEST(HttpConnectionManagerTracingStatsTest, verifyTracingStats) { diff --git a/test/common/http/filter/buffer_filter_test.cc b/test/common/http/filter/buffer_filter_test.cc index b4136d7700470..04ebc0cdeaf1a 100644 --- a/test/common/http/filter/buffer_filter_test.cc +++ b/test/common/http/filter/buffer_filter_test.cc @@ -18,7 +18,7 @@ using testing::_; using testing::DoAll; using testing::InSequence; using testing::NiceMock; -using testing::ReturnRef; +using testing::Return; using testing::SaveArg; namespace Http { @@ -86,7 +86,7 @@ TEST_F(BufferFilterTest, RequestTooLarge) { EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); Buffer::InstancePtr buffered_data(new Buffer::OwnedImpl("buffered")); - ON_CALL(callbacks_, decodingBuffer()).WillByDefault(ReturnRef(buffered_data)); + ON_CALL(callbacks_, decodingBuffer()).WillByDefault(Return(buffered_data.get())); Buffer::OwnedImpl data1("hello"); config_->max_request_bytes_ = 1; diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index 2026068565db7..1eb70ab665002 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -695,7 +695,7 @@ TEST_F(RouterTest, RetryUpstream5xxNotComplete) { callbacks.onPoolReady(encoder2, cm_.conn_pool_.host_); return nullptr; })); - ON_CALL(callbacks_, decodingBuffer()).WillByDefault(ReturnRef(body_data)); + ON_CALL(callbacks_, decodingBuffer()).WillByDefault(Return(body_data.get())); EXPECT_CALL(encoder2, encodeHeaders(_, false)); EXPECT_CALL(encoder2, encodeData(_, false)); EXPECT_CALL(encoder2, encodeTrailers(_)); @@ -747,7 +747,9 @@ TEST_F(RouterTest, Shadow) { EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, router_.decodeData(*body_data, false)); Http::TestHeaderMapImpl trailers{{"some", "trailer"}}; - EXPECT_CALL(callbacks_, decodingBuffer()).Times(AtLeast(1)).WillRepeatedly(ReturnRef(body_data)); + EXPECT_CALL(callbacks_, decodingBuffer()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(body_data.get())); EXPECT_CALL(*shadow_writer_, shadow_("foo", _, std::chrono::milliseconds(10))) .WillOnce(Invoke([](const std::string&, Http::MessagePtr& request, std::chrono::milliseconds) -> void { diff --git a/test/mocks/http/mocks.cc b/test/mocks/http/mocks.cc index 48c42b6acd1f9..91f983ce75310 100644 --- a/test/mocks/http/mocks.cc +++ b/test/mocks/http/mocks.cc @@ -81,14 +81,14 @@ template static void initializeMockStreamFilterCallbacks(T& callbacks) MockStreamDecoderFilterCallbacks::MockStreamDecoderFilterCallbacks() { initializeMockStreamFilterCallbacks(*this); - ON_CALL(*this, decodingBuffer()).WillByDefault(ReturnRef(buffer_)); + ON_CALL(*this, decodingBuffer()).WillByDefault(Return(buffer_.get())); } MockStreamDecoderFilterCallbacks::~MockStreamDecoderFilterCallbacks() {} MockStreamEncoderFilterCallbacks::MockStreamEncoderFilterCallbacks() { initializeMockStreamFilterCallbacks(*this); - ON_CALL(*this, encodingBuffer()).WillByDefault(ReturnRef(buffer_)); + ON_CALL(*this, encodingBuffer()).WillByDefault(Return(buffer_.get())); } MockStreamEncoderFilterCallbacks::~MockStreamEncoderFilterCallbacks() {} diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h index ce332e1f75f55..541431eff8ec2 100644 --- a/test/mocks/http/mocks.h +++ b/test/mocks/http/mocks.h @@ -239,7 +239,8 @@ class MockStreamDecoderFilterCallbacks : public StreamDecoderFilterCallbacks, void encodeTrailers(HeaderMapPtr&& trailers) override { encodeTrailers_(*trailers); } MOCK_METHOD0(continueDecoding, void()); - MOCK_METHOD0(decodingBuffer, Buffer::InstancePtr&()); + MOCK_METHOD1(addDecodedData, void(Buffer::Instance& data)); + MOCK_METHOD0(decodingBuffer, const Buffer::Instance*()); MOCK_METHOD2(encodeHeaders_, void(HeaderMap& headers, bool end_stream)); MOCK_METHOD2(encodeData, void(Buffer::Instance& data, bool end_stream)); MOCK_METHOD1(encodeTrailers_, void(HeaderMap& trailers)); @@ -266,8 +267,9 @@ class MockStreamEncoderFilterCallbacks : public StreamEncoderFilterCallbacks, MOCK_METHOD0(downstreamAddress, const std::string&()); // Http::StreamEncoderFilterCallbacks + MOCK_METHOD1(addEncodedData, void(Buffer::Instance& data)); MOCK_METHOD0(continueEncoding, void()); - MOCK_METHOD0(encodingBuffer, Buffer::InstancePtr&()); + MOCK_METHOD0(encodingBuffer, const Buffer::Instance*()); Buffer::InstancePtr buffer_; };