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/quic/core/qpack/qpack_encoder_stream_receiver.h"
6 
7 #include "absl/strings/escaping.h"
8 #include "absl/strings/string_view.h"
9 #include "quiche/quic/platform/api/quic_test.h"
10 
11 using testing::Eq;
12 using testing::StrictMock;
13 
14 namespace quic {
15 namespace test {
16 namespace {
17 
18 class MockDelegate : public QpackEncoderStreamReceiver::Delegate {
19  public:
20   ~MockDelegate() override = default;
21 
22   MOCK_METHOD(void, OnInsertWithNameReference,
23               (bool is_static, uint64_t name_index, absl::string_view value),
24               (override));
25   MOCK_METHOD(void, OnInsertWithoutNameReference,
26               (absl::string_view name, absl::string_view value), (override));
27   MOCK_METHOD(void, OnDuplicate, (uint64_t index), (override));
28   MOCK_METHOD(void, OnSetDynamicTableCapacity, (uint64_t capacity), (override));
29   MOCK_METHOD(void, OnErrorDetected,
30               (QuicErrorCode error_code, absl::string_view error_message),
31               (override));
32 };
33 
34 class QpackEncoderStreamReceiverTest : public QuicTest {
35  protected:
QpackEncoderStreamReceiverTest()36   QpackEncoderStreamReceiverTest() : stream_(&delegate_) {}
37   ~QpackEncoderStreamReceiverTest() override = default;
38 
Decode(absl::string_view data)39   void Decode(absl::string_view data) { stream_.Decode(data); }
delegate()40   StrictMock<MockDelegate>* delegate() { return &delegate_; }
41 
42  private:
43   QpackEncoderStreamReceiver stream_;
44   StrictMock<MockDelegate> delegate_;
45 };
46 
TEST_F(QpackEncoderStreamReceiverTest,InsertWithNameReference)47 TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) {
48   // Static, index fits in prefix, empty value.
49   EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, Eq("")));
50   // Static, index fits in prefix, Huffman encoded value.
51   EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, Eq("foo")));
52   // Not static, index does not fit in prefix, not Huffman encoded value.
53   EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, Eq("bar")));
54   // Value length does not fit in prefix.
55   // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
56   EXPECT_CALL(*delegate(),
57               OnInsertWithNameReference(false, 42, Eq(std::string(127, 'Z'))));
58 
59   std::string encoded_data;
60   ASSERT_TRUE(absl::HexStringToBytes(
61       "c500"
62       "c28294e7"
63       "bf4a03626172"
64       "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
65       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
66       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
67       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a",
68       &encoded_data));
69   Decode(encoded_data);
70 }
71 
TEST_F(QpackEncoderStreamReceiverTest,InsertWithNameReferenceIndexTooLarge)72 TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) {
73   EXPECT_CALL(*delegate(),
74               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
75                               Eq("Encoded integer too large.")));
76 
77   std::string encoded_data;
78   ASSERT_TRUE(
79       absl::HexStringToBytes("bfffffffffffffffffffffff", &encoded_data));
80   Decode(encoded_data);
81 }
82 
TEST_F(QpackEncoderStreamReceiverTest,InsertWithNameReferenceValueTooLong)83 TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) {
84   EXPECT_CALL(*delegate(),
85               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
86                               Eq("Encoded integer too large.")));
87 
88   std::string encoded_data;
89   ASSERT_TRUE(
90       absl::HexStringToBytes("c57fffffffffffffffffffff", &encoded_data));
91   Decode(encoded_data);
92 }
93 
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReference)94 TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) {
95   // Empty name and value.
96   EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq("")));
97   // Huffman encoded short strings.
98   EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar")));
99   // Not Huffman encoded short strings.
100   EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("foo")));
101   // Not Huffman encoded long strings; length does not fit on prefix.
102   // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
103   EXPECT_CALL(*delegate(),
104               OnInsertWithoutNameReference(Eq(std::string(31, 'Z')),
105                                            Eq(std::string(127, 'Z'))));
106 
107   std::string encoded_data;
108   ASSERT_TRUE(absl::HexStringToBytes(
109       "4000"
110       "4362617203626172"
111       "6294e78294e7"
112       "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f005a"
113       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
114       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
115       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
116       "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a",
117       &encoded_data));
118   Decode(encoded_data);
119 }
120 
121 // Name Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceNameTooLongForVarintDecoder)122 TEST_F(QpackEncoderStreamReceiverTest,
123        InsertWithoutNameReferenceNameTooLongForVarintDecoder) {
124   EXPECT_CALL(*delegate(),
125               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
126                               Eq("Encoded integer too large.")));
127 
128   std::string encoded_data;
129   ASSERT_TRUE(absl::HexStringToBytes("5fffffffffffffffffffff", &encoded_data));
130   Decode(encoded_data);
131 }
132 
133 // Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceNameExceedsLimit)134 TEST_F(QpackEncoderStreamReceiverTest,
135        InsertWithoutNameReferenceNameExceedsLimit) {
136   EXPECT_CALL(*delegate(),
137               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_STRING_LITERAL_TOO_LONG,
138                               Eq("String literal too long.")));
139 
140   std::string encoded_data;
141   ASSERT_TRUE(absl::HexStringToBytes("5fffff7f", &encoded_data));
142   Decode(encoded_data);
143 }
144 
145 // Value Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceValueTooLongForVarintDecoder)146 TEST_F(QpackEncoderStreamReceiverTest,
147        InsertWithoutNameReferenceValueTooLongForVarintDecoder) {
148   EXPECT_CALL(*delegate(),
149               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
150                               Eq("Encoded integer too large.")));
151 
152   std::string encoded_data;
153   ASSERT_TRUE(
154       absl::HexStringToBytes("436261727fffffffffffffffffffff", &encoded_data));
155   Decode(encoded_data);
156 }
157 
158 // Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceValueExceedsLimit)159 TEST_F(QpackEncoderStreamReceiverTest,
160        InsertWithoutNameReferenceValueExceedsLimit) {
161   EXPECT_CALL(*delegate(),
162               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_STRING_LITERAL_TOO_LONG,
163                               Eq("String literal too long.")));
164 
165   std::string encoded_data;
166   ASSERT_TRUE(absl::HexStringToBytes("436261727fffff7f", &encoded_data));
167   Decode(encoded_data);
168 }
169 
TEST_F(QpackEncoderStreamReceiverTest,Duplicate)170 TEST_F(QpackEncoderStreamReceiverTest, Duplicate) {
171   // Small index fits in prefix.
172   EXPECT_CALL(*delegate(), OnDuplicate(17));
173   // Large index requires two extension bytes.
174   EXPECT_CALL(*delegate(), OnDuplicate(500));
175 
176   std::string encoded_data;
177   ASSERT_TRUE(absl::HexStringToBytes("111fd503", &encoded_data));
178   Decode(encoded_data);
179 }
180 
TEST_F(QpackEncoderStreamReceiverTest,DuplicateIndexTooLarge)181 TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) {
182   EXPECT_CALL(*delegate(),
183               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
184                               Eq("Encoded integer too large.")));
185 
186   std::string encoded_data;
187   ASSERT_TRUE(absl::HexStringToBytes("1fffffffffffffffffffff", &encoded_data));
188   Decode(encoded_data);
189 }
190 
TEST_F(QpackEncoderStreamReceiverTest,SetDynamicTableCapacity)191 TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) {
192   // Small capacity fits in prefix.
193   EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(17));
194   // Large capacity requires two extension bytes.
195   EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500));
196 
197   std::string encoded_data;
198   ASSERT_TRUE(absl::HexStringToBytes("313fd503", &encoded_data));
199   Decode(encoded_data);
200 }
201 
TEST_F(QpackEncoderStreamReceiverTest,SetDynamicTableCapacityTooLarge)202 TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) {
203   EXPECT_CALL(*delegate(),
204               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
205                               Eq("Encoded integer too large.")));
206 
207   std::string encoded_data;
208   ASSERT_TRUE(absl::HexStringToBytes("3fffffffffffffffffffff", &encoded_data));
209   Decode(encoded_data);
210 }
211 
TEST_F(QpackEncoderStreamReceiverTest,InvalidHuffmanEncoding)212 TEST_F(QpackEncoderStreamReceiverTest, InvalidHuffmanEncoding) {
213   EXPECT_CALL(*delegate(),
214               OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_HUFFMAN_ENCODING_ERROR,
215                               Eq("Error in Huffman-encoded string.")));
216 
217   std::string encoded_data;
218   ASSERT_TRUE(absl::HexStringToBytes("c281ff", &encoded_data));
219   Decode(encoded_data);
220 }
221 
222 }  // namespace
223 }  // namespace test
224 }  // namespace quic
225