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/decoder/http2_structure_decoder.h"
6 
7 // Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined in
8 // quiche/http2/http2_structures.h) using Http2StructureDecoder, which
9 // handles buffering of structures split across input buffer boundaries, and in
10 // turn uses DoDecode when it has all of a structure in a contiguous buffer.
11 
12 // NOTE: This tests the first pair of Start and Resume, which don't take
13 // a remaining_payload parameter. The other pair are well tested via the
14 // payload decoder tests, though...
15 // TODO(jamessynge): Create type parameterized tests for Http2StructureDecoder
16 // where the type is the type of structure, and with testing of both pairs of
17 // Start and Resume methods; note that it appears that the first pair will be
18 // used only for Http2FrameHeader, and the other pair only for structures in the
19 // frame payload.
20 
21 #include <stddef.h>
22 
23 #include <cstdint>
24 #include <string>
25 #include <utility>
26 
27 #include "absl/strings/string_view.h"
28 #include "quiche/http2/decoder/decode_buffer.h"
29 #include "quiche/http2/decoder/decode_status.h"
30 #include "quiche/http2/http2_constants.h"
31 #include "quiche/http2/test_tools/http2_frame_builder.h"
32 #include "quiche/http2/test_tools/http2_structures_test_util.h"
33 #include "quiche/http2/test_tools/random_decoder_test_base.h"
34 #include "quiche/http2/test_tools/verify_macros.h"
35 #include "quiche/common/platform/api/quiche_logging.h"
36 
37 using ::testing::AssertionSuccess;
38 
39 namespace http2 {
40 namespace test {
41 namespace {
42 const bool kMayReturnZeroOnFirst = false;
43 
44 template <class S>
45 class Http2StructureDecoderTest : public RandomDecoderTest {
46  protected:
47   typedef S Structure;
48 
Http2StructureDecoderTest()49   Http2StructureDecoderTest() {
50     // IF the test adds more data after the encoded structure, stop as
51     // soon as the structure is decoded.
52     stop_decode_on_done_ = true;
53   }
54 
StartDecoding(DecodeBuffer * b)55   DecodeStatus StartDecoding(DecodeBuffer* b) override {
56     // Overwrite the current contents of |structure_|, into which we'll
57     // decode the buffer, so that we can be confident that we really decoded
58     // the structure every time.
59     structure_ = std::make_unique<S>();
60     uint32_t old_remaining = b->Remaining();
61     if (structure_decoder_.Start(structure_.get(), b)) {
62       EXPECT_EQ(old_remaining - S::EncodedSize(), b->Remaining());
63       ++fast_decode_count_;
64       return DecodeStatus::kDecodeDone;
65     } else {
66       EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
67       EXPECT_EQ(0u, b->Remaining());
68       EXPECT_EQ(old_remaining - structure_decoder_.offset(), b->Remaining());
69       ++incomplete_start_count_;
70       return DecodeStatus::kDecodeInProgress;
71     }
72   }
73 
ResumeDecoding(DecodeBuffer * b)74   DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
75     uint32_t old_offset = structure_decoder_.offset();
76     EXPECT_LT(old_offset, S::EncodedSize());
77     uint32_t avail = b->Remaining();
78     if (structure_decoder_.Resume(structure_.get(), b)) {
79       EXPECT_LE(S::EncodedSize(), old_offset + avail);
80       EXPECT_EQ(b->Remaining(), avail - (S::EncodedSize() - old_offset));
81       ++slow_decode_count_;
82       return DecodeStatus::kDecodeDone;
83     } else {
84       EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
85       EXPECT_EQ(0u, b->Remaining());
86       EXPECT_GT(S::EncodedSize(), old_offset + avail);
87       ++incomplete_resume_count_;
88       return DecodeStatus::kDecodeInProgress;
89     }
90   }
91 
92   // Fully decodes the Structure at the start of data, and confirms it matches
93   // *expected (if provided).
DecodeLeadingStructure(const S * expected,absl::string_view data)94   AssertionResult DecodeLeadingStructure(const S* expected,
95                                          absl::string_view data) {
96     HTTP2_VERIFY_LE(S::EncodedSize(), data.size());
97     DecodeBuffer original(data);
98 
99     // The validator is called after each of the several times that the input
100     // DecodeBuffer is decoded, each with a different segmentation of the input.
101     // Validate that structure_ matches the expected value, if provided.
102     Validator validator;
103     if (expected != nullptr) {
104       validator = [expected, this](const DecodeBuffer& /*db*/,
105                                    DecodeStatus /*status*/) -> AssertionResult {
106         HTTP2_VERIFY_EQ(*expected, *structure_);
107         return AssertionSuccess();
108       };
109     }
110 
111     // Before that, validate that decoding is done and that we've advanced
112     // the cursor the expected amount.
113     validator = ValidateDoneAndOffset(S::EncodedSize(), std::move(validator));
114 
115     // Decode several times, with several segmentations of the input buffer.
116     fast_decode_count_ = 0;
117     slow_decode_count_ = 0;
118     incomplete_start_count_ = 0;
119     incomplete_resume_count_ = 0;
120     HTTP2_VERIFY_SUCCESS(DecodeAndValidateSeveralWays(
121         &original, kMayReturnZeroOnFirst, validator));
122     HTTP2_VERIFY_FALSE(HasFailure());
123     HTTP2_VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset());
124     HTTP2_VERIFY_EQ(S::EncodedSize(), original.Offset());
125     HTTP2_VERIFY_LT(0u, fast_decode_count_);
126     HTTP2_VERIFY_LT(0u, slow_decode_count_);
127     HTTP2_VERIFY_LT(0u, incomplete_start_count_);
128 
129     // If the structure is large enough so that SelectZeroOrOne will have
130     // caused Resume to return false, check that occurred.
131     if (S::EncodedSize() >= 2) {
132       HTTP2_VERIFY_LE(0u, incomplete_resume_count_);
133     } else {
134       HTTP2_VERIFY_EQ(0u, incomplete_resume_count_);
135     }
136     if (expected != nullptr) {
137       QUICHE_DVLOG(1) << "DecodeLeadingStructure expected: " << *expected;
138       QUICHE_DVLOG(1) << "DecodeLeadingStructure   actual: " << *structure_;
139       HTTP2_VERIFY_EQ(*expected, *structure_);
140     }
141     return AssertionSuccess();
142   }
143 
144   template <size_t N>
DecodeLeadingStructure(const char (& data)[N])145   AssertionResult DecodeLeadingStructure(const char (&data)[N]) {
146     return DecodeLeadingStructure(nullptr, absl::string_view(data, N));
147   }
148 
149   template <size_t N>
DecodeLeadingStructure(const unsigned char (& data)[N])150   AssertionResult DecodeLeadingStructure(const unsigned char (&data)[N]) {
151     return DecodeLeadingStructure(nullptr, ToStringPiece(data));
152   }
153 
154   // Encode the structure |in_s| into bytes, then decode the bytes
155   // and validate that the decoder produced the same field values.
EncodeThenDecode(const S & in_s)156   AssertionResult EncodeThenDecode(const S& in_s) {
157     std::string bytes = SerializeStructure(in_s);
158     HTTP2_VERIFY_EQ(S::EncodedSize(), bytes.size());
159     return DecodeLeadingStructure(&in_s, bytes);
160   }
161 
162   // Repeatedly fill a structure with random but valid contents, encode it, then
163   // decode it, and finally validate that the decoded structure matches the
164   // random input. Lather-rinse-and-repeat.
TestDecodingRandomizedStructures(size_t count)165   AssertionResult TestDecodingRandomizedStructures(size_t count) {
166     for (size_t i = 0; i < count; ++i) {
167       Structure input;
168       Randomize(&input, RandomPtr());
169       HTTP2_VERIFY_SUCCESS(EncodeThenDecode(input));
170     }
171     return AssertionSuccess();
172   }
173 
TestDecodingRandomizedStructures()174   AssertionResult TestDecodingRandomizedStructures() {
175     HTTP2_VERIFY_SUCCESS(TestDecodingRandomizedStructures(100));
176     return AssertionSuccess();
177   }
178 
179   uint32_t decode_offset_ = 0;
180   std::unique_ptr<S> structure_;
181   Http2StructureDecoder structure_decoder_;
182   size_t fast_decode_count_ = 0;
183   size_t slow_decode_count_ = 0;
184   size_t incomplete_start_count_ = 0;
185   size_t incomplete_resume_count_ = 0;
186 };
187 
188 class Http2FrameHeaderDecoderTest
189     : public Http2StructureDecoderTest<Http2FrameHeader> {};
190 
TEST_F(Http2FrameHeaderDecoderTest,DecodesLiteral)191 TEST_F(Http2FrameHeaderDecoderTest, DecodesLiteral) {
192   {
193     // Realistic input.
194     // clang-format off
195     const char kData[] = {
196         0x00, 0x00, 0x05,        // Payload length: 5
197         0x01,                    // Frame type: HEADERS
198         0x08,                    // Flags: PADDED
199         0x00, 0x00, 0x00, 0x01,  // Stream ID: 1
200         0x04,                    // Padding length: 4
201         0x00, 0x00, 0x00, 0x00,  // Padding bytes
202     };
203     // clang-format on
204     ASSERT_TRUE(DecodeLeadingStructure(kData));
205     EXPECT_EQ(5u, structure_->payload_length);
206     EXPECT_EQ(Http2FrameType::HEADERS, structure_->type);
207     EXPECT_EQ(Http2FrameFlag::PADDED, structure_->flags);
208     EXPECT_EQ(1u, structure_->stream_id);
209   }
210   {
211     // Unlikely input.
212     // clang-format off
213     const unsigned char kData[] = {
214         0xff, 0xff, 0xff,        // Payload length: uint24 max
215         0xff,                    // Frame type: Unknown
216         0xff,                    // Flags: Unknown/All
217         0xff, 0xff, 0xff, 0xff,  // Stream ID: uint31 max, plus R-bit
218     };
219     // clang-format on
220     ASSERT_TRUE(DecodeLeadingStructure(kData));
221     EXPECT_EQ((1u << 24) - 1u, structure_->payload_length);
222     EXPECT_EQ(static_cast<Http2FrameType>(255), structure_->type);
223     EXPECT_EQ(255, structure_->flags);
224     EXPECT_EQ(0x7FFFFFFFu, structure_->stream_id);
225   }
226 }
227 
TEST_F(Http2FrameHeaderDecoderTest,DecodesRandomized)228 TEST_F(Http2FrameHeaderDecoderTest, DecodesRandomized) {
229   EXPECT_TRUE(TestDecodingRandomizedStructures());
230 }
231 
232 //------------------------------------------------------------------------------
233 
234 class Http2PriorityFieldsDecoderTest
235     : public Http2StructureDecoderTest<Http2PriorityFields> {};
236 
TEST_F(Http2PriorityFieldsDecoderTest,DecodesLiteral)237 TEST_F(Http2PriorityFieldsDecoderTest, DecodesLiteral) {
238   {
239     // clang-format off
240     const unsigned char kData[] = {
241         0x80, 0x00, 0x00, 0x05,  // Exclusive (yes) and Dependency (5)
242         0xff,                    // Weight: 256 (after adding 1)
243     };
244     // clang-format on
245     ASSERT_TRUE(DecodeLeadingStructure(kData));
246     EXPECT_EQ(5u, structure_->stream_dependency);
247     EXPECT_EQ(256u, structure_->weight);
248     EXPECT_EQ(true, structure_->is_exclusive);
249   }
250   {
251     // clang-format off
252     const unsigned char kData[] = {
253         0x7f, 0xff, 0xff, 0xff,  // Excl. (no) and Dependency (uint31 max)
254         0x00,                    // Weight: 1 (after adding 1)
255     };
256     // clang-format on
257     ASSERT_TRUE(DecodeLeadingStructure(kData));
258     EXPECT_EQ(StreamIdMask(), structure_->stream_dependency);
259     EXPECT_EQ(1u, structure_->weight);
260     EXPECT_FALSE(structure_->is_exclusive);
261   }
262 }
263 
TEST_F(Http2PriorityFieldsDecoderTest,DecodesRandomized)264 TEST_F(Http2PriorityFieldsDecoderTest, DecodesRandomized) {
265   EXPECT_TRUE(TestDecodingRandomizedStructures());
266 }
267 
268 //------------------------------------------------------------------------------
269 
270 class Http2RstStreamFieldsDecoderTest
271     : public Http2StructureDecoderTest<Http2RstStreamFields> {};
272 
TEST_F(Http2RstStreamFieldsDecoderTest,DecodesLiteral)273 TEST_F(Http2RstStreamFieldsDecoderTest, DecodesLiteral) {
274   {
275     // clang-format off
276     const char kData[] = {
277         0x00, 0x00, 0x00, 0x01,  // Error: PROTOCOL_ERROR
278     };
279     // clang-format on
280     ASSERT_TRUE(DecodeLeadingStructure(kData));
281     EXPECT_TRUE(structure_->IsSupportedErrorCode());
282     EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_->error_code);
283   }
284   {
285     // clang-format off
286     const unsigned char kData[] = {
287         0xff, 0xff, 0xff, 0xff,  // Error: max uint32 (Unknown error code)
288     };
289     // clang-format on
290     ASSERT_TRUE(DecodeLeadingStructure(kData));
291     EXPECT_FALSE(structure_->IsSupportedErrorCode());
292     EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_->error_code);
293   }
294 }
295 
TEST_F(Http2RstStreamFieldsDecoderTest,DecodesRandomized)296 TEST_F(Http2RstStreamFieldsDecoderTest, DecodesRandomized) {
297   EXPECT_TRUE(TestDecodingRandomizedStructures());
298 }
299 
300 //------------------------------------------------------------------------------
301 
302 class Http2SettingFieldsDecoderTest
303     : public Http2StructureDecoderTest<Http2SettingFields> {};
304 
TEST_F(Http2SettingFieldsDecoderTest,DecodesLiteral)305 TEST_F(Http2SettingFieldsDecoderTest, DecodesLiteral) {
306   {
307     // clang-format off
308     const char kData[] = {
309         0x00, 0x01,              // Setting: HEADER_TABLE_SIZE
310         0x00, 0x00, 0x40, 0x00,  // Value: 16K
311     };
312     // clang-format on
313     ASSERT_TRUE(DecodeLeadingStructure(kData));
314     EXPECT_TRUE(structure_->IsSupportedParameter());
315     EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, structure_->parameter);
316     EXPECT_EQ(1u << 14, structure_->value);
317   }
318   {
319     // clang-format off
320     const unsigned char kData[] = {
321         0x00, 0x00,              // Setting: Unknown (0)
322         0xff, 0xff, 0xff, 0xff,  // Value: max uint32
323     };
324     // clang-format on
325     ASSERT_TRUE(DecodeLeadingStructure(kData));
326     EXPECT_FALSE(structure_->IsSupportedParameter());
327     EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_->parameter);
328   }
329 }
330 
TEST_F(Http2SettingFieldsDecoderTest,DecodesRandomized)331 TEST_F(Http2SettingFieldsDecoderTest, DecodesRandomized) {
332   EXPECT_TRUE(TestDecodingRandomizedStructures());
333 }
334 
335 //------------------------------------------------------------------------------
336 
337 class Http2PushPromiseFieldsDecoderTest
338     : public Http2StructureDecoderTest<Http2PushPromiseFields> {};
339 
TEST_F(Http2PushPromiseFieldsDecoderTest,DecodesLiteral)340 TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesLiteral) {
341   {
342     // clang-format off
343     const unsigned char kData[] = {
344         0x00, 0x01, 0x8a, 0x92,  // Promised Stream ID: 101010
345     };
346     // clang-format on
347     ASSERT_TRUE(DecodeLeadingStructure(kData));
348     EXPECT_EQ(101010u, structure_->promised_stream_id);
349   }
350   {
351     // Promised stream id has R-bit (reserved for future use) set, which
352     // should be cleared by the decoder.
353     // clang-format off
354     const unsigned char kData[] = {
355         // Promised Stream ID: max uint31 and R-bit
356         0xff, 0xff, 0xff, 0xff,
357     };
358     // clang-format on
359     ASSERT_TRUE(DecodeLeadingStructure(kData));
360     EXPECT_EQ(StreamIdMask(), structure_->promised_stream_id);
361   }
362 }
363 
TEST_F(Http2PushPromiseFieldsDecoderTest,DecodesRandomized)364 TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesRandomized) {
365   EXPECT_TRUE(TestDecodingRandomizedStructures());
366 }
367 
368 //------------------------------------------------------------------------------
369 
370 class Http2PingFieldsDecoderTest
371     : public Http2StructureDecoderTest<Http2PingFields> {};
372 
TEST_F(Http2PingFieldsDecoderTest,DecodesLiteral)373 TEST_F(Http2PingFieldsDecoderTest, DecodesLiteral) {
374   {
375     // Each byte is different, so can detect if order changed.
376     const char kData[] = {
377         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
378     };
379     ASSERT_TRUE(DecodeLeadingStructure(kData));
380     EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes));
381   }
382   {
383     // All zeros, detect problems handling NULs.
384     const char kData[] = {
385         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386     };
387     ASSERT_TRUE(DecodeLeadingStructure(kData));
388     EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes));
389   }
390   {
391     const unsigned char kData[] = {
392         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
393     };
394     ASSERT_TRUE(DecodeLeadingStructure(kData));
395     EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes));
396   }
397 }
398 
TEST_F(Http2PingFieldsDecoderTest,DecodesRandomized)399 TEST_F(Http2PingFieldsDecoderTest, DecodesRandomized) {
400   EXPECT_TRUE(TestDecodingRandomizedStructures());
401 }
402 
403 //------------------------------------------------------------------------------
404 
405 class Http2GoAwayFieldsDecoderTest
406     : public Http2StructureDecoderTest<Http2GoAwayFields> {};
407 
TEST_F(Http2GoAwayFieldsDecoderTest,DecodesLiteral)408 TEST_F(Http2GoAwayFieldsDecoderTest, DecodesLiteral) {
409   {
410     // clang-format off
411     const char kData[] = {
412         0x00, 0x00, 0x00, 0x00,  // Last Stream ID: 0
413         0x00, 0x00, 0x00, 0x00,  // Error: NO_ERROR (0)
414     };
415     // clang-format on
416     ASSERT_TRUE(DecodeLeadingStructure(kData));
417     EXPECT_EQ(0u, structure_->last_stream_id);
418     EXPECT_TRUE(structure_->IsSupportedErrorCode());
419     EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_->error_code);
420   }
421   {
422     // clang-format off
423     const char kData[] = {
424         0x00, 0x00, 0x00, 0x01,  // Last Stream ID: 1
425         0x00, 0x00, 0x00, 0x0d,  // Error: HTTP_1_1_REQUIRED
426     };
427     // clang-format on
428     ASSERT_TRUE(DecodeLeadingStructure(kData));
429     EXPECT_EQ(1u, structure_->last_stream_id);
430     EXPECT_TRUE(structure_->IsSupportedErrorCode());
431     EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_->error_code);
432   }
433   {
434     // clang-format off
435     const unsigned char kData[] = {
436         0xff, 0xff, 0xff, 0xff,  // Last Stream ID: max uint31 and R-bit
437         0xff, 0xff, 0xff, 0xff,  // Error: max uint32 (Unknown error code)
438     };
439     // clang-format on
440     ASSERT_TRUE(DecodeLeadingStructure(kData));
441     EXPECT_EQ(StreamIdMask(), structure_->last_stream_id);  // No high-bit.
442     EXPECT_FALSE(structure_->IsSupportedErrorCode());
443     EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_->error_code);
444   }
445 }
446 
TEST_F(Http2GoAwayFieldsDecoderTest,DecodesRandomized)447 TEST_F(Http2GoAwayFieldsDecoderTest, DecodesRandomized) {
448   EXPECT_TRUE(TestDecodingRandomizedStructures());
449 }
450 
451 //------------------------------------------------------------------------------
452 
453 class Http2WindowUpdateFieldsDecoderTest
454     : public Http2StructureDecoderTest<Http2WindowUpdateFields> {};
455 
TEST_F(Http2WindowUpdateFieldsDecoderTest,DecodesLiteral)456 TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesLiteral) {
457   {
458     // clang-format off
459     const char kData[] = {
460         0x00, 0x01, 0x00, 0x00,  // Window Size Increment: 2 ^ 16
461     };
462     // clang-format on
463     ASSERT_TRUE(DecodeLeadingStructure(kData));
464     EXPECT_EQ(1u << 16, structure_->window_size_increment);
465   }
466   {
467     // Increment must be non-zero, but we need to be able to decode the invalid
468     // zero to detect it.
469     // clang-format off
470     const char kData[] = {
471         0x00, 0x00, 0x00, 0x00,  // Window Size Increment: 0
472     };
473     // clang-format on
474     ASSERT_TRUE(DecodeLeadingStructure(kData));
475     EXPECT_EQ(0u, structure_->window_size_increment);
476   }
477   {
478     // Increment has R-bit (reserved for future use) set, which
479     // should be cleared by the decoder.
480     // clang-format off
481     const unsigned char kData[] = {
482         // Window Size Increment: max uint31 and R-bit
483         0xff, 0xff, 0xff, 0xff,
484     };
485     // clang-format on
486     ASSERT_TRUE(DecodeLeadingStructure(kData));
487     EXPECT_EQ(StreamIdMask(), structure_->window_size_increment);
488   }
489 }
490 
TEST_F(Http2WindowUpdateFieldsDecoderTest,DecodesRandomized)491 TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesRandomized) {
492   EXPECT_TRUE(TestDecodingRandomizedStructures());
493 }
494 
495 //------------------------------------------------------------------------------
496 
497 class Http2AltSvcFieldsDecoderTest
498     : public Http2StructureDecoderTest<Http2AltSvcFields> {};
499 
TEST_F(Http2AltSvcFieldsDecoderTest,DecodesLiteral)500 TEST_F(Http2AltSvcFieldsDecoderTest, DecodesLiteral) {
501   {
502     // clang-format off
503     const char kData[] = {
504         0x00, 0x00,  // Origin Length: 0
505     };
506     // clang-format on
507     ASSERT_TRUE(DecodeLeadingStructure(kData));
508     EXPECT_EQ(0, structure_->origin_length);
509   }
510   {
511     // clang-format off
512     const char kData[] = {
513         0x00, 0x14,  // Origin Length: 20
514     };
515     // clang-format on
516     ASSERT_TRUE(DecodeLeadingStructure(kData));
517     EXPECT_EQ(20, structure_->origin_length);
518   }
519   {
520     // clang-format off
521     const unsigned char kData[] = {
522         0xff, 0xff,  // Origin Length: uint16 max
523     };
524     // clang-format on
525     ASSERT_TRUE(DecodeLeadingStructure(kData));
526     EXPECT_EQ(65535, structure_->origin_length);
527   }
528 }
529 
TEST_F(Http2AltSvcFieldsDecoderTest,DecodesRandomized)530 TEST_F(Http2AltSvcFieldsDecoderTest, DecodesRandomized) {
531   EXPECT_TRUE(TestDecodingRandomizedStructures());
532 }
533 
534 }  // namespace
535 }  // namespace test
536 }  // namespace http2
537