/proc/self/cwd/test/integration/utility.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <cstdint> |
4 | | #include <functional> |
5 | | #include <memory> |
6 | | #include <string> |
7 | | |
8 | | #include "envoy/api/api.h" |
9 | | #include "envoy/extensions/http/header_validators/envoy_default/v3/header_validator.pb.h" |
10 | | #include "envoy/http/codec.h" |
11 | | #include "envoy/http/header_map.h" |
12 | | #include "envoy/network/filter.h" |
13 | | #include "envoy/server/factory_context.h" |
14 | | |
15 | | #include "source/common/common/assert.h" |
16 | | #include "source/common/common/dump_state_utils.h" |
17 | | #include "source/common/common/utility.h" |
18 | | #include "source/common/http/codec_client.h" |
19 | | #include "source/common/stats/isolated_store_impl.h" |
20 | | |
21 | | #include "test/test_common/printers.h" |
22 | | #include "test/test_common/test_time.h" |
23 | | #include "test/test_common/utility.h" |
24 | | |
25 | | #include "gtest/gtest.h" |
26 | | |
27 | | namespace Envoy { |
28 | | /** |
29 | | * A buffering response decoder used for testing. |
30 | | */ |
31 | | class BufferingStreamDecoder : public Http::ResponseDecoder, public Http::StreamCallbacks { |
32 | | public: |
33 | 2.64k | BufferingStreamDecoder(std::function<void()> on_complete_cb) : on_complete_cb_(on_complete_cb) {}Unexecuted instantiation: Envoy::BufferingStreamDecoder::BufferingStreamDecoder(std::__1::function<void ()>) Envoy::BufferingStreamDecoder::BufferingStreamDecoder(std::__1::function<void ()>) Line | Count | Source | 33 | 2.64k | BufferingStreamDecoder(std::function<void()> on_complete_cb) : on_complete_cb_(on_complete_cb) {} |
|
34 | | |
35 | 5.29k | bool complete() { return complete_; } |
36 | 2.64k | const Http::ResponseHeaderMap& headers() { return *headers_; } |
37 | 2.64k | const std::string& body() { return body_; } |
38 | | |
39 | | // Http::StreamDecoder |
40 | | void decodeData(Buffer::Instance&, bool end_stream) override; |
41 | 0 | void decodeMetadata(Http::MetadataMapPtr&&) override {} |
42 | | |
43 | | // Http::ResponseDecoder |
44 | 0 | void decode1xxHeaders(Http::ResponseHeaderMapPtr&&) override {} |
45 | | void decodeHeaders(Http::ResponseHeaderMapPtr&& headers, bool end_stream) override; |
46 | | void decodeTrailers(Http::ResponseTrailerMapPtr&& trailers) override; |
47 | 0 | void dumpState(std::ostream& os, int indent_level) const override { |
48 | 0 | DUMP_STATE_UNIMPLEMENTED(BufferingStreamDecoder); |
49 | 0 | } |
50 | | |
51 | | // Http::StreamCallbacks |
52 | | void onResetStream(Http::StreamResetReason reason, |
53 | | absl::string_view transport_failure_reason) override; |
54 | 0 | void onAboveWriteBufferHighWatermark() override {} |
55 | 0 | void onBelowWriteBufferLowWatermark() override {} |
56 | | |
57 | | private: |
58 | | void onComplete(); |
59 | | |
60 | | Http::ResponseHeaderMapPtr headers_; |
61 | | std::string body_; |
62 | | bool complete_{}; |
63 | | std::function<void()> on_complete_cb_; |
64 | | }; |
65 | | |
66 | | using BufferingStreamDecoderPtr = std::unique_ptr<BufferingStreamDecoder>; |
67 | | |
68 | | /** |
69 | | * Basic driver for a raw connection. |
70 | | */ |
71 | | class RawConnectionDriver { |
72 | | public: |
73 | | // Callback that is executed to write data to connection. The provided buffer |
74 | | // should be populated with the data to write. If the callback returns true, |
75 | | // the connection will be closed after writing. |
76 | | using DoWriteCallback = std::function<bool(Buffer::Instance&)>; |
77 | | using ReadCallback = std::function<void(Network::ClientConnection&, const Buffer::Instance&)>; |
78 | | |
79 | | RawConnectionDriver(uint32_t port, DoWriteCallback write_request_callback, |
80 | | ReadCallback response_data_callback, Network::Address::IpVersion version, |
81 | | Event::Dispatcher& dispatcher, |
82 | | Network::TransportSocketPtr transport_socket = nullptr); |
83 | | // Similar to the constructor above but accepts the request as a constructor argument. |
84 | | RawConnectionDriver(uint32_t port, Buffer::Instance& request_data, |
85 | | ReadCallback response_data_callback, Network::Address::IpVersion version, |
86 | | Event::Dispatcher& dispatcher, |
87 | | Network::TransportSocketPtr transport_socket = nullptr); |
88 | | ~RawConnectionDriver(); |
89 | | |
90 | | testing::AssertionResult |
91 | | run(Event::Dispatcher::RunType run_type = Event::Dispatcher::RunType::Block, |
92 | | std::chrono::milliseconds timeout = TestUtility::DefaultTimeout); |
93 | | void close(); |
94 | 0 | Network::ConnectionEvent lastConnectionEvent() const { |
95 | 0 | return callbacks_->last_connection_event_; |
96 | 0 | } |
97 | | // Wait until connected or closed(). |
98 | | ABSL_MUST_USE_RESULT testing::AssertionResult waitForConnection(); |
99 | | |
100 | 0 | bool closed() { return callbacks_->closed(); } |
101 | | bool allBytesSent() const; |
102 | | |
103 | | private: |
104 | | struct ForwardingFilter : public Network::ReadFilterBaseImpl { |
105 | | ForwardingFilter(RawConnectionDriver& parent, ReadCallback cb) |
106 | 0 | : parent_(parent), response_data_callback_(cb) {} |
107 | | |
108 | | // Network::ReadFilter |
109 | 0 | Network::FilterStatus onData(Buffer::Instance& data, bool) override { |
110 | 0 | response_data_callback_(*parent_.client_, data); |
111 | 0 | data.drain(data.length()); |
112 | 0 | return Network::FilterStatus::StopIteration; |
113 | 0 | } |
114 | | |
115 | | RawConnectionDriver& parent_; |
116 | | ReadCallback response_data_callback_; |
117 | | }; |
118 | | |
119 | | struct ConnectionCallbacks : public Network::ConnectionCallbacks { |
120 | | using WriteCb = std::function<void()>; |
121 | | |
122 | | ConnectionCallbacks(WriteCb write_cb, Event::Dispatcher& dispatcher) |
123 | 0 | : write_cb_(write_cb), dispatcher_(dispatcher) {} |
124 | 0 | bool connected() const { return connected_; } |
125 | 0 | bool closed() const { return closed_; } |
126 | | |
127 | | // Network::ConnectionCallbacks |
128 | 0 | void onEvent(Network::ConnectionEvent event) override { |
129 | 0 | if (!connected_ && event == Network::ConnectionEvent::Connected) { |
130 | 0 | write_cb_(); |
131 | 0 | } |
132 | 0 | last_connection_event_ = event; |
133 | |
|
134 | 0 | closed_ |= (event == Network::ConnectionEvent::RemoteClose || |
135 | 0 | event == Network::ConnectionEvent::LocalClose); |
136 | 0 | connected_ |= (event == Network::ConnectionEvent::Connected); |
137 | |
|
138 | 0 | if (closed_) { |
139 | 0 | dispatcher_.exit(); |
140 | 0 | } |
141 | 0 | } |
142 | 0 | void onAboveWriteBufferHighWatermark() override {} |
143 | 0 | void onBelowWriteBufferLowWatermark() override { write_cb_(); } |
144 | | |
145 | | Network::ConnectionEvent last_connection_event_; |
146 | | |
147 | | private: |
148 | | WriteCb write_cb_; |
149 | | Event::Dispatcher& dispatcher_; |
150 | | bool connected_{false}; |
151 | | bool closed_{false}; |
152 | | }; |
153 | | |
154 | | Stats::IsolatedStoreImpl stats_store_; |
155 | | Api::ApiPtr api_; |
156 | | Event::Dispatcher& dispatcher_; |
157 | | std::unique_ptr<ConnectionCallbacks> callbacks_; |
158 | | Network::ClientConnectionPtr client_; |
159 | | uint64_t remaining_bytes_to_send_; |
160 | | }; |
161 | | |
162 | | /** |
163 | | * Utility routines for integration tests. |
164 | | */ |
165 | | class IntegrationUtil { |
166 | | public: |
167 | | /** |
168 | | * Make a new connection, issues a request, and then disconnect when the request is complete. |
169 | | * @param addr supplies the address to connect to. |
170 | | * @param method supplies the request method. |
171 | | * @param url supplies the request url. |
172 | | * @param body supplies the optional request body to send. |
173 | | * @param type supplies the codec to use for the request. |
174 | | * @param host supplies the host header to use for the request. |
175 | | * @param content_type supplies the content-type header to use for the request, if any. |
176 | | * @return BufferingStreamDecoderPtr the complete request or a partial request if there was |
177 | | * remote early disconnection. |
178 | | */ |
179 | | static BufferingStreamDecoderPtr |
180 | | makeSingleRequest(const Network::Address::InstanceConstSharedPtr& addr, const std::string& method, |
181 | | const std::string& url, const std::string& body, Http::CodecType type, |
182 | | const std::string& host = "host", const std::string& content_type = ""); |
183 | | |
184 | | /** |
185 | | * Make a new connection, issues a request, and then disconnect when the request is complete. |
186 | | * @param port supplies the port to connect to on localhost. |
187 | | * @param method supplies the request method. |
188 | | * @param url supplies the request url. |
189 | | * @param body supplies the optional request body to send. |
190 | | * @param type supplies the codec to use for the request. |
191 | | * @param version the IP address version of the client and server. |
192 | | * @param host supplies the host header to use for the request. |
193 | | * @param content_type supplies the content-type header to use for the request, if any. |
194 | | * @return BufferingStreamDecoderPtr the complete request or a partial request if there was |
195 | | * remote early disconnection. |
196 | | */ |
197 | | static BufferingStreamDecoderPtr makeSingleRequest(uint32_t port, const std::string& method, |
198 | | const std::string& url, |
199 | | const std::string& body, Http::CodecType type, |
200 | | Network::Address::IpVersion ip_version, |
201 | | const std::string& host = "host", |
202 | | const std::string& content_type = ""); |
203 | | |
204 | | /** |
205 | | * Create transport socket factory for Quic upstream transport socket. |
206 | | * @return TransportSocketFactoryPtr the client transport socket factory. |
207 | | */ |
208 | | static Network::UpstreamTransportSocketFactoryPtr |
209 | | createQuicUpstreamTransportSocketFactory(Api::Api& api, Stats::Store& store, |
210 | | Ssl::ContextManager& context_manager, |
211 | | const std::string& san_to_match); |
212 | | |
213 | | static Http::HeaderValidatorFactoryPtr makeHeaderValidationFactory( |
214 | | const ::envoy::extensions::http::header_validators::envoy_default::v3::HeaderValidatorConfig& |
215 | | config); |
216 | | }; |
217 | | |
218 | | // A set of connection callbacks which tracks connection state. |
219 | | class ConnectionStatusCallbacks : public Network::ConnectionCallbacks { |
220 | | public: |
221 | 0 | bool connected() const { return connected_; } |
222 | 0 | bool closed() const { return closed_; } |
223 | 0 | void reset() { |
224 | 0 | connected_ = false; |
225 | 0 | closed_ = false; |
226 | 0 | } |
227 | | |
228 | | // Network::ConnectionCallbacks |
229 | 0 | void onEvent(Network::ConnectionEvent event) override { |
230 | 0 | closed_ |= (event == Network::ConnectionEvent::RemoteClose || |
231 | 0 | event == Network::ConnectionEvent::LocalClose); |
232 | 0 | connected_ |= (event == Network::ConnectionEvent::Connected); |
233 | 0 | } |
234 | 0 | void onAboveWriteBufferHighWatermark() override {} |
235 | 0 | void onBelowWriteBufferLowWatermark() override {} |
236 | | |
237 | | private: |
238 | | bool connected_{false}; |
239 | | bool closed_{false}; |
240 | | }; |
241 | | |
242 | | // A read filter which waits for a given data then stops the dispatcher loop. |
243 | | class WaitForPayloadReader : public Network::ReadFilterBaseImpl { |
244 | | public: |
245 | | WaitForPayloadReader(Event::Dispatcher& dispatcher); |
246 | | |
247 | | // Network::ReadFilter |
248 | | Network::FilterStatus onData(Buffer::Instance& data, bool end_stream) override; |
249 | | |
250 | 0 | void setDataToWaitFor(const std::string& data, bool exact_match = true) { |
251 | 0 | data_to_wait_for_ = data; |
252 | 0 | exact_match_ = exact_match; |
253 | 0 | } |
254 | | |
255 | | ABSL_MUST_USE_RESULT testing::AssertionResult waitForLength(size_t length, |
256 | 0 | std::chrono::milliseconds timeout) { |
257 | 0 | ASSERT(!wait_for_length_); |
258 | 0 | length_to_wait_for_ = length; |
259 | 0 | wait_for_length_ = true; |
260 | |
|
261 | 0 | Event::TimerPtr timeout_timer = |
262 | 0 | dispatcher_.createTimer([this]() -> void { dispatcher_.exit(); }); |
263 | 0 | timeout_timer->enableTimer(timeout); |
264 | |
|
265 | 0 | dispatcher_.run(Event::Dispatcher::RunType::Block); |
266 | |
|
267 | 0 | if (timeout_timer->enabled()) { |
268 | 0 | timeout_timer->disableTimer(); |
269 | 0 | return testing::AssertionSuccess(); |
270 | 0 | } |
271 | | |
272 | 0 | length_to_wait_for_ = 0; |
273 | 0 | wait_for_length_ = false; |
274 | 0 | return testing::AssertionFailure() << "Timed out waiting for " << length << " bytes of data\n"; |
275 | 0 | } |
276 | | |
277 | 0 | const std::string& data() { return data_; } |
278 | 0 | bool readLastByte() { return read_end_stream_; } |
279 | 0 | void clearData(size_t count = std::string::npos) { data_.erase(0, count); } |
280 | | |
281 | | private: |
282 | | Event::Dispatcher& dispatcher_; |
283 | | std::string data_to_wait_for_; |
284 | | std::string data_; |
285 | | bool exact_match_{true}; |
286 | | bool read_end_stream_{}; |
287 | | size_t length_to_wait_for_{0}; |
288 | | bool wait_for_length_{false}; |
289 | | }; |
290 | | |
291 | | } // namespace Envoy |