xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/test_tools/frame_parts.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "quiche/http2/test_tools/frame_parts.h"
6 
7 #include <optional>
8 #include <type_traits>
9 
10 #include "absl/strings/escaping.h"
11 #include "quiche/http2/test_tools/http2_structures_test_util.h"
12 #include "quiche/http2/test_tools/verify_macros.h"
13 #include "quiche/common/platform/api/quiche_logging.h"
14 #include "quiche/common/platform/api/quiche_test.h"
15 
16 using ::testing::AssertionFailure;
17 using ::testing::AssertionResult;
18 using ::testing::AssertionSuccess;
19 using ::testing::ContainerEq;
20 
21 namespace http2 {
22 namespace test {
23 namespace {
24 
25 static_assert(std::is_base_of<Http2FrameDecoderListener, FrameParts>::value &&
26                   !std::is_abstract<FrameParts>::value,
27               "FrameParts needs to implement all of the methods of "
28               "Http2FrameDecoderListener");
29 
30 // Compare two optional variables of the same type.
31 // TODO(jamessynge): Maybe create a ::testing::Matcher for this.
32 template <class T>
VerifyOptionalEq(const T & opt_a,const T & opt_b)33 AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) {
34   if (opt_a) {
35     if (opt_b) {
36       HTTP2_VERIFY_EQ(opt_a.value(), opt_b.value());
37     } else {
38       return AssertionFailure()
39              << "opt_b is not set; opt_a.value()=" << opt_a.value();
40     }
41   } else if (opt_b) {
42     return AssertionFailure()
43            << "opt_a is not set; opt_b.value()=" << opt_b.value();
44   }
45   return AssertionSuccess();
46 }
47 
48 }  // namespace
49 
FrameParts(const Http2FrameHeader & header)50 FrameParts::FrameParts(const Http2FrameHeader& header) : frame_header_(header) {
51   QUICHE_VLOG(1) << "FrameParts, header: " << frame_header_;
52 }
53 
FrameParts(const Http2FrameHeader & header,absl::string_view payload)54 FrameParts::FrameParts(const Http2FrameHeader& header,
55                        absl::string_view payload)
56     : FrameParts(header) {
57   QUICHE_VLOG(1) << "FrameParts with payload.size() = " << payload.size();
58   this->payload_.append(payload.data(), payload.size());
59   opt_payload_length_ = payload.size();
60 }
FrameParts(const Http2FrameHeader & header,absl::string_view payload,size_t total_pad_length)61 FrameParts::FrameParts(const Http2FrameHeader& header,
62                        absl::string_view payload, size_t total_pad_length)
63     : FrameParts(header, payload) {
64   QUICHE_VLOG(1) << "FrameParts with total_pad_length=" << total_pad_length;
65   SetTotalPadLength(total_pad_length);
66 }
67 
68 FrameParts::FrameParts(const FrameParts& header) = default;
69 
70 FrameParts::~FrameParts() = default;
71 
VerifyEquals(const FrameParts & that) const72 AssertionResult FrameParts::VerifyEquals(const FrameParts& that) const {
73 #define COMMON_MESSAGE "\n  this: " << *this << "\n  that: " << that
74 
75   HTTP2_VERIFY_EQ(frame_header_, that.frame_header_) << COMMON_MESSAGE;
76   HTTP2_VERIFY_EQ(payload_, that.payload_) << COMMON_MESSAGE;
77   HTTP2_VERIFY_EQ(padding_, that.padding_) << COMMON_MESSAGE;
78   HTTP2_VERIFY_EQ(altsvc_origin_, that.altsvc_origin_) << COMMON_MESSAGE;
79   HTTP2_VERIFY_EQ(altsvc_value_, that.altsvc_value_) << COMMON_MESSAGE;
80   HTTP2_VERIFY_EQ(settings_, that.settings_) << COMMON_MESSAGE;
81 
82 #define HTTP2_VERIFY_OPTIONAL_FIELD(field_name) \
83   HTTP2_VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name))
84 
85   HTTP2_VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length_) << COMMON_MESSAGE;
86   HTTP2_VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length_) << COMMON_MESSAGE;
87   HTTP2_VERIFY_OPTIONAL_FIELD(opt_priority_update_) << COMMON_MESSAGE;
88   HTTP2_VERIFY_OPTIONAL_FIELD(opt_goaway_) << COMMON_MESSAGE;
89   HTTP2_VERIFY_OPTIONAL_FIELD(opt_missing_length_) << COMMON_MESSAGE;
90   HTTP2_VERIFY_OPTIONAL_FIELD(opt_pad_length_) << COMMON_MESSAGE;
91   HTTP2_VERIFY_OPTIONAL_FIELD(opt_ping_) << COMMON_MESSAGE;
92   HTTP2_VERIFY_OPTIONAL_FIELD(opt_priority_) << COMMON_MESSAGE;
93   HTTP2_VERIFY_OPTIONAL_FIELD(opt_push_promise_) << COMMON_MESSAGE;
94   HTTP2_VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code_) << COMMON_MESSAGE;
95   HTTP2_VERIFY_OPTIONAL_FIELD(opt_window_update_increment_) << COMMON_MESSAGE;
96 
97 #undef HTTP2_VERIFY_OPTIONAL_FIELD
98 
99   return AssertionSuccess();
100 }
101 
SetTotalPadLength(size_t total_pad_length)102 void FrameParts::SetTotalPadLength(size_t total_pad_length) {
103   opt_pad_length_.reset();
104   padding_.clear();
105   if (total_pad_length > 0) {
106     ASSERT_LE(total_pad_length, 256u);
107     ASSERT_TRUE(frame_header_.IsPadded());
108     opt_pad_length_ = total_pad_length - 1;
109     char zero = 0;
110     padding_.append(opt_pad_length_.value(), zero);
111   }
112 
113   if (opt_pad_length_) {
114     QUICHE_VLOG(1) << "SetTotalPadLength: pad_length="
115                    << opt_pad_length_.value();
116   } else {
117     QUICHE_VLOG(1) << "SetTotalPadLength: has no pad length";
118   }
119 }
120 
SetAltSvcExpected(absl::string_view origin,absl::string_view value)121 void FrameParts::SetAltSvcExpected(absl::string_view origin,
122                                    absl::string_view value) {
123   altsvc_origin_.append(origin.data(), origin.size());
124   altsvc_value_.append(value.data(), value.size());
125   opt_altsvc_origin_length_ = origin.size();
126   opt_altsvc_value_length_ = value.size();
127 }
128 
OnFrameHeader(const Http2FrameHeader &)129 bool FrameParts::OnFrameHeader(const Http2FrameHeader& /*header*/) {
130   ADD_FAILURE() << "OnFrameHeader: " << *this;
131   return true;
132 }
133 
OnDataStart(const Http2FrameHeader & header)134 void FrameParts::OnDataStart(const Http2FrameHeader& header) {
135   QUICHE_VLOG(1) << "OnDataStart: " << header;
136   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::DATA)) << *this;
137   opt_payload_length_ = header.payload_length;
138 }
139 
OnDataPayload(const char * data,size_t len)140 void FrameParts::OnDataPayload(const char* data, size_t len) {
141   QUICHE_VLOG(1) << "OnDataPayload: len=" << len
142                  << "; frame_header_: " << frame_header_;
143   ASSERT_TRUE(InFrameOfType(Http2FrameType::DATA)) << *this;
144   ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
145                            &opt_payload_length_));
146 }
147 
OnDataEnd()148 void FrameParts::OnDataEnd() {
149   QUICHE_VLOG(1) << "OnDataEnd; frame_header_: " << frame_header_;
150   ASSERT_TRUE(EndFrameOfType(Http2FrameType::DATA)) << *this;
151 }
152 
OnHeadersStart(const Http2FrameHeader & header)153 void FrameParts::OnHeadersStart(const Http2FrameHeader& header) {
154   QUICHE_VLOG(1) << "OnHeadersStart: " << header;
155   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::HEADERS)) << *this;
156   opt_payload_length_ = header.payload_length;
157 }
158 
OnHeadersPriority(const Http2PriorityFields & priority)159 void FrameParts::OnHeadersPriority(const Http2PriorityFields& priority) {
160   QUICHE_VLOG(1) << "OnHeadersPriority: priority: " << priority
161                  << "; frame_header_: " << frame_header_;
162   ASSERT_TRUE(InFrameOfType(Http2FrameType::HEADERS)) << *this;
163   ASSERT_FALSE(opt_priority_);
164   opt_priority_ = priority;
165   ASSERT_TRUE(opt_payload_length_);
166   opt_payload_length_ =
167       opt_payload_length_.value() - Http2PriorityFields::EncodedSize();
168 }
169 
OnHpackFragment(const char * data,size_t len)170 void FrameParts::OnHpackFragment(const char* data, size_t len) {
171   QUICHE_VLOG(1) << "OnHpackFragment: len=" << len
172                  << "; frame_header_: " << frame_header_;
173   ASSERT_TRUE(got_start_callback_);
174   ASSERT_FALSE(got_end_callback_);
175   ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header_)) << *this;
176   ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
177                            &opt_payload_length_));
178 }
179 
OnHeadersEnd()180 void FrameParts::OnHeadersEnd() {
181   QUICHE_VLOG(1) << "OnHeadersEnd; frame_header_: " << frame_header_;
182   ASSERT_TRUE(EndFrameOfType(Http2FrameType::HEADERS)) << *this;
183 }
184 
OnPriorityFrame(const Http2FrameHeader & header,const Http2PriorityFields & priority)185 void FrameParts::OnPriorityFrame(const Http2FrameHeader& header,
186                                  const Http2PriorityFields& priority) {
187   QUICHE_VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
188   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY)) << *this;
189   ASSERT_FALSE(opt_priority_);
190   opt_priority_ = priority;
191   ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY)) << *this;
192 }
193 
OnContinuationStart(const Http2FrameHeader & header)194 void FrameParts::OnContinuationStart(const Http2FrameHeader& header) {
195   QUICHE_VLOG(1) << "OnContinuationStart: " << header;
196   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::CONTINUATION)) << *this;
197   opt_payload_length_ = header.payload_length;
198 }
199 
OnContinuationEnd()200 void FrameParts::OnContinuationEnd() {
201   QUICHE_VLOG(1) << "OnContinuationEnd; frame_header_: " << frame_header_;
202   ASSERT_TRUE(EndFrameOfType(Http2FrameType::CONTINUATION)) << *this;
203 }
204 
OnPadLength(size_t trailing_length)205 void FrameParts::OnPadLength(size_t trailing_length) {
206   QUICHE_VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
207   ASSERT_TRUE(InPaddedFrame()) << *this;
208   ASSERT_FALSE(opt_pad_length_);
209   ASSERT_TRUE(opt_payload_length_);
210   size_t total_padding_length = trailing_length + 1;
211   ASSERT_GE(opt_payload_length_.value(), total_padding_length);
212   opt_payload_length_ = opt_payload_length_.value() - total_padding_length;
213   opt_pad_length_ = trailing_length;
214 }
215 
OnPadding(const char * pad,size_t skipped_length)216 void FrameParts::OnPadding(const char* pad, size_t skipped_length) {
217   QUICHE_VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
218   ASSERT_TRUE(InPaddedFrame()) << *this;
219   ASSERT_TRUE(opt_pad_length_);
220   ASSERT_TRUE(AppendString(absl::string_view(pad, skipped_length), &padding_,
221                            &opt_pad_length_));
222 }
223 
OnRstStream(const Http2FrameHeader & header,Http2ErrorCode error_code)224 void FrameParts::OnRstStream(const Http2FrameHeader& header,
225                              Http2ErrorCode error_code) {
226   QUICHE_VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
227   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::RST_STREAM)) << *this;
228   ASSERT_FALSE(opt_rst_stream_error_code_);
229   opt_rst_stream_error_code_ = error_code;
230   ASSERT_TRUE(EndFrameOfType(Http2FrameType::RST_STREAM)) << *this;
231 }
232 
OnSettingsStart(const Http2FrameHeader & header)233 void FrameParts::OnSettingsStart(const Http2FrameHeader& header) {
234   QUICHE_VLOG(1) << "OnSettingsStart: " << header;
235   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
236   ASSERT_EQ(0u, settings_.size());
237   ASSERT_FALSE(header.IsAck()) << header;
238 }
239 
OnSetting(const Http2SettingFields & setting_fields)240 void FrameParts::OnSetting(const Http2SettingFields& setting_fields) {
241   QUICHE_VLOG(1) << "OnSetting: " << setting_fields;
242   ASSERT_TRUE(InFrameOfType(Http2FrameType::SETTINGS)) << *this;
243   settings_.push_back(setting_fields);
244 }
245 
OnSettingsEnd()246 void FrameParts::OnSettingsEnd() {
247   QUICHE_VLOG(1) << "OnSettingsEnd; frame_header_: " << frame_header_;
248   ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
249 }
250 
OnSettingsAck(const Http2FrameHeader & header)251 void FrameParts::OnSettingsAck(const Http2FrameHeader& header) {
252   QUICHE_VLOG(1) << "OnSettingsAck: " << header;
253   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
254   ASSERT_EQ(0u, settings_.size());
255   ASSERT_TRUE(header.IsAck());
256   ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
257 }
258 
OnPushPromiseStart(const Http2FrameHeader & header,const Http2PushPromiseFields & promise,size_t total_padding_length)259 void FrameParts::OnPushPromiseStart(const Http2FrameHeader& header,
260                                     const Http2PushPromiseFields& promise,
261                                     size_t total_padding_length) {
262   QUICHE_VLOG(1) << "OnPushPromiseStart header: " << header
263                  << "; promise: " << promise
264                  << "; total_padding_length: " << total_padding_length;
265   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PUSH_PROMISE)) << *this;
266   ASSERT_GE(header.payload_length, Http2PushPromiseFields::EncodedSize());
267   opt_payload_length_ =
268       header.payload_length - Http2PushPromiseFields::EncodedSize();
269   ASSERT_FALSE(opt_push_promise_);
270   opt_push_promise_ = promise;
271   if (total_padding_length > 0) {
272     ASSERT_GE(opt_payload_length_.value(), total_padding_length);
273     OnPadLength(total_padding_length - 1);
274   } else {
275     ASSERT_FALSE(header.IsPadded());
276   }
277 }
278 
OnPushPromiseEnd()279 void FrameParts::OnPushPromiseEnd() {
280   QUICHE_VLOG(1) << "OnPushPromiseEnd; frame_header_: " << frame_header_;
281   ASSERT_TRUE(EndFrameOfType(Http2FrameType::PUSH_PROMISE)) << *this;
282 }
283 
OnPing(const Http2FrameHeader & header,const Http2PingFields & ping)284 void FrameParts::OnPing(const Http2FrameHeader& header,
285                         const Http2PingFields& ping) {
286   QUICHE_VLOG(1) << "OnPing header: " << header << "   ping: " << ping;
287   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
288   ASSERT_FALSE(header.IsAck());
289   ASSERT_FALSE(opt_ping_);
290   opt_ping_ = ping;
291   ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
292 }
293 
OnPingAck(const Http2FrameHeader & header,const Http2PingFields & ping)294 void FrameParts::OnPingAck(const Http2FrameHeader& header,
295                            const Http2PingFields& ping) {
296   QUICHE_VLOG(1) << "OnPingAck header: " << header << "   ping: " << ping;
297   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
298   ASSERT_TRUE(header.IsAck());
299   ASSERT_FALSE(opt_ping_);
300   opt_ping_ = ping;
301   ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
302 }
303 
OnGoAwayStart(const Http2FrameHeader & header,const Http2GoAwayFields & goaway)304 void FrameParts::OnGoAwayStart(const Http2FrameHeader& header,
305                                const Http2GoAwayFields& goaway) {
306   QUICHE_VLOG(1) << "OnGoAwayStart: " << goaway;
307   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::GOAWAY)) << *this;
308   ASSERT_FALSE(opt_goaway_);
309   opt_goaway_ = goaway;
310   opt_payload_length_ =
311       header.payload_length - Http2GoAwayFields::EncodedSize();
312 }
313 
OnGoAwayOpaqueData(const char * data,size_t len)314 void FrameParts::OnGoAwayOpaqueData(const char* data, size_t len) {
315   QUICHE_VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
316   ASSERT_TRUE(InFrameOfType(Http2FrameType::GOAWAY)) << *this;
317   ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
318                            &opt_payload_length_));
319 }
320 
OnGoAwayEnd()321 void FrameParts::OnGoAwayEnd() {
322   QUICHE_VLOG(1) << "OnGoAwayEnd; frame_header_: " << frame_header_;
323   ASSERT_TRUE(EndFrameOfType(Http2FrameType::GOAWAY)) << *this;
324 }
325 
OnWindowUpdate(const Http2FrameHeader & header,uint32_t increment)326 void FrameParts::OnWindowUpdate(const Http2FrameHeader& header,
327                                 uint32_t increment) {
328   QUICHE_VLOG(1) << "OnWindowUpdate header: " << header
329                  << "     increment=" << increment;
330   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::WINDOW_UPDATE)) << *this;
331   ASSERT_FALSE(opt_window_update_increment_);
332   opt_window_update_increment_ = increment;
333   ASSERT_TRUE(EndFrameOfType(Http2FrameType::WINDOW_UPDATE)) << *this;
334 }
335 
OnAltSvcStart(const Http2FrameHeader & header,size_t origin_length,size_t value_length)336 void FrameParts::OnAltSvcStart(const Http2FrameHeader& header,
337                                size_t origin_length, size_t value_length) {
338   QUICHE_VLOG(1) << "OnAltSvcStart: " << header
339                  << "    origin_length: " << origin_length
340                  << "    value_length: " << value_length;
341   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::ALTSVC)) << *this;
342   ASSERT_FALSE(opt_altsvc_origin_length_);
343   opt_altsvc_origin_length_ = origin_length;
344   ASSERT_FALSE(opt_altsvc_value_length_);
345   opt_altsvc_value_length_ = value_length;
346 }
347 
OnAltSvcOriginData(const char * data,size_t len)348 void FrameParts::OnAltSvcOriginData(const char* data, size_t len) {
349   QUICHE_VLOG(1) << "OnAltSvcOriginData: len=" << len;
350   ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
351   ASSERT_TRUE(AppendString(absl::string_view(data, len), &altsvc_origin_,
352                            &opt_altsvc_origin_length_));
353 }
354 
OnAltSvcValueData(const char * data,size_t len)355 void FrameParts::OnAltSvcValueData(const char* data, size_t len) {
356   QUICHE_VLOG(1) << "OnAltSvcValueData: len=" << len;
357   ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
358   ASSERT_TRUE(AppendString(absl::string_view(data, len), &altsvc_value_,
359                            &opt_altsvc_value_length_));
360 }
361 
OnAltSvcEnd()362 void FrameParts::OnAltSvcEnd() {
363   QUICHE_VLOG(1) << "OnAltSvcEnd; frame_header_: " << frame_header_;
364   ASSERT_TRUE(EndFrameOfType(Http2FrameType::ALTSVC)) << *this;
365 }
366 
OnPriorityUpdateStart(const Http2FrameHeader & header,const Http2PriorityUpdateFields & priority_update)367 void FrameParts::OnPriorityUpdateStart(
368     const Http2FrameHeader& header,
369     const Http2PriorityUpdateFields& priority_update) {
370   QUICHE_VLOG(1) << "OnPriorityUpdateStart: " << header
371                  << "    prioritized_stream_id: "
372                  << priority_update.prioritized_stream_id;
373   ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY_UPDATE))
374       << *this;
375   ASSERT_FALSE(opt_priority_update_);
376   opt_priority_update_ = priority_update;
377   opt_payload_length_ =
378       header.payload_length - Http2PriorityUpdateFields::EncodedSize();
379 }
380 
OnPriorityUpdatePayload(const char * data,size_t len)381 void FrameParts::OnPriorityUpdatePayload(const char* data, size_t len) {
382   QUICHE_VLOG(1) << "OnPriorityUpdatePayload: len=" << len;
383   ASSERT_TRUE(InFrameOfType(Http2FrameType::PRIORITY_UPDATE)) << *this;
384   payload_.append(data, len);
385 }
386 
OnPriorityUpdateEnd()387 void FrameParts::OnPriorityUpdateEnd() {
388   QUICHE_VLOG(1) << "OnPriorityUpdateEnd; frame_header_: " << frame_header_;
389   ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY_UPDATE)) << *this;
390 }
391 
OnUnknownStart(const Http2FrameHeader & header)392 void FrameParts::OnUnknownStart(const Http2FrameHeader& header) {
393   QUICHE_VLOG(1) << "OnUnknownStart: " << header;
394   ASSERT_FALSE(IsSupportedHttp2FrameType(header.type)) << header;
395   ASSERT_FALSE(got_start_callback_);
396   ASSERT_EQ(frame_header_, header);
397   got_start_callback_ = true;
398   opt_payload_length_ = header.payload_length;
399 }
400 
OnUnknownPayload(const char * data,size_t len)401 void FrameParts::OnUnknownPayload(const char* data, size_t len) {
402   QUICHE_VLOG(1) << "OnUnknownPayload: len=" << len;
403   ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
404   ASSERT_TRUE(got_start_callback_);
405   ASSERT_FALSE(got_end_callback_);
406   ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
407                            &opt_payload_length_));
408 }
409 
OnUnknownEnd()410 void FrameParts::OnUnknownEnd() {
411   QUICHE_VLOG(1) << "OnUnknownEnd; frame_header_: " << frame_header_;
412   ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
413   ASSERT_TRUE(got_start_callback_);
414   ASSERT_FALSE(got_end_callback_);
415   got_end_callback_ = true;
416 }
417 
OnPaddingTooLong(const Http2FrameHeader & header,size_t missing_length)418 void FrameParts::OnPaddingTooLong(const Http2FrameHeader& header,
419                                   size_t missing_length) {
420   QUICHE_VLOG(1) << "OnPaddingTooLong: " << header
421                  << "; missing_length: " << missing_length;
422   ASSERT_EQ(frame_header_, header);
423   ASSERT_FALSE(got_end_callback_);
424   ASSERT_TRUE(FrameIsPadded(header));
425   ASSERT_FALSE(opt_pad_length_);
426   ASSERT_FALSE(opt_missing_length_);
427   opt_missing_length_ = missing_length;
428   got_start_callback_ = true;
429   got_end_callback_ = true;
430 }
431 
OnFrameSizeError(const Http2FrameHeader & header)432 void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) {
433   QUICHE_VLOG(1) << "OnFrameSizeError: " << header;
434   ASSERT_EQ(frame_header_, header);
435   ASSERT_FALSE(got_end_callback_);
436   ASSERT_FALSE(has_frame_size_error_);
437   has_frame_size_error_ = true;
438   got_end_callback_ = true;
439 }
440 
OutputTo(std::ostream & out) const441 void FrameParts::OutputTo(std::ostream& out) const {
442   out << "FrameParts{\n  frame_header_: " << frame_header_ << "\n";
443   if (!payload_.empty()) {
444     out << "  payload_=\"" << absl::CHexEscape(payload_) << "\"\n";
445   }
446   if (!padding_.empty()) {
447     out << "  padding_=\"" << absl::CHexEscape(padding_) << "\"\n";
448   }
449   if (!altsvc_origin_.empty()) {
450     out << "  altsvc_origin_=\"" << absl::CHexEscape(altsvc_origin_) << "\"\n";
451   }
452   if (!altsvc_value_.empty()) {
453     out << "  altsvc_value_=\"" << absl::CHexEscape(altsvc_value_) << "\"\n";
454   }
455   if (opt_priority_) {
456     out << "  priority=" << opt_priority_.value() << "\n";
457   }
458   if (opt_rst_stream_error_code_) {
459     out << "  rst_stream=" << opt_rst_stream_error_code_.value() << "\n";
460   }
461   if (opt_push_promise_) {
462     out << "  push_promise=" << opt_push_promise_.value() << "\n";
463   }
464   if (opt_ping_) {
465     out << "  ping=" << opt_ping_.value() << "\n";
466   }
467   if (opt_goaway_) {
468     out << "  goaway=" << opt_goaway_.value() << "\n";
469   }
470   if (opt_window_update_increment_) {
471     out << "  window_update=" << opt_window_update_increment_.value() << "\n";
472   }
473   if (opt_payload_length_) {
474     out << "  payload_length=" << opt_payload_length_.value() << "\n";
475   }
476   if (opt_pad_length_) {
477     out << "  pad_length=" << opt_pad_length_.value() << "\n";
478   }
479   if (opt_missing_length_) {
480     out << "  missing_length=" << opt_missing_length_.value() << "\n";
481   }
482   if (opt_altsvc_origin_length_) {
483     out << "  origin_length=" << opt_altsvc_origin_length_.value() << "\n";
484   }
485   if (opt_altsvc_value_length_) {
486     out << "  value_length=" << opt_altsvc_value_length_.value() << "\n";
487   }
488   if (opt_priority_update_) {
489     out << "  prioritized_stream_id_=" << opt_priority_update_.value() << "\n";
490   }
491   if (has_frame_size_error_) {
492     out << "  has_frame_size_error\n";
493   }
494   if (got_start_callback_) {
495     out << "  got_start_callback\n";
496   }
497   if (got_end_callback_) {
498     out << "  got_end_callback\n";
499   }
500   for (size_t ndx = 0; ndx < settings_.size(); ++ndx) {
501     out << "  setting[" << ndx << "]=" << settings_[ndx];
502   }
503   out << "}";
504 }
505 
StartFrameOfType(const Http2FrameHeader & header,Http2FrameType expected_frame_type)506 AssertionResult FrameParts::StartFrameOfType(
507     const Http2FrameHeader& header, Http2FrameType expected_frame_type) {
508   HTTP2_VERIFY_EQ(header.type, expected_frame_type);
509   HTTP2_VERIFY_FALSE(got_start_callback_);
510   HTTP2_VERIFY_FALSE(got_end_callback_);
511   HTTP2_VERIFY_EQ(frame_header_, header);
512   got_start_callback_ = true;
513   return AssertionSuccess();
514 }
515 
InFrameOfType(Http2FrameType expected_frame_type)516 AssertionResult FrameParts::InFrameOfType(Http2FrameType expected_frame_type) {
517   HTTP2_VERIFY_TRUE(got_start_callback_);
518   HTTP2_VERIFY_FALSE(got_end_callback_);
519   HTTP2_VERIFY_EQ(frame_header_.type, expected_frame_type);
520   return AssertionSuccess();
521 }
522 
EndFrameOfType(Http2FrameType expected_frame_type)523 AssertionResult FrameParts::EndFrameOfType(Http2FrameType expected_frame_type) {
524   HTTP2_VERIFY_SUCCESS(InFrameOfType(expected_frame_type));
525   got_end_callback_ = true;
526   return AssertionSuccess();
527 }
528 
InPaddedFrame()529 AssertionResult FrameParts::InPaddedFrame() {
530   HTTP2_VERIFY_TRUE(got_start_callback_);
531   HTTP2_VERIFY_FALSE(got_end_callback_);
532   HTTP2_VERIFY_TRUE(FrameIsPadded(frame_header_));
533   return AssertionSuccess();
534 }
535 
AppendString(absl::string_view source,std::string * target,std::optional<size_t> * opt_length)536 AssertionResult FrameParts::AppendString(absl::string_view source,
537                                          std::string* target,
538                                          std::optional<size_t>* opt_length) {
539   target->append(source.data(), source.size());
540   if (opt_length != nullptr) {
541     HTTP2_VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
542     HTTP2_VERIFY_LE(target->size(), opt_length->value())
543         << "String too large; source.size() = " << source.size() << "\n"
544         << *this;
545   }
546   return ::testing::AssertionSuccess();
547 }
548 
operator <<(std::ostream & out,const FrameParts & v)549 std::ostream& operator<<(std::ostream& out, const FrameParts& v) {
550   v.OutputTo(out);
551   return out;
552 }
553 
554 }  // namespace test
555 }  // namespace http2
556