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_entry_collector.h" | |
6 | |
7 #include <sstream> | |
8 #include <string> | |
9 | |
10 #include "base/logging.h" | |
11 #include "net/http2/hpack/decoder/hpack_string_collector.h" | |
12 #include "net/http2/hpack/http2_hpack_constants.h" | |
13 #include "net/http2/tools/failure.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 using ::testing::AssertionResult; | |
17 using std::string; | |
18 using base::StringPiece; | |
19 | |
20 namespace net { | |
21 namespace test { | |
22 namespace { | |
23 | |
24 const HpackEntryType kInvalidHeaderType = static_cast<HpackEntryType>(99); | |
25 const size_t kInvalidIndex = 99999999; | |
26 | |
27 } // namespace | |
28 | |
29 HpackEntryCollector::HpackEntryCollector() { | |
30 Clear(); | |
31 } | |
32 | |
33 HpackEntryCollector::HpackEntryCollector(const HpackEntryCollector& other) | |
34 : header_type_(other.header_type_), | |
35 index_(other.index_), | |
36 name_(other.name_), | |
37 value_(other.value_), | |
38 started_(other.started_), | |
39 ended_(other.ended_) {} | |
40 | |
41 HpackEntryCollector::HpackEntryCollector(HpackEntryType type, | |
42 size_t index_or_size) | |
43 : header_type_(type), index_(index_or_size), started_(true), ended_(true) {} | |
44 HpackEntryCollector::HpackEntryCollector(HpackEntryType type, | |
45 size_t index, | |
46 bool value_huffman, | |
47 const string& value) | |
48 : header_type_(type), | |
49 index_(index), | |
50 value_(value, value_huffman), | |
51 started_(true), | |
52 ended_(true) {} | |
53 HpackEntryCollector::HpackEntryCollector(HpackEntryType type, | |
54 bool name_huffman, | |
55 const string& name, | |
56 bool value_huffman, | |
57 const string& value) | |
58 : header_type_(type), | |
59 index_(0), | |
60 name_(name, name_huffman), | |
61 value_(value, value_huffman), | |
62 started_(true), | |
63 ended_(true) {} | |
64 | |
65 HpackEntryCollector::~HpackEntryCollector() {} | |
66 | |
67 void HpackEntryCollector::OnIndexedHeader(size_t index) { | |
68 ASSERT_FALSE(started_); | |
69 ASSERT_TRUE(IsClear()) << ToString(); | |
70 Init(HpackEntryType::kIndexedHeader, index); | |
71 ended_ = true; | |
72 } | |
73 void HpackEntryCollector::OnStartLiteralHeader(HpackEntryType header_type, | |
74 size_t maybe_name_index) { | |
75 ASSERT_FALSE(started_); | |
76 ASSERT_TRUE(IsClear()) << ToString(); | |
77 Init(header_type, maybe_name_index); | |
78 } | |
79 void HpackEntryCollector::OnNameStart(bool huffman_encoded, size_t len) { | |
80 ASSERT_TRUE(started_); | |
81 ASSERT_FALSE(ended_); | |
82 ASSERT_FALSE(IsClear()); | |
83 ASSERT_TRUE(LiteralNameExpected()) << ToString(); | |
84 name_.OnStringStart(huffman_encoded, len); | |
85 } | |
86 void HpackEntryCollector::OnNameData(const char* data, size_t len) { | |
87 ASSERT_TRUE(started_); | |
88 ASSERT_FALSE(ended_); | |
89 ASSERT_TRUE(LiteralNameExpected()) << ToString(); | |
90 ASSERT_TRUE(name_.IsInProgress()); | |
91 name_.OnStringData(data, len); | |
92 } | |
93 void HpackEntryCollector::OnNameEnd() { | |
94 ASSERT_TRUE(started_); | |
95 ASSERT_FALSE(ended_); | |
96 ASSERT_TRUE(LiteralNameExpected()) << ToString(); | |
97 ASSERT_TRUE(name_.IsInProgress()); | |
98 name_.OnStringEnd(); | |
99 } | |
100 void HpackEntryCollector::OnValueStart(bool huffman_encoded, size_t len) { | |
101 ASSERT_TRUE(started_); | |
102 ASSERT_FALSE(ended_); | |
103 if (LiteralNameExpected()) { | |
104 ASSERT_TRUE(name_.HasEnded()); | |
105 } | |
106 ASSERT_TRUE(LiteralValueExpected()) << ToString(); | |
107 ASSERT_TRUE(value_.IsClear()) << value_.ToString(); | |
108 value_.OnStringStart(huffman_encoded, len); | |
109 } | |
110 void HpackEntryCollector::OnValueData(const char* data, size_t len) { | |
111 ASSERT_TRUE(started_); | |
112 ASSERT_FALSE(ended_); | |
113 ASSERT_TRUE(LiteralValueExpected()) << ToString(); | |
114 ASSERT_TRUE(value_.IsInProgress()); | |
115 value_.OnStringData(data, len); | |
116 } | |
117 void HpackEntryCollector::OnValueEnd() { | |
118 ASSERT_TRUE(started_); | |
119 ASSERT_FALSE(ended_); | |
120 ASSERT_TRUE(LiteralValueExpected()) << ToString(); | |
121 ASSERT_TRUE(value_.IsInProgress()); | |
122 value_.OnStringEnd(); | |
123 ended_ = true; | |
124 } | |
125 void HpackEntryCollector::OnDynamicTableSizeUpdate(size_t size) { | |
126 ASSERT_FALSE(started_); | |
127 ASSERT_TRUE(IsClear()) << ToString(); | |
128 Init(HpackEntryType::kDynamicTableSizeUpdate, size); | |
129 ended_ = true; | |
130 } | |
131 | |
132 void HpackEntryCollector::Clear() { | |
133 header_type_ = kInvalidHeaderType; | |
134 index_ = kInvalidIndex; | |
135 name_.Clear(); | |
136 value_.Clear(); | |
137 started_ = ended_ = false; | |
138 } | |
139 bool HpackEntryCollector::IsClear() const { | |
140 return header_type_ == kInvalidHeaderType && index_ == kInvalidIndex && | |
141 name_.IsClear() && value_.IsClear() && !started_ && !ended_; | |
142 } | |
143 bool HpackEntryCollector::IsComplete() const { | |
144 return started_ && ended_; | |
145 } | |
146 bool HpackEntryCollector::LiteralNameExpected() const { | |
147 switch (header_type_) { | |
148 case HpackEntryType::kIndexedLiteralHeader: | |
149 case HpackEntryType::kUnindexedLiteralHeader: | |
150 case HpackEntryType::kNeverIndexedLiteralHeader: | |
151 return index_ == 0; | |
152 default: | |
153 return false; | |
154 } | |
155 } | |
156 bool HpackEntryCollector::LiteralValueExpected() const { | |
157 switch (header_type_) { | |
158 case HpackEntryType::kIndexedLiteralHeader: | |
159 case HpackEntryType::kUnindexedLiteralHeader: | |
160 case HpackEntryType::kNeverIndexedLiteralHeader: | |
161 return true; | |
162 default: | |
163 return false; | |
164 } | |
165 } | |
166 AssertionResult HpackEntryCollector::ValidateIndexedHeader( | |
167 size_t expected_index) const { | |
168 VERIFY_TRUE(started_); | |
169 VERIFY_TRUE(ended_); | |
170 VERIFY_EQ(HpackEntryType::kIndexedHeader, header_type_); | |
171 VERIFY_EQ(expected_index, index_); | |
172 return ::testing::AssertionSuccess(); | |
173 } | |
174 AssertionResult HpackEntryCollector::ValidateLiteralValueHeader( | |
175 HpackEntryType expected_type, | |
176 size_t expected_index, | |
177 bool expected_value_huffman, | |
178 StringPiece expected_value) const { | |
179 VERIFY_TRUE(started_); | |
180 VERIFY_TRUE(ended_); | |
181 VERIFY_EQ(expected_type, header_type_); | |
182 VERIFY_NE(0u, expected_index); | |
183 VERIFY_EQ(expected_index, index_); | |
184 VERIFY_TRUE(name_.IsClear()); | |
185 VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); | |
186 return ::testing::AssertionSuccess(); | |
187 } | |
188 AssertionResult HpackEntryCollector::ValidateLiteralNameValueHeader( | |
189 HpackEntryType expected_type, | |
190 bool expected_name_huffman, | |
191 StringPiece expected_name, | |
192 bool expected_value_huffman, | |
193 StringPiece expected_value) const { | |
194 VERIFY_TRUE(started_); | |
195 VERIFY_TRUE(ended_); | |
196 VERIFY_EQ(expected_type, header_type_); | |
197 VERIFY_EQ(0u, index_); | |
198 VERIFY_SUCCESS(name_.Collected(expected_name, expected_name_huffman)); | |
199 VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); | |
200 return ::testing::AssertionSuccess(); | |
201 } | |
202 AssertionResult HpackEntryCollector::ValidateDynamicTableSizeUpdate( | |
203 size_t size) const { | |
204 VERIFY_TRUE(started_); | |
205 VERIFY_TRUE(ended_); | |
206 VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, header_type_); | |
207 VERIFY_EQ(index_, size); | |
208 return ::testing::AssertionSuccess(); | |
209 } | |
210 | |
211 void HpackEntryCollector::AppendToHpackBlockBuilder( | |
212 HpackBlockBuilder* hbb) const { | |
213 ASSERT_TRUE(started_ && ended_) << *this; | |
214 switch (header_type_) { | |
215 case HpackEntryType::kIndexedHeader: | |
216 hbb->AppendIndexedHeader(index_); | |
217 return; | |
218 | |
219 case HpackEntryType::kDynamicTableSizeUpdate: | |
220 hbb->AppendDynamicTableSizeUpdate(index_); | |
221 return; | |
222 | |
223 case HpackEntryType::kIndexedLiteralHeader: | |
224 case HpackEntryType::kUnindexedLiteralHeader: | |
225 case HpackEntryType::kNeverIndexedLiteralHeader: | |
226 ASSERT_TRUE(value_.HasEnded()) << *this; | |
227 if (index_ != 0) { | |
228 CHECK(name_.IsClear()); | |
229 hbb->AppendNameIndexAndLiteralValue(header_type_, index_, | |
230 value_.huffman_encoded, value_.s); | |
231 } else { | |
232 CHECK(name_.HasEnded()) << *this; | |
233 hbb->AppendLiteralNameAndValue(header_type_, name_.huffman_encoded, | |
234 name_.s, value_.huffman_encoded, | |
235 value_.s); | |
236 } | |
237 return; | |
238 | |
239 default: | |
240 ADD_FAILURE() << *this; | |
241 } | |
242 } | |
243 | |
244 string HpackEntryCollector::ToString() const { | |
245 string result("Type="); | |
246 switch (header_type_) { | |
247 case HpackEntryType::kIndexedHeader: | |
248 result += "IndexedHeader"; | |
249 break; | |
250 case HpackEntryType::kDynamicTableSizeUpdate: | |
251 result += "DynamicTableSizeUpdate"; | |
252 break; | |
253 case HpackEntryType::kIndexedLiteralHeader: | |
254 result += "IndexedLiteralHeader"; | |
255 break; | |
256 case HpackEntryType::kUnindexedLiteralHeader: | |
257 result += "UnindexedLiteralHeader"; | |
258 break; | |
259 case HpackEntryType::kNeverIndexedLiteralHeader: | |
260 result += "NeverIndexedLiteralHeader"; | |
261 break; | |
262 default: | |
263 if (header_type_ == kInvalidHeaderType) { | |
264 result += "<unset>"; | |
265 } else { | |
266 std::stringstream ss; | |
267 ss << header_type_; | |
268 result.append(ss.str()); | |
269 } | |
270 } | |
271 if (index_ != 0) { | |
272 result.append(" Index="); | |
273 std::stringstream ss; | |
274 ss << index_; | |
275 result.append(ss.str()); | |
276 } | |
277 if (!name_.IsClear()) { | |
278 result.append(" Name"); | |
279 result.append(name_.ToString()); | |
280 } | |
281 if (!value_.IsClear()) { | |
282 result.append(" Value"); | |
283 result.append(value_.ToString()); | |
284 } | |
285 if (!started_) { | |
286 EXPECT_FALSE(ended_); | |
287 result.append(" !started"); | |
288 } else if (!ended_) { | |
289 result.append(" !ended"); | |
290 } else { | |
291 result.append(" Complete"); | |
292 } | |
293 return result; | |
294 } | |
295 | |
296 void HpackEntryCollector::Init(HpackEntryType type, size_t maybe_index) { | |
297 ASSERT_TRUE(IsClear()) << ToString(); | |
298 header_type_ = type; | |
299 index_ = maybe_index; | |
300 started_ = true; | |
301 } | |
302 | |
303 bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b) { | |
304 return a.name() == b.name() && a.value() == b.value() && | |
305 a.index() == b.index() && a.header_type() == b.header_type() && | |
306 a.started() == b.started() && a.ended() == b.ended(); | |
307 } | |
308 bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b) { | |
309 return !(a == b); | |
310 } | |
311 | |
312 std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v) { | |
313 return out << v.ToString(); | |
314 } | |
315 | |
316 } // namespace test | |
317 } // namespace net | |
OLD | NEW |