Coverage Report

Created: 2023-11-12 09:30

/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