Coverage Report

Created: 2024-09-19 09:45

/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