| #ifndef QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_ | |
| #define QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_ | |
| #include <cstdint> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/container/flat_hash_map.h" | |
| #include "absl/strings/string_view.h" | |
| #include "http2/adapter/data_source.h" | |
| #include "http2/adapter/http2_protocol.h" | |
| #include "http2/adapter/mock_http2_visitor.h" | |
| #include "common/platform/api/quiche_export.h" | |
| #include "common/platform/api/quiche_test.h" | |
| #include "spdy/core/spdy_header_block.h" | |
| #include "spdy/core/spdy_protocol.h" | |
| namespace http2 { | |
| namespace adapter { | |
| namespace test { | |
| class QUICHE_NO_EXPORT DataSavingVisitor | |
| : public testing::StrictMock<MockHttp2Visitor> { | |
| public: | |
| int64_t OnReadyToSend(absl::string_view data) override { | |
| if (has_write_error_) { | |
| return kSendError; | |
| } | |
| if (is_write_blocked_) { | |
| return kSendBlocked; | |
| } | |
| const size_t to_accept = std::min(send_limit_, data.size()); | |
| if (to_accept == 0) { | |
| return kSendBlocked; | |
| } | |
| absl::StrAppend(&data_, data.substr(0, to_accept)); | |
| return to_accept; | |
| } | |
| bool OnMetadataForStream(Http2StreamId stream_id, | |
| absl::string_view metadata) override { | |
| const bool ret = testing::StrictMock<MockHttp2Visitor>::OnMetadataForStream( | |
| stream_id, metadata); | |
| if (ret) { | |
| auto result = | |
| metadata_map_.try_emplace(stream_id, std::vector<std::string>()); | |
| result.first->second.push_back(std::string(metadata)); | |
| } | |
| return ret; | |
| } | |
| const std::vector<std::string> GetMetadata(Http2StreamId stream_id) { | |
| auto it = metadata_map_.find(stream_id); | |
| if (it == metadata_map_.end()) { | |
| return {}; | |
| } else { | |
| return it->second; | |
| } | |
| } | |
| const std::string& data() { return data_; } | |
| void Clear() { data_.clear(); } | |
| void set_send_limit(size_t limit) { send_limit_ = limit; } | |
| bool is_write_blocked() const { return is_write_blocked_; } | |
| void set_is_write_blocked(bool value) { is_write_blocked_ = value; } | |
| void set_has_write_error() { has_write_error_ = true; } | |
| private: | |
| std::string data_; | |
| absl::flat_hash_map<Http2StreamId, std::vector<std::string>> metadata_map_; | |
| size_t send_limit_ = std::numeric_limits<size_t>::max(); | |
| bool is_write_blocked_ = false; | |
| bool has_write_error_ = false; | |
| }; | |
| // A test DataFrameSource. Starts out in the empty, blocked state. | |
| class QUICHE_NO_EXPORT TestDataFrameSource : public DataFrameSource { | |
| public: | |
| TestDataFrameSource(Http2VisitorInterface& visitor, bool has_fin); | |
| void AppendPayload(absl::string_view payload); | |
| void EndData(); | |
| void SimulateError() { return_error_ = true; } | |
| std::pair<int64_t, bool> SelectPayloadLength(size_t max_length) override; | |
| bool Send(absl::string_view frame_header, size_t payload_length) override; | |
| bool send_fin() const override { return has_fin_; } | |
| private: | |
| Http2VisitorInterface& visitor_; | |
| std::vector<std::string> payload_fragments_; | |
| absl::string_view current_fragment_; | |
| // Whether the stream should end with the final frame of data. | |
| const bool has_fin_; | |
| // Whether |payload_fragments_| contains the final segment of data. | |
| bool end_data_ = false; | |
| // Whether SelectPayloadLength() should return an error. | |
| bool return_error_ = false; | |
| }; | |
| class QUICHE_NO_EXPORT TestMetadataSource : public MetadataSource { | |
| public: | |
| explicit TestMetadataSource(const spdy::SpdyHeaderBlock& entries); | |
| size_t NumFrames(size_t max_frame_size) const override { | |
| // Round up to the next frame. | |
| return (encoded_entries_.size() + max_frame_size - 1) / max_frame_size; | |
| } | |
| std::pair<int64_t, bool> Pack(uint8_t* dest, size_t dest_len) override; | |
| void OnFailure() override {} | |
| private: | |
| const std::string encoded_entries_; | |
| absl::string_view remaining_; | |
| }; | |
| // These matchers check whether a string consists entirely of HTTP/2 frames of | |
| // the specified ordered sequence. This is useful in tests where we want to show | |
| // that one or more particular frame types are serialized for sending to the | |
| // peer. The match will fail if there are input bytes not consumed by the | |
| // matcher. | |
| // Requires that frames match both types and lengths. | |
| testing::Matcher<absl::string_view> EqualsFrames( | |
| std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>> | |
| types_and_lengths); | |
| // Requires that frames match the specified types. | |
| testing::Matcher<absl::string_view> EqualsFrames( | |
| std::vector<spdy::SpdyFrameType> types); | |
| } // namespace test | |
| } // namespace adapter | |
| } // namespace http2 | |
| #endif // QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_ |