1 // 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
5 #include "quiche/http2/hpack/decoder/hpack_decoder_string_buffer.h"
6
7 // Tests of HpackDecoderStringBuffer.
8
9 #include <initializer_list>
10
11 #include "absl/strings/escaping.h"
12 #include "absl/strings/match.h"
13 #include "quiche/http2/test_tools/verify_macros.h"
14 #include "quiche/common/platform/api/quiche_logging.h"
15 #include "quiche/common/platform/api/quiche_test.h"
16
17 using ::testing::AssertionResult;
18 using ::testing::AssertionSuccess;
19 using ::testing::HasSubstr;
20
21 namespace http2 {
22 namespace test {
23 namespace {
24
25 class HpackDecoderStringBufferTest : public quiche::test::QuicheTest {
26 protected:
27 typedef HpackDecoderStringBuffer::State State;
28 typedef HpackDecoderStringBuffer::Backing Backing;
29
state() const30 State state() const { return buf_.state_for_testing(); }
backing() const31 Backing backing() const { return buf_.backing_for_testing(); }
32
33 // We want to know that QUICHE_LOG(x) << buf_ will work in production should
34 // that be needed, so we test that it outputs the expected values.
VerifyLogHasSubstrs(std::initializer_list<std::string> strs)35 AssertionResult VerifyLogHasSubstrs(std::initializer_list<std::string> strs) {
36 QUICHE_VLOG(1) << buf_;
37 std::ostringstream ss;
38 buf_.OutputDebugStringTo(ss);
39 std::string dbg_str(ss.str());
40 for (const auto& expected : strs) {
41 HTTP2_VERIFY_TRUE(absl::StrContains(dbg_str, expected));
42 }
43 return AssertionSuccess();
44 }
45
46 HpackDecoderStringBuffer buf_;
47 };
48
TEST_F(HpackDecoderStringBufferTest,SetStatic)49 TEST_F(HpackDecoderStringBufferTest, SetStatic) {
50 absl::string_view data("static string");
51
52 EXPECT_EQ(state(), State::RESET);
53 EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"}));
54
55 buf_.Set(data, /*is_static*/ true);
56 QUICHE_LOG(INFO) << buf_;
57 EXPECT_EQ(state(), State::COMPLETE);
58 EXPECT_EQ(backing(), Backing::STATIC);
59 EXPECT_EQ(data, buf_.str());
60 EXPECT_EQ(data.data(), buf_.str().data());
61 EXPECT_TRUE(VerifyLogHasSubstrs(
62 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
63
64 // The string is static, so BufferStringIfUnbuffered won't change anything.
65 buf_.BufferStringIfUnbuffered();
66 EXPECT_EQ(state(), State::COMPLETE);
67 EXPECT_EQ(backing(), Backing::STATIC);
68 EXPECT_EQ(data, buf_.str());
69 EXPECT_EQ(data.data(), buf_.str().data());
70 EXPECT_TRUE(VerifyLogHasSubstrs(
71 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
72 }
73
TEST_F(HpackDecoderStringBufferTest,PlainWhole)74 TEST_F(HpackDecoderStringBufferTest, PlainWhole) {
75 absl::string_view data("some text.");
76
77 QUICHE_LOG(INFO) << buf_;
78 EXPECT_EQ(state(), State::RESET);
79
80 buf_.OnStart(/*huffman_encoded*/ false, data.size());
81 EXPECT_EQ(state(), State::COLLECTING);
82 EXPECT_EQ(backing(), Backing::RESET);
83 QUICHE_LOG(INFO) << buf_;
84
85 EXPECT_TRUE(buf_.OnData(data.data(), data.size()));
86 EXPECT_EQ(state(), State::COLLECTING);
87 EXPECT_EQ(backing(), Backing::UNBUFFERED);
88
89 EXPECT_TRUE(buf_.OnEnd());
90 EXPECT_EQ(state(), State::COMPLETE);
91 EXPECT_EQ(backing(), Backing::UNBUFFERED);
92 EXPECT_EQ(0u, buf_.BufferedLength());
93 EXPECT_TRUE(VerifyLogHasSubstrs(
94 {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."}));
95
96 // We expect that the string buffer points to the passed in
97 // string_view's backing store.
98 EXPECT_EQ(data.data(), buf_.str().data());
99
100 // Now force it to buffer the string, after which it will still have the same
101 // string value, but the backing store will be different.
102 buf_.BufferStringIfUnbuffered();
103 QUICHE_LOG(INFO) << buf_;
104 EXPECT_EQ(backing(), Backing::BUFFERED);
105 EXPECT_EQ(buf_.BufferedLength(), data.size());
106 EXPECT_EQ(data, buf_.str());
107 EXPECT_NE(data.data(), buf_.str().data());
108 EXPECT_TRUE(VerifyLogHasSubstrs(
109 {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."}));
110 }
111
TEST_F(HpackDecoderStringBufferTest,PlainSplit)112 TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
113 absl::string_view data("some text.");
114 absl::string_view part1 = data.substr(0, 1);
115 absl::string_view part2 = data.substr(1);
116
117 EXPECT_EQ(state(), State::RESET);
118 buf_.OnStart(/*huffman_encoded*/ false, data.size());
119 EXPECT_EQ(state(), State::COLLECTING);
120 EXPECT_EQ(backing(), Backing::RESET);
121
122 // OnData with only a part of the data, not the whole, so buf_ will buffer
123 // the data.
124 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
125 EXPECT_EQ(state(), State::COLLECTING);
126 EXPECT_EQ(backing(), Backing::BUFFERED);
127 EXPECT_EQ(buf_.BufferedLength(), part1.size());
128 QUICHE_LOG(INFO) << buf_;
129
130 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
131 EXPECT_EQ(state(), State::COLLECTING);
132 EXPECT_EQ(backing(), Backing::BUFFERED);
133 EXPECT_EQ(buf_.BufferedLength(), data.size());
134
135 EXPECT_TRUE(buf_.OnEnd());
136 EXPECT_EQ(state(), State::COMPLETE);
137 EXPECT_EQ(backing(), Backing::BUFFERED);
138 EXPECT_EQ(buf_.BufferedLength(), data.size());
139 QUICHE_LOG(INFO) << buf_;
140
141 absl::string_view buffered = buf_.str();
142 EXPECT_EQ(data, buffered);
143 EXPECT_NE(data.data(), buffered.data());
144
145 // The string is already buffered, so BufferStringIfUnbuffered should not make
146 // any change.
147 buf_.BufferStringIfUnbuffered();
148 EXPECT_EQ(backing(), Backing::BUFFERED);
149 EXPECT_EQ(buf_.BufferedLength(), data.size());
150 EXPECT_EQ(buffered, buf_.str());
151 EXPECT_EQ(buffered.data(), buf_.str().data());
152 }
153
TEST_F(HpackDecoderStringBufferTest,HuffmanWhole)154 TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
155 std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff");
156 absl::string_view decoded("www.example.com");
157
158 EXPECT_EQ(state(), State::RESET);
159 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
160 EXPECT_EQ(state(), State::COLLECTING);
161
162 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
163 EXPECT_EQ(state(), State::COLLECTING);
164 EXPECT_EQ(backing(), Backing::BUFFERED);
165
166 EXPECT_TRUE(buf_.OnEnd());
167 EXPECT_EQ(state(), State::COMPLETE);
168 EXPECT_EQ(backing(), Backing::BUFFERED);
169 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
170 EXPECT_EQ(decoded, buf_.str());
171 EXPECT_TRUE(VerifyLogHasSubstrs(
172 {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"}));
173
174 std::string s = buf_.ReleaseString();
175 EXPECT_EQ(s, decoded);
176 EXPECT_EQ(state(), State::RESET);
177 }
178
TEST_F(HpackDecoderStringBufferTest,HuffmanSplit)179 TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
180 std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff");
181 std::string part1 = encoded.substr(0, 5);
182 std::string part2 = encoded.substr(5);
183 absl::string_view decoded("www.example.com");
184
185 EXPECT_EQ(state(), State::RESET);
186 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
187 EXPECT_EQ(state(), State::COLLECTING);
188 EXPECT_EQ(backing(), Backing::BUFFERED);
189 EXPECT_EQ(0u, buf_.BufferedLength());
190 QUICHE_LOG(INFO) << buf_;
191
192 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
193 EXPECT_EQ(state(), State::COLLECTING);
194 EXPECT_EQ(backing(), Backing::BUFFERED);
195 EXPECT_GT(buf_.BufferedLength(), 0u);
196 EXPECT_LT(buf_.BufferedLength(), decoded.size());
197 QUICHE_LOG(INFO) << buf_;
198
199 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
200 EXPECT_EQ(state(), State::COLLECTING);
201 EXPECT_EQ(backing(), Backing::BUFFERED);
202 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
203 QUICHE_LOG(INFO) << buf_;
204
205 EXPECT_TRUE(buf_.OnEnd());
206 EXPECT_EQ(state(), State::COMPLETE);
207 EXPECT_EQ(backing(), Backing::BUFFERED);
208 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
209 EXPECT_EQ(decoded, buf_.str());
210 QUICHE_LOG(INFO) << buf_;
211
212 buf_.Reset();
213 EXPECT_EQ(state(), State::RESET);
214 QUICHE_LOG(INFO) << buf_;
215 }
216
TEST_F(HpackDecoderStringBufferTest,InvalidHuffmanOnData)217 TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
218 // Explicitly encode the End-of-String symbol, a no-no.
219 std::string encoded = absl::HexStringToBytes("ffffffff");
220
221 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
222 EXPECT_EQ(state(), State::COLLECTING);
223
224 EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size()));
225 EXPECT_EQ(state(), State::COLLECTING);
226 EXPECT_EQ(backing(), Backing::BUFFERED);
227
228 QUICHE_LOG(INFO) << buf_;
229 }
230
TEST_F(HpackDecoderStringBufferTest,InvalidHuffmanOnEnd)231 TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
232 // Last byte of string doesn't end with prefix of End-of-String symbol.
233 std::string encoded = absl::HexStringToBytes("00");
234
235 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
236 EXPECT_EQ(state(), State::COLLECTING);
237
238 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
239 EXPECT_EQ(state(), State::COLLECTING);
240 EXPECT_EQ(backing(), Backing::BUFFERED);
241
242 EXPECT_FALSE(buf_.OnEnd());
243 QUICHE_LOG(INFO) << buf_;
244 }
245
246 // TODO(jamessynge): Add tests for ReleaseString().
247
248 } // namespace
249 } // namespace test
250 } // namespace http2
251