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/http2_structures.h"
6
7 // Tests are focused on Http2FrameHeader because it has by far the most
8 // methods of any of the structures.
9 // Note that EXPECT.*DEATH tests are slow (a fork is probably involved).
10
11 // And in case you're wondering, yes, these are ridiculously thorough tests,
12 // but believe it or not, I've found silly bugs this way.
13
14 #include <memory>
15 #include <ostream>
16 #include <sstream>
17 #include <string>
18 #include <tuple>
19 #include <type_traits>
20 #include <vector>
21
22 #include "absl/strings/str_cat.h"
23 #include "quiche/http2/test_tools/http2_random.h"
24 #include "quiche/http2/test_tools/http2_structures_test_util.h"
25 #include "quiche/http2/test_tools/verify_macros.h"
26 #include "quiche/common/platform/api/quiche_test.h"
27
28 using ::testing::AssertionResult;
29 using ::testing::AssertionSuccess;
30 using ::testing::Combine;
31 using ::testing::HasSubstr;
32 using ::testing::MatchesRegex;
33 using ::testing::Not;
34 using ::testing::Values;
35 using ::testing::ValuesIn;
36
37 namespace http2 {
38 namespace test {
39 namespace {
40
41 template <typename E>
IncrementEnum(E e)42 E IncrementEnum(E e) {
43 using I = typename std::underlying_type<E>::type;
44 return static_cast<E>(1 + static_cast<I>(e));
45 }
46
47 template <class T>
VerifyRandomCalls()48 AssertionResult VerifyRandomCalls() {
49 T t1;
50 // Initialize with a stable key, to avoid test flakiness.
51 Http2Random seq1(
52 "6d9a61ddf2bc1fc0b8245505a1f28e324559d8b5c9c3268f38b42b1af3287c47");
53 Randomize(&t1, &seq1);
54
55 T t2;
56 Http2Random seq2(seq1.Key());
57 Randomize(&t2, &seq2);
58
59 // The two Randomize calls should have made the same number of calls into
60 // the Http2Random implementations.
61 HTTP2_VERIFY_EQ(seq1.Rand64(), seq2.Rand64());
62
63 // And because Http2Random implementation is returning the same sequence, and
64 // Randomize should have been consistent in applying those results, the two
65 // Ts should have the same value.
66 HTTP2_VERIFY_EQ(t1, t2);
67
68 Randomize(&t2, &seq2);
69 HTTP2_VERIFY_NE(t1, t2);
70
71 Randomize(&t1, &seq1);
72 HTTP2_VERIFY_EQ(t1, t2);
73
74 HTTP2_VERIFY_EQ(seq1.Rand64(), seq2.Rand64());
75
76 return AssertionSuccess();
77 }
78
79 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
ValidFrameTypes()80 std::vector<Http2FrameType> ValidFrameTypes() {
81 std::vector<Http2FrameType> valid_types{Http2FrameType::DATA};
82 while (valid_types.back() != Http2FrameType::ALTSVC) {
83 valid_types.push_back(IncrementEnum(valid_types.back()));
84 }
85 return valid_types;
86 }
87 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
88
TEST(Http2FrameHeaderTest,Constructor)89 TEST(Http2FrameHeaderTest, Constructor) {
90 Http2Random random;
91 uint8_t frame_type = 0;
92 do {
93 // Only the payload length is QUICHE_DCHECK'd in the constructor, so we need
94 // to make sure it is a "uint24".
95 uint32_t payload_length = random.Rand32() & 0xffffff;
96 Http2FrameType type = static_cast<Http2FrameType>(frame_type);
97 uint8_t flags = random.Rand8();
98 uint32_t stream_id = random.Rand32();
99
100 Http2FrameHeader v(payload_length, type, flags, stream_id);
101
102 EXPECT_EQ(payload_length, v.payload_length);
103 EXPECT_EQ(type, v.type);
104 EXPECT_EQ(flags, v.flags);
105 EXPECT_EQ(stream_id, v.stream_id);
106 } while (frame_type++ != 255);
107
108 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
109 EXPECT_QUICHE_DEBUG_DEATH(
110 Http2FrameHeader(0x01000000, Http2FrameType::DATA, 0, 1),
111 "payload_length");
112 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
113 }
114
TEST(Http2FrameHeaderTest,Eq)115 TEST(Http2FrameHeaderTest, Eq) {
116 Http2Random random;
117 uint32_t payload_length = random.Rand32() & 0xffffff;
118 Http2FrameType type = static_cast<Http2FrameType>(random.Rand8());
119
120 uint8_t flags = random.Rand8();
121 uint32_t stream_id = random.Rand32();
122
123 Http2FrameHeader v(payload_length, type, flags, stream_id);
124
125 EXPECT_EQ(payload_length, v.payload_length);
126 EXPECT_EQ(type, v.type);
127 EXPECT_EQ(flags, v.flags);
128 EXPECT_EQ(stream_id, v.stream_id);
129
130 Http2FrameHeader u(0, type, ~flags, stream_id);
131
132 EXPECT_NE(u, v);
133 EXPECT_NE(v, u);
134 EXPECT_FALSE(u == v);
135 EXPECT_FALSE(v == u);
136 EXPECT_TRUE(u != v);
137 EXPECT_TRUE(v != u);
138
139 u = v;
140
141 EXPECT_EQ(u, v);
142 EXPECT_EQ(v, u);
143 EXPECT_TRUE(u == v);
144 EXPECT_TRUE(v == u);
145 EXPECT_FALSE(u != v);
146 EXPECT_FALSE(v != u);
147
148 EXPECT_TRUE(VerifyRandomCalls<Http2FrameHeader>());
149 }
150
151 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
152
153 using TestParams = std::tuple<Http2FrameType, uint8_t>;
154
TestParamToString(const testing::TestParamInfo<TestParams> & info)155 std::string TestParamToString(const testing::TestParamInfo<TestParams>& info) {
156 Http2FrameType type = std::get<0>(info.param);
157 uint8_t flags = std::get<1>(info.param);
158
159 return absl::StrCat(Http2FrameTypeToString(type), static_cast<int>(flags));
160 }
161
162 // The tests of the valid frame types include EXPECT_QUICHE_DEBUG_DEATH, which
163 // is quite slow, so using value parameterized tests in order to allow sharding.
164 class Http2FrameHeaderTypeAndFlagTest
165 : public quiche::test::QuicheTestWithParam<TestParams> {
166 protected:
Http2FrameHeaderTypeAndFlagTest()167 Http2FrameHeaderTypeAndFlagTest()
168 : type_(std::get<0>(GetParam())), flags_(std::get<1>(GetParam())) {
169 QUICHE_LOG(INFO) << "Frame type: " << type_;
170 QUICHE_LOG(INFO) << "Frame flags: "
171 << Http2FrameFlagsToString(type_, flags_);
172 }
173
174 const Http2FrameType type_;
175 const uint8_t flags_;
176 };
177
178 class IsEndStreamTest : public Http2FrameHeaderTypeAndFlagTest {};
179 INSTANTIATE_TEST_SUITE_P(IsEndStream, IsEndStreamTest,
180 Combine(ValuesIn(ValidFrameTypes()),
181 Values(~Http2FrameFlag::END_STREAM, 0xff)),
182 TestParamToString);
TEST_P(IsEndStreamTest,IsEndStream)183 TEST_P(IsEndStreamTest, IsEndStream) {
184 const bool is_set =
185 (flags_ & Http2FrameFlag::END_STREAM) == Http2FrameFlag::END_STREAM;
186 std::string flags_string;
187 Http2FrameHeader v(0, type_, flags_, 0);
188 switch (type_) {
189 case Http2FrameType::DATA:
190 case Http2FrameType::HEADERS:
191 EXPECT_EQ(is_set, v.IsEndStream()) << v;
192 flags_string = v.FlagsToString();
193 if (is_set) {
194 EXPECT_THAT(flags_string, MatchesRegex(".*\\|?END_STREAM\\|.*"));
195 } else {
196 EXPECT_THAT(flags_string, Not(HasSubstr("END_STREAM")));
197 }
198 v.RetainFlags(Http2FrameFlag::END_STREAM);
199 EXPECT_EQ(is_set, v.IsEndStream()) << v;
200 {
201 std::stringstream s;
202 s << v;
203 EXPECT_EQ(v.ToString(), s.str());
204 if (is_set) {
205 EXPECT_THAT(s.str(), HasSubstr("flags=END_STREAM,"));
206 } else {
207 EXPECT_THAT(s.str(), HasSubstr("flags=,"));
208 }
209 }
210 break;
211 default:
212 EXPECT_QUICHE_DEBUG_DEATH(v.IsEndStream(), "DATA.*HEADERS");
213 }
214 }
215
216 class IsACKTest : public Http2FrameHeaderTypeAndFlagTest {};
217 INSTANTIATE_TEST_SUITE_P(IsAck, IsACKTest,
218 Combine(ValuesIn(ValidFrameTypes()),
219 Values(~Http2FrameFlag::ACK, 0xff)),
220 TestParamToString);
TEST_P(IsACKTest,IsAck)221 TEST_P(IsACKTest, IsAck) {
222 const bool is_set = (flags_ & Http2FrameFlag::ACK) == Http2FrameFlag::ACK;
223 std::string flags_string;
224 Http2FrameHeader v(0, type_, flags_, 0);
225 switch (type_) {
226 case Http2FrameType::SETTINGS:
227 case Http2FrameType::PING:
228 EXPECT_EQ(is_set, v.IsAck()) << v;
229 flags_string = v.FlagsToString();
230 if (is_set) {
231 EXPECT_THAT(flags_string, MatchesRegex(".*\\|?ACK\\|.*"));
232 } else {
233 EXPECT_THAT(flags_string, Not(HasSubstr("ACK")));
234 }
235 v.RetainFlags(Http2FrameFlag::ACK);
236 EXPECT_EQ(is_set, v.IsAck()) << v;
237 {
238 std::stringstream s;
239 s << v;
240 EXPECT_EQ(v.ToString(), s.str());
241 if (is_set) {
242 EXPECT_THAT(s.str(), HasSubstr("flags=ACK,"));
243 } else {
244 EXPECT_THAT(s.str(), HasSubstr("flags=,"));
245 }
246 }
247 break;
248 default:
249 EXPECT_QUICHE_DEBUG_DEATH(v.IsAck(), "SETTINGS.*PING");
250 }
251 }
252
253 class IsEndHeadersTest : public Http2FrameHeaderTypeAndFlagTest {};
254 INSTANTIATE_TEST_SUITE_P(IsEndHeaders, IsEndHeadersTest,
255 Combine(ValuesIn(ValidFrameTypes()),
256 Values(~Http2FrameFlag::END_HEADERS, 0xff)),
257 TestParamToString);
TEST_P(IsEndHeadersTest,IsEndHeaders)258 TEST_P(IsEndHeadersTest, IsEndHeaders) {
259 const bool is_set =
260 (flags_ & Http2FrameFlag::END_HEADERS) == Http2FrameFlag::END_HEADERS;
261 std::string flags_string;
262 Http2FrameHeader v(0, type_, flags_, 0);
263 switch (type_) {
264 case Http2FrameType::HEADERS:
265 case Http2FrameType::PUSH_PROMISE:
266 case Http2FrameType::CONTINUATION:
267 EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
268 flags_string = v.FlagsToString();
269 if (is_set) {
270 EXPECT_THAT(flags_string, MatchesRegex(".*\\|?END_HEADERS\\|.*"));
271 } else {
272 EXPECT_THAT(flags_string, Not(HasSubstr("END_HEADERS")));
273 }
274 v.RetainFlags(Http2FrameFlag::END_HEADERS);
275 EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
276 {
277 std::stringstream s;
278 s << v;
279 EXPECT_EQ(v.ToString(), s.str());
280 if (is_set) {
281 EXPECT_THAT(s.str(), HasSubstr("flags=END_HEADERS,"));
282 } else {
283 EXPECT_THAT(s.str(), HasSubstr("flags=,"));
284 }
285 }
286 break;
287 default:
288 EXPECT_QUICHE_DEBUG_DEATH(v.IsEndHeaders(),
289 "HEADERS.*PUSH_PROMISE.*CONTINUATION");
290 }
291 }
292
293 class IsPaddedTest : public Http2FrameHeaderTypeAndFlagTest {};
294 INSTANTIATE_TEST_SUITE_P(IsPadded, IsPaddedTest,
295 Combine(ValuesIn(ValidFrameTypes()),
296 Values(~Http2FrameFlag::PADDED, 0xff)),
297 TestParamToString);
TEST_P(IsPaddedTest,IsPadded)298 TEST_P(IsPaddedTest, IsPadded) {
299 const bool is_set =
300 (flags_ & Http2FrameFlag::PADDED) == Http2FrameFlag::PADDED;
301 std::string flags_string;
302 Http2FrameHeader v(0, type_, flags_, 0);
303 switch (type_) {
304 case Http2FrameType::DATA:
305 case Http2FrameType::HEADERS:
306 case Http2FrameType::PUSH_PROMISE:
307 EXPECT_EQ(is_set, v.IsPadded()) << v;
308 flags_string = v.FlagsToString();
309 if (is_set) {
310 EXPECT_THAT(flags_string, MatchesRegex(".*\\|?PADDED\\|.*"));
311 } else {
312 EXPECT_THAT(flags_string, Not(HasSubstr("PADDED")));
313 }
314 v.RetainFlags(Http2FrameFlag::PADDED);
315 EXPECT_EQ(is_set, v.IsPadded()) << v;
316 {
317 std::stringstream s;
318 s << v;
319 EXPECT_EQ(v.ToString(), s.str());
320 if (is_set) {
321 EXPECT_THAT(s.str(), HasSubstr("flags=PADDED,"));
322 } else {
323 EXPECT_THAT(s.str(), HasSubstr("flags=,"));
324 }
325 }
326 break;
327 default:
328 EXPECT_QUICHE_DEBUG_DEATH(v.IsPadded(), "DATA.*HEADERS.*PUSH_PROMISE");
329 }
330 }
331
332 class HasPriorityTest : public Http2FrameHeaderTypeAndFlagTest {};
333 INSTANTIATE_TEST_SUITE_P(HasPriority, HasPriorityTest,
334 Combine(ValuesIn(ValidFrameTypes()),
335 Values(~Http2FrameFlag::PRIORITY, 0xff)),
336 TestParamToString);
TEST_P(HasPriorityTest,HasPriority)337 TEST_P(HasPriorityTest, HasPriority) {
338 const bool is_set =
339 (flags_ & Http2FrameFlag::PRIORITY) == Http2FrameFlag::PRIORITY;
340 std::string flags_string;
341 Http2FrameHeader v(0, type_, flags_, 0);
342 switch (type_) {
343 case Http2FrameType::HEADERS:
344 EXPECT_EQ(is_set, v.HasPriority()) << v;
345 flags_string = v.FlagsToString();
346 if (is_set) {
347 EXPECT_THAT(flags_string, MatchesRegex(".*\\|?PRIORITY\\|.*"));
348 } else {
349 EXPECT_THAT(flags_string, Not(HasSubstr("PRIORITY")));
350 }
351 v.RetainFlags(Http2FrameFlag::PRIORITY);
352 EXPECT_EQ(is_set, v.HasPriority()) << v;
353 {
354 std::stringstream s;
355 s << v;
356 EXPECT_EQ(v.ToString(), s.str());
357 if (is_set) {
358 EXPECT_THAT(s.str(), HasSubstr("flags=PRIORITY,"));
359 } else {
360 EXPECT_THAT(s.str(), HasSubstr("flags=,"));
361 }
362 }
363 break;
364 default:
365 EXPECT_QUICHE_DEBUG_DEATH(v.HasPriority(), "HEADERS");
366 }
367 }
368
TEST(Http2PriorityFieldsTest,Constructor)369 TEST(Http2PriorityFieldsTest, Constructor) {
370 Http2Random random;
371 uint32_t stream_dependency = random.Rand32() & StreamIdMask();
372 uint32_t weight = 1 + random.Rand8();
373 bool is_exclusive = random.OneIn(2);
374
375 Http2PriorityFields v(stream_dependency, weight, is_exclusive);
376
377 EXPECT_EQ(stream_dependency, v.stream_dependency);
378 EXPECT_EQ(weight, v.weight);
379 EXPECT_EQ(is_exclusive, v.is_exclusive);
380
381 // The high-bit must not be set on the stream id.
382 EXPECT_QUICHE_DEBUG_DEATH(
383 Http2PriorityFields(stream_dependency | 0x80000000, weight, is_exclusive),
384 "31-bit");
385
386 // The weight must be in the range 1-256.
387 EXPECT_QUICHE_DEBUG_DEATH(
388 Http2PriorityFields(stream_dependency, 0, is_exclusive), "too small");
389 EXPECT_QUICHE_DEBUG_DEATH(
390 Http2PriorityFields(stream_dependency, weight + 256, is_exclusive),
391 "too large");
392
393 EXPECT_TRUE(VerifyRandomCalls<Http2PriorityFields>());
394 }
395 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
396
TEST(Http2RstStreamFieldsTest,IsSupported)397 TEST(Http2RstStreamFieldsTest, IsSupported) {
398 Http2RstStreamFields v{Http2ErrorCode::HTTP2_NO_ERROR};
399 EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
400
401 Http2RstStreamFields u{static_cast<Http2ErrorCode>(~0)};
402 EXPECT_FALSE(u.IsSupportedErrorCode()) << v;
403
404 EXPECT_TRUE(VerifyRandomCalls<Http2RstStreamFields>());
405 }
406
TEST(Http2SettingFieldsTest,Misc)407 TEST(Http2SettingFieldsTest, Misc) {
408 Http2Random random;
409 Http2SettingsParameter parameter =
410 static_cast<Http2SettingsParameter>(random.Rand16());
411 uint32_t value = random.Rand32();
412
413 Http2SettingFields v(parameter, value);
414
415 EXPECT_EQ(v, v);
416 EXPECT_EQ(parameter, v.parameter);
417 EXPECT_EQ(value, v.value);
418
419 if (static_cast<uint16_t>(parameter) < 7) {
420 EXPECT_TRUE(v.IsSupportedParameter()) << v;
421 } else {
422 EXPECT_FALSE(v.IsSupportedParameter()) << v;
423 }
424
425 Http2SettingFields u(parameter, ~value);
426 EXPECT_NE(v, u);
427 EXPECT_EQ(v.parameter, u.parameter);
428 EXPECT_NE(v.value, u.value);
429
430 Http2SettingFields w(IncrementEnum(parameter), value);
431 EXPECT_NE(v, w);
432 EXPECT_NE(v.parameter, w.parameter);
433 EXPECT_EQ(v.value, w.value);
434
435 Http2SettingFields x(Http2SettingsParameter::MAX_FRAME_SIZE, 123);
436 std::stringstream s;
437 s << x;
438 EXPECT_EQ("parameter=MAX_FRAME_SIZE, value=123", s.str());
439
440 EXPECT_TRUE(VerifyRandomCalls<Http2SettingFields>());
441 }
442
TEST(Http2PushPromiseTest,Misc)443 TEST(Http2PushPromiseTest, Misc) {
444 Http2Random random;
445 uint32_t promised_stream_id = random.Rand32() & StreamIdMask();
446
447 Http2PushPromiseFields v{promised_stream_id};
448 EXPECT_EQ(promised_stream_id, v.promised_stream_id);
449 EXPECT_EQ(v, v);
450
451 std::stringstream s;
452 s << v;
453 EXPECT_EQ(absl::StrCat("promised_stream_id=", promised_stream_id), s.str());
454
455 // High-bit is reserved, but not used, so we can set it.
456 promised_stream_id |= 0x80000000;
457 Http2PushPromiseFields w{promised_stream_id};
458 EXPECT_EQ(w, w);
459 EXPECT_NE(v, w);
460
461 v.promised_stream_id = promised_stream_id;
462 EXPECT_EQ(v, w);
463
464 EXPECT_TRUE(VerifyRandomCalls<Http2PushPromiseFields>());
465 }
466
TEST(Http2PingFieldsTest,Misc)467 TEST(Http2PingFieldsTest, Misc) {
468 Http2PingFields v{{'8', ' ', 'b', 'y', 't', 'e', 's', '\0'}};
469 std::stringstream s;
470 s << v;
471 EXPECT_EQ("opaque_bytes=0x3820627974657300", s.str());
472
473 EXPECT_TRUE(VerifyRandomCalls<Http2PingFields>());
474 }
475
TEST(Http2GoAwayFieldsTest,Misc)476 TEST(Http2GoAwayFieldsTest, Misc) {
477 Http2Random random;
478 uint32_t last_stream_id = random.Rand32() & StreamIdMask();
479 Http2ErrorCode error_code = static_cast<Http2ErrorCode>(random.Rand32());
480
481 Http2GoAwayFields v(last_stream_id, error_code);
482 EXPECT_EQ(v, v);
483 EXPECT_EQ(last_stream_id, v.last_stream_id);
484 EXPECT_EQ(error_code, v.error_code);
485
486 if (static_cast<uint32_t>(error_code) < 14) {
487 EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
488 } else {
489 EXPECT_FALSE(v.IsSupportedErrorCode()) << v;
490 }
491
492 Http2GoAwayFields u(~last_stream_id, error_code);
493 EXPECT_NE(v, u);
494 EXPECT_NE(v.last_stream_id, u.last_stream_id);
495 EXPECT_EQ(v.error_code, u.error_code);
496
497 EXPECT_TRUE(VerifyRandomCalls<Http2GoAwayFields>());
498 }
499
TEST(Http2WindowUpdateTest,Misc)500 TEST(Http2WindowUpdateTest, Misc) {
501 Http2Random random;
502 uint32_t window_size_increment = random.Rand32() & UInt31Mask();
503
504 Http2WindowUpdateFields v{window_size_increment};
505 EXPECT_EQ(window_size_increment, v.window_size_increment);
506 EXPECT_EQ(v, v);
507
508 std::stringstream s;
509 s << v;
510 EXPECT_EQ(absl::StrCat("window_size_increment=", window_size_increment),
511 s.str());
512
513 // High-bit is reserved, but not used, so we can set it.
514 window_size_increment |= 0x80000000;
515 Http2WindowUpdateFields w{window_size_increment};
516 EXPECT_EQ(w, w);
517 EXPECT_NE(v, w);
518
519 v.window_size_increment = window_size_increment;
520 EXPECT_EQ(v, w);
521
522 EXPECT_TRUE(VerifyRandomCalls<Http2WindowUpdateFields>());
523 }
524
TEST(Http2AltSvcTest,Misc)525 TEST(Http2AltSvcTest, Misc) {
526 Http2Random random;
527 uint16_t origin_length = random.Rand16();
528
529 Http2AltSvcFields v{origin_length};
530 EXPECT_EQ(origin_length, v.origin_length);
531 EXPECT_EQ(v, v);
532
533 std::stringstream s;
534 s << v;
535 EXPECT_EQ(absl::StrCat("origin_length=", origin_length), s.str());
536
537 Http2AltSvcFields w{++origin_length};
538 EXPECT_EQ(w, w);
539 EXPECT_NE(v, w);
540
541 v.origin_length = w.origin_length;
542 EXPECT_EQ(v, w);
543
544 EXPECT_TRUE(VerifyRandomCalls<Http2AltSvcFields>());
545 }
546
TEST(Http2PriorityUpdateFieldsTest,Eq)547 TEST(Http2PriorityUpdateFieldsTest, Eq) {
548 Http2PriorityUpdateFields u(/* prioritized_stream_id = */ 1);
549 Http2PriorityUpdateFields v(/* prioritized_stream_id = */ 3);
550
551 EXPECT_NE(u, v);
552 EXPECT_FALSE(u == v);
553 EXPECT_TRUE(u != v);
554
555 u = v;
556 EXPECT_EQ(u, v);
557 EXPECT_TRUE(u == v);
558 EXPECT_FALSE(u != v);
559 }
560
TEST(Http2PriorityUpdateFieldsTest,Misc)561 TEST(Http2PriorityUpdateFieldsTest, Misc) {
562 Http2PriorityUpdateFields u(/* prioritized_stream_id = */ 1);
563 EXPECT_EQ("prioritized_stream_id=1", u.ToString());
564
565 EXPECT_TRUE(VerifyRandomCalls<Http2PriorityUpdateFields>());
566 }
567
568 } // namespace
569 } // namespace test
570 } // namespace http2
571