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