1 #ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_ 2 #define QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_ 3 4 #include <cstdint> 5 #include <vector> 6 7 #include "absl/strings/string_view.h" 8 #include "quiche/http2/adapter/http2_protocol.h" 9 #include "quiche/http2/adapter/nghttp2.h" 10 #include "quiche/common/platform/api/quiche_export.h" 11 #include "quiche/common/platform/api/quiche_test.h" 12 13 namespace http2 { 14 namespace adapter { 15 namespace test { 16 17 // A simple class that can easily be adapted to act as a nghttp2_data_source. 18 class QUICHE_NO_EXPORT TestDataSource { 19 public: TestDataSource(absl::string_view data)20 explicit TestDataSource(absl::string_view data) : data_(std::string(data)) {} 21 ReadNext(size_t size)22 absl::string_view ReadNext(size_t size) { 23 const size_t to_send = std::min(size, remaining_.size()); 24 auto ret = remaining_.substr(0, to_send); 25 remaining_.remove_prefix(to_send); 26 return ret; 27 } 28 SelectPayloadLength(size_t max_length)29 size_t SelectPayloadLength(size_t max_length) { 30 return std::min(max_length, remaining_.size()); 31 } 32 MakeDataProvider()33 nghttp2_data_provider MakeDataProvider() { 34 nghttp2_data_source s; 35 s.ptr = this; 36 return nghttp2_data_provider{ 37 s, 38 [](nghttp2_session*, int32_t, uint8_t*, size_t length, 39 uint32_t* data_flags, nghttp2_data_source* source, 40 void*) -> ssize_t { 41 *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; 42 auto* s = static_cast<TestDataSource*>(source->ptr); 43 if (!s->is_data_available()) { 44 return NGHTTP2_ERR_DEFERRED; 45 } 46 const ssize_t ret = s->SelectPayloadLength(length); 47 if (ret < static_cast<ssize_t>(length)) { 48 *data_flags |= NGHTTP2_DATA_FLAG_EOF; 49 } 50 return ret; 51 }}; 52 } 53 is_data_available()54 bool is_data_available() const { return is_data_available_; } set_is_data_available(bool value)55 void set_is_data_available(bool value) { is_data_available_ = value; } 56 57 private: 58 const std::string data_; 59 absl::string_view remaining_ = data_; 60 bool is_data_available_ = true; 61 }; 62 63 // Matchers for nghttp2 data types. 64 testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader( 65 uint32_t streamid, uint8_t type, const testing::Matcher<int> flags); 66 testing::Matcher<const nghttp2_frame_hd&> HasFrameHeaderRef( 67 uint32_t streamid, uint8_t type, const testing::Matcher<int> flags); 68 69 testing::Matcher<const nghttp2_frame*> IsData( 70 const testing::Matcher<uint32_t> stream_id, 71 const testing::Matcher<size_t> length, const testing::Matcher<int> flags, 72 const testing::Matcher<size_t> padding = testing::_); 73 74 testing::Matcher<const nghttp2_frame*> IsHeaders( 75 const testing::Matcher<uint32_t> stream_id, 76 const testing::Matcher<int> flags, const testing::Matcher<int> category); 77 78 testing::Matcher<const nghttp2_frame*> IsRstStream( 79 const testing::Matcher<uint32_t> stream_id, 80 const testing::Matcher<uint32_t> error_code); 81 82 testing::Matcher<const nghttp2_frame*> IsSettings( 83 const testing::Matcher<std::vector<Http2Setting>> values); 84 85 testing::Matcher<const nghttp2_frame*> IsPing( 86 const testing::Matcher<uint64_t> id); 87 88 testing::Matcher<const nghttp2_frame*> IsPingAck( 89 const testing::Matcher<uint64_t> id); 90 91 testing::Matcher<const nghttp2_frame*> IsGoAway( 92 const testing::Matcher<uint32_t> last_stream_id, 93 const testing::Matcher<uint32_t> error_code, 94 const testing::Matcher<absl::string_view> opaque_data); 95 96 testing::Matcher<const nghttp2_frame*> IsWindowUpdate( 97 const testing::Matcher<uint32_t> delta); 98 99 } // namespace test 100 } // namespace adapter 101 } // namespace http2 102 103 #endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_ 104