Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / spdy / hpack_decoder_test.cc
1 // Copyright 2014 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/spdy/hpack_decoder.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/basictypes.h"
11 #include "base/logging.h"
12 #include "base/strings/string_piece.h"
13 #include "net/spdy/hpack_encoder.h"
14 #include "net/spdy/hpack_input_stream.h"
15 #include "net/spdy/hpack_output_stream.h"
16 #include "net/spdy/spdy_test_utils.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace net {
21
22 namespace test {
23
24 using base::StringPiece;
25 using std::string;
26
27 class HpackDecoderPeer {
28  public:
29   explicit HpackDecoderPeer(HpackDecoder* decoder)
30       : decoder_(decoder) {}
31
32   void HandleHeaderRepresentation(StringPiece name, StringPiece value) {
33     decoder_->HandleHeaderRepresentation(name, value);
34   }
35   bool DecodeNextName(HpackInputStream* in, StringPiece* out) {
36     return decoder_->DecodeNextName(in, out);
37   }
38   HpackHeaderTable* header_table() {
39     return &decoder_->header_table_;
40   }
41   void set_cookie_value(string value) {
42     decoder_->cookie_value_ = value;
43   }
44   string cookie_value() {
45     return decoder_->cookie_value_;
46   }
47   const std::map<string, string>& decoded_block() const {
48     return decoder_->decoded_block_;
49   }
50   const string& headers_block_buffer() const {
51     return decoder_->headers_block_buffer_;
52   }
53
54  private:
55   HpackDecoder* decoder_;
56 };
57
58 }  // namespace test
59
60 namespace {
61
62 using base::StringPiece;
63 using std::string;
64 using test::a2b_hex;
65
66 using testing::ElementsAre;
67 using testing::Pair;
68
69 const size_t kLiteralBound = 1024;
70
71 class HpackDecoderTest : public ::testing::Test {
72  protected:
73   HpackDecoderTest()
74       : decoder_(ObtainHpackHuffmanTable()),
75         decoder_peer_(&decoder_) {}
76
77   bool DecodeHeaderBlock(StringPiece str) {
78     return decoder_.HandleControlFrameHeadersData(0, str.data(), str.size()) &&
79         decoder_.HandleControlFrameHeadersComplete(0);
80   }
81
82   const std::map<string, string>& decoded_block() const {
83     // TODO(jgraettinger): HpackDecoderTest should implement
84     // SpdyHeadersHandlerInterface, and collect headers for examination.
85     return decoder_peer_.decoded_block();
86   }
87
88   const std::map<string, string>& DecodeBlockExpectingSuccess(StringPiece str) {
89     EXPECT_TRUE(DecodeHeaderBlock(str));
90     return decoded_block();
91   }
92
93   void expectEntry(size_t index, size_t size, const string& name,
94                    const string& value) {
95     const HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index);
96     EXPECT_EQ(name, entry->name()) << "index " << index;
97     EXPECT_EQ(value, entry->value());
98     EXPECT_EQ(size, entry->Size());
99     EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry));
100   }
101
102   HpackDecoder decoder_;
103   test::HpackDecoderPeer decoder_peer_;
104 };
105
106 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) {
107   // Strings under threshold are concatenated in the buffer.
108   EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(
109       0, "small string one", 16));
110   EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(
111       0, "small string two", 16));
112   // A string which would push the buffer over the threshold is refused.
113   EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(
114       0, "fails", kMaxDecodeBufferSize - 32 + 1));
115
116   EXPECT_EQ(decoder_peer_.headers_block_buffer(),
117             "small string onesmall string two");
118 }
119
120 TEST_F(HpackDecoderTest, HandleControlFrameHeadersComplete) {
121   decoder_peer_.set_cookie_value("foobar=baz");
122
123   // Incremental cookie buffer should be emitted and cleared.
124   decoder_.HandleControlFrameHeadersData(0, "\x82\x85", 2);
125   decoder_.HandleControlFrameHeadersComplete(0);
126
127   EXPECT_THAT(decoded_block(), ElementsAre(
128       Pair(":method", "GET"),
129       Pair(":path", "/index.html"),
130       Pair("cookie", "foobar=baz")));
131   EXPECT_EQ(decoder_peer_.cookie_value(), "");
132 }
133
134 TEST_F(HpackDecoderTest, HandleHeaderRepresentation) {
135   // All cookie crumbs are joined.
136   decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
137   decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
138   decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
139
140   // Already-delimited headers are passed through.
141   decoder_peer_.HandleHeaderRepresentation("passed-through",
142                                            string("foo\0baz", 7));
143
144   // Other headers are joined on \0. Case matters.
145   decoder_peer_.HandleHeaderRepresentation("joined", "not joined");
146   decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
147   decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
148
149   // Empty headers remain empty.
150   decoder_peer_.HandleHeaderRepresentation("empty", "");
151
152   // Joined empty headers work as expected.
153   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
154   decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
155   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
156   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
157
158   // Non-contiguous cookie crumb.
159   decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
160
161   // Finish and emit all headers.
162   decoder_.HandleControlFrameHeadersComplete(0);
163
164   EXPECT_THAT(decoded_block(), ElementsAre(
165       Pair("cookie", " part 1; part 2 ; part3;  fin!"),
166       Pair("empty", ""),
167       Pair("empty-joined", string("\0foo\0\0", 6)),
168       Pair("joineD", string("value 1\0value 2", 15)),
169       Pair("joined", "not joined"),
170       Pair("passed-through", string("foo\0baz", 7))));
171 }
172
173 // Decoding an encoded name with a valid string literal should work.
174 TEST_F(HpackDecoderTest, DecodeNextNameLiteral) {
175   HpackInputStream input_stream(kLiteralBound, StringPiece("\x00\x04name", 6));
176
177   StringPiece string_piece;
178   EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
179   EXPECT_EQ("name", string_piece);
180   EXPECT_FALSE(input_stream.HasMoreData());
181 }
182
183 TEST_F(HpackDecoderTest, DecodeNextNameLiteralWithHuffmanEncoding) {
184   string input = a2b_hex("008825a849e95ba97d7f");
185   HpackInputStream input_stream(kLiteralBound, input);
186
187   StringPiece string_piece;
188   EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
189   EXPECT_EQ("custom-key", string_piece);
190   EXPECT_FALSE(input_stream.HasMoreData());
191 }
192
193 // Decoding an encoded name with a valid index should work.
194 TEST_F(HpackDecoderTest, DecodeNextNameIndexed) {
195   HpackInputStream input_stream(kLiteralBound, "\x01");
196
197   StringPiece string_piece;
198   EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
199   EXPECT_EQ(":authority", string_piece);
200   EXPECT_FALSE(input_stream.HasMoreData());
201 }
202
203 // Decoding an encoded name with an invalid index should fail.
204 TEST_F(HpackDecoderTest, DecodeNextNameInvalidIndex) {
205   // One more than the number of static table entries.
206   HpackInputStream input_stream(kLiteralBound, "\x3e");
207
208   StringPiece string_piece;
209   EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
210 }
211
212 // Decoding indexed static table field should work.
213 TEST_F(HpackDecoderTest, IndexedHeaderStatic) {
214   // Reference static table entries #2 and #5.
215   std::map<string, string> header_set1 =
216       DecodeBlockExpectingSuccess("\x82\x85");
217   std::map<string, string> expected_header_set1;
218   expected_header_set1[":method"] = "GET";
219   expected_header_set1[":path"] = "/index.html";
220   EXPECT_EQ(expected_header_set1, header_set1);
221
222   // Reference static table entry #2.
223   std::map<string, string> header_set2 =
224       DecodeBlockExpectingSuccess("\x82");
225   std::map<string, string> expected_header_set2;
226   expected_header_set2[":method"] = "GET";
227   EXPECT_EQ(expected_header_set2, header_set2);
228 }
229
230 TEST_F(HpackDecoderTest, IndexedHeaderDynamic) {
231   // First header block: add an entry to header table.
232   std::map<string, string> header_set1 =
233       DecodeBlockExpectingSuccess("\x40\x03" "foo" "\x03" "bar");
234   std::map<string, string> expected_header_set1;
235   expected_header_set1["foo"] = "bar";
236   EXPECT_EQ(expected_header_set1, header_set1);
237
238   // Second header block: add another entry to header table.
239   std::map<string, string> header_set2 =
240       DecodeBlockExpectingSuccess("\xbe\x40\x04" "spam" "\x04" "eggs");
241   std::map<string, string> expected_header_set2;
242   expected_header_set2["foo"] = "bar";
243   expected_header_set2["spam"] = "eggs";
244   EXPECT_EQ(expected_header_set2, header_set2);
245
246   // Third header block: refer to most recently added entry.
247   std::map<string, string> header_set3 =
248       DecodeBlockExpectingSuccess("\xbe");
249   std::map<string, string> expected_header_set3;
250   expected_header_set3["spam"] = "eggs";
251   EXPECT_EQ(expected_header_set3, header_set3);
252 }
253
254 // Test a too-large indexed header.
255 TEST_F(HpackDecoderTest, InvalidIndexedHeader) {
256   // High-bit set, and a prefix of one more than the number of static entries.
257   EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1)));
258 }
259
260 // Test that a header block with a pseudo-header field following a regular one
261 // is treated as malformed.  (HTTP2 draft-14 8.1.2.1., HPACK draft-09 3.1.)
262
263 TEST_F(HpackDecoderTest, InvalidPseudoHeaderPositionStatic) {
264   // Okay: ":path" (static entry 4) followed by "allow" (static entry 20).
265   EXPECT_TRUE(DecodeHeaderBlock(a2b_hex("8494")));
266   // Malformed: "allow" (static entry 20) followed by ":path" (static entry 4).
267   EXPECT_FALSE(DecodeHeaderBlock(a2b_hex("9484")));
268 }
269
270 TEST_F(HpackDecoderTest, InvalidPseudoHeaderPositionLiteral) {
271   // Okay: literal ":bar" followed by literal "foo".
272   EXPECT_TRUE(DecodeHeaderBlock(a2b_hex("40043a626172004003666f6f00")));
273   // Malformed: literal "foo" followed by literal ":bar".
274   EXPECT_FALSE(DecodeHeaderBlock(a2b_hex("4003666f6f0040043a62617200")));
275 }
276
277 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) {
278   EXPECT_EQ(kDefaultHeaderTableSizeSetting,
279             decoder_peer_.header_table()->max_size());
280   string input;
281   {
282     // Maximum-size update with size 126. Succeeds.
283     HpackOutputStream output_stream;
284     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
285     output_stream.AppendUint32(126);
286
287     output_stream.TakeString(&input);
288     EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
289     EXPECT_EQ(126u, decoder_peer_.header_table()->max_size());
290   }
291   {
292     // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
293     HpackOutputStream output_stream;
294     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
295     output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
296
297     output_stream.TakeString(&input);
298     EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
299     EXPECT_EQ(kDefaultHeaderTableSizeSetting,
300               decoder_peer_.header_table()->max_size());
301   }
302   {
303     // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
304     HpackOutputStream output_stream;
305     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
306     output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
307
308     output_stream.TakeString(&input);
309     EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
310     EXPECT_EQ(kDefaultHeaderTableSizeSetting,
311               decoder_peer_.header_table()->max_size());
312   }
313 }
314
315 // Decoding two valid encoded literal headers with no indexing should
316 // work.
317 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) {
318   // First header with indexed name, second header with string literal
319   // name.
320   const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
321   std::map<string, string> header_set =
322       DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
323
324   std::map<string, string> expected_header_set;
325   expected_header_set[":path"] = "/sample/path";
326   expected_header_set[":path2"] = "/sample/path/2";
327   EXPECT_EQ(expected_header_set, header_set);
328 }
329
330 // Decoding two valid encoded literal headers with incremental
331 // indexing and string literal names should work.
332 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) {
333   const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
334   std::map<string, string> header_set =
335       DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
336
337   std::map<string, string> expected_header_set;
338   expected_header_set[":path"] = "/sample/path";
339   expected_header_set[":path2"] = "/sample/path/2";
340   EXPECT_EQ(expected_header_set, header_set);
341 }
342
343 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) {
344   decoder_.ApplyHeaderTableSizeSetting(0);
345
346   // Name is the last static index. Works.
347   EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo")));
348   // Name is one beyond the last static index. Fails.
349   EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo")));
350 }
351
352 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexingInvalidNameIndex) {
353   // Name is the last static index. Works.
354   EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x0f\x2e\x03ooo")));
355   // Name is one beyond the last static index. Fails.
356   EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x0f\x2f\x03ooo")));
357 }
358
359 TEST_F(HpackDecoderTest, LiteralHeaderNeverIndexedInvalidNameIndex) {
360   // Name is the last static index. Works.
361   EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x1f\x2e\x03ooo")));
362   // Name is one beyond the last static index. Fails.
363   EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x1f\x2f\x03ooo")));
364 }
365
366 // Round-tripping the header set from E.2.1 should work.
367 TEST_F(HpackDecoderTest, BasicE21) {
368   HpackEncoder encoder(ObtainHpackHuffmanTable());
369
370   std::map<string, string> expected_header_set;
371   expected_header_set[":method"] = "GET";
372   expected_header_set[":scheme"] = "http";
373   expected_header_set[":path"] = "/";
374   expected_header_set[":authority"] = "www.example.com";
375
376   string encoded_header_set;
377   EXPECT_TRUE(encoder.EncodeHeaderSet(
378       expected_header_set, &encoded_header_set));
379
380   EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set));
381   EXPECT_EQ(expected_header_set, decoded_block());
382 }
383
384 TEST_F(HpackDecoderTest, SectionD4RequestHuffmanExamples) {
385   std::map<string, string> header_set;
386
387   // 82                                      | == Indexed - Add ==
388   //                                         |   idx = 2
389   //                                         | -> :method: GET
390   // 86                                      | == Indexed - Add ==
391   //                                         |   idx = 6
392   //                                         | -> :scheme: http
393   // 84                                      | == Indexed - Add ==
394   //                                         |   idx = 4
395   //                                         | -> :path: /
396   // 41                                      | == Literal indexed ==
397   //                                         |   Indexed name (idx = 1)
398   //                                         |     :authority
399   // 8c                                      |   Literal value (len = 15)
400   //                                         |     Huffman encoded:
401   // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
402   //                                         |     Decoded:
403   //                                         | www.example.com
404   //                                         | -> :authority: www.example.com
405   string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4"
406                          "ff");
407   header_set = DecodeBlockExpectingSuccess(first);
408
409   EXPECT_THAT(header_set, ElementsAre(
410       Pair(":authority", "www.example.com"),
411       Pair(":method", "GET"),
412       Pair(":path", "/"),
413       Pair(":scheme", "http")));
414
415   expectEntry(62, 57, ":authority", "www.example.com");
416   EXPECT_EQ(57u, decoder_peer_.header_table()->size());
417
418   // 82                                      | == Indexed - Add ==
419   //                                         |   idx = 2
420   //                                         | -> :method: GET
421   // 86                                      | == Indexed - Add ==
422   //                                         |   idx = 6
423   //                                         | -> :scheme: http
424   // 84                                      | == Indexed - Add ==
425   //                                         |   idx = 4
426   //                                         | -> :path: /
427   // be                                      | == Indexed - Add ==
428   //                                         |   idx = 62
429   //                                         | -> :authority: www.example.com
430   // 58                                      | == Literal indexed ==
431   //                                         |   Indexed name (idx = 24)
432   //                                         |     cache-control
433   // 86                                      |   Literal value (len = 8)
434   //                                         |     Huffman encoded:
435   // a8eb 1064 9cbf                          | ...d..
436   //                                         |     Decoded:
437   //                                         | no-cache
438   //                                         | -> cache-control: no-cache
439
440   string second = a2b_hex("828684be5886a8eb10649cbf");
441   header_set = DecodeBlockExpectingSuccess(second);
442
443   EXPECT_THAT(header_set, ElementsAre(
444       Pair(":authority", "www.example.com"),
445       Pair(":method", "GET"),
446       Pair(":path", "/"),
447       Pair(":scheme", "http"),
448       Pair("cache-control", "no-cache")));
449
450   expectEntry(62, 53, "cache-control", "no-cache");
451   expectEntry(63, 57, ":authority", "www.example.com");
452   EXPECT_EQ(110u, decoder_peer_.header_table()->size());
453
454   // 82                                      | == Indexed - Add ==
455   //                                         |   idx = 2
456   //                                         | -> :method: GET
457   // 87                                      | == Indexed - Add ==
458   //                                         |   idx = 7
459   //                                         | -> :scheme: https
460   // 85                                      | == Indexed - Add ==
461   //                                         |   idx = 5
462   //                                         | -> :path: /index.html
463   // bf                                      | == Indexed - Add ==
464   //                                         |   idx = 63
465   //                                         | -> :authority: www.example.com
466   // 40                                      | == Literal indexed ==
467   // 88                                      |   Literal name (len = 10)
468   //                                         |     Huffman encoded:
469   // 25a8 49e9 5ba9 7d7f                     | %.I.[.}.
470   //                                         |     Decoded:
471   //                                         | custom-key
472   // 89                                      |   Literal value (len = 12)
473   //                                         |     Huffman encoded:
474   // 25a8 49e9 5bb8 e8b4 bf                  | %.I.[....
475   //                                         |     Decoded:
476   //                                         | custom-value
477   //                                         | -> custom-key: custom-value
478   string third = a2b_hex("828785bf408825a849e95ba97d7f89"
479                          "25a849e95bb8e8b4bf");
480   header_set = DecodeBlockExpectingSuccess(third);
481
482   EXPECT_THAT(header_set, ElementsAre(
483       Pair(":authority", "www.example.com"),
484       Pair(":method", "GET"),
485       Pair(":path", "/index.html"),
486       Pair(":scheme", "https"),
487       Pair("custom-key", "custom-value")));
488
489   expectEntry(62, 54, "custom-key", "custom-value");
490   expectEntry(63, 53, "cache-control", "no-cache");
491   expectEntry(64, 57, ":authority", "www.example.com");
492   EXPECT_EQ(164u, decoder_peer_.header_table()->size());
493 }
494
495 TEST_F(HpackDecoderTest, SectionD6ResponseHuffmanExamples) {
496   std::map<string, string> header_set;
497   decoder_.ApplyHeaderTableSizeSetting(256);
498
499   // 48                                      | == Literal indexed ==
500   //                                         |   Indexed name (idx = 8)
501   //                                         |     :status
502   // 82                                      |   Literal value (len = 3)
503   //                                         |     Huffman encoded:
504   // 6402                                    | d.
505   //                                         |     Decoded:
506   //                                         | 302
507   //                                         | -> :status: 302
508   // 58                                      | == Literal indexed ==
509   //                                         |   Indexed name (idx = 24)
510   //                                         |     cache-control
511   // 85                                      |   Literal value (len = 7)
512   //                                         |     Huffman encoded:
513   // aec3 771a 4b                            | ..w.K
514   //                                         |     Decoded:
515   //                                         | private
516   //                                         | -> cache-control: private
517   // 61                                      | == Literal indexed ==
518   //                                         |   Indexed name (idx = 33)
519   //                                         |     date
520   // 96                                      |   Literal value (len = 29)
521   //                                         |     Huffman encoded:
522   // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
523   // e082 a62d 1bff                          | ...-..
524   //                                         |     Decoded:
525   //                                         | Mon, 21 Oct 2013 20:13:21
526   //                                         | GMT
527   //                                         | -> date: Mon, 21 Oct 2013
528   //                                         |   20:13:21 GMT
529   // 6e                                      | == Literal indexed ==
530   //                                         |   Indexed name (idx = 46)
531   //                                         |     location
532   // 91                                      |   Literal value (len = 23)
533   //                                         |     Huffman encoded:
534   // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
535   // d3                                      | .
536   //                                         |     Decoded:
537   //                                         | https://www.example.com
538   //                                         | -> location: https://www.e
539   //                                         |    xample.com
540
541   string first = a2b_hex("488264025885aec3771a4b6196d07abe"
542                          "941054d444a8200595040b8166e082a6"
543                          "2d1bff6e919d29ad171863c78f0b97c8"
544                          "e9ae82ae43d3");
545   header_set = DecodeBlockExpectingSuccess(first);
546
547   EXPECT_THAT(header_set, ElementsAre(
548       Pair(":status", "302"),
549       Pair("cache-control", "private"),
550       Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
551       Pair("location", "https://www.example.com")));
552
553   expectEntry(62, 63, "location", "https://www.example.com");
554   expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
555   expectEntry(64, 52, "cache-control", "private");
556   expectEntry(65, 42, ":status", "302");
557   EXPECT_EQ(222u, decoder_peer_.header_table()->size());
558
559   // 48                                      | == Literal indexed ==
560   //                                         |   Indexed name (idx = 8)
561   //                                         |     :status
562   // 83                                      |   Literal value (len = 3)
563   //                                         |     Huffman encoded:
564   // 640e ff                                 | d..
565   //                                         |     Decoded:
566   //                                         | 307
567   //                                         | - evict: :status: 302
568   //                                         | -> :status: 307
569   // c1                                      | == Indexed - Add ==
570   //                                         |   idx = 65
571   //                                         | -> cache-control: private
572   // c0                                      | == Indexed - Add ==
573   //                                         |   idx = 64
574   //                                         | -> date: Mon, 21 Oct 2013
575   //                                         |   20:13:21 GMT
576   // bf                                      | == Indexed - Add ==
577   //                                         |   idx = 63
578   //                                         | -> location:
579   //                                         |   https://www.example.com
580   string second = a2b_hex("4883640effc1c0bf");
581   header_set = DecodeBlockExpectingSuccess(second);
582
583   EXPECT_THAT(header_set, ElementsAre(
584       Pair(":status", "307"),
585       Pair("cache-control", "private"),
586       Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
587       Pair("location", "https://www.example.com")));
588
589   expectEntry(62, 42, ":status", "307");
590   expectEntry(63, 63, "location", "https://www.example.com");
591   expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
592   expectEntry(65, 52, "cache-control", "private");
593   EXPECT_EQ(222u, decoder_peer_.header_table()->size());
594
595   // 88                                      | == Indexed - Add ==
596   //                                         |   idx = 8
597   //                                         | -> :status: 200
598   // c1                                      | == Indexed - Add ==
599   //                                         |   idx = 65
600   //                                         | -> cache-control: private
601   // 61                                      | == Literal indexed ==
602   //                                         |   Indexed name (idx = 33)
603   //                                         |     date
604   // 96                                      |   Literal value (len = 22)
605   //                                         |     Huffman encoded:
606   // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
607   // e084 a62d 1bff                          | ...-..
608   //                                         |     Decoded:
609   //                                         | Mon, 21 Oct 2013 20:13:22
610   //                                         | GMT
611   //                                         | - evict: cache-control:
612   //                                         |   private
613   //                                         | -> date: Mon, 21 Oct 2013
614   //                                         |   20:13:22 GMT
615   // c0                                      | == Indexed - Add ==
616   //                                         |   idx = 64
617   //                                         | -> location:
618   //                                         |    https://www.example.com
619   // 5a                                      | == Literal indexed ==
620   //                                         |   Indexed name (idx = 26)
621   //                                         |     content-encoding
622   // 83                                      |   Literal value (len = 3)
623   //                                         |     Huffman encoded:
624   // 9bd9 ab                                 | ...
625   //                                         |     Decoded:
626   //                                         | gzip
627   //                                         | - evict: date: Mon, 21 Oct
628   //                                         |    2013 20:13:21 GMT
629   //                                         | -> content-encoding: gzip
630   // 77                                      | == Literal indexed ==
631   //                                         |   Indexed name (idx = 55)
632   //                                         |     set-cookie
633   // ad                                      |   Literal value (len = 45)
634   //                                         |     Huffman encoded:
635   // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
636   // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
637   // 3160 65c0 03ed 4ee5 b106 3d50 07        | 1`e...N...=P.
638   //                                         |     Decoded:
639   //                                         | foo=ASDJKHQKBZXOQWEOPIUAXQ
640   //                                         | WEOIU; max-age=3600; versi
641   //                                         | on=1
642   //                                         | - evict: location:
643   //                                         |   https://www.example.com
644   //                                         | - evict: :status: 307
645   //                                         | -> set-cookie: foo=ASDJKHQ
646   //                                         |   KBZXOQWEOPIUAXQWEOIU;
647   //                                         |   max-age=3600; version=1
648   string third = a2b_hex("88c16196d07abe941054d444a8200595"
649                          "040b8166e084a62d1bffc05a839bd9ab"
650                          "77ad94e7821dd7f2e6c7b335dfdfcd5b"
651                          "3960d5af27087f3672c1ab270fb5291f"
652                          "9587316065c003ed4ee5b1063d5007");
653   header_set = DecodeBlockExpectingSuccess(third);
654
655   EXPECT_THAT(header_set, ElementsAre(
656       Pair(":status", "200"),
657       Pair("cache-control", "private"),
658       Pair("content-encoding", "gzip"),
659       Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
660       Pair("location", "https://www.example.com"),
661       Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
662            " max-age=3600; version=1")));
663
664   expectEntry(62, 98, "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
665               " max-age=3600; version=1");
666   expectEntry(63, 52, "content-encoding", "gzip");
667   expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
668   EXPECT_EQ(215u, decoder_peer_.header_table()->size());
669 }
670
671 }  // namespace
672
673 }  // namespace net