blob: 7b25299ae68b955688cbf28f1e59ae70be8b3de0 [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// 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 "net/third_party/quiche/src/http2/test_tools/frame_parts.h"
6
7#include <type_traits>
8
QUICHE teamfd50a402018-12-07 22:54:05 -05009#include "net/third_party/quiche/src/http2/http2_structures_test_util.h"
QUICHE team61940b42019-03-07 23:32:27 -050010#include "net/third_party/quiche/src/http2/platform/api/http2_logging.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050011#include "net/third_party/quiche/src/http2/platform/api/http2_string_utils.h"
12#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
bnc6744c062020-09-30 10:45:28 -070013#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050014
15using ::testing::AssertionFailure;
16using ::testing::AssertionResult;
17using ::testing::AssertionSuccess;
18using ::testing::ContainerEq;
19
20namespace http2 {
21namespace test {
22namespace {
23
24static_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.
31template <class T>
32AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) {
33 if (opt_a) {
34 if (opt_b) {
35 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
49FrameParts::FrameParts(const Http2FrameHeader& header) : frame_header_(header) {
QUICHE team61940b42019-03-07 23:32:27 -050050 HTTP2_VLOG(1) << "FrameParts, header: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -050051}
52
bnc74646d12019-12-13 09:21:19 -080053FrameParts::FrameParts(const Http2FrameHeader& header,
54 quiche::QuicheStringPiece payload)
QUICHE teamfd50a402018-12-07 22:54:05 -050055 : FrameParts(header) {
QUICHE team61940b42019-03-07 23:32:27 -050056 HTTP2_VLOG(1) << "FrameParts with payload.size() = " << payload.size();
QUICHE teamfd50a402018-12-07 22:54:05 -050057 this->payload_.append(payload.data(), payload.size());
58 opt_payload_length_ = payload.size();
59}
60FrameParts::FrameParts(const Http2FrameHeader& header,
bnc74646d12019-12-13 09:21:19 -080061 quiche::QuicheStringPiece payload,
QUICHE teamfd50a402018-12-07 22:54:05 -050062 size_t total_pad_length)
63 : FrameParts(header, payload) {
QUICHE team61940b42019-03-07 23:32:27 -050064 HTTP2_VLOG(1) << "FrameParts with total_pad_length=" << total_pad_length;
QUICHE teamfd50a402018-12-07 22:54:05 -050065 SetTotalPadLength(total_pad_length);
66}
67
68FrameParts::FrameParts(const FrameParts& header) = default;
69
70FrameParts::~FrameParts() = default;
71
72AssertionResult FrameParts::VerifyEquals(const FrameParts& that) const {
73#define COMMON_MESSAGE "\n this: " << *this << "\n that: " << that
74
75 VERIFY_EQ(frame_header_, that.frame_header_) << COMMON_MESSAGE;
76 VERIFY_EQ(payload_, that.payload_) << COMMON_MESSAGE;
77 VERIFY_EQ(padding_, that.padding_) << COMMON_MESSAGE;
78 VERIFY_EQ(altsvc_origin_, that.altsvc_origin_) << COMMON_MESSAGE;
79 VERIFY_EQ(altsvc_value_, that.altsvc_value_) << COMMON_MESSAGE;
80 VERIFY_THAT(settings_, ContainerEq(that.settings_)) << COMMON_MESSAGE;
81
82#define VERIFY_OPTIONAL_FIELD(field_name) \
83 VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name))
84
85 VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length_) << COMMON_MESSAGE;
86 VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length_) << COMMON_MESSAGE;
87 VERIFY_OPTIONAL_FIELD(opt_goaway_) << COMMON_MESSAGE;
88 VERIFY_OPTIONAL_FIELD(opt_missing_length_) << COMMON_MESSAGE;
89 VERIFY_OPTIONAL_FIELD(opt_pad_length_) << COMMON_MESSAGE;
90 VERIFY_OPTIONAL_FIELD(opt_ping_) << COMMON_MESSAGE;
91 VERIFY_OPTIONAL_FIELD(opt_priority_) << COMMON_MESSAGE;
92 VERIFY_OPTIONAL_FIELD(opt_push_promise_) << COMMON_MESSAGE;
93 VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code_) << COMMON_MESSAGE;
94 VERIFY_OPTIONAL_FIELD(opt_window_update_increment_) << COMMON_MESSAGE;
95
96#undef VERIFY_OPTIONAL_FIELD
97
98 return AssertionSuccess();
99}
100
101void 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_) {
QUICHE team61940b42019-03-07 23:32:27 -0500113 HTTP2_VLOG(1) << "SetTotalPadLength: pad_length="
114 << opt_pad_length_.value();
QUICHE teamfd50a402018-12-07 22:54:05 -0500115 } else {
QUICHE team61940b42019-03-07 23:32:27 -0500116 HTTP2_VLOG(1) << "SetTotalPadLength: has no pad length";
QUICHE teamfd50a402018-12-07 22:54:05 -0500117 }
118}
119
bnc74646d12019-12-13 09:21:19 -0800120void FrameParts::SetAltSvcExpected(quiche::QuicheStringPiece origin,
121 quiche::QuicheStringPiece value) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500122 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
128bool FrameParts::OnFrameHeader(const Http2FrameHeader& header) {
129 ADD_FAILURE() << "OnFrameHeader: " << *this;
130 return true;
131}
132
133void FrameParts::OnDataStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500134 HTTP2_VLOG(1) << "OnDataStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500135 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::DATA)) << *this;
136 opt_payload_length_ = header.payload_length;
137}
138
139void FrameParts::OnDataPayload(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500140 HTTP2_VLOG(1) << "OnDataPayload: len=" << len
141 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500142 ASSERT_TRUE(InFrameOfType(Http2FrameType::DATA)) << *this;
bnc74646d12019-12-13 09:21:19 -0800143 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500144 &opt_payload_length_));
145}
146
147void FrameParts::OnDataEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500148 HTTP2_VLOG(1) << "OnDataEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500149 ASSERT_TRUE(EndFrameOfType(Http2FrameType::DATA)) << *this;
150}
151
152void FrameParts::OnHeadersStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500153 HTTP2_VLOG(1) << "OnHeadersStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500154 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::HEADERS)) << *this;
155 opt_payload_length_ = header.payload_length;
156}
157
158void FrameParts::OnHeadersPriority(const Http2PriorityFields& priority) {
QUICHE team61940b42019-03-07 23:32:27 -0500159 HTTP2_VLOG(1) << "OnHeadersPriority: priority: " << priority
160 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500161 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
169void FrameParts::OnHpackFragment(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500170 HTTP2_VLOG(1) << "OnHpackFragment: len=" << len
171 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500172 ASSERT_TRUE(got_start_callback_);
173 ASSERT_FALSE(got_end_callback_);
174 ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header_)) << *this;
bnc74646d12019-12-13 09:21:19 -0800175 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500176 &opt_payload_length_));
177}
178
179void FrameParts::OnHeadersEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500180 HTTP2_VLOG(1) << "OnHeadersEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500181 ASSERT_TRUE(EndFrameOfType(Http2FrameType::HEADERS)) << *this;
182}
183
184void FrameParts::OnPriorityFrame(const Http2FrameHeader& header,
185 const Http2PriorityFields& priority) {
QUICHE team61940b42019-03-07 23:32:27 -0500186 HTTP2_VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
QUICHE teamfd50a402018-12-07 22:54:05 -0500187 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
193void FrameParts::OnContinuationStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500194 HTTP2_VLOG(1) << "OnContinuationStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500195 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::CONTINUATION)) << *this;
196 opt_payload_length_ = header.payload_length;
197}
198
199void FrameParts::OnContinuationEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500200 HTTP2_VLOG(1) << "OnContinuationEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500201 ASSERT_TRUE(EndFrameOfType(Http2FrameType::CONTINUATION)) << *this;
202}
203
204void FrameParts::OnPadLength(size_t trailing_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500205 HTTP2_VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500206 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
215void FrameParts::OnPadding(const char* pad, size_t skipped_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500216 HTTP2_VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500217 ASSERT_TRUE(InPaddedFrame()) << *this;
218 ASSERT_TRUE(opt_pad_length_);
bnc74646d12019-12-13 09:21:19 -0800219 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(pad, skipped_length),
220 &padding_, &opt_pad_length_));
QUICHE teamfd50a402018-12-07 22:54:05 -0500221}
222
223void FrameParts::OnRstStream(const Http2FrameHeader& header,
224 Http2ErrorCode error_code) {
QUICHE team61940b42019-03-07 23:32:27 -0500225 HTTP2_VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
QUICHE teamfd50a402018-12-07 22:54:05 -0500226 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
232void FrameParts::OnSettingsStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500233 HTTP2_VLOG(1) << "OnSettingsStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500234 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
235 ASSERT_EQ(0u, settings_.size());
236 ASSERT_FALSE(header.IsAck()) << header;
237}
238
239void FrameParts::OnSetting(const Http2SettingFields& setting_fields) {
QUICHE team61940b42019-03-07 23:32:27 -0500240 HTTP2_VLOG(1) << "OnSetting: " << setting_fields;
QUICHE teamfd50a402018-12-07 22:54:05 -0500241 ASSERT_TRUE(InFrameOfType(Http2FrameType::SETTINGS)) << *this;
242 settings_.push_back(setting_fields);
243}
244
245void FrameParts::OnSettingsEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500246 HTTP2_VLOG(1) << "OnSettingsEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500247 ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
248}
249
250void FrameParts::OnSettingsAck(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500251 HTTP2_VLOG(1) << "OnSettingsAck: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500252 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
258void FrameParts::OnPushPromiseStart(const Http2FrameHeader& header,
259 const Http2PushPromiseFields& promise,
260 size_t total_padding_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500261 HTTP2_VLOG(1) << "OnPushPromiseStart header: " << header
262 << "; promise: " << promise
263 << "; total_padding_length: " << total_padding_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500264 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
278void FrameParts::OnPushPromiseEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500279 HTTP2_VLOG(1) << "OnPushPromiseEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500280 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PUSH_PROMISE)) << *this;
281}
282
283void FrameParts::OnPing(const Http2FrameHeader& header,
284 const Http2PingFields& ping) {
QUICHE team61940b42019-03-07 23:32:27 -0500285 HTTP2_VLOG(1) << "OnPing header: " << header << " ping: " << ping;
QUICHE teamfd50a402018-12-07 22:54:05 -0500286 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
293void FrameParts::OnPingAck(const Http2FrameHeader& header,
294 const Http2PingFields& ping) {
QUICHE team61940b42019-03-07 23:32:27 -0500295 HTTP2_VLOG(1) << "OnPingAck header: " << header << " ping: " << ping;
QUICHE teamfd50a402018-12-07 22:54:05 -0500296 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
303void FrameParts::OnGoAwayStart(const Http2FrameHeader& header,
304 const Http2GoAwayFields& goaway) {
QUICHE team61940b42019-03-07 23:32:27 -0500305 HTTP2_VLOG(1) << "OnGoAwayStart: " << goaway;
QUICHE teamfd50a402018-12-07 22:54:05 -0500306 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
313void FrameParts::OnGoAwayOpaqueData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500314 HTTP2_VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500315 ASSERT_TRUE(InFrameOfType(Http2FrameType::GOAWAY)) << *this;
bnc74646d12019-12-13 09:21:19 -0800316 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500317 &opt_payload_length_));
318}
319
320void FrameParts::OnGoAwayEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500321 HTTP2_VLOG(1) << "OnGoAwayEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500322 ASSERT_TRUE(EndFrameOfType(Http2FrameType::GOAWAY)) << *this;
323}
324
325void FrameParts::OnWindowUpdate(const Http2FrameHeader& header,
326 uint32_t increment) {
QUICHE team61940b42019-03-07 23:32:27 -0500327 HTTP2_VLOG(1) << "OnWindowUpdate header: " << header
328 << " increment=" << increment;
QUICHE teamfd50a402018-12-07 22:54:05 -0500329 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
335void FrameParts::OnAltSvcStart(const Http2FrameHeader& header,
336 size_t origin_length,
337 size_t value_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500338 HTTP2_VLOG(1) << "OnAltSvcStart: " << header
339 << " origin_length: " << origin_length
340 << " value_length: " << value_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500341 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
348void FrameParts::OnAltSvcOriginData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500349 HTTP2_VLOG(1) << "OnAltSvcOriginData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500350 ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
bnc74646d12019-12-13 09:21:19 -0800351 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len),
352 &altsvc_origin_, &opt_altsvc_origin_length_));
QUICHE teamfd50a402018-12-07 22:54:05 -0500353}
354
355void FrameParts::OnAltSvcValueData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500356 HTTP2_VLOG(1) << "OnAltSvcValueData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500357 ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
bnc74646d12019-12-13 09:21:19 -0800358 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len), &altsvc_value_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500359 &opt_altsvc_value_length_));
360}
361
362void FrameParts::OnAltSvcEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500363 HTTP2_VLOG(1) << "OnAltSvcEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500364 ASSERT_TRUE(EndFrameOfType(Http2FrameType::ALTSVC)) << *this;
365}
366
367void FrameParts::OnUnknownStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500368 HTTP2_VLOG(1) << "OnUnknownStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500369 ASSERT_FALSE(IsSupportedHttp2FrameType(header.type)) << header;
370 ASSERT_FALSE(got_start_callback_);
371 ASSERT_EQ(frame_header_, header);
372 got_start_callback_ = true;
373 opt_payload_length_ = header.payload_length;
374}
375
376void FrameParts::OnUnknownPayload(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500377 HTTP2_VLOG(1) << "OnUnknownPayload: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500378 ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
379 ASSERT_TRUE(got_start_callback_);
380 ASSERT_FALSE(got_end_callback_);
bnc74646d12019-12-13 09:21:19 -0800381 ASSERT_TRUE(AppendString(quiche::QuicheStringPiece(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500382 &opt_payload_length_));
383}
384
385void FrameParts::OnUnknownEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500386 HTTP2_VLOG(1) << "OnUnknownEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500387 ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
388 ASSERT_TRUE(got_start_callback_);
389 ASSERT_FALSE(got_end_callback_);
390 got_end_callback_ = true;
391}
392
393void FrameParts::OnPaddingTooLong(const Http2FrameHeader& header,
394 size_t missing_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500395 HTTP2_VLOG(1) << "OnPaddingTooLong: " << header
396 << "; missing_length: " << missing_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500397 ASSERT_EQ(frame_header_, header);
398 ASSERT_FALSE(got_end_callback_);
399 ASSERT_TRUE(FrameIsPadded(header));
400 ASSERT_FALSE(opt_pad_length_);
401 ASSERT_FALSE(opt_missing_length_);
402 opt_missing_length_ = missing_length;
403 got_start_callback_ = true;
404 got_end_callback_ = true;
405}
406
407void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500408 HTTP2_VLOG(1) << "OnFrameSizeError: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500409 ASSERT_EQ(frame_header_, header);
410 ASSERT_FALSE(got_end_callback_);
411 ASSERT_FALSE(has_frame_size_error_);
412 has_frame_size_error_ = true;
413 got_end_callback_ = true;
414}
415
416void FrameParts::OutputTo(std::ostream& out) const {
417 out << "FrameParts{\n frame_header_: " << frame_header_ << "\n";
418 if (!payload_.empty()) {
419 out << " payload_=\"" << Http2HexEscape(payload_) << "\"\n";
420 }
421 if (!padding_.empty()) {
422 out << " padding_=\"" << Http2HexEscape(padding_) << "\"\n";
423 }
424 if (!altsvc_origin_.empty()) {
425 out << " altsvc_origin_=\"" << Http2HexEscape(altsvc_origin_) << "\"\n";
426 }
427 if (!altsvc_value_.empty()) {
428 out << " altsvc_value_=\"" << Http2HexEscape(altsvc_value_) << "\"\n";
429 }
430 if (opt_priority_) {
431 out << " priority=" << opt_priority_.value() << "\n";
432 }
433 if (opt_rst_stream_error_code_) {
434 out << " rst_stream=" << opt_rst_stream_error_code_.value() << "\n";
435 }
436 if (opt_push_promise_) {
437 out << " push_promise=" << opt_push_promise_.value() << "\n";
438 }
439 if (opt_ping_) {
440 out << " ping=" << opt_ping_.value() << "\n";
441 }
442 if (opt_goaway_) {
443 out << " goaway=" << opt_goaway_.value() << "\n";
444 }
445 if (opt_window_update_increment_) {
446 out << " window_update=" << opt_window_update_increment_.value() << "\n";
447 }
448 if (opt_payload_length_) {
449 out << " payload_length=" << opt_payload_length_.value() << "\n";
450 }
451 if (opt_pad_length_) {
452 out << " pad_length=" << opt_pad_length_.value() << "\n";
453 }
454 if (opt_missing_length_) {
455 out << " missing_length=" << opt_missing_length_.value() << "\n";
456 }
457 if (opt_altsvc_origin_length_) {
458 out << " origin_length=" << opt_altsvc_origin_length_.value() << "\n";
459 }
460 if (opt_altsvc_value_length_) {
461 out << " value_length=" << opt_altsvc_value_length_.value() << "\n";
462 }
463 if (has_frame_size_error_) {
464 out << " has_frame_size_error\n";
465 }
466 if (got_start_callback_) {
467 out << " got_start_callback\n";
468 }
469 if (got_end_callback_) {
470 out << " got_end_callback\n";
471 }
472 for (size_t ndx = 0; ndx < settings_.size(); ++ndx) {
473 out << " setting[" << ndx << "]=" << settings_[ndx];
474 }
475 out << "}";
476}
477
478AssertionResult FrameParts::StartFrameOfType(
479 const Http2FrameHeader& header,
480 Http2FrameType expected_frame_type) {
481 VERIFY_EQ(header.type, expected_frame_type);
482 VERIFY_FALSE(got_start_callback_);
483 VERIFY_FALSE(got_end_callback_);
484 VERIFY_EQ(frame_header_, header);
485 got_start_callback_ = true;
486 return AssertionSuccess();
487}
488
489AssertionResult FrameParts::InFrameOfType(Http2FrameType expected_frame_type) {
490 VERIFY_TRUE(got_start_callback_);
491 VERIFY_FALSE(got_end_callback_);
492 VERIFY_EQ(frame_header_.type, expected_frame_type);
493 return AssertionSuccess();
494}
495
496AssertionResult FrameParts::EndFrameOfType(Http2FrameType expected_frame_type) {
497 VERIFY_SUCCESS(InFrameOfType(expected_frame_type));
498 got_end_callback_ = true;
499 return AssertionSuccess();
500}
501
502AssertionResult FrameParts::InPaddedFrame() {
503 VERIFY_TRUE(got_start_callback_);
504 VERIFY_FALSE(got_end_callback_);
505 VERIFY_TRUE(FrameIsPadded(frame_header_));
506 return AssertionSuccess();
507}
508
bnc766e81c2020-01-15 07:16:52 -0800509AssertionResult FrameParts::AppendString(
510 quiche::QuicheStringPiece source,
511 std::string* target,
512 quiche::QuicheOptional<size_t>* opt_length) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500513 target->append(source.data(), source.size());
514 if (opt_length != nullptr) {
515 VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
516 VERIFY_LE(target->size(), opt_length->value())
517 << "String too large; source.size() = " << source.size() << "\n"
518 << *this;
519 }
520 return ::testing::AssertionSuccess();
521}
522
523std::ostream& operator<<(std::ostream& out, const FrameParts& v) {
524 v.OutputTo(out);
525 return out;
526}
527
528} // namespace test
529} // namespace http2