Coverage Report

Created: 2024-09-19 09:45

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