1/*
2 * Copyright (C) 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WTFStringUtilities.h"
28#include <wtf/MainThread.h>
29#include <wtf/URLParser.h>
30#include <wtf/text/StringBuilder.h>
31
32namespace TestWebKitAPI {
33
34class WTF_URLParser : public testing::Test {
35public:
36 void SetUp() final
37 {
38 WTF::initializeMainThread();
39 }
40};
41
42struct ExpectedParts {
43 String protocol;
44 String user;
45 String password;
46 String host;
47 unsigned short port;
48 String path;
49 String query;
50 String fragment;
51 String string;
52
53 bool isInvalid() const
54 {
55 return protocol.isEmpty()
56 && user.isEmpty()
57 && password.isEmpty()
58 && host.isEmpty()
59 && !port
60 && path.isEmpty()
61 && query.isEmpty()
62 && fragment.isEmpty();
63 }
64};
65
66template<typename T, typename U>
67bool eq(T&& s1, U&& s2)
68{
69 EXPECT_STREQ(s1.utf8().data(), s2.utf8().data());
70 return s1.utf8() == s2.utf8();
71}
72
73static String insertTabAtLocation(const String& string, size_t location)
74{
75 ASSERT(location <= string.length());
76 return makeString(string.substring(0, location), "\t", string.substring(location));
77}
78
79static ExpectedParts invalidParts(const String& urlStringWithTab)
80{
81 return {"", "", "", "", 0, "" , "", "", urlStringWithTab};
82}
83
84enum class TestTabs { No, Yes };
85
86// Inserting tabs between surrogate pairs changes the encoded value instead of being skipped by the URLParser.
87const TestTabs testTabsValueForSurrogatePairs = TestTabs::No;
88
89static void checkURL(const String& urlString, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
90{
91 auto url = URL(URL(), urlString);
92
93 EXPECT_TRUE(eq(parts.protocol, url.protocol()));
94 EXPECT_TRUE(eq(parts.user, url.user()));
95 EXPECT_TRUE(eq(parts.password, url.pass()));
96 EXPECT_TRUE(eq(parts.host, url.host()));
97 EXPECT_EQ(parts.port, url.port().valueOr(0));
98 EXPECT_TRUE(eq(parts.path, url.path()));
99 EXPECT_TRUE(eq(parts.query, url.query()));
100 EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
101 EXPECT_TRUE(eq(parts.string, url.string()));
102
103 EXPECT_TRUE(WTF::URLParser::internalValuesConsistent(url));
104
105 if (testTabs == TestTabs::No)
106 return;
107
108 for (size_t i = 0; i < urlString.length(); ++i) {
109 String urlStringWithTab = insertTabAtLocation(urlString, i);
110 checkURL(urlStringWithTab,
111 parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
112 TestTabs::No);
113 }
114}
115
116static void checkRelativeURL(const String& urlString, const String& baseURLString, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
117{
118 auto url = URL(URL(URL(), baseURLString), urlString);
119
120 EXPECT_TRUE(eq(parts.protocol, url.protocol()));
121 EXPECT_TRUE(eq(parts.user, url.user()));
122 EXPECT_TRUE(eq(parts.password, url.pass()));
123 EXPECT_TRUE(eq(parts.host, url.host()));
124 EXPECT_EQ(parts.port, url.port().valueOr(0));
125 EXPECT_TRUE(eq(parts.path, url.path()));
126 EXPECT_TRUE(eq(parts.query, url.query()));
127 EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
128 EXPECT_TRUE(eq(parts.string, url.string()));
129
130 EXPECT_TRUE(WTF::URLParser::internalValuesConsistent(url));
131
132 if (testTabs == TestTabs::No)
133 return;
134
135 for (size_t i = 0; i < urlString.length(); ++i) {
136 String urlStringWithTab = insertTabAtLocation(urlString, i);
137 checkRelativeURL(urlStringWithTab,
138 baseURLString,
139 parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
140 TestTabs::No);
141 }
142}
143
144static void checkURLDifferences(const String& urlString, const ExpectedParts& partsNew, const ExpectedParts& partsOld, TestTabs testTabs = TestTabs::Yes)
145{
146 UNUSED_PARAM(partsOld); // FIXME: Remove all the old expected parts.
147 auto url = URL(URL(), urlString);
148
149 EXPECT_TRUE(eq(partsNew.protocol, url.protocol()));
150 EXPECT_TRUE(eq(partsNew.user, url.user()));
151 EXPECT_TRUE(eq(partsNew.password, url.pass()));
152 EXPECT_TRUE(eq(partsNew.host, url.host()));
153 EXPECT_EQ(partsNew.port, url.port().valueOr(0));
154 EXPECT_TRUE(eq(partsNew.path, url.path()));
155 EXPECT_TRUE(eq(partsNew.query, url.query()));
156 EXPECT_TRUE(eq(partsNew.fragment, url.fragmentIdentifier()));
157 EXPECT_TRUE(eq(partsNew.string, url.string()));
158
159 EXPECT_TRUE(WTF::URLParser::internalValuesConsistent(url));
160
161 if (testTabs == TestTabs::No)
162 return;
163
164 for (size_t i = 0; i < urlString.length(); ++i) {
165 String urlStringWithTab = insertTabAtLocation(urlString, i);
166 checkURLDifferences(urlStringWithTab,
167 partsNew.isInvalid() ? invalidParts(urlStringWithTab) : partsNew,
168 partsOld.isInvalid() ? invalidParts(urlStringWithTab) : partsOld,
169 TestTabs::No);
170 }
171}
172
173static void checkRelativeURLDifferences(const String& urlString, const String& baseURLString, const ExpectedParts& partsNew, const ExpectedParts& partsOld, TestTabs testTabs = TestTabs::Yes)
174{
175 UNUSED_PARAM(partsOld); // FIXME: Remove all the old expected parts.
176 auto url = URL(URL(URL(), baseURLString), urlString);
177
178 EXPECT_TRUE(eq(partsNew.protocol, url.protocol()));
179 EXPECT_TRUE(eq(partsNew.user, url.user()));
180 EXPECT_TRUE(eq(partsNew.password, url.pass()));
181 EXPECT_TRUE(eq(partsNew.host, url.host()));
182 EXPECT_EQ(partsNew.port, url.port().valueOr(0));
183 EXPECT_TRUE(eq(partsNew.path, url.path()));
184 EXPECT_TRUE(eq(partsNew.query, url.query()));
185 EXPECT_TRUE(eq(partsNew.fragment, url.fragmentIdentifier()));
186 EXPECT_TRUE(eq(partsNew.string, url.string()));
187
188 EXPECT_TRUE(WTF::URLParser::internalValuesConsistent(url));
189
190 if (testTabs == TestTabs::No)
191 return;
192
193 for (size_t i = 0; i < urlString.length(); ++i) {
194 String urlStringWithTab = insertTabAtLocation(urlString, i);
195 checkRelativeURLDifferences(urlStringWithTab, baseURLString,
196 partsNew.isInvalid() ? invalidParts(urlStringWithTab) : partsNew,
197 partsOld.isInvalid() ? invalidParts(urlStringWithTab) : partsOld,
198 TestTabs::No);
199 }
200}
201
202static void shouldFail(const String& urlString)
203{
204 checkURL(urlString, {"", "", "", "", 0, "", "", "", urlString});
205}
206
207static void shouldFail(const String& urlString, const String& baseString)
208{
209 checkRelativeURL(urlString, baseString, {"", "", "", "", 0, "", "", "", urlString});
210}
211
212TEST_F(WTF_URLParser, Basic)
213{
214 checkURL("http://user:pass@webkit.org:123/path?query#fragment", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "fragment", "http://user:pass@webkit.org:123/path?query#fragment"});
215 checkURL("http://user:pass@webkit.org:123/path?query", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "", "http://user:pass@webkit.org:123/path?query"});
216 checkURL("http://user:pass@webkit.org:123/path", {"http", "user", "pass", "webkit.org", 123, "/path", "", "", "http://user:pass@webkit.org:123/path"});
217 checkURL("http://user:pass@webkit.org:123/", {"http", "user", "pass", "webkit.org", 123, "/", "", "", "http://user:pass@webkit.org:123/"});
218 checkURL("http://user:pass@webkit.org:123", {"http", "user", "pass", "webkit.org", 123, "/", "", "", "http://user:pass@webkit.org:123/"});
219 checkURL("http://user:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
220 checkURL("http://user:\t\t\tpass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
221 checkURL("http://us\ter:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
222 checkURL("http://user:pa\tss@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
223 checkURL("http://user:pass\t@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
224 checkURL("http://\tuser:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
225 checkURL("http://user\t:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
226 checkURL("http://webkit.org", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
227 checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
228 checkURL("http://webkit.org/", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
229 checkURL("http://webkit.org/path1/path2/index.html", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
230 checkURL("about:blank", {"about", "", "", "", 0, "blank", "", "", "about:blank"});
231 checkURL("about:blank?query", {"about", "", "", "", 0, "blank", "query", "", "about:blank?query"});
232 checkURL("about:blank#fragment", {"about", "", "", "", 0, "blank", "", "fragment", "about:blank#fragment"});
233 checkURL("http://[0::0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
234 checkURL("http://[0::]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
235 checkURL("http://[::]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
236 checkURL("http://[::0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
237 checkURL("http://[::0:0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
238 checkURL("http://[f::0:0]/", {"http", "", "", "[f::]", 0, "/", "", "", "http://[f::]/"});
239 checkURL("http://[f:0::f]/", {"http", "", "", "[f::f]", 0, "/", "", "", "http://[f::f]/"});
240 checkURL("http://[::0:ff]/", {"http", "", "", "[::ff]", 0, "/", "", "", "http://[::ff]/"});
241 checkURL("http://[::00:0:0:0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
242 checkURL("http://[::0:00:0:0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
243 checkURL("http://[::0:0.0.0.0]/", {"http", "", "", "[::]", 0, "/", "", "", "http://[::]/"});
244 checkURL("http://[0:f::f:f:0:0]", {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"});
245 checkURL("http://[0:f:0:0:f::]", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
246 checkURL("http://[::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
247 checkURL("http://[0:f:0:0:f::]:", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
248 checkURL("http://[0:f:0:0:f::]:\t", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
249 checkURL("http://[0:f:0:0:f::]\t:", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
250 checkURL("http://\t[::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
251 checkURL("http://[\t::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
252 checkURL("http://[:\t:f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
253 checkURL("http://[::\tf:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
254 checkURL("http://[::f\t:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
255 checkURL("http://[::f:\t0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
256 checkURL("http://example.com/path1/path2/.", {"http", "", "", "example.com", 0, "/path1/path2/", "", "", "http://example.com/path1/path2/"});
257 checkURL("http://example.com/path1/path2/..", {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"});
258 checkURL("http://example.com/path1/path2/./path3", {"http", "", "", "example.com", 0, "/path1/path2/path3", "", "", "http://example.com/path1/path2/path3"});
259 checkURL("http://example.com/path1/path2/.\\path3", {"http", "", "", "example.com", 0, "/path1/path2/path3", "", "", "http://example.com/path1/path2/path3"});
260 checkURL("http://example.com/path1/path2/../path3", {"http", "", "", "example.com", 0, "/path1/path3", "", "", "http://example.com/path1/path3"});
261 checkURL("http://example.com/path1/path2/..\\path3", {"http", "", "", "example.com", 0, "/path1/path3", "", "", "http://example.com/path1/path3"});
262 checkURL("http://example.com/.", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
263 checkURL("http://example.com/..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
264 checkURL("http://example.com/./path1", {"http", "", "", "example.com", 0, "/path1", "", "", "http://example.com/path1"});
265 checkURL("http://example.com/../path1", {"http", "", "", "example.com", 0, "/path1", "", "", "http://example.com/path1"});
266 checkURL("http://example.com/../path1/../../path2/path3/../path4", {"http", "", "", "example.com", 0, "/path2/path4", "", "", "http://example.com/path2/path4"});
267 checkURL("http://example.com/path1/.%2", {"http", "", "", "example.com", 0, "/path1/.%2", "", "", "http://example.com/path1/.%2"});
268 checkURL("http://example.com/path1/%2", {"http", "", "", "example.com", 0, "/path1/%2", "", "", "http://example.com/path1/%2"});
269 checkURL("http://example.com/path1/%", {"http", "", "", "example.com", 0, "/path1/%", "", "", "http://example.com/path1/%"});
270 checkURL("http://example.com/path1/.%", {"http", "", "", "example.com", 0, "/path1/.%", "", "", "http://example.com/path1/.%"});
271 checkURL("http://example.com//.", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
272 checkURL("http://example.com//./", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
273 checkURL("http://example.com//.//", {"http", "", "", "example.com", 0, "///", "", "", "http://example.com///"});
274 checkURL("http://example.com//..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
275 checkURL("http://example.com//../", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
276 checkURL("http://example.com//..//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
277 checkURL("http://example.com//..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
278 checkURL("http://example.com/.//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
279 checkURL("http://example.com/..//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
280 checkURL("http://example.com/./", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
281 checkURL("http://example.com/../", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
282 checkURL("http://example.com/path1/.../path3", {"http", "", "", "example.com", 0, "/path1/.../path3", "", "", "http://example.com/path1/.../path3"});
283 checkURL("http://example.com/path1/...", {"http", "", "", "example.com", 0, "/path1/...", "", "", "http://example.com/path1/..."});
284 checkURL("http://example.com/path1/.../", {"http", "", "", "example.com", 0, "/path1/.../", "", "", "http://example.com/path1/.../"});
285 checkURL("http://example.com/.path1/", {"http", "", "", "example.com", 0, "/.path1/", "", "", "http://example.com/.path1/"});
286 checkURL("http://example.com/..path1/", {"http", "", "", "example.com", 0, "/..path1/", "", "", "http://example.com/..path1/"});
287 checkURL("http://example.com/path1/.path2", {"http", "", "", "example.com", 0, "/path1/.path2", "", "", "http://example.com/path1/.path2"});
288 checkURL("http://example.com/path1/..path2", {"http", "", "", "example.com", 0, "/path1/..path2", "", "", "http://example.com/path1/..path2"});
289 checkURL("http://example.com/path1/path2/.?query", {"http", "", "", "example.com", 0, "/path1/path2/", "query", "", "http://example.com/path1/path2/?query"});
290 checkURL("http://example.com/path1/path2/..?query", {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"});
291 checkURL("http://example.com/path1/path2/.#fragment", {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"});
292 checkURL("http://example.com/path1/path2/..#fragment", {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"});
293
294 checkURL("file:", {"file", "", "", "", 0, "/", "", "", "file:///"});
295 checkURL("file:/", {"file", "", "", "", 0, "/", "", "", "file:///"});
296 checkURL("file://", {"file", "", "", "", 0, "/", "", "", "file:///"});
297 checkURL("file:///", {"file", "", "", "", 0, "/", "", "", "file:///"});
298 checkURL("file:////", {"file", "", "", "", 0, "//", "", "", "file:////"}); // This matches Firefox and URL::parse which I believe are correct, but not Chrome.
299 checkURL("file:/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
300 checkURL("file://host/path", {"file", "", "", "host", 0, "/path", "", "", "file://host/path"});
301 checkURL("file://host", {"file", "", "", "host", 0, "/", "", "", "file://host/"});
302 checkURL("file://host/", {"file", "", "", "host", 0, "/", "", "", "file://host/"});
303 checkURL("file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
304 checkURL("file:////path", {"file", "", "", "", 0, "//path", "", "", "file:////path"});
305 checkURL("file://localhost/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
306 checkURL("file://localhost/", {"file", "", "", "", 0, "/", "", "", "file:///"});
307 checkURL("file://localhost", {"file", "", "", "", 0, "/", "", "", "file:///"});
308 checkURL("file://lOcAlHoSt", {"file", "", "", "", 0, "/", "", "", "file:///"});
309 checkURL("file://lOcAlHoSt/", {"file", "", "", "", 0, "/", "", "", "file:///"});
310 checkURL("file:/pAtH/", {"file", "", "", "", 0, "/pAtH/", "", "", "file:///pAtH/"});
311 checkURL("file:/pAtH", {"file", "", "", "", 0, "/pAtH", "", "", "file:///pAtH"});
312 checkURL("file:?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
313 checkURL("file:#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
314 checkURL("file:?query#fragment", {"file", "", "", "", 0, "/", "query", "fragment", "file:///?query#fragment"});
315 checkURL("file:#fragment?notquery", {"file", "", "", "", 0, "/", "", "fragment?notquery", "file:///#fragment?notquery"});
316 checkURL("file:/?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
317 checkURL("file:/#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
318 checkURL("file://?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
319 checkURL("file://#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
320 checkURL("file:///?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
321 checkURL("file:///#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
322 checkURL("file:////?query", {"file", "", "", "", 0, "//", "query", "", "file:////?query"});
323 checkURL("file:////#fragment", {"file", "", "", "", 0, "//", "", "fragment", "file:////#fragment"});
324 checkURL("file://?Q", {"file", "", "", "", 0, "/", "Q", "", "file:///?Q"});
325 checkURL("file://#F", {"file", "", "", "", 0, "/", "", "F", "file:///#F"});
326 checkURL("file://host?Q", {"file", "", "", "host", 0, "/", "Q", "", "file://host/?Q"});
327 checkURL("file://host#F", {"file", "", "", "host", 0, "/", "", "F", "file://host/#F"});
328 checkURL("file://host\\P", {"file", "", "", "host", 0, "/P", "", "", "file://host/P"});
329 checkURL("file://host\\?Q", {"file", "", "", "host", 0, "/", "Q", "", "file://host/?Q"});
330 checkURL("file://host\\../P", {"file", "", "", "host", 0, "/P", "", "", "file://host/P"});
331 checkURL("file://host\\/../P", {"file", "", "", "host", 0, "/P", "", "", "file://host/P"});
332 checkURL("file://host\\/P", {"file", "", "", "host", 0, "//P", "", "", "file://host//P"});
333 checkURL("http://host/A b", {"http", "", "", "host", 0, "/A%20b", "", "", "http://host/A%20b"});
334 checkURL("http://host/a%20B", {"http", "", "", "host", 0, "/a%20B", "", "", "http://host/a%20B"});
335 checkURL("http://host?q=@ <>!#fragment", {"http", "", "", "host", 0, "/", "q=@%20%3C%3E!", "fragment", "http://host/?q=@%20%3C%3E!#fragment"});
336 checkURL("http://user:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
337 checkURL("http://user:@\thost", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
338 checkURL("http://user:\t@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
339 checkURL("http://user\t:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
340 checkURL("http://use\tr:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
341 checkURL("http://127.0.0.1:10100/path", {"http", "", "", "127.0.0.1", 10100, "/path", "", "", "http://127.0.0.1:10100/path"});
342 checkURL("http://127.0.0.1:/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
343 checkURL("http://127.0.0.1\t:/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
344 checkURL("http://127.0.0.1:\t/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
345 checkURL("http://127.0.0.1:/\tpath", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
346 checkURL("http://127.0.0.1:123", {"http", "", "", "127.0.0.1", 123, "/", "", "", "http://127.0.0.1:123/"});
347 checkURL("http://127.0.0.1:", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
348 checkURL("ws://08./", {"ws", "", "", "08.", 0, "/", "", "", "ws://08./"});
349 checkURL("http://[0:f::f:f:0:0]:123/path", {"http", "", "", "[0:f::f:f:0:0]", 123, "/path", "", "", "http://[0:f::f:f:0:0]:123/path"});
350 checkURL("http://[0:f::f:f:0:0]:123", {"http", "", "", "[0:f::f:f:0:0]", 123, "/", "", "", "http://[0:f::f:f:0:0]:123/"});
351 checkURL("http://[0:f:0:0:f:\t:]:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
352 checkURL("http://[0:f:0:0:f::\t]:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
353 checkURL("http://[0:f:0:0:f::]\t:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
354 checkURL("http://[0:f:0:0:f::]:\t123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
355 checkURL("http://[0:f:0:0:f::]:1\t23", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
356 checkURL("http://[0:f::f:f:0:0]:/path", {"http", "", "", "[0:f::f:f:0:0]", 0, "/path", "", "", "http://[0:f::f:f:0:0]/path"});
357 checkURL("a://[::2:]", {"a", "", "", "[::2]", 0, "", "", "", "a://[::2]"});
358 checkURL("http://[0:f::f:f:0:0]:", {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"});
359 checkURL("http://host:10100/path", {"http", "", "", "host", 10100, "/path", "", "", "http://host:10100/path"});
360 checkURL("http://host:/path", {"http", "", "", "host", 0, "/path", "", "", "http://host/path"});
361 checkURL("http://host:123", {"http", "", "", "host", 123, "/", "", "", "http://host:123/"});
362 checkURL("http://host:", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
363 checkURL("http://hos\tt\n:\t1\n2\t3\t/\npath", {"http", "", "", "host", 123, "/path", "", "", "http://host:123/path"});
364 checkURL("http://user@example.org/path3", {"http", "user", "", "example.org", 0, "/path3", "", "", "http://user@example.org/path3"});
365 checkURL("sc:/pa/pa", {"sc", "", "", "", 0, "/pa/pa", "", "", "sc:/pa/pa"});
366 checkURL("sc:/pa", {"sc", "", "", "", 0, "/pa", "", "", "sc:/pa"});
367 checkURL("sc:/pa/", {"sc", "", "", "", 0, "/pa/", "", "", "sc:/pa/"});
368 checkURL("notspecial:/notuser:notpassword@nothost", {"notspecial", "", "", "", 0, "/notuser:notpassword@nothost", "", "", "notspecial:/notuser:notpassword@nothost"});
369 checkURL("sc://pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
370 checkURL("sc://\tpa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
371 checkURL("sc:/\t/pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
372 checkURL("sc:\t//pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
373 checkURL("http://host \a ", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
374 checkURL("notspecial:/a", {"notspecial", "", "", "", 0, "/a", "", "", "notspecial:/a"});
375 checkURL("notspecial:", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
376 checkURL("http:/a", {"http", "", "", "a", 0, "/", "", "", "http://a/"});
377 checkURL("http://256../", {"http", "", "", "256..", 0, "/", "", "", "http://256../"});
378 checkURL("http://256..", {"http", "", "", "256..", 0, "/", "", "", "http://256../"});
379 checkURL("http://127..1/", {"http", "", "", "127..1", 0, "/", "", "", "http://127..1/"});
380 checkURL("http://127.a.0.1/", {"http", "", "", "127.a.0.1", 0, "/", "", "", "http://127.a.0.1/"});
381 checkURL("http://127.0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
382 checkURL("http://12\t7.0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
383 checkURL("http://127.\t0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
384 checkURL("http://./", {"http", "", "", ".", 0, "/", "", "", "http://./"});
385 checkURL("http://.", {"http", "", "", ".", 0, "/", "", "", "http://./"});
386 checkURL("notspecial:/a", {"notspecial", "", "", "", 0, "/a", "", "", "notspecial:/a"});
387 checkURL("notspecial:", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
388 checkURL("notspecial:/", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
389 checkURL("data:image/png;base64,encoded-data-follows-here", {"data", "", "", "", 0, "image/png;base64,encoded-data-follows-here", "", "", "data:image/png;base64,encoded-data-follows-here"});
390 checkURL("data:image/png;base64,encoded/data-with-slash", {"data", "", "", "", 0, "image/png;base64,encoded/data-with-slash", "", "", "data:image/png;base64,encoded/data-with-slash"});
391 checkURL("about:~", {"about", "", "", "", 0, "~", "", "", "about:~"});
392 checkURL("https://@test@test@example:800\\path@end", {"", "", "", "", 0, "", "", "", "https://@test@test@example:800\\path@end"});
393 checkURL("http://www.example.com/#a\nb\rc\td", {"http", "", "", "www.example.com", 0, "/", "", "abcd", "http://www.example.com/#abcd"});
394 checkURL("http://[A:b:c:DE:fF:0:1:aC]/", {"http", "", "", "[a:b:c:de:ff:0:1:ac]", 0, "/", "", "", "http://[a:b:c:de:ff:0:1:ac]/"});
395 checkURL("http:////////user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
396 checkURL("http:////////user:@webkit.org:99#foo", {"http", "user", "", "webkit.org", 99, "/", "", "foo", "http://user@webkit.org:99/#foo"});
397 checkURL("http:////\t////user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
398 checkURL("http://\t//\\///user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
399 checkURL("http:/\\user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
400 checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
401 checkURLDifferences("http://127.0.0.1.",
402 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
403 {"http", "", "", "127.0.0.1.", 0, "/", "", "", "http://127.0.0.1./"});
404 checkURLDifferences("http://127.0.0.1./",
405 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
406 {"http", "", "", "127.0.0.1.", 0, "/", "", "", "http://127.0.0.1./"});
407 checkURL("http://127.0.0.1../", {"http", "", "", "127.0.0.1..", 0, "/", "", "", "http://127.0.0.1../"});
408 checkURLDifferences("http://0x100.0/",
409 {"", "", "", "", 0, "", "", "", "http://0x100.0/"},
410 {"http", "", "", "0x100.0", 0, "/", "", "", "http://0x100.0/"});
411 checkURLDifferences("http://0.0.0x100.0/",
412 {"", "", "", "", 0, "", "", "", "http://0.0.0x100.0/"},
413 {"http", "", "", "0.0.0x100.0", 0, "/", "", "", "http://0.0.0x100.0/"});
414 checkURLDifferences("http://0.0.0.0x100/",
415 {"", "", "", "", 0, "", "", "", "http://0.0.0.0x100/"},
416 {"http", "", "", "0.0.0.0x100", 0, "/", "", "", "http://0.0.0.0x100/"});
417 checkURL("http://host:123?", {"http", "", "", "host", 123, "/", "", "", "http://host:123/?"});
418 checkURL("http://host:123?query", {"http", "", "", "host", 123, "/", "query", "", "http://host:123/?query"});
419 checkURL("http://host:123#", {"http", "", "", "host", 123, "/", "", "", "http://host:123/#"});
420 checkURL("http://host:123#fragment", {"http", "", "", "host", 123, "/", "", "fragment", "http://host:123/#fragment"});
421 checkURLDifferences("foo:////",
422 {"foo", "", "", "", 0, "//", "", "", "foo:////"},
423 {"foo", "", "", "", 0, "////", "", "", "foo:////"});
424 checkURLDifferences("foo:///?",
425 {"foo", "", "", "", 0, "/", "", "", "foo:///?"},
426 {"foo", "", "", "", 0, "///", "", "", "foo:///?"});
427 checkURLDifferences("foo:///#",
428 {"foo", "", "", "", 0, "/", "", "", "foo:///#"},
429 {"foo", "", "", "", 0, "///", "", "", "foo:///#"});
430 checkURLDifferences("foo:///",
431 {"foo", "", "", "", 0, "/", "", "", "foo:///"},
432 {"foo", "", "", "", 0, "///", "", "", "foo:///"});
433 checkURLDifferences("foo://?",
434 {"foo", "", "", "", 0, "", "", "", "foo://?"},
435 {"foo", "", "", "", 0, "//", "", "", "foo://?"});
436 checkURLDifferences("foo://#",
437 {"foo", "", "", "", 0, "", "", "", "foo://#"},
438 {"foo", "", "", "", 0, "//", "", "", "foo://#"});
439 checkURLDifferences("foo://",
440 {"foo", "", "", "", 0, "", "", "", "foo://"},
441 {"foo", "", "", "", 0, "//", "", "", "foo://"});
442 checkURL("foo:/?", {"foo", "", "", "", 0, "/", "", "", "foo:/?"});
443 checkURL("foo:/#", {"foo", "", "", "", 0, "/", "", "", "foo:/#"});
444 checkURL("foo:/", {"foo", "", "", "", 0, "/", "", "", "foo:/"});
445 checkURL("foo:?", {"foo", "", "", "", 0, "", "", "", "foo:?"});
446 checkURL("foo:#", {"foo", "", "", "", 0, "", "", "", "foo:#"});
447 checkURLDifferences("A://",
448 {"a", "", "", "", 0, "", "", "", "a://"},
449 {"a", "", "", "", 0, "//", "", "", "a://"});
450 checkURLDifferences("aA://",
451 {"aa", "", "", "", 0, "", "", "", "aa://"},
452 {"aa", "", "", "", 0, "//", "", "", "aa://"});
453 checkURL(utf16String(u"foo://host/#ПП\u0007 a</"), {"foo", "", "", "host", 0, "/", "", "%D0%9F%D0%9F%07 a</", "foo://host/#%D0%9F%D0%9F%07 a</"});
454 checkURL(utf16String(u"foo://host/#\u0007 a</"), {"foo", "", "", "host", 0, "/", "", "%07 a</", "foo://host/#%07 a</"});
455 checkURL(utf16String(u"http://host?ß😍#ß😍"), {"http", "", "", "host", 0, "/", "%C3%9F%F0%9F%98%8D", "%C3%9F%F0%9F%98%8D", "http://host/?%C3%9F%F0%9F%98%8D#%C3%9F%F0%9F%98%8D"}, testTabsValueForSurrogatePairs);
456 checkURL(utf16String(u"http://host/path#💩\t💩"), {"http", "", "", "host", 0, "/path", "", "%F0%9F%92%A9%F0%9F%92%A9", "http://host/path#%F0%9F%92%A9%F0%9F%92%A9"}, testTabsValueForSurrogatePairs);
457 checkURL(utf16String(u"http://host/#ПП\u0007 a</"), {"http", "", "", "host", 0, "/", "", "%D0%9F%D0%9F%07 a</", "http://host/#%D0%9F%D0%9F%07 a</"});
458 checkURL(utf16String(u"http://host/#\u0007 a</"), {"http", "", "", "host", 0, "/", "", "%07 a</", "http://host/#%07 a</"});
459
460 // This disagrees with the web platform test for http://:@www.example.com but agrees with Chrome and URL::parse,
461 // and Firefox fails the web platform test differently. Maybe the web platform test ought to be changed.
462 checkURL("http://:@host", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
463}
464
465static void testUserPass(const String& value, const String& decoded, const String& encoded)
466{
467 URL userURL(URL(), makeString("http://", value, "@example.com/"));
468 URL passURL(URL(), makeString("http://user:", value, "@example.com/"));
469 EXPECT_EQ(encoded, userURL.encodedUser());
470 EXPECT_EQ(encoded, passURL.encodedPass());
471 EXPECT_EQ(decoded, userURL.user());
472 EXPECT_EQ(decoded, passURL.pass());
473}
474
475static void testUserPass(const String& value, const String& encoded)
476{
477 testUserPass(value, value, encoded);
478}
479
480TEST_F(WTF_URLParser, Credentials)
481{
482 auto validSurrogate = utf16String<3>({0xD800, 0xDD55, '\0'});
483 auto invalidSurrogate = utf16String<3>({0xD800, 'A', '\0'});
484 auto replacementA = utf16String<3>({0xFFFD, 'A', '\0'});
485
486 testUserPass("a", "a");
487 testUserPass("%", "%");
488 testUserPass("%25", "%", "%25");
489 testUserPass("%2525", "%25", "%2525");
490 testUserPass("%FX", "%FX");
491 testUserPass("%00", String::fromUTF8("\0", 1), "%00");
492 testUserPass("%F%25", "%F%", "%F%25");
493 testUserPass("%X%25", "%X%", "%X%25");
494 testUserPass("%%25", "%%", "%%25");
495 testUserPass("💩", "%C3%B0%C2%9F%C2%92%C2%A9");
496 testUserPass("%💩", "%%C3%B0%C2%9F%C2%92%C2%A9");
497 testUserPass(validSurrogate, "%F0%90%85%95");
498 testUserPass(replacementA, "%EF%BF%BDA");
499 testUserPass(invalidSurrogate, replacementA, "%EF%BF%BDA");
500}
501
502TEST_F(WTF_URLParser, ParseRelative)
503{
504 checkRelativeURL("/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "webkit.org", 0, "/index.html", "", "", "http://webkit.org/index.html"});
505 checkRelativeURL("http://whatwg.org/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "whatwg.org", 0, "/index.html", "", "", "http://whatwg.org/index.html"});
506 checkRelativeURL("index.html", "http://webkit.org/path1/path2/page.html?query#fragment", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
507 checkRelativeURL("//whatwg.org/index.html", "https://www.webkit.org/path", {"https", "", "", "whatwg.org", 0, "/index.html", "", "", "https://whatwg.org/index.html"});
508 checkRelativeURL("http://example\t.\norg", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/", "", "", "http://example.org/"});
509 checkRelativeURL("test", "file:///path1/path2", {"file", "", "", "", 0, "/path1/test", "", "", "file:///path1/test"});
510 checkRelativeURL(utf16String(u"http://www.foo。bar.com"), "http://other.com/", {"http", "", "", "www.foo.bar.com", 0, "/", "", "", "http://www.foo.bar.com/"});
511 checkRelativeURLDifferences(utf16String(u"sc://ñ.test/"), "about:blank",
512 {"sc", "", "", "%C3%B1.test", 0, "/", "", "", "sc://%C3%B1.test/"},
513 {"sc", "", "", "xn--ida.test", 0, "/", "", "", "sc://xn--ida.test/"});
514 checkRelativeURL("#fragment", "http://host/path", {"http", "", "", "host", 0, "/path", "", "fragment", "http://host/path#fragment"});
515 checkRelativeURL("#fragment", "file:///path", {"file", "", "", "", 0, "/path", "", "fragment", "file:///path#fragment"});
516 checkRelativeURL("#fragment", "file:///path#old", {"file", "", "", "", 0, "/path", "", "fragment", "file:///path#fragment"});
517 checkRelativeURL("#", "file:///path#old", {"file", "", "", "", 0, "/path", "", "", "file:///path#"});
518 checkRelativeURL(" ", "file:///path#old", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
519 checkRelativeURL("#", "file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path#"});
520 checkRelativeURL("#", "file:///path?query", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query#"});
521 checkRelativeURL("#", "file:///path?query#old", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query#"});
522 checkRelativeURL("?query", "http://host/path", {"http", "", "", "host", 0, "/path", "query", "", "http://host/path?query"});
523 checkRelativeURL("?query#fragment", "http://host/path", {"http", "", "", "host", 0, "/path", "query", "fragment", "http://host/path?query#fragment"});
524 checkRelativeURL("?new", "file:///path?old#fragment", {"file", "", "", "", 0, "/path", "new", "", "file:///path?new"});
525 checkRelativeURL("?", "file:///path?old#fragment", {"file", "", "", "", 0, "/path", "", "", "file:///path?"});
526 checkRelativeURL("?", "file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path?"});
527 checkRelativeURL("?query", "file:///path", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query"});
528 checkRelativeURL(utf16String(u"?β"), "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "%CE%B2", "", "http://example.org/foo/bar?%CE%B2"});
529 checkRelativeURL("?", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar?"});
530 checkRelativeURL("#", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar#"});
531 checkRelativeURL("?#", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar?#"});
532 checkRelativeURL("#?", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "?", "http://example.org/foo/bar#?"});
533 checkRelativeURL("/", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/", "", "", "http://example.org/"});
534 checkRelativeURL("http://@host", "about:blank", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
535 checkRelativeURL("http://:@host", "about:blank", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
536 checkRelativeURL("http://foo.com/\\@", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "//@", "", "", "http://foo.com//@"});
537 checkRelativeURL("\\@", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/@", "", "", "http://example.org/@"});
538 checkRelativeURL("/path3", "http://user@example.org/path1/path2", {"http", "user", "", "example.org", 0, "/path3", "", "", "http://user@example.org/path3"});
539 checkRelativeURL("", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
540 checkRelativeURL("\t", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
541 checkRelativeURL(" ", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
542 checkRelativeURL(" \a \t\n", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
543 checkRelativeURL(":foo.com\\", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/:foo.com/", "", "", "http://example.org/foo/:foo.com/"});
544 checkRelativeURL("http:/example.com/", "about:blank", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
545 checkRelativeURL("http:example.com/", "about:blank", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
546 checkRelativeURL("http:\\\\foo.com\\", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
547 checkRelativeURL("http:\\\\foo.com/", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
548 checkRelativeURL("http:\\\\foo.com", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
549 checkRelativeURL("http://ExAmPlE.CoM", "http://other.com", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
550 checkRelativeURL("http:", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
551 checkRelativeURL("#x", "data:,", {"data", "", "", "", 0, ",", "", "x", "data:,#x"});
552 checkRelativeURL("#x", "about:blank", {"about", "", "", "", 0, "blank", "", "x", "about:blank#x"});
553 checkRelativeURL(" foo.com ", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/foo.com", "", "", "http://example.org/foo/foo.com"});
554 checkRelativeURL(" \a baz", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/baz", "", "", "http://example.org/foo/baz"});
555 checkRelativeURL("~", "http://example.org", {"http", "", "", "example.org", 0, "/~", "", "", "http://example.org/~"});
556 checkRelativeURL("notspecial:", "about:blank", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
557 checkRelativeURL("notspecial:", "http://host", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
558 checkRelativeURL("http:", "http://host", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
559 checkRelativeURL("i", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
560 checkRelativeURL("i ", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
561 checkRelativeURL("i\t\n ", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
562 checkRelativeURL("i", "sc://ho/pa", {"sc", "", "", "ho", 0, "/i", "", "", "sc://ho/i"});
563 checkRelativeURL("!", "sc://ho/pa", {"sc", "", "", "ho", 0, "/!", "", "", "sc://ho/!"});
564 checkRelativeURL("!", "sc:/ho/pa", {"sc", "", "", "", 0, "/ho/!", "", "", "sc:/ho/!"});
565 checkRelativeURL("notspecial:/", "about:blank", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
566 checkRelativeURL("notspecial:/", "http://host", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
567 checkRelativeURL("foo:/", "http://example.org/foo/bar", {"foo", "", "", "", 0, "/", "", "", "foo:/"});
568 checkRelativeURL("://:0/", "http://webkit.org/", {"http", "", "", "webkit.org", 0, "/://:0/", "", "", "http://webkit.org/://:0/"});
569 checkRelativeURL(String(), "http://webkit.org/", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
570 checkRelativeURL("https://@test@test@example:800\\path@end", "http://doesnotmatter/", {"", "", "", "", 0, "", "", "", "https://@test@test@example:800\\path@end"});
571 checkRelativeURL("http://f:0/c", "http://example.org/foo/bar", {"http", "", "", "f", 0, "/c", "", "", "http://f:0/c"});
572 checkRelativeURL(String(), "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
573 checkRelativeURL("", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
574 checkRelativeURL(" ", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
575 checkRelativeURL(" ", "http://host/path?query#fra#gment", {"http", "", "", "host", 0, "/path", "query", "", "http://host/path?query"});
576 checkRelativeURL(" \a ", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
577 checkRelativeURLDifferences("foo://", "http://example.org/foo/bar",
578 {"foo", "", "", "", 0, "", "", "", "foo://"},
579 {"foo", "", "", "", 0, "//", "", "", "foo://"});
580 checkRelativeURL(utf16String(u"#β"), "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "%CE%B2", "http://example.org/foo/bar#%CE%B2"});
581 checkRelativeURL("index.html", "applewebdata://Host/", {"applewebdata", "", "", "Host", 0, "/index.html", "", "", "applewebdata://Host/index.html"});
582 checkRelativeURL("index.html", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "/index.html", "", "", "applewebdata://Host/index.html"});
583 checkRelativeURL("", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "", "", "applewebdata://Host"});
584 checkRelativeURL("?query", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "query", "", "applewebdata://Host?query"});
585 checkRelativeURL("#fragment", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "", "fragment", "applewebdata://Host#fragment"});
586 checkRelativeURL("notspecial://something?", "file:////var//containers//stuff/", {"notspecial", "", "", "something", 0, "", "", "", "notspecial://something?"}, TestTabs::No);
587 checkRelativeURL("notspecial://something#", "file:////var//containers//stuff/", {"notspecial", "", "", "something", 0, "", "", "", "notspecial://something#"}, TestTabs::No);
588 checkRelativeURL("http://something?", "file:////var//containers//stuff/", {"http", "", "", "something", 0, "/", "", "", "http://something/?"}, TestTabs::No);
589 checkRelativeURL("http://something#", "file:////var//containers//stuff/", {"http", "", "", "something", 0, "/", "", "", "http://something/#"}, TestTabs::No);
590 checkRelativeURL("file:", "file:///path?query#fragment", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query"});
591 checkRelativeURL("/", "file:///C:/a/b", {"file", "", "", "", 0, "/C:/", "", "", "file:///C:/"});
592 checkRelativeURL("/abc", "file:///C:/a/b", {"file", "", "", "", 0, "/C:/abc", "", "", "file:///C:/abc"});
593 checkRelativeURL("/abc", "file:///C:", {"file", "", "", "", 0, "/C:/abc", "", "", "file:///C:/abc"});
594 checkRelativeURL("/abc", "file:///", {"file", "", "", "", 0, "/abc", "", "", "file:///abc"});
595 checkRelativeURL("//d:", "file:///C:/a/b", {"file", "", "", "", 0, "/d:", "", "", "file:///d:"}, TestTabs::No);
596 checkRelativeURL("//d|", "file:///C:/a/b", {"file", "", "", "", 0, "/d:", "", "", "file:///d:"}, TestTabs::No);
597 checkRelativeURL("//A|", "file:///C:/a/b", {"file", "", "", "", 0, "/A:", "", "", "file:///A:"}, TestTabs::No);
598
599 // The checking of slashes in SpecialAuthoritySlashes needed to get this to pass contradicts what is in the spec,
600 // but it is included in the web platform tests.
601 checkRelativeURL("http:\\\\host\\foo", "about:blank", {"http", "", "", "host", 0, "/foo", "", "", "http://host/foo"});
602}
603
604// These are differences between the new URLParser and the old URL::parse which make URLParser more standards compliant.
605TEST_F(WTF_URLParser, ParserDifferences)
606{
607 checkURLDifferences("http://127.0.1",
608 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
609 {"http", "", "", "127.0.1", 0, "/", "", "", "http://127.0.1/"});
610 checkURLDifferences("http://011.11.0X11.0x011",
611 {"http", "", "", "9.11.17.17", 0, "/", "", "", "http://9.11.17.17/"},
612 {"http", "", "", "011.11.0x11.0x011", 0, "/", "", "", "http://011.11.0x11.0x011/"});
613 checkURLDifferences("http://[1234:0078:90AB:CdEf:0123:0007:89AB:0000]",
614 {"http", "", "", "[1234:78:90ab:cdef:123:7:89ab:0]", 0, "/", "", "", "http://[1234:78:90ab:cdef:123:7:89ab:0]/"},
615 {"http", "", "", "[1234:0078:90ab:cdef:0123:0007:89ab:0000]", 0, "/", "", "", "http://[1234:0078:90ab:cdef:0123:0007:89ab:0000]/"});
616 checkURLDifferences("http://[0:f:0:0:f:f:0:0]",
617 {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"},
618 {"http", "", "", "[0:f:0:0:f:f:0:0]", 0, "/", "", "", "http://[0:f:0:0:f:f:0:0]/"});
619 checkURLDifferences("http://[0:f:0:0:f:0:0:0]",
620 {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"},
621 {"http", "", "", "[0:f:0:0:f:0:0:0]", 0, "/", "", "", "http://[0:f:0:0:f:0:0:0]/"});
622 checkURLDifferences("http://[0:0:f:0:0:f:0:0]",
623 {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"},
624 {"http", "", "", "[0:0:f:0:0:f:0:0]", 0, "/", "", "", "http://[0:0:f:0:0:f:0:0]/"});
625 checkURLDifferences("http://[a:0:0:0:b:c::d]",
626 {"http", "", "", "[a::b:c:0:d]", 0, "/", "", "", "http://[a::b:c:0:d]/"},
627 {"http", "", "", "[a:0:0:0:b:c::d]", 0, "/", "", "", "http://[a:0:0:0:b:c::d]/"});
628 checkURLDifferences("http://[::7f00:0001]/",
629 {"http", "", "", "[::7f00:1]", 0, "/", "", "", "http://[::7f00:1]/"},
630 {"http", "", "", "[::7f00:0001]", 0, "/", "", "", "http://[::7f00:0001]/"});
631 checkURLDifferences("http://[::7f00:00]/",
632 {"http", "", "", "[::7f00:0]", 0, "/", "", "", "http://[::7f00:0]/"},
633 {"http", "", "", "[::7f00:00]", 0, "/", "", "", "http://[::7f00:00]/"});
634 checkURLDifferences("http://[::0:7f00:0001]/",
635 {"http", "", "", "[::7f00:1]", 0, "/", "", "", "http://[::7f00:1]/"},
636 {"http", "", "", "[::0:7f00:0001]", 0, "/", "", "", "http://[::0:7f00:0001]/"});
637 checkURLDifferences("http://127.00.0.1/",
638 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
639 {"http", "", "", "127.00.0.1", 0, "/", "", "", "http://127.00.0.1/"});
640 checkURLDifferences("http://127.0.0.01/",
641 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
642 {"http", "", "", "127.0.0.01", 0, "/", "", "", "http://127.0.0.01/"});
643 checkURLDifferences("http://example.com/path1/.%2e",
644 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
645 {"http", "", "", "example.com", 0, "/path1/.%2e", "", "", "http://example.com/path1/.%2e"});
646 checkURLDifferences("http://example.com/path1/.%2E",
647 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
648 {"http", "", "", "example.com", 0, "/path1/.%2E", "", "", "http://example.com/path1/.%2E"});
649 checkURLDifferences("http://example.com/path1/.%2E/",
650 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
651 {"http", "", "", "example.com", 0, "/path1/.%2E/", "", "", "http://example.com/path1/.%2E/"});
652 checkURLDifferences("http://example.com/path1/%2e.",
653 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
654 {"http", "", "", "example.com", 0, "/path1/%2e.", "", "", "http://example.com/path1/%2e."});
655 checkURLDifferences("http://example.com/path1/%2E%2e",
656 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
657 {"http", "", "", "example.com", 0, "/path1/%2E%2e", "", "", "http://example.com/path1/%2E%2e"});
658 checkURLDifferences("http://example.com/path1/%2e",
659 {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
660 {"http", "", "", "example.com", 0, "/path1/%2e", "", "", "http://example.com/path1/%2e"});
661 checkURLDifferences("http://example.com/path1/%2E",
662 {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
663 {"http", "", "", "example.com", 0, "/path1/%2E", "", "", "http://example.com/path1/%2E"});
664 checkURLDifferences("http://example.com/path1/%2E/",
665 {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
666 {"http", "", "", "example.com", 0, "/path1/%2E/", "", "", "http://example.com/path1/%2E/"});
667 checkURLDifferences("http://example.com/path1/path2/%2e?query",
668 {"http", "", "", "example.com", 0, "/path1/path2/", "query", "", "http://example.com/path1/path2/?query"},
669 {"http", "", "", "example.com", 0, "/path1/path2/%2e", "query", "", "http://example.com/path1/path2/%2e?query"});
670 checkURLDifferences("http://example.com/path1/path2/%2e%2e?query",
671 {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"},
672 {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "query", "", "http://example.com/path1/path2/%2e%2e?query"});
673 checkURLDifferences("http://example.com/path1/path2/%2e#fragment",
674 {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"},
675 {"http", "", "", "example.com", 0, "/path1/path2/%2e", "", "fragment", "http://example.com/path1/path2/%2e#fragment"});
676 checkURLDifferences("http://example.com/path1/path2/%2e%2e#fragment",
677 {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"},
678 {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "", "fragment", "http://example.com/path1/path2/%2e%2e#fragment"});
679 checkURL("http://example.com/path1/path2/A%2e%2e#fragment", {"http", "", "", "example.com", 0, "/path1/path2/A%2e%2e", "", "fragment", "http://example.com/path1/path2/A%2e%2e#fragment"});
680 checkURLDifferences("file://[0:a:0:0:b:c:0:0]/path",
681 {"file", "", "", "[0:a::b:c:0:0]", 0, "/path", "", "", "file://[0:a::b:c:0:0]/path"},
682 {"file", "", "", "[0:a:0:0:b:c:0:0]", 0, "/path", "", "", "file://[0:a:0:0:b:c:0:0]/path"});
683 checkURLDifferences("http://",
684 {"", "", "", "", 0, "", "", "", "http://"},
685 {"http", "", "", "", 0, "/", "", "", "http:/"});
686 checkRelativeURLDifferences("//", "https://www.webkit.org/path",
687 {"", "", "", "", 0, "", "", "", "//"},
688 {"https", "", "", "", 0, "/", "", "", "https:/"});
689 checkURLDifferences("http://127.0.0.1:65536/path",
690 {"", "", "", "", 0, "", "", "", "http://127.0.0.1:65536/path"},
691 {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1:65536/path"});
692 checkURLDifferences("http://host:65536",
693 {"", "", "", "", 0, "", "", "", "http://host:65536"},
694 {"http", "", "", "host", 0, "/", "", "", "http://host:65536/"});
695 checkURLDifferences("http://127.0.0.1:65536",
696 {"", "", "", "", 0, "", "", "", "http://127.0.0.1:65536"},
697 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1:65536/"});
698 checkURLDifferences("http://[0:f::f:f:0:0]:65536",
699 {"", "", "", "", 0, "", "", "", "http://[0:f::f:f:0:0]:65536"},
700 {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]:65536/"});
701 checkRelativeURLDifferences(":foo.com\\", "notspecial://example.org/foo/bar",
702 {"notspecial", "", "", "example.org", 0, "/foo/:foo.com\\", "", "", "notspecial://example.org/foo/:foo.com\\"},
703 {"notspecial", "", "", "example.org", 0, "/foo/:foo.com/", "", "", "notspecial://example.org/foo/:foo.com/"});
704 checkURL("sc://pa", {"sc", "", "", "pa", 0, "", "", "", "sc://pa"});
705 checkRelativeURLDifferences("notspecial:\\\\foo.com\\", "http://example.org/foo/bar",
706 {"notspecial", "", "", "", 0, "\\\\foo.com\\", "", "", "notspecial:\\\\foo.com\\"},
707 {"notspecial", "", "", "foo.com", 0, "/", "", "", "notspecial://foo.com/"});
708 checkRelativeURLDifferences("notspecial:\\\\foo.com/", "http://example.org/foo/bar",
709 {"notspecial", "", "", "", 0, "\\\\foo.com/", "", "", "notspecial:\\\\foo.com/"},
710 {"notspecial", "", "", "foo.com", 0, "/", "", "", "notspecial://foo.com/"});
711 checkRelativeURLDifferences("notspecial:\\\\foo.com", "http://example.org/foo/bar",
712 {"notspecial", "", "", "", 0, "\\\\foo.com", "", "", "notspecial:\\\\foo.com"},
713 {"notspecial", "", "", "foo.com", 0, "", "", "", "notspecial://foo.com"});
714 checkURLDifferences("file://notuser:notpassword@test",
715 {"", "", "", "", 0, "", "", "", "file://notuser:notpassword@test"},
716 {"file", "notuser", "notpassword", "test", 0, "/", "", "", "file://notuser:notpassword@test/"});
717 checkURLDifferences("file://notuser:notpassword@test/",
718 {"", "", "", "", 0, "", "", "", "file://notuser:notpassword@test/"},
719 {"file", "notuser", "notpassword", "test", 0, "/", "", "", "file://notuser:notpassword@test/"});
720 checkRelativeURLDifferences("http:/", "about:blank",
721 {"", "", "", "", 0, "", "", "", "http:/"},
722 {"http", "", "", "", 0, "/", "", "", "http:/"});
723 checkRelativeURLDifferences("http:", "about:blank",
724 {"http", "", "", "", 0, "", "", "", "http:"},
725 {"http", "", "", "", 0, "/", "", "", "http:/"});
726 checkRelativeURLDifferences("http:/", "http://host",
727 {"", "", "", "", 0, "", "", "", "http:/"},
728 {"http", "", "", "", 0, "/", "", "", "http:/"});
729 checkURLDifferences("http:/",
730 {"", "", "", "", 0, "", "", "", "http:/"},
731 {"http", "", "", "", 0, "/", "", "", "http:/"});
732 checkURLDifferences("http:",
733 {"http", "", "", "", 0, "", "", "", "http:"},
734 {"http", "", "", "", 0, "/", "", "", "http:/"});
735 checkRelativeURLDifferences("http:/example.com/", "http://example.org/foo/bar",
736 {"http", "", "", "example.org", 0, "/example.com/", "", "", "http://example.org/example.com/"},
737 {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
738
739 // This behavior matches Chrome and Firefox, but not WebKit using URL::parse.
740 // The behavior of URL::parse is clearly wrong because reparsing file://path would make path the host.
741 // The spec is unclear.
742 checkURLDifferences("file:path",
743 {"file", "", "", "", 0, "/path", "", "", "file:///path"},
744 {"file", "", "", "", 0, "path", "", "", "file://path"});
745 checkURLDifferences("file:pAtH",
746 {"file", "", "", "", 0, "/pAtH", "", "", "file:///pAtH"},
747 {"file", "", "", "", 0, "pAtH", "", "", "file://pAtH"});
748 checkURLDifferences("file:pAtH/",
749 {"file", "", "", "", 0, "/pAtH/", "", "", "file:///pAtH/"},
750 {"file", "", "", "", 0, "pAtH/", "", "", "file://pAtH/"});
751 checkURLDifferences("http://example.com%A0",
752 {"", "", "", "", 0, "", "", "", "http://example.com%A0"},
753 {"http", "", "", "example.com%a0", 0, "/", "", "", "http://example.com%a0/"});
754 checkURLDifferences("http://%E2%98%83",
755 {"http", "", "", "xn--n3h", 0, "/", "", "", "http://xn--n3h/"},
756 {"http", "", "", "%e2%98%83", 0, "/", "", "", "http://%e2%98%83/"});
757 checkURLDifferences("http://host%73",
758 {"http", "", "", "hosts", 0, "/", "", "", "http://hosts/"},
759 {"http", "", "", "host%73", 0, "/", "", "", "http://host%73/"});
760 checkURLDifferences("http://host%53",
761 {"http", "", "", "hosts", 0, "/", "", "", "http://hosts/"},
762 {"http", "", "", "host%53", 0, "/", "", "", "http://host%53/"});
763 checkURLDifferences("http://%",
764 {"", "", "", "", 0, "", "", "", "http://%"},
765 {"http", "", "", "%", 0, "/", "", "", "http://%/"});
766 checkURLDifferences("http://%7",
767 {"", "", "", "", 0, "", "", "", "http://%7"},
768 {"http", "", "", "%7", 0, "/", "", "", "http://%7/"});
769 checkURLDifferences("http://%7s",
770 {"", "", "", "", 0, "", "", "", "http://%7s"},
771 {"http", "", "", "%7s", 0, "/", "", "", "http://%7s/"});
772 checkURLDifferences("http://%73",
773 {"http", "", "", "s", 0, "/", "", "", "http://s/"},
774 {"http", "", "", "%73", 0, "/", "", "", "http://%73/"});
775 checkURLDifferences("http://abcdefg%",
776 {"", "", "", "", 0, "", "", "", "http://abcdefg%"},
777 {"http", "", "", "abcdefg%", 0, "/", "", "", "http://abcdefg%/"});
778 checkURLDifferences("http://abcd%7Xefg",
779 {"", "", "", "", 0, "", "", "", "http://abcd%7Xefg"},
780 {"http", "", "", "abcd%7xefg", 0, "/", "", "", "http://abcd%7xefg/"});
781 checkURL("ws://äAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", {"ws", "", "", "xn--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-rsb254a", 0, "/", "", "", "ws://xn--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-rsb254a/"}, TestTabs::No);
782 shouldFail("ws://äAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
783 checkURL("ws://&äAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", {"ws", "", "", "xn--&aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ssb254a", 0, "/", "", "", "ws://xn--&aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ssb254a/"}, TestTabs::No);
784 shouldFail("ws://&äAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
785
786 // URLParser matches Chrome and the spec, but not URL::parse or Firefox.
787 checkURLDifferences(utf16String(u"http://0Xc0.0250.01"),
788 {"http", "", "", "192.168.0.1", 0, "/", "", "", "http://192.168.0.1/"},
789 {"http", "", "", "0xc0.0250.01", 0, "/", "", "", "http://0xc0.0250.01/"});
790
791 checkURL("http://host/path%2e.%2E", {"http", "", "", "host", 0, "/path%2e.%2E", "", "", "http://host/path%2e.%2E"});
792
793 checkRelativeURLDifferences(utf16String(u"http://foo:💩@example.com/bar"), "http://other.com/",
794 {"http", "foo", utf16String(u"💩"), "example.com", 0, "/bar", "", "", "http://foo:%F0%9F%92%A9@example.com/bar"},
795 {"", "", "", "", 0, "", "", "", utf16String(u"http://foo:💩@example.com/bar")}, testTabsValueForSurrogatePairs);
796 checkRelativeURLDifferences("http://&a:foo(b]c@d:2/", "http://example.org/foo/bar",
797 {"http", "&a", "foo(b]c", "d", 2, "/", "", "", "http://&a:foo(b%5Dc@d:2/"},
798 {"", "", "", "", 0, "", "", "", "http://&a:foo(b]c@d:2/"});
799 checkRelativeURLDifferences("http://`{}:`{}@h/`{}?`{}", "http://doesnotmatter/",
800 {"http", "`{}", "`{}", "h", 0, "/%60%7B%7D", "`{}", "", "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}"},
801 {"", "", "", "", 0, "", "", "", "http://`{}:`{}@h/`{}?`{}"});
802 checkURLDifferences("http://[0:f::f::f]",
803 {"", "", "", "", 0, "" , "", "", "http://[0:f::f::f]"},
804 {"http", "", "", "[0:f::f::f]", 0, "/" , "", "", "http://[0:f::f::f]/"});
805 checkURLDifferences("http://123",
806 {"http", "", "", "0.0.0.123", 0, "/", "", "", "http://0.0.0.123/"},
807 {"http", "", "", "123", 0, "/", "", "", "http://123/"});
808 checkURLDifferences("http://123.234/",
809 {"http", "", "", "123.0.0.234", 0, "/", "", "", "http://123.0.0.234/"},
810 {"http", "", "", "123.234", 0, "/", "", "", "http://123.234/"});
811 checkURLDifferences("http://123.234.012",
812 {"http", "", "", "123.234.0.10", 0, "/", "", "", "http://123.234.0.10/"},
813 {"http", "", "", "123.234.012", 0, "/", "", "", "http://123.234.012/"});
814 checkURLDifferences("http://123.234.12",
815 {"http", "", "", "123.234.0.12", 0, "/", "", "", "http://123.234.0.12/"},
816 {"http", "", "", "123.234.12", 0, "/", "", "", "http://123.234.12/"});
817 checkRelativeURLDifferences("file:c:\\foo\\bar.html", "file:///tmp/mock/path",
818 {"file", "", "", "", 0, "/c:/foo/bar.html", "", "", "file:///c:/foo/bar.html"},
819 {"file", "", "", "", 0, "/tmp/mock/c:/foo/bar.html", "", "", "file:///tmp/mock/c:/foo/bar.html"});
820 checkRelativeURLDifferences(" File:c|////foo\\bar.html", "file:///tmp/mock/path",
821 {"file", "", "", "", 0, "/c:////foo/bar.html", "", "", "file:///c:////foo/bar.html"},
822 {"file", "", "", "", 0, "/tmp/mock/c|////foo/bar.html", "", "", "file:///tmp/mock/c|////foo/bar.html"});
823 checkRelativeURLDifferences(" Fil\t\n\te\n\t\n:\t\n\tc\t\n\t|\n\t\n/\t\n\t/\n\t\n//foo\\bar.html", "file:///tmp/mock/path",
824 {"file", "", "", "", 0, "/c:////foo/bar.html", "", "", "file:///c:////foo/bar.html"},
825 {"file", "", "", "", 0, "/tmp/mock/c|////foo/bar.html", "", "", "file:///tmp/mock/c|////foo/bar.html"});
826 checkRelativeURLDifferences("C|/foo/bar", "file:///tmp/mock/path",
827 {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
828 {"file", "", "", "", 0, "/tmp/mock/C|/foo/bar", "", "", "file:///tmp/mock/C|/foo/bar"});
829 checkRelativeURLDifferences("/C|/foo/bar", "file:///tmp/mock/path",
830 {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
831 {"file", "", "", "", 0, "/C|/foo/bar", "", "", "file:///C|/foo/bar"});
832 checkRelativeURLDifferences("https://@test@test@example:800/", "http://doesnotmatter/",
833 {"https", "@test@test", "", "example", 800, "/", "", "", "https://%40test%40test@example:800/"},
834 {"", "", "", "", 0, "", "", "", "https://@test@test@example:800/"});
835 checkRelativeURLDifferences("https://@test@test@example:800/path@end", "http://doesnotmatter/",
836 {"https", "@test@test", "", "example", 800, "/path@end", "", "", "https://%40test%40test@example:800/path@end"},
837 {"", "", "", "", 0, "", "", "", "https://@test@test@example:800/path@end"});
838 checkURLDifferences("notspecial://@test@test@example:800/path@end",
839 {"notspecial", "@test@test", "", "example", 800, "/path@end", "", "", "notspecial://%40test%40test@example:800/path@end"},
840 {"", "", "", "", 0, "", "", "", "notspecial://@test@test@example:800/path@end"});
841 checkURLDifferences("notspecial://@test@test@example:800\\path@end",
842 {"notspecial", "@test@test@example", "800\\path", "end", 0, "", "", "", "notspecial://%40test%40test%40example:800%5Cpath@end"},
843 {"", "", "", "", 0, "", "", "", "notspecial://@test@test@example:800\\path@end"});
844 checkURLDifferences("http://%48OsT",
845 {"http", "", "", "host", 0, "/", "", "", "http://host/"},
846 {"http", "", "", "%48ost", 0, "/", "", "", "http://%48ost/"});
847 checkURLDifferences("http://h%4FsT",
848 {"http", "", "", "host", 0, "/", "", "", "http://host/"},
849 {"http", "", "", "h%4fst", 0, "/", "", "", "http://h%4fst/"});
850 checkURLDifferences("http://h%4fsT",
851 {"http", "", "", "host", 0, "/", "", "", "http://host/"},
852 {"http", "", "", "h%4fst", 0, "/", "", "", "http://h%4fst/"});
853 checkURLDifferences("http://h%6fsT",
854 {"http", "", "", "host", 0, "/", "", "", "http://host/"},
855 {"http", "", "", "h%6fst", 0, "/", "", "", "http://h%6fst/"});
856 checkURLDifferences("http://host/`",
857 {"http", "", "", "host", 0, "/%60", "", "", "http://host/%60"},
858 {"http", "", "", "host", 0, "/`", "", "", "http://host/`"});
859 checkURLDifferences("http://://",
860 {"", "", "", "", 0, "", "", "", "http://://"},
861 {"http", "", "", "", 0, "//", "", "", "http://://"});
862 checkURLDifferences("http://:123?",
863 {"", "", "", "", 0, "", "", "", "http://:123?"},
864 {"http", "", "", "", 123, "/", "", "", "http://:123/?"});
865 checkURLDifferences("http:/:",
866 {"", "", "", "", 0, "", "", "", "http:/:"},
867 {"http", "", "", "", 0, "/", "", "", "http://:/"});
868 checkURLDifferences("asdf://:",
869 {"", "", "", "", 0, "", "", "", "asdf://:"},
870 {"asdf", "", "", "", 0, "", "", "", "asdf://:"});
871 checkURLDifferences("http://:",
872 {"", "", "", "", 0, "", "", "", "http://:"},
873 {"http", "", "", "", 0, "/", "", "", "http://:/"});
874 checkURLDifferences("http:##foo",
875 {"", "", "", "", 0, "", "", "", "http:##foo"},
876 {"http", "", "", "", 0, "/", "", "#foo", "http:/##foo"});
877 checkURLDifferences("http:??bar",
878 {"", "", "", "", 0, "", "", "", "http:??bar"},
879 {"http", "", "", "", 0, "/", "?bar", "", "http:/??bar"});
880 checkURL("asdf:##foo", {"asdf", "", "", "", 0, "", "", "#foo", "asdf:##foo"});
881 checkURL("asdf:??bar", {"asdf", "", "", "", 0, "", "?bar", "", "asdf:??bar"});
882 checkRelativeURLDifferences("//C|/foo/bar", "file:///tmp/mock/path",
883 {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
884 {"", "", "", "", 0, "", "", "", "//C|/foo/bar"});
885 checkRelativeURLDifferences("//C:/foo/bar", "file:///tmp/mock/path",
886 {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
887 {"file", "", "", "c", 0, "/foo/bar", "", "", "file://c/foo/bar"});
888 checkRelativeURLDifferences("//C|?foo/bar", "file:///tmp/mock/path",
889 {"file", "", "", "", 0, "/C:/", "foo/bar", "", "file:///C:/?foo/bar"},
890 {"", "", "", "", 0, "", "", "", "//C|?foo/bar"});
891 checkRelativeURLDifferences("//C|#foo/bar", "file:///tmp/mock/path",
892 {"file", "", "", "", 0, "/C:/", "", "foo/bar", "file:///C:/#foo/bar"},
893 {"", "", "", "", 0, "", "", "", "//C|#foo/bar"});
894 checkURLDifferences("http://0xFFFFFfFF/",
895 {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
896 {"http", "", "", "0xffffffff", 0, "/", "", "", "http://0xffffffff/"});
897 checkURLDifferences("http://0000000000000000037777777777/",
898 {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
899 {"http", "", "", "0000000000000000037777777777", 0, "/", "", "", "http://0000000000000000037777777777/"});
900 checkURLDifferences("http://4294967295/",
901 {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
902 {"http", "", "", "4294967295", 0, "/", "", "", "http://4294967295/"});
903 checkURLDifferences("http://256/",
904 {"http", "", "", "0.0.1.0", 0, "/", "", "", "http://0.0.1.0/"},
905 {"http", "", "", "256", 0, "/", "", "", "http://256/"});
906 checkURLDifferences("http://256./",
907 {"http", "", "", "0.0.1.0", 0, "/", "", "", "http://0.0.1.0/"},
908 {"http", "", "", "256.", 0, "/", "", "", "http://256./"});
909 checkURLDifferences("http://123.256/",
910 {"http", "", "", "123.0.1.0", 0, "/", "", "", "http://123.0.1.0/"},
911 {"http", "", "", "123.256", 0, "/", "", "", "http://123.256/"});
912 checkURLDifferences("http://127.%.0.1/",
913 {"", "", "", "", 0, "", "", "", "http://127.%.0.1/"},
914 {"http", "", "", "127.%.0.1", 0, "/", "", "", "http://127.%.0.1/"});
915 checkURLDifferences("http://[1:2:3:4:5:6:7:8:]/",
916 {"", "", "", "", 0, "", "", "", "http://[1:2:3:4:5:6:7:8:]/"},
917 {"http", "", "", "[1:2:3:4:5:6:7:8:]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:8:]/"});
918 checkURLDifferences("http://[:2:3:4:5:6:7:8:]/",
919 {"", "", "", "", 0, "", "", "", "http://[:2:3:4:5:6:7:8:]/"},
920 {"http", "", "", "[:2:3:4:5:6:7:8:]", 0, "/", "", "", "http://[:2:3:4:5:6:7:8:]/"});
921 checkURLDifferences("http://[1:2:3:4:5:6:7::]/",
922 {"http", "", "", "[1:2:3:4:5:6:7:0]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:0]/"},
923 {"http", "", "", "[1:2:3:4:5:6:7::]", 0, "/", "", "", "http://[1:2:3:4:5:6:7::]/"});
924 checkURLDifferences("http://[1:2:3:4:5:6:7:::]/",
925 {"", "", "", "", 0, "", "", "", "http://[1:2:3:4:5:6:7:::]/"},
926 {"http", "", "", "[1:2:3:4:5:6:7:::]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:::]/"});
927 checkURLDifferences("http://127.0.0.1~/",
928 {"http", "", "", "127.0.0.1~", 0, "/", "", "", "http://127.0.0.1~/"},
929 {"", "", "", "", 0, "", "", "", "http://127.0.0.1~/"});
930 checkURLDifferences("http://127.0.1~/",
931 {"http", "", "", "127.0.1~", 0, "/", "", "", "http://127.0.1~/"},
932 {"", "", "", "", 0, "", "", "", "http://127.0.1~/"});
933 checkURLDifferences("http://127.0.1./",
934 {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
935 {"http", "", "", "127.0.1.", 0, "/", "", "", "http://127.0.1./"});
936 checkURLDifferences("http://127.0.1.~/",
937 {"http", "", "", "127.0.1.~", 0, "/", "", "", "http://127.0.1.~/"},
938 {"", "", "", "", 0, "", "", "", "http://127.0.1.~/"});
939 checkURLDifferences("http://127.0.1.~",
940 {"http", "", "", "127.0.1.~", 0, "/", "", "", "http://127.0.1.~/"},
941 {"", "", "", "", 0, "", "", "", "http://127.0.1.~"});
942 checkRelativeURLDifferences("http://f:000/c", "http://example.org/foo/bar",
943 {"http", "", "", "f", 0, "/c", "", "", "http://f:0/c"},
944 {"http", "", "", "f", 0, "/c", "", "", "http://f:000/c"});
945 checkRelativeURLDifferences("http://f:010/c", "http://example.org/foo/bar",
946 {"http", "", "", "f", 10, "/c", "", "", "http://f:10/c"},
947 {"http", "", "", "f", 10, "/c", "", "", "http://f:010/c"});
948 checkURL("notspecial://HoSt", {"notspecial", "", "", "HoSt", 0, "", "", "", "notspecial://HoSt"});
949 checkURL("notspecial://H%6FSt", {"notspecial", "", "", "H%6FSt", 0, "", "", "", "notspecial://H%6FSt"});
950 checkURL("notspecial://H%4fSt", {"notspecial", "", "", "H%4fSt", 0, "", "", "", "notspecial://H%4fSt"});
951 checkURLDifferences(utf16String(u"notspecial://H😍ßt"),
952 {"notspecial", "", "", "H%F0%9F%98%8D%C3%9Ft", 0, "", "", "", "notspecial://H%F0%9F%98%8D%C3%9Ft"},
953 {"notspecial", "", "", "xn--hsst-qc83c", 0, "", "", "", "notspecial://xn--hsst-qc83c"}, testTabsValueForSurrogatePairs);
954 checkURLDifferences("http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/",
955 {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]/"},
956 {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/"}, TestTabs::No);
957 checkURLDifferences("http://[::123.234.12.210]/",
958 {"http", "", "", "[::7bea:cd2]", 0, "/", "", "", "http://[::7bea:cd2]/"},
959 {"http", "", "", "[::123.234.12.210]", 0, "/", "", "", "http://[::123.234.12.210]/"});
960 checkURLDifferences("http://[::a:255.255.255.255]/",
961 {"http", "", "", "[::a:ffff:ffff]", 0, "/", "", "", "http://[::a:ffff:ffff]/"},
962 {"http", "", "", "[::a:255.255.255.255]", 0, "/", "", "", "http://[::a:255.255.255.255]/"});
963 checkURLDifferences("http://[::0.00.255.255]/",
964 {"", "", "", "", 0, "", "", "", "http://[::0.00.255.255]/"},
965 {"http", "", "", "[::0.00.255.255]", 0, "/", "", "", "http://[::0.00.255.255]/"});
966 checkURLDifferences("http://[::0.0.255.255]/",
967 {"http", "", "", "[::ffff]", 0, "/", "", "", "http://[::ffff]/"},
968 {"http", "", "", "[::0.0.255.255]", 0, "/", "", "", "http://[::0.0.255.255]/"});
969 checkURLDifferences("http://[::0:1.0.255.255]/",
970 {"http", "", "", "[::100:ffff]", 0, "/", "", "", "http://[::100:ffff]/"},
971 {"http", "", "", "[::0:1.0.255.255]", 0, "/", "", "", "http://[::0:1.0.255.255]/"});
972 checkURLDifferences("http://[::A:1.0.255.255]/",
973 {"http", "", "", "[::a:100:ffff]", 0, "/", "", "", "http://[::a:100:ffff]/"},
974 {"http", "", "", "[::a:1.0.255.255]", 0, "/", "", "", "http://[::a:1.0.255.255]/"});
975 checkURLDifferences("http://[:127.0.0.1]",
976 {"", "", "", "", 0, "", "", "", "http://[:127.0.0.1]"},
977 {"http", "", "", "[:127.0.0.1]", 0, "/", "", "", "http://[:127.0.0.1]/"});
978 checkURLDifferences("http://[127.0.0.1]",
979 {"", "", "", "", 0, "", "", "", "http://[127.0.0.1]"},
980 {"http", "", "", "[127.0.0.1]", 0, "/", "", "", "http://[127.0.0.1]/"});
981 checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1]",
982 {"http", "", "", "[a:b:c:d:e:f:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:1]/"},
983 {"http", "", "", "[a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1]/"});
984 checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.101]",
985 {"http", "", "", "[a:b:c:d:e:f:7f00:65]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:65]/"},
986 {"http", "", "", "[a:b:c:d:e:f:127.0.0.101]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.101]/"});
987 checkURLDifferences("http://[::a:b:c:d:e:f:127.0.0.1]",
988 {"", "", "", "", 0, "", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]"},
989 {"http", "", "", "[::a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]/"});
990 checkURLDifferences("http://[a:b::c:d:e:f:127.0.0.1]",
991 {"", "", "", "", 0, "", "", "", "http://[a:b::c:d:e:f:127.0.0.1]"},
992 {"http", "", "", "[a:b::c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b::c:d:e:f:127.0.0.1]/"});
993 checkURLDifferences("http://[a:b:c:d:e:127.0.0.1]",
994 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:127.0.0.1]"},
995 {"http", "", "", "[a:b:c:d:e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:127.0.0.1]/"});
996 checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.0.1]",
997 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]"},
998 {"http", "", "", "[a:b:c:d:e:f:127.0.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]/"});
999 checkURLDifferences("http://[a:b:c:d:e:f:127.0.1]",
1000 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.1]"},
1001 {"http", "", "", "[a:b:c:d:e:f:127.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.1]/"});
1002 checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.011]", // Chrome treats this as octal, Firefox and the spec fail
1003 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.011]"},
1004 {"http", "", "", "[a:b:c:d:e:f:127.0.0.011]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.011]/"});
1005 checkURLDifferences("http://[a:b:c:d:e:f:127.0.00.1]",
1006 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.00.1]"},
1007 {"http", "", "", "[a:b:c:d:e:f:127.0.00.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.00.1]/"});
1008 checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1.]",
1009 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]"},
1010 {"http", "", "", "[a:b:c:d:e:f:127.0.0.1.]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]/"});
1011 checkURLDifferences("http://[a:b:c:d:e:f:127.0..0.1]",
1012 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0..0.1]"},
1013 {"http", "", "", "[a:b:c:d:e:f:127.0..0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0..0.1]/"});
1014 checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.1]",
1015 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.1]"},
1016 {"http", "", "", "[a:b:c:d:e:f::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.1]/"});
1017 checkURLDifferences("http://[a:b:c:d:e::127.0.0.1]",
1018 {"http", "", "", "[a:b:c:d:e:0:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:0:7f00:1]/"},
1019 {"http", "", "", "[a:b:c:d:e::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e::127.0.0.1]/"});
1020 checkURLDifferences("http://[a:b:c:d::e:127.0.0.1]",
1021 {"http", "", "", "[a:b:c:d:0:e:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:0:e:7f00:1]/"},
1022 {"http", "", "", "[a:b:c:d::e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d::e:127.0.0.1]/"});
1023 checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.]",
1024 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.]"},
1025 {"http", "", "", "[a:b:c:d:e:f::127.0.0.]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.]/"});
1026 checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.256]",
1027 {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.256]"},
1028 {"http", "", "", "[a:b:c:d:e:f::127.0.0.256]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.256]/"});
1029 checkURLDifferences("http://123456", {"http", "", "", "0.1.226.64", 0, "/", "", "", "http://0.1.226.64/"}, {"http", "", "", "123456", 0, "/", "", "", "http://123456/"});
1030 checkURL("asdf://123456", {"asdf", "", "", "123456", 0, "", "", "", "asdf://123456"});
1031 checkURLDifferences("http://[0:0:0:0:a:b:c:d]",
1032 {"http", "", "", "[::a:b:c:d]", 0, "/", "", "", "http://[::a:b:c:d]/"},
1033 {"http", "", "", "[0:0:0:0:a:b:c:d]", 0, "/", "", "", "http://[0:0:0:0:a:b:c:d]/"});
1034 checkURLDifferences("asdf://[0:0:0:0:a:b:c:d]",
1035 {"asdf", "", "", "[::a:b:c:d]", 0, "", "", "", "asdf://[::a:b:c:d]"},
1036 {"asdf", "", "", "[0:0:0:0:a:b:c:d]", 0, "", "", "", "asdf://[0:0:0:0:a:b:c:d]"}, TestTabs::No);
1037 shouldFail("a://%:a");
1038 checkURL("a://%:/", {"a", "", "", "%", 0, "/", "", "", "a://%/"});
1039 checkURL("a://%:", {"a", "", "", "%", 0, "", "", "", "a://%"});
1040 checkURL("a://%:1/", {"a", "", "", "%", 1, "/", "", "", "a://%:1/"});
1041 checkURLDifferences("http://%:",
1042 {"", "", "", "", 0, "", "", "", "http://%:"},
1043 {"http", "", "", "%", 0, "/", "", "", "http://%/"});
1044 checkURL("a://123456", {"a", "", "", "123456", 0, "", "", "", "a://123456"});
1045 checkURL("a://123456:7", {"a", "", "", "123456", 7, "", "", "", "a://123456:7"});
1046 checkURL("a://123456:7/", {"a", "", "", "123456", 7, "/", "", "", "a://123456:7/"});
1047 checkURL("a://A", {"a", "", "", "A", 0, "", "", "", "a://A"});
1048 checkURL("a://A:2", {"a", "", "", "A", 2, "", "", "", "a://A:2"});
1049 checkURL("a://A:2/", {"a", "", "", "A", 2, "/", "", "", "a://A:2/"});
1050 checkURLDifferences(u8"asd://ß",
1051 {"asd", "", "", "%C3%83%C2%9F", 0, "", "", "", "asd://%C3%83%C2%9F"},
1052 {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
1053 checkURLDifferences(u8"asd://ß:4",
1054 {"asd", "", "", "%C3%83%C2%9F", 4, "", "", "", "asd://%C3%83%C2%9F:4"},
1055 {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
1056 checkURLDifferences(u8"asd://ß:4/",
1057 {"asd", "", "", "%C3%83%C2%9F", 4, "/", "", "", "asd://%C3%83%C2%9F:4/"},
1058 {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
1059 checkURLDifferences("a://[A::b]:4",
1060 {"a", "", "", "[a::b]", 4, "", "", "", "a://[a::b]:4"},
1061 {"a", "", "", "[A::b]", 4, "", "", "", "a://[A::b]:4"});
1062 shouldFail("http://[~]");
1063 shouldFail("a://[~]");
1064 checkRelativeURLDifferences("a://b", "//[aBc]",
1065 {"a", "", "", "b", 0, "", "", "", "a://b"},
1066 {"", "", "", "", 0, "", "", "", "a://b"});
1067 checkURL(utf16String(u"http://öbb.at"), {"http", "", "", "xn--bb-eka.at", 0, "/", "", "", "http://xn--bb-eka.at/"});
1068 checkURL(utf16String(u"http://ÖBB.at"), {"http", "", "", "xn--bb-eka.at", 0, "/", "", "", "http://xn--bb-eka.at/"});
1069 checkURL(utf16String(u"http://√.com"), {"http", "", "", "xn--19g.com", 0, "/", "", "", "http://xn--19g.com/"});
1070 checkURLDifferences(utf16String(u"http://faß.de"),
1071 {"http", "", "", "xn--fa-hia.de", 0, "/", "", "", "http://xn--fa-hia.de/"},
1072 {"http", "", "", "fass.de", 0, "/", "", "", "http://fass.de/"});
1073 checkURL(utf16String(u"http://ԛәлп.com"), {"http", "", "", "xn--k1ai47bhi.com", 0, "/", "", "", "http://xn--k1ai47bhi.com/"});
1074 checkURLDifferences(utf16String(u"http://Ⱥbby.com"),
1075 {"http", "", "", "xn--bby-iy0b.com", 0, "/", "", "", "http://xn--bby-iy0b.com/"},
1076 {"http", "", "", "xn--bby-spb.com", 0, "/", "", "", "http://xn--bby-spb.com/"});
1077 checkURLDifferences(utf16String(u"http://\u2132"),
1078 {"", "", "", "", 0, "", "", "", utf16String(u"http://Ⅎ")},
1079 {"http", "", "", "xn--f3g", 0, "/", "", "", "http://xn--f3g/"});
1080 checkURLDifferences(utf16String(u"http://\u05D9\u05B4\u05D5\u05D0\u05B8/"),
1081 {"http", "", "", "xn--cdbi5etas", 0, "/", "", "", "http://xn--cdbi5etas/"},
1082 {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
1083 checkURLDifferences(utf16String(u"http://bidirectional\u0786\u07AE\u0782\u07B0\u0795\u07A9\u0793\u07A6\u0783\u07AA/"),
1084 {"", "", "", "", 0, "", "", "", utf16String(u"http://bidirectionalކޮންޕީޓަރު/")},
1085 {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
1086 checkURLDifferences(utf16String(u"http://contextj\u200D"),
1087 {"", "", "", "", 0, "", "", "", utf16String(u"http://contextj\u200D")},
1088 {"http", "", "", "contextj", 0, "/", "", "", "http://contextj/"});
1089 checkURL(utf16String(u"http://contexto\u30FB"), {"http", "", "", "xn--contexto-wg5g", 0, "/", "", "", "http://xn--contexto-wg5g/"});
1090 checkURLDifferences(utf16String(u"http://\u321D\u321E/"),
1091 {"http", "", "", "xn--()()-bs0sc174agx4b", 0, "/", "", "", "http://xn--()()-bs0sc174agx4b/"},
1092 {"http", "", "", "xn--5mkc", 0, "/", "", "", "http://xn--5mkc/"});
1093}
1094
1095TEST_F(WTF_URLParser, DefaultPort)
1096{
1097 checkURL("FtP://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1098 checkURL("ftp://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1099 checkURL("f\ttp://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1100 checkURL("f\ttp://host\t:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1101 checkURL("f\ttp://host:\t21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1102 checkURL("f\ttp://host:2\t1/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1103 checkURL("f\ttp://host:21\t/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1104 checkURL("ftp://host\t:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1105 checkURL("ftp://host:\t21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1106 checkURL("ftp://host:2\t1/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1107 checkURL("ftp://host:21\t/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
1108 checkURL("ftp://host:22/", {"ftp", "", "", "host", 22, "/", "", "", "ftp://host:22/"});
1109 checkURLDifferences("ftp://host:21",
1110 {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"},
1111 {"ftp", "", "", "host", 0, "", "", "", "ftp://host"});
1112 checkURLDifferences("ftp://host:22",
1113 {"ftp", "", "", "host", 22, "/", "", "", "ftp://host:22/"},
1114 {"ftp", "", "", "host", 22, "", "", "", "ftp://host:22"});
1115
1116 checkURL("gOpHeR://host:70/", {"gopher", "", "", "host", 70, "/", "", "", "gopher://host:70/"});
1117 checkURL("gopher://host:70/", {"gopher", "", "", "host", 70, "/", "", "", "gopher://host:70/"});
1118 checkURL("gopher://host:71/", {"gopher", "", "", "host", 71, "/", "", "", "gopher://host:71/"});
1119
1120 checkURL("hTtP://host:80", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
1121 checkURL("http://host:80", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
1122 checkURL("http://host:80/", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
1123 checkURL("http://host:81", {"http", "", "", "host", 81, "/", "", "", "http://host:81/"});
1124 checkURL("http://host:81/", {"http", "", "", "host", 81, "/", "", "", "http://host:81/"});
1125
1126 checkURL("hTtPs://host:443", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
1127 checkURL("https://host:443", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
1128 checkURL("https://host:443/", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
1129 checkURL("https://host:444", {"https", "", "", "host", 444, "/", "", "", "https://host:444/"});
1130 checkURL("https://host:444/", {"https", "", "", "host", 444, "/", "", "", "https://host:444/"});
1131
1132 checkURL("wS://host:80/", {"ws", "", "", "host", 0, "/", "", "", "ws://host/"});
1133 checkURL("ws://host:80/", {"ws", "", "", "host", 0, "/", "", "", "ws://host/"});
1134 checkURL("ws://host:81/", {"ws", "", "", "host", 81, "/", "", "", "ws://host:81/"});
1135 // URLParser matches Chrome and Firefox, but not URL::parse
1136 checkURLDifferences("ws://host:80",
1137 {"ws", "", "", "host", 0, "/", "", "", "ws://host/"},
1138 {"ws", "", "", "host", 0, "", "", "", "ws://host"});
1139 checkURLDifferences("ws://host:81",
1140 {"ws", "", "", "host", 81, "/", "", "", "ws://host:81/"},
1141 {"ws", "", "", "host", 81, "", "", "", "ws://host:81"});
1142
1143 checkURL("WsS://host:443/", {"wss", "", "", "host", 0, "/", "", "", "wss://host/"});
1144 checkURL("wss://host:443/", {"wss", "", "", "host", 0, "/", "", "", "wss://host/"});
1145 checkURL("wss://host:444/", {"wss", "", "", "host", 444, "/", "", "", "wss://host:444/"});
1146 // URLParser matches Chrome and Firefox, but not URL::parse
1147 checkURLDifferences("wss://host:443",
1148 {"wss", "", "", "host", 0, "/", "", "", "wss://host/"},
1149 {"wss", "", "", "host", 0, "", "", "", "wss://host"});
1150 checkURLDifferences("wss://host:444",
1151 {"wss", "", "", "host", 444, "/", "", "", "wss://host:444/"},
1152 {"wss", "", "", "host", 444, "", "", "", "wss://host:444"});
1153
1154 checkURL("fTpS://host:990/", {"ftps", "", "", "host", 990, "/", "", "", "ftps://host:990/"});
1155 checkURL("ftps://host:990/", {"ftps", "", "", "host", 990, "/", "", "", "ftps://host:990/"});
1156 checkURL("ftps://host:991/", {"ftps", "", "", "host", 991, "/", "", "", "ftps://host:991/"});
1157 checkURL("ftps://host:990", {"ftps", "", "", "host", 990, "", "", "", "ftps://host:990"});
1158 checkURL("ftps://host:991", {"ftps", "", "", "host", 991, "", "", "", "ftps://host:991"});
1159
1160 checkURL("uNkNoWn://host:80/", {"unknown", "", "", "host", 80, "/", "", "", "unknown://host:80/"});
1161 checkURL("unknown://host:80/", {"unknown", "", "", "host", 80, "/", "", "", "unknown://host:80/"});
1162 checkURL("unknown://host:81/", {"unknown", "", "", "host", 81, "/", "", "", "unknown://host:81/"});
1163 checkURL("unknown://host:80", {"unknown", "", "", "host", 80, "", "", "", "unknown://host:80"});
1164 checkURL("unknown://host:81", {"unknown", "", "", "host", 81, "", "", "", "unknown://host:81"});
1165
1166 checkURL("file://host:0", {"file", "", "", "host", 0, "/", "", "", "file://host:0/"});
1167 checkURL("file://host:80", {"file", "", "", "host", 80, "/", "", "", "file://host:80/"});
1168 checkURL("file://host:80/path", {"file", "", "", "host", 80, "/path", "", "", "file://host:80/path"});
1169 checkURLDifferences("file://:80/path",
1170 {"", "", "", "", 0, "", "", "", "file://:80/path"},
1171 {"file", "", "", "", 80, "/path", "", "", "file://:80/path"});
1172 checkURLDifferences("file://:0/path",
1173 {"", "", "", "", 0, "", "", "", "file://:0/path"},
1174 {"file", "", "", "", 0, "/path", "", "", "file://:0/path"});
1175
1176 checkURL("http://example.com:0000000000000077", {"http", "", "", "example.com", 77, "/", "", "", "http://example.com:77/"});
1177 checkURL("http://example.com:0000000000000080", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
1178}
1179
1180TEST_F(WTF_URLParser, ParserFailures)
1181{
1182 shouldFail(" ");
1183 shouldFail(" \a ");
1184 shouldFail("");
1185 shouldFail(String());
1186 shouldFail("", "about:blank");
1187 shouldFail(String(), "about:blank");
1188 shouldFail("http://127.0.0.1:abc");
1189 shouldFail("http://host:abc");
1190 shouldFail("http://:abc");
1191 shouldFail("http://a:@", "about:blank");
1192 shouldFail("http://:b@", "about:blank");
1193 shouldFail("http://:@", "about:blank");
1194 shouldFail("http://a:@");
1195 shouldFail("http://:b@");
1196 shouldFail("http://@");
1197 shouldFail("http://[0:f::f:f:0:0]:abc");
1198 shouldFail("../i", "sc:sd");
1199 shouldFail("../i", "sc:sd/sd");
1200 shouldFail("/i", "sc:sd");
1201 shouldFail("/i", "sc:sd/sd");
1202 shouldFail("?i", "sc:sd");
1203 shouldFail("?i", "sc:sd/sd");
1204 shouldFail("http://example example.com", "http://other.com/");
1205 shouldFail("http://[www.example.com]/", "about:blank");
1206 shouldFail("http://192.168.0.1 hello", "http://other.com/");
1207 shouldFail("http://[example.com]", "http://other.com/");
1208 shouldFail("i", "sc:sd");
1209 shouldFail("i", "sc:sd/sd");
1210 shouldFail("i");
1211 shouldFail("asdf");
1212 shouldFail("~");
1213 shouldFail("%");
1214 shouldFail("//%");
1215 shouldFail("~", "about:blank");
1216 shouldFail("~~~");
1217 shouldFail("://:0/");
1218 shouldFail("://:0/", "");
1219 shouldFail("://:0/", "about:blank");
1220 shouldFail("about~");
1221 shouldFail("//C:asdf/foo/bar", "file:///tmp/mock/path");
1222 shouldFail("wss://[c::]abc/");
1223 shouldFail("abc://[c::]:abc/");
1224 shouldFail("abc://[c::]01");
1225 shouldFail("http://[1234::ab#]");
1226 shouldFail("http://[1234::ab/]");
1227 shouldFail("http://[1234::ab?]");
1228 shouldFail("http://[1234::ab@]");
1229 shouldFail("http://[1234::ab~]");
1230 shouldFail("http://[2001::1");
1231 shouldFail("http://4:b\xE1");
1232 shouldFail("http://[1:2:3:4:5:6:7:8~]/");
1233 shouldFail("http://[a:b:c:d:e:f:g:127.0.0.1]");
1234 shouldFail("http://[a:b:c:d:e:f:g:h:127.0.0.1]");
1235 shouldFail("http://[a:b:c:d:e:f:127.0.0.0x11]"); // Chrome treats this as hex, Firefox and the spec fail
1236 shouldFail("http://[a:b:c:d:e:f:127.0.-0.1]");
1237 shouldFail("asdf://space In\aHost");
1238 shouldFail("asdf://[0:0:0:0:a:b:c:d");
1239 shouldFail("http://[::0:0.0.00000.0]/");
1240}
1241
1242// These are in the spec but not in the web platform tests.
1243TEST_F(WTF_URLParser, AdditionalTests)
1244{
1245 checkURL("about:\a\aabc", {"about", "", "", "", 0, "%07%07abc", "", "", "about:%07%07abc"});
1246 checkURL("notspecial:\t\t\n\t", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
1247 checkURL("notspecial\t\t\n\t:\t\t\n\t/\t\t\n\t/\t\t\n\thost", {"notspecial", "", "", "host", 0, "", "", "", "notspecial://host"});
1248 checkRelativeURL("http:", "http://example.org/foo/bar?query#fragment", {"http", "", "", "example.org", 0, "/foo/bar", "query", "", "http://example.org/foo/bar?query"});
1249 checkRelativeURLDifferences("ws:", "http://example.org/foo/bar",
1250 {"ws", "", "", "", 0, "", "", "", "ws:"},
1251 {"ws", "", "", "", 0, "s:", "", "", "ws:s:"});
1252 checkRelativeURL("notspecial:", "http://example.org/foo/bar", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
1253
1254 const wchar_t surrogateBegin = 0xD800;
1255 const wchar_t validSurrogateEnd = 0xDD55;
1256 const wchar_t invalidSurrogateEnd = 'A';
1257 const wchar_t replacementCharacter = 0xFFFD;
1258 checkURL(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, validSurrogateEnd, '\0'}),
1259 {"http", "", "", "w", 0, "/%F0%90%85%95", "", "", "http://w/%F0%90%85%95"}, testTabsValueForSurrogatePairs);
1260 shouldFail(utf16String<10>({'h', 't', 't', 'p', ':', '/', surrogateBegin, invalidSurrogateEnd, '/', '\0'}));
1261 shouldFail(utf16String<9>({'h', 't', 't', 'p', ':', '/', replacementCharacter, '/', '\0'}));
1262
1263 // URLParser matches Chrome and Firefox but not URL::parse.
1264 checkURLDifferences(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, invalidSurrogateEnd}),
1265 {"http", "", "", "w", 0, "/%EF%BF%BDA", "", "", "http://w/%EF%BF%BDA"},
1266 {"http", "", "", "w", 0, "/%ED%A0%80A", "", "", "http://w/%ED%A0%80A"});
1267 checkURLDifferences(utf16String<13>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, invalidSurrogateEnd, '\0'}),
1268 {"http", "", "", "w", 0, "/", "%EF%BF%BDA", "", "http://w/?%EF%BF%BDA"},
1269 {"http", "", "", "w", 0, "/", "%ED%A0%80A", "", "http://w/?%ED%A0%80A"});
1270 checkURLDifferences(utf16String<11>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, '\0'}),
1271 {"http", "", "", "w", 0, "/%EF%BF%BD", "", "", "http://w/%EF%BF%BD"},
1272 {"http", "", "", "w", 0, "/%ED%A0%80", "", "", "http://w/%ED%A0%80"});
1273 checkURLDifferences(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, '\0'}),
1274 {"http", "", "", "w", 0, "/", "%EF%BF%BD", "", "http://w/?%EF%BF%BD"},
1275 {"http", "", "", "w", 0, "/", "%ED%A0%80", "", "http://w/?%ED%A0%80"});
1276 checkURLDifferences(utf16String<13>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, ' ', '\0'}),
1277 {"http", "", "", "w", 0, "/", "%EF%BF%BD", "", "http://w/?%EF%BF%BD"},
1278 {"http", "", "", "w", 0, "/", "%ED%A0%80", "", "http://w/?%ED%A0%80"});
1279
1280 // FIXME: Write more invalid surrogate pair tests based on feedback from https://bugs.webkit.org/show_bug.cgi?id=162105
1281}
1282
1283} // namespace TestWebKitAPI
1284