blob: 9a18d2f67619c7ced0d3cd76eb1c8fb8ae60e339 [file] [log] [blame]
mkwst28c7c112015-07-14 22:41:061// Copyright 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
avic0c60312015-12-21 21:03:505#include <stddef.h>
6#include <stdint.h>
7
8#include "base/macros.h"
mkwst28c7c112015-07-14 22:41:069#include "testing/gtest/include/gtest/gtest.h"
10#include "url/gurl.h"
11#include "url/scheme_host_port.h"
Charles Harrison60f0c532018-03-12 17:30:5512#include "url/url_util.h"
mkwst28c7c112015-07-14 22:41:0613
14namespace {
15
Nick Carter123ca192018-03-30 23:25:3616class SchemeHostPortTest : public testing::Test {
17 public:
18 SchemeHostPortTest() = default;
19 ~SchemeHostPortTest() override {
20 // Reset any added schemes.
21 url::Shutdown();
22 }
23
24 private:
25 DISALLOW_COPY_AND_ASSIGN(SchemeHostPortTest);
26};
27
csharrison6fbc9fa2016-10-08 03:31:5028void ExpectParsedUrlsEqual(const GURL& a, const GURL& b) {
29 EXPECT_EQ(a, b);
30 const url::Parsed& a_parsed = a.parsed_for_possibly_invalid_spec();
31 const url::Parsed& b_parsed = b.parsed_for_possibly_invalid_spec();
32 EXPECT_EQ(a_parsed.scheme.begin, b_parsed.scheme.begin);
33 EXPECT_EQ(a_parsed.scheme.len, b_parsed.scheme.len);
34 EXPECT_EQ(a_parsed.username.begin, b_parsed.username.begin);
35 EXPECT_EQ(a_parsed.username.len, b_parsed.username.len);
36 EXPECT_EQ(a_parsed.password.begin, b_parsed.password.begin);
37 EXPECT_EQ(a_parsed.password.len, b_parsed.password.len);
38 EXPECT_EQ(a_parsed.host.begin, b_parsed.host.begin);
39 EXPECT_EQ(a_parsed.host.len, b_parsed.host.len);
40 EXPECT_EQ(a_parsed.port.begin, b_parsed.port.begin);
41 EXPECT_EQ(a_parsed.port.len, b_parsed.port.len);
42 EXPECT_EQ(a_parsed.path.begin, b_parsed.path.begin);
43 EXPECT_EQ(a_parsed.path.len, b_parsed.path.len);
44 EXPECT_EQ(a_parsed.query.begin, b_parsed.query.begin);
45 EXPECT_EQ(a_parsed.query.len, b_parsed.query.len);
46 EXPECT_EQ(a_parsed.ref.begin, b_parsed.ref.begin);
47 EXPECT_EQ(a_parsed.ref.len, b_parsed.ref.len);
48}
49
Nick Carter123ca192018-03-30 23:25:3650TEST_F(SchemeHostPortTest, Invalid) {
mkwst28c7c112015-07-14 22:41:0651 url::SchemeHostPort invalid;
52 EXPECT_EQ("", invalid.scheme());
53 EXPECT_EQ("", invalid.host());
54 EXPECT_EQ(0, invalid.port());
55 EXPECT_TRUE(invalid.IsInvalid());
56 EXPECT_TRUE(invalid.Equals(invalid));
57
csharrison39a260f92017-01-09 22:24:1458 const char* urls[] = {
59 "data:text/html,Hello!", "javascript:alert(1)",
60 "file://example.com:443/etc/passwd",
61
62 // These schemes do not follow the generic URL syntax, so make sure we
63 // treat them as invalid (scheme, host, port) tuples (even though such
64 // URLs' _Origin_ might have a (scheme, host, port) tuple, they themselves
65 // do not). This is only *implicitly* checked in the code, by means of
66 // blob schemes not being standard, and filesystem schemes having type
67 // SCHEME_WITHOUT_AUTHORITY. If conditions change such that the implicit
68 // checks no longer hold, this policy should be made explicit.
69 "blob:https://example.com/uuid-goes-here",
70 "filesystem:https://example.com/temporary/yay.png"};
mkwst28c7c112015-07-14 22:41:0671
vmpstr981aa5a2016-07-14 01:05:0872 for (auto* test : urls) {
mkwst28c7c112015-07-14 22:41:0673 SCOPED_TRACE(test);
74 GURL url(test);
75 url::SchemeHostPort tuple(url);
76 EXPECT_EQ("", tuple.scheme());
77 EXPECT_EQ("", tuple.host());
78 EXPECT_EQ(0, tuple.port());
79 EXPECT_TRUE(tuple.IsInvalid());
80 EXPECT_TRUE(tuple.Equals(tuple));
81 EXPECT_TRUE(tuple.Equals(invalid));
82 EXPECT_TRUE(invalid.Equals(tuple));
csharrison6fbc9fa2016-10-08 03:31:5083 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwst28c7c112015-07-14 22:41:0684 }
85}
86
Nick Carter123ca192018-03-30 23:25:3687TEST_F(SchemeHostPortTest, ExplicitConstruction) {
mkwst28c7c112015-07-14 22:41:0688 struct TestCases {
89 const char* scheme;
90 const char* host;
avic0c60312015-12-21 21:03:5091 uint16_t port;
mkwst28c7c112015-07-14 22:41:0692 } cases[] = {
93 {"http", "example.com", 80},
94 {"http", "example.com", 123},
95 {"https", "example.com", 443},
96 {"https", "example.com", 123},
97 {"file", "", 0},
98 {"file", "example.com", 0},
99 };
100
101 for (const auto& test : cases) {
102 SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
103 << test.port);
104 url::SchemeHostPort tuple(test.scheme, test.host, test.port);
105 EXPECT_EQ(test.scheme, tuple.scheme());
106 EXPECT_EQ(test.host, tuple.host());
107 EXPECT_EQ(test.port, tuple.port());
108 EXPECT_FALSE(tuple.IsInvalid());
109 EXPECT_TRUE(tuple.Equals(tuple));
csharrison6fbc9fa2016-10-08 03:31:50110 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwst28c7c112015-07-14 22:41:06111 }
112}
113
Nick Carter123ca192018-03-30 23:25:36114TEST_F(SchemeHostPortTest, InvalidConstruction) {
mkwstd8335d982015-07-25 05:18:48115 struct TestCases {
116 const char* scheme;
117 const char* host;
avic0c60312015-12-21 21:03:50118 uint16_t port;
mkwstd8335d982015-07-25 05:18:48119 } cases[] = {{"", "", 0},
120 {"data", "", 0},
121 {"blob", "", 0},
122 {"filesystem", "", 0},
123 {"http", "", 80},
124 {"data", "example.com", 80},
125 {"http", "☃.net", 80},
126 {"http\nmore", "example.com", 80},
127 {"http\rmore", "example.com", 80},
128 {"http\n", "example.com", 80},
129 {"http\r", "example.com", 80},
130 {"http", "example.com\nnot-example.com", 80},
131 {"http", "example.com\rnot-example.com", 80},
132 {"http", "example.com\n", 80},
133 {"http", "example.com\r", 80},
134 {"http", "example.com", 0},
135 {"file", "", 80}};
136
137 for (const auto& test : cases) {
138 SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
139 << test.port);
140 url::SchemeHostPort tuple(test.scheme, test.host, test.port);
141 EXPECT_EQ("", tuple.scheme());
142 EXPECT_EQ("", tuple.host());
143 EXPECT_EQ(0, tuple.port());
144 EXPECT_TRUE(tuple.IsInvalid());
145 EXPECT_TRUE(tuple.Equals(tuple));
csharrison6fbc9fa2016-10-08 03:31:50146 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwstd8335d982015-07-25 05:18:48147 }
148}
149
Nick Carter123ca192018-03-30 23:25:36150TEST_F(SchemeHostPortTest, InvalidConstructionWithEmbeddedNulls) {
mkwstd8335d982015-07-25 05:18:48151 struct TestCases {
152 const char* scheme;
153 size_t scheme_length;
154 const char* host;
155 size_t host_length;
avic0c60312015-12-21 21:03:50156 uint16_t port;
mkwstd8335d982015-07-25 05:18:48157 } cases[] = {{"http\0more", 9, "example.com", 11, 80},
158 {"http\0", 5, "example.com", 11, 80},
159 {"\0http", 5, "example.com", 11, 80},
160 {"http", 4, "example.com\0not-example.com", 27, 80},
161 {"http", 4, "example.com\0", 12, 80},
162 {"http", 4, "\0example.com", 12, 80}};
163
164 for (const auto& test : cases) {
165 SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
166 << test.port);
167 url::SchemeHostPort tuple(std::string(test.scheme, test.scheme_length),
168 std::string(test.host, test.host_length),
169 test.port);
170 EXPECT_EQ("", tuple.scheme());
171 EXPECT_EQ("", tuple.host());
172 EXPECT_EQ(0, tuple.port());
173 EXPECT_TRUE(tuple.IsInvalid());
csharrison6fbc9fa2016-10-08 03:31:50174 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwstd8335d982015-07-25 05:18:48175 }
176}
177
Nick Carter123ca192018-03-30 23:25:36178TEST_F(SchemeHostPortTest, GURLConstruction) {
mkwst28c7c112015-07-14 22:41:06179 struct TestCases {
180 const char* url;
181 const char* scheme;
182 const char* host;
avic0c60312015-12-21 21:03:50183 uint16_t port;
mkwst28c7c112015-07-14 22:41:06184 } cases[] = {
185 {"http://192.168.9.1/", "http", "192.168.9.1", 80},
186 {"http://[2001:db8::1]/", "http", "[2001:db8::1]", 80},
187 {"http://☃.net/", "http", "xn--n3h.net", 80},
188 {"http://example.com/", "http", "example.com", 80},
189 {"http://example.com:123/", "http", "example.com", 123},
190 {"https://example.com/", "https", "example.com", 443},
191 {"https://example.com:123/", "https", "example.com", 123},
192 {"file:///etc/passwd", "file", "", 0},
193 {"file://example.com/etc/passwd", "file", "example.com", 0},
194 {"http://u:[email protected]/", "http", "example.com", 80},
195 {"http://u:[email protected]/path", "http", "example.com", 80},
196 {"http://u:[email protected]/path?123", "http", "example.com", 80},
197 {"http://u:[email protected]/path?123#hash", "http", "example.com", 80},
198 };
199
200 for (const auto& test : cases) {
201 SCOPED_TRACE(test.url);
202 GURL url(test.url);
203 EXPECT_TRUE(url.is_valid());
204 url::SchemeHostPort tuple(url);
205 EXPECT_EQ(test.scheme, tuple.scheme());
206 EXPECT_EQ(test.host, tuple.host());
207 EXPECT_EQ(test.port, tuple.port());
208 EXPECT_FALSE(tuple.IsInvalid());
209 EXPECT_TRUE(tuple.Equals(tuple));
csharrison6fbc9fa2016-10-08 03:31:50210 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwst28c7c112015-07-14 22:41:06211 }
212}
213
Nick Carter123ca192018-03-30 23:25:36214TEST_F(SchemeHostPortTest, Serialization) {
mkwst28c7c112015-07-14 22:41:06215 struct TestCases {
216 const char* url;
217 const char* expected;
218 } cases[] = {
219 {"http://192.168.9.1/", "http://192.168.9.1"},
220 {"http://[2001:db8::1]/", "http://[2001:db8::1]"},
221 {"http://☃.net/", "http://xn--n3h.net"},
222 {"http://example.com/", "http://example.com"},
223 {"http://example.com:123/", "http://example.com:123"},
224 {"https://example.com/", "https://example.com"},
225 {"https://example.com:123/", "https://example.com:123"},
226 {"file:///etc/passwd", "file://"},
227 {"file://example.com/etc/passwd", "file://example.com"},
228 };
229
230 for (const auto& test : cases) {
231 SCOPED_TRACE(test.url);
232 GURL url(test.url);
233 url::SchemeHostPort tuple(url);
234 EXPECT_EQ(test.expected, tuple.Serialize());
csharrison6fbc9fa2016-10-08 03:31:50235 ExpectParsedUrlsEqual(GURL(tuple.Serialize()), tuple.GetURL());
mkwst28c7c112015-07-14 22:41:06236 }
237}
238
Nick Carter123ca192018-03-30 23:25:36239TEST_F(SchemeHostPortTest, Comparison) {
mkwst28c7c112015-07-14 22:41:06240 // These tuples are arranged in increasing order:
241 struct SchemeHostPorts {
242 const char* scheme;
243 const char* host;
avic0c60312015-12-21 21:03:50244 uint16_t port;
mkwst28c7c112015-07-14 22:41:06245 } tuples[] = {
246 {"http", "a", 80},
247 {"http", "b", 80},
248 {"https", "a", 80},
249 {"https", "b", 80},
250 {"http", "a", 81},
251 {"http", "b", 81},
252 {"https", "a", 81},
253 {"https", "b", 81},
254 };
255
256 for (size_t i = 0; i < arraysize(tuples); i++) {
257 url::SchemeHostPort current(tuples[i].scheme, tuples[i].host,
258 tuples[i].port);
259 for (size_t j = i; j < arraysize(tuples); j++) {
260 url::SchemeHostPort to_compare(tuples[j].scheme, tuples[j].host,
261 tuples[j].port);
262 EXPECT_EQ(i < j, current < to_compare) << i << " < " << j;
263 EXPECT_EQ(j < i, to_compare < current) << j << " < " << i;
264 }
265 }
266}
267
Charles Harrison60f0c532018-03-12 17:30:55268// Some schemes have optional authority. Make sure that GURL conversion from
269// SchemeHostPort is not opinionated in that regard. For more info, See
270// crbug.com/820194, where we considered all SchemeHostPorts with
Nick Carter123ca192018-03-30 23:25:36271// SCHEME_WITH_HOST (i.e., without ports) as valid with empty hosts, even though
272// most are not (e.g. chrome URLs).
273TEST_F(SchemeHostPortTest, EmptyHostGurlConversion) {
274 url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST);
Charles Harrison60f0c532018-03-12 17:30:55275
276 GURL chrome_url("chrome:");
277 EXPECT_FALSE(chrome_url.is_valid());
278
279 url::SchemeHostPort chrome_tuple("chrome", "", 0);
280 EXPECT_FALSE(chrome_tuple.GetURL().is_valid());
281 ExpectParsedUrlsEqual(GURL(chrome_tuple.Serialize()), chrome_tuple.GetURL());
282 ExpectParsedUrlsEqual(chrome_url, chrome_tuple.GetURL());
283}
284
mkwst28c7c112015-07-14 22:41:06285} // namespace url