• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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