/proc/self/cwd/test/integration/autonomous_upstream.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "test/integration/autonomous_upstream.h" |
2 | | |
3 | | namespace Envoy { |
4 | | namespace { |
5 | | |
6 | | void headerToInt(const char header_name[], int32_t& return_int, |
7 | 2.35k | Http::TestResponseHeaderMapImpl& headers) { |
8 | 2.35k | const std::string header_value(headers.get_(header_name)); |
9 | 2.35k | if (!header_value.empty()) { |
10 | 0 | uint64_t parsed_value; |
11 | 0 | RELEASE_ASSERT(absl::SimpleAtoi(header_value, &parsed_value) && |
12 | 0 | parsed_value < static_cast<uint32_t>(std::numeric_limits<int32_t>::max()), |
13 | 0 | ""); |
14 | 0 | return_int = parsed_value; |
15 | 0 | } |
16 | 2.35k | } |
17 | | |
18 | | } // namespace |
19 | | |
20 | | const char AutonomousStream::RESPONSE_SIZE_BYTES[] = "response_size_bytes"; |
21 | | const char AutonomousStream::RESPONSE_DATA_BLOCKS[] = "response_data_blocks"; |
22 | | const char AutonomousStream::EXPECT_REQUEST_SIZE_BYTES[] = "expect_request_size_bytes"; |
23 | | const char AutonomousStream::RESET_AFTER_REQUEST[] = "reset_after_request"; |
24 | | const char AutonomousStream::RESET_AFTER_RESPONSE_HEADERS[] = "reset_after_response_headers"; |
25 | | const char AutonomousStream::RESET_AFTER_RESPONSE_DATA[] = "reset_after_response_data"; |
26 | | const char AutonomousStream::CLOSE_AFTER_RESPONSE[] = "close_after_response"; |
27 | | const char AutonomousStream::NO_TRAILERS[] = "no_trailers"; |
28 | | const char AutonomousStream::NO_END_STREAM[] = "no_end_stream"; |
29 | | const char AutonomousStream::RESPOND_AFTER_REQUEST_HEADERS[] = "respond_after_request_headers"; |
30 | | |
31 | | AutonomousStream::AutonomousStream(FakeHttpConnection& parent, Http::ResponseEncoder& encoder, |
32 | | AutonomousUpstream& upstream, bool allow_incomplete_streams) |
33 | | : FakeStream(parent, encoder, upstream.timeSystem()), upstream_(upstream), |
34 | 786 | allow_incomplete_streams_(allow_incomplete_streams) {} Unexecuted instantiation: Envoy::AutonomousStream::AutonomousStream(Envoy::FakeHttpConnection&, Envoy::Http::ResponseEncoder&, Envoy::AutonomousUpstream&, bool) Envoy::AutonomousStream::AutonomousStream(Envoy::FakeHttpConnection&, Envoy::Http::ResponseEncoder&, Envoy::AutonomousUpstream&, bool) Line | Count | Source | 34 | 786 | allow_incomplete_streams_(allow_incomplete_streams) {} |
|
35 | | |
36 | 786 | AutonomousStream::~AutonomousStream() { |
37 | 786 | if (!allow_incomplete_streams_) { |
38 | 0 | RELEASE_ASSERT(complete(), "Found that end_stream is not true"); |
39 | 0 | } |
40 | 786 | } |
41 | | |
42 | 786 | void AutonomousStream::decodeHeaders(Http::RequestHeaderMapSharedPtr&& headers, bool end_stream) { |
43 | 786 | bool send_response = !headers->get(Http::LowerCaseString(RESPOND_AFTER_REQUEST_HEADERS)).empty(); |
44 | 786 | FakeStream::decodeHeaders(std::move(headers), end_stream); |
45 | | |
46 | 786 | if (send_response) { |
47 | 0 | absl::MutexLock lock(&lock_); |
48 | 0 | sendResponse(); |
49 | 0 | } |
50 | 786 | } |
51 | | |
52 | | // By default, automatically send a response when the request is complete. |
53 | 1.22k | void AutonomousStream::setEndStream(bool end_stream) { |
54 | 1.22k | FakeStream::setEndStream(end_stream); |
55 | 1.22k | if (end_stream && headers_->get(Http::LowerCaseString(RESPOND_AFTER_REQUEST_HEADERS)).empty()) { |
56 | 786 | sendResponse(); |
57 | 786 | } |
58 | 1.22k | } |
59 | | |
60 | | // Check all the special headers and send a customized response based on them. |
61 | 786 | void AutonomousStream::sendResponse() { |
62 | 786 | Http::TestResponseHeaderMapImpl headers(*headers_); |
63 | 786 | upstream_.setLastRequestHeaders(*headers_); |
64 | | |
65 | 786 | int32_t request_body_length = -1; |
66 | 786 | headerToInt(EXPECT_REQUEST_SIZE_BYTES, request_body_length, headers); |
67 | 786 | if (request_body_length >= 0) { |
68 | 0 | EXPECT_EQ(request_body_length, body_.length()); |
69 | 0 | } |
70 | | |
71 | 786 | if (!headers.get_(RESET_AFTER_REQUEST).empty()) { |
72 | 0 | encodeResetStream(); |
73 | 0 | return; |
74 | 0 | } |
75 | | |
76 | 786 | int32_t response_body_length = 10; |
77 | 786 | headerToInt(RESPONSE_SIZE_BYTES, response_body_length, headers); |
78 | | |
79 | 786 | int32_t response_data_blocks = 1; |
80 | 786 | headerToInt(RESPONSE_DATA_BLOCKS, response_data_blocks, headers); |
81 | | |
82 | 786 | const bool end_stream = headers.get_(NO_END_STREAM).empty(); |
83 | 786 | const bool send_trailers = end_stream && headers.get_(NO_TRAILERS).empty(); |
84 | 786 | const bool headers_only_response = !send_trailers && response_data_blocks == 0 && end_stream; |
85 | | |
86 | 786 | pre_response_headers_metadata_ = upstream_.preResponseHeadersMetadata(); |
87 | 786 | if (pre_response_headers_metadata_) { |
88 | 0 | encodeMetadata(*pre_response_headers_metadata_); |
89 | 0 | } |
90 | | |
91 | 786 | encodeHeaders(upstream_.responseHeaders(), headers_only_response); |
92 | | |
93 | 786 | if (!headers.get_(RESET_AFTER_RESPONSE_HEADERS).empty()) { |
94 | 0 | encodeResetStream(); |
95 | 0 | return; |
96 | 0 | } |
97 | | |
98 | 786 | if (!headers_only_response) { |
99 | 786 | if (upstream_.responseBody().has_value()) { |
100 | 0 | encodeData(*upstream_.responseBody(), !send_trailers); |
101 | 786 | } else { |
102 | 1.57k | for (int32_t i = 0; i < response_data_blocks; ++i) { |
103 | 786 | encodeData(response_body_length, |
104 | 786 | i == (response_data_blocks - 1) && !send_trailers && end_stream); |
105 | | |
106 | 786 | if (!headers.get_(RESET_AFTER_RESPONSE_DATA).empty()) { |
107 | 0 | encodeResetStream(); |
108 | 0 | return; |
109 | 0 | } |
110 | 786 | } |
111 | 786 | } |
112 | 786 | if (send_trailers) { |
113 | 786 | encodeTrailers(upstream_.responseTrailers()); |
114 | 786 | } |
115 | 786 | } |
116 | 786 | if (!headers.get_(CLOSE_AFTER_RESPONSE).empty()) { |
117 | 0 | parent_.connection().dispatcher().post( |
118 | 0 | [this]() -> void { parent_.connection().close(Network::ConnectionCloseType::FlushWrite); }); |
119 | 0 | return; |
120 | 0 | } |
121 | 786 | } |
122 | | |
123 | | AutonomousHttpConnection::AutonomousHttpConnection(AutonomousUpstream& autonomous_upstream, |
124 | | SharedConnectionWrapper& shared_connection, |
125 | | Http::CodecType type, |
126 | | uint32_t max_request_headers_kb, |
127 | | uint32_t max_request_headers_count, |
128 | | AutonomousUpstream& upstream) |
129 | | : FakeHttpConnection(autonomous_upstream, shared_connection, type, upstream.timeSystem(), |
130 | | max_request_headers_kb, max_request_headers_count, |
131 | | envoy::config::core::v3::HttpProtocolOptions::ALLOW), |
132 | 393 | upstream_(upstream) {} Unexecuted instantiation: Envoy::AutonomousHttpConnection::AutonomousHttpConnection(Envoy::AutonomousUpstream&, Envoy::SharedConnectionWrapper&, Envoy::Http::CodecType, unsigned int, unsigned int, Envoy::AutonomousUpstream&) Envoy::AutonomousHttpConnection::AutonomousHttpConnection(Envoy::AutonomousUpstream&, Envoy::SharedConnectionWrapper&, Envoy::Http::CodecType, unsigned int, unsigned int, Envoy::AutonomousUpstream&) Line | Count | Source | 132 | 393 | upstream_(upstream) {} |
|
133 | | |
134 | | Http::RequestDecoder& AutonomousHttpConnection::newStream(Http::ResponseEncoder& response_encoder, |
135 | 786 | bool) { |
136 | 786 | auto stream = |
137 | 786 | new AutonomousStream(*this, response_encoder, upstream_, upstream_.allow_incomplete_streams_); |
138 | 786 | streams_.push_back(FakeStreamPtr{stream}); |
139 | 786 | return *(stream); |
140 | 786 | } |
141 | | |
142 | 403 | AutonomousUpstream::~AutonomousUpstream() { |
143 | | // Make sure the dispatcher is stopped before the connections are destroyed. |
144 | 403 | cleanUp(); |
145 | 403 | http_connections_.clear(); |
146 | 403 | } |
147 | | |
148 | | bool AutonomousUpstream::createNetworkFilterChain(Network::Connection& connection, |
149 | 393 | const Filter::NetworkFilterFactoriesList&) { |
150 | 393 | shared_connections_.emplace_back(new SharedConnectionWrapper(connection)); |
151 | 393 | AutonomousHttpConnectionPtr http_connection(new AutonomousHttpConnection( |
152 | 393 | *this, *shared_connections_.back(), http_type_, config().max_request_headers_kb_, |
153 | 393 | config().max_request_headers_count_, *this)); |
154 | 393 | http_connection->initialize(); |
155 | 393 | http_connections_.push_back(std::move(http_connection)); |
156 | 393 | return true; |
157 | 393 | } |
158 | | |
159 | 393 | bool AutonomousUpstream::createListenerFilterChain(Network::ListenerFilterManager&) { return true; } |
160 | | |
161 | | void AutonomousUpstream::createUdpListenerFilterChain(Network::UdpListenerFilterManager&, |
162 | 0 | Network::UdpReadFilterCallbacks&) {} |
163 | | |
164 | 0 | bool AutonomousUpstream::createQuicListenerFilterChain(Network::QuicListenerFilterManager&) { |
165 | 0 | return true; |
166 | 0 | } |
167 | | |
168 | 786 | void AutonomousUpstream::setLastRequestHeaders(const Http::HeaderMap& headers) { |
169 | 786 | Thread::LockGuard lock(headers_lock_); |
170 | 786 | last_request_headers_ = std::make_unique<Http::TestRequestHeaderMapImpl>(headers); |
171 | 786 | } |
172 | | |
173 | 0 | std::unique_ptr<Http::TestRequestHeaderMapImpl> AutonomousUpstream::lastRequestHeaders() { |
174 | 0 | Thread::LockGuard lock(headers_lock_); |
175 | 0 | return std::move(last_request_headers_); |
176 | 0 | } |
177 | | |
178 | | void AutonomousUpstream::setResponseTrailers( |
179 | 0 | std::unique_ptr<Http::TestResponseTrailerMapImpl>&& response_trailers) { |
180 | 0 | Thread::LockGuard lock(headers_lock_); |
181 | 0 | response_trailers_ = std::move(response_trailers); |
182 | 0 | } |
183 | | |
184 | 0 | void AutonomousUpstream::setResponseBody(std::string body) { |
185 | 0 | Thread::LockGuard lock(headers_lock_); |
186 | 0 | response_body_ = body; |
187 | 0 | } |
188 | | |
189 | | void AutonomousUpstream::setResponseHeaders( |
190 | 0 | std::unique_ptr<Http::TestResponseHeaderMapImpl>&& response_headers) { |
191 | 0 | Thread::LockGuard lock(headers_lock_); |
192 | 0 | response_headers_ = std::move(response_headers); |
193 | 0 | } |
194 | | |
195 | | void AutonomousUpstream::setPreResponseHeadersMetadata( |
196 | 0 | std::unique_ptr<Http::MetadataMapVector>&& metadata) { |
197 | 0 | Thread::LockGuard lock(headers_lock_); |
198 | 0 | pre_response_headers_metadata_ = std::move(metadata); |
199 | 0 | } |
200 | | |
201 | 786 | Http::TestResponseTrailerMapImpl AutonomousUpstream::responseTrailers() { |
202 | 786 | Thread::LockGuard lock(headers_lock_); |
203 | 786 | Http::TestResponseTrailerMapImpl return_trailers = *response_trailers_; |
204 | 786 | return return_trailers; |
205 | 786 | } |
206 | | |
207 | 786 | absl::optional<std::string> AutonomousUpstream::responseBody() { |
208 | 786 | Thread::LockGuard lock(headers_lock_); |
209 | 786 | return response_body_; |
210 | 786 | } |
211 | | |
212 | 786 | Http::TestResponseHeaderMapImpl AutonomousUpstream::responseHeaders() { |
213 | 786 | Thread::LockGuard lock(headers_lock_); |
214 | 786 | Http::TestResponseHeaderMapImpl return_headers = *response_headers_; |
215 | 786 | return return_headers; |
216 | 786 | } |
217 | | |
218 | 786 | std::unique_ptr<Http::MetadataMapVector> AutonomousUpstream::preResponseHeadersMetadata() { |
219 | 786 | Thread::LockGuard lock(headers_lock_); |
220 | 786 | return std::move(pre_response_headers_metadata_); |
221 | 786 | } |
222 | | |
223 | | AssertionResult AutonomousUpstream::closeConnection(uint32_t index, |
224 | 0 | std::chrono::milliseconds timeout) { |
225 | 0 | return shared_connections_[index]->executeOnDispatcher( |
226 | 0 | [](Network::Connection& connection) { |
227 | 0 | ASSERT(connection.state() == Network::Connection::State::Open); |
228 | 0 | connection.close(Network::ConnectionCloseType::FlushWrite); |
229 | 0 | }, |
230 | 0 | timeout); |
231 | 0 | } |
232 | | |
233 | | } // namespace Envoy |