blob: 56cfe84a5165113c8559534ab45ac370e44fc7b6 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
bncc7497ad2019-08-14 07:19:29 -070010#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
renjietangc2aa5cb2019-06-20 12:22:53 -070011#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
14
15using ::testing::Eq;
16using ::testing::StrictMock;
17using ::testing::Values;
18
19namespace quic {
20namespace test {
21namespace {
22
bncf21c1ad2019-06-20 20:09:50 -070023class QpackEncoderTest : public QuicTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -050024 protected:
bncc7497ad2019-08-14 07:19:29 -070025 QpackEncoderTest() : encoder_(&decoder_stream_error_delegate_) {
26 encoder_.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate_);
27 encoder_.SetMaximumBlockedStreams(1);
28 }
29
QUICHE teama6ef0a62019-03-07 20:34:33 -050030 ~QpackEncoderTest() override = default;
31
vasilvvc48c8712019-03-11 13:38:16 -070032 std::string Encode(const spdy::SpdyHeaderBlock* header_list) {
bncc7497ad2019-08-14 07:19:29 -070033 return encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050034 }
35
36 StrictMock<MockDecoderStreamErrorDelegate> decoder_stream_error_delegate_;
bncc7497ad2019-08-14 07:19:29 -070037 StrictMock<MockQpackStreamSenderDelegate> encoder_stream_sender_delegate_;
38 QpackEncoder encoder_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050039};
40
bncf21c1ad2019-06-20 20:09:50 -070041TEST_F(QpackEncoderTest, Empty) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050042 spdy::SpdyHeaderBlock header_list;
vasilvvc48c8712019-03-11 13:38:16 -070043 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050044
45 EXPECT_EQ(QuicTextUtils::HexDecode("0000"), output);
46}
47
bncf21c1ad2019-06-20 20:09:50 -070048TEST_F(QpackEncoderTest, EmptyName) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050049 spdy::SpdyHeaderBlock header_list;
50 header_list[""] = "foo";
vasilvvc48c8712019-03-11 13:38:16 -070051 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050052
53 EXPECT_EQ(QuicTextUtils::HexDecode("0000208294e7"), output);
54}
55
bncf21c1ad2019-06-20 20:09:50 -070056TEST_F(QpackEncoderTest, EmptyValue) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050057 spdy::SpdyHeaderBlock header_list;
58 header_list["foo"] = "";
vasilvvc48c8712019-03-11 13:38:16 -070059 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050060
61 EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e700"), output);
62}
63
bncf21c1ad2019-06-20 20:09:50 -070064TEST_F(QpackEncoderTest, EmptyNameAndValue) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050065 spdy::SpdyHeaderBlock header_list;
66 header_list[""] = "";
vasilvvc48c8712019-03-11 13:38:16 -070067 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050068
69 EXPECT_EQ(QuicTextUtils::HexDecode("00002000"), output);
70}
71
bncf21c1ad2019-06-20 20:09:50 -070072TEST_F(QpackEncoderTest, Simple) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 spdy::SpdyHeaderBlock header_list;
74 header_list["foo"] = "bar";
vasilvvc48c8712019-03-11 13:38:16 -070075 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050076
77 EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e703626172"), output);
78}
79
bncf21c1ad2019-06-20 20:09:50 -070080TEST_F(QpackEncoderTest, Multiple) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 spdy::SpdyHeaderBlock header_list;
82 header_list["foo"] = "bar";
83 // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
vasilvvc48c8712019-03-11 13:38:16 -070084 header_list["ZZZZZZZ"] = std::string(127, 'Z');
85 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050086
87 EXPECT_EQ(
88 QuicTextUtils::HexDecode(
89 "0000" // prefix
90 "2a94e703626172" // foo: bar
91 "27005a5a5a5a5a5a5a" // 7 octet long header name, the smallest number
92 // that does not fit on a 3-bit prefix.
93 "7f005a5a5a5a5a5a5a" // 127 octet long header value, the smallest
94 "5a5a5a5a5a5a5a5a5a" // number that does not fit on a 7-bit prefix.
95 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
96 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
97 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
98 "5a5a5a5a5a5a5a5a5a"),
99 output);
100}
101
bncf21c1ad2019-06-20 20:09:50 -0700102TEST_F(QpackEncoderTest, StaticTable) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500103 {
104 spdy::SpdyHeaderBlock header_list;
105 header_list[":method"] = "GET";
106 header_list["accept-encoding"] = "gzip, deflate, br";
107 header_list["location"] = "";
108
vasilvvc48c8712019-03-11 13:38:16 -0700109 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110 EXPECT_EQ(QuicTextUtils::HexDecode("0000d1dfcc"), output);
111 }
112 {
113 spdy::SpdyHeaderBlock header_list;
114 header_list[":method"] = "POST";
115 header_list["accept-encoding"] = "compress";
116 header_list["location"] = "foo";
117
vasilvvc48c8712019-03-11 13:38:16 -0700118 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 EXPECT_EQ(QuicTextUtils::HexDecode("0000d45f108621e9aec2a11f5c8294e7"),
120 output);
121 }
122 {
123 spdy::SpdyHeaderBlock header_list;
124 header_list[":method"] = "TRACE";
125 header_list["accept-encoding"] = "";
126
vasilvvc48c8712019-03-11 13:38:16 -0700127 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 EXPECT_EQ(QuicTextUtils::HexDecode("00005f000554524143455f1000"), output);
129 }
130}
131
bncf21c1ad2019-06-20 20:09:50 -0700132TEST_F(QpackEncoderTest, DecoderStreamError) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500133 EXPECT_CALL(decoder_stream_error_delegate_,
134 OnDecoderStreamError(Eq("Encoded integer too large.")));
135
renjietang8a2df8f2019-08-07 10:43:52 -0700136 QpackEncoder encoder(&decoder_stream_error_delegate_);
137 encoder.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate_);
bnc7d9e2a72019-08-09 08:20:10 -0700138 encoder.decoder_stream_receiver()->Decode(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
140}
141
bncf21c1ad2019-06-20 20:09:50 -0700142TEST_F(QpackEncoderTest, SplitAlongNullCharacter) {
bnc78053612019-04-25 20:08:12 -0700143 spdy::SpdyHeaderBlock header_list;
144 header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
145 std::string output = Encode(&header_list);
146
147 EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
148 "2a94e703626172" // foo: bar
149 "2a94e703626172" // foo: bar
150 "2a94e70362617a" // foo: baz
151 ),
152 output);
153}
154
bncc39c2812019-08-14 07:48:09 -0700155TEST_F(QpackEncoderTest, ZeroInsertCountIncrement) {
156 // Encoder receives insert count increment with forbidden value 0.
157 EXPECT_CALL(decoder_stream_error_delegate_,
158 OnDecoderStreamError(Eq("Invalid increment value 0.")));
159 encoder_.OnInsertCountIncrement(0);
160}
161
162TEST_F(QpackEncoderTest, TooLargeInsertCountIncrement) {
163 // Encoder receives insert count increment with value that increases Known
164 // Received Count to a value (one) which is larger than the number of dynamic
165 // table insertions sent (zero).
166 EXPECT_CALL(
167 decoder_stream_error_delegate_,
168 OnDecoderStreamError(Eq("Increment value 1 raises known received count "
169 "to 1 exceeding inserted entry count 0")));
170 encoder_.OnInsertCountIncrement(1);
171}
172
173TEST_F(QpackEncoderTest, InvalidHeaderAcknowledgement) {
174 // Encoder receives header acknowledgement for a stream on which no header
175 // block with dynamic table entries was ever sent.
176 EXPECT_CALL(
177 decoder_stream_error_delegate_,
178 OnDecoderStreamError(Eq("Header Acknowledgement received for stream 0 "
179 "with no outstanding header blocks.")));
180 encoder_.OnHeaderAcknowledgement(/* stream_id = */ 0);
181}
182
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183} // namespace
184} // namespace test
185} // namespace quic