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 |