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.
5 #include "net/spdy/spdy_alt_svc_wire_format.h"
7 #include "base/logging.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/platform_test.h"
17 // Expose all private methods of class SpdyAltSvcWireFormat.
18 class SpdyAltSvcWireFormatPeer
{
20 static void SkipWhiteSpace(StringPiece::const_iterator
* c
,
21 StringPiece::const_iterator end
) {
22 SpdyAltSvcWireFormat::SkipWhiteSpace(c
, end
);
24 static bool PercentDecode(StringPiece::const_iterator c
,
25 StringPiece::const_iterator end
,
26 std::string
* output
) {
27 return SpdyAltSvcWireFormat::PercentDecode(c
, end
, output
);
29 static bool ParseAltAuthority(StringPiece::const_iterator c
,
30 StringPiece::const_iterator end
,
33 return SpdyAltSvcWireFormat::ParseAltAuthority(c
, end
, host
, port
);
35 static bool ParsePositiveInteger16(StringPiece::const_iterator c
,
36 StringPiece::const_iterator end
,
38 return SpdyAltSvcWireFormat::ParsePositiveInteger16(c
, end
, max_age
);
40 static bool ParsePositiveInteger32(StringPiece::const_iterator c
,
41 StringPiece::const_iterator end
,
43 return SpdyAltSvcWireFormat::ParsePositiveInteger32(c
, end
, max_age
);
45 static bool ParseProbability(StringPiece::const_iterator c
,
46 StringPiece::const_iterator end
,
48 return SpdyAltSvcWireFormat::ParseProbability(c
, end
, p
);
56 void FuzzHeaderFieldValue(
58 std::string
* header_field_value
,
59 SpdyAltSvcWireFormat::AlternativeService
* expected_altsvc
) {
60 if (!header_field_value
->empty()) {
61 header_field_value
->push_back(',');
63 expected_altsvc
->protocol_id
= "a=b%c";
64 header_field_value
->append("a%3Db%25c=\"");
65 expected_altsvc
->host
= "";
67 expected_altsvc
->host
= "foo\"bar\\baz";
68 header_field_value
->append("foo\\\"bar\\\\baz");
70 expected_altsvc
->port
= 42;
71 header_field_value
->append(":42\"");
73 header_field_value
->append(" ");
75 expected_altsvc
->max_age
= 86400;
77 expected_altsvc
->max_age
= 1111;
78 header_field_value
->append(";");
80 header_field_value
->append(" ");
82 header_field_value
->append("mA=1111");
84 header_field_value
->append(" ");
88 header_field_value
->append("; J=s");
90 expected_altsvc
->p
= 1.0;
92 expected_altsvc
->p
= 0.33;
93 header_field_value
->append("; P=.33");
96 expected_altsvc
->p
= 0.0;
97 header_field_value
->append("; p=0");
100 expected_altsvc
->max_age
= 999999999;
101 header_field_value
->append("; Ma=999999999");
104 expected_altsvc
->p
= 0.0;
105 header_field_value
->append("; P=0.");
108 header_field_value
->append(";");
111 header_field_value
->append(" ");
114 header_field_value
->append(",");
117 header_field_value
->append(" ");
121 void FuzzAlternativeService(int i
,
122 SpdyAltSvcWireFormat::AlternativeService
* altsvc
,
123 std::string
* expected_header_field_value
) {
124 if (!expected_header_field_value
->empty()) {
125 expected_header_field_value
->push_back(',');
127 altsvc
->protocol_id
= "a=b%c";
129 expected_header_field_value
->append("a%3Db%25c=\"");
131 altsvc
->host
= "foo\"bar\\baz";
132 expected_header_field_value
->append("foo\\\"bar\\\\baz");
134 expected_header_field_value
->append(":42\"");
135 altsvc
->max_age
= 86400;
137 altsvc
->max_age
= 1111;
138 expected_header_field_value
->append("; ma=1111");
143 expected_header_field_value
->append("; p=0.33");
147 class SpdyAltSvcWireFormatTest
: public ::testing::Test
{};
149 // Tests of public API.
151 TEST(SpdyAltSvcWireFormatTest
, ParseEmptyHeaderFieldValue
) {
152 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
153 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue("", &altsvc_vector
));
154 EXPECT_EQ(0u, altsvc_vector
.size());
157 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored
158 // parameters, duplicate parameters, trailing space, trailing alternate service
159 // separator, etc. Single alternative service at a time.
160 TEST(SpdyAltSvcWireFormatTest
, ParseHeaderFieldValue
) {
161 for (int i
= 0; i
< 1 << 13; ++i
) {
162 std::string header_field_value
;
163 SpdyAltSvcWireFormat::AlternativeService expected_altsvc
;
164 FuzzHeaderFieldValue(i
, &header_field_value
, &expected_altsvc
);
165 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
166 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value
,
168 ASSERT_EQ(1u, altsvc_vector
.size());
169 EXPECT_EQ(expected_altsvc
.protocol_id
, altsvc_vector
[0].protocol_id
);
170 EXPECT_EQ(expected_altsvc
.host
, altsvc_vector
[0].host
);
171 EXPECT_EQ(expected_altsvc
.port
, altsvc_vector
[0].port
);
172 EXPECT_EQ(expected_altsvc
.max_age
, altsvc_vector
[0].max_age
);
173 EXPECT_DOUBLE_EQ(expected_altsvc
.p
, altsvc_vector
[0].p
);
177 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored
178 // parameters, duplicate parameters, trailing space, trailing alternate service
179 // separator, etc. Possibly multiple alternative service at a time.
180 TEST(SpdyAltSvcWireFormatTest
, ParseHeaderFieldValueMultiple
) {
181 for (int i
= 0; i
< 1 << 13;) {
182 std::string header_field_value
;
183 SpdyAltSvcWireFormat::AlternativeServiceVector expected_altsvc_vector
;
184 // This will generate almost two hundred header field values with two,
185 // three, four, five, six, and seven alternative services each, and
186 // thousands with a single one.
188 SpdyAltSvcWireFormat::AlternativeService expected_altsvc
;
189 FuzzHeaderFieldValue(i
, &header_field_value
, &expected_altsvc
);
190 expected_altsvc_vector
.push_back(expected_altsvc
);
192 } while ((i
< 1 << 13) && (i
% 6 < i
% 7));
193 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
194 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value
,
196 ASSERT_EQ(expected_altsvc_vector
.size(), altsvc_vector
.size());
197 for (unsigned int j
= 0; j
< altsvc_vector
.size(); ++j
) {
198 EXPECT_EQ(expected_altsvc_vector
[j
].protocol_id
,
199 altsvc_vector
[j
].protocol_id
);
200 EXPECT_EQ(expected_altsvc_vector
[j
].host
, altsvc_vector
[j
].host
);
201 EXPECT_EQ(expected_altsvc_vector
[j
].port
, altsvc_vector
[j
].port
);
202 EXPECT_EQ(expected_altsvc_vector
[j
].max_age
, altsvc_vector
[j
].max_age
);
203 EXPECT_DOUBLE_EQ(expected_altsvc_vector
[j
].p
, altsvc_vector
[j
].p
);
208 TEST(SpdyAltSvcWireFormatTest
, SerializeEmptyHeaderFieldValue
) {
209 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
210 EXPECT_EQ("", SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector
));
213 // Test SerializeHeaderFieldValue() with and without hostname and each
214 // parameter. Single alternative service at a time.
215 TEST(SpdyAltSvcWireFormatTest
, SerializeHeaderFieldValue
) {
216 for (int i
= 0; i
< 1 << 3; ++i
) {
217 SpdyAltSvcWireFormat::AlternativeService altsvc
;
218 std::string expected_header_field_value
;
219 FuzzAlternativeService(i
, &altsvc
, &expected_header_field_value
);
220 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
221 altsvc_vector
.push_back(altsvc
);
222 EXPECT_EQ(expected_header_field_value
,
223 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector
));
227 // Test SerializeHeaderFieldValue() with and without hostname and each
228 // parameter. Multiple alternative services at a time.
229 TEST(SpdyAltSvcWireFormatTest
, SerializeHeaderFieldValueMultiple
) {
230 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
231 std::string expected_header_field_value
;
232 for (int i
= 0; i
< 1 << 3; ++i
) {
233 SpdyAltSvcWireFormat::AlternativeService altsvc
;
234 FuzzAlternativeService(i
, &altsvc
, &expected_header_field_value
);
235 altsvc_vector
.push_back(altsvc
);
237 EXPECT_EQ(expected_header_field_value
,
238 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector
));
241 // ParseHeaderFieldValue() should return false on malformed field values:
242 // invalid percent encoding, unmatched quotation mark, empty port, non-numeric
243 // characters in numeric fields, negative or larger than 1.0 probability.
244 TEST(SpdyAltSvcWireFormatTest
, ParseHeaderFieldValueInvalid
) {
245 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
246 const char* invalid_field_value_array
[] = {"a%", "a%x", "a%b", "a%9z",
247 "a=", "a=\"", "a=\"b\"", "a=\":\"", "a=\"c:\"", "a=\"c:foo\"",
248 "a=\"c:42foo\"", "a=\"b:42\"bar", "a=\"b:42\" ; m",
249 "a=\"b:42\" ; min-age", "a=\"b:42\" ; ma", "a=\"b:42\" ; ma=",
250 "a=\"b:42\" ; ma=ma", "a=\"b:42\" ; ma=123bar", "a=\"b:42\" ; p=-2",
251 "a=\"b:42\" ; p=..", "a=\"b:42\" ; p=1.05"};
252 for (const char* invalid_field_value
: invalid_field_value_array
) {
253 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
254 invalid_field_value
, &altsvc_vector
))
255 << invalid_field_value
;
259 // ParseHeaderFieldValue() should return false on a field values truncated
260 // before closing quotation mark, without trying to access memory beyond the end
262 TEST(SpdyAltSvcWireFormatTest
, ParseTruncatedHeaderFieldValue
) {
263 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
264 const char* field_value_array
[] = {
265 "p=\":137\"", "p=\"foo:137\"", "p%25=\"foo\\\"bar\\\\baz:137\""};
266 for (std::string field_value
: field_value_array
) {
267 for (size_t len
= 1; len
< field_value
.size(); ++len
) {
268 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
269 field_value
.substr(0, len
), &altsvc_vector
))
275 // Tests of private methods.
277 // Test SkipWhiteSpace().
278 TEST(SpdyAltSvcWireFormatTest
, SkipWhiteSpace
) {
279 StringPiece
input("a \tb ");
280 StringPiece::const_iterator c
= input
.begin();
281 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c
, input
.end());
282 ASSERT_EQ(input
.begin(), c
);
284 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c
, input
.end());
285 ASSERT_EQ(input
.begin() + 3, c
);
287 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c
, input
.end());
288 ASSERT_EQ(input
.end(), c
);
291 // Test PercentDecode() on valid input.
292 TEST(SpdyAltSvcWireFormatTest
, PercentDecodeValid
) {
293 StringPiece
input("");
295 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
296 input
.begin(), input
.end(), &output
));
297 EXPECT_EQ("", output
);
299 input
= StringPiece("foo");
301 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
302 input
.begin(), input
.end(), &output
));
303 EXPECT_EQ("foo", output
);
305 input
= StringPiece("%2ca%5Cb");
307 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
308 input
.begin(), input
.end(), &output
));
309 EXPECT_EQ(",a\\b", output
);
312 // Test PercentDecode() on invalid input.
313 TEST(SpdyAltSvcWireFormatTest
, PercentDecodeInvalid
) {
314 const char* invalid_input_array
[] = {"a%", "a%x", "a%b", "%J22", "%9z"};
315 for (const char* invalid_input
: invalid_input_array
) {
316 StringPiece
input(invalid_input
);
318 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
319 input
.begin(), input
.end(), &output
))
324 // Test ParseAltAuthority() on valid input.
325 TEST(SpdyAltSvcWireFormatTest
, ParseAltAuthorityValid
) {
326 StringPiece
input(":42");
329 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
330 input
.begin(), input
.end(), &host
, &port
));
331 EXPECT_TRUE(host
.empty());
334 input
= StringPiece("foo:137");
335 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
336 input
.begin(), input
.end(), &host
, &port
));
337 EXPECT_EQ("foo", host
);
338 EXPECT_EQ(137, port
);
341 // Test ParseAltAuthority() on invalid input: empty string, no port, zero port,
342 // non-digit characters following port.
343 TEST(SpdyAltSvcWireFormatTest
, ParseAltAuthorityInvalid
) {
344 const char* invalid_input_array
[] = {"", ":", "foo:", ":bar", ":0", "foo:0",
345 ":12bar", "foo:23bar", " ", ":12 ", "foo:12 "};
346 for (const char* invalid_input
: invalid_input_array
) {
347 StringPiece
input(invalid_input
);
350 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
351 input
.begin(), input
.end(), &host
, &port
))
356 // Test ParseInteger() on valid input.
357 TEST(SpdyAltSvcWireFormatTest
, ParseIntegerValid
) {
358 StringPiece
input("3");
360 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
361 input
.begin(), input
.end(), &value
));
364 input
= StringPiece("1337");
365 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
366 input
.begin(), input
.end(), &value
));
367 EXPECT_EQ(1337, value
);
370 // Test ParseIntegerValid() on invalid input: empty, zero, non-numeric, trailing
371 // non-numeric characters.
372 TEST(SpdyAltSvcWireFormatTest
, ParseIntegerInvalid
) {
373 const char* invalid_input_array
[] = {"", " ", "a", "0", "00", "1 ", "12b"};
374 for (const char* invalid_input
: invalid_input_array
) {
375 StringPiece
input(invalid_input
);
377 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
378 input
.begin(), input
.end(), &value
))
383 // Test ParseIntegerValid() around overflow limit.
384 TEST(SpdyAltSvcWireFormatTest
, ParseIntegerOverflow
) {
385 // Largest possible uint16 value.
386 StringPiece
input("65535");
388 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
389 input
.begin(), input
.end(), &value16
));
390 EXPECT_EQ(65535, value16
);
392 // Overflow uint16, ParsePositiveInteger16() should return false.
393 input
= StringPiece("65536");
394 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
395 input
.begin(), input
.end(), &value16
));
397 // However, even if overflow is not checked for, 65536 overflows to 0, which
398 // returns false anyway. Check for a larger number which overflows to 1.
399 input
= StringPiece("65537");
400 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
401 input
.begin(), input
.end(), &value16
));
403 // Largest possible uint32 value.
404 input
= StringPiece("4294967295");
406 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
407 input
.begin(), input
.end(), &value32
));
408 EXPECT_EQ(4294967295, value32
);
410 // Overflow uint32, ParsePositiveInteger32() should return false.
411 input
= StringPiece("4294967296");
412 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
413 input
.begin(), input
.end(), &value32
));
415 // However, even if overflow is not checked for, 4294967296 overflows to 0,
416 // which returns false anyway. Check for a larger number which overflows to
418 input
= StringPiece("4294967297");
419 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
420 input
.begin(), input
.end(), &value32
));
423 // Test ParseProbability() on valid input.
424 TEST(SpdyAltSvcWireFormatTest
, ParseProbabilityValid
) {
425 StringPiece
input("0");
426 double probability
= -2.0;
427 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
428 input
.begin(), input
.end(), &probability
));
429 EXPECT_DOUBLE_EQ(0.0, probability
);
431 input
= StringPiece("0.");
433 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
434 input
.begin(), input
.end(), &probability
));
435 EXPECT_DOUBLE_EQ(0.0, probability
);
437 input
= StringPiece("0.0");
439 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
440 input
.begin(), input
.end(), &probability
));
441 EXPECT_DOUBLE_EQ(0.0, probability
);
443 input
= StringPiece("1");
445 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
446 input
.begin(), input
.end(), &probability
));
447 EXPECT_DOUBLE_EQ(1.0, probability
);
449 input
= StringPiece("1.");
451 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
452 input
.begin(), input
.end(), &probability
));
453 EXPECT_DOUBLE_EQ(1.0, probability
);
455 input
= StringPiece("1.0");
457 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
458 input
.begin(), input
.end(), &probability
));
459 EXPECT_DOUBLE_EQ(1.0, probability
);
461 input
= StringPiece("0.37");
463 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
464 input
.begin(), input
.end(), &probability
));
465 EXPECT_DOUBLE_EQ(0.37, probability
);
467 input
= StringPiece("0.72");
469 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
470 input
.begin(), input
.end(), &probability
));
471 EXPECT_DOUBLE_EQ(0.72, probability
);
474 // Test ParseProbability() on invalid input: empty string, non-digit characters,
475 // negative input, larger than 1.0.
476 TEST(SpdyAltSvcWireFormatTest
, ParseProbabilityInvalid
) {
477 const char* invalid_input_array
[] = {"", " ", ".", "a", "-2", "-0", "0a",
478 "1b ", "0.9z2", "0.33 ", "0.98x", "2.0", "1.0001", "1.00001",
480 for (const char* invalid_input
: invalid_input_array
) {
481 StringPiece
input(invalid_input
);
483 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseProbability(
484 input
.begin(), input
.end(), &probability
));