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(StringPiece::const_iterator* c, |
| 21 StringPiece::const_iterator end) { |
| 22 SpdyAltSvcWireFormat::SkipWhiteSpace(c, end); |
| 23 } |
| 24 static bool PercentDecode(StringPiece::const_iterator c, |
| 25 StringPiece::const_iterator end, |
| 26 std::string* output) { |
| 27 return SpdyAltSvcWireFormat::PercentDecode(c, end, output); |
| 28 } |
| 29 static bool ParseAltAuthority(StringPiece::const_iterator c, |
| 30 StringPiece::const_iterator end, |
| 31 std::string* host, |
| 32 uint16* port) { |
| 33 return SpdyAltSvcWireFormat::ParseAltAuthority(c, end, host, port); |
| 34 } |
| 35 static bool ParsePositiveInteger16(StringPiece::const_iterator c, |
| 36 StringPiece::const_iterator end, |
| 37 uint16* max_age) { |
| 38 return SpdyAltSvcWireFormat::ParsePositiveInteger16(c, end, max_age); |
| 39 } |
| 40 static bool ParsePositiveInteger32(StringPiece::const_iterator c, |
| 41 StringPiece::const_iterator end, |
| 42 uint32* max_age) { |
| 43 return SpdyAltSvcWireFormat::ParsePositiveInteger32(c, end, max_age); |
| 44 } |
| 45 static bool ParseProbability(StringPiece::const_iterator c, |
| 46 StringPiece::const_iterator end, |
| 47 double* p) { |
| 48 return SpdyAltSvcWireFormat::ParseProbability(c, end, p); |
| 49 } |
| 50 }; |
| 51 |
| 52 } // namespace test |
| 53 |
| 54 namespace { |
| 55 |
| 56 class SpdyAltSvcWireFormatTest : public ::testing::Test {}; |
| 57 |
| 58 // Tests of public API. |
| 59 |
| 60 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored |
| 61 // parameters, duplicate parameters, trailing space, trailing alternate service |
| 62 // separator, etc. |
| 63 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValue) { |
| 64 for (int i = 0; i < 1 << 13; ++i) { |
| 65 std::string header_field_value = "a%3Db%25c=\""; |
| 66 std::string expected_host; |
| 67 if (i & 1 << 0) { |
| 68 expected_host = "foo\"bar\\baz"; |
| 69 header_field_value.append("foo\\\"bar\\\\baz"); |
| 70 } |
| 71 header_field_value.append(":42\""); |
| 72 if (i & 1 << 1) { |
| 73 header_field_value.append(" "); |
| 74 } |
| 75 uint32 expected_max_age = 86400; |
| 76 if (i & 3 << 2) { |
| 77 expected_max_age = 1111; |
| 78 header_field_value.append(";"); |
| 79 if (i & 1 << 2) { |
| 80 header_field_value.append(" "); |
| 81 } |
| 82 header_field_value.append("mA=1111"); |
| 83 if (i & 2 << 2) { |
| 84 header_field_value.append(" "); |
| 85 } |
| 86 } |
| 87 if (i & 1 << 4) { |
| 88 header_field_value.append("; J=s"); |
| 89 } |
| 90 double expected_p = 1.0; |
| 91 if (i & 1 << 5) { |
| 92 expected_p = 0.33; |
| 93 header_field_value.append("; P=.33"); |
| 94 } |
| 95 if (i & 1 << 6) { |
| 96 expected_p = 0.0; |
| 97 header_field_value.append("; p=0"); |
| 98 } |
| 99 if (i & 1 << 7) { |
| 100 expected_max_age = 999999999; |
| 101 header_field_value.append("; Ma=999999999"); |
| 102 } |
| 103 if (i & 1 << 8) { |
| 104 expected_p = 0.0; |
| 105 header_field_value.append("; P=0."); |
| 106 } |
| 107 if (i & 1 << 9) { |
| 108 header_field_value.append(";"); |
| 109 } |
| 110 if (i & 1 << 10) { |
| 111 header_field_value.append(" "); |
| 112 } |
| 113 if (i & 1 << 11) { |
| 114 header_field_value.append(","); |
| 115 } |
| 116 if (i & 1 << 12) { |
| 117 header_field_value.append(" "); |
| 118 } |
| 119 |
| 120 std::string protocol_id; |
| 121 std::string host; |
| 122 uint16 port = 0; |
| 123 uint32 max_age = 0; |
| 124 double p = 0.0; |
| 125 |
| 126 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
| 127 header_field_value, &protocol_id, &host, &port, &max_age, &p)); |
| 128 EXPECT_EQ("a=b%c", protocol_id); |
| 129 EXPECT_EQ(expected_host, host); |
| 130 EXPECT_EQ(42, port); |
| 131 EXPECT_EQ(expected_max_age, max_age); |
| 132 EXPECT_DOUBLE_EQ(expected_p, p); |
| 133 } |
| 134 } |
| 135 |
| 136 // Test SerializeHeaderFieldValue() with and without hostname and each |
| 137 // parameter. |
| 138 TEST(SpdyAltSvcWireFormatTest, SerializeHeaderFieldValue) { |
| 139 for (int i = 0; i < 1 << 3; ++i) { |
| 140 std::string expected_header_field_value = "a%3Db%25c=\""; |
| 141 std::string host; |
| 142 if (i & 1 << 0) { |
| 143 host = "foo\"bar\\baz"; |
| 144 expected_header_field_value.append("foo\\\"bar\\\\baz"); |
| 145 } |
| 146 expected_header_field_value.append(":42\""); |
| 147 int max_age = 86400; |
| 148 if (i & 1 << 1) { |
| 149 max_age = 1111; |
| 150 expected_header_field_value.append("; ma=1111"); |
| 151 } |
| 152 double p = 1.0; |
| 153 if (i & 1 << 2) { |
| 154 p = 0.33; |
| 155 expected_header_field_value.append("; p=0.33"); |
| 156 } |
| 157 EXPECT_EQ(expected_header_field_value, |
| 158 SpdyAltSvcWireFormat::SerializeHeaderFieldValue("a=b%c", host, 42, |
| 159 max_age, p)); |
| 160 } |
| 161 } |
| 162 |
| 163 // ParseHeaderFieldValue() should return false on malformed field values: |
| 164 // invalid percent encoding, unmatched quotation mark, empty port, non-numeric |
| 165 // characters in numeric fields, negative or larger than 1.0 probability. |
| 166 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueInvalid) { |
| 167 std::string protocol_id; |
| 168 std::string host; |
| 169 uint16 port; |
| 170 uint32 max_age; |
| 171 double p; |
| 172 const char* invalid_field_value_array[] = {"", "a%", "a%x", "a%b", "a%9z", |
| 173 "a=", "a=\"", "a=\"b\"", "a=\":\"", "a=\"c:\"", "a=\"c:foo\"", |
| 174 "a=\"c:42foo\"", "a=\"b:42\"bar", "a=\"b:42\" ; m", |
| 175 "a=\"b:42\" ; min-age", "a=\"b:42\" ; ma", "a=\"b:42\" ; ma=", |
| 176 "a=\"b:42\" ; ma=ma", "a=\"b:42\" ; ma=123bar", "a=\"b:42\" ; p=-2", |
| 177 "a=\"b:42\" ; p=..", "a=\"b:42\" ; p=1.05"}; |
| 178 for (const char* invalid_field_value : invalid_field_value_array) { |
| 179 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
| 180 invalid_field_value, &protocol_id, &host, &port, &max_age, &p)) |
| 181 << invalid_field_value; |
| 182 } |
| 183 } |
| 184 |
| 185 // ParseHeaderFieldValue() should return false on a field values truncated |
| 186 // before closing quotation mark, without trying to access memory beyond the end |
| 187 // of the input. |
| 188 TEST(SpdyAltSvcWireFormatTest, ParseTruncatedHeaderFieldValue) { |
| 189 std::string protocol_id; |
| 190 std::string host; |
| 191 uint16 port; |
| 192 uint32 max_age; |
| 193 double p; |
| 194 const char* field_value_array[] = { |
| 195 "p=\":137\"", "p=\"foo:137\"", "p%25=\"foo\\\"bar\\\\baz:137\""}; |
| 196 for (std::string field_value : field_value_array) { |
| 197 for (size_t len = 1; len < field_value.size(); ++len) { |
| 198 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
| 199 field_value.substr(0, len), &protocol_id, &host, &port, &max_age, &p)) |
| 200 << len; |
| 201 } |
| 202 } |
| 203 } |
| 204 |
| 205 // Tests of private methods. |
| 206 |
| 207 // Test SkipWhiteSpace(). |
| 208 TEST(SpdyAltSvcWireFormatTest, SkipWhiteSpace) { |
| 209 StringPiece input("a \tb "); |
| 210 StringPiece::const_iterator c = input.begin(); |
| 211 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); |
| 212 ASSERT_EQ(input.begin(), c); |
| 213 ++c; |
| 214 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); |
| 215 ASSERT_EQ(input.begin() + 3, c); |
| 216 ++c; |
| 217 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end()); |
| 218 ASSERT_EQ(input.end(), c); |
| 219 } |
| 220 |
| 221 // Test PercentDecode() on valid input. |
| 222 TEST(SpdyAltSvcWireFormatTest, PercentDecodeValid) { |
| 223 StringPiece input(""); |
| 224 std::string output; |
| 225 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( |
| 226 input.begin(), input.end(), &output)); |
| 227 EXPECT_EQ("", output); |
| 228 |
| 229 input = StringPiece("foo"); |
| 230 output.clear(); |
| 231 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( |
| 232 input.begin(), input.end(), &output)); |
| 233 EXPECT_EQ("foo", output); |
| 234 |
| 235 input = StringPiece("%2ca%5Cb"); |
| 236 output.clear(); |
| 237 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode( |
| 238 input.begin(), input.end(), &output)); |
| 239 EXPECT_EQ(",a\\b", output); |
| 240 } |
| 241 |
| 242 // Test PercentDecode() on invalid input. |
| 243 TEST(SpdyAltSvcWireFormatTest, PercentDecodeInvalid) { |
| 244 const char* invalid_input_array[] = {"a%", "a%x", "a%b", "%J22", "%9z"}; |
| 245 for (const char* invalid_input : invalid_input_array) { |
| 246 StringPiece input(invalid_input); |
| 247 std::string output; |
| 248 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::PercentDecode( |
| 249 input.begin(), input.end(), &output)) |
| 250 << input; |
| 251 } |
| 252 } |
| 253 |
| 254 // Test ParseAltAuthority() on valid input. |
| 255 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityValid) { |
| 256 StringPiece input(":42"); |
| 257 std::string host; |
| 258 uint16 port; |
| 259 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( |
| 260 input.begin(), input.end(), &host, &port)); |
| 261 EXPECT_TRUE(host.empty()); |
| 262 EXPECT_EQ(42, port); |
| 263 |
| 264 input = StringPiece("foo:137"); |
| 265 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( |
| 266 input.begin(), input.end(), &host, &port)); |
| 267 EXPECT_EQ("foo", host); |
| 268 EXPECT_EQ(137, port); |
| 269 } |
| 270 |
| 271 // Test ParseAltAuthority() on invalid input: empty string, no port, zero port, |
| 272 // non-digit characters following port. |
| 273 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityInvalid) { |
| 274 const char* invalid_input_array[] = {"", ":", "foo:", ":bar", ":0", "foo:0", |
| 275 ":12bar", "foo:23bar", " ", ":12 ", "foo:12 "}; |
| 276 for (const char* invalid_input : invalid_input_array) { |
| 277 StringPiece input(invalid_input); |
| 278 std::string host; |
| 279 uint16 port; |
| 280 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority( |
| 281 input.begin(), input.end(), &host, &port)) |
| 282 << input; |
| 283 } |
| 284 } |
| 285 |
| 286 // Test ParseInteger() on valid input. |
| 287 TEST(SpdyAltSvcWireFormatTest, ParseIntegerValid) { |
| 288 StringPiece input("3"); |
| 289 uint16 value; |
| 290 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 291 input.begin(), input.end(), &value)); |
| 292 EXPECT_EQ(3, value); |
| 293 |
| 294 input = StringPiece("1337"); |
| 295 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 296 input.begin(), input.end(), &value)); |
| 297 EXPECT_EQ(1337, value); |
| 298 } |
| 299 |
| 300 // Test ParseIntegerValid() on invalid input: empty, zero, non-numeric, trailing |
| 301 // non-numeric characters. |
| 302 TEST(SpdyAltSvcWireFormatTest, ParseIntegerInvalid) { |
| 303 const char* invalid_input_array[] = {"", " ", "a", "0", "00", "1 ", "12b"}; |
| 304 for (const char* invalid_input : invalid_input_array) { |
| 305 StringPiece input(invalid_input); |
| 306 uint16 value; |
| 307 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 308 input.begin(), input.end(), &value)) |
| 309 << input; |
| 310 } |
| 311 } |
| 312 |
| 313 // Test ParseIntegerValid() around overflow limit. |
| 314 TEST(SpdyAltSvcWireFormatTest, ParseIntegerOverflow) { |
| 315 // Largest possible uint16 value. |
| 316 StringPiece input("65535"); |
| 317 uint16 value16; |
| 318 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 319 input.begin(), input.end(), &value16)); |
| 320 EXPECT_EQ(65535, value16); |
| 321 |
| 322 // Overflow uint16, ParsePositiveInteger16() should return false. |
| 323 input = StringPiece("65536"); |
| 324 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 325 input.begin(), input.end(), &value16)); |
| 326 |
| 327 // However, even if overflow is not checked for, 65536 overflows to 0, which |
| 328 // returns false anyway. Check for a larger number which overflows to 1. |
| 329 input = StringPiece("65537"); |
| 330 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16( |
| 331 input.begin(), input.end(), &value16)); |
| 332 |
| 333 // Largest possible uint32 value. |
| 334 input = StringPiece("4294967295"); |
| 335 uint32 value32; |
| 336 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( |
| 337 input.begin(), input.end(), &value32)); |
| 338 EXPECT_EQ(4294967295, value32); |
| 339 |
| 340 // Overflow uint32, ParsePositiveInteger32() should return false. |
| 341 input = StringPiece("4294967296"); |
| 342 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( |
| 343 input.begin(), input.end(), &value32)); |
| 344 |
| 345 // However, even if overflow is not checked for, 4294967296 overflows to 0, |
| 346 // which returns false anyway. Check for a larger number which overflows to |
| 347 // 1. |
| 348 input = StringPiece("4294967297"); |
| 349 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32( |
| 350 input.begin(), input.end(), &value32)); |
| 351 } |
| 352 |
| 353 // Test ParseProbability() on valid input. |
| 354 TEST(SpdyAltSvcWireFormatTest, ParseProbabilityValid) { |
| 355 StringPiece input("0"); |
| 356 double probability = -2.0; |
| 357 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 358 input.begin(), input.end(), &probability)); |
| 359 EXPECT_DOUBLE_EQ(0.0, probability); |
| 360 |
| 361 input = StringPiece("0."); |
| 362 probability = -2.0; |
| 363 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 364 input.begin(), input.end(), &probability)); |
| 365 EXPECT_DOUBLE_EQ(0.0, probability); |
| 366 |
| 367 input = StringPiece("0.0"); |
| 368 probability = -2.0; |
| 369 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 370 input.begin(), input.end(), &probability)); |
| 371 EXPECT_DOUBLE_EQ(0.0, probability); |
| 372 |
| 373 input = StringPiece("1"); |
| 374 probability = -2.0; |
| 375 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 376 input.begin(), input.end(), &probability)); |
| 377 EXPECT_DOUBLE_EQ(1.0, probability); |
| 378 |
| 379 input = StringPiece("1."); |
| 380 probability = -2.0; |
| 381 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 382 input.begin(), input.end(), &probability)); |
| 383 EXPECT_DOUBLE_EQ(1.0, probability); |
| 384 |
| 385 input = StringPiece("1.0"); |
| 386 probability = -2.0; |
| 387 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 388 input.begin(), input.end(), &probability)); |
| 389 EXPECT_DOUBLE_EQ(1.0, probability); |
| 390 |
| 391 input = StringPiece("0.37"); |
| 392 probability = -2.0; |
| 393 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 394 input.begin(), input.end(), &probability)); |
| 395 EXPECT_DOUBLE_EQ(0.37, probability); |
| 396 |
| 397 input = StringPiece("0.72"); |
| 398 probability = -2.0; |
| 399 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 400 input.begin(), input.end(), &probability)); |
| 401 EXPECT_DOUBLE_EQ(0.72, probability); |
| 402 } |
| 403 |
| 404 // Test ParseProbability() on invalid input: empty string, non-digit characters, |
| 405 // negative input, larger than 1.0. |
| 406 TEST(SpdyAltSvcWireFormatTest, ParseProbabilityInvalid) { |
| 407 const char* invalid_input_array[] = {"", " ", ".", "a", "-2", "-0", "0a", |
| 408 "1b ", "0.9z2", "0.33 ", "0.98x", "2.0", "1.0001", "1.00001", |
| 409 "1.000001"}; |
| 410 for (const char* invalid_input : invalid_input_array) { |
| 411 StringPiece input(invalid_input); |
| 412 double probability; |
| 413 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseProbability( |
| 414 input.begin(), input.end(), &probability)); |
| 415 } |
| 416 } |
| 417 |
| 418 } // namespace |
| 419 |
| 420 } // namespace net |
OLD | NEW |