Home | History | Annotate | Download | only in spdy
      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
    674