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/hpack/decoder/hpack_decoder_state.h"
6
7 // Tests of HpackDecoderState.
8
9 #include <utility>
10 #include <vector>
11
12 #include "absl/strings/string_view.h"
13 #include "quiche/http2/hpack/http2_hpack_constants.h"
14 #include "quiche/http2/http2_constants.h"
15 #include "quiche/http2/test_tools/verify_macros.h"
16 #include "quiche/common/platform/api/quiche_logging.h"
17 #include "quiche/common/platform/api/quiche_test.h"
18
19 using ::testing::AssertionResult;
20 using ::testing::AssertionSuccess;
21 using ::testing::Eq;
22 using ::testing::Mock;
23 using ::testing::StrictMock;
24
25 namespace http2 {
26 namespace test {
27 class HpackDecoderStatePeer {
28 public:
GetDecoderTables(HpackDecoderState * state)29 static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) {
30 return &state->decoder_tables_;
31 }
32 };
33
34 namespace {
35
36 class MockHpackDecoderListener : public HpackDecoderListener {
37 public:
38 MOCK_METHOD(void, OnHeaderListStart, (), (override));
39 MOCK_METHOD(void, OnHeader,
40 (const std::string& name, const std::string& value), (override));
41 MOCK_METHOD(void, OnHeaderListEnd, (), (override));
42 MOCK_METHOD(void, OnHeaderErrorDetected, (absl::string_view error_message),
43 (override));
44 };
45
46 enum StringBacking { STATIC, UNBUFFERED, BUFFERED };
47
48 class HpackDecoderStateTest : public quiche::test::QuicheTest {
49 protected:
HpackDecoderStateTest()50 HpackDecoderStateTest() : decoder_state_(&listener_) {}
51
GetDecoderTables()52 HpackDecoderTables* GetDecoderTables() {
53 return HpackDecoderStatePeer::GetDecoderTables(&decoder_state_);
54 }
55
Lookup(size_t index)56 const HpackStringPair* Lookup(size_t index) {
57 return GetDecoderTables()->Lookup(index);
58 }
59
current_header_table_size()60 size_t current_header_table_size() {
61 return GetDecoderTables()->current_header_table_size();
62 }
63
header_table_size_limit()64 size_t header_table_size_limit() {
65 return GetDecoderTables()->header_table_size_limit();
66 }
67
set_header_table_size_limit(size_t size)68 void set_header_table_size_limit(size_t size) {
69 GetDecoderTables()->DynamicTableSizeUpdate(size);
70 }
71
SetStringBuffer(const char * s,StringBacking backing,HpackDecoderStringBuffer * string_buffer)72 void SetStringBuffer(const char* s, StringBacking backing,
73 HpackDecoderStringBuffer* string_buffer) {
74 switch (backing) {
75 case STATIC:
76 string_buffer->Set(s, true);
77 break;
78 case UNBUFFERED:
79 string_buffer->Set(s, false);
80 break;
81 case BUFFERED:
82 string_buffer->Set(s, false);
83 string_buffer->BufferStringIfUnbuffered();
84 break;
85 }
86 }
87
SetName(const char * s,StringBacking backing)88 void SetName(const char* s, StringBacking backing) {
89 SetStringBuffer(s, backing, &name_buffer_);
90 }
91
SetValue(const char * s,StringBacking backing)92 void SetValue(const char* s, StringBacking backing) {
93 SetStringBuffer(s, backing, &value_buffer_);
94 }
95
SendStartAndVerifyCallback()96 void SendStartAndVerifyCallback() {
97 EXPECT_CALL(listener_, OnHeaderListStart());
98 decoder_state_.OnHeaderBlockStart();
99 Mock::VerifyAndClearExpectations(&listener_);
100 }
101
SendSizeUpdate(size_t size)102 void SendSizeUpdate(size_t size) {
103 decoder_state_.OnDynamicTableSizeUpdate(size);
104 Mock::VerifyAndClearExpectations(&listener_);
105 }
106
SendIndexAndVerifyCallback(size_t index,HpackEntryType,const char * expected_name,const char * expected_value)107 void SendIndexAndVerifyCallback(size_t index,
108 HpackEntryType /*expected_type*/,
109 const char* expected_name,
110 const char* expected_value) {
111 EXPECT_CALL(listener_, OnHeader(Eq(expected_name), Eq(expected_value)));
112 decoder_state_.OnIndexedHeader(index);
113 Mock::VerifyAndClearExpectations(&listener_);
114 }
115
SendValueAndVerifyCallback(size_t name_index,HpackEntryType entry_type,const char * name,const char * value,StringBacking value_backing)116 void SendValueAndVerifyCallback(size_t name_index, HpackEntryType entry_type,
117 const char* name, const char* value,
118 StringBacking value_backing) {
119 SetValue(value, value_backing);
120 EXPECT_CALL(listener_, OnHeader(Eq(name), Eq(value)));
121 decoder_state_.OnNameIndexAndLiteralValue(entry_type, name_index,
122 &value_buffer_);
123 Mock::VerifyAndClearExpectations(&listener_);
124 }
125
SendNameAndValueAndVerifyCallback(HpackEntryType entry_type,const char * name,StringBacking name_backing,const char * value,StringBacking value_backing)126 void SendNameAndValueAndVerifyCallback(HpackEntryType entry_type,
127 const char* name,
128 StringBacking name_backing,
129 const char* value,
130 StringBacking value_backing) {
131 SetName(name, name_backing);
132 SetValue(value, value_backing);
133 EXPECT_CALL(listener_, OnHeader(Eq(name), Eq(value)));
134 decoder_state_.OnLiteralNameAndValue(entry_type, &name_buffer_,
135 &value_buffer_);
136 Mock::VerifyAndClearExpectations(&listener_);
137 }
138
SendEndAndVerifyCallback()139 void SendEndAndVerifyCallback() {
140 EXPECT_CALL(listener_, OnHeaderListEnd());
141 decoder_state_.OnHeaderBlockEnd();
142 Mock::VerifyAndClearExpectations(&listener_);
143 }
144
145 // dynamic_index is one-based, because that is the way RFC 7541 shows it.
VerifyEntry(size_t dynamic_index,const char * name,const char * value)146 AssertionResult VerifyEntry(size_t dynamic_index, const char* name,
147 const char* value) {
148 const HpackStringPair* entry =
149 Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
150 HTTP2_VERIFY_NE(entry, nullptr);
151 HTTP2_VERIFY_EQ(entry->name, name);
152 HTTP2_VERIFY_EQ(entry->value, value);
153 return AssertionSuccess();
154 }
VerifyNoEntry(size_t dynamic_index)155 AssertionResult VerifyNoEntry(size_t dynamic_index) {
156 const HpackStringPair* entry =
157 Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
158 HTTP2_VERIFY_EQ(entry, nullptr);
159 return AssertionSuccess();
160 }
VerifyDynamicTableContents(const std::vector<std::pair<const char *,const char * >> & entries)161 AssertionResult VerifyDynamicTableContents(
162 const std::vector<std::pair<const char*, const char*>>& entries) {
163 size_t index = 1;
164 for (const auto& entry : entries) {
165 HTTP2_VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second));
166 ++index;
167 }
168 HTTP2_VERIFY_SUCCESS(VerifyNoEntry(index));
169 return AssertionSuccess();
170 }
171
172 StrictMock<MockHpackDecoderListener> listener_;
173 HpackDecoderState decoder_state_;
174 HpackDecoderStringBuffer name_buffer_, value_buffer_;
175 };
176
177 // Test based on RFC 7541, section C.3: Request Examples without Huffman Coding.
178 // This section shows several consecutive header lists, corresponding to HTTP
179 // requests, on the same connection.
TEST_F(HpackDecoderStateTest,C3_RequestExamples)180 TEST_F(HpackDecoderStateTest, C3_RequestExamples) {
181 // C.3.1 First Request
182 //
183 // Header list to encode:
184 //
185 // :method: GET
186 // :scheme: http
187 // :path: /
188 // :authority: www.example.com
189
190 SendStartAndVerifyCallback();
191 SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
192 "GET");
193 SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme",
194 "http");
195 SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/");
196 SendValueAndVerifyCallback(1, HpackEntryType::kIndexedLiteralHeader,
197 ":authority", "www.example.com", UNBUFFERED);
198 SendEndAndVerifyCallback();
199
200 // Dynamic Table (after decoding):
201 //
202 // [ 1] (s = 57) :authority: www.example.com
203 // Table size: 57
204
205 ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}}));
206 ASSERT_EQ(57u, current_header_table_size());
207
208 // C.3.2 Second Request
209 //
210 // Header list to encode:
211 //
212 // :method: GET
213 // :scheme: http
214 // :path: /
215 // :authority: www.example.com
216 // cache-control: no-cache
217
218 SendStartAndVerifyCallback();
219 SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
220 "GET");
221 SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme",
222 "http");
223 SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/");
224 SendIndexAndVerifyCallback(62, HpackEntryType::kIndexedHeader, ":authority",
225 "www.example.com");
226 SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader,
227 "cache-control", "no-cache", UNBUFFERED);
228 SendEndAndVerifyCallback();
229
230 // Dynamic Table (after decoding):
231 //
232 // [ 1] (s = 53) cache-control: no-cache
233 // [ 2] (s = 57) :authority: www.example.com
234 // Table size: 110
235
236 ASSERT_TRUE(VerifyDynamicTableContents(
237 {{"cache-control", "no-cache"}, {":authority", "www.example.com"}}));
238 ASSERT_EQ(110u, current_header_table_size());
239
240 // C.3.3 Third Request
241 //
242 // Header list to encode:
243 //
244 // :method: GET
245 // :scheme: https
246 // :path: /index.html
247 // :authority: www.example.com
248 // custom-key: custom-value
249
250 SendStartAndVerifyCallback();
251 SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
252 "GET");
253 SendIndexAndVerifyCallback(7, HpackEntryType::kIndexedHeader, ":scheme",
254 "https");
255 SendIndexAndVerifyCallback(5, HpackEntryType::kIndexedHeader, ":path",
256 "/index.html");
257 SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, ":authority",
258 "www.example.com");
259 SendNameAndValueAndVerifyCallback(HpackEntryType::kIndexedLiteralHeader,
260 "custom-key", UNBUFFERED, "custom-value",
261 UNBUFFERED);
262 SendEndAndVerifyCallback();
263
264 // Dynamic Table (after decoding):
265 //
266 // [ 1] (s = 54) custom-key: custom-value
267 // [ 2] (s = 53) cache-control: no-cache
268 // [ 3] (s = 57) :authority: www.example.com
269 // Table size: 164
270
271 ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"},
272 {"cache-control", "no-cache"},
273 {":authority", "www.example.com"}}));
274 ASSERT_EQ(164u, current_header_table_size());
275 }
276
277 // Test based on RFC 7541, section C.5: Response Examples without Huffman
278 // Coding. This section shows several consecutive header lists, corresponding
279 // to HTTP responses, on the same connection. The HTTP/2 setting parameter
280 // SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing
281 // some evictions to occur.
TEST_F(HpackDecoderStateTest,C5_ResponseExamples)282 TEST_F(HpackDecoderStateTest, C5_ResponseExamples) {
283 set_header_table_size_limit(256);
284
285 // C.5.1 First Response
286 //
287 // Header list to encode:
288 //
289 // :status: 302
290 // cache-control: private
291 // date: Mon, 21 Oct 2013 20:13:21 GMT
292 // location: https://www.example.com
293
294 SendStartAndVerifyCallback();
295 SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader,
296 ":status", "302", BUFFERED);
297 SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader,
298 "cache-control", "private", UNBUFFERED);
299 SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date",
300 "Mon, 21 Oct 2013 20:13:21 GMT", UNBUFFERED);
301 SendValueAndVerifyCallback(46, HpackEntryType::kIndexedLiteralHeader,
302 "location", "https://www.example.com", UNBUFFERED);
303 SendEndAndVerifyCallback();
304
305 // Dynamic Table (after decoding):
306 //
307 // [ 1] (s = 63) location: https://www.example.com
308 // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
309 // [ 3] (s = 52) cache-control: private
310 // [ 4] (s = 42) :status: 302
311 // Table size: 222
312
313 ASSERT_TRUE(
314 VerifyDynamicTableContents({{"location", "https://www.example.com"},
315 {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
316 {"cache-control", "private"},
317 {":status", "302"}}));
318 ASSERT_EQ(222u, current_header_table_size());
319
320 // C.5.2 Second Response
321 //
322 // The (":status", "302") header field is evicted from the dynamic table to
323 // free space to allow adding the (":status", "307") header field.
324 //
325 // Header list to encode:
326 //
327 // :status: 307
328 // cache-control: private
329 // date: Mon, 21 Oct 2013 20:13:21 GMT
330 // location: https://www.example.com
331
332 SendStartAndVerifyCallback();
333 SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader,
334 ":status", "307", BUFFERED);
335 SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader,
336 "cache-control", "private");
337 SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "date",
338 "Mon, 21 Oct 2013 20:13:21 GMT");
339 SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, "location",
340 "https://www.example.com");
341 SendEndAndVerifyCallback();
342
343 // Dynamic Table (after decoding):
344 //
345 // [ 1] (s = 42) :status: 307
346 // [ 2] (s = 63) location: https://www.example.com
347 // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
348 // [ 4] (s = 52) cache-control: private
349 // Table size: 222
350
351 ASSERT_TRUE(
352 VerifyDynamicTableContents({{":status", "307"},
353 {"location", "https://www.example.com"},
354 {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
355 {"cache-control", "private"}}));
356 ASSERT_EQ(222u, current_header_table_size());
357
358 // C.5.3 Third Response
359 //
360 // Several header fields are evicted from the dynamic table during the
361 // processing of this header list.
362 //
363 // Header list to encode:
364 //
365 // :status: 200
366 // cache-control: private
367 // date: Mon, 21 Oct 2013 20:13:22 GMT
368 // location: https://www.example.com
369 // content-encoding: gzip
370 // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
371
372 SendStartAndVerifyCallback();
373 SendIndexAndVerifyCallback(8, HpackEntryType::kIndexedHeader, ":status",
374 "200");
375 SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader,
376 "cache-control", "private");
377 SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date",
378 "Mon, 21 Oct 2013 20:13:22 GMT", BUFFERED);
379 SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "location",
380 "https://www.example.com");
381 SendValueAndVerifyCallback(26, HpackEntryType::kIndexedLiteralHeader,
382 "content-encoding", "gzip", UNBUFFERED);
383 SendValueAndVerifyCallback(
384 55, HpackEntryType::kIndexedLiteralHeader, "set-cookie",
385 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", BUFFERED);
386 SendEndAndVerifyCallback();
387
388 // Dynamic Table (after decoding):
389 //
390 // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
391 // max-age=3600; version=1
392 // [ 2] (s = 52) content-encoding: gzip
393 // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
394 // Table size: 215
395
396 ASSERT_TRUE(VerifyDynamicTableContents(
397 {{"set-cookie",
398 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
399 {"content-encoding", "gzip"},
400 {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}}));
401 ASSERT_EQ(215u, current_header_table_size());
402 }
403
404 // Confirm that the table size can be changed, but at most twice.
TEST_F(HpackDecoderStateTest,OptionalTableSizeChanges)405 TEST_F(HpackDecoderStateTest, OptionalTableSizeChanges) {
406 SendStartAndVerifyCallback();
407 EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
408 header_table_size_limit());
409 SendSizeUpdate(1024);
410 EXPECT_EQ(1024u, header_table_size_limit());
411 SendSizeUpdate(0);
412 EXPECT_EQ(0u, header_table_size_limit());
413
414 // Three updates aren't allowed.
415 EXPECT_CALL(listener_, OnHeaderErrorDetected(
416 Eq("Dynamic table size update not allowed")));
417 SendSizeUpdate(0);
418 }
419
420 // Confirm that required size updates are indeed required before headers.
TEST_F(HpackDecoderStateTest,RequiredTableSizeChangeBeforeHeader)421 TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeHeader) {
422 EXPECT_EQ(4096u, decoder_state_.GetCurrentHeaderTableSizeSetting());
423 decoder_state_.ApplyHeaderTableSizeSetting(1024);
424 decoder_state_.ApplyHeaderTableSizeSetting(2048);
425 EXPECT_EQ(2048u, decoder_state_.GetCurrentHeaderTableSizeSetting());
426
427 // First provide the required update, and an allowed second update.
428 SendStartAndVerifyCallback();
429 EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
430 header_table_size_limit());
431 SendSizeUpdate(1024);
432 EXPECT_EQ(1024u, header_table_size_limit());
433 SendSizeUpdate(1500);
434 EXPECT_EQ(1500u, header_table_size_limit());
435 SendEndAndVerifyCallback();
436
437 // Another HPACK block, but this time missing the required size update.
438 decoder_state_.ApplyHeaderTableSizeSetting(1024);
439 EXPECT_EQ(1024u, decoder_state_.GetCurrentHeaderTableSizeSetting());
440 SendStartAndVerifyCallback();
441 EXPECT_CALL(listener_,
442 OnHeaderErrorDetected(Eq("Missing dynamic table size update")));
443 decoder_state_.OnIndexedHeader(1);
444
445 // Further decoded entries are ignored.
446 decoder_state_.OnIndexedHeader(1);
447 decoder_state_.OnDynamicTableSizeUpdate(1);
448 SetValue("value", UNBUFFERED);
449 decoder_state_.OnNameIndexAndLiteralValue(
450 HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_);
451 SetName("name", UNBUFFERED);
452 decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader,
453 &name_buffer_, &value_buffer_);
454 decoder_state_.OnHeaderBlockEnd();
455 decoder_state_.OnHpackDecodeError(HpackDecodingError::kIndexVarintError, "");
456 }
457
458 // Confirm that required size updates are validated.
TEST_F(HpackDecoderStateTest,InvalidRequiredSizeUpdate)459 TEST_F(HpackDecoderStateTest, InvalidRequiredSizeUpdate) {
460 // Require a size update, but provide one that isn't small enough.
461 decoder_state_.ApplyHeaderTableSizeSetting(1024);
462 SendStartAndVerifyCallback();
463 EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
464 header_table_size_limit());
465 EXPECT_CALL(
466 listener_,
467 OnHeaderErrorDetected(
468 Eq("Initial dynamic table size update is above low water mark")));
469 SendSizeUpdate(2048);
470 }
471
472 // Confirm that required size updates are indeed required before the end.
TEST_F(HpackDecoderStateTest,RequiredTableSizeChangeBeforeEnd)473 TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeEnd) {
474 decoder_state_.ApplyHeaderTableSizeSetting(1024);
475 SendStartAndVerifyCallback();
476 EXPECT_CALL(listener_,
477 OnHeaderErrorDetected(Eq("Missing dynamic table size update")));
478 decoder_state_.OnHeaderBlockEnd();
479 }
480
481 // Confirm that optional size updates are validated.
TEST_F(HpackDecoderStateTest,InvalidOptionalSizeUpdate)482 TEST_F(HpackDecoderStateTest, InvalidOptionalSizeUpdate) {
483 // Require a size update, but provide one that isn't small enough.
484 SendStartAndVerifyCallback();
485 EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
486 header_table_size_limit());
487 EXPECT_CALL(listener_,
488 OnHeaderErrorDetected(Eq(
489 "Dynamic table size update is above acknowledged setting")));
490 SendSizeUpdate(Http2SettingsInfo::DefaultHeaderTableSize() + 1);
491 }
492
TEST_F(HpackDecoderStateTest,InvalidStaticIndex)493 TEST_F(HpackDecoderStateTest, InvalidStaticIndex) {
494 SendStartAndVerifyCallback();
495 EXPECT_CALL(listener_,
496 OnHeaderErrorDetected(
497 Eq("Invalid index in indexed header field representation")));
498 decoder_state_.OnIndexedHeader(0);
499 }
500
TEST_F(HpackDecoderStateTest,InvalidDynamicIndex)501 TEST_F(HpackDecoderStateTest, InvalidDynamicIndex) {
502 SendStartAndVerifyCallback();
503 EXPECT_CALL(listener_,
504 OnHeaderErrorDetected(
505 Eq("Invalid index in indexed header field representation")));
506 decoder_state_.OnIndexedHeader(kFirstDynamicTableIndex);
507 }
508
TEST_F(HpackDecoderStateTest,InvalidNameIndex)509 TEST_F(HpackDecoderStateTest, InvalidNameIndex) {
510 SendStartAndVerifyCallback();
511 EXPECT_CALL(listener_,
512 OnHeaderErrorDetected(Eq("Invalid index in literal header field "
513 "with indexed name representation")));
514 SetValue("value", UNBUFFERED);
515 decoder_state_.OnNameIndexAndLiteralValue(
516 HpackEntryType::kIndexedLiteralHeader, kFirstDynamicTableIndex,
517 &value_buffer_);
518 }
519
TEST_F(HpackDecoderStateTest,ErrorsSuppressCallbacks)520 TEST_F(HpackDecoderStateTest, ErrorsSuppressCallbacks) {
521 SendStartAndVerifyCallback();
522 EXPECT_CALL(listener_,
523 OnHeaderErrorDetected(Eq("Name Huffman encoding error")));
524 decoder_state_.OnHpackDecodeError(HpackDecodingError::kNameHuffmanError, "");
525
526 // Further decoded entries are ignored.
527 decoder_state_.OnIndexedHeader(1);
528 decoder_state_.OnDynamicTableSizeUpdate(1);
529 SetValue("value", UNBUFFERED);
530 decoder_state_.OnNameIndexAndLiteralValue(
531 HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_);
532 SetName("name", UNBUFFERED);
533 decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader,
534 &name_buffer_, &value_buffer_);
535 decoder_state_.OnHeaderBlockEnd();
536 decoder_state_.OnHpackDecodeError(HpackDecodingError::kIndexVarintError, "");
537 }
538
539 } // namespace
540 } // namespace test
541 } // namespace http2
542