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 Decode(absl::HexStringToBytes(
60 "c500"
61 "c28294e7"
62 "bf4a03626172"
63 "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
64 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
65 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
66 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"));
67 }
68
TEST_F(QpackEncoderStreamReceiverTest,InsertWithNameReferenceIndexTooLarge)69 TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) {
70 EXPECT_CALL(*delegate(),
71 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
72 Eq("Encoded integer too large.")));
73
74 Decode(absl::HexStringToBytes("bfffffffffffffffffffffff"));
75 }
76
TEST_F(QpackEncoderStreamReceiverTest,InsertWithNameReferenceValueTooLong)77 TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) {
78 EXPECT_CALL(*delegate(),
79 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
80 Eq("Encoded integer too large.")));
81
82 Decode(absl::HexStringToBytes("c57fffffffffffffffffffff"));
83 }
84
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReference)85 TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) {
86 // Empty name and value.
87 EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq("")));
88 // Huffman encoded short strings.
89 EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar")));
90 // Not Huffman encoded short strings.
91 EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("foo")));
92 // Not Huffman encoded long strings; length does not fit on prefix.
93 // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
94 EXPECT_CALL(*delegate(),
95 OnInsertWithoutNameReference(Eq(std::string(31, 'Z')),
96 Eq(std::string(127, 'Z'))));
97
98 Decode(absl::HexStringToBytes(
99 "4000"
100 "4362617203626172"
101 "6294e78294e7"
102 "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f005a"
103 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
104 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
105 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
106 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"));
107 }
108
109 // Name Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceNameTooLongForVarintDecoder)110 TEST_F(QpackEncoderStreamReceiverTest,
111 InsertWithoutNameReferenceNameTooLongForVarintDecoder) {
112 EXPECT_CALL(*delegate(),
113 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
114 Eq("Encoded integer too large.")));
115
116 Decode(absl::HexStringToBytes("5fffffffffffffffffffff"));
117 }
118
119 // Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceNameExceedsLimit)120 TEST_F(QpackEncoderStreamReceiverTest,
121 InsertWithoutNameReferenceNameExceedsLimit) {
122 EXPECT_CALL(*delegate(),
123 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_STRING_LITERAL_TOO_LONG,
124 Eq("String literal too long.")));
125
126 Decode(absl::HexStringToBytes("5fffff7f"));
127 }
128
129 // Value Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceValueTooLongForVarintDecoder)130 TEST_F(QpackEncoderStreamReceiverTest,
131 InsertWithoutNameReferenceValueTooLongForVarintDecoder) {
132 EXPECT_CALL(*delegate(),
133 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
134 Eq("Encoded integer too large.")));
135
136 Decode(absl::HexStringToBytes("436261727fffffffffffffffffffff"));
137 }
138
139 // Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,InsertWithoutNameReferenceValueExceedsLimit)140 TEST_F(QpackEncoderStreamReceiverTest,
141 InsertWithoutNameReferenceValueExceedsLimit) {
142 EXPECT_CALL(*delegate(),
143 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_STRING_LITERAL_TOO_LONG,
144 Eq("String literal too long.")));
145
146 Decode(absl::HexStringToBytes("436261727fffff7f"));
147 }
148
TEST_F(QpackEncoderStreamReceiverTest,Duplicate)149 TEST_F(QpackEncoderStreamReceiverTest, Duplicate) {
150 // Small index fits in prefix.
151 EXPECT_CALL(*delegate(), OnDuplicate(17));
152 // Large index requires two extension bytes.
153 EXPECT_CALL(*delegate(), OnDuplicate(500));
154
155 Decode(absl::HexStringToBytes("111fd503"));
156 }
157
TEST_F(QpackEncoderStreamReceiverTest,DuplicateIndexTooLarge)158 TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) {
159 EXPECT_CALL(*delegate(),
160 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
161 Eq("Encoded integer too large.")));
162
163 Decode(absl::HexStringToBytes("1fffffffffffffffffffff"));
164 }
165
TEST_F(QpackEncoderStreamReceiverTest,SetDynamicTableCapacity)166 TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) {
167 // Small capacity fits in prefix.
168 EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(17));
169 // Large capacity requires two extension bytes.
170 EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500));
171
172 Decode(absl::HexStringToBytes("313fd503"));
173 }
174
TEST_F(QpackEncoderStreamReceiverTest,SetDynamicTableCapacityTooLarge)175 TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) {
176 EXPECT_CALL(*delegate(),
177 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
178 Eq("Encoded integer too large.")));
179
180 Decode(absl::HexStringToBytes("3fffffffffffffffffffff"));
181 }
182
TEST_F(QpackEncoderStreamReceiverTest,InvalidHuffmanEncoding)183 TEST_F(QpackEncoderStreamReceiverTest, InvalidHuffmanEncoding) {
184 EXPECT_CALL(*delegate(),
185 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_HUFFMAN_ENCODING_ERROR,
186 Eq("Error in Huffman-encoded string.")));
187
188 Decode(absl::HexStringToBytes("c281ff"));
189 }
190
191 } // namespace
192 } // namespace test
193 } // namespace quic
194