blob: 11b0d9773bb32bc7f0649e5a86820125b7e1a5ad [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
5#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h"
6
7// Tests of HpackDecoderStringBuffer.
8
9#include <initializer_list>
10
QUICHE teamfd50a402018-12-07 22:54:05 -050011#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
QUICHE team61940b42019-03-07 23:32:27 -050013#include "net/third_party/quiche/src/http2/platform/api/http2_logging.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050014#include "net/third_party/quiche/src/http2/platform/api/http2_string.h"
15#include "net/third_party/quiche/src/http2/platform/api/http2_string_utils.h"
16#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
17
18using ::testing::AssertionResult;
19using ::testing::AssertionSuccess;
20using ::testing::HasSubstr;
21
22namespace http2 {
23namespace test {
24namespace {
25
26class HpackDecoderStringBufferTest : public ::testing::Test {
27 protected:
28 typedef HpackDecoderStringBuffer::State State;
29 typedef HpackDecoderStringBuffer::Backing Backing;
30
31 State state() const { return buf_.state_for_testing(); }
32 Backing backing() const { return buf_.backing_for_testing(); }
33
QUICHE team61940b42019-03-07 23:32:27 -050034 // We want to know that HTTP2_LOG(x) << buf_ will work in production should
35 // that be needed, so we test that it outputs the expected values.
QUICHE teamfd50a402018-12-07 22:54:05 -050036 AssertionResult VerifyLogHasSubstrs(std::initializer_list<Http2String> strs) {
QUICHE team61940b42019-03-07 23:32:27 -050037 HTTP2_VLOG(1) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050038 std::ostringstream ss;
39 buf_.OutputDebugStringTo(ss);
40 Http2String dbg_str(ss.str());
41 for (const auto& expected : strs) {
42 VERIFY_THAT(dbg_str, HasSubstr(expected));
43 }
44 return AssertionSuccess();
45 }
46
47 HpackDecoderStringBuffer buf_;
48};
49
50TEST_F(HpackDecoderStringBufferTest, SetStatic) {
51 Http2StringPiece data("static string");
52
53 EXPECT_EQ(state(), State::RESET);
54 EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"}));
55
56 buf_.Set(data, /*is_static*/ true);
QUICHE team61940b42019-03-07 23:32:27 -050057 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050058 EXPECT_EQ(state(), State::COMPLETE);
59 EXPECT_EQ(backing(), Backing::STATIC);
60 EXPECT_EQ(data, buf_.str());
61 EXPECT_EQ(data.data(), buf_.str().data());
62 EXPECT_TRUE(VerifyLogHasSubstrs(
63 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
64
65 // The string is static, so BufferStringIfUnbuffered won't change anything.
66 buf_.BufferStringIfUnbuffered();
67 EXPECT_EQ(state(), State::COMPLETE);
68 EXPECT_EQ(backing(), Backing::STATIC);
69 EXPECT_EQ(data, buf_.str());
70 EXPECT_EQ(data.data(), buf_.str().data());
71 EXPECT_TRUE(VerifyLogHasSubstrs(
72 {"state=COMPLETE", "backing=STATIC", "value: static string"}));
73}
74
75TEST_F(HpackDecoderStringBufferTest, PlainWhole) {
76 Http2StringPiece data("some text.");
77
QUICHE team61940b42019-03-07 23:32:27 -050078 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050079 EXPECT_EQ(state(), State::RESET);
80
81 buf_.OnStart(/*huffman_encoded*/ false, data.size());
82 EXPECT_EQ(state(), State::COLLECTING);
83 EXPECT_EQ(backing(), Backing::RESET);
QUICHE team61940b42019-03-07 23:32:27 -050084 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -050085
86 EXPECT_TRUE(buf_.OnData(data.data(), data.size()));
87 EXPECT_EQ(state(), State::COLLECTING);
88 EXPECT_EQ(backing(), Backing::UNBUFFERED);
89
90 EXPECT_TRUE(buf_.OnEnd());
91 EXPECT_EQ(state(), State::COMPLETE);
92 EXPECT_EQ(backing(), Backing::UNBUFFERED);
93 EXPECT_EQ(0u, buf_.BufferedLength());
94 EXPECT_TRUE(VerifyLogHasSubstrs(
95 {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."}));
96
97 // We expect that the string buffer points to the passed in Http2StringPiece's
98 // backing store.
99 EXPECT_EQ(data.data(), buf_.str().data());
100
101 // Now force it to buffer the string, after which it will still have the same
102 // string value, but the backing store will be different.
103 buf_.BufferStringIfUnbuffered();
QUICHE team61940b42019-03-07 23:32:27 -0500104 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500105 EXPECT_EQ(backing(), Backing::BUFFERED);
106 EXPECT_EQ(buf_.BufferedLength(), data.size());
107 EXPECT_EQ(data, buf_.str());
108 EXPECT_NE(data.data(), buf_.str().data());
109 EXPECT_TRUE(VerifyLogHasSubstrs(
110 {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."}));
111}
112
113TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
114 Http2StringPiece data("some text.");
115 Http2StringPiece part1 = data.substr(0, 1);
116 Http2StringPiece part2 = data.substr(1);
117
118 EXPECT_EQ(state(), State::RESET);
119 buf_.OnStart(/*huffman_encoded*/ false, data.size());
120 EXPECT_EQ(state(), State::COLLECTING);
121 EXPECT_EQ(backing(), Backing::RESET);
122
123 // OnData with only a part of the data, not the whole, so buf_ will buffer
124 // the data.
125 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
126 EXPECT_EQ(state(), State::COLLECTING);
127 EXPECT_EQ(backing(), Backing::BUFFERED);
128 EXPECT_EQ(buf_.BufferedLength(), part1.size());
QUICHE team61940b42019-03-07 23:32:27 -0500129 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500130
131 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
132 EXPECT_EQ(state(), State::COLLECTING);
133 EXPECT_EQ(backing(), Backing::BUFFERED);
134 EXPECT_EQ(buf_.BufferedLength(), data.size());
135
136 EXPECT_TRUE(buf_.OnEnd());
137 EXPECT_EQ(state(), State::COMPLETE);
138 EXPECT_EQ(backing(), Backing::BUFFERED);
139 EXPECT_EQ(buf_.BufferedLength(), data.size());
QUICHE team61940b42019-03-07 23:32:27 -0500140 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500141
142 Http2StringPiece buffered = buf_.str();
143 EXPECT_EQ(data, buffered);
144 EXPECT_NE(data.data(), buffered.data());
145
146 // The string is already buffered, so BufferStringIfUnbuffered should not make
147 // any change.
148 buf_.BufferStringIfUnbuffered();
149 EXPECT_EQ(backing(), Backing::BUFFERED);
150 EXPECT_EQ(buf_.BufferedLength(), data.size());
151 EXPECT_EQ(buffered, buf_.str());
152 EXPECT_EQ(buffered.data(), buf_.str().data());
153}
154
155TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
156 Http2String encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
157 Http2StringPiece decoded("www.example.com");
158
159 EXPECT_EQ(state(), State::RESET);
160 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
161 EXPECT_EQ(state(), State::COLLECTING);
162
163 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
164 EXPECT_EQ(state(), State::COLLECTING);
165 EXPECT_EQ(backing(), Backing::BUFFERED);
166
167 EXPECT_TRUE(buf_.OnEnd());
168 EXPECT_EQ(state(), State::COMPLETE);
169 EXPECT_EQ(backing(), Backing::BUFFERED);
170 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
171 EXPECT_EQ(decoded, buf_.str());
172 EXPECT_TRUE(VerifyLogHasSubstrs(
173 {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"}));
174
175 Http2String s = buf_.ReleaseString();
176 EXPECT_EQ(s, decoded);
177 EXPECT_EQ(state(), State::RESET);
178}
179
180TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
181 Http2String encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
182 Http2String part1 = encoded.substr(0, 5);
183 Http2String part2 = encoded.substr(5);
184 Http2StringPiece decoded("www.example.com");
185
186 EXPECT_EQ(state(), State::RESET);
187 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
188 EXPECT_EQ(state(), State::COLLECTING);
189 EXPECT_EQ(backing(), Backing::BUFFERED);
190 EXPECT_EQ(0u, buf_.BufferedLength());
QUICHE team61940b42019-03-07 23:32:27 -0500191 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500192
193 EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
194 EXPECT_EQ(state(), State::COLLECTING);
195 EXPECT_EQ(backing(), Backing::BUFFERED);
196 EXPECT_GT(buf_.BufferedLength(), 0u);
197 EXPECT_LT(buf_.BufferedLength(), decoded.size());
QUICHE team61940b42019-03-07 23:32:27 -0500198 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500199
200 EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
201 EXPECT_EQ(state(), State::COLLECTING);
202 EXPECT_EQ(backing(), Backing::BUFFERED);
203 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
QUICHE team61940b42019-03-07 23:32:27 -0500204 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500205
206 EXPECT_TRUE(buf_.OnEnd());
207 EXPECT_EQ(state(), State::COMPLETE);
208 EXPECT_EQ(backing(), Backing::BUFFERED);
209 EXPECT_EQ(buf_.BufferedLength(), decoded.size());
210 EXPECT_EQ(decoded, buf_.str());
QUICHE team61940b42019-03-07 23:32:27 -0500211 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500212
213 buf_.Reset();
214 EXPECT_EQ(state(), State::RESET);
QUICHE team61940b42019-03-07 23:32:27 -0500215 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500216}
217
218TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
219 // Explicitly encode the End-of-String symbol, a no-no.
220 Http2String encoded = Http2HexDecode("ffffffff");
221
222 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
223 EXPECT_EQ(state(), State::COLLECTING);
224
225 EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size()));
226 EXPECT_EQ(state(), State::COLLECTING);
227 EXPECT_EQ(backing(), Backing::BUFFERED);
228
QUICHE team61940b42019-03-07 23:32:27 -0500229 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500230}
231
232TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
233 // Last byte of string doesn't end with prefix of End-of-String symbol.
234 Http2String encoded = Http2HexDecode("00");
235
236 buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
237 EXPECT_EQ(state(), State::COLLECTING);
238
239 EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
240 EXPECT_EQ(state(), State::COLLECTING);
241 EXPECT_EQ(backing(), Backing::BUFFERED);
242
243 EXPECT_FALSE(buf_.OnEnd());
QUICHE team61940b42019-03-07 23:32:27 -0500244 HTTP2_LOG(INFO) << buf_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500245}
246
247// TODO(jamessynge): Add tests for ReleaseString().
248
249} // namespace
250} // namespace test
251} // namespace http2