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 |