| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015 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/spdy/spdy_alt_svc_wire_format.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "testing/gmock/include/gmock/gmock.h" | |
| 9 #include "testing/platform_test.h" | |
| 10 | |
| 11 using ::testing::_; | |
| 12 | |
| 13 namespace net { | |
| 14 | |
| 15 namespace test { | |
| 16 | |
| 17 // Expose all private methods of class SpdyAltSvcWireFormat. | |
| 18 class SpdyAltSvcWireFormatPeer { | |
| 19 public: | |
| 20 static void SkipWhiteSpace(SpdyStringPiece::const_iterator* c, | |
| 21 SpdyStringPiece::const_iterator end) { | |
| 22 SpdyAltSvcWireFormat::SkipWhiteSpace(c, end); | |
| 23 } | |
| 24 static bool PercentDecode(SpdyStringPiece::const_iterator c, | |
| 25 SpdyStringPiece::const_iterator end, | |
| 26 SpdyString* output) { | |
| 27 return SpdyAltSvcWireFormat::PercentDecode(c, end, output); | |
| 28 } | |
| 29 static bool ParseAltAuthority(SpdyStringPiece::const_iterator c, | |
| 30 SpdyStringPiece::const_iterator end, | |
| 31 SpdyString* host, | |
| 32 uint16_t* port) { | |
| 33 return SpdyAltSvcWireFormat::ParseAltAuthority(c, end, host, port); | |
| 34 } | |
| 35 static bool ParsePositiveInteger16(SpdyStringPiece::const_iterator c, | |
| 36 SpdyStringPiece::const_iterator end, | |
| 37 uint16_t* max_age) { | |
| 38 return SpdyAltSvcWireFormat::ParsePositiveInteger16(c, end, max_age); | |
| 39 } | |
| 40 static bool ParsePositiveInteger32(SpdyStringPiece::const_iterator c, | |
| 41 SpdyStringPiece::const_iterator end, | |
| 42 uint32_t* max_age) { | |
| 43 return SpdyAltSvcWireFormat::ParsePositiveInteger32(c, end, max_age); | |
| 44 } | |
| 45 }; | |
| 46 | |
| 47 } // namespace test | |
| 48 | |
| 49 namespace { | |
| 50 | |
| 51 // Generate header field values, possibly with multiply defined parameters and | |
| 52 // random case, and corresponding AlternativeService entries. | |
| 53 void FuzzHeaderFieldValue( | |
| 54 int i, | |
| 55 SpdyString* header_field_value, | |
| 56 SpdyAltSvcWireFormat::AlternativeService* expected_altsvc) { | |
| 57 if (!header_field_value->empty()) { | |
| 58 header_field_value->push_back(','); | |
| 59 } | |
| 60 expected_altsvc->protocol_id = "a=b%c"; | |
| 61 header_field_value->append("a%3Db%25c=\""); | |
| 62 expected_altsvc->host = ""; | |
| 63 if (i & 1 << 0) { | |
| 64 expected_altsvc->host = "foo\"bar\\baz"; | |
| 65 header_field_value->append("foo\\\"bar\\\\baz"); | |
| 66 } | |
| 67 expected_altsvc->port = 42; | |
| 68 header_field_value->append(":42\""); | |
| 69 if (i & 1 << 1) { | |
| 70 header_field_value->append(" "); | |
| 71 } | |
| 72 if (i & 3 << 2) { | |
| 73 expected_altsvc->max_age = 1111; | |
| 74 header_field_value->append(";"); | |
| 75 if (i & 1 << 2) { | |
| 76 header_field_value->append(" "); | |
| 77 } | |
| 78 header_field_value->append("mA=1111"); | |
| 79 if (i & 2 << 2) { | |
| 80 header_field_value->append(" "); | |
| 81 } | |
| 82 } | |
| 83 if (i & 1 << 4) { | |
| 84 header_field_value->append("; J=s"); | |
| 85 } | |
| 86 if (i & 1 << 5) { | |
| 87 expected_altsvc->version.push_back(24); | |
| 88 header_field_value->append("; v=\"24\""); | |
| 89 } | |
| 90 if (i & 1 << 6) { | |
| 91 expected_altsvc->max_age = 999999999; | |
| 92 header_field_value->append("; Ma=999999999"); | |
| 93 } | |
| 94 if (i & 1 << 7) { | |
| 95 header_field_value->append(";"); | |
| 96 } | |
| 97 if (i & 1 << 8) { | |
| 98 header_field_value->append(" "); | |
| 99 } | |
| 100 if (i & 1 << 9) { | |
| 101 header_field_value->append(","); | |
| 102 } | |
| 103 if (i & 1 << 10) { | |
| 104 header_field_value->append(" "); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 // Generate AlternativeService entries and corresponding header field values in | |
| 109 // canonical form, that is, what SerializeHeaderFieldValue() should output. | |
| 110 void FuzzAlternativeService(int i, | |
| 111 SpdyAltSvcWireFormat::AlternativeService* altsvc, | |
| 112 SpdyString* expected_header_field_value) { | |
| 113 if (!expected_header_field_value->empty()) { | |
| 114 expected_header_field_value->push_back(','); | |
| 115 } | |
| 116 altsvc->protocol_id = "a=b%c"; | |
| 117 altsvc->port = 42; | |
| 118 expected_header_field_value->append("a%3Db%25c=\""); | |
| 119 if (i & 1 << 0) { | |
| 120 altsvc->host = "foo\"bar\\baz"; | |
| 121 expected_header_field_value->append("foo\\\"bar\\\\baz"); | |
| 122 } | |
| 123 expected_header_field_value->append(":42\""); | |
| 124 if (i & 1 << 1) { | |
| 125 altsvc->max_age = 1111; | |
| 126 expected_header_field_value->append("; ma=1111"); | |
| 127 } | |
| 128 if (i & 1 << 2) { | |
| 129 altsvc->version.push_back(24); | |
| 130 altsvc->version.push_back(25); | |
| 131 expected_header_field_value->append("; v=\"24,25\""); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 class SpdyAltSvcWireFormatTest : public ::testing::Test {}; | |
| 136 | |
| 137 // Tests of public API. | |
| 138 | |
| 139 TEST(SpdyAltSvcWireFormatTest, DefaultValues) { | |
| 140 SpdyAltSvcWireFormat::AlternativeService altsvc; | |
| 141 EXPECT_EQ("", altsvc.protocol_id); | |
| 142 EXPECT_EQ("", altsvc.host); | |
| 143 EXPECT_EQ(0u, altsvc.port); | |
| 144 EXPECT_EQ(86400u, altsvc.max_age); | |
| 145 EXPECT_TRUE(altsvc.version.empty()); | |
| 146 } | |
| 147 | |
| 148 TEST(SpdyAltSvcWireFormatTest, ParseInvalidEmptyHeaderFieldValue) { | |
| 149 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 150 ASSERT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue("", &altsvc_vector)); | |
| 151 } | |
| 152 | |
| 153 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueClear) { | |
| 154 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 155 ASSERT_TRUE( | |
| 156 SpdyAltSvcWireFormat::ParseHeaderFieldValue("clear", &altsvc_vector)); | |
| 157 EXPECT_EQ(0u, altsvc_vector.size()); | |
| 158 } | |
| 159 | |
| 160 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored | |
| 161 // parameters, duplicate parameters, trailing space, trailing alternate service | |
| 162 // separator, etc. Single alternative service at a time. | |
| 163 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValue) { | |
| 164 for (int i = 0; i < 1 << 11; ++i) { | |
| 165 SpdyString header_field_value; | |
| 166 SpdyAltSvcWireFormat::AlternativeService expected_altsvc; | |
| 167 FuzzHeaderFieldValue(i, &header_field_value, &expected_altsvc); | |
| 168 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 169 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value, | |
| 170 &altsvc_vector)); | |
| 171 ASSERT_EQ(1u, altsvc_vector.size()); | |
| 172 EXPECT_EQ(expected_altsvc.protocol_id, altsvc_vector[0].protocol_id); | |
| 173 EXPECT_EQ(expected_altsvc.host, altsvc_vector[0].host); | |
| 174 EXPECT_EQ(expected_altsvc.port, altsvc_vector[0].port); | |
| 175 EXPECT_EQ(expected_altsvc.max_age, altsvc_vector[0].max_age); | |
| 176 EXPECT_EQ(expected_altsvc.version, altsvc_vector[0].version); | |
| 177 | |
| 178 // Roundtrip test starting with |altsvc_vector|. | |
| 179 SpdyString reserialized_header_field_value = | |
| 180 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector); | |
| 181 SpdyAltSvcWireFormat::AlternativeServiceVector roundtrip_altsvc_vector; | |
| 182 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 183 reserialized_header_field_value, &roundtrip_altsvc_vector)); | |
| 184 ASSERT_EQ(1u, roundtrip_altsvc_vector.size()); | |
| 185 EXPECT_EQ(expected_altsvc.protocol_id, | |
| 186 roundtrip_altsvc_vector[0].protocol_id); | |
| 187 EXPECT_EQ(expected_altsvc.host, roundtrip_altsvc_vector[0].host); | |
| 188 EXPECT_EQ(expected_altsvc.port, roundtrip_altsvc_vector[0].port); | |
| 189 EXPECT_EQ(expected_altsvc.max_age, roundtrip_altsvc_vector[0].max_age); | |
| 190 EXPECT_EQ(expected_altsvc.version, roundtrip_altsvc_vector[0].version); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored | |
| 195 // parameters, duplicate parameters, trailing space, trailing alternate service | |
| 196 // separator, etc. Possibly multiple alternative service at a time. | |
| 197 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueMultiple) { | |
| 198 for (int i = 0; i < 1 << 11;) { | |
| 199 SpdyString header_field_value; | |
| 200 SpdyAltSvcWireFormat::AlternativeServiceVector expected_altsvc_vector; | |
| 201 // This will generate almost two hundred header field values with two, | |
| 202 // three, four, five, six, and seven alternative services each, and | |
| 203 // thousands with a single one. | |
| 204 do { | |
| 205 SpdyAltSvcWireFormat::AlternativeService expected_altsvc; | |
| 206 FuzzHeaderFieldValue(i, &header_field_value, &expected_altsvc); | |
| 207 expected_altsvc_vector.push_back(expected_altsvc); | |
| 208 ++i; | |
| 209 } while ((i < 1 << 13) && (i % 6 < i % 7)); | |
| 210 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 211 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value, | |
| 212 &altsvc_vector)); | |
| 213 ASSERT_EQ(expected_altsvc_vector.size(), altsvc_vector.size()); | |
| 214 for (unsigned int j = 0; j < altsvc_vector.size(); ++j) { | |
| 215 EXPECT_EQ(expected_altsvc_vector[j].protocol_id, | |
| 216 altsvc_vector[j].protocol_id); | |
| 217 EXPECT_EQ(expected_altsvc_vector[j].host, altsvc_vector[j].host); | |
| 218 EXPECT_EQ(expected_altsvc_vector[j].port, altsvc_vector[j].port); | |
| 219 EXPECT_EQ(expected_altsvc_vector[j].max_age, altsvc_vector[j].max_age); | |
| 220 EXPECT_EQ(expected_altsvc_vector[j].version, altsvc_vector[j].version); | |
| 221 } | |
| 222 | |
| 223 // Roundtrip test starting with |altsvc_vector|. | |
| 224 SpdyString reserialized_header_field_value = | |
| 225 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector); | |
| 226 SpdyAltSvcWireFormat::AlternativeServiceVector roundtrip_altsvc_vector; | |
| 227 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 228 reserialized_header_field_value, &roundtrip_altsvc_vector)); | |
| 229 ASSERT_EQ(expected_altsvc_vector.size(), roundtrip_altsvc_vector.size()); | |
| 230 for (unsigned int j = 0; j < roundtrip_altsvc_vector.size(); ++j) { | |
| 231 EXPECT_EQ(expected_altsvc_vector[j].protocol_id, | |
| 232 roundtrip_altsvc_vector[j].protocol_id); | |
| 233 EXPECT_EQ(expected_altsvc_vector[j].host, | |
| 234 roundtrip_altsvc_vector[j].host); | |
| 235 EXPECT_EQ(expected_altsvc_vector[j].port, | |
| 236 roundtrip_altsvc_vector[j].port); | |
| 237 EXPECT_EQ(expected_altsvc_vector[j].max_age, | |
| 238 roundtrip_altsvc_vector[j].max_age); | |
| 239 EXPECT_EQ(expected_altsvc_vector[j].version, | |
| 240 roundtrip_altsvc_vector[j].version); | |
| 241 } | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 TEST(SpdyAltSvcWireFormatTest, SerializeEmptyHeaderFieldValue) { | |
| 246 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 247 EXPECT_EQ("clear", | |
| 248 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector)); | |
| 249 } | |
| 250 | |
| 251 // Test ParseHeaderFieldValue() and SerializeHeaderFieldValue() on the same pair | |
| 252 // of |expected_header_field_value| and |altsvc|, with and without hostname and | |
| 253 // each | |
| 254 // parameter. Single alternative service at a time. | |
| 255 TEST(SpdyAltSvcWireFormatTest, RoundTrip) { | |
| 256 for (int i = 0; i < 1 << 3; ++i) { | |
| 257 SpdyAltSvcWireFormat::AlternativeService altsvc; | |
| 258 SpdyString expected_header_field_value; | |
| 259 FuzzAlternativeService(i, &altsvc, &expected_header_field_value); | |
| 260 | |
| 261 // Test ParseHeaderFieldValue(). | |
| 262 SpdyAltSvcWireFormat::AlternativeServiceVector parsed_altsvc_vector; | |
| 263 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 264 expected_header_field_value, &parsed_altsvc_vector)); | |
| 265 ASSERT_EQ(1u, parsed_altsvc_vector.size()); | |
| 266 EXPECT_EQ(altsvc.protocol_id, parsed_altsvc_vector[0].protocol_id); | |
| 267 EXPECT_EQ(altsvc.host, parsed_altsvc_vector[0].host); | |
| 268 EXPECT_EQ(altsvc.port, parsed_altsvc_vector[0].port); | |
| 269 EXPECT_EQ(altsvc.max_age, parsed_altsvc_vector[0].max_age); | |
| 270 EXPECT_EQ(altsvc.version, parsed_altsvc_vector[0].version); | |
| 271 | |
| 272 // Test SerializeHeaderFieldValue(). | |
| 273 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 274 altsvc_vector.push_back(altsvc); | |
| 275 EXPECT_EQ(expected_header_field_value, | |
| 276 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector)); | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 // Test ParseHeaderFieldValue() and SerializeHeaderFieldValue() on the same pair | |
| 281 // of |expected_header_field_value| and |altsvc|, with and without hostname and | |
| 282 // each | |
| 283 // parameter. Multiple alternative services at a time. | |
| 284 TEST(SpdyAltSvcWireFormatTest, RoundTripMultiple) { | |
| 285 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 286 SpdyString expected_header_field_value; | |
| 287 for (int i = 0; i < 1 << 3; ++i) { | |
| 288 SpdyAltSvcWireFormat::AlternativeService altsvc; | |
| 289 FuzzAlternativeService(i, &altsvc, &expected_header_field_value); | |
| 290 altsvc_vector.push_back(altsvc); | |
| 291 } | |
| 292 | |
| 293 // Test ParseHeaderFieldValue(). | |
| 294 SpdyAltSvcWireFormat::AlternativeServiceVector parsed_altsvc_vector; | |
| 295 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 296 expected_header_field_value, &parsed_altsvc_vector)); | |
| 297 ASSERT_EQ(altsvc_vector.size(), parsed_altsvc_vector.size()); | |
| 298 SpdyAltSvcWireFormat::AlternativeServiceVector::iterator expected_it = | |
| 299 altsvc_vector.begin(); | |
| 300 SpdyAltSvcWireFormat::AlternativeServiceVector::iterator parsed_it = | |
| 301 parsed_altsvc_vector.begin(); | |
| 302 for (; expected_it != altsvc_vector.end(); ++expected_it, ++parsed_it) { | |
| 303 EXPECT_EQ(expected_it->protocol_id, parsed_it->protocol_id); | |
| 304 EXPECT_EQ(expected_it->host, parsed_it->host); | |
| 305 EXPECT_EQ(expected_it->port, parsed_it->port); | |
| 306 EXPECT_EQ(expected_it->max_age, parsed_it->max_age); | |
| 307 EXPECT_EQ(expected_it->version, parsed_it->version); | |
| 308 } | |
| 309 | |
| 310 // Test SerializeHeaderFieldValue(). | |
| 311 EXPECT_EQ(expected_header_field_value, | |
| 312 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector)); | |
| 313 } | |
| 314 | |
| 315 // ParseHeaderFieldValue() should return false on malformed field values: | |
| 316 // invalid percent encoding, unmatched quotation mark, empty port, non-numeric | |
| 317 // characters in numeric fields. | |
| 318 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueInvalid) { | |
| 319 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 320 const char* invalid_field_value_array[] = {"a%", | |
| 321 "a%x", | |
| 322 "a%b", | |
| 323 "a%9z", | |
| 324 "a=", | |
| 325 "a=\"", | |
| 326 "a=\"b\"", | |
| 327 "a=\":\"", | |
| 328 "a=\"c:\"", | |
| 329 "a=\"c:foo\"", | |
| 330 "a=\"c:42foo\"", | |
| 331 "a=\"b:42\"bar", | |
| 332 "a=\"b:42\" ; m", | |
| 333 "a=\"b:42\" ; min-age", | |
| 334 "a=\"b:42\" ; ma", | |
| 335 "a=\"b:42\" ; ma=", | |
| 336 "a=\"b:42\" ; v=\"..\"", | |
| 337 "a=\"b:42\" ; ma=ma", | |
| 338 "a=\"b:42\" ; ma=123bar", | |
| 339 "a=\"b:42\" ; v=24", | |
| 340 "a=\"b:42\" ; v=24,25", | |
| 341 "a=\"b:42\" ; v=\"-3\"", | |
| 342 "a=\"b:42\" ; v=\"1.2\"", | |
| 343 "a=\"b:42\" ; v=\"24,\""}; | |
| 344 for (const char* invalid_field_value : invalid_field_value_array) { | |
| 345 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 346 invalid_field_value, &altsvc_vector)) | |
| 347 << invalid_field_value; | |
| 348 } | |
| 349 } | |
| 350 | |
| 351 // ParseHeaderFieldValue() should return false on a field values truncated | |
| 352 // before closing quotation mark, without trying to access memory beyond the end | |
| 353 // of the input. | |
| 354 TEST(SpdyAltSvcWireFormatTest, ParseTruncatedHeaderFieldValue) { | |
| 355 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 356 const char* field_value_array[] = {"a=\":137\"", "a=\"foo:137\"", | |
| 357 "a%25=\"foo\\\"bar\\\\baz:137\""}; | |
| 358 for (const SpdyString& field_value : field_value_array) { | |
| 359 for (size_t len = 1; len < field_value.size(); ++len) { | |
| 360 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( | |
| 361 field_value.substr(0, len), &altsvc_vector)) | |
| 362 << len; | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 // Tests of private methods. | |
| 368 | |
| 369 // Test SkipWhiteSpace(). | |
| 370 TEST(SpdyAltSvcWireFormatTest, SkipWhiteSpace) { | |
| 371 SpdyStringPiece input("a \tb "); | |
| 372 SpdyStringPiece::const_iterator c = input.begin(); | |
| 373 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); | |
| 374 ASSERT_EQ(input.begin(), c); | |
| 375 ++c; | |
| 376 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); | |
| 377 ASSERT_EQ(input.begin() + 3, c); | |
| 378 ++c; | |
| 379 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); | |
| 380 ASSERT_EQ(input.end(), c); | |
| 381 } | |
| 382 | |
| 383 // Test PercentDecode() on valid input. | |
| 384 TEST(SpdyAltSvcWireFormatTest, PercentDecodeValid) { | |
| 385 SpdyStringPiece input(""); | |
| 386 SpdyString output; | |
| 387 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( | |
| 388 input.begin(), input.end(), &output)); | |
| 389 EXPECT_EQ("", output); | |
| 390 | |
| 391 input = SpdyStringPiece("foo"); | |
| 392 output.clear(); | |
| 393 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( | |
| 394 input.begin(), input.end(), &output)); | |
| 395 EXPECT_EQ("foo", output); | |
| 396 | |
| 397 input = SpdyStringPiece("%2ca%5Cb"); | |
| 398 output.clear(); | |
| 399 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( | |
| 400 input.begin(), input.end(), &output)); | |
| 401 EXPECT_EQ(",a\\b", output); | |
| 402 } | |
| 403 | |
| 404 // Test PercentDecode() on invalid input. | |
| 405 TEST(SpdyAltSvcWireFormatTest, PercentDecodeInvalid) { | |
| 406 const char* invalid_input_array[] = {"a%", "a%x", "a%b", "%J22", "%9z"}; | |
| 407 for (const char* invalid_input : invalid_input_array) { | |
| 408 SpdyStringPiece input(invalid_input); | |
| 409 SpdyString output; | |
| 410 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::PercentDecode( | |
| 411 input.begin(), input.end(), &output)) | |
| 412 << input; | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 // Test ParseAltAuthority() on valid input. | |
| 417 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityValid) { | |
| 418 SpdyStringPiece input(":42"); | |
| 419 SpdyString host; | |
| 420 uint16_t port; | |
| 421 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( | |
| 422 input.begin(), input.end(), &host, &port)); | |
| 423 EXPECT_TRUE(host.empty()); | |
| 424 EXPECT_EQ(42, port); | |
| 425 | |
| 426 input = SpdyStringPiece("foo:137"); | |
| 427 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( | |
| 428 input.begin(), input.end(), &host, &port)); | |
| 429 EXPECT_EQ("foo", host); | |
| 430 EXPECT_EQ(137, port); | |
| 431 | |
| 432 input = SpdyStringPiece("[2003:8:0:16::509d:9615]:443"); | |
| 433 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( | |
| 434 input.begin(), input.end(), &host, &port)); | |
| 435 EXPECT_EQ("[2003:8:0:16::509d:9615]", host); | |
| 436 EXPECT_EQ(443, port); | |
| 437 } | |
| 438 | |
| 439 // Test ParseAltAuthority() on invalid input: empty string, no port, zero port, | |
| 440 // non-digit characters following port. | |
| 441 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityInvalid) { | |
| 442 const char* invalid_input_array[] = {"", | |
| 443 ":", | |
| 444 "foo:", | |
| 445 ":bar", | |
| 446 ":0", | |
| 447 "foo:0", | |
| 448 ":12bar", | |
| 449 "foo:23bar", | |
| 450 " ", | |
| 451 ":12 ", | |
| 452 "foo:12 ", | |
| 453 "[2003:8:0:16::509d:9615]", | |
| 454 "[2003:8:0:16::509d:9615]:", | |
| 455 "[2003:8:0:16::509d:9615]foo:443", | |
| 456 "[2003:8:0:16::509d:9615:443", | |
| 457 "2003:8:0:16::509d:9615]:443"}; | |
| 458 for (const char* invalid_input : invalid_input_array) { | |
| 459 SpdyStringPiece input(invalid_input); | |
| 460 SpdyString host; | |
| 461 uint16_t port; | |
| 462 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( | |
| 463 input.begin(), input.end(), &host, &port)) | |
| 464 << input; | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 // Test ParseInteger() on valid input. | |
| 469 TEST(SpdyAltSvcWireFormatTest, ParseIntegerValid) { | |
| 470 SpdyStringPiece input("3"); | |
| 471 uint16_t value; | |
| 472 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 473 input.begin(), input.end(), &value)); | |
| 474 EXPECT_EQ(3, value); | |
| 475 | |
| 476 input = SpdyStringPiece("1337"); | |
| 477 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 478 input.begin(), input.end(), &value)); | |
| 479 EXPECT_EQ(1337, value); | |
| 480 } | |
| 481 | |
| 482 // Test ParseIntegerValid() on invalid input: empty, zero, non-numeric, trailing | |
| 483 // non-numeric characters. | |
| 484 TEST(SpdyAltSvcWireFormatTest, ParseIntegerInvalid) { | |
| 485 const char* invalid_input_array[] = {"", " ", "a", "0", "00", "1 ", "12b"}; | |
| 486 for (const char* invalid_input : invalid_input_array) { | |
| 487 SpdyStringPiece input(invalid_input); | |
| 488 uint16_t value; | |
| 489 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 490 input.begin(), input.end(), &value)) | |
| 491 << input; | |
| 492 } | |
| 493 } | |
| 494 | |
| 495 // Test ParseIntegerValid() around overflow limit. | |
| 496 TEST(SpdyAltSvcWireFormatTest, ParseIntegerOverflow) { | |
| 497 // Largest possible uint16_t value. | |
| 498 SpdyStringPiece input("65535"); | |
| 499 uint16_t value16; | |
| 500 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 501 input.begin(), input.end(), &value16)); | |
| 502 EXPECT_EQ(65535, value16); | |
| 503 | |
| 504 // Overflow uint16_t, ParsePositiveInteger16() should return false. | |
| 505 input = SpdyStringPiece("65536"); | |
| 506 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 507 input.begin(), input.end(), &value16)); | |
| 508 | |
| 509 // However, even if overflow is not checked for, 65536 overflows to 0, which | |
| 510 // returns false anyway. Check for a larger number which overflows to 1. | |
| 511 input = SpdyStringPiece("65537"); | |
| 512 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( | |
| 513 input.begin(), input.end(), &value16)); | |
| 514 | |
| 515 // Largest possible uint32_t value. | |
| 516 input = SpdyStringPiece("4294967295"); | |
| 517 uint32_t value32; | |
| 518 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( | |
| 519 input.begin(), input.end(), &value32)); | |
| 520 EXPECT_EQ(4294967295, value32); | |
| 521 | |
| 522 // Overflow uint32_t, ParsePositiveInteger32() should return false. | |
| 523 input = SpdyStringPiece("4294967296"); | |
| 524 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( | |
| 525 input.begin(), input.end(), &value32)); | |
| 526 | |
| 527 // However, even if overflow is not checked for, 4294967296 overflows to 0, | |
| 528 // which returns false anyway. Check for a larger number which overflows to | |
| 529 // 1. | |
| 530 input = SpdyStringPiece("4294967297"); | |
| 531 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( | |
| 532 input.begin(), input.end(), &value32)); | |
| 533 } | |
| 534 | |
| 535 // Test parsing an Alt-Svc entry with IP literal hostname. | |
| 536 // Regression test for https://crbug.com/664173. | |
| 537 TEST(SpdyAltSvcWireFormatTest, ParseIPLiteral) { | |
| 538 const char* input = | |
| 539 "quic=\"[2003:8:0:16::509d:9615]:443\"; v=\"36,35\"; ma=60"; | |
| 540 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; | |
| 541 ASSERT_TRUE( | |
| 542 SpdyAltSvcWireFormat::ParseHeaderFieldValue(input, &altsvc_vector)); | |
| 543 EXPECT_EQ(1u, altsvc_vector.size()); | |
| 544 EXPECT_EQ("quic", altsvc_vector[0].protocol_id); | |
| 545 EXPECT_EQ("[2003:8:0:16::509d:9615]", altsvc_vector[0].host); | |
| 546 EXPECT_EQ(443u, altsvc_vector[0].port); | |
| 547 EXPECT_EQ(60u, altsvc_vector[0].max_age); | |
| 548 EXPECT_THAT(altsvc_vector[0].version, ::testing::ElementsAre(36, 35)); | |
| 549 } | |
| 550 | |
| 551 } // namespace | |
| 552 | |
| 553 } // namespace net | |
| OLD | NEW |