xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/adapter/test_utils.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 #ifndef QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
2 #define QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
3 
4 #include <cstdint>
5 #include <string>
6 #include <vector>
7 
8 #include "absl/container/flat_hash_map.h"
9 #include "absl/strings/string_view.h"
10 #include "quiche/http2/adapter/data_source.h"
11 #include "quiche/http2/adapter/http2_protocol.h"
12 #include "quiche/http2/adapter/mock_http2_visitor.h"
13 #include "quiche/common/platform/api/quiche_export.h"
14 #include "quiche/common/platform/api/quiche_test.h"
15 #include "quiche/spdy/core/http2_header_block.h"
16 #include "quiche/spdy/core/spdy_protocol.h"
17 
18 namespace http2 {
19 namespace adapter {
20 namespace test {
21 
22 class QUICHE_NO_EXPORT DataSavingVisitor
23     : public testing::StrictMock<MockHttp2Visitor> {
24  public:
OnReadyToSend(absl::string_view data)25   int64_t OnReadyToSend(absl::string_view data) override {
26     if (has_write_error_) {
27       return kSendError;
28     }
29     if (is_write_blocked_) {
30       return kSendBlocked;
31     }
32     const size_t to_accept = std::min(send_limit_, data.size());
33     if (to_accept == 0) {
34       return kSendBlocked;
35     }
36     absl::StrAppend(&data_, data.substr(0, to_accept));
37     return to_accept;
38   }
39 
OnMetadataForStream(Http2StreamId stream_id,absl::string_view metadata)40   bool OnMetadataForStream(Http2StreamId stream_id,
41                            absl::string_view metadata) override {
42     const bool ret = testing::StrictMock<MockHttp2Visitor>::OnMetadataForStream(
43         stream_id, metadata);
44     if (ret) {
45       auto result =
46           metadata_map_.try_emplace(stream_id, std::vector<std::string>());
47       result.first->second.push_back(std::string(metadata));
48     }
49     return ret;
50   }
51 
GetMetadata(Http2StreamId stream_id)52   const std::vector<std::string> GetMetadata(Http2StreamId stream_id) {
53     auto it = metadata_map_.find(stream_id);
54     if (it == metadata_map_.end()) {
55       return {};
56     } else {
57       return it->second;
58     }
59   }
60 
data()61   const std::string& data() { return data_; }
Clear()62   void Clear() { data_.clear(); }
63 
set_send_limit(size_t limit)64   void set_send_limit(size_t limit) { send_limit_ = limit; }
65 
is_write_blocked()66   bool is_write_blocked() const { return is_write_blocked_; }
set_is_write_blocked(bool value)67   void set_is_write_blocked(bool value) { is_write_blocked_ = value; }
68 
set_has_write_error()69   void set_has_write_error() { has_write_error_ = true; }
70 
71  private:
72   std::string data_;
73   absl::flat_hash_map<Http2StreamId, std::vector<std::string>> metadata_map_;
74   size_t send_limit_ = std::numeric_limits<size_t>::max();
75   bool is_write_blocked_ = false;
76   bool has_write_error_ = false;
77 };
78 
79 // A test DataFrameSource. Starts out in the empty, blocked state.
80 class QUICHE_NO_EXPORT TestDataFrameSource : public DataFrameSource {
81  public:
82   TestDataFrameSource(Http2VisitorInterface& visitor, bool has_fin);
83 
84   void AppendPayload(absl::string_view payload);
85   void EndData();
SimulateError()86   void SimulateError() { return_error_ = true; }
87 
88   std::pair<int64_t, bool> SelectPayloadLength(size_t max_length) override;
89   bool Send(absl::string_view frame_header, size_t payload_length) override;
send_fin()90   bool send_fin() const override { return has_fin_; }
91 
92  private:
93   Http2VisitorInterface& visitor_;
94   std::vector<std::string> payload_fragments_;
95   absl::string_view current_fragment_;
96   // Whether the stream should end with the final frame of data.
97   const bool has_fin_;
98   // Whether |payload_fragments_| contains the final segment of data.
99   bool end_data_ = false;
100   // Whether SelectPayloadLength() should return an error.
101   bool return_error_ = false;
102 };
103 
104 class QUICHE_NO_EXPORT TestMetadataSource : public MetadataSource {
105  public:
106   explicit TestMetadataSource(const spdy::Http2HeaderBlock& entries);
107 
NumFrames(size_t max_frame_size)108   size_t NumFrames(size_t max_frame_size) const override {
109     // Round up to the next frame.
110     return (encoded_entries_.size() + max_frame_size - 1) / max_frame_size;
111   }
112   std::pair<int64_t, bool> Pack(uint8_t* dest, size_t dest_len) override;
OnFailure()113   void OnFailure() override {}
114 
InjectFailure()115   void InjectFailure() { fail_when_packing_ = true; }
116 
117  private:
118   const std::string encoded_entries_;
119   absl::string_view remaining_;
120   bool fail_when_packing_ = false;
121 };
122 
123 // These matchers check whether a string consists entirely of HTTP/2 frames of
124 // the specified ordered sequence. This is useful in tests where we want to show
125 // that one or more particular frame types are serialized for sending to the
126 // peer. The match will fail if there are input bytes not consumed by the
127 // matcher.
128 
129 // Requires that frames match both types and lengths.
130 testing::Matcher<absl::string_view> EqualsFrames(
131     std::vector<std::pair<spdy::SpdyFrameType, std::optional<size_t>>>
132         types_and_lengths);
133 
134 // Requires that frames match the specified types.
135 testing::Matcher<absl::string_view> EqualsFrames(
136     std::vector<spdy::SpdyFrameType> types);
137 
138 }  // namespace test
139 }  // namespace adapter
140 }  // namespace http2
141 
142 #endif  // QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
143