1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_HTTP2_TEST_TOOLS_FRAME_PARTS_H_ 6 #define QUICHE_HTTP2_TEST_TOOLS_FRAME_PARTS_H_ 7 8 // FrameParts implements Http2FrameDecoderListener, recording the callbacks 9 // during the decoding of a single frame. It is also used for comparing the 10 // info that a test expects to be recorded during the decoding of a frame 11 // with the actual recorded value (i.e. by providing a comparator). 12 13 #include <stddef.h> 14 15 #include <cstdint> 16 #include <optional> 17 #include <string> 18 #include <vector> 19 20 #include "absl/strings/string_view.h" 21 #include "quiche/http2/decoder/http2_frame_decoder_listener.h" 22 #include "quiche/http2/http2_constants.h" 23 #include "quiche/http2/http2_structures.h" 24 #include "quiche/common/platform/api/quiche_export.h" 25 #include "quiche/common/platform/api/quiche_logging.h" 26 #include "quiche/common/platform/api/quiche_test.h" 27 28 namespace http2 { 29 namespace test { 30 31 class QUICHE_NO_EXPORT FrameParts : public Http2FrameDecoderListener { 32 public: 33 // The first callback for every type of frame includes the frame header; this 34 // is the only constructor used during decoding of a frame. 35 explicit FrameParts(const Http2FrameHeader& header); 36 37 // For use in tests where the expected frame has a variable size payload. 38 FrameParts(const Http2FrameHeader& header, absl::string_view payload); 39 40 // For use in tests where the expected frame has a variable size payload 41 // and may be padded. 42 FrameParts(const Http2FrameHeader& header, absl::string_view payload, 43 size_t total_pad_length); 44 45 // Copy constructor. 46 FrameParts(const FrameParts& header); 47 48 ~FrameParts() override; 49 50 // Returns AssertionSuccess() if they're equal, else AssertionFailure() 51 // with info about the difference. 52 ::testing::AssertionResult VerifyEquals(const FrameParts& other) const; 53 54 // Format this FrameParts object. 55 void OutputTo(std::ostream& out) const; 56 57 // Set the total padding length (0 to 256). 58 void SetTotalPadLength(size_t total_pad_length); 59 60 // Set the origin and value expected in an ALTSVC frame. 61 void SetAltSvcExpected(absl::string_view origin, absl::string_view value); 62 63 // Http2FrameDecoderListener methods: 64 bool OnFrameHeader(const Http2FrameHeader& header) override; 65 void OnDataStart(const Http2FrameHeader& header) override; 66 void OnDataPayload(const char* data, size_t len) override; 67 void OnDataEnd() override; 68 void OnHeadersStart(const Http2FrameHeader& header) override; 69 void OnHeadersPriority(const Http2PriorityFields& priority) override; 70 void OnHpackFragment(const char* data, size_t len) override; 71 void OnHeadersEnd() override; 72 void OnPriorityFrame(const Http2FrameHeader& header, 73 const Http2PriorityFields& priority) override; 74 void OnContinuationStart(const Http2FrameHeader& header) override; 75 void OnContinuationEnd() override; 76 void OnPadLength(size_t trailing_length) override; 77 void OnPadding(const char* pad, size_t skipped_length) override; 78 void OnRstStream(const Http2FrameHeader& header, 79 Http2ErrorCode error_code) override; 80 void OnSettingsStart(const Http2FrameHeader& header) override; 81 void OnSetting(const Http2SettingFields& setting_fields) override; 82 void OnSettingsEnd() override; 83 void OnSettingsAck(const Http2FrameHeader& header) override; 84 void OnPushPromiseStart(const Http2FrameHeader& header, 85 const Http2PushPromiseFields& promise, 86 size_t total_padding_length) override; 87 void OnPushPromiseEnd() override; 88 void OnPing(const Http2FrameHeader& header, 89 const Http2PingFields& ping) override; 90 void OnPingAck(const Http2FrameHeader& header, 91 const Http2PingFields& ping) override; 92 void OnGoAwayStart(const Http2FrameHeader& header, 93 const Http2GoAwayFields& goaway) override; 94 void OnGoAwayOpaqueData(const char* data, size_t len) override; 95 void OnGoAwayEnd() override; 96 void OnWindowUpdate(const Http2FrameHeader& header, 97 uint32_t increment) override; 98 void OnAltSvcStart(const Http2FrameHeader& header, size_t origin_length, 99 size_t value_length) override; 100 void OnAltSvcOriginData(const char* data, size_t len) override; 101 void OnAltSvcValueData(const char* data, size_t len) override; 102 void OnAltSvcEnd() override; 103 void OnPriorityUpdateStart( 104 const Http2FrameHeader& header, 105 const Http2PriorityUpdateFields& priority_update) override; 106 void OnPriorityUpdatePayload(const char* data, size_t len) override; 107 void OnPriorityUpdateEnd() override; 108 void OnUnknownStart(const Http2FrameHeader& header) override; 109 void OnUnknownPayload(const char* data, size_t len) override; 110 void OnUnknownEnd() override; 111 void OnPaddingTooLong(const Http2FrameHeader& header, 112 size_t missing_length) override; 113 void OnFrameSizeError(const Http2FrameHeader& header) override; 114 AppendSetting(const Http2SettingFields & setting_fields)115 void AppendSetting(const Http2SettingFields& setting_fields) { 116 settings_.push_back(setting_fields); 117 } 118 GetFrameHeader()119 const Http2FrameHeader& GetFrameHeader() const { return frame_header_; } 120 GetOptPriority()121 std::optional<Http2PriorityFields> GetOptPriority() const { 122 return opt_priority_; 123 } GetOptRstStreamErrorCode()124 std::optional<Http2ErrorCode> GetOptRstStreamErrorCode() const { 125 return opt_rst_stream_error_code_; 126 } GetOptPushPromise()127 std::optional<Http2PushPromiseFields> GetOptPushPromise() const { 128 return opt_push_promise_; 129 } GetOptPing()130 std::optional<Http2PingFields> GetOptPing() const { return opt_ping_; } GetOptGoaway()131 std::optional<Http2GoAwayFields> GetOptGoaway() const { return opt_goaway_; } GetOptPadLength()132 std::optional<size_t> GetOptPadLength() const { return opt_pad_length_; } GetOptPayloadLength()133 std::optional<size_t> GetOptPayloadLength() const { 134 return opt_payload_length_; 135 } GetOptMissingLength()136 std::optional<size_t> GetOptMissingLength() const { 137 return opt_missing_length_; 138 } GetOptAltsvcOriginLength()139 std::optional<size_t> GetOptAltsvcOriginLength() const { 140 return opt_altsvc_origin_length_; 141 } GetOptAltsvcValueLength()142 std::optional<size_t> GetOptAltsvcValueLength() const { 143 return opt_altsvc_value_length_; 144 } GetOptWindowUpdateIncrement()145 std::optional<size_t> GetOptWindowUpdateIncrement() const { 146 return opt_window_update_increment_; 147 } GetHasFrameSizeError()148 bool GetHasFrameSizeError() const { return has_frame_size_error_; } 149 SetOptPriority(std::optional<Http2PriorityFields> opt_priority)150 void SetOptPriority(std::optional<Http2PriorityFields> opt_priority) { 151 opt_priority_ = opt_priority; 152 } SetOptRstStreamErrorCode(std::optional<Http2ErrorCode> opt_rst_stream_error_code)153 void SetOptRstStreamErrorCode( 154 std::optional<Http2ErrorCode> opt_rst_stream_error_code) { 155 opt_rst_stream_error_code_ = opt_rst_stream_error_code; 156 } SetOptPushPromise(std::optional<Http2PushPromiseFields> opt_push_promise)157 void SetOptPushPromise( 158 std::optional<Http2PushPromiseFields> opt_push_promise) { 159 opt_push_promise_ = opt_push_promise; 160 } SetOptPing(std::optional<Http2PingFields> opt_ping)161 void SetOptPing(std::optional<Http2PingFields> opt_ping) { 162 opt_ping_ = opt_ping; 163 } SetOptGoaway(std::optional<Http2GoAwayFields> opt_goaway)164 void SetOptGoaway(std::optional<Http2GoAwayFields> opt_goaway) { 165 opt_goaway_ = opt_goaway; 166 } SetOptPadLength(std::optional<size_t> opt_pad_length)167 void SetOptPadLength(std::optional<size_t> opt_pad_length) { 168 opt_pad_length_ = opt_pad_length; 169 } SetOptPayloadLength(std::optional<size_t> opt_payload_length)170 void SetOptPayloadLength(std::optional<size_t> opt_payload_length) { 171 opt_payload_length_ = opt_payload_length; 172 } SetOptMissingLength(std::optional<size_t> opt_missing_length)173 void SetOptMissingLength(std::optional<size_t> opt_missing_length) { 174 opt_missing_length_ = opt_missing_length; 175 } SetOptAltsvcOriginLength(std::optional<size_t> opt_altsvc_origin_length)176 void SetOptAltsvcOriginLength( 177 std::optional<size_t> opt_altsvc_origin_length) { 178 opt_altsvc_origin_length_ = opt_altsvc_origin_length; 179 } SetOptAltsvcValueLength(std::optional<size_t> opt_altsvc_value_length)180 void SetOptAltsvcValueLength(std::optional<size_t> opt_altsvc_value_length) { 181 opt_altsvc_value_length_ = opt_altsvc_value_length; 182 } SetOptWindowUpdateIncrement(std::optional<size_t> opt_window_update_increment)183 void SetOptWindowUpdateIncrement( 184 std::optional<size_t> opt_window_update_increment) { 185 opt_window_update_increment_ = opt_window_update_increment; 186 } SetOptPriorityUpdate(std::optional<Http2PriorityUpdateFields> priority_update)187 void SetOptPriorityUpdate( 188 std::optional<Http2PriorityUpdateFields> priority_update) { 189 opt_priority_update_ = priority_update; 190 } 191 SetHasFrameSizeError(bool has_frame_size_error)192 void SetHasFrameSizeError(bool has_frame_size_error) { 193 has_frame_size_error_ = has_frame_size_error; 194 } 195 196 private: 197 // ASSERT during an On* method that we're handling a frame of type 198 // expected_frame_type, and have not already received other On* methods 199 // (i.e. got_start_callback is false). 200 ::testing::AssertionResult StartFrameOfType( 201 const Http2FrameHeader& header, Http2FrameType expected_frame_type); 202 203 // ASSERT that StartFrameOfType has already been called with 204 // expected_frame_type (i.e. got_start_callback has been called), and that 205 // EndFrameOfType has not yet been called (i.e. got_end_callback is false). 206 ::testing::AssertionResult InFrameOfType(Http2FrameType expected_frame_type); 207 208 // ASSERT that we're InFrameOfType, and then sets got_end_callback=true. 209 ::testing::AssertionResult EndFrameOfType(Http2FrameType expected_frame_type); 210 211 // ASSERT that we're in the middle of processing a frame that is padded. 212 ::testing::AssertionResult InPaddedFrame(); 213 214 // Append source to target. If opt_length is not nullptr, then verifies that 215 // the optional has a value (i.e. that the necessary On*Start method has been 216 // called), and that target is not longer than opt_length->value(). 217 ::testing::AssertionResult AppendString(absl::string_view source, 218 std::string* target, 219 std::optional<size_t>* opt_length); 220 221 const Http2FrameHeader frame_header_; 222 223 std::string payload_; 224 std::string padding_; 225 std::string altsvc_origin_; 226 std::string altsvc_value_; 227 228 std::optional<Http2PriorityFields> opt_priority_; 229 std::optional<Http2ErrorCode> opt_rst_stream_error_code_; 230 std::optional<Http2PushPromiseFields> opt_push_promise_; 231 std::optional<Http2PingFields> opt_ping_; 232 std::optional<Http2GoAwayFields> opt_goaway_; 233 std::optional<Http2PriorityUpdateFields> opt_priority_update_; 234 235 std::optional<size_t> opt_pad_length_; 236 std::optional<size_t> opt_payload_length_; 237 std::optional<size_t> opt_missing_length_; 238 std::optional<size_t> opt_altsvc_origin_length_; 239 std::optional<size_t> opt_altsvc_value_length_; 240 241 std::optional<size_t> opt_window_update_increment_; 242 243 bool has_frame_size_error_ = false; 244 245 std::vector<Http2SettingFields> settings_; 246 247 // These booleans are not checked by CompareCollectedFrames. 248 bool got_start_callback_ = false; 249 bool got_end_callback_ = false; 250 }; 251 252 QUICHE_NO_EXPORT std::ostream& operator<<(std::ostream& out, 253 const FrameParts& v); 254 255 } // namespace test 256 } // namespace http2 257 258 #endif // QUICHE_HTTP2_TEST_TOOLS_FRAME_PARTS_H_ 259