/proc/self/cwd/test/common/http/conn_manager_impl_test_base.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "source/common/http/conn_manager_impl.h" |
4 | | #include "source/common/http/context_impl.h" |
5 | | #include "source/common/http/date_provider_impl.h" |
6 | | #include "source/common/network/address_impl.h" |
7 | | #include "source/common/tracing/custom_tag_impl.h" |
8 | | #include "source/extensions/access_loggers/common/file_access_log_impl.h" |
9 | | #include "source/extensions/http/header_validators/envoy_default/http1_header_validator.h" |
10 | | |
11 | | #include "test/mocks/access_log/mocks.h" |
12 | | #include "test/mocks/event/mocks.h" |
13 | | #include "test/mocks/http/header_validator.h" |
14 | | #include "test/mocks/http/mocks.h" |
15 | | #include "test/mocks/local_info/mocks.h" |
16 | | #include "test/mocks/network/mocks.h" |
17 | | #include "test/mocks/router/mocks.h" |
18 | | #include "test/mocks/runtime/mocks.h" |
19 | | #include "test/mocks/server/factory_context.h" |
20 | | #include "test/mocks/ssl/mocks.h" |
21 | | #include "test/test_common/delegating_route_utility.h" |
22 | | #include "test/test_common/simulated_time_system.h" |
23 | | |
24 | | #include "gmock/gmock.h" |
25 | | #include "gtest/gtest.h" |
26 | | |
27 | | using testing::NiceMock; |
28 | | |
29 | | namespace Envoy { |
30 | | namespace Http { |
31 | | |
32 | | // Base class for HttpConnectionManagerImpl related tests. This base class is used by tests under |
33 | | // common/http as well as test/extensions/filters/http/ext_proc/, to reuse the many mocks/default |
34 | | // impls of ConnectionManagerConfig that we need to provide to HttpConnectionManagerImpl. |
35 | | class HttpConnectionManagerImplMixin : public ConnectionManagerConfig { |
36 | | public: |
37 | | HttpConnectionManagerImplMixin(); |
38 | | ~HttpConnectionManagerImplMixin() override; |
39 | | Tracing::CustomTagConstSharedPtr requestHeaderCustomTag(const std::string& header); |
40 | | void setup(bool ssl, const std::string& server_name, bool tracing = true, bool use_srds = false); |
41 | | void setupFilterChain(int num_decoder_filters, int num_encoder_filters, int num_requests = 1); |
42 | | void setUpBufferLimits(); |
43 | | |
44 | | // If request_with_data_and_trailers is true, includes data and trailers in the request. If |
45 | | // decode_headers_stop_all is true, decoder_filters_[0]'s callback decodeHeaders() returns |
46 | | // StopAllIterationAndBuffer. |
47 | | void setUpEncoderAndDecoder(bool request_with_data_and_trailers, bool decode_headers_stop_all); |
48 | | |
49 | | // Sends request headers, and stashes the new stream in decoder_; |
50 | | void startRequest(bool end_stream = false, absl::optional<std::string> body = absl::nullopt); |
51 | | |
52 | | Event::MockTimer* setUpTimer(); |
53 | | void sendRequestHeadersAndData(); |
54 | | ResponseHeaderMap* |
55 | | sendResponseHeaders(ResponseHeaderMapPtr&& response_headers, |
56 | | absl::optional<StreamInfo::ResponseFlag> response_flag = absl::nullopt, |
57 | | std::string response_code_details = "details"); |
58 | | void expectOnDestroy(bool deferred = true); |
59 | | void doRemoteClose(bool deferred = true); |
60 | | void testPathNormalization(const RequestHeaderMap& request_headers, |
61 | | const ResponseHeaderMap& expected_response); |
62 | | |
63 | | // Http::ConnectionManagerConfig |
64 | 7 | const std::list<AccessLog::InstanceSharedPtr>& accessLogs() override { return access_logs_; } |
65 | 7 | bool flushAccessLogOnNewRequest() override { return flush_access_log_on_new_request_; } |
66 | 0 | bool flushAccessLogOnTunnelSuccessfullyEstablished() const override { |
67 | 0 | return flush_log_on_tunnel_successfully_established_; |
68 | 0 | } |
69 | 7 | const absl::optional<std::chrono::milliseconds>& accessLogFlushInterval() override { |
70 | 7 | return access_log_flush_interval_; |
71 | 7 | } |
72 | | ServerConnectionPtr createCodec(Network::Connection&, const Buffer::Instance&, |
73 | 0 | ServerConnectionCallbacks&, Server::OverloadManager&) override { |
74 | 0 | return ServerConnectionPtr{codec_}; |
75 | 0 | } |
76 | 1 | DateProvider& dateProvider() override { return date_provider_; } |
77 | 0 | std::chrono::milliseconds drainTimeout() const override { return std::chrono::milliseconds(100); } |
78 | 7 | FilterChainFactory& filterFactory() override { return filter_factory_; } |
79 | 7 | bool generateRequestId() const override { return true; } |
80 | 7 | bool preserveExternalRequestId() const override { return false; } |
81 | 1 | bool alwaysSetRequestIdInResponse() const override { return false; } |
82 | 0 | uint32_t maxRequestHeadersKb() const override { return max_request_headers_kb_; } |
83 | 0 | uint32_t maxRequestHeadersCount() const override { return max_request_headers_count_; } |
84 | 18 | absl::optional<std::chrono::milliseconds> idleTimeout() const override { return idle_timeout_; } |
85 | 28 | bool isRoutable() const override { return true; } |
86 | 18 | absl::optional<std::chrono::milliseconds> maxConnectionDuration() const override { |
87 | 18 | return max_connection_duration_; |
88 | 18 | } |
89 | 7 | std::chrono::milliseconds streamIdleTimeout() const override { return stream_idle_timeout_; } |
90 | 7 | std::chrono::milliseconds requestTimeout() const override { return request_timeout_; } |
91 | 7 | std::chrono::milliseconds requestHeadersTimeout() const override { |
92 | 7 | return request_headers_timeout_; |
93 | 7 | } |
94 | 18 | std::chrono::milliseconds delayedCloseTimeout() const override { return delayed_close_timeout_; } |
95 | 14 | absl::optional<std::chrono::milliseconds> maxStreamDuration() const override { |
96 | 14 | return max_stream_duration_; |
97 | 14 | } |
98 | | bool use_srds_{}; |
99 | 42 | Router::RouteConfigProvider* routeConfigProvider() override { |
100 | 42 | if (use_srds_) { |
101 | 0 | return nullptr; |
102 | 0 | } |
103 | 42 | return &route_config_provider_; |
104 | 42 | } |
105 | 14 | Config::ConfigProvider* scopedRouteConfigProvider() override { |
106 | 14 | if (use_srds_) { |
107 | 0 | return &scoped_route_config_provider_; |
108 | 0 | } |
109 | 14 | return nullptr; |
110 | 14 | } |
111 | 7 | OptRef<const Router::ScopeKeyBuilder> scopeKeyBuilder() override { |
112 | 7 | if (use_srds_) { |
113 | 0 | return scope_key_builder_; |
114 | 0 | } |
115 | 7 | return {}; |
116 | 7 | } |
117 | 19 | const std::string& serverName() const override { return server_name_; } |
118 | | HttpConnectionManagerProto::ServerHeaderTransformation |
119 | 1 | serverHeaderTransformation() const override { |
120 | 1 | return server_transformation_; |
121 | 1 | } |
122 | 7 | const absl::optional<std::string>& schemeToSet() const override { return scheme_; } |
123 | 18 | ConnectionManagerStats& stats() override { return stats_; } |
124 | 0 | ConnectionManagerTracingStats& tracingStats() override { return tracing_stats_; } |
125 | 7 | bool useRemoteAddress() const override { return use_remote_address_; } |
126 | 7 | const Http::InternalAddressConfig& internalAddressConfig() const override { |
127 | 7 | return internal_address_config_; |
128 | 7 | } |
129 | 7 | uint32_t xffNumTrustedHops() const override { return 0; } |
130 | 7 | bool skipXffAppend() const override { return false; } |
131 | 8 | const std::string& via() const override { return EMPTY_STRING; } |
132 | 14 | Http::ForwardClientCertType forwardClientCert() const override { return forward_client_cert_; } |
133 | 0 | const std::vector<Http::ClientCertDetailsType>& setCurrentClientCertDetails() const override { |
134 | 0 | return set_current_client_cert_details_; |
135 | 0 | } |
136 | 0 | const Network::Address::Instance& localAddress() override { return local_address_; } |
137 | 7 | const absl::optional<std::string>& userAgent() override { return user_agent_; } |
138 | 0 | Tracing::TracerSharedPtr tracer() override { return tracer_; } |
139 | 14 | const TracingConnectionManagerConfig* tracingConfig() override { return tracing_config_.get(); } |
140 | 18 | ConnectionManagerListenerStats& listenerStats() override { return listener_stats_; } |
141 | 14 | bool proxy100Continue() const override { return proxy_100_continue_; } |
142 | 0 | bool streamErrorOnInvalidHttpMessaging() const override { |
143 | 0 | return stream_error_on_invalid_http_messaging_; |
144 | 0 | } |
145 | 0 | const Http::Http1Settings& http1Settings() const override { return http1_settings_; } |
146 | 7 | bool shouldNormalizePath() const override { return normalize_path_; } |
147 | 7 | bool shouldMergeSlashes() const override { return merge_slashes_; } |
148 | 7 | bool shouldStripTrailingHostDot() const override { return strip_trailing_host_dot_; } |
149 | 14 | Http::StripPortType stripPortType() const override { return strip_port_type_; } |
150 | 7 | const RequestIDExtensionSharedPtr& requestIDExtension() override { return request_id_extension_; } |
151 | | envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction |
152 | 0 | headersWithUnderscoresAction() const override { |
153 | 0 | return headers_with_underscores_action_; |
154 | 0 | } |
155 | 7 | const LocalReply::LocalReply& localReply() const override { return *local_reply_; } |
156 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
157 | | PathWithEscapedSlashesAction |
158 | 7 | pathWithEscapedSlashesAction() const override { |
159 | 7 | return path_with_escaped_slashes_action_; |
160 | 7 | } |
161 | | const std::vector<Http::OriginalIPDetectionSharedPtr>& |
162 | 0 | originalIpDetectionExtensions() const override { |
163 | 0 | return ip_detection_extensions_; |
164 | 0 | } |
165 | 7 | const std::vector<Http::EarlyHeaderMutationPtr>& earlyHeaderMutationExtensions() const override { |
166 | 7 | return early_header_mutations_; |
167 | 7 | } |
168 | 7 | uint64_t maxRequestsPerConnection() const override { return max_requests_per_connection_; } |
169 | 19 | const HttpConnectionManagerProto::ProxyStatusConfig* proxyStatusConfig() const override { |
170 | 19 | return proxy_status_config_.get(); |
171 | 19 | } |
172 | 7 | ServerHeaderValidatorPtr makeHeaderValidator(Protocol protocol) override { |
173 | 7 | return header_validator_factory_.createServerHeaderValidator(protocol, header_validator_stats_); |
174 | 7 | } |
175 | 14 | bool appendXForwardedPort() const override { return false; } |
176 | 18 | bool addProxyProtocolConnectionState() const override { |
177 | 18 | return add_proxy_protocol_connection_state_; |
178 | 18 | } |
179 | | |
180 | | // Simple helper to wrapper filter to the factory function. |
181 | 0 | FilterFactoryCb createDecoderFilterFactoryCb(StreamDecoderFilterSharedPtr filter) { |
182 | 0 | return [filter](FilterChainFactoryCallbacks& callbacks) { |
183 | 0 | callbacks.addStreamDecoderFilter(filter); |
184 | 0 | }; |
185 | 0 | } |
186 | 0 | FilterFactoryCb createEncoderFilterFactoryCb(StreamEncoderFilterSharedPtr filter) { |
187 | 0 | return [filter](FilterChainFactoryCallbacks& callbacks) { |
188 | 0 | callbacks.addStreamEncoderFilter(filter); |
189 | 0 | }; |
190 | 0 | } |
191 | 0 | FilterFactoryCb createStreamFilterFactoryCb(StreamFilterSharedPtr filter) { |
192 | 0 | return [filter](FilterChainFactoryCallbacks& callbacks) { callbacks.addStreamFilter(filter); }; |
193 | 0 | } |
194 | 0 | FilterFactoryCb createLogHandlerFactoryCb(AccessLog::InstanceSharedPtr handler) { |
195 | 0 | return [handler](FilterChainFactoryCallbacks& callbacks) { |
196 | 0 | callbacks.addAccessLogHandler(handler); |
197 | 0 | }; |
198 | 0 | } |
199 | | void expectUhvHeaderCheck( |
200 | | HeaderValidator::ValidationResult validation_result, |
201 | | ServerHeaderValidator::RequestHeadersTransformationResult transformation_result); |
202 | | void expectUhvTrailerCheck(HeaderValidator::ValidationResult validation_result, |
203 | | HeaderValidator::TransformationResult transformation_result, |
204 | | bool expect_response = true); |
205 | | // This method sets-up expectation that UHV will be called and provides real default UHV to |
206 | | // validate headers. |
207 | | void expectCheckWithDefaultUhv(); |
208 | | |
209 | | Event::MockSchedulableCallback* enableStreamsPerIoLimit(uint32_t limit); |
210 | | |
211 | | Envoy::Event::SimulatedTimeSystem test_time_; |
212 | | NiceMock<Router::MockRouteConfigProvider> route_config_provider_; |
213 | | std::shared_ptr<Router::MockConfig> route_config_{new NiceMock<Router::MockConfig>()}; |
214 | | NiceMock<Router::MockScopedRouteConfigProvider> scoped_route_config_provider_; |
215 | | Router::MockScopeKeyBuilder scope_key_builder_; |
216 | | Stats::TestUtil::TestSymbolTable symbol_table_; |
217 | | Stats::IsolatedStoreImpl fake_stats_; |
218 | | Http::ContextImpl http_context_; |
219 | | NiceMock<Runtime::MockLoader> runtime_; |
220 | | NiceMock<Envoy::AccessLog::MockAccessLogManager> log_manager_; |
221 | | std::string access_log_path_; |
222 | | std::list<AccessLog::InstanceSharedPtr> access_logs_; |
223 | | bool flush_access_log_on_new_request_ = false; |
224 | | bool flush_log_on_tunnel_successfully_established_ = false; |
225 | | absl::optional<std::chrono::milliseconds> access_log_flush_interval_; |
226 | | NiceMock<Network::MockReadFilterCallbacks> filter_callbacks_; |
227 | | MockServerConnection* codec_; |
228 | | NiceMock<MockFilterChainFactory> filter_factory_; |
229 | | ConnectionManagerStats stats_; |
230 | | ConnectionManagerTracingStats tracing_stats_{CONN_MAN_TRACING_STATS(POOL_COUNTER(fake_stats_))}; |
231 | | NiceMock<Network::MockDrainDecision> drain_close_; |
232 | | std::unique_ptr<ConnectionManagerImpl> conn_manager_; |
233 | | std::string server_name_; |
234 | | HttpConnectionManagerProto::ServerHeaderTransformation server_transformation_{ |
235 | | HttpConnectionManagerProto::OVERWRITE}; |
236 | | absl::optional<std::string> scheme_; |
237 | | Network::Address::Ipv4Instance local_address_{"127.0.0.1"}; |
238 | | bool use_remote_address_{true}; |
239 | | Http::DefaultInternalAddressConfig internal_address_config_; |
240 | | Http::ForwardClientCertType forward_client_cert_{Http::ForwardClientCertType::Sanitize}; |
241 | | std::vector<Http::ClientCertDetailsType> set_current_client_cert_details_; |
242 | | absl::optional<std::string> user_agent_; |
243 | | uint32_t max_request_headers_kb_{Http::DEFAULT_MAX_REQUEST_HEADERS_KB}; |
244 | | uint32_t max_request_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; |
245 | | uint64_t max_requests_per_connection_{}; |
246 | | absl::optional<std::chrono::milliseconds> idle_timeout_; |
247 | | absl::optional<std::chrono::milliseconds> max_connection_duration_; |
248 | | std::chrono::milliseconds stream_idle_timeout_{}; |
249 | | std::chrono::milliseconds request_timeout_{}; |
250 | | std::chrono::milliseconds request_headers_timeout_{}; |
251 | | std::chrono::milliseconds delayed_close_timeout_{}; |
252 | | absl::optional<std::chrono::milliseconds> max_stream_duration_{}; |
253 | | NiceMock<Random::MockRandomGenerator> random_; |
254 | | NiceMock<LocalInfo::MockLocalInfo> local_info_; |
255 | | NiceMock<Server::Configuration::MockFactoryContext> factory_context_; |
256 | | RequestDecoder* decoder_{}; |
257 | | std::shared_ptr<Ssl::MockConnectionInfo> ssl_connection_; |
258 | | std::shared_ptr<NiceMock<Tracing::MockTracer>> tracer_{ |
259 | | std::make_shared<NiceMock<Tracing::MockTracer>>()}; |
260 | | TracingConnectionManagerConfigPtr tracing_config_; |
261 | | SlowDateProviderImpl date_provider_{test_time_.timeSystem()}; |
262 | | Http::StreamCallbacks* stream_callbacks_{nullptr}; |
263 | | NiceMock<Upstream::MockClusterManager> cluster_manager_; |
264 | | NiceMock<Server::MockOverloadManager> overload_manager_; |
265 | | uint32_t initial_buffer_limit_{}; |
266 | | bool streaming_filter_{false}; |
267 | | Stats::IsolatedStoreImpl fake_listener_stats_; |
268 | | ConnectionManagerListenerStats listener_stats_; |
269 | | bool proxy_100_continue_ = false; |
270 | | bool stream_error_on_invalid_http_messaging_ = false; |
271 | | bool preserve_external_request_id_ = false; |
272 | | Http::Http1Settings http1_settings_; |
273 | | bool normalize_path_ = false; |
274 | | bool merge_slashes_ = false; |
275 | | Http::StripPortType strip_port_type_ = Http::StripPortType::None; |
276 | | envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction |
277 | | headers_with_underscores_action_ = envoy::config::core::v3::HttpProtocolOptions::ALLOW; |
278 | | NiceMock<Network::MockClientConnection> upstream_conn_; // for websocket tests |
279 | | NiceMock<Tcp::ConnectionPool::MockInstance> conn_pool_; // for websocket tests |
280 | | RequestIDExtensionSharedPtr request_id_extension_; |
281 | | std::vector<Http::OriginalIPDetectionSharedPtr> ip_detection_extensions_{}; |
282 | | std::vector<Http::EarlyHeaderMutationPtr> early_header_mutations_{}; |
283 | | bool add_proxy_protocol_connection_state_ = true; |
284 | | |
285 | | const LocalReply::LocalReplyPtr local_reply_; |
286 | | |
287 | | NiceMock<MockResponseEncoder> response_encoder_; |
288 | | std::vector<MockStreamDecoderFilter*> decoder_filters_; |
289 | | std::vector<MockStreamEncoderFilter*> encoder_filters_; |
290 | | std::shared_ptr<AccessLog::MockInstance> log_handler_; |
291 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
292 | | PathWithEscapedSlashesAction path_with_escaped_slashes_action_{ |
293 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
294 | | KEEP_UNCHANGED}; |
295 | | bool strip_trailing_host_dot_ = false; |
296 | | std::unique_ptr<HttpConnectionManagerProto::ProxyStatusConfig> proxy_status_config_; |
297 | | NiceMock<MockHeaderValidatorFactory> header_validator_factory_; |
298 | | NiceMock<MockHeaderValidatorStats> header_validator_stats_; |
299 | | envoy::extensions::http::header_validators::envoy_default::v3::HeaderValidatorConfig |
300 | | header_validator_config_; |
301 | | Extensions::Http::HeaderValidators::EnvoyDefault::ConfigOverrides |
302 | | header_validator_config_overrides_; |
303 | | }; |
304 | | |
305 | | class HttpConnectionManagerImplTest : public HttpConnectionManagerImplMixin, |
306 | | public testing::Test {}; |
307 | | } // namespace Http |
308 | | } // namespace Envoy |