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