• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 "quiche/http2/hpack/huffman/hpack_huffman_encoder.h"
6 
7 #include "absl/base/macros.h"
8 #include "absl/strings/escaping.h"
9 #include "quiche/common/platform/api/quiche_test.h"
10 
11 namespace http2 {
12 namespace {
13 
14 class HuffmanEncoderTest : public quiche::test::QuicheTestWithParam<bool> {
15  protected:
HuffmanEncoderTest()16   HuffmanEncoderTest() : use_fast_encoder_(GetParam()) {}
17   virtual ~HuffmanEncoderTest() = default;
18 
Encode(absl::string_view input,size_t encoded_size,std::string * output)19   void Encode(absl::string_view input, size_t encoded_size,
20               std::string* output) {
21     use_fast_encoder_ ? HuffmanEncodeFast(input, encoded_size, output)
22                       : HuffmanEncode(input, encoded_size, output);
23   }
24 
25   const bool use_fast_encoder_;
26 };
27 
28 INSTANTIATE_TEST_SUITE_P(TwoEncoders, HuffmanEncoderTest, ::testing::Bool());
29 
TEST_P(HuffmanEncoderTest,Empty)30 TEST_P(HuffmanEncoderTest, Empty) {
31   std::string empty("");
32   size_t encoded_size = HuffmanSize(empty);
33   EXPECT_EQ(0u, encoded_size);
34 
35   std::string buffer;
36   Encode(empty, encoded_size, &buffer);
37   EXPECT_EQ("", buffer);
38 }
39 
TEST_P(HuffmanEncoderTest,SpecRequestExamples)40 TEST_P(HuffmanEncoderTest, SpecRequestExamples) {
41   std::string test_table[] = {
42       absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"),
43       "www.example.com",
44       absl::HexStringToBytes("a8eb10649cbf"),
45       "no-cache",
46       absl::HexStringToBytes("25a849e95ba97d7f"),
47       "custom-key",
48       absl::HexStringToBytes("25a849e95bb8e8b4bf"),
49       "custom-value",
50   };
51   for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) {
52     const std::string& huffman_encoded(test_table[i]);
53     const std::string& plain_string(test_table[i + 1]);
54     size_t encoded_size = HuffmanSize(plain_string);
55     EXPECT_EQ(huffman_encoded.size(), encoded_size);
56     std::string buffer;
57     buffer.reserve(huffman_encoded.size());
58     Encode(plain_string, encoded_size, &buffer);
59     EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string;
60   }
61 }
62 
TEST_P(HuffmanEncoderTest,SpecResponseExamples)63 TEST_P(HuffmanEncoderTest, SpecResponseExamples) {
64   // clang-format off
65   std::string test_table[] = {
66     absl::HexStringToBytes("6402"),
67     "302",
68     absl::HexStringToBytes("aec3771a4b"),
69     "private",
70     absl::HexStringToBytes("d07abe941054d444a8200595040b8166"
71             "e082a62d1bff"),
72     "Mon, 21 Oct 2013 20:13:21 GMT",
73     absl::HexStringToBytes("9d29ad171863c78f0b97c8e9ae82ae43"
74             "d3"),
75     "https://www.example.com",
76     absl::HexStringToBytes("94e7821dd7f2e6c7b335dfdfcd5b3960"
77             "d5af27087f3672c1ab270fb5291f9587"
78             "316065c003ed4ee5b1063d5007"),
79     "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
80   };
81   // clang-format on
82   for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) {
83     const std::string& huffman_encoded(test_table[i]);
84     const std::string& plain_string(test_table[i + 1]);
85     size_t encoded_size = HuffmanSize(plain_string);
86     EXPECT_EQ(huffman_encoded.size(), encoded_size);
87     std::string buffer;
88     Encode(plain_string, encoded_size, &buffer);
89     EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string;
90   }
91 }
92 
TEST_P(HuffmanEncoderTest,EncodedSizeAgreesWithEncodeString)93 TEST_P(HuffmanEncoderTest, EncodedSizeAgreesWithEncodeString) {
94   std::string test_table[] = {
95       "",
96       "Mon, 21 Oct 2013 20:13:21 GMT",
97       "https://www.example.com",
98       "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
99       std::string(1, '\0'),
100       std::string("foo\0bar", 7),
101       std::string(256, '\0'),
102   };
103   // Modify last |test_table| entry to cover all codes.
104   for (size_t i = 0; i != 256; ++i) {
105     test_table[ABSL_ARRAYSIZE(test_table) - 1][i] = static_cast<char>(i);
106   }
107 
108   for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); ++i) {
109     const std::string& plain_string = test_table[i];
110     size_t encoded_size = HuffmanSize(plain_string);
111     std::string huffman_encoded;
112     Encode(plain_string, encoded_size, &huffman_encoded);
113     EXPECT_EQ(encoded_size, huffman_encoded.size());
114   }
115 }
116 
117 // Test that encoding appends to output without overwriting it.
TEST_P(HuffmanEncoderTest,AppendToOutput)118 TEST_P(HuffmanEncoderTest, AppendToOutput) {
119   size_t encoded_size = HuffmanSize("foo");
120   std::string buffer;
121   Encode("foo", encoded_size, &buffer);
122   EXPECT_EQ(absl::HexStringToBytes("94e7"), buffer);
123 
124   encoded_size = HuffmanSize("bar");
125   Encode("bar", encoded_size, &buffer);
126   EXPECT_EQ(absl::HexStringToBytes("94e78c767f"), buffer);
127 }
128 
129 }  // namespace
130 }  // namespace http2
131