1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.java.net;
18
19import java.net.Inet6Address;
20import java.net.InetAddress;
21import java.net.MalformedURLException;
22import java.net.URISyntaxException;
23import java.net.URI;
24import java.net.URL;
25import junit.framework.TestCase;
26import libcore.util.SerializationTester;
27
28public final class URLTest extends TestCase {
29
30    public void testUrlParts() throws Exception {
31        URL url = new URL("http://username:password@host:8080/directory/file?query#ref");
32        assertEquals("http", url.getProtocol());
33        assertEquals("username:password@host:8080", url.getAuthority());
34        assertEquals("username:password", url.getUserInfo());
35        assertEquals("host", url.getHost());
36        assertEquals(8080, url.getPort());
37        assertEquals(80, url.getDefaultPort());
38        assertEquals("/directory/file?query", url.getFile());
39        assertEquals("/directory/file", url.getPath());
40        assertEquals("query", url.getQuery());
41        assertEquals("ref", url.getRef());
42    }
43    // http://code.google.com/p/android/issues/detail?id=12724
44    public void testExplicitPort() throws Exception {
45        URL url = new URL("http://www.google.com:80/example?language[id]=2");
46        assertEquals("www.google.com", url.getHost());
47        assertEquals(80, url.getPort());
48    }
49
50    /**
51     * Android's URL.equals() works as if the network is down. This is different
52     * from the RI, which does potentially slow and inconsistent DNS lookups in
53     * URL.equals.
54     */
55    public void testEqualsDoesNotDoHostnameResolution() throws Exception {
56        for (InetAddress inetAddress : InetAddress.getAllByName("localhost")) {
57            String address = inetAddress.getHostAddress();
58            if (inetAddress instanceof Inet6Address) {
59                address = "[" + address + "]";
60            }
61            URL urlByHostName = new URL("http://localhost/foo?bar=baz#quux");
62            URL urlByAddress = new URL("http://" + address + "/foo?bar=baz#quux");
63            assertFalse("Expected " + urlByHostName + " to not equal " + urlByAddress,
64                    urlByHostName.equals(urlByAddress)); // fails on RI, which does DNS
65        }
66    }
67
68    public void testEqualsCaseMapping() throws Exception {
69        assertEquals(new URL("HTTP://localhost/foo?bar=baz#quux"),
70                new URL("HTTP://localhost/foo?bar=baz#quux"));
71        assertTrue(new URL("http://localhost/foo?bar=baz#quux").equals(
72                new URL("http://LOCALHOST/foo?bar=baz#quux")));
73        assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
74                new URL("http://localhost/FOO?bar=baz#quux")));
75        assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
76                new URL("http://localhost/foo?BAR=BAZ#quux")));
77        assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
78                new URL("http://localhost/foo?bar=baz#QUUX")));
79    }
80
81    public void testFileEqualsWithEmptyHost() throws Exception {
82        assertEquals(new URL("file", "", -1, "/a/"), new URL("file:/a/"));
83    }
84
85    public void testHttpEqualsWithEmptyHost() throws Exception {
86        assertEquals(new URL("http", "", 80, "/a/"), new URL("http:/a/"));
87        assertFalse(new URL("http", "", 80, "/a/").equals(new URL("http://host/a/")));
88    }
89
90    public void testFileEquals() throws Exception {
91        assertEquals(new URL("file", null, -1, "/a"), new URL("file", null, -1, "/a"));
92        assertFalse(new URL("file", null, -1, "/a").equals(new URL("file", null, -1, "/A")));
93    }
94
95    public void testJarEquals() throws Exception {
96        assertEquals(new URL("jar", null, -1, "/a!b"), new URL("jar", null, -1, "/a!b"));
97        assertFalse(new URL("jar", null, -1, "/a!b").equals(new URL("jar", null, -1, "/a!B")));
98        assertFalse(new URL("jar", null, -1, "/a!b").equals(new URL("jar", null, -1, "/A!b")));
99    }
100
101    public void testUrlSerialization() throws Exception {
102        String s = "aced00057372000c6a6176612e6e65742e55524c962537361afce472030006490004706f72744c0"
103                + "009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c65710"
104                + "07e00014c0004686f737471007e00014c000870726f746f636f6c71007e00014c000372656671007"
105                + "e00017870ffffffff74000e757365723a7061737340686f73747400102f706174682f66696c653f7"
106                + "175657279740004686f7374740004687474707400046861736878";
107        URL url = new URL("http://user:pass@host/path/file?query#hash");
108        new SerializationTester<URL>(url, s).test();
109    }
110
111    /**
112     * The serialized form of a URL includes its hash code. But the hash code
113     * is not documented. Check that we don't return a deserialized hash code
114     * from a deserialized value.
115     */
116    public void testUrlSerializationWithHashCode() throws Exception {
117        String s = "aced00057372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436"
118                + "f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696"
119                + "e673b4c000466696c6571007e00014c0004686f737471007e00014c000870726f746f636f6c71007"
120                + "e00014c000372656671007e00017870cdf0efacffffffff74000e757365723a7061737340686f737"
121                + "47400102f706174682f66696c653f7175657279740004686f7374740004687474707400046861736"
122                + "878";
123        final URL url = new URL("http://user:pass@host/path/file?query#hash");
124        new SerializationTester<URL>(url, s) {
125            @Override protected void verify(URL deserialized) {
126                assertEquals(url.hashCode(), deserialized.hashCode());
127            }
128        }.test();
129    }
130
131    public void testOnlySupportedProtocols() {
132        try {
133            new URL("abcd://host");
134            fail();
135        } catch (MalformedURLException expected) {
136        }
137    }
138
139    public void testOmittedHost() throws Exception {
140        URL url = new URL("http:///path");
141        assertEquals("", url.getHost());
142        assertEquals("/path", url.getFile());
143        assertEquals("/path", url.getPath());
144    }
145
146    public void testNoHost() throws Exception {
147        URL url = new URL("http:/path");
148        assertEquals("http", url.getProtocol());
149        assertEquals(null, url.getAuthority());
150        assertEquals(null, url.getUserInfo());
151        assertEquals("", url.getHost());
152        assertEquals(-1, url.getPort());
153        assertEquals(80, url.getDefaultPort());
154        assertEquals("/path", url.getFile());
155        assertEquals("/path", url.getPath());
156        assertEquals(null, url.getQuery());
157        assertEquals(null, url.getRef());
158    }
159
160    public void testNoPath() throws Exception {
161        URL url = new URL("http://host");
162        assertEquals("host", url.getHost());
163        assertEquals("", url.getFile());
164        assertEquals("", url.getPath());
165    }
166
167    public void testEmptyHostAndNoPath() throws Exception {
168        URL url = new URL("http://");
169        assertEquals("http", url.getProtocol());
170        assertEquals("", url.getAuthority());
171        assertEquals(null, url.getUserInfo());
172        assertEquals("", url.getHost());
173        assertEquals(-1, url.getPort());
174        assertEquals(80, url.getDefaultPort());
175        assertEquals("", url.getFile());
176        assertEquals("", url.getPath());
177        assertEquals(null, url.getQuery());
178        assertEquals(null, url.getRef());
179    }
180
181    public void testNoHostAndNoPath() throws Exception {
182        URL url = new URL("http:");
183        assertEquals("http", url.getProtocol());
184        assertEquals(null, url.getAuthority());
185        assertEquals(null, url.getUserInfo());
186        assertEquals("", url.getHost());
187        assertEquals(-1, url.getPort());
188        assertEquals(80, url.getDefaultPort());
189        assertEquals("", url.getFile());
190        assertEquals("", url.getPath());
191        assertEquals(null, url.getQuery());
192        assertEquals(null, url.getRef());
193    }
194
195    public void testAtSignInUserInfo() throws Exception {
196        try {
197            new URL("http://user@userhost.com:password@host");
198            fail();
199        } catch (MalformedURLException expected) {
200        }
201    }
202
203    public void testUserNoPassword() throws Exception {
204        URL url = new URL("http://user@host");
205        assertEquals("user@host", url.getAuthority());
206        assertEquals("user", url.getUserInfo());
207        assertEquals("host", url.getHost());
208    }
209
210    public void testUserNoPasswordExplicitPort() throws Exception {
211        URL url = new URL("http://user@host:8080");
212        assertEquals("user@host:8080", url.getAuthority());
213        assertEquals("user", url.getUserInfo());
214        assertEquals("host", url.getHost());
215        assertEquals(8080, url.getPort());
216    }
217
218    public void testUserPasswordHostPort() throws Exception {
219        URL url = new URL("http://user:password@host:8080");
220        assertEquals("user:password@host:8080", url.getAuthority());
221        assertEquals("user:password", url.getUserInfo());
222        assertEquals("host", url.getHost());
223        assertEquals(8080, url.getPort());
224    }
225
226    public void testUserPasswordEmptyHostPort() throws Exception {
227        URL url = new URL("http://user:password@:8080");
228        assertEquals("user:password@:8080", url.getAuthority());
229        assertEquals("user:password", url.getUserInfo());
230        assertEquals("", url.getHost());
231        assertEquals(8080, url.getPort());
232    }
233
234    public void testUserPasswordEmptyHostEmptyPort() throws Exception {
235        URL url = new URL("http://user:password@");
236        assertEquals("user:password@", url.getAuthority());
237        assertEquals("user:password", url.getUserInfo());
238        assertEquals("", url.getHost());
239        assertEquals(-1, url.getPort());
240    }
241
242    public void testPathOnly() throws Exception {
243        URL url = new URL("http://host/path");
244        assertEquals("/path", url.getFile());
245        assertEquals("/path", url.getPath());
246    }
247
248    public void testQueryOnly() throws Exception {
249        URL url = new URL("http://host?query");
250        assertEquals("?query", url.getFile());
251        assertEquals("", url.getPath());
252        assertEquals("query", url.getQuery());
253    }
254
255    public void testFragmentOnly() throws Exception {
256        URL url = new URL("http://host#fragment");
257        assertEquals("", url.getFile());
258        assertEquals("", url.getPath());
259        assertEquals("fragment", url.getRef());
260    }
261
262    public void testAtSignInPath() throws Exception {
263        URL url = new URL("http://host/file@foo");
264        assertEquals("/file@foo", url.getFile());
265        assertEquals("/file@foo", url.getPath());
266        assertEquals(null, url.getUserInfo());
267    }
268
269    public void testColonInPath() throws Exception {
270        URL url = new URL("http://host/file:colon");
271        assertEquals("/file:colon", url.getFile());
272        assertEquals("/file:colon", url.getPath());
273    }
274
275    public void testSlashInQuery() throws Exception {
276        URL url = new URL("http://host/file?query/path");
277        assertEquals("/file?query/path", url.getFile());
278        assertEquals("/file", url.getPath());
279        assertEquals("query/path", url.getQuery());
280    }
281
282    public void testQuestionMarkInQuery() throws Exception {
283        URL url = new URL("http://host/file?query?another");
284        assertEquals("/file?query?another", url.getFile());
285        assertEquals("/file", url.getPath());
286        assertEquals("query?another", url.getQuery());
287    }
288
289    public void testAtSignInQuery() throws Exception {
290        URL url = new URL("http://host/file?query@at");
291        assertEquals("/file?query@at", url.getFile());
292        assertEquals("/file", url.getPath());
293        assertEquals("query@at", url.getQuery());
294    }
295
296    public void testColonInQuery() throws Exception {
297        URL url = new URL("http://host/file?query:colon");
298        assertEquals("/file?query:colon", url.getFile());
299        assertEquals("/file", url.getPath());
300        assertEquals("query:colon", url.getQuery());
301    }
302
303    public void testQuestionMarkInFragment() throws Exception {
304        URL url = new URL("http://host/file#fragment?query");
305        assertEquals("/file", url.getFile());
306        assertEquals("/file", url.getPath());
307        assertEquals(null, url.getQuery());
308        assertEquals("fragment?query", url.getRef());
309    }
310
311    public void testColonInFragment() throws Exception {
312        URL url = new URL("http://host/file#fragment:80");
313        assertEquals("/file", url.getFile());
314        assertEquals("/file", url.getPath());
315        assertEquals(-1, url.getPort());
316        assertEquals("fragment:80", url.getRef());
317    }
318
319    public void testSlashInFragment() throws Exception {
320        URL url = new URL("http://host/file#fragment/path");
321        assertEquals("/file", url.getFile());
322        assertEquals("/file", url.getPath());
323        assertEquals("fragment/path", url.getRef());
324    }
325
326    public void testSlashInFragmentCombiningConstructor() throws Exception {
327        URL url = new URL("http", "host", "/file#fragment/path");
328        assertEquals("/file", url.getFile());
329        assertEquals("/file", url.getPath());
330        assertEquals("fragment/path", url.getRef());
331    }
332
333    public void testHashInFragment() throws Exception {
334        URL url = new URL("http://host/file#fragment#another");
335        assertEquals("/file", url.getFile());
336        assertEquals("/file", url.getPath());
337        assertEquals("fragment#another", url.getRef());
338    }
339
340    public void testEmptyPort() throws Exception {
341        URL url = new URL("http://host:/");
342        assertEquals(-1, url.getPort());
343    }
344
345    public void testNonNumericPort() throws Exception {
346        try {
347            new URL("http://host:x/");
348            fail();
349        } catch (MalformedURLException expected) {
350        }
351    }
352
353    public void testNegativePort() throws Exception {
354        try {
355            new URL("http://host:-2/");
356            fail();
357        } catch (MalformedURLException expected) {
358        }
359    }
360
361    public void testNegativePortEqualsPlaceholder() throws Exception {
362        try {
363            new URL("http://host:-1/");
364            fail(); // RI fails this
365        } catch (MalformedURLException expected) {
366        }
367    }
368
369    public void testRelativePathOnQuery() throws Exception {
370        URL base = new URL("http://host/file?query/x");
371        URL url = new URL(base, "another");
372        assertEquals("http://host/another", url.toString());
373        assertEquals("/another", url.getFile());
374        assertEquals("/another", url.getPath());
375        assertEquals(null, url.getQuery());
376        assertEquals(null, url.getRef());
377    }
378
379    public void testRelativeFragmentOnQuery() throws Exception {
380        URL base = new URL("http://host/file?query/x#fragment");
381        URL url = new URL(base, "#another");
382        assertEquals("http://host/file?query/x#another", url.toString());
383        assertEquals("/file?query/x", url.getFile());
384        assertEquals("/file", url.getPath());
385        assertEquals("query/x", url.getQuery());
386        assertEquals("another", url.getRef());
387    }
388
389    public void testPathContainsRelativeParts() throws Exception {
390        URL url = new URL("http://host/a/b/../c");
391        assertEquals("http://host/a/c", url.toString()); // RI doesn't canonicalize
392    }
393
394    public void testRelativePathAndFragment() throws Exception {
395        URL base = new URL("http://host/file");
396        assertEquals("http://host/another#fragment", new URL(base, "another#fragment").toString());
397    }
398
399    public void testRelativeParentDirectory() throws Exception {
400        URL base = new URL("http://host/a/b/c");
401        assertEquals("http://host/a/d", new URL(base, "../d").toString());
402    }
403
404    public void testRelativeChildDirectory() throws Exception {
405        URL base = new URL("http://host/a/b/c");
406        assertEquals("http://host/a/b/d/e", new URL(base, "d/e").toString());
407    }
408
409    public void testRelativeRootDirectory() throws Exception {
410        URL base = new URL("http://host/a/b/c");
411        assertEquals("http://host/d", new URL(base, "/d").toString());
412    }
413
414    public void testRelativeFullUrl() throws Exception {
415        URL base = new URL("http://host/a/b/c");
416        assertEquals("http://host2/d/e", new URL(base, "http://host2/d/e").toString());
417        assertEquals("https://host2/d/e", new URL(base, "https://host2/d/e").toString());
418    }
419
420    public void testRelativeDifferentScheme() throws Exception {
421        URL base = new URL("http://host/a/b/c");
422        assertEquals("https://host2/d/e", new URL(base, "https://host2/d/e").toString());
423    }
424
425    public void testRelativeDifferentAuthority() throws Exception {
426        URL base = new URL("http://host/a/b/c");
427        assertEquals("http://another/d/e", new URL(base, "//another/d/e").toString());
428    }
429
430    public void testRelativeWithScheme() throws Exception {
431        URL base = new URL("http://host/a/b/c");
432        assertEquals("http://host/a/b/c", new URL(base, "http:").toString());
433        assertEquals("http://host/", new URL(base, "http:/").toString());
434    }
435
436    public void testMalformedUrlsRefusedByFirefoxAndChrome() throws Exception {
437        URL base = new URL("http://host/a/b/c");
438        assertEquals("http://", new URL(base, "http://").toString()); // fails on RI; path retained
439        assertEquals("http://", new URL(base, "//").toString()); // fails on RI
440        assertEquals("https:", new URL(base, "https:").toString());
441        assertEquals("https:/", new URL(base, "https:/").toString());
442        assertEquals("https://", new URL(base, "https://").toString());
443    }
444
445    public void testRfc1808NormalExamples() throws Exception {
446        URL base = new URL("http://a/b/c/d;p?q");
447        assertEquals("https:h", new URL(base, "https:h").toString());
448        assertEquals("http://a/b/c/g", new URL(base, "g").toString());
449        assertEquals("http://a/b/c/g", new URL(base, "./g").toString());
450        assertEquals("http://a/b/c/g/", new URL(base, "g/").toString());
451        assertEquals("http://a/g", new URL(base, "/g").toString());
452        assertEquals("http://g", new URL(base, "//g").toString());
453        assertEquals("http://a/b/c/d;p?y", new URL(base, "?y").toString()); // RI fails; file lost
454        assertEquals("http://a/b/c/g?y", new URL(base, "g?y").toString());
455        assertEquals("http://a/b/c/d;p?q#s", new URL(base, "#s").toString());
456        assertEquals("http://a/b/c/g#s", new URL(base, "g#s").toString());
457        assertEquals("http://a/b/c/g?y#s", new URL(base, "g?y#s").toString());
458        assertEquals("http://a/b/c/;x", new URL(base, ";x").toString());
459        assertEquals("http://a/b/c/g;x", new URL(base, "g;x").toString());
460        assertEquals("http://a/b/c/g;x?y#s", new URL(base, "g;x?y#s").toString());
461        assertEquals("http://a/b/c/d;p?q", new URL(base, "").toString());
462        assertEquals("http://a/b/c/", new URL(base, ".").toString());
463        assertEquals("http://a/b/c/", new URL(base, "./").toString());
464        assertEquals("http://a/b/", new URL(base, "..").toString());
465        assertEquals("http://a/b/", new URL(base, "../").toString());
466        assertEquals("http://a/b/g", new URL(base, "../g").toString());
467        assertEquals("http://a/", new URL(base, "../..").toString());
468        assertEquals("http://a/", new URL(base, "../../").toString());
469        assertEquals("http://a/g", new URL(base, "../../g").toString());
470    }
471
472    public void testRfc1808AbnormalExampleTooManyDotDotSequences() throws Exception {
473        URL base = new URL("http://a/b/c/d;p?q");
474        assertEquals("http://a/g", new URL(base, "../../../g").toString()); // RI doesn't normalize
475        assertEquals("http://a/g", new URL(base, "../../../../g").toString());
476    }
477
478    public void testRfc1808AbnormalExampleRemoveDotSegments() throws Exception {
479        URL base = new URL("http://a/b/c/d;p?q");
480        assertEquals("http://a/g", new URL(base, "/./g").toString()); // RI doesn't normalize
481        assertEquals("http://a/g", new URL(base, "/../g").toString()); // RI doesn't normalize
482        assertEquals("http://a/b/c/g.", new URL(base, "g.").toString());
483        assertEquals("http://a/b/c/.g", new URL(base, ".g").toString());
484        assertEquals("http://a/b/c/g..", new URL(base, "g..").toString());
485        assertEquals("http://a/b/c/..g", new URL(base, "..g").toString());
486    }
487
488    public void testRfc1808AbnormalExampleNonsensicalDots() throws Exception {
489        URL base = new URL("http://a/b/c/d;p?q");
490        assertEquals("http://a/b/g", new URL(base, "./../g").toString());
491        assertEquals("http://a/b/c/g/", new URL(base, "./g/.").toString());
492        assertEquals("http://a/b/c/g/h", new URL(base, "g/./h").toString());
493        assertEquals("http://a/b/c/h", new URL(base, "g/../h").toString());
494        assertEquals("http://a/b/c/g;x=1/y", new URL(base, "g;x=1/./y").toString());
495        assertEquals("http://a/b/c/y", new URL(base, "g;x=1/../y").toString());
496    }
497
498    public void testRfc1808AbnormalExampleRelativeScheme() throws Exception {
499        URL base = new URL("http://a/b/c/d;p?q");
500        // this result is permitted; strict parsers prefer "http:g"
501        assertEquals("http://a/b/c/g", new URL(base, "http:g").toString());
502    }
503
504    public void testRfc1808AbnormalExampleQueryOrFragmentDots() throws Exception {
505        URL base = new URL("http://a/b/c/d;p?q");
506        assertEquals("http://a/b/c/g?y/./x", new URL(base, "g?y/./x").toString());
507        assertEquals("http://a/b/c/g?y/../x", new URL(base, "g?y/../x").toString());
508        assertEquals("http://a/b/c/g#s/./x", new URL(base, "g#s/./x").toString());
509        assertEquals("http://a/b/c/g#s/../x", new URL(base, "g#s/../x").toString());
510    }
511
512    public void testSquareBracketsInUserInfo() throws Exception {
513        URL url = new URL("http://user:[::1]@host");
514        assertEquals("user:[::1]", url.getUserInfo());
515        assertEquals("host", url.getHost());
516    }
517
518    public void testComposeUrl() throws Exception {
519        URL url = new URL("http", "host", "a");
520        assertEquals("http", url.getProtocol());
521        assertEquals("host", url.getAuthority());
522        assertEquals("host", url.getHost());
523        assertEquals("/a", url.getFile()); // RI fails; doesn't insert '/' separator
524        assertEquals("http://host/a", url.toString()); // fails on RI
525    }
526
527    public void testComposeUrlWithNullHost() throws Exception {
528        URL url = new URL("http", null, "a");
529        assertEquals("http", url.getProtocol());
530        assertEquals(null, url.getAuthority());
531        assertEquals(null, url.getHost());
532        assertEquals("a", url.getFile());
533        assertEquals("http:a", url.toString()); // fails on RI
534    }
535
536    public void testFileUrlExtraLeadingSlashes() throws Exception {
537        URL url = new URL("file:////foo");
538        assertEquals("", url.getAuthority()); // RI returns null
539        assertEquals("//foo", url.getPath());
540        assertEquals("file:////foo", url.toString());
541    }
542
543    public void testFileUrlWithAuthority() throws Exception {
544        URL url = new URL("file://x/foo");
545        assertEquals("x", url.getAuthority());
546        assertEquals("/foo", url.getPath());
547        assertEquals("file://x/foo", url.toString());
548    }
549
550    /**
551     * The RI is not self-consistent on missing authorities, returning either
552     * null or the empty string depending on the number of slashes in the path.
553     * We always treat '//' as the beginning of an authority.
554     */
555    public void testEmptyAuthority() throws Exception {
556        URL url = new URL("http:///foo");
557        assertEquals("", url.getAuthority());
558        assertEquals("/foo", url.getPath());
559        assertEquals("http:///foo", url.toString()); // RI drops '//'
560    }
561
562    public void testHttpUrlExtraLeadingSlashes() throws Exception {
563        URL url = new URL("http:////foo");
564        assertEquals("", url.getAuthority()); // RI returns null
565        assertEquals("//foo", url.getPath());
566        assertEquals("http:////foo", url.toString());
567    }
568
569    public void testFileUrlRelativePath() throws Exception {
570        URL base = new URL("file:a/b/c");
571        assertEquals("file:a/b/d", new URL(base, "d").toString());
572    }
573
574    public void testFileUrlDottedPath() throws Exception {
575        URL url = new URL("file:../a/b");
576        assertEquals("../a/b", url.getPath());
577        assertEquals("file:../a/b", url.toString());
578    }
579
580    public void testParsingDotAsHostname() throws Exception {
581        URL url = new URL("http://./");
582        assertEquals(".", url.getAuthority());
583        assertEquals(".", url.getHost());
584    }
585
586    public void testSquareBracketsWithIPv4() throws Exception {
587        try {
588            new URL("http://[192.168.0.1]/");
589            fail();
590        } catch (MalformedURLException expected) {
591        }
592        URL url = new URL("http", "[192.168.0.1]", "/");
593        assertEquals("[192.168.0.1]", url.getHost());
594    }
595
596    public void testSquareBracketsWithHostname() throws Exception {
597        try {
598            new URL("http://[www.android.com]/");
599            fail();
600        } catch (MalformedURLException expected) {
601        }
602        URL url = new URL("http", "[www.android.com]", "/");
603        assertEquals("[www.android.com]", url.getHost());
604    }
605
606    public void testIPv6WithoutSquareBrackets() throws Exception {
607        try {
608            new URL("http://fe80::1234/");
609            fail();
610        } catch (MalformedURLException expected) {
611        }
612        URL url = new URL("http", "fe80::1234", "/");
613        assertEquals("[fe80::1234]", url.getHost());
614    }
615
616    public void testIpv6WithSquareBrackets() throws Exception {
617        URL url = new URL("http://[::1]:2/");
618        assertEquals("[::1]", url.getHost());
619        assertEquals(2, url.getPort());
620    }
621
622    public void testEqualityWithNoPath() throws Exception {
623        assertFalse(new URL("http://android.com").equals(new URL("http://android.com/")));
624    }
625
626    public void testUrlDoesNotEncodeParts() throws Exception {
627        URL url = new URL("http", "host", 80, "/doc|search?q=green robots#over 6\"");
628        assertEquals("http", url.getProtocol());
629        assertEquals("host:80", url.getAuthority());
630        assertEquals("/doc|search", url.getPath());
631        assertEquals("q=green robots", url.getQuery());
632        assertEquals("over 6\"", url.getRef());
633        assertEquals("http://host:80/doc|search?q=green robots#over 6\"", url.toString());
634    }
635
636    public void testSchemeCaseIsCanonicalized() throws Exception {
637        URL url = new URL("HTTP://host/path");
638        assertEquals("http", url.getProtocol());
639    }
640
641    public void testEmptyAuthorityWithPath() throws Exception {
642        URL url = new URL("http:///path");
643        assertEquals("", url.getAuthority());
644        assertEquals("/path", url.getPath());
645    }
646
647    public void testEmptyAuthorityWithQuery() throws Exception {
648        URL url = new URL("http://?query");
649        assertEquals("", url.getAuthority());
650        assertEquals("", url.getPath());
651        assertEquals("query", url.getQuery());
652    }
653
654    public void testEmptyAuthorityWithFragment() throws Exception {
655        URL url = new URL("http://#fragment");
656        assertEquals("", url.getAuthority());
657        assertEquals("", url.getPath());
658        assertEquals("fragment", url.getRef());
659    }
660
661    public void testCombiningConstructorsMakeRelativePathsAbsolute() throws Exception {
662        assertEquals("/relative", new URL("http", "host", "relative").getPath());
663        assertEquals("/relative", new URL("http", "host", -1, "relative").getPath());
664        assertEquals("/relative", new URL("http", "host", -1, "relative", null).getPath());
665    }
666
667    public void testCombiningConstructorsDoNotMakeEmptyPathsAbsolute() throws Exception {
668        assertEquals("", new URL("http", "host", "").getPath());
669        assertEquals("", new URL("http", "host", -1, "").getPath());
670        assertEquals("", new URL("http", "host", -1, "", null).getPath());
671    }
672
673    public void testPartContainsSpace() throws Exception {
674        try {
675            new URL("ht tp://host/");
676            fail();
677        } catch (MalformedURLException expected) {
678        }
679        assertEquals("user name", new URL("http://user name@host/").getUserInfo());
680        assertEquals("ho st", new URL("http://ho st/").getHost());
681        try {
682            new URL("http://host:80 80/");
683            fail();
684        } catch (MalformedURLException expected) {
685        }
686        assertEquals("/fi le", new URL("http://host/fi le").getFile());
687        assertEquals("que ry", new URL("http://host/file?que ry").getQuery());
688        assertEquals("re f", new URL("http://host/file?query#re f").getRef());
689    }
690
691    // http://code.google.com/p/android/issues/detail?id=37577
692    public void testUnderscore() throws Exception {
693        URL url = new URL("http://a_b.c.d.net/");
694        assertEquals("a_b.c.d.net", url.getAuthority());
695        // The RFC's don't permit underscores in hostnames, but URL accepts them (unlike URI).
696        assertEquals("a_b.c.d.net", url.getHost());
697    }
698
699    // http://b/7369778
700    public void testToURILeniantThrowsURISyntaxExceptionWithPartialTrailingEscape()
701            throws Exception {
702        // make sure if there a partial trailing escape that we don't throw the wrong exception
703        URL[] badUrls = new URL[] {
704            new URL("http://example.com/?foo=%%bar"),
705            new URL("http://example.com/?foo=%%bar%"),
706            new URL("http://example.com/?foo=%%bar%2"),
707            new URL("http://example.com/?foo=%%bar%%"),
708            new URL("http://example.com/?foo=%%bar%%%"),
709            new URL("http://example.com/?foo=%%bar%%%%"),
710        };
711        for (URL badUrl : badUrls) {
712            try {
713                badUrl.toURILenient();
714                fail();
715            } catch (URISyntaxException expected) {
716            }
717        }
718
719        // make sure we properly handle an normal escape at the end of a string
720        String[] goodUrls = new String[] {
721            "http://example.com/?foo=bar",
722            "http://example.com/?foo=bar%20",
723        };
724        for (String goodUrl : goodUrls) {
725            assertEquals(new URI(goodUrl), new URL(goodUrl).toURILenient());
726        }
727    }
728
729    // Adding a new test? Consider adding an equivalent test to URITest.java
730}
731