blob: 9ea45567a56c97c36bf34f5ea72ac1961d0c1f68 [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 "testing/gtest/include/gtest/gtest.h"
10#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
11#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_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
23class QpackEncoderTest : public QuicTestWithParam<FragmentMode> {
24 protected:
25 QpackEncoderTest() : fragment_mode_(GetParam()) {}
26 ~QpackEncoderTest() override = default;
27
vasilvvc48c8712019-03-11 13:38:16 -070028 std::string Encode(const spdy::SpdyHeaderBlock* header_list) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050029 return QpackEncode(
30 &decoder_stream_error_delegate_, &encoder_stream_sender_delegate_,
31 FragmentModeToFragmentSizeGenerator(fragment_mode_), header_list);
32 }
33
34 StrictMock<MockDecoderStreamErrorDelegate> decoder_stream_error_delegate_;
35 NoopEncoderStreamSenderDelegate encoder_stream_sender_delegate_;
36
37 private:
38 const FragmentMode fragment_mode_;
39};
40
41INSTANTIATE_TEST_SUITE_P(,
42 QpackEncoderTest,
43 Values(FragmentMode::kSingleChunk,
44 FragmentMode::kOctetByOctet));
45
46TEST_P(QpackEncoderTest, Empty) {
47 spdy::SpdyHeaderBlock header_list;
vasilvvc48c8712019-03-11 13:38:16 -070048 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050049
50 EXPECT_EQ(QuicTextUtils::HexDecode("0000"), output);
51}
52
53TEST_P(QpackEncoderTest, EmptyName) {
54 spdy::SpdyHeaderBlock header_list;
55 header_list[""] = "foo";
vasilvvc48c8712019-03-11 13:38:16 -070056 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050057
58 EXPECT_EQ(QuicTextUtils::HexDecode("0000208294e7"), output);
59}
60
61TEST_P(QpackEncoderTest, EmptyValue) {
62 spdy::SpdyHeaderBlock header_list;
63 header_list["foo"] = "";
vasilvvc48c8712019-03-11 13:38:16 -070064 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050065
66 EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e700"), output);
67}
68
69TEST_P(QpackEncoderTest, EmptyNameAndValue) {
70 spdy::SpdyHeaderBlock header_list;
71 header_list[""] = "";
vasilvvc48c8712019-03-11 13:38:16 -070072 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050073
74 EXPECT_EQ(QuicTextUtils::HexDecode("00002000"), output);
75}
76
77TEST_P(QpackEncoderTest, Simple) {
78 spdy::SpdyHeaderBlock header_list;
79 header_list["foo"] = "bar";
vasilvvc48c8712019-03-11 13:38:16 -070080 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050081
82 EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e703626172"), output);
83}
84
85TEST_P(QpackEncoderTest, Multiple) {
86 spdy::SpdyHeaderBlock header_list;
87 header_list["foo"] = "bar";
88 // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
vasilvvc48c8712019-03-11 13:38:16 -070089 header_list["ZZZZZZZ"] = std::string(127, 'Z');
90 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -050091
92 EXPECT_EQ(
93 QuicTextUtils::HexDecode(
94 "0000" // prefix
95 "2a94e703626172" // foo: bar
96 "27005a5a5a5a5a5a5a" // 7 octet long header name, the smallest number
97 // that does not fit on a 3-bit prefix.
98 "7f005a5a5a5a5a5a5a" // 127 octet long header value, the smallest
99 "5a5a5a5a5a5a5a5a5a" // number that does not fit on a 7-bit prefix.
100 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
101 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
102 "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
103 "5a5a5a5a5a5a5a5a5a"),
104 output);
105}
106
107TEST_P(QpackEncoderTest, StaticTable) {
108 {
109 spdy::SpdyHeaderBlock header_list;
110 header_list[":method"] = "GET";
111 header_list["accept-encoding"] = "gzip, deflate, br";
112 header_list["location"] = "";
113
vasilvvc48c8712019-03-11 13:38:16 -0700114 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 EXPECT_EQ(QuicTextUtils::HexDecode("0000d1dfcc"), output);
116 }
117 {
118 spdy::SpdyHeaderBlock header_list;
119 header_list[":method"] = "POST";
120 header_list["accept-encoding"] = "compress";
121 header_list["location"] = "foo";
122
vasilvvc48c8712019-03-11 13:38:16 -0700123 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124 EXPECT_EQ(QuicTextUtils::HexDecode("0000d45f108621e9aec2a11f5c8294e7"),
125 output);
126 }
127 {
128 spdy::SpdyHeaderBlock header_list;
129 header_list[":method"] = "TRACE";
130 header_list["accept-encoding"] = "";
131
vasilvvc48c8712019-03-11 13:38:16 -0700132 std::string output = Encode(&header_list);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500133 EXPECT_EQ(QuicTextUtils::HexDecode("00005f000554524143455f1000"), output);
134 }
135}
136
137TEST_P(QpackEncoderTest, SimpleIndexed) {
138 spdy::SpdyHeaderBlock header_list;
139 header_list[":path"] = "/";
140
141 QpackEncoder encoder(&decoder_stream_error_delegate_,
142 &encoder_stream_sender_delegate_);
143 auto progressive_encoder =
144 encoder.EncodeHeaderList(/* stream_id = */ 1, &header_list);
145 EXPECT_TRUE(progressive_encoder->HasNext());
146
147 // This indexed header field takes exactly three bytes:
148 // two for the prefix, one for the indexed static entry.
vasilvvc48c8712019-03-11 13:38:16 -0700149 std::string output;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 progressive_encoder->Next(3, &output);
151
152 EXPECT_EQ(QuicTextUtils::HexDecode("0000c1"), output);
153 EXPECT_FALSE(progressive_encoder->HasNext());
154}
155
156TEST_P(QpackEncoderTest, DecoderStreamError) {
157 EXPECT_CALL(decoder_stream_error_delegate_,
158 OnDecoderStreamError(Eq("Encoded integer too large.")));
159
160 QpackEncoder encoder(&decoder_stream_error_delegate_,
161 &encoder_stream_sender_delegate_);
162 encoder.DecodeDecoderStreamData(
163 QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
164}
165
bnc78053612019-04-25 20:08:12 -0700166TEST_P(QpackEncoderTest, SplitAlongNullCharacter) {
167 spdy::SpdyHeaderBlock header_list;
168 header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
169 std::string output = Encode(&header_list);
170
171 EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
172 "2a94e703626172" // foo: bar
173 "2a94e703626172" // foo: bar
174 "2a94e70362617a" // foo: baz
175 ),
176 output);
177}
178
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179} // namespace
180} // namespace test
181} // namespace quic