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