#pragma once #include "common/http/conn_manager_impl.h" #include "common/http/context_impl.h" #include "common/http/date_provider_impl.h" #include "common/network/address_impl.h" #include "extensions/access_loggers/file/file_access_log_impl.h" #include "test/mocks/access_log/mocks.h" #include "test/mocks/event/mocks.h" #include "test/mocks/http/mocks.h" #include "test/mocks/local_info/mocks.h" #include "test/mocks/network/mocks.h" #include "test/mocks/router/mocks.h" #include "test/mocks/runtime/mocks.h" #include "test/mocks/server/factory_context.h" #include "test/mocks/ssl/mocks.h" #include "test/test_common/simulated_time_system.h" #include "gmock/gmock.h" #include "gtest/gtest.h" using testing::NiceMock; namespace Envoy { namespace Http { class HttpConnectionManagerImplTest : public testing::Test, public ConnectionManagerConfig { public: struct RouteConfigProvider : public Router::RouteConfigProvider { RouteConfigProvider(TimeSource& time_source) : time_source_(time_source) {} // Router::RouteConfigProvider Router::ConfigConstSharedPtr config() override { return route_config_; } absl::optional configInfo() const override { return {}; } SystemTime lastUpdated() const override { return time_source_.systemTime(); } void onConfigUpdate() override {} TimeSource& time_source_; std::shared_ptr route_config_{new NiceMock()}; }; HttpConnectionManagerImplTest(); ~HttpConnectionManagerImplTest() override; Tracing::CustomTagConstSharedPtr requestHeaderCustomTag(const std::string& header); void setup(bool ssl, const std::string& server_name, bool tracing = true, bool use_srds = false); void setupFilterChain(int num_decoder_filters, int num_encoder_filters, int num_requests = 1); void setUpBufferLimits(); // If request_with_data_and_trailers is true, includes data and trailers in the request. If // decode_headers_stop_all is true, decoder_filters_[0]'s callback decodeHeaders() returns // StopAllIterationAndBuffer. void setUpEncoderAndDecoder(bool request_with_data_and_trailers, bool decode_headers_stop_all); // Sends request headers, and stashes the new stream in decoder_; void startRequest(bool end_stream = false, absl::optional body = absl::nullopt); Event::MockTimer* setUpTimer(); void sendRequestHeadersAndData(); ResponseHeaderMap* sendResponseHeaders(ResponseHeaderMapPtr&& response_headers); void expectOnDestroy(bool deferred = true); void doRemoteClose(bool deferred = true); // Http::ConnectionManagerConfig const std::list& accessLogs() override { return access_logs_; } ServerConnectionPtr createCodec(Network::Connection&, const Buffer::Instance&, ServerConnectionCallbacks&) override { return ServerConnectionPtr{codec_}; } DateProvider& dateProvider() override { return date_provider_; } std::chrono::milliseconds drainTimeout() const override { return std::chrono::milliseconds(100); } FilterChainFactory& filterFactory() override { return filter_factory_; } bool generateRequestId() const override { return true; } bool preserveExternalRequestId() const override { return false; } bool alwaysSetRequestIdInResponse() const override { return false; } uint32_t maxRequestHeadersKb() const override { return max_request_headers_kb_; } uint32_t maxRequestHeadersCount() const override { return max_request_headers_count_; } absl::optional idleTimeout() const override { return idle_timeout_; } bool isRoutable() const override { return true; } absl::optional maxConnectionDuration() const override { return max_connection_duration_; } std::chrono::milliseconds streamIdleTimeout() const override { return stream_idle_timeout_; } std::chrono::milliseconds requestTimeout() const override { return request_timeout_; } std::chrono::milliseconds requestHeadersTimeout() const override { return request_headers_timeout_; } std::chrono::milliseconds delayedCloseTimeout() const override { return delayed_close_timeout_; } absl::optional maxStreamDuration() const override { return max_stream_duration_; } bool use_srds_{}; Router::RouteConfigProvider* routeConfigProvider() override { if (use_srds_) { return nullptr; } return &route_config_provider_; } Config::ConfigProvider* scopedRouteConfigProvider() override { if (use_srds_) { return &scoped_route_config_provider_; } return nullptr; } const std::string& serverName() const override { return server_name_; } HttpConnectionManagerProto::ServerHeaderTransformation serverHeaderTransformation() const override { return server_transformation_; } ConnectionManagerStats& stats() override { return stats_; } ConnectionManagerTracingStats& tracingStats() override { return tracing_stats_; } bool useRemoteAddress() const override { return use_remote_address_; } const Http::InternalAddressConfig& internalAddressConfig() const override { return internal_address_config_; } uint32_t xffNumTrustedHops() const override { return 0; } bool skipXffAppend() const override { return false; } const std::string& via() const override { return EMPTY_STRING; } Http::ForwardClientCertType forwardClientCert() const override { return forward_client_cert_; } const std::vector& setCurrentClientCertDetails() const override { return set_current_client_cert_details_; } const Network::Address::Instance& localAddress() override { return local_address_; } const absl::optional& userAgent() override { return user_agent_; } Tracing::HttpTracerSharedPtr tracer() override { return tracer_; } const TracingConnectionManagerConfig* tracingConfig() override { return tracing_config_.get(); } ConnectionManagerListenerStats& listenerStats() override { return listener_stats_; } bool proxy100Continue() const override { return proxy_100_continue_; } bool streamErrorOnInvalidHttpMessaging() const override { return stream_error_on_invalid_http_messaging_; } const Http::Http1Settings& http1Settings() const override { return http1_settings_; } bool shouldNormalizePath() const override { return normalize_path_; } bool shouldMergeSlashes() const override { return merge_slashes_; } bool shouldStripMatchingPort() const override { return strip_matching_port_; } RequestIDExtensionSharedPtr requestIDExtension() override { return request_id_extension_; } envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction headersWithUnderscoresAction() const override { return headers_with_underscores_action_; } const LocalReply::LocalReply& localReply() const override { return *local_reply_; } Envoy::Event::SimulatedTimeSystem test_time_; NiceMock route_config_provider_; std::shared_ptr route_config_{new NiceMock()}; NiceMock scoped_route_config_provider_; Stats::IsolatedStoreImpl fake_stats_; Http::ContextImpl http_context_; NiceMock runtime_; NiceMock log_manager_; std::string access_log_path_; std::list access_logs_; NiceMock filter_callbacks_; MockServerConnection* codec_; NiceMock filter_factory_; ConnectionManagerStats stats_; ConnectionManagerTracingStats tracing_stats_{CONN_MAN_TRACING_STATS(POOL_COUNTER(fake_stats_))}; NiceMock drain_close_; std::unique_ptr conn_manager_; std::string server_name_; HttpConnectionManagerProto::ServerHeaderTransformation server_transformation_{ HttpConnectionManagerProto::OVERWRITE}; Network::Address::Ipv4Instance local_address_{"127.0.0.1"}; bool use_remote_address_{true}; Http::DefaultInternalAddressConfig internal_address_config_; Http::ForwardClientCertType forward_client_cert_{Http::ForwardClientCertType::Sanitize}; std::vector set_current_client_cert_details_; absl::optional user_agent_; uint32_t max_request_headers_kb_{Http::DEFAULT_MAX_REQUEST_HEADERS_KB}; uint32_t max_request_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; absl::optional idle_timeout_; absl::optional max_connection_duration_; std::chrono::milliseconds stream_idle_timeout_{}; std::chrono::milliseconds request_timeout_{}; std::chrono::milliseconds request_headers_timeout_{}; std::chrono::milliseconds delayed_close_timeout_{}; absl::optional max_stream_duration_{}; NiceMock random_; NiceMock local_info_; NiceMock factory_context_; RequestDecoder* decoder_{}; std::shared_ptr ssl_connection_; std::shared_ptr> tracer_{ std::make_shared>()}; TracingConnectionManagerConfigPtr tracing_config_; SlowDateProviderImpl date_provider_{test_time_.timeSystem()}; MockStream stream_; Http::StreamCallbacks* stream_callbacks_{nullptr}; NiceMock cluster_manager_; NiceMock overload_manager_; uint32_t initial_buffer_limit_{}; bool streaming_filter_{false}; Stats::IsolatedStoreImpl fake_listener_stats_; ConnectionManagerListenerStats listener_stats_; bool proxy_100_continue_ = false; bool stream_error_on_invalid_http_messaging_ = false; bool preserve_external_request_id_ = false; Http::Http1Settings http1_settings_; bool normalize_path_ = false; bool merge_slashes_ = false; bool strip_matching_port_ = false; envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction headers_with_underscores_action_ = envoy::config::core::v3::HttpProtocolOptions::ALLOW; NiceMock upstream_conn_; // for websocket tests NiceMock conn_pool_; // for websocket tests RequestIDExtensionSharedPtr request_id_extension_; const LocalReply::LocalReplyPtr local_reply_; // TODO(mattklein123): Not all tests have been converted over to better setup. Convert the rest. NiceMock response_encoder_; std::vector decoder_filters_; std::vector encoder_filters_; std::shared_ptr log_handler_; }; } // namespace Http } // namespace Envoy