blob: 707191344855cb220467e25257340fea35caa8fb [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2018 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/quic/core/qpack/qpack_decoder.h"
6
7#include <algorithm>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
10#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
vasilvv0fb44432019-03-13 22:47:36 -070011#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
14#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
15
16using ::testing::Eq;
bnc098ff612019-07-09 03:24:37 -070017using ::testing::Mock;
QUICHE teama6ef0a62019-03-07 20:34:33 -050018using ::testing::Sequence;
19using ::testing::StrictMock;
20using ::testing::Values;
21
22namespace quic {
23namespace test {
24namespace {
25
26// Header Acknowledgement decoder stream instruction with stream_id = 1.
27const char* const kHeaderAcknowledgement = "\x81";
28
bnc57b5f622019-08-21 14:07:44 -070029const uint64_t kMaximumDynamicTableCapacity = 1024;
30const uint64_t kMaximumBlockedStreams = 1;
bnc4c664c52019-08-04 18:14:12 -070031
QUICHE teama6ef0a62019-03-07 20:34:33 -050032class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
33 protected:
34 QpackDecoderTest()
bnc57b5f622019-08-21 14:07:44 -070035 : qpack_decoder_(kMaximumDynamicTableCapacity,
36 kMaximumBlockedStreams,
37 &encoder_stream_error_delegate_),
renjietang8a2df8f2019-08-07 10:43:52 -070038 fragment_mode_(GetParam()) {
39 qpack_decoder_.set_qpack_stream_sender_delegate(
40 &decoder_stream_sender_delegate_);
41 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050042
43 ~QpackDecoderTest() override = default;
44
45 void DecodeEncoderStreamData(QuicStringPiece data) {
bnc7d9e2a72019-08-09 08:20:10 -070046 qpack_decoder_.encoder_stream_receiver()->Decode(data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050047 }
48
bnc57b5f622019-08-21 14:07:44 -070049 std::unique_ptr<QpackProgressiveDecoder> CreateProgressiveDecoder(
50 QuicStreamId stream_id) {
51 return qpack_decoder_.CreateProgressiveDecoder(stream_id, &handler_);
52 }
53
bnc098ff612019-07-09 03:24:37 -070054 // Set up |progressive_decoder_|.
55 void StartDecoding() {
bnc57b5f622019-08-21 14:07:44 -070056 progressive_decoder_ = CreateProgressiveDecoder(/* stream_id = */ 1);
bnc098ff612019-07-09 03:24:37 -070057 }
58
59 // Pass header block data to QpackProgressiveDecoder::Decode()
60 // in fragments dictated by |fragment_mode_|.
61 void DecodeData(QuicStringPiece data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 auto fragment_size_generator =
63 FragmentModeToFragmentSizeGenerator(fragment_mode_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050064 while (!data.empty()) {
65 size_t fragment_size = std::min(fragment_size_generator(), data.size());
bnc098ff612019-07-09 03:24:37 -070066 progressive_decoder_->Decode(data.substr(0, fragment_size));
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 data = data.substr(fragment_size);
68 }
bnc098ff612019-07-09 03:24:37 -070069 }
70
71 // Signal end of header block to QpackProgressiveDecoder.
72 void EndDecoding() {
73 progressive_decoder_->EndHeaderBlock();
74 // |progressive_decoder_| is kept alive so that it can
75 // handle callbacks later in case of blocked decoding.
76 }
77
78 // Decode an entire header block.
79 void DecodeHeaderBlock(QuicStringPiece data) {
80 StartDecoding();
81 DecodeData(data);
82 EndDecoding();
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 }
84
85 StrictMock<MockEncoderStreamErrorDelegate> encoder_stream_error_delegate_;
renjietangc2aa5cb2019-06-20 12:22:53 -070086 StrictMock<MockQpackStreamSenderDelegate> decoder_stream_sender_delegate_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 StrictMock<MockHeadersHandler> handler_;
88
89 private:
90 QpackDecoder qpack_decoder_;
91 const FragmentMode fragment_mode_;
bnc098ff612019-07-09 03:24:37 -070092 std::unique_ptr<QpackProgressiveDecoder> progressive_decoder_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050093};
94
QUICHE team1bfe0d72019-09-23 04:50:47 -070095INSTANTIATE_TEST_SUITE_P(All,
vasilvvc48c8712019-03-11 13:38:16 -070096 QpackDecoderTest,
97 Values(FragmentMode::kSingleChunk,
98 FragmentMode::kOctetByOctet));
QUICHE teama6ef0a62019-03-07 20:34:33 -050099
100TEST_P(QpackDecoderTest, NoPrefix) {
101 EXPECT_CALL(handler_,
102 OnDecodingErrorDetected(Eq("Incomplete header data prefix.")));
103
104 // Header Data Prefix is at least two bytes long.
105 DecodeHeaderBlock(QuicTextUtils::HexDecode("00"));
106}
107
108TEST_P(QpackDecoderTest, EmptyHeaderBlock) {
109 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110
111 DecodeHeaderBlock(QuicTextUtils::HexDecode("0000"));
112}
113
114TEST_P(QpackDecoderTest, LiteralEntryEmptyName) {
115 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("foo")));
116 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117
118 DecodeHeaderBlock(QuicTextUtils::HexDecode("00002003666f6f"));
119}
120
121TEST_P(QpackDecoderTest, LiteralEntryEmptyValue) {
122 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
123 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124
125 DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f00"));
126}
127
128TEST_P(QpackDecoderTest, LiteralEntryEmptyNameAndValue) {
129 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("")));
130 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131
132 DecodeHeaderBlock(QuicTextUtils::HexDecode("00002000"));
133}
134
135TEST_P(QpackDecoderTest, SimpleLiteralEntry) {
136 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
137 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138
139 DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f03626172"));
140}
141
142TEST_P(QpackDecoderTest, MultipleLiteralEntries) {
143 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
vasilvvc48c8712019-03-11 13:38:16 -0700144 std::string str(127, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foobaar"), QuicStringPiece(str)));
146 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147
148 DecodeHeaderBlock(QuicTextUtils::HexDecode(
149 "0000" // prefix
150 "23666f6f03626172" // foo: bar
151 "2700666f6f62616172" // 7 octet long header name, the smallest number
152 // that does not fit on a 3-bit prefix.
153 "7f0061616161616161" // 127 octet long header value, the smallest number
154 "616161616161616161" // that does not fit on a 7-bit prefix.
155 "6161616161616161616161616161616161616161616161616161616161616161616161"
156 "6161616161616161616161616161616161616161616161616161616161616161616161"
157 "6161616161616161616161616161616161616161616161616161616161616161616161"
158 "616161616161"));
159}
160
161// Name Length value is too large for varint decoder to decode.
162TEST_P(QpackDecoderTest, NameLenTooLargeForVarintDecoder) {
163 EXPECT_CALL(handler_,
164 OnDecodingErrorDetected(Eq("Encoded integer too large.")));
165
166 DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffffffffffffffffffff"));
167}
168
169// Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
170TEST_P(QpackDecoderTest, NameLenExceedsLimit) {
171 EXPECT_CALL(handler_,
172 OnDecodingErrorDetected(Eq("String literal too long.")));
173
174 DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffff7f"));
175}
176
177// Value Length value is too large for varint decoder to decode.
178TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) {
179 EXPECT_CALL(handler_,
180 OnDecodingErrorDetected(Eq("Encoded integer too large.")));
181
182 DecodeHeaderBlock(
183 QuicTextUtils::HexDecode("000023666f6f7fffffffffffffffffffff"));
184}
185
186// Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
187TEST_P(QpackDecoderTest, ValueLenExceedsLimit) {
188 EXPECT_CALL(handler_,
189 OnDecodingErrorDetected(Eq("String literal too long.")));
190
191 DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f7fffff7f"));
192}
193
194TEST_P(QpackDecoderTest, IncompleteHeaderBlock) {
195 EXPECT_CALL(handler_,
196 OnDecodingErrorDetected(Eq("Incomplete header block.")));
197
198 DecodeHeaderBlock(QuicTextUtils::HexDecode("00002366"));
199}
200
201TEST_P(QpackDecoderTest, HuffmanSimple) {
202 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")));
203 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204
205 DecodeHeaderBlock(
206 QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
207}
208
209TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
210 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")))
211 .Times(4);
212 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213
214 DecodeHeaderBlock(QuicTextUtils::HexDecode(
215 "0000" // Prefix.
216 "2f0125a849e95ba97d7f" // Huffman-encoded name.
217 "8925a849e95bb8e8b4bf" // Huffman-encoded value.
218 "2703637573746f6d2d6b6579" // Non-Huffman encoded name.
219 "0c637573746f6d2d76616c7565" // Non-Huffman encoded value.
220 "2f0125a849e95ba97d7f" // Huffman-encoded name.
221 "0c637573746f6d2d76616c7565" // Non-Huffman encoded value.
222 "2703637573746f6d2d6b6579" // Non-Huffman encoded name.
223 "8925a849e95bb8e8b4bf")); // Huffman-encoded value.
224}
225
226TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) {
227 EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
228 "Error in Huffman-encoded string.")));
229
230 // 'y' ends in 0b0 on the most significant bit of the last byte.
231 // The remaining 7 bits must be a prefix of EOS, which is all 1s.
232 DecodeHeaderBlock(
233 QuicTextUtils::HexDecode("00002f0125a849e95ba97d7e8925a849e95bb8e8b4bf"));
234}
235
236TEST_P(QpackDecoderTest, HuffmanValueDoesNotHaveEOSPrefix) {
237 EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
238 "Error in Huffman-encoded string.")));
239
240 // 'e' ends in 0b101, taking up the 3 most significant bits of the last byte.
241 // The remaining 5 bits must be a prefix of EOS, which is all 1s.
242 DecodeHeaderBlock(
243 QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4be"));
244}
245
246TEST_P(QpackDecoderTest, HuffmanNameEOSPrefixTooLong) {
247 EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
248 "Error in Huffman-encoded string.")));
249
250 // The trailing EOS prefix must be at most 7 bits long. Appending one octet
251 // with value 0xff is invalid, even though 0b111111111111111 (15 bits) is a
252 // prefix of EOS.
253 DecodeHeaderBlock(QuicTextUtils::HexDecode(
254 "00002f0225a849e95ba97d7fff8925a849e95bb8e8b4bf"));
255}
256
257TEST_P(QpackDecoderTest, HuffmanValueEOSPrefixTooLong) {
258 EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
259 "Error in Huffman-encoded string.")));
260
261 // The trailing EOS prefix must be at most 7 bits long. Appending one octet
262 // with value 0xff is invalid, even though 0b1111111111111 (13 bits) is a
263 // prefix of EOS.
264 DecodeHeaderBlock(QuicTextUtils::HexDecode(
265 "00002f0125a849e95ba97d7f8a25a849e95bb8e8b4bfff"));
266}
267
268TEST_P(QpackDecoderTest, StaticTable) {
269 // A header name that has multiple entries with different values.
270 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
271 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("POST")));
272 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("TRACE")));
273
274 // A header name that has a single entry with non-empty value.
275 EXPECT_CALL(handler_,
276 OnHeaderDecoded(Eq("accept-encoding"), Eq("gzip, deflate, br")));
277 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("compress")));
278 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("")));
279
280 // A header name that has a single entry with empty value.
281 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("")));
282 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("foo")));
283
284 EXPECT_CALL(handler_, OnDecodingCompleted());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285
286 DecodeHeaderBlock(QuicTextUtils::HexDecode(
287 "0000d1dfccd45f108621e9aec2a11f5c8294e75f000554524143455f1000"));
288}
289
290TEST_P(QpackDecoderTest, TooHighStaticTableIndex) {
291 // This is the last entry in the static table with index 98.
292 EXPECT_CALL(handler_,
293 OnHeaderDecoded(Eq("x-frame-options"), Eq("sameorigin")));
294
295 // Addressing entry 99 should trigger an error.
296 EXPECT_CALL(handler_,
297 OnDecodingErrorDetected(Eq("Static table entry not found.")));
298
299 DecodeHeaderBlock(QuicTextUtils::HexDecode("0000ff23ff24"));
300}
301
302TEST_P(QpackDecoderTest, DynamicTable) {
303 DecodeEncoderStreamData(QuicTextUtils::HexDecode(
bnc40e9a7b2019-08-30 05:27:08 -0700304 "3fe107" // Set dynamic table capacity to 1024.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305 "6294e703626172" // Add literal entry with name "foo" and value "bar".
306 "80035a5a5a" // Add entry with name of dynamic table entry index 0
307 // (relative index) and value "ZZZ".
308 "cf8294e7" // Add entry with name of static table entry index 15
309 // and value "foo".
310 "01")); // Duplicate entry with relative index 1.
311
312 // Now there are four entries in the dynamic table.
313 // Entry 0: "foo", "bar"
314 // Entry 1: "foo", "ZZZ"
315 // Entry 2: ":method", "foo"
316 // Entry 3: "foo", "ZZZ"
317
318 // Use a Sequence to test that mock methods are called in order.
319 Sequence s;
320
321 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
322 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
323 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
324 .InSequence(s);
325 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
326 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
327 EXPECT_CALL(decoder_stream_sender_delegate_,
renjietangc2aa5cb2019-06-20 12:22:53 -0700328 WriteStreamData(Eq(kHeaderAcknowledgement)))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 .InSequence(s);
330 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
331
332 DecodeHeaderBlock(QuicTextUtils::HexDecode(
333 "0500" // Required Insert Count 4 and Delta Base 0.
334 // Base is 4 + 0 = 4.
335 "83" // Dynamic table entry with relative index 3, absolute index 0.
336 "82" // Dynamic table entry with relative index 2, absolute index 1.
337 "81" // Dynamic table entry with relative index 1, absolute index 2.
338 "80" // Dynamic table entry with relative index 0, absolute index 3.
339 "41025a5a")); // Name of entry 1 (relative index) from dynamic table,
340 // with value "ZZ".
341
342 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
343 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
344 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
345 .InSequence(s);
346 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
347 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
348 EXPECT_CALL(decoder_stream_sender_delegate_,
renjietangc2aa5cb2019-06-20 12:22:53 -0700349 WriteStreamData(Eq(kHeaderAcknowledgement)))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 .InSequence(s);
351 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
352
353 DecodeHeaderBlock(QuicTextUtils::HexDecode(
354 "0502" // Required Insert Count 4 and Delta Base 2.
355 // Base is 4 + 2 = 6.
356 "85" // Dynamic table entry with relative index 5, absolute index 0.
357 "84" // Dynamic table entry with relative index 4, absolute index 1.
358 "83" // Dynamic table entry with relative index 3, absolute index 2.
359 "82" // Dynamic table entry with relative index 2, absolute index 3.
360 "43025a5a")); // Name of entry 3 (relative index) from dynamic table,
361 // with value "ZZ".
362
363 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
364 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
365 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
366 .InSequence(s);
367 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
368 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
369 EXPECT_CALL(decoder_stream_sender_delegate_,
renjietangc2aa5cb2019-06-20 12:22:53 -0700370 WriteStreamData(Eq(kHeaderAcknowledgement)))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371 .InSequence(s);
372 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
373
374 DecodeHeaderBlock(QuicTextUtils::HexDecode(
375 "0582" // Required Insert Count 4 and Delta Base 2 with sign bit set.
376 // Base is 4 - 2 - 1 = 1.
377 "80" // Dynamic table entry with relative index 0, absolute index 0.
378 "10" // Dynamic table entry with post-base index 0, absolute index 1.
379 "11" // Dynamic table entry with post-base index 1, absolute index 2.
380 "12" // Dynamic table entry with post-base index 2, absolute index 3.
381 "01025a5a")); // Name of entry 1 (post-base index) from dynamic table,
382 // with value "ZZ".
383}
384
385TEST_P(QpackDecoderTest, DecreasingDynamicTableCapacityEvictsEntries) {
bnc40e9a7b2019-08-30 05:27:08 -0700386 // Set dynamic table capacity to 1024.
387 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500388 // Add literal entry with name "foo" and value "bar".
389 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
390
391 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
392 EXPECT_CALL(handler_, OnDecodingCompleted());
393 EXPECT_CALL(decoder_stream_sender_delegate_,
renjietangc2aa5cb2019-06-20 12:22:53 -0700394 WriteStreamData(Eq(kHeaderAcknowledgement)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500395
396 DecodeHeaderBlock(QuicTextUtils::HexDecode(
397 "0200" // Required Insert Count 1 and Delta Base 0.
398 // Base is 1 + 0 = 1.
399 "80")); // Dynamic table entry with relative index 0, absolute index 0.
400
401 // Change dynamic table capacity to 32 bytes, smaller than the entry.
402 // This must cause the entry to be evicted.
403 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f01"));
404
bnc098ff612019-07-09 03:24:37 -0700405 EXPECT_CALL(handler_, OnDecodingErrorDetected(
406 Eq("Dynamic table entry already evicted.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500407
408 DecodeHeaderBlock(QuicTextUtils::HexDecode(
409 "0200" // Required Insert Count 1 and Delta Base 0.
410 // Base is 1 + 0 = 1.
411 "80")); // Dynamic table entry with relative index 0, absolute index 0.
412}
413
414TEST_P(QpackDecoderTest, EncoderStreamErrorEntryTooLarge) {
415 EXPECT_CALL(encoder_stream_error_delegate_,
416 OnEncoderStreamError(Eq("Error inserting literal entry.")));
417
418 // Set dynamic table capacity to 34.
419 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f03"));
420 // Add literal entry with name "foo" and value "bar", size is 32 + 3 + 3 = 38.
421 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
422}
423
424TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) {
425 EXPECT_CALL(encoder_stream_error_delegate_,
426 OnEncoderStreamError(Eq("Invalid static table entry.")));
427
428 // Address invalid static table entry index 99.
429 DecodeEncoderStreamData(QuicTextUtils::HexDecode("ff2400"));
430}
431
432TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidDynamicTableEntry) {
433 EXPECT_CALL(encoder_stream_error_delegate_,
bncae04c652019-08-14 13:15:14 -0700434 OnEncoderStreamError(Eq("Invalid relative index.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435
436 DecodeEncoderStreamData(QuicTextUtils::HexDecode(
bnc40e9a7b2019-08-30 05:27:08 -0700437 "3fe107" // Set dynamic table capacity to 1024.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500438 "6294e703626172" // Add literal entry with name "foo" and value "bar".
439 "8100")); // Address dynamic table entry with relative index 1. Such
440 // entry does not exist. The most recently added and only
441 // dynamic table entry has relative index 0.
442}
443
444TEST_P(QpackDecoderTest, EncoderStreamErrorDuplicateInvalidEntry) {
445 EXPECT_CALL(encoder_stream_error_delegate_,
bncae04c652019-08-14 13:15:14 -0700446 OnEncoderStreamError(Eq("Invalid relative index.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500447
448 DecodeEncoderStreamData(QuicTextUtils::HexDecode(
bnc40e9a7b2019-08-30 05:27:08 -0700449 "3fe107" // Set dynamic table capacity to 1024.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500450 "6294e703626172" // Add literal entry with name "foo" and value "bar".
451 "01")); // Duplicate dynamic table entry with relative index 1. Such
452 // entry does not exist. The most recently added and only
453 // dynamic table entry has relative index 0.
454}
455
456TEST_P(QpackDecoderTest, EncoderStreamErrorTooLargeInteger) {
457 EXPECT_CALL(encoder_stream_error_delegate_,
458 OnEncoderStreamError(Eq("Encoded integer too large.")));
459
460 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
461}
462
463TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIsZero) {
464 EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
465
bnc40e9a7b2019-08-30 05:27:08 -0700466 // Set dynamic table capacity to 1024.
467 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
bnc098ff612019-07-09 03:24:37 -0700468 // Add literal entry with name "foo" and value "bar".
469 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
470
QUICHE teama6ef0a62019-03-07 20:34:33 -0500471 DecodeHeaderBlock(QuicTextUtils::HexDecode(
472 "0280" // Required Insert Count is 1. Base 1 - 1 - 0 = 0 is explicitly
473 // permitted by the spec.
474 "80")); // However, addressing entry with relative index 0 would point to
475 // absolute index -1, which is invalid.
476}
477
478TEST_P(QpackDecoderTest, InvalidNegativeBase) {
479 EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Error calculating Base.")));
480
481 // Required Insert Count 1, Delta Base 1 with sign bit set, Base would
482 // be 1 - 1 - 1 = -1, but it is not allowed to be negative.
483 DecodeHeaderBlock(QuicTextUtils::HexDecode("0281"));
484}
485
486TEST_P(QpackDecoderTest, InvalidDynamicEntryByRelativeIndex) {
bnc40e9a7b2019-08-30 05:27:08 -0700487 // Set dynamic table capacity to 1024.
488 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500489 // Add literal entry with name "foo" and value "bar".
490 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
491
bnc098ff612019-07-09 03:24:37 -0700492 EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
493
494 DecodeHeaderBlock(QuicTextUtils::HexDecode(
495 "0200" // Required Insert Count 1 and Delta Base 0.
496 // Base is 1 + 0 = 1.
497 "81")); // Indexed Header Field instruction addressing relative index 1.
498 // This is absolute index -1, which is invalid.
499
500 EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
501
502 DecodeHeaderBlock(QuicTextUtils::HexDecode(
503 "0200" // Required Insert Count 1 and Delta Base 0.
504 // Base is 1 + 0 = 1.
505 "4100")); // Literal Header Field with Name Reference instruction
506 // addressing relative index 1. This is absolute index -1,
507 // which is invalid.
508}
509
510TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
511 // Update dynamic table capacity to 128.
512 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
513
514 // Add literal entry with name "foo" and value "bar", size 32 + 3 + 3 = 38.
515 // This fits in the table three times.
516 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
517 // Duplicate entry four times. This evicts the first two instances.
518 DecodeEncoderStreamData(QuicTextUtils::HexDecode("00000000"));
519
520 EXPECT_CALL(handler_, OnDecodingErrorDetected(
521 Eq("Dynamic table entry already evicted.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500522
523 DecodeHeaderBlock(QuicTextUtils::HexDecode(
524 "0500" // Required Insert Count 4 and Delta Base 0.
525 // Base is 4 + 0 = 4.
526 "82")); // Indexed Header Field instruction addressing relative index 2.
527 // This is absolute index 1. Such entry does not exist.
528
bnc098ff612019-07-09 03:24:37 -0700529 EXPECT_CALL(handler_, OnDecodingErrorDetected(
530 Eq("Dynamic table entry already evicted.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500531
532 DecodeHeaderBlock(QuicTextUtils::HexDecode(
533 "0500" // Required Insert Count 4 and Delta Base 0.
534 // Base is 4 + 0 = 4.
535 "4200")); // Literal Header Field with Name Reference instruction
536 // addressing relative index 2. This is absolute index 1. Such
537 // entry does not exist.
538
bnc098ff612019-07-09 03:24:37 -0700539 EXPECT_CALL(handler_, OnDecodingErrorDetected(
540 Eq("Dynamic table entry already evicted.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500541
542 DecodeHeaderBlock(QuicTextUtils::HexDecode(
543 "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
544 // Base is 2 - 0 - 1 = 1
545 "10")); // Indexed Header Field instruction addressing dynamic table
546 // entry with post-base index 0, absolute index 1. Such entry
547 // does not exist.
548
bnc098ff612019-07-09 03:24:37 -0700549 EXPECT_CALL(handler_, OnDecodingErrorDetected(
550 Eq("Dynamic table entry already evicted.")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500551
552 DecodeHeaderBlock(QuicTextUtils::HexDecode(
553 "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
554 // Base is 2 - 0 - 1 = 1
555 "0000")); // Literal Header Field With Name Reference instruction
556 // addressing dynamic table entry with post-base index 0,
557 // absolute index 1. Such entry does not exist.
558}
559
560TEST_P(QpackDecoderTest, TableCapacityMustNotExceedMaximum) {
561 EXPECT_CALL(
562 encoder_stream_error_delegate_,
563 OnEncoderStreamError(Eq("Error updating dynamic table capacity.")));
564
565 // Try to update dynamic table capacity to 2048, which exceeds the maximum.
566 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe10f"));
567}
568
bnc4c664c52019-08-04 18:14:12 -0700569TEST_P(QpackDecoderTest, SetDynamicTableCapacity) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500570 // Update dynamic table capacity to 128, which does not exceed the maximum.
571 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
572}
573
574TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) {
575 // Maximum dynamic table capacity is 1024.
576 // MaxEntries is 1024 / 32 = 32.
577 // Required Insert Count is decoded modulo 2 * MaxEntries, that is, modulo 64.
578 // A value of 1 cannot be encoded as 65 even though it has the same remainder.
579 EXPECT_CALL(handler_, OnDecodingErrorDetected(
580 Eq("Error decoding Required Insert Count.")));
581 DecodeHeaderBlock(QuicTextUtils::HexDecode("4100"));
582}
583
bnc32e69f82019-06-14 06:38:36 -0700584// Regression test for https://crbug.com/970218: Decoder must stop processing
585// after a Header Block Prefix with an invalid Encoded Required Insert Count.
586TEST_P(QpackDecoderTest, DataAfterInvalidEncodedRequiredInsertCount) {
587 EXPECT_CALL(handler_, OnDecodingErrorDetected(
588 Eq("Error decoding Required Insert Count.")));
589 // Header Block Prefix followed by some extra data.
590 DecodeHeaderBlock(QuicTextUtils::HexDecode("410000"));
591}
592
QUICHE teama6ef0a62019-03-07 20:34:33 -0500593TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
594 // Maximum dynamic table capacity is 1024.
595 // MaxEntries is 1024 / 32 = 32.
596
bnc40e9a7b2019-08-30 05:27:08 -0700597 // Set dynamic table capacity to 1024.
598 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500599 // Add literal entry with name "foo" and a 600 byte long value. This will fit
600 // in the dynamic table once but not twice.
601 DecodeEncoderStreamData(
602 QuicTextUtils::HexDecode("6294e7" // Name "foo".
603 "7fd903")); // Value length 600.
vasilvvc48c8712019-03-11 13:38:16 -0700604 std::string header_value(600, 'Z');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500605 DecodeEncoderStreamData(header_value);
606
607 // Duplicate most recent entry 200 times.
vasilvvc48c8712019-03-11 13:38:16 -0700608 DecodeEncoderStreamData(std::string(200, '\x00'));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500609
610 // Now there is only one entry in the dynamic table, with absolute index 200.
611
612 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(header_value)));
613 EXPECT_CALL(handler_, OnDecodingCompleted());
614 EXPECT_CALL(decoder_stream_sender_delegate_,
renjietangc2aa5cb2019-06-20 12:22:53 -0700615 WriteStreamData(Eq(kHeaderAcknowledgement)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500616
617 // Send header block with Required Insert Count = 201.
618 DecodeHeaderBlock(QuicTextUtils::HexDecode(
619 "0a00" // Encoded Required Insert Count 10, Required Insert Count 201,
620 // Delta Base 0, Base 201.
621 "80")); // Emit dynamic table entry with relative index 0.
622}
623
624TEST_P(QpackDecoderTest, NonZeroRequiredInsertCountButNoDynamicEntries) {
bnc40e9a7b2019-08-30 05:27:08 -0700625 // Set dynamic table capacity to 1024.
626 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
bnc098ff612019-07-09 03:24:37 -0700627 // Add literal entry with name "foo" and value "bar".
628 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
629
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
631 EXPECT_CALL(handler_,
632 OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
633
634 DecodeHeaderBlock(QuicTextUtils::HexDecode(
635 "0200" // Required Insert Count is 1.
636 "d1")); // But the only instruction references the static table.
637}
638
639TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
bnc40e9a7b2019-08-30 05:27:08 -0700640 // Set dynamic table capacity to 1024.
641 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
bnc098ff612019-07-09 03:24:37 -0700642 // Add literal entry with name "foo" and value "bar".
643 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
644
QUICHE teama6ef0a62019-03-07 20:34:33 -0500645 EXPECT_CALL(
646 handler_,
647 OnDecodingErrorDetected(
648 Eq("Absolute Index must be smaller than Required Insert Count.")));
649
650 DecodeHeaderBlock(QuicTextUtils::HexDecode(
651 "0201" // Required Insert Count 1 and Delta Base 1.
652 // Base is 1 + 1 = 2.
653 "80")); // Indexed Header Field instruction addressing dynamic table
654 // entry with relative index 0, absolute index 1. This is not
655 // allowed by Required Insert Count.
656
657 EXPECT_CALL(
658 handler_,
659 OnDecodingErrorDetected(
660 Eq("Absolute Index must be smaller than Required Insert Count.")));
661
662 DecodeHeaderBlock(QuicTextUtils::HexDecode(
663 "0201" // Required Insert Count 1 and Delta Base 1.
664 // Base is 1 + 1 = 2.
665 "4000")); // Literal Header Field with Name Reference instruction
666 // addressing dynamic table entry with relative index 0,
667 // absolute index 1. This is not allowed by Required Index
668 // Count.
669
670 EXPECT_CALL(
671 handler_,
672 OnDecodingErrorDetected(
673 Eq("Absolute Index must be smaller than Required Insert Count.")));
674
675 DecodeHeaderBlock(QuicTextUtils::HexDecode(
676 "0200" // Required Insert Count 1 and Delta Base 0.
677 // Base is 1 + 0 = 1.
678 "10")); // Indexed Header Field with Post-Base Index instruction
679 // addressing dynamic table entry with post-base index 0,
680 // absolute index 1. This is not allowed by Required Insert
681 // Count.
682
683 EXPECT_CALL(
684 handler_,
685 OnDecodingErrorDetected(
686 Eq("Absolute Index must be smaller than Required Insert Count.")));
687
688 DecodeHeaderBlock(QuicTextUtils::HexDecode(
689 "0200" // Required Insert Count 1 and Delta Base 0.
690 // Base is 1 + 0 = 1.
691 "0000")); // Literal Header Field with Post-Base Name Reference
692 // instruction addressing dynamic table entry with post-base
693 // index 0, absolute index 1. This is not allowed by Required
694 // Index Count.
695}
696
697TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
bnc40e9a7b2019-08-30 05:27:08 -0700698 // Set dynamic table capacity to 1024.
699 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500700 // Add literal entry with name "foo" and value "bar".
701 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
bnc098ff612019-07-09 03:24:37 -0700702 // Duplicate entry twice so that decoding of header blocks with Required
703 // Insert Count not exceeding 3 is not blocked.
704 DecodeEncoderStreamData(QuicTextUtils::HexDecode("00"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500705 DecodeEncoderStreamData(QuicTextUtils::HexDecode("00"));
706
707 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
708 EXPECT_CALL(handler_,
709 OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
710
711 DecodeHeaderBlock(QuicTextUtils::HexDecode(
712 "0300" // Required Insert Count 2 and Delta Base 0.
713 // Base is 2 + 0 = 2.
714 "81")); // Indexed Header Field instruction addressing dynamic table
715 // entry with relative index 1, absolute index 0. Header block
716 // requires insert count of 1, even though Required Insert Count
717 // is 2.
718
719 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
720 EXPECT_CALL(handler_,
721 OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
722
723 DecodeHeaderBlock(QuicTextUtils::HexDecode(
724 "0300" // Required Insert Count 2 and Delta Base 0.
725 // Base is 2 + 0 = 2.
726 "4100")); // Literal Header Field with Name Reference instruction
727 // addressing dynamic table entry with relative index 1,
728 // absolute index 0. Header block requires insert count of 1,
729 // even though Required Insert Count is 2.
730
731 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
732 EXPECT_CALL(handler_,
733 OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
734
735 DecodeHeaderBlock(QuicTextUtils::HexDecode(
736 "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
737 // Base is 3 - 1 - 1 = 1.
738 "10")); // Indexed Header Field with Post-Base Index instruction
739 // addressing dynamic table entry with post-base index 0,
740 // absolute index 1. Header block requires insert count of 2,
741 // even though Required Insert Count is 3.
742
743 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
744 EXPECT_CALL(handler_,
745 OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
746
747 DecodeHeaderBlock(QuicTextUtils::HexDecode(
748 "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
749 // Base is 3 - 1 - 1 = 1.
750 "0000")); // Literal Header Field with Post-Base Name Reference
751 // instruction addressing dynamic table entry with post-base
752 // index 0, absolute index 1. Header block requires insert
753 // count of 2, even though Required Insert Count is 3.
754}
755
bnc098ff612019-07-09 03:24:37 -0700756TEST_P(QpackDecoderTest, BlockedDecoding) {
757 DecodeHeaderBlock(QuicTextUtils::HexDecode(
758 "0200" // Required Insert Count 1 and Delta Base 0.
759 // Base is 1 + 0 = 1.
760 "80")); // Indexed Header Field instruction addressing dynamic table
761 // entry with relative index 0, absolute index 0.
762
763 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
764 EXPECT_CALL(handler_, OnDecodingCompleted());
765 EXPECT_CALL(decoder_stream_sender_delegate_,
766 WriteStreamData(Eq(kHeaderAcknowledgement)));
767
bnc40e9a7b2019-08-30 05:27:08 -0700768 // Set dynamic table capacity to 1024.
769 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
bnc098ff612019-07-09 03:24:37 -0700770 // Add literal entry with name "foo" and value "bar".
771 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
772}
773
774TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
775 StartDecoding();
776 DecodeData(QuicTextUtils::HexDecode(
777 "0200" // Required Insert Count 1 and Delta Base 0.
778 // Base is 1 + 0 = 1.
779 "80" // Indexed Header Field instruction addressing dynamic table
780 // entry with relative index 0, absolute index 0.
781 "d1")); // Static table entry with index 17.
782
783 // Add literal entry with name "foo" and value "bar". Decoding is now
784 // unblocked because dynamic table Insert Count reached the Required Insert
785 // Count of the header block. |handler_| methods are called immediately for
786 // the already consumed part of the header block.
787 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
788 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
bnc40e9a7b2019-08-30 05:27:08 -0700789
790 // Set dynamic table capacity to 1024.
791 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
792 // Add literal entry with name "foo" and value "bar".
bnc098ff612019-07-09 03:24:37 -0700793 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
794 Mock::VerifyAndClearExpectations(&handler_);
795
796 // Rest of header block is processed by QpackProgressiveDecoder
797 // in the unblocked state.
798 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
799 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":scheme"), Eq("https")));
800 DecodeData(QuicTextUtils::HexDecode(
801 "80" // Indexed Header Field instruction addressing dynamic table
802 // entry with relative index 0, absolute index 0.
803 "d7")); // Static table entry with index 23.
804 Mock::VerifyAndClearExpectations(&handler_);
805
806 EXPECT_CALL(handler_, OnDecodingCompleted());
807 EXPECT_CALL(decoder_stream_sender_delegate_,
808 WriteStreamData(Eq(kHeaderAcknowledgement)));
809 EndDecoding();
810}
811
812// Make sure that Required Insert Count is compared to Insert Count,
813// not size of dynamic table.
814TEST_P(QpackDecoderTest, BlockedDecodingAndEvictedEntries) {
815 // Update dynamic table capacity to 128.
816 // At most three non-empty entries fit in the dynamic table.
817 DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
818
819 StartDecoding();
820 DecodeHeaderBlock(QuicTextUtils::HexDecode(
821 "0700" // Required Insert Count 6 and Delta Base 0.
822 // Base is 6 + 0 = 6.
823 "80")); // Indexed Header Field instruction addressing dynamic table
824 // entry with relative index 0, absolute index 5.
825
826 // Add literal entry with name "foo" and value "bar".
827 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
828
829 // Duplicate entry four times. This evicts the first two instances.
830 DecodeEncoderStreamData(QuicTextUtils::HexDecode("00000000"));
831
832 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("baz")));
833 EXPECT_CALL(handler_, OnDecodingCompleted());
834 EXPECT_CALL(decoder_stream_sender_delegate_,
835 WriteStreamData(Eq(kHeaderAcknowledgement)));
836
837 // Add literal entry with name "foo" and value "bar".
838 // Insert Count is now 6, reaching Required Insert Count of the header block.
839 DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e70362617a"));
840}
841
bnc57b5f622019-08-21 14:07:44 -0700842TEST_P(QpackDecoderTest, TooManyBlockedStreams) {
843 // Required Insert Count 1 and Delta Base 0.
844 // Without any dynamic table entries received, decoding is blocked.
845 std::string data = QuicTextUtils::HexDecode("0200");
846
847 auto progressive_decoder1 = CreateProgressiveDecoder(/* stream_id = */ 1);
848 progressive_decoder1->Decode(data);
849
850 EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq(
851 "Limit on number of blocked streams exceeded.")));
852
853 auto progressive_decoder2 = CreateProgressiveDecoder(/* stream_id = */ 2);
854 progressive_decoder2->Decode(data);
855}
856
QUICHE teama6ef0a62019-03-07 20:34:33 -0500857} // namespace
858} // namespace test
859} // namespace quic