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
32namespace TestWebKitAPI {
33
34class WTF_URL : public testing::Test {
35public:
36 virtual void SetUp()
37 {
38 WTF::initializeMainThread();
39 }
40};
41
42TEST_F(WTF_URL, URLConstructorDefault)
43{
44 URL kurl;
45
46 EXPECT_TRUE(kurl.isEmpty());
47 EXPECT_TRUE(kurl.isNull());
48 EXPECT_FALSE(kurl.isValid());
49}
50
51TEST_F(WTF_URL, URLConstructorConstChar)
52{
53 URL kurl({ }, "http://username:[email protected]: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
72static URL createURL(const char* urlAsString)
73{
74 return URL({ }, urlAsString);
75};
76
77TEST_F(WTF_URL, URLProtocolHostAndPort)
78{
79 auto url = createURL("http://username:[email protected]: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://:[email protected]:8080/index.html?var=val#fragment");
86 EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
87
88 url = createURL("http://[email protected]: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:[email protected]: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
119TEST_F(WTF_URL, 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
128TEST_F(WTF_URL, 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
160TEST_F(WTF_URL, 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
189TEST_F(WTF_URL, 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
213TEST_F(WTF_URL, 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
264TEST_F(WTF_URL, 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
315TEST_F(WTF_URL, 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
333TEST_F(WTF_URL, 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
373TEST_F(WTF_URL, 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
402