| 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 |