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