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