Move URL from WebCore to WTF
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebCore / URL.cpp
1 /*
2  * Copyright (C) 2011, 2012 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/URL.h>
30 #include <wtf/URLParser.h>
31
32 namespace TestWebKitAPI {
33
34 class URLTest : public testing::Test {
35 public:
36     virtual void SetUp()
37     {
38         WTF::initializeMainThread();
39     }
40 };
41
42 TEST_F(URLTest, URLConstructorDefault)
43 {
44     URL kurl;
45
46     EXPECT_TRUE(kurl.isEmpty());
47     EXPECT_TRUE(kurl.isNull());
48     EXPECT_FALSE(kurl.isValid());
49 }
50
51 TEST_F(URLTest, URLConstructorConstChar)
52 {
53     URL kurl({ }, "http://username:password@www.example.com:8080/index.html?var=val#fragment");
54
55     EXPECT_FALSE(kurl.isEmpty());
56     EXPECT_FALSE(kurl.isNull());
57     EXPECT_TRUE(kurl.isValid());
58
59     EXPECT_EQ(kurl.protocol() == "http", true);
60     EXPECT_EQ(String("www.example.com"), kurl.host().toString());
61     EXPECT_TRUE(!!kurl.port());
62     EXPECT_EQ(8080, kurl.port().value());
63     EXPECT_EQ(String("username"), kurl.user());
64     EXPECT_EQ(String("password"), kurl.pass());
65     EXPECT_EQ(String("/index.html"), kurl.path());
66     EXPECT_EQ(String("index.html"), kurl.lastPathComponent());
67     EXPECT_EQ(String("var=val"), kurl.query());
68     EXPECT_TRUE(kurl.hasFragmentIdentifier());
69     EXPECT_EQ(String("fragment"), kurl.fragmentIdentifier());
70 }
71
72 static URL createURL(const char* urlAsString)
73 {
74     return URL({ }, urlAsString);
75 };
76
77 TEST_F(URLTest, URLProtocolHostAndPort)
78 {
79     auto url = createURL("http://username:password@www.example.com:8080/index.html?var=val#fragment");
80     EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
81
82     url = createURL("http://username:@www.example.com:8080/index.html?var=val#fragment");
83     EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
84
85     url = createURL("http://:password@www.example.com:8080/index.html?var=val#fragment");
86     EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
87
88     url = createURL("http://username@www.example.com:8080/index.html?var=val#fragment");
89     EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
90
91     url = createURL("http://www.example.com:8080/index.html?var=val#fragment");
92     EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
93
94     url = createURL("http://www.example.com:/index.html?var=val#fragment");
95     EXPECT_EQ(String("http://www.example.com"), url.protocolHostAndPort());
96
97     url = createURL("http://www.example.com/index.html?var=val#fragment");
98     EXPECT_EQ(String("http://www.example.com"), url.protocolHostAndPort());
99
100     url = createURL("file:///a/b/c");
101     EXPECT_EQ(String("file://"), url.protocolHostAndPort());
102
103     url = createURL("file:///a/b");
104     EXPECT_EQ(String("file://"), url.protocolHostAndPort());
105
106     url = createURL("file:///a");
107     EXPECT_EQ(String("file://"), url.protocolHostAndPort());
108
109     url = createURL("file:///a");
110     EXPECT_EQ(String("file://"), url.protocolHostAndPort());
111
112     url = createURL("asdf://username:password@www.example.com:8080/index.html?var=val#fragment");
113     EXPECT_EQ(String("asdf://www.example.com:8080"), url.protocolHostAndPort());
114
115     url = createURL("asdf:///a/b/c");
116     EXPECT_EQ(String("asdf://"), url.protocolHostAndPort());
117 }
118
119 TEST_F(URLTest, URLDataURIStringSharing)
120 {
121     URL baseURL({ }, "http://www.webkit.org/");
122     String threeApples = "data:text/plain;charset=utf-8;base64,76O/76O/76O/";
123
124     URL url(baseURL, threeApples);
125     EXPECT_EQ(threeApples.impl(), url.string().impl());
126 }
127
128 TEST_F(URLTest, URLSetQuery)
129 {
130     URL url = createURL("http://www.webkit.org/?test");
131     URL url1 = createURL("http://www.webkit.org/");
132     URL url2 = createURL("http://www.webkit.org/?");
133     URL url3 = createURL("http://www.webkit.org/?test");
134     URL url4 = createURL("http://www.webkit.org/?test1");
135
136     url1.setQuery("test");
137     url2.setQuery("test");
138     url3.setQuery("test");
139     url4.setQuery("test");
140
141     EXPECT_EQ(url.string(), url1.string());
142     EXPECT_EQ(url.string(), url2.string());
143     EXPECT_EQ(url.string(), url3.string());
144     EXPECT_EQ(url.string(), url4.string());
145
146     URL urlWithFragmentIdentifier = createURL("http://www.webkit.org/?test%C3%83%C2%A5#newFragment");
147     URL urlWithFragmentIdentifier1 = createURL("http://www.webkit.org/#newFragment");
148     URL urlWithFragmentIdentifier2 = createURL("http://www.webkit.org/?#newFragment");
149     URL urlWithFragmentIdentifier3 = createURL("http://www.webkit.org/?test1#newFragment");
150
151     urlWithFragmentIdentifier1.setQuery("test\xc3\xa5");
152     urlWithFragmentIdentifier2.setQuery("test\xc3\xa5");
153     urlWithFragmentIdentifier3.setQuery("test\xc3\xa5");
154
155     EXPECT_EQ(urlWithFragmentIdentifier.string(), urlWithFragmentIdentifier1.string());
156     EXPECT_EQ(urlWithFragmentIdentifier.string(), urlWithFragmentIdentifier2.string());
157     EXPECT_EQ(urlWithFragmentIdentifier.string(), urlWithFragmentIdentifier3.string());
158 }
159
160 TEST_F(URLTest, URLSetFragmentIdentifier)
161 {
162     URL url = createURL("http://www.webkit.org/#newFragment%C3%83%C2%A5");
163     URL url1 = createURL("http://www.webkit.org/");
164     URL url2 = createURL("http://www.webkit.org/#test2");
165     URL url3 = createURL("http://www.webkit.org/#");
166
167     url1.setFragmentIdentifier("newFragment\xc3\xa5");
168     url2.setFragmentIdentifier("newFragment\xc3\xa5");
169     url3.setFragmentIdentifier("newFragment\xc3\xa5");
170
171     EXPECT_EQ(url.string(), url1.string());
172     EXPECT_EQ(url.string(), url2.string());
173     EXPECT_EQ(url.string(), url3.string());
174
175     URL urlWithQuery = createURL("http://www.webkit.org/?test1#newFragment");
176     URL urlWithQuery1 = createURL("http://www.webkit.org/?test1");
177     URL urlWithQuery2 = createURL("http://www.webkit.org/?test1#");
178     URL urlWithQuery3 = createURL("http://www.webkit.org/?test1#test2");
179
180     urlWithQuery1.setFragmentIdentifier("newFragment");
181     urlWithQuery2.setFragmentIdentifier("newFragment");
182     urlWithQuery3.setFragmentIdentifier("newFragment");
183
184     EXPECT_EQ(urlWithQuery.string(), urlWithQuery1.string());
185     EXPECT_EQ(urlWithQuery.string(), urlWithQuery2.string());
186     EXPECT_EQ(urlWithQuery.string(), urlWithQuery3.string());
187 }
188
189 TEST_F(URLTest, URLRemoveQueryAndFragmentIdentifier)
190 {
191     URL url = createURL("http://www.webkit.org/");
192     URL url1 = createURL("http://www.webkit.org/?");
193     URL url2 = createURL("http://www.webkit.org/?test1");
194     URL url3 = createURL("http://www.webkit.org/?test1#test2");
195     URL url4 = createURL("http://www.webkit.org/#test2");
196     URL url5 = createURL("http://www.webkit.org/#");
197
198     url.removeQueryAndFragmentIdentifier();
199     url1.removeQueryAndFragmentIdentifier();
200     url2.removeQueryAndFragmentIdentifier();
201     url3.removeQueryAndFragmentIdentifier();
202     url4.removeQueryAndFragmentIdentifier();
203     url5.removeQueryAndFragmentIdentifier();
204
205     EXPECT_EQ(url.string(), url.string());
206     EXPECT_EQ(url.string(), url1.string());
207     EXPECT_EQ(url.string(), url2.string());
208     EXPECT_EQ(url.string(), url3.string());
209     EXPECT_EQ(url.string(), url4.string());
210     EXPECT_EQ(url.string(), url5.string());
211 }
212
213 TEST_F(URLTest, EqualIgnoringFragmentIdentifier)
214 {
215     struct TestCase {
216         const char* url1;
217         const char* url2;
218         bool expected;
219     } cases[] = {
220         {"http://example.com/", "http://example.com/", true},
221         {"http://example.com/#hash", "http://example.com/", true},
222         {"http://example.com/path", "http://example.com/", false},
223         {"http://example.com/path", "http://example.com/path", true},
224         {"http://example.com/path#hash", "http://example.com/path", true},
225         {"http://example.com/path?query", "http://example.com/path", false},
226         {"http://example.com/path?query#hash", "http://example.com/path", false},
227         {"http://example.com/otherpath", "http://example.com/path", false},
228         {"http://example.com:80/", "http://example.com/", true},
229         {"http://example.com:80/#hash", "http://example.com/", true},
230         {"http://example.com:80/path", "http://example.com/", false},
231         {"http://example.com:80/path#hash", "http://example.com/path", true},
232         {"http://example.com:80/path?query", "http://example.com/path", false},
233         {"http://example.com:80/path?query#hash", "http://example.com/path", false},
234         {"http://example.com:80/otherpath", "http://example.com/path", false},
235         {"http://not-example.com:80/", "http://example.com/", false},
236         {"http://example.com:81/", "http://example.com/", false},
237         {"http://example.com:81/#hash", "http://example.com:81/", true},
238         {"http://example.com:81/path", "http://example.com:81", false},
239         {"http://example.com:81/path#hash", "http://example.com:81/path", true},
240         {"http://example.com:81/path?query", "http://example.com:81/path", false},
241         {"http://example.com:81/path?query#hash", "http://example.com:81/path", false},
242         {"http://example.com:81/otherpath", "http://example.com:81/path", false},
243         {"file:///path/to/file.html", "file:///path/to/file.html", true},
244         {"file:///path/to/file.html#hash", "file:///path/to/file.html", true},
245         {"file:///path/to/file.html?query", "file:///path/to/file.html", false},
246         {"file:///path/to/file.html?query#hash", "file:///path/to/file.html", false},
247         {"file:///path/to/other_file.html", "file:///path/to/file.html", false},
248         {"file:///path/to/other/file.html", "file:///path/to/file.html", false},
249         {"data:text/plain;charset=utf-8;base64,76O/76O/76O/", "data:text/plain;charset=utf-8;base64,760/760/760/", false},
250         {"http://example.com", "file://example.com", false},
251         {"http://example.com/#hash", "file://example.com", false},
252         {"http://example.com/?query", "file://example.com/", false},
253         {"http://example.com/?query#hash", "file://example.com/", false},
254     };
255
256     for (const auto& test : cases) {
257         URL url1 = createURL(test.url1);
258         URL url2 = createURL(test.url2);
259         EXPECT_EQ(test.expected, equalIgnoringFragmentIdentifier(url1, url2))
260             << "Test failed for " << test.url1 << " vs. " << test.url2;
261     }
262 }
263
264 TEST_F(URLTest, EqualIgnoringQueryAndFragment)
265 {
266     struct TestCase {
267         const char* url1;
268         const char* url2;
269         bool expected;
270     } cases[] = {
271         {"http://example.com/", "http://example.com/", true},
272         {"http://example.com/#hash", "http://example.com/", true},
273         {"http://example.com/path", "http://example.com/", false},
274         {"http://example.com/path", "http://example.com/path", true},
275         {"http://example.com/path#hash", "http://example.com/path", true},
276         {"http://example.com/path?query", "http://example.com/path", true},
277         {"http://example.com/path?query#hash", "http://example.com/path", true},
278         {"http://example.com/otherpath", "http://example.com/path", false},
279         {"http://example.com:80/", "http://example.com/", true},
280         {"http://example.com:80/#hash", "http://example.com/", true},
281         {"http://example.com:80/path", "http://example.com/", false},
282         {"http://example.com:80/path#hash", "http://example.com/path", true},
283         {"http://example.com:80/path?query", "http://example.com/path", true},
284         {"http://example.com:80/path?query#hash", "http://example.com/path", true},
285         {"http://example.com:80/otherpath", "http://example.com/path", false},
286         {"http://not-example.com:80/", "http://example.com:80/", false},
287         {"http://example.com:81/", "http://example.com/", false},
288         {"http://example.com:81/#hash", "http://example.com:81/", true},
289         {"http://example.com:81/path", "http://example.com:81", false},
290         {"http://example.com:81/path#hash", "http://example.com:81/path", true},
291         {"http://example.com:81/path?query", "http://example.com:81/path", true},
292         {"http://example.com:81/path?query#hash", "http://example.com:81/path", true},
293         {"http://example.com:81/otherpath", "http://example.com:81/path", false},
294         {"file:///path/to/file.html", "file:///path/to/file.html", true},
295         {"file:///path/to/file.html#hash", "file:///path/to/file.html", true},
296         {"file:///path/to/file.html?query", "file:///path/to/file.html", true},
297         {"file:///path/to/file.html?query#hash", "file:///path/to/file.html", true},
298         {"file:///path/to/other_file.html", "file:///path/to/file.html", false},
299         {"file:///path/to/other/file.html", "file:///path/to/file.html", false},
300         {"data:text/plain;charset=utf-8;base64,76O/76O/76O/", "data:text/plain;charset=utf-8;base64,760/760/760/", false},
301         {"http://example.com", "file://example.com", false},
302         {"http://example.com/#hash", "file://example.com", false},
303         {"http://example.com/?query", "file://example.com/", false},
304         {"http://example.com/?query#hash", "file://example.com/", false},
305     };
306
307     for (const auto& test : cases) {
308         URL url1 = createURL(test.url1);
309         URL url2 = createURL(test.url2);
310         EXPECT_EQ(test.expected, equalIgnoringQueryAndFragment(url1, url2))
311             << "Test failed for " << test.url1 << " vs. " << test.url2;
312     }
313 }
314
315 TEST_F(URLTest, ProtocolIsInHTTPFamily)
316 {
317     EXPECT_FALSE(WTF::protocolIsInHTTPFamily({ }));
318     EXPECT_FALSE(WTF::protocolIsInHTTPFamily(""));
319     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("a"));
320     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("ab"));
321     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("abc"));
322     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("abcd"));
323     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("abcde"));
324     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("abcdef"));
325     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("abcdefg"));
326     EXPECT_TRUE(WTF::protocolIsInHTTPFamily("http:"));
327     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("http"));
328     EXPECT_TRUE(WTF::protocolIsInHTTPFamily("https:"));
329     EXPECT_FALSE(WTF::protocolIsInHTTPFamily("https"));
330     EXPECT_TRUE(WTF::protocolIsInHTTPFamily("https://!@#$%^&*()"));
331 }
332
333 TEST_F(URLTest, HostIsIPAddress)
334 {
335     EXPECT_FALSE(URL::hostIsIPAddress({ }));
336     EXPECT_FALSE(URL::hostIsIPAddress(""));
337     EXPECT_FALSE(URL::hostIsIPAddress("localhost"));
338     EXPECT_FALSE(URL::hostIsIPAddress("127.localhost"));
339     EXPECT_FALSE(URL::hostIsIPAddress("localhost.127"));
340     EXPECT_FALSE(URL::hostIsIPAddress("127.0.0"));
341     EXPECT_FALSE(URL::hostIsIPAddress("127.0 .0.1"));
342     EXPECT_FALSE(URL::hostIsIPAddress(" 127.0.0.1"));
343     EXPECT_FALSE(URL::hostIsIPAddress("127..0.0.1"));
344     EXPECT_FALSE(URL::hostIsIPAddress("127.0.0."));
345     EXPECT_FALSE(URL::hostIsIPAddress("256.0.0.1"));
346     EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98"));
347     EXPECT_FALSE(URL::hostIsIPAddress("012x:4567:89AB:cdef:3210:7654:ba98:FeDc"));
348 #if !PLATFORM(COCOA)
349     // FIXME: This fails in Mac.
350     EXPECT_FALSE(URL::hostIsIPAddress("127.0.0.01"));
351     EXPECT_FALSE(URL::hostIsIPAddress("00123:4567:89AB:cdef:3210:7654:ba98:FeDc"));
352 #endif
353     EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:123.45.67.89"));
354     EXPECT_FALSE(URL::hostIsIPAddress(":::"));
355     EXPECT_FALSE(URL::hostIsIPAddress("0123::89AB:cdef:3210:7654::FeDc"));
356     EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98:"));
357     EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98:FeDc:"));
358     EXPECT_FALSE(URL::hostIsIPAddress(":4567:89AB:cdef:3210:7654:ba98:FeDc"));
359     EXPECT_FALSE(URL::hostIsIPAddress(":0123:4567:89AB:cdef:3210:7654:ba98:FeDc"));
360
361     EXPECT_TRUE(URL::hostIsIPAddress("127.0.0.1"));
362     EXPECT_TRUE(URL::hostIsIPAddress("255.1.10.100"));
363     EXPECT_TRUE(URL::hostIsIPAddress("0.0.0.0"));
364     EXPECT_TRUE(URL::hostIsIPAddress("::1"));
365     EXPECT_TRUE(URL::hostIsIPAddress("::"));
366     EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98:FeDc"));
367     EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98::"));
368     EXPECT_TRUE(URL::hostIsIPAddress("::4567:89AB:cdef:3210:7654:ba98:FeDc"));
369     EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:123.45.67.89"));
370     EXPECT_TRUE(URL::hostIsIPAddress("::123.45.67.89"));
371 }
372
373 TEST_F(URLTest, HostIsMatchingDomain)
374 {
375     URL url = createURL("http://www.webkit.org");
376
377     EXPECT_TRUE(url.isMatchingDomain(String { }));
378     EXPECT_TRUE(url.isMatchingDomain(emptyString()));
379     EXPECT_TRUE(url.isMatchingDomain("org"_s));
380     EXPECT_TRUE(url.isMatchingDomain("webkit.org"_s));
381     EXPECT_TRUE(url.isMatchingDomain("www.webkit.org"_s));
382
383     EXPECT_FALSE(url.isMatchingDomain("rg"_s));
384     EXPECT_FALSE(url.isMatchingDomain(".org"_s));
385     EXPECT_FALSE(url.isMatchingDomain("ww.webkit.org"_s));
386     EXPECT_FALSE(url.isMatchingDomain("http://www.webkit.org"_s));
387
388     url = createURL("file:///www.webkit.org");
389
390     EXPECT_TRUE(url.isMatchingDomain(String { }));
391     EXPECT_TRUE(url.isMatchingDomain(emptyString()));
392     EXPECT_FALSE(url.isMatchingDomain("org"_s));
393     EXPECT_FALSE(url.isMatchingDomain("webkit.org"_s));
394     EXPECT_FALSE(url.isMatchingDomain("www.webkit.org"_s));
395
396     URL emptyURL;
397     EXPECT_FALSE(emptyURL.isMatchingDomain(String { }));
398     EXPECT_FALSE(emptyURL.isMatchingDomain(emptyString()));
399 }
400
401 } // namespace TestWebKitAPI