• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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