blob: d5c96fb937516a42fab3e0caf2b67d5c7c229686 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 <memory>
vasilvv872e7a32019-03-12 16:42:44 -07006#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05007
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
13
14using spdy::SpdyHeaderBlock;
15using testing::Pair;
16using testing::UnorderedElementsAre;
17
18namespace quic {
19namespace test {
bnc5231ee22019-04-15 19:02:13 -070020namespace {
21
22const bool kExpectFinalByteOffset = true;
23const bool kDoNotExpectFinalByteOffset = false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050024
25static std::unique_ptr<QuicHeaderList> FromList(
26 const QuicHeaderList::ListType& src) {
27 std::unique_ptr<QuicHeaderList> headers(new QuicHeaderList);
28 headers->OnHeaderBlockStart();
29 for (const auto& p : src) {
30 headers->OnHeader(p.first, p.second);
31 }
32 headers->OnHeaderBlockEnd(0, 0);
33 return headers;
34}
35
bnc5231ee22019-04-15 19:02:13 -070036} // anonymous namespace
37
QUICHE teama6ef0a62019-03-07 20:34:33 -050038using CopyAndValidateHeaders = QuicTest;
39
40TEST_F(CopyAndValidateHeaders, NormalUsage) {
41 auto headers = FromList({// All cookie crumbs are joined.
42 {"cookie", " part 1"},
43 {"cookie", "part 2 "},
44 {"cookie", "part3"},
45
46 // Already-delimited headers are passed through.
vasilvvc48c8712019-03-11 13:38:16 -070047 {"passed-through", std::string("foo\0baz", 7)},
QUICHE teama6ef0a62019-03-07 20:34:33 -050048
49 // Other headers are joined on \0.
50 {"joined", "value 1"},
51 {"joined", "value 2"},
52
53 // Empty headers remain empty.
54 {"empty", ""},
55
56 // Joined empty headers work as expected.
57 {"empty-joined", ""},
58 {"empty-joined", "foo"},
59 {"empty-joined", ""},
60 {"empty-joined", ""},
61
62 // Non-continguous cookie crumb.
63 {"cookie", " fin!"}});
64
65 int64_t content_length = -1;
66 SpdyHeaderBlock block;
67 ASSERT_TRUE(
68 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
69 EXPECT_THAT(block,
70 UnorderedElementsAre(
71 Pair("cookie", " part 1; part 2 ; part3; fin!"),
72 Pair("passed-through", QuicStringPiece("foo\0baz", 7)),
73 Pair("joined", QuicStringPiece("value 1\0value 2", 15)),
74 Pair("empty", ""),
75 Pair("empty-joined", QuicStringPiece("\0foo\0\0", 6))));
76 EXPECT_EQ(-1, content_length);
77}
78
79TEST_F(CopyAndValidateHeaders, EmptyName) {
80 auto headers = FromList({{"foo", "foovalue"}, {"", "barvalue"}, {"baz", ""}});
81 int64_t content_length = -1;
82 SpdyHeaderBlock block;
83 ASSERT_FALSE(
84 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
85}
86
87TEST_F(CopyAndValidateHeaders, UpperCaseName) {
88 auto headers =
89 FromList({{"foo", "foovalue"}, {"bar", "barvalue"}, {"bAz", ""}});
90 int64_t content_length = -1;
91 SpdyHeaderBlock block;
92 ASSERT_FALSE(
93 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
94}
95
96TEST_F(CopyAndValidateHeaders, MultipleContentLengths) {
97 auto headers = FromList({{"content-length", "9"},
98 {"foo", "foovalue"},
99 {"content-length", "9"},
100 {"bar", "barvalue"},
101 {"baz", ""}});
102 int64_t content_length = -1;
103 SpdyHeaderBlock block;
104 ASSERT_TRUE(
105 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
106 EXPECT_THAT(block, UnorderedElementsAre(
107 Pair("foo", "foovalue"), Pair("bar", "barvalue"),
108 Pair("content-length", QuicStringPiece("9\09", 3)),
109 Pair("baz", "")));
110 EXPECT_EQ(9, content_length);
111}
112
113TEST_F(CopyAndValidateHeaders, InconsistentContentLengths) {
114 auto headers = FromList({{"content-length", "9"},
115 {"foo", "foovalue"},
116 {"content-length", "8"},
117 {"bar", "barvalue"},
118 {"baz", ""}});
119 int64_t content_length = -1;
120 SpdyHeaderBlock block;
121 ASSERT_FALSE(
122 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
123}
124
125TEST_F(CopyAndValidateHeaders, LargeContentLength) {
126 auto headers = FromList({{"content-length", "9000000000"},
127 {"foo", "foovalue"},
128 {"bar", "barvalue"},
129 {"baz", ""}});
130 int64_t content_length = -1;
131 SpdyHeaderBlock block;
132 ASSERT_TRUE(
133 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
134 EXPECT_THAT(block, UnorderedElementsAre(
135 Pair("foo", "foovalue"), Pair("bar", "barvalue"),
136 Pair("content-length", QuicStringPiece("9000000000")),
137 Pair("baz", "")));
138 EXPECT_EQ(9000000000, content_length);
139}
140
141TEST_F(CopyAndValidateHeaders, MultipleValues) {
142 auto headers = FromList({{"foo", "foovalue"},
143 {"bar", "barvalue"},
144 {"baz", ""},
145 {"foo", "boo"},
146 {"baz", "buzz"}});
147 int64_t content_length = -1;
148 SpdyHeaderBlock block;
149 ASSERT_TRUE(
150 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
151 EXPECT_THAT(block, UnorderedElementsAre(
152 Pair("foo", QuicStringPiece("foovalue\0boo", 12)),
153 Pair("bar", "barvalue"),
154 Pair("baz", QuicStringPiece("\0buzz", 5))));
155 EXPECT_EQ(-1, content_length);
156}
157
158TEST_F(CopyAndValidateHeaders, MoreThanTwoValues) {
159 auto headers = FromList({{"set-cookie", "value1"},
160 {"set-cookie", "value2"},
161 {"set-cookie", "value3"}});
162 int64_t content_length = -1;
163 SpdyHeaderBlock block;
164 ASSERT_TRUE(
165 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
166 EXPECT_THAT(
167 block, UnorderedElementsAre(Pair(
168 "set-cookie", QuicStringPiece("value1\0value2\0value3", 20))));
169 EXPECT_EQ(-1, content_length);
170}
171
172TEST_F(CopyAndValidateHeaders, Cookie) {
173 auto headers = FromList({{"foo", "foovalue"},
174 {"bar", "barvalue"},
175 {"cookie", "value1"},
176 {"baz", ""}});
177 int64_t content_length = -1;
178 SpdyHeaderBlock block;
179 ASSERT_TRUE(
180 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
181 EXPECT_THAT(block, UnorderedElementsAre(
182 Pair("foo", "foovalue"), Pair("bar", "barvalue"),
183 Pair("cookie", "value1"), Pair("baz", "")));
184 EXPECT_EQ(-1, content_length);
185}
186
187TEST_F(CopyAndValidateHeaders, MultipleCookies) {
188 auto headers = FromList({{"foo", "foovalue"},
189 {"bar", "barvalue"},
190 {"cookie", "value1"},
191 {"baz", ""},
192 {"cookie", "value2"}});
193 int64_t content_length = -1;
194 SpdyHeaderBlock block;
195 ASSERT_TRUE(
196 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
197 EXPECT_THAT(block, UnorderedElementsAre(
198 Pair("foo", "foovalue"), Pair("bar", "barvalue"),
199 Pair("cookie", "value1; value2"), Pair("baz", "")));
200 EXPECT_EQ(-1, content_length);
201}
202
203using CopyAndValidateTrailers = QuicTest;
204
205TEST_F(CopyAndValidateTrailers, SimplestValidList) {
206 // Verify that the simplest trailers are valid: just a final byte offset that
207 // gets parsed successfully.
208 auto trailers = FromList({{kFinalOffsetHeaderKey, "1234"}});
209 size_t final_byte_offset = 0;
210 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700211 EXPECT_TRUE(SpdyUtils::CopyAndValidateTrailers(
212 *trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213 EXPECT_EQ(1234u, final_byte_offset);
214}
215
bnc5231ee22019-04-15 19:02:13 -0700216TEST_F(CopyAndValidateTrailers, EmptyTrailerListWithFinalByteOffsetExpected) {
217 // An empty trailer list will fail as expected key kFinalOffsetHeaderKey is
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 // not present.
219 QuicHeaderList trailers;
220 size_t final_byte_offset = 0;
221 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700222 EXPECT_FALSE(SpdyUtils::CopyAndValidateTrailers(
223 trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224}
225
bnc5231ee22019-04-15 19:02:13 -0700226TEST_F(CopyAndValidateTrailers,
227 EmptyTrailerListWithFinalByteOffsetNotExpected) {
228 // An empty trailer list will pass successfully if kFinalOffsetHeaderKey is
229 // not expected.
230 QuicHeaderList trailers;
231 size_t final_byte_offset = 0;
232 SpdyHeaderBlock block;
233 EXPECT_TRUE(SpdyUtils::CopyAndValidateTrailers(
234 trailers, kDoNotExpectFinalByteOffset, &final_byte_offset, &block));
235 EXPECT_TRUE(block.empty());
236}
237
238TEST_F(CopyAndValidateTrailers, FinalByteOffsetExpectedButNotPresent) {
239 // Validation fails if expected kFinalOffsetHeaderKey is not present, even if
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 // the rest of the header block is valid.
241 auto trailers = FromList({{"key", "value"}});
242 size_t final_byte_offset = 0;
243 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700244 EXPECT_FALSE(SpdyUtils::CopyAndValidateTrailers(
245 *trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
246}
247
248TEST_F(CopyAndValidateTrailers, FinalByteOffsetNotExpectedButPresent) {
249 // Validation fails if kFinalOffsetHeaderKey is present but should not be,
250 // even if the rest of the header block is valid.
251 auto trailers = FromList({{"key", "value"}, {kFinalOffsetHeaderKey, "1234"}});
252 size_t final_byte_offset = 0;
253 SpdyHeaderBlock block;
254 EXPECT_FALSE(SpdyUtils::CopyAndValidateTrailers(
255 *trailers, kDoNotExpectFinalByteOffset, &final_byte_offset, &block));
256}
257
258TEST_F(CopyAndValidateTrailers, FinalByteOffsetNotExpectedAndNotPresent) {
259 // Validation succeeds if kFinalOffsetHeaderKey is not expected and not
260 // present.
261 auto trailers = FromList({{"key", "value"}});
262 size_t final_byte_offset = 0;
263 SpdyHeaderBlock block;
264 EXPECT_TRUE(SpdyUtils::CopyAndValidateTrailers(
265 *trailers, kDoNotExpectFinalByteOffset, &final_byte_offset, &block));
266 EXPECT_THAT(block, UnorderedElementsAre(Pair("key", "value")));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267}
268
269TEST_F(CopyAndValidateTrailers, EmptyName) {
270 // Trailer validation will fail with an empty header key, in an otherwise
271 // valid block of trailers.
272 auto trailers = FromList({{"", "value"}, {kFinalOffsetHeaderKey, "1234"}});
273 size_t final_byte_offset = 0;
274 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700275 EXPECT_FALSE(SpdyUtils::CopyAndValidateTrailers(
276 *trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277}
278
279TEST_F(CopyAndValidateTrailers, PseudoHeaderInTrailers) {
280 // Pseudo headers are illegal in trailers.
281 auto trailers =
282 FromList({{":pseudo_key", "value"}, {kFinalOffsetHeaderKey, "1234"}});
283 size_t final_byte_offset = 0;
284 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700285 EXPECT_FALSE(SpdyUtils::CopyAndValidateTrailers(
286 *trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500287}
288
289TEST_F(CopyAndValidateTrailers, DuplicateTrailers) {
290 // Duplicate trailers are allowed, and their values are concatenated into a
291 // single string delimted with '\0'. Some of the duplicate headers
292 // deliberately have an empty value.
293 auto trailers = FromList({{"key", "value0"},
294 {"key", "value1"},
295 {"key", ""},
296 {"key", ""},
297 {"key", "value2"},
298 {"key", ""},
299 {kFinalOffsetHeaderKey, "1234"},
300 {"other_key", "value"},
301 {"key", "non_contiguous_duplicate"}});
302 size_t final_byte_offset = 0;
303 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700304 EXPECT_TRUE(SpdyUtils::CopyAndValidateTrailers(
305 *trailers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500306 EXPECT_THAT(
307 block,
308 UnorderedElementsAre(
309 Pair("key",
310 QuicStringPiece(
311 "value0\0value1\0\0\0value2\0\0non_contiguous_duplicate",
312 48)),
313 Pair("other_key", "value")));
314}
315
316TEST_F(CopyAndValidateTrailers, DuplicateCookies) {
317 // Duplicate cookie headers in trailers should be concatenated into a single
318 // "; " delimted string.
319 auto headers = FromList({{"cookie", " part 1"},
320 {"cookie", "part 2 "},
321 {"cookie", "part3"},
322 {"key", "value"},
323 {kFinalOffsetHeaderKey, "1234"},
324 {"cookie", " non_contiguous_cookie!"}});
325
326 size_t final_byte_offset = 0;
327 SpdyHeaderBlock block;
bnc5231ee22019-04-15 19:02:13 -0700328 EXPECT_TRUE(SpdyUtils::CopyAndValidateTrailers(
329 *headers, kExpectFinalByteOffset, &final_byte_offset, &block));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330 EXPECT_THAT(
331 block,
332 UnorderedElementsAre(
333 Pair("cookie", " part 1; part 2 ; part3; non_contiguous_cookie!"),
334 Pair("key", "value")));
335}
336
337using GetPromisedUrlFromHeaders = QuicTest;
338
339TEST_F(GetPromisedUrlFromHeaders, Basic) {
340 SpdyHeaderBlock headers;
341 headers[":method"] = "GET";
342 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
343 headers[":scheme"] = "https";
344 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
345 headers[":authority"] = "www.google.com";
346 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
347 headers[":path"] = "/index.html";
348 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers),
349 "https://www.google.com/index.html");
350 headers["key1"] = "value1";
351 headers["key2"] = "value2";
352 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers),
353 "https://www.google.com/index.html");
354}
355
356TEST_F(GetPromisedUrlFromHeaders, Connect) {
357 SpdyHeaderBlock headers;
358 headers[":method"] = "CONNECT";
359 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
360 headers[":authority"] = "www.google.com";
361 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
362 headers[":scheme"] = "https";
363 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
364 headers[":path"] = "https";
365 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
366}
367
368TEST_F(GetPromisedUrlFromHeaders, InvalidUserinfo) {
369 SpdyHeaderBlock headers;
370 headers[":method"] = "GET";
371 headers[":authority"] = "user@www.google.com";
372 headers[":scheme"] = "https";
373 headers[":path"] = "/";
374 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
375}
376
377TEST_F(GetPromisedUrlFromHeaders, InvalidPath) {
378 SpdyHeaderBlock headers;
379 headers[":method"] = "GET";
380 headers[":authority"] = "www.google.com";
381 headers[":scheme"] = "https";
382 headers[":path"] = "";
383 EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
384}
385
386using GetPromisedHostNameFromHeaders = QuicTest;
387
388TEST_F(GetPromisedHostNameFromHeaders, NormalUsage) {
389 SpdyHeaderBlock headers;
390 headers[":method"] = "GET";
391 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers), "");
392 headers[":scheme"] = "https";
393 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers), "");
394 headers[":authority"] = "www.google.com";
395 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers), "");
396 headers[":path"] = "/index.html";
397 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers),
398 "www.google.com");
399 headers["key1"] = "value1";
400 headers["key2"] = "value2";
401 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers),
402 "www.google.com");
403 headers[":authority"] = "www.google.com:6666";
404 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers),
405 "www.google.com");
406 headers[":authority"] = "192.168.1.1";
407 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers), "192.168.1.1");
408 headers[":authority"] = "192.168.1.1:6666";
409 EXPECT_EQ(SpdyUtils::GetPromisedHostNameFromHeaders(headers), "192.168.1.1");
410}
411
412using PopulateHeaderBlockFromUrl = QuicTest;
413
414TEST_F(PopulateHeaderBlockFromUrl, NormalUsage) {
vasilvvc48c8712019-03-11 13:38:16 -0700415 std::string url = "https://www.google.com/index.html";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500416 SpdyHeaderBlock headers;
417 EXPECT_TRUE(SpdyUtils::PopulateHeaderBlockFromUrl(url, &headers));
418 EXPECT_EQ("https", headers[":scheme"].as_string());
419 EXPECT_EQ("www.google.com", headers[":authority"].as_string());
420 EXPECT_EQ("/index.html", headers[":path"].as_string());
421}
422
423TEST_F(PopulateHeaderBlockFromUrl, UrlWithNoPath) {
vasilvvc48c8712019-03-11 13:38:16 -0700424 std::string url = "https://www.google.com";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500425 SpdyHeaderBlock headers;
426 EXPECT_TRUE(SpdyUtils::PopulateHeaderBlockFromUrl(url, &headers));
427 EXPECT_EQ("https", headers[":scheme"].as_string());
428 EXPECT_EQ("www.google.com", headers[":authority"].as_string());
429 EXPECT_EQ("/", headers[":path"].as_string());
430}
431
432TEST_F(PopulateHeaderBlockFromUrl, Failure) {
433 SpdyHeaderBlock headers;
434 EXPECT_FALSE(SpdyUtils::PopulateHeaderBlockFromUrl("/", &headers));
435 EXPECT_FALSE(SpdyUtils::PopulateHeaderBlockFromUrl("/index.html", &headers));
436 EXPECT_FALSE(
437 SpdyUtils::PopulateHeaderBlockFromUrl("www.google.com/", &headers));
438}
439
440using PushPromiseUrlTest = QuicTest;
441
442TEST_F(PushPromiseUrlTest, GetPushPromiseUrl) {
443 // Test rejection of various inputs.
444 EXPECT_EQ("",
445 SpdyUtils::GetPushPromiseUrl("file", "localhost", "/etc/password"));
446 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("file", "",
447 "/C:/Windows/System32/Config/"));
448 EXPECT_EQ("",
449 SpdyUtils::GetPushPromiseUrl("", "https://www.google.com", "/"));
450
451 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https://www.google.com",
452 "www.google.com", "/"));
453 EXPECT_EQ("",
454 SpdyUtils::GetPushPromiseUrl("https://", "www.google.com", "/"));
455 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "", "/"));
456 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "", "www.google.com/"));
457 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google.com/", "/"));
458 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google.com", ""));
459 EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google", ".com/"));
460
461 // Test acception/rejection of various input combinations.
462 // |input_headers| is an array of pairs. The first value of each pair is a
463 // string that will be used as one of the inputs of GetPushPromiseUrl(). The
464 // second value of each pair is a bitfield where the lowest 3 bits indicate
465 // for which headers that string is valid (in a PUSH_PROMISE). For example,
466 // the string "http" would be valid for both the ":scheme" and ":authority"
467 // headers, so the bitfield paired with it is set to SCHEME | AUTH.
468 const unsigned char SCHEME = (1u << 0);
469 const unsigned char AUTH = (1u << 1);
470 const unsigned char PATH = (1u << 2);
471 const std::pair<const char*, unsigned char> input_headers[] = {
472 {"http", SCHEME | AUTH},
473 {"https", SCHEME | AUTH},
474 {"hTtP", SCHEME | AUTH},
475 {"HTTPS", SCHEME | AUTH},
476 {"www.google.com", AUTH},
477 {"90af90e0", AUTH},
478 {"12foo%20-bar:00001233", AUTH},
479 {"GOO\u200b\u2060\ufeffgoo", AUTH},
480 {"192.168.0.5", AUTH},
481 {"[::ffff:192.168.0.1.]", AUTH},
482 {"http:", AUTH},
483 {"bife l", AUTH},
484 {"/", PATH},
485 {"/foo/bar/baz", PATH},
486 {"/%20-2DVdkj.cie/foe_.iif/", PATH},
487 {"http://", 0},
488 {":443", 0},
489 {":80/eddd", 0},
490 {"google.com:-0", 0},
491 {"google.com:65536", 0},
492 {"http://google.com", 0},
493 {"http://google.com:39", 0},
494 {"//google.com/foo", 0},
495 {".com/", 0},
496 {"http://www.google.com/", 0},
497 {"http://foo:439", 0},
498 {"[::ffff:192.168", 0},
499 {"]/", 0},
500 {"//", 0}};
501 for (size_t i = 0; i < QUIC_ARRAYSIZE(input_headers); ++i) {
502 bool should_accept = (input_headers[i].second & SCHEME);
503 for (size_t j = 0; j < QUIC_ARRAYSIZE(input_headers); ++j) {
504 bool should_accept_2 = should_accept && (input_headers[j].second & AUTH);
505 for (size_t k = 0; k < QUIC_ARRAYSIZE(input_headers); ++k) {
506 // |should_accept_3| indicates whether or not GetPushPromiseUrl() is
507 // expected to accept this input combination.
508 bool should_accept_3 =
509 should_accept_2 && (input_headers[k].second & PATH);
510
511 std::string url = SpdyUtils::GetPushPromiseUrl(input_headers[i].first,
512 input_headers[j].first,
513 input_headers[k].first);
514
515 ::testing::AssertionResult result = ::testing::AssertionSuccess();
516 if (url.empty() == should_accept_3) {
517 result = ::testing::AssertionFailure()
518 << "GetPushPromiseUrl() accepted/rejected the inputs when "
519 "it shouldn't have."
520 << std::endl
521 << " scheme: " << input_headers[i].first << std::endl
522 << " authority: " << input_headers[j].first << std::endl
523 << " path: " << input_headers[k].first << std::endl
524 << "Output: " << url << std::endl;
525 }
526 ASSERT_TRUE(result);
527 }
528 }
529 }
530
531 // Test canonicalization of various valid inputs.
532 EXPECT_EQ("http://www.google.com/",
533 SpdyUtils::GetPushPromiseUrl("http", "www.google.com", "/"));
534 EXPECT_EQ(
535 "https://www.goo-gle.com/fOOo/baRR",
536 SpdyUtils::GetPushPromiseUrl("hTtPs", "wWw.gOo-gLE.cOm", "/fOOo/baRR"));
537 EXPECT_EQ("https://www.goo-gle.com:3278/pAth/To/reSOurce",
538 SpdyUtils::GetPushPromiseUrl("hTtPs", "Www.gOo-Gle.Com:000003278",
539 "/pAth/To/reSOurce"));
540 EXPECT_EQ("https://foo%20bar/foo/bar/baz",
541 SpdyUtils::GetPushPromiseUrl("https", "foo bar", "/foo/bar/baz"));
542 EXPECT_EQ("http://foo.com:70/e/",
543 SpdyUtils::GetPushPromiseUrl("http", "foo.com:0000070", "/e/"));
544 EXPECT_EQ(
545 "http://192.168.0.1:70/e/",
546 SpdyUtils::GetPushPromiseUrl("http", "0300.0250.00.01:0070", "/e/"));
547 EXPECT_EQ("http://192.168.0.1/e/",
548 SpdyUtils::GetPushPromiseUrl("http", "0xC0a80001", "/e/"));
549 EXPECT_EQ("http://[::c0a8:1]/",
550 SpdyUtils::GetPushPromiseUrl("http", "[::192.168.0.1]", "/"));
551 EXPECT_EQ(
552 "https://[::ffff:c0a8:1]/",
553 SpdyUtils::GetPushPromiseUrl("https", "[::ffff:0xC0.0Xa8.0x0.0x1]", "/"));
554}
555
556} // namespace test
557} // namespace quic