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 <string>
17 #include <vector>
18 
19 #include "absl/strings/string_view.h"
20 #include "absl/types/optional.h"
21 #include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h"
22 #include "net/third_party/quiche/src/http2/http2_constants.h"
23 #include "net/third_party/quiche/src/http2/http2_structures.h"
24 #include "net/third_party/quiche/src/http2/platform/api/http2_logging.h"
25 #include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
26 
27 namespace http2 {
28 namespace test {
29 
30 class FrameParts : public Http2FrameDecoderListener {
31  public:
32   // The first callback for every type of frame includes the frame header; this
33   // is the only constructor used during decoding of a frame.
34   explicit FrameParts(const Http2FrameHeader& header);
35 
36   // For use in tests where the expected frame has a variable size payload.
37   FrameParts(const Http2FrameHeader& header, absl::string_view payload);
38 
39   // For use in tests where the expected frame has a variable size payload
40   // and may be padded.
41   FrameParts(const Http2FrameHeader& header,
42              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,
99                      size_t origin_length,
100                      size_t value_length) override;
101   void OnAltSvcOriginData(const char* data, size_t len) override;
102   void OnAltSvcValueData(const char* data, size_t len) override;
103   void OnAltSvcEnd() override;
104   void OnUnknownStart(const Http2FrameHeader& header) override;
105   void OnUnknownPayload(const char* data, size_t len) override;
106   void OnUnknownEnd() override;
107   void OnPaddingTooLong(const Http2FrameHeader& header,
108                         size_t missing_length) override;
109   void OnFrameSizeError(const Http2FrameHeader& header) override;
110 
AppendSetting(const Http2SettingFields & setting_fields)111   void AppendSetting(const Http2SettingFields& setting_fields) {
112     settings_.push_back(setting_fields);
113   }
114 
GetFrameHeader()115   const Http2FrameHeader& GetFrameHeader() const { return frame_header_; }
116 
GetOptPriority()117   absl::optional<Http2PriorityFields> GetOptPriority() const {
118     return opt_priority_;
119   }
GetOptRstStreamErrorCode()120   absl::optional<Http2ErrorCode> GetOptRstStreamErrorCode() const {
121     return opt_rst_stream_error_code_;
122   }
GetOptPushPromise()123   absl::optional<Http2PushPromiseFields> GetOptPushPromise() const {
124     return opt_push_promise_;
125   }
GetOptPing()126   absl::optional<Http2PingFields> GetOptPing() const { return opt_ping_; }
GetOptGoaway()127   absl::optional<Http2GoAwayFields> GetOptGoaway() const { return opt_goaway_; }
GetOptPadLength()128   absl::optional<size_t> GetOptPadLength() const { return opt_pad_length_; }
GetOptPayloadLength()129   absl::optional<size_t> GetOptPayloadLength() const {
130     return opt_payload_length_;
131   }
GetOptMissingLength()132   absl::optional<size_t> GetOptMissingLength() const {
133     return opt_missing_length_;
134   }
GetOptAltsvcOriginLength()135   absl::optional<size_t> GetOptAltsvcOriginLength() const {
136     return opt_altsvc_origin_length_;
137   }
GetOptAltsvcValueLength()138   absl::optional<size_t> GetOptAltsvcValueLength() const {
139     return opt_altsvc_value_length_;
140   }
GetOptWindowUpdateIncrement()141   absl::optional<size_t> GetOptWindowUpdateIncrement() const {
142     return opt_window_update_increment_;
143   }
GetHasFrameSizeError()144   bool GetHasFrameSizeError() const { return has_frame_size_error_; }
145 
SetOptPriority(absl::optional<Http2PriorityFields> opt_priority)146   void SetOptPriority(absl::optional<Http2PriorityFields> opt_priority) {
147     opt_priority_ = opt_priority;
148   }
SetOptRstStreamErrorCode(absl::optional<Http2ErrorCode> opt_rst_stream_error_code)149   void SetOptRstStreamErrorCode(
150       absl::optional<Http2ErrorCode> opt_rst_stream_error_code) {
151     opt_rst_stream_error_code_ = opt_rst_stream_error_code;
152   }
SetOptPushPromise(absl::optional<Http2PushPromiseFields> opt_push_promise)153   void SetOptPushPromise(
154       absl::optional<Http2PushPromiseFields> opt_push_promise) {
155     opt_push_promise_ = opt_push_promise;
156   }
SetOptPing(absl::optional<Http2PingFields> opt_ping)157   void SetOptPing(absl::optional<Http2PingFields> opt_ping) {
158     opt_ping_ = opt_ping;
159   }
SetOptGoaway(absl::optional<Http2GoAwayFields> opt_goaway)160   void SetOptGoaway(absl::optional<Http2GoAwayFields> opt_goaway) {
161     opt_goaway_ = opt_goaway;
162   }
SetOptPadLength(absl::optional<size_t> opt_pad_length)163   void SetOptPadLength(absl::optional<size_t> opt_pad_length) {
164     opt_pad_length_ = opt_pad_length;
165   }
SetOptPayloadLength(absl::optional<size_t> opt_payload_length)166   void SetOptPayloadLength(absl::optional<size_t> opt_payload_length) {
167     opt_payload_length_ = opt_payload_length;
168   }
SetOptMissingLength(absl::optional<size_t> opt_missing_length)169   void SetOptMissingLength(absl::optional<size_t> opt_missing_length) {
170     opt_missing_length_ = opt_missing_length;
171   }
SetOptAltsvcOriginLength(absl::optional<size_t> opt_altsvc_origin_length)172   void SetOptAltsvcOriginLength(
173       absl::optional<size_t> opt_altsvc_origin_length) {
174     opt_altsvc_origin_length_ = opt_altsvc_origin_length;
175   }
SetOptAltsvcValueLength(absl::optional<size_t> opt_altsvc_value_length)176   void SetOptAltsvcValueLength(absl::optional<size_t> opt_altsvc_value_length) {
177     opt_altsvc_value_length_ = opt_altsvc_value_length;
178   }
SetOptWindowUpdateIncrement(absl::optional<size_t> opt_window_update_increment)179   void SetOptWindowUpdateIncrement(
180       absl::optional<size_t> opt_window_update_increment) {
181     opt_window_update_increment_ = opt_window_update_increment;
182   }
183 
SetHasFrameSizeError(bool has_frame_size_error)184   void SetHasFrameSizeError(bool has_frame_size_error) {
185     has_frame_size_error_ = has_frame_size_error;
186   }
187 
188  private:
189   // ASSERT during an On* method that we're handling a frame of type
190   // expected_frame_type, and have not already received other On* methods
191   // (i.e. got_start_callback is false).
192   ::testing::AssertionResult StartFrameOfType(
193       const Http2FrameHeader& header,
194       Http2FrameType expected_frame_type);
195 
196   // ASSERT that StartFrameOfType has already been called with
197   // expected_frame_type (i.e. got_start_callback has been called), and that
198   // EndFrameOfType has not yet been called (i.e. got_end_callback is false).
199   ::testing::AssertionResult InFrameOfType(Http2FrameType expected_frame_type);
200 
201   // ASSERT that we're InFrameOfType, and then sets got_end_callback=true.
202   ::testing::AssertionResult EndFrameOfType(Http2FrameType expected_frame_type);
203 
204   // ASSERT that we're in the middle of processing a frame that is padded.
205   ::testing::AssertionResult InPaddedFrame();
206 
207   // Append source to target. If opt_length is not nullptr, then verifies that
208   // the optional has a value (i.e. that the necessary On*Start method has been
209   // called), and that target is not longer than opt_length->value().
210   ::testing::AssertionResult AppendString(absl::string_view source,
211                                           std::string* target,
212                                           absl::optional<size_t>* opt_length);
213 
214   const Http2FrameHeader frame_header_;
215 
216   std::string payload_;
217   std::string padding_;
218   std::string altsvc_origin_;
219   std::string altsvc_value_;
220 
221   absl::optional<Http2PriorityFields> opt_priority_;
222   absl::optional<Http2ErrorCode> opt_rst_stream_error_code_;
223   absl::optional<Http2PushPromiseFields> opt_push_promise_;
224   absl::optional<Http2PingFields> opt_ping_;
225   absl::optional<Http2GoAwayFields> opt_goaway_;
226 
227   absl::optional<size_t> opt_pad_length_;
228   absl::optional<size_t> opt_payload_length_;
229   absl::optional<size_t> opt_missing_length_;
230   absl::optional<size_t> opt_altsvc_origin_length_;
231   absl::optional<size_t> opt_altsvc_value_length_;
232 
233   absl::optional<size_t> opt_window_update_increment_;
234 
235   bool has_frame_size_error_ = false;
236 
237   std::vector<Http2SettingFields> settings_;
238 
239   // These booleans are not checked by CompareCollectedFrames.
240   bool got_start_callback_ = false;
241   bool got_end_callback_ = false;
242 };
243 
244 std::ostream& operator<<(std::ostream& out, const FrameParts& v);
245 
246 }  // namespace test
247 }  // namespace http2
248 
249 #endif  // QUICHE_HTTP2_TEST_TOOLS_FRAME_PARTS_H_
250