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