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