blob: 6c6a9773c5985cdd777abe3cbbc15271f3ca0d60 [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// Copyright 2016 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "http2/hpack/decoder/hpack_decoder_string_buffer.h"
QUICHE teamfd50a402018-12-07 22:54:05 -05006
7// Tests of HpackDecoderStringBuffer.
8
9#include <initializer_list>
10
QUICHE team5be974e2020-12-29 18:35:24 -050011#include "http2/platform/api/http2_logging.h"
12#include "http2/platform/api/http2_string_utils.h"
13#include "http2/platform/api/http2_test_helpers.h"
14#include "common/platform/api/quiche_test.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050015
16using ::testing::AssertionResult;
17using ::testing::AssertionSuccess;
18using ::testing::HasSubstr;
19
20namespace http2 {
21namespace test {
22namespace {
23
bnc6744c062020-09-30 10:45:28 -070024class HpackDecoderStringBufferTest : public QuicheTest {
QUICHE teamfd50a402018-12-07 22:54:05 -050025 protected:
26 typedef HpackDecoderStringBuffer::State State;
27 typedef HpackDecoderStringBuffer::Backing Backing;
28
29 State state() const { return buf_.state_for_testing(); }
30 Backing backing() const { return buf_.backing_for_testing(); }
31
QUICHE team61940b42019-03-07 23:32:27 -050032 // We want to know that HTTP2_LOG(x) << buf_ will work in production should
33 // that be needed, so we test that it outputs the expected values.
bnc47904002019-08-16 11:49:48 -070034 AssertionResult VerifyLogHasSubstrs(std::initializer_list<std::string> strs) {
QUICHE team61940b42019-03-07 23:32:27 -050035 HTTP2_VLOG(1) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050036 std::ostringstream ss;
37 buf_.OutputDebugStringTo(ss);
bnc47904002019-08-16 11:49:48 -070038 std::string dbg_str(ss.str());
QUICHE teamfd50a402018-12-07 22:54:05 -050039 for (const auto& expected : strs) {
40 VERIFY_THAT(dbg_str, HasSubstr(expected));
41 }
42 return AssertionSuccess();
43 }
44
45 HpackDecoderStringBuffer buf_;
46};
47
48TEST_F(HpackDecoderStringBufferTest, SetStatic) {
vasilvvb16f7962020-10-13 10:48:38 -070049 absl::string_view data("static string");
QUICHE teamfd50a402018-12-07 22:54:05 -050050
51 EXPECT_EQ(state(), State::RESET);
52 EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"}));
53
54 buf_.Set(data, /*is_static*/ true);
QUICHE team61940b42019-03-07 23:32:27 -050055 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050056 EXPECT_EQ(state(), State::COMPLETE);
57 EXPECT_EQ(backing(), Backing::STATIC);
58 EXPECT_EQ(data, buf_.str());
59 EXPECT_EQ(data.data(), buf_.str().data());
60 EXPECT_TRUE(VerifyLogHasSubstrs(
61 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
62
63 // The string is static, so BufferStringIfUnbuffered won't change anything.
64 buf_.BufferStringIfUnbuffered();
65 EXPECT_EQ(state(), State::COMPLETE);
66 EXPECT_EQ(backing(), Backing::STATIC);
67 EXPECT_EQ(data, buf_.str());
68 EXPECT_EQ(data.data(), buf_.str().data());
69 EXPECT_TRUE(VerifyLogHasSubstrs(
70 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
71}
72
73TEST_F(HpackDecoderStringBufferTest, PlainWhole) {
vasilvvb16f7962020-10-13 10:48:38 -070074 absl::string_view data("some text.");
QUICHE teamfd50a402018-12-07 22:54:05 -050075
QUICHE team61940b42019-03-07 23:32:27 -050076 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050077 EXPECT_EQ(state(), State::RESET);
78
79 buf_.OnStart(/*huffman_encoded*/ false, data.size());
80 EXPECT_EQ(state(), State::COLLECTING);
81 EXPECT_EQ(backing(), Backing::RESET);
QUICHE team61940b42019-03-07 23:32:27 -050082 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050083
84 EXPECT_TRUE(buf_.OnData(data.data(), data.size()));
85 EXPECT_EQ(state(), State::COLLECTING);
86 EXPECT_EQ(backing(), Backing::UNBUFFERED);
87
88 EXPECT_TRUE(buf_.OnEnd());
89 EXPECT_EQ(state(), State::COMPLETE);
90 EXPECT_EQ(backing(), Backing::UNBUFFERED);
91 EXPECT_EQ(0u, buf_.BufferedLength());
92 EXPECT_TRUE(VerifyLogHasSubstrs(
93 {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."}));
94
bnc74646d12019-12-13 09:21:19 -080095 // We expect that the string buffer points to the passed in
vasilvvb16f7962020-10-13 10:48:38 -070096 // string_view's backing store.
QUICHE teamfd50a402018-12-07 22:54:05 -050097 EXPECT_EQ(data.data(), buf_.str().data());
98
99 // Now force it to buffer the string, after which it will still have the same
100 // string value, but the backing store will be different.
101 buf_.BufferStringIfUnbuffered();
QUICHE team61940b42019-03-07 23:32:27 -0500102 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500103 EXPECT_EQ(backing(), Backing::BUFFERED);
104 EXPECT_EQ(buf_.BufferedLength(), data.size());
105 EXPECT_EQ(data, buf_.str());
106 EXPECT_NE(data.data(), buf_.str().data());
107 EXPECT_TRUE(VerifyLogHasSubstrs(
108 {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."}));
109}
110
111TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
vasilvvb16f7962020-10-13 10:48:38 -0700112 absl::string_view data("some text.");
113 absl::string_view part1 = data.substr(0, 1);
114 absl::string_view part2 = data.substr(1);
QUICHE teamfd50a402018-12-07 22:54:05 -0500115
116 EXPECT_EQ(state(), State::RESET);
117 buf_.OnStart(/*huffman_encoded*/ false, data.size());
118 EXPECT_EQ(state(), State::COLLECTING);
119 EXPECT_EQ(backing(), Backing::RESET);
120
121 // OnData with only a part of the data, not the whole, so buf_ will buffer
122 // the data.
123 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
124 EXPECT_EQ(state(), State::COLLECTING);
125 EXPECT_EQ(backing(), Backing::BUFFERED);
126 EXPECT_EQ(buf_.BufferedLength(), part1.size());
QUICHE team61940b42019-03-07 23:32:27 -0500127 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500128
129 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
130 EXPECT_EQ(state(), State::COLLECTING);
131 EXPECT_EQ(backing(), Backing::BUFFERED);
132 EXPECT_EQ(buf_.BufferedLength(), data.size());
133
134 EXPECT_TRUE(buf_.OnEnd());
135 EXPECT_EQ(state(), State::COMPLETE);
136 EXPECT_EQ(backing(), Backing::BUFFERED);
137 EXPECT_EQ(buf_.BufferedLength(), data.size());
QUICHE team61940b42019-03-07 23:32:27 -0500138 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500139
vasilvvb16f7962020-10-13 10:48:38 -0700140 absl::string_view buffered = buf_.str();
QUICHE teamfd50a402018-12-07 22:54:05 -0500141 EXPECT_EQ(data, buffered);
142 EXPECT_NE(data.data(), buffered.data());
143
144 // The string is already buffered, so BufferStringIfUnbuffered should not make
145 // any change.
146 buf_.BufferStringIfUnbuffered();
147 EXPECT_EQ(backing(), Backing::BUFFERED);
148 EXPECT_EQ(buf_.BufferedLength(), data.size());
149 EXPECT_EQ(buffered, buf_.str());
150 EXPECT_EQ(buffered.data(), buf_.str().data());
151}
152
153TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
bnc47904002019-08-16 11:49:48 -0700154 std::string encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
vasilvvb16f7962020-10-13 10:48:38 -0700155 absl::string_view decoded("www.example.com");
QUICHE teamfd50a402018-12-07 22:54:05 -0500156
157 EXPECT_EQ(state(), State::RESET);
158 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
159 EXPECT_EQ(state(), State::COLLECTING);
160
161 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
162 EXPECT_EQ(state(), State::COLLECTING);
163 EXPECT_EQ(backing(), Backing::BUFFERED);
164
165 EXPECT_TRUE(buf_.OnEnd());
166 EXPECT_EQ(state(), State::COMPLETE);
167 EXPECT_EQ(backing(), Backing::BUFFERED);
168 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
169 EXPECT_EQ(decoded, buf_.str());
170 EXPECT_TRUE(VerifyLogHasSubstrs(
171 {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"}));
172
bnc47904002019-08-16 11:49:48 -0700173 std::string s = buf_.ReleaseString();
QUICHE teamfd50a402018-12-07 22:54:05 -0500174 EXPECT_EQ(s, decoded);
175 EXPECT_EQ(state(), State::RESET);
176}
177
178TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
bnc47904002019-08-16 11:49:48 -0700179 std::string encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
180 std::string part1 = encoded.substr(0, 5);
181 std::string part2 = encoded.substr(5);
vasilvvb16f7962020-10-13 10:48:38 -0700182 absl::string_view decoded("www.example.com");
QUICHE teamfd50a402018-12-07 22:54:05 -0500183
184 EXPECT_EQ(state(), State::RESET);
185 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
186 EXPECT_EQ(state(), State::COLLECTING);
187 EXPECT_EQ(backing(), Backing::BUFFERED);
188 EXPECT_EQ(0u, buf_.BufferedLength());
QUICHE team61940b42019-03-07 23:32:27 -0500189 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500190
191 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
192 EXPECT_EQ(state(), State::COLLECTING);
193 EXPECT_EQ(backing(), Backing::BUFFERED);
194 EXPECT_GT(buf_.BufferedLength(), 0u);
195 EXPECT_LT(buf_.BufferedLength(), decoded.size());
QUICHE team61940b42019-03-07 23:32:27 -0500196 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500197
198 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
199 EXPECT_EQ(state(), State::COLLECTING);
200 EXPECT_EQ(backing(), Backing::BUFFERED);
201 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
QUICHE team61940b42019-03-07 23:32:27 -0500202 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500203
204 EXPECT_TRUE(buf_.OnEnd());
205 EXPECT_EQ(state(), State::COMPLETE);
206 EXPECT_EQ(backing(), Backing::BUFFERED);
207 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
208 EXPECT_EQ(decoded, buf_.str());
QUICHE team61940b42019-03-07 23:32:27 -0500209 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500210
211 buf_.Reset();
212 EXPECT_EQ(state(), State::RESET);
QUICHE team61940b42019-03-07 23:32:27 -0500213 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500214}
215
216TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
217 // Explicitly encode the End-of-String symbol, a no-no.
bnc47904002019-08-16 11:49:48 -0700218 std::string encoded = Http2HexDecode("ffffffff");
QUICHE teamfd50a402018-12-07 22:54:05 -0500219
220 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
221 EXPECT_EQ(state(), State::COLLECTING);
222
223 EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size()));
224 EXPECT_EQ(state(), State::COLLECTING);
225 EXPECT_EQ(backing(), Backing::BUFFERED);
226
QUICHE team61940b42019-03-07 23:32:27 -0500227 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500228}
229
230TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
231 // Last byte of string doesn't end with prefix of End-of-String symbol.
bnc47904002019-08-16 11:49:48 -0700232 std::string encoded = Http2HexDecode("00");
QUICHE teamfd50a402018-12-07 22:54:05 -0500233
234 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
235 EXPECT_EQ(state(), State::COLLECTING);
236
237 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
238 EXPECT_EQ(state(), State::COLLECTING);
239 EXPECT_EQ(backing(), Backing::BUFFERED);
240
241 EXPECT_FALSE(buf_.OnEnd());
QUICHE team61940b42019-03-07 23:32:27 -0500242 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500243}
244
245// TODO(jamessynge): Add tests for ReleaseString().
246
247} // namespace
248} // namespace test
249} // namespace http2