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