blob: 066442e44e0b9e95161ba71f87752f2f96247f8a [file] [log] [blame]
Elliott Hughes6470a302010-11-29 18:17:06 -08001/*
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
Tobias Thierer7dbee732018-02-08 21:45:09 +000019import junit.framework.TestCase;
20
21import java.io.IOException;
22import java.lang.reflect.Field;
23import java.lang.reflect.Method;
24import java.lang.reflect.Modifier;
Jesse Wilson7e00db42011-01-30 14:28:49 -080025import java.net.Inet6Address;
26import java.net.InetAddress;
Jesse Wilson8f99aa02011-05-20 16:30:30 -070027import java.net.MalformedURLException;
Elliott Hughes6470a302010-11-29 18:17:06 -080028import java.net.URL;
Tobias Thierer7dbee732018-02-08 21:45:09 +000029import java.net.URLConnection;
30import java.net.URLStreamHandler;
31import java.net.URLStreamHandlerFactory;
32import java.util.Arrays;
33import java.util.HashSet;
34import java.util.Set;
35import java.util.concurrent.Callable;
36import libcore.libcore.util.SerializationTester;
Narayan Kamathb93dbae2016-02-01 15:54:33 +000037
38import dalvik.system.BlockGuard;
Tobias Thierer7dbee732018-02-08 21:45:09 +000039
40import static java.util.Arrays.asList;
Elliott Hughes6470a302010-11-29 18:17:06 -080041
Jesse Wilson52924102011-05-23 18:38:38 -070042public final class URLTest extends TestCase {
Jesse Wilson8f99aa02011-05-20 16:30:30 -070043
44 public void testUrlParts() throws Exception {
45 URL url = new URL("http://username:password@host:8080/directory/file?query#ref");
46 assertEquals("http", url.getProtocol());
47 assertEquals("username:password@host:8080", url.getAuthority());
Jesse Wilson8f99aa02011-05-20 16:30:30 -070048 assertEquals("username:password", url.getUserInfo());
49 assertEquals("host", url.getHost());
50 assertEquals(8080, url.getPort());
Jesse Wilson8f99aa02011-05-20 16:30:30 -070051 assertEquals(80, url.getDefaultPort());
Jesse Wilson52924102011-05-23 18:38:38 -070052 assertEquals("/directory/file?query", url.getFile());
53 assertEquals("/directory/file", url.getPath());
54 assertEquals("query", url.getQuery());
55 assertEquals("ref", url.getRef());
Jesse Wilson8f99aa02011-05-20 16:30:30 -070056 }
Elliott Hughes6470a302010-11-29 18:17:06 -080057 // http://code.google.com/p/android/issues/detail?id=12724
58 public void testExplicitPort() throws Exception {
59 URL url = new URL("http://www.google.com:80/example?language[id]=2");
60 assertEquals("www.google.com", url.getHost());
61 assertEquals(80, url.getPort());
62 }
Jesse Wilson8fd02252010-12-06 11:59:04 -080063
Jesse Wilson7e00db42011-01-30 14:28:49 -080064 /**
65 * Android's URL.equals() works as if the network is down. This is different
66 * from the RI, which does potentially slow and inconsistent DNS lookups in
67 * URL.equals.
68 */
69 public void testEqualsDoesNotDoHostnameResolution() throws Exception {
70 for (InetAddress inetAddress : InetAddress.getAllByName("localhost")) {
71 String address = inetAddress.getHostAddress();
72 if (inetAddress instanceof Inet6Address) {
73 address = "[" + address + "]";
74 }
75 URL urlByHostName = new URL("http://localhost/foo?bar=baz#quux");
76 URL urlByAddress = new URL("http://" + address + "/foo?bar=baz#quux");
77 assertFalse("Expected " + urlByHostName + " to not equal " + urlByAddress,
Jesse Wilsonc68609e2011-05-26 19:33:57 -070078 urlByHostName.equals(urlByAddress)); // fails on RI, which does DNS
Jesse Wilson7e00db42011-01-30 14:28:49 -080079 }
80 }
81
82 public void testEqualsCaseMapping() throws Exception {
83 assertEquals(new URL("HTTP://localhost/foo?bar=baz#quux"),
84 new URL("HTTP://localhost/foo?bar=baz#quux"));
85 assertTrue(new URL("http://localhost/foo?bar=baz#quux").equals(
86 new URL("http://LOCALHOST/foo?bar=baz#quux")));
87 assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
88 new URL("http://localhost/FOO?bar=baz#quux")));
89 assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
90 new URL("http://localhost/foo?BAR=BAZ#quux")));
91 assertFalse(new URL("http://localhost/foo?bar=baz#quux").equals(
92 new URL("http://localhost/foo?bar=baz#QUUX")));
93 }
Jesse Wilsonf5fc66d2011-02-22 21:47:19 -080094
Jesse Wilson52924102011-05-23 18:38:38 -070095 public void testFileEqualsWithEmptyHost() throws Exception {
96 assertEquals(new URL("file", "", -1, "/a/"), new URL("file:/a/"));
97 }
98
99 public void testHttpEqualsWithEmptyHost() throws Exception {
100 assertEquals(new URL("http", "", 80, "/a/"), new URL("http:/a/"));
101 assertFalse(new URL("http", "", 80, "/a/").equals(new URL("http://host/a/")));
102 }
103
104 public void testFileEquals() throws Exception {
105 assertEquals(new URL("file", null, -1, "/a"), new URL("file", null, -1, "/a"));
106 assertFalse(new URL("file", null, -1, "/a").equals(new URL("file", null, -1, "/A")));
107 }
108
109 public void testJarEquals() throws Exception {
110 assertEquals(new URL("jar", null, -1, "/a!b"), new URL("jar", null, -1, "/a!b"));
111 assertFalse(new URL("jar", null, -1, "/a!b").equals(new URL("jar", null, -1, "/a!B")));
112 assertFalse(new URL("jar", null, -1, "/a!b").equals(new URL("jar", null, -1, "/A!b")));
Jesse Wilson6c434a12011-02-21 14:00:10 -0800113 }
Jesse Wilson8f99aa02011-05-20 16:30:30 -0700114
115 public void testUrlSerialization() throws Exception {
116 String s = "aced00057372000c6a6176612e6e65742e55524c962537361afce472030006490004706f72744c0"
117 + "009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c65710"
118 + "07e00014c0004686f737471007e00014c000870726f746f636f6c71007e00014c000372656671007"
119 + "e00017870ffffffff74000e757365723a7061737340686f73747400102f706174682f66696c653f7"
120 + "175657279740004686f7374740004687474707400046861736878";
121 URL url = new URL("http://user:pass@host/path/file?query#hash");
Jesse Wilsonb416ef52011-12-13 19:03:54 -0500122 new SerializationTester<URL>(url, s).test();
Jesse Wilson8f99aa02011-05-20 16:30:30 -0700123 }
124
125 /**
Tobias Thierer7dbee732018-02-08 21:45:09 +0000126 * For a custom URLStreamHandler, a (de)serialization round trip reconstructs an
127 * inconsistently null authority from host and port.
128 */
129 public void testUrlSerializationRoundTrip_customHandler_nullAuthorityReconstructed()
130 throws Exception {
131 withCustomURLStreamHandlerFactory(() -> {
132 URL url = new URL("android://example.com:80/file");
133 getUrlField("authority").set(url, null);
134 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
135
136 assertFields(url, "android", "example.com", 80, null, "/file");
137 assertFields(reserializedUrl, "android", "example.com", 80, "example.com:80", "/file");
138 return null;
139 });
140 }
141
142 /**
143 * For a custom URLStreamHandler, a (de)serialization round trip does not reconstruct
144 * an inconsistent but nonnull authority from host and port.
145 */
146 public void testUrlSerializationRoundTrip_customHandler_nonnullAuthorityNotReconstructed()
147 throws Exception {
148 withCustomURLStreamHandlerFactory(() -> {
149 URL url = new URL("android://example.com/file");
150 getUrlField("authority").set(url, "evil.com:1234");
151 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
152
153 assertFields(url, "android", "example.com", -1, "evil.com:1234", "/file");
154 assertFields(reserializedUrl, "android", "example.com", -1, "evil.com:1234", "/file");
155 return null;
156 });
157 }
158
159 /**
160 * For a custom URLStreamHandler, a (de)serialization round trip does not
161 * reconstruct host and port from the authority, even if host is null.
162 */
163 public void testUrlSerializationRoundTrip_customHandler_hostAndPortNotReconstructed()
164 throws Exception {
165 checkUrlSerializationRoundTrip_customHandler_hostAndPortNotReconstructed(null /* host */);
166 checkUrlSerializationRoundTrip_customHandler_hostAndPortNotReconstructed("evil.com");
167 }
168
169 private void checkUrlSerializationRoundTrip_customHandler_hostAndPortNotReconstructed(
170 final String hostOrNull) throws Exception {
171 withCustomURLStreamHandlerFactory(() -> {
172 URL url = new URL("android://example.com:80/file");
173 getUrlField("host").set(url, hostOrNull);
174 getUrlField("port").set(url, 12345);
175 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
176
177 assertFields(url, "android", hostOrNull, 12345, "example.com:80", "/file");
178 assertFields(reserializedUrl, "android", hostOrNull, 12345, "example.com:80", "/file");
179 return null;
180 });
181 }
182
183 /**
184 * Temporarily registers a {@link URLStreamHandlerFactory} that accepts any protocol,
185 * and then, while that factory is registered, runs the given {@code callable} on this
186 * thread.
187 * @throw Exception any Exception thrown by the Callable will be thrown on to the caller.
188 */
189 private static void withCustomURLStreamHandlerFactory(Callable<Void> callable)
190 throws Exception {
191 Field factoryField = getUrlField("factory");
192 assertTrue(Modifier.isStatic(factoryField.getModifiers()));
193 URLStreamHandlerFactory oldFactory = (URLStreamHandlerFactory) factoryField.get(null);
194 try {
195 URL.setURLStreamHandlerFactory(
196 protocol -> new libcore.java.net.customstreamhandler.http.Handler());
197 callable.call();
198 } finally {
199 factoryField.set(null, null);
200 URL.setURLStreamHandlerFactory(oldFactory);
201 }
202 }
203
204 /**
205 * Host and port are reconstructed from the authority during deserialization.
206 */
207 public void testUrlSerializationRoundTrip_builtinHandler_hostAndPortReconstructed()
208 throws Exception {
209 URL url = new URL("http://example.com:42/file");
210 getUrlField("host").set(url, "wronghost.com");
211 getUrlField("port").setInt(url, 1234);
212 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
213 assertFields(url, "http", "wronghost.com", 1234, "example.com:42", "/file");
214 assertFields(reserializedUrl, "http", "example.com", 42, "example.com:42", "/file");
215
216 // Check that the normalization occurs during deserialization rather than during
217 // serialization.
218 assertFalse(Arrays.equals(
219 SerializationTester.serialize(url),
220 SerializationTester.serialize(reserializedUrl)
221 ));
222 assertTrue(Arrays.equals(
223 SerializationTester.serialize(reserializedUrl),
224 SerializationTester.serialize(reserializedUrl)
225 ));
226 }
227
228 /**
229 * The authority is not reconstructed from host and port, but the other way around.
230 */
231 public void testUrlSerializationRoundTrip_builtinHandler_authorityNotReconstructed()
232 throws Exception {
233 URL url = new URL("http://example.com/file");
234 getUrlField("authority").set(url, "newhost.com:80");
235 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
236
237 assertFields(url, "http", "example.com", -1, "newhost.com:80", "/file");
238 assertFields(reserializedUrl, "http", "newhost.com", 80, "newhost.com:80", "/file");
239 }
240
241 /**
242 * The boundary where the authority part ends and the file part starts is
243 * reconstructed during deserialization.
244 */
245 public void testUrlSerializationRoundTrip_builtinHandler_authorityAndFileReconstructed()
246 throws Exception {
247 URL url = new URL("http://temporaryhost.com/temporaryfile");
248 getUrlField("authority").set(url, "exam");
249 getUrlField("file").set(url, "ple.com:80/file");
250 URL reserializedUrl = (URL) SerializationTester.reserialize(url);
251 assertFields(reserializedUrl, "http", "example.com", 80, "example.com:80", "/file");
252 }
253
254 private static Field getUrlField(String fieldName) throws Exception {
255 Field result = URL.class.getDeclaredField(fieldName);
256 result.setAccessible(true);
257 return result;
258 }
259
260 private static void assertFields(URL url,
261 String protocol, String host, int port, String authority, String file) {
262 assertEquals(
263 asList(protocol, host, port, authority, file),
264 asList(url.getProtocol(), url.getHost(), url.getPort(), url.getAuthority(),
265 url.getFile()));
266 }
267
268 /**
Jesse Wilson8f99aa02011-05-20 16:30:30 -0700269 * The serialized form of a URL includes its hash code. But the hash code
270 * is not documented. Check that we don't return a deserialized hash code
271 * from a deserialized value.
272 */
273 public void testUrlSerializationWithHashCode() throws Exception {
274 String s = "aced00057372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436"
275 + "f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696"
276 + "e673b4c000466696c6571007e00014c0004686f737471007e00014c000870726f746f636f6c71007"
277 + "e00014c000372656671007e00017870cdf0efacffffffff74000e757365723a7061737340686f737"
278 + "47400102f706174682f66696c653f7175657279740004686f7374740004687474707400046861736"
279 + "878";
280 final URL url = new URL("http://user:pass@host/path/file?query#hash");
Jesse Wilsonb416ef52011-12-13 19:03:54 -0500281 new SerializationTester<URL>(url, s) {
Jesse Wilson8f99aa02011-05-20 16:30:30 -0700282 @Override protected void verify(URL deserialized) {
283 assertEquals(url.hashCode(), deserialized.hashCode());
284 }
285 }.test();
286 }
287
288 public void testOnlySupportedProtocols() {
289 try {
290 new URL("abcd://host");
291 fail();
292 } catch (MalformedURLException expected) {
293 }
294 }
295
Jesse Wilson52924102011-05-23 18:38:38 -0700296 public void testOmittedHost() throws Exception {
297 URL url = new URL("http:///path");
298 assertEquals("", url.getHost());
299 assertEquals("/path", url.getFile());
300 assertEquals("/path", url.getPath());
301 }
302
303 public void testNoHost() throws Exception {
304 URL url = new URL("http:/path");
305 assertEquals("http", url.getProtocol());
306 assertEquals(null, url.getAuthority());
307 assertEquals(null, url.getUserInfo());
308 assertEquals("", url.getHost());
309 assertEquals(-1, url.getPort());
310 assertEquals(80, url.getDefaultPort());
311 assertEquals("/path", url.getFile());
312 assertEquals("/path", url.getPath());
313 assertEquals(null, url.getQuery());
314 assertEquals(null, url.getRef());
315 }
316
317 public void testNoPath() throws Exception {
318 URL url = new URL("http://host");
319 assertEquals("host", url.getHost());
320 assertEquals("", url.getFile());
321 assertEquals("", url.getPath());
322 }
323
324 public void testEmptyHostAndNoPath() throws Exception {
325 URL url = new URL("http://");
326 assertEquals("http", url.getProtocol());
327 assertEquals("", url.getAuthority());
328 assertEquals(null, url.getUserInfo());
329 assertEquals("", url.getHost());
330 assertEquals(-1, url.getPort());
331 assertEquals(80, url.getDefaultPort());
332 assertEquals("", url.getFile());
333 assertEquals("", url.getPath());
334 assertEquals(null, url.getQuery());
335 assertEquals(null, url.getRef());
336 }
337
338 public void testNoHostAndNoPath() throws Exception {
339 URL url = new URL("http:");
340 assertEquals("http", url.getProtocol());
341 assertEquals(null, url.getAuthority());
342 assertEquals(null, url.getUserInfo());
343 assertEquals("", url.getHost());
344 assertEquals(-1, url.getPort());
345 assertEquals(80, url.getDefaultPort());
346 assertEquals("", url.getFile());
347 assertEquals("", url.getPath());
348 assertEquals(null, url.getQuery());
349 assertEquals(null, url.getRef());
350 }
351
Yi Kongeca3a932017-01-30 11:17:40 +0800352 // This behavior of URLs with invalid user info changed due to bug http://b/33351987 after
353 // Android security level 1 April 2017.
Jesse Wilson52924102011-05-23 18:38:38 -0700354 public void testAtSignInUserInfo() throws Exception {
Yi Kongeca3a932017-01-30 11:17:40 +0800355 URL url = new URL("http://user@userhost.com:password@host");
356 assertNull(url.getUserInfo());
357 assertTrue(url.getHost().isEmpty());
Jesse Wilson52924102011-05-23 18:38:38 -0700358 }
359
360 public void testUserNoPassword() throws Exception {
361 URL url = new URL("http://user@host");
362 assertEquals("user@host", url.getAuthority());
363 assertEquals("user", url.getUserInfo());
364 assertEquals("host", url.getHost());
365 }
366
367 public void testUserNoPasswordExplicitPort() throws Exception {
368 URL url = new URL("http://user@host:8080");
369 assertEquals("user@host:8080", url.getAuthority());
370 assertEquals("user", url.getUserInfo());
371 assertEquals("host", url.getHost());
372 assertEquals(8080, url.getPort());
373 }
374
375 public void testUserPasswordHostPort() throws Exception {
376 URL url = new URL("http://user:password@host:8080");
377 assertEquals("user:password@host:8080", url.getAuthority());
378 assertEquals("user:password", url.getUserInfo());
379 assertEquals("host", url.getHost());
380 assertEquals(8080, url.getPort());
381 }
382
383 public void testUserPasswordEmptyHostPort() throws Exception {
384 URL url = new URL("http://user:password@:8080");
385 assertEquals("user:password@:8080", url.getAuthority());
386 assertEquals("user:password", url.getUserInfo());
387 assertEquals("", url.getHost());
388 assertEquals(8080, url.getPort());
389 }
390
391 public void testUserPasswordEmptyHostEmptyPort() throws Exception {
392 URL url = new URL("http://user:password@");
393 assertEquals("user:password@", url.getAuthority());
394 assertEquals("user:password", url.getUserInfo());
395 assertEquals("", url.getHost());
396 assertEquals(-1, url.getPort());
397 }
398
399 public void testPathOnly() throws Exception {
400 URL url = new URL("http://host/path");
401 assertEquals("/path", url.getFile());
402 assertEquals("/path", url.getPath());
403 }
404
405 public void testQueryOnly() throws Exception {
406 URL url = new URL("http://host?query");
407 assertEquals("?query", url.getFile());
408 assertEquals("", url.getPath());
409 assertEquals("query", url.getQuery());
410 }
411
412 public void testFragmentOnly() throws Exception {
413 URL url = new URL("http://host#fragment");
414 assertEquals("", url.getFile());
415 assertEquals("", url.getPath());
416 assertEquals("fragment", url.getRef());
417 }
418
419 public void testAtSignInPath() throws Exception {
420 URL url = new URL("http://host/file@foo");
421 assertEquals("/file@foo", url.getFile());
422 assertEquals("/file@foo", url.getPath());
423 assertEquals(null, url.getUserInfo());
424 }
425
426 public void testColonInPath() throws Exception {
427 URL url = new URL("http://host/file:colon");
428 assertEquals("/file:colon", url.getFile());
429 assertEquals("/file:colon", url.getPath());
430 }
431
432 public void testSlashInQuery() throws Exception {
433 URL url = new URL("http://host/file?query/path");
434 assertEquals("/file?query/path", url.getFile());
435 assertEquals("/file", url.getPath());
436 assertEquals("query/path", url.getQuery());
437 }
438
439 public void testQuestionMarkInQuery() throws Exception {
440 URL url = new URL("http://host/file?query?another");
441 assertEquals("/file?query?another", url.getFile());
442 assertEquals("/file", url.getPath());
443 assertEquals("query?another", url.getQuery());
444 }
445
446 public void testAtSignInQuery() throws Exception {
447 URL url = new URL("http://host/file?query@at");
448 assertEquals("/file?query@at", url.getFile());
449 assertEquals("/file", url.getPath());
450 assertEquals("query@at", url.getQuery());
451 }
452
Tobias Thierer7dbee732018-02-08 21:45:09 +0000453 public void testCommonProtocolsAreHandledByBuiltinHandlers() throws Exception {
454 Method getURLStreamHandler = URL.class.getDeclaredMethod(
455 "getURLStreamHandler", String.class);
456 getURLStreamHandler.setAccessible(true);
457 Set<String> builtinHandlers =
458 (Set<String>) getUrlField("BUILTIN_HANDLER_CLASS_NAMES").get(null);
459 Set<String> commonHandlers = new HashSet<>();
460 for (String protocol : Arrays.asList("file", "ftp", "jar", "http", "https")) {
461 URLStreamHandler handler =
462 (URLStreamHandler) getURLStreamHandler.invoke(null, protocol);
463 assertNotNull("Handler for protocol " + protocol + " should exist", handler);
464 commonHandlers.add(handler.getClass().getName());
465 }
466 assertTrue("Built-in handlers " + builtinHandlers + " should contain all of the handlers "
467 + commonHandlers + " for common protocols.",
468 builtinHandlers.containsAll(commonHandlers));
469 }
470
Jesse Wilson52924102011-05-23 18:38:38 -0700471 public void testColonInQuery() throws Exception {
472 URL url = new URL("http://host/file?query:colon");
473 assertEquals("/file?query:colon", url.getFile());
474 assertEquals("/file", url.getPath());
475 assertEquals("query:colon", url.getQuery());
476 }
477
478 public void testQuestionMarkInFragment() throws Exception {
479 URL url = new URL("http://host/file#fragment?query");
480 assertEquals("/file", url.getFile());
481 assertEquals("/file", url.getPath());
482 assertEquals(null, url.getQuery());
483 assertEquals("fragment?query", url.getRef());
484 }
485
486 public void testColonInFragment() throws Exception {
487 URL url = new URL("http://host/file#fragment:80");
488 assertEquals("/file", url.getFile());
489 assertEquals("/file", url.getPath());
490 assertEquals(-1, url.getPort());
491 assertEquals("fragment:80", url.getRef());
492 }
493
494 public void testSlashInFragment() throws Exception {
495 URL url = new URL("http://host/file#fragment/path");
496 assertEquals("/file", url.getFile());
497 assertEquals("/file", url.getPath());
498 assertEquals("fragment/path", url.getRef());
499 }
500
Jesse Wilsonc68609e2011-05-26 19:33:57 -0700501 public void testSlashInFragmentCombiningConstructor() throws Exception {
502 URL url = new URL("http", "host", "/file#fragment/path");
503 assertEquals("/file", url.getFile());
504 assertEquals("/file", url.getPath());
505 assertEquals("fragment/path", url.getRef());
506 }
507
Jesse Wilson52924102011-05-23 18:38:38 -0700508 public void testHashInFragment() throws Exception {
509 URL url = new URL("http://host/file#fragment#another");
510 assertEquals("/file", url.getFile());
511 assertEquals("/file", url.getPath());
512 assertEquals("fragment#another", url.getRef());
513 }
514
515 public void testEmptyPort() throws Exception {
516 URL url = new URL("http://host:/");
517 assertEquals(-1, url.getPort());
518 }
519
520 public void testNonNumericPort() throws Exception {
521 try {
522 new URL("http://host:x/");
523 fail();
524 } catch (MalformedURLException expected) {
525 }
526 }
527
Calin Juravlebb3195f2014-04-10 16:50:32 +0100528 public void testPortWithMinusSign() throws Exception {
Jesse Wilson52924102011-05-23 18:38:38 -0700529 try {
530 new URL("http://host:-2/");
531 fail();
532 } catch (MalformedURLException expected) {
533 }
534 }
535
Calin Juravlebb3195f2014-04-10 16:50:32 +0100536 public void testPortWithPlusSign() throws Exception {
537 try {
538 new URL("http://host:+2/");
539 fail();
540 } catch (MalformedURLException expected) {
541 }
542 }
543
544 public void testPortNonASCII() throws Exception {
545 try {
546 new URL("http://host:١٢٣/"); // 123 in arabic
547 fail();
548 } catch (MalformedURLException expected) {
549 }
550 }
551
Jesse Wilson52924102011-05-23 18:38:38 -0700552 public void testNegativePortEqualsPlaceholder() throws Exception {
553 try {
554 new URL("http://host:-1/");
555 fail(); // RI fails this
556 } catch (MalformedURLException expected) {
557 }
558 }
559
560 public void testRelativePathOnQuery() throws Exception {
561 URL base = new URL("http://host/file?query/x");
562 URL url = new URL(base, "another");
563 assertEquals("http://host/another", url.toString());
564 assertEquals("/another", url.getFile());
565 assertEquals("/another", url.getPath());
566 assertEquals(null, url.getQuery());
567 assertEquals(null, url.getRef());
568 }
569
570 public void testRelativeFragmentOnQuery() throws Exception {
571 URL base = new URL("http://host/file?query/x#fragment");
572 URL url = new URL(base, "#another");
573 assertEquals("http://host/file?query/x#another", url.toString());
574 assertEquals("/file?query/x", url.getFile());
575 assertEquals("/file", url.getPath());
576 assertEquals("query/x", url.getQuery());
577 assertEquals("another", url.getRef());
578 }
579
580 public void testPathContainsRelativeParts() throws Exception {
581 URL url = new URL("http://host/a/b/../c");
582 assertEquals("http://host/a/c", url.toString()); // RI doesn't canonicalize
583 }
584
Pete Bentleyc1295562018-07-09 11:42:50 +0100585 public void testPathContainsBackslash() throws Exception {
586 URL url = new URL("http://host\\path@foo");
587 assertEquals("\\path@foo", url.getPath());
588 assertEquals("host", url.getHost());
589 }
590
591 public void testQueryContainsForwardSlash() throws Exception {
592 URL url = new URL("http://host?query/foo");
593 assertEquals("", url.getPath());
594 assertEquals("host", url.getHost());
595 assertEquals("query/foo", url.getQuery());
596 }
597
598 public void testFragmentContainsForwardSlash() throws Exception {
599 URL url = new URL("http://host#fragment/foo");
600 assertEquals("", url.getPath());
601 assertEquals("host", url.getHost());
602 assertEquals("fragment/foo", url.getRef());
603 }
604
Jesse Wilson52924102011-05-23 18:38:38 -0700605 public void testRelativePathAndFragment() throws Exception {
606 URL base = new URL("http://host/file");
607 assertEquals("http://host/another#fragment", new URL(base, "another#fragment").toString());
608 }
609
610 public void testRelativeParentDirectory() throws Exception {
611 URL base = new URL("http://host/a/b/c");
612 assertEquals("http://host/a/d", new URL(base, "../d").toString());
613 }
614
615 public void testRelativeChildDirectory() throws Exception {
616 URL base = new URL("http://host/a/b/c");
617 assertEquals("http://host/a/b/d/e", new URL(base, "d/e").toString());
618 }
619
620 public void testRelativeRootDirectory() throws Exception {
621 URL base = new URL("http://host/a/b/c");
622 assertEquals("http://host/d", new URL(base, "/d").toString());
623 }
624
625 public void testRelativeFullUrl() throws Exception {
626 URL base = new URL("http://host/a/b/c");
627 assertEquals("http://host2/d/e", new URL(base, "http://host2/d/e").toString());
628 assertEquals("https://host2/d/e", new URL(base, "https://host2/d/e").toString());
629 }
630
631 public void testRelativeDifferentScheme() throws Exception {
632 URL base = new URL("http://host/a/b/c");
633 assertEquals("https://host2/d/e", new URL(base, "https://host2/d/e").toString());
634 }
635
636 public void testRelativeDifferentAuthority() throws Exception {
637 URL base = new URL("http://host/a/b/c");
638 assertEquals("http://another/d/e", new URL(base, "//another/d/e").toString());
639 }
640
641 public void testRelativeWithScheme() throws Exception {
642 URL base = new URL("http://host/a/b/c");
643 assertEquals("http://host/a/b/c", new URL(base, "http:").toString());
644 assertEquals("http://host/", new URL(base, "http:/").toString());
645 }
646
647 public void testMalformedUrlsRefusedByFirefoxAndChrome() throws Exception {
648 URL base = new URL("http://host/a/b/c");
Jesse Wilsonc68609e2011-05-26 19:33:57 -0700649 assertEquals("http://", new URL(base, "http://").toString()); // fails on RI; path retained
Jesse Wilson52924102011-05-23 18:38:38 -0700650 assertEquals("http://", new URL(base, "//").toString()); // fails on RI
651 assertEquals("https:", new URL(base, "https:").toString());
652 assertEquals("https:/", new URL(base, "https:/").toString());
653 assertEquals("https://", new URL(base, "https://").toString());
654 }
655
656 public void testRfc1808NormalExamples() throws Exception {
657 URL base = new URL("http://a/b/c/d;p?q");
658 assertEquals("https:h", new URL(base, "https:h").toString());
659 assertEquals("http://a/b/c/g", new URL(base, "g").toString());
660 assertEquals("http://a/b/c/g", new URL(base, "./g").toString());
661 assertEquals("http://a/b/c/g/", new URL(base, "g/").toString());
662 assertEquals("http://a/g", new URL(base, "/g").toString());
663 assertEquals("http://g", new URL(base, "//g").toString());
Jesse Wilsonc68609e2011-05-26 19:33:57 -0700664 assertEquals("http://a/b/c/d;p?y", new URL(base, "?y").toString()); // RI fails; file lost
Jesse Wilson52924102011-05-23 18:38:38 -0700665 assertEquals("http://a/b/c/g?y", new URL(base, "g?y").toString());
666 assertEquals("http://a/b/c/d;p?q#s", new URL(base, "#s").toString());
667 assertEquals("http://a/b/c/g#s", new URL(base, "g#s").toString());
668 assertEquals("http://a/b/c/g?y#s", new URL(base, "g?y#s").toString());
669 assertEquals("http://a/b/c/;x", new URL(base, ";x").toString());
670 assertEquals("http://a/b/c/g;x", new URL(base, "g;x").toString());
671 assertEquals("http://a/b/c/g;x?y#s", new URL(base, "g;x?y#s").toString());
672 assertEquals("http://a/b/c/d;p?q", new URL(base, "").toString());
673 assertEquals("http://a/b/c/", new URL(base, ".").toString());
674 assertEquals("http://a/b/c/", new URL(base, "./").toString());
675 assertEquals("http://a/b/", new URL(base, "..").toString());
676 assertEquals("http://a/b/", new URL(base, "../").toString());
677 assertEquals("http://a/b/g", new URL(base, "../g").toString());
678 assertEquals("http://a/", new URL(base, "../..").toString());
679 assertEquals("http://a/", new URL(base, "../../").toString());
680 assertEquals("http://a/g", new URL(base, "../../g").toString());
681 }
682
683 public void testRfc1808AbnormalExampleTooManyDotDotSequences() throws Exception {
684 URL base = new URL("http://a/b/c/d;p?q");
Jesse Wilson10527ac2011-05-25 14:50:18 -0700685 assertEquals("http://a/g", new URL(base, "../../../g").toString()); // RI doesn't normalize
686 assertEquals("http://a/g", new URL(base, "../../../../g").toString());
Jesse Wilson52924102011-05-23 18:38:38 -0700687 }
688
689 public void testRfc1808AbnormalExampleRemoveDotSegments() throws Exception {
690 URL base = new URL("http://a/b/c/d;p?q");
Jesse Wilson10527ac2011-05-25 14:50:18 -0700691 assertEquals("http://a/g", new URL(base, "/./g").toString()); // RI doesn't normalize
692 assertEquals("http://a/g", new URL(base, "/../g").toString()); // RI doesn't normalize
Jesse Wilson52924102011-05-23 18:38:38 -0700693 assertEquals("http://a/b/c/g.", new URL(base, "g.").toString());
694 assertEquals("http://a/b/c/.g", new URL(base, ".g").toString());
695 assertEquals("http://a/b/c/g..", new URL(base, "g..").toString());
696 assertEquals("http://a/b/c/..g", new URL(base, "..g").toString());
697 }
698
699 public void testRfc1808AbnormalExampleNonsensicalDots() throws Exception {
700 URL base = new URL("http://a/b/c/d;p?q");
701 assertEquals("http://a/b/g", new URL(base, "./../g").toString());
702 assertEquals("http://a/b/c/g/", new URL(base, "./g/.").toString());
703 assertEquals("http://a/b/c/g/h", new URL(base, "g/./h").toString());
704 assertEquals("http://a/b/c/h", new URL(base, "g/../h").toString());
705 assertEquals("http://a/b/c/g;x=1/y", new URL(base, "g;x=1/./y").toString());
706 assertEquals("http://a/b/c/y", new URL(base, "g;x=1/../y").toString());
707 }
708
709 public void testRfc1808AbnormalExampleRelativeScheme() throws Exception {
710 URL base = new URL("http://a/b/c/d;p?q");
711 // this result is permitted; strict parsers prefer "http:g"
712 assertEquals("http://a/b/c/g", new URL(base, "http:g").toString());
713 }
714
715 public void testRfc1808AbnormalExampleQueryOrFragmentDots() throws Exception {
716 URL base = new URL("http://a/b/c/d;p?q");
717 assertEquals("http://a/b/c/g?y/./x", new URL(base, "g?y/./x").toString());
718 assertEquals("http://a/b/c/g?y/../x", new URL(base, "g?y/../x").toString());
719 assertEquals("http://a/b/c/g#s/./x", new URL(base, "g#s/./x").toString());
720 assertEquals("http://a/b/c/g#s/../x", new URL(base, "g#s/../x").toString());
721 }
722
723 public void testSquareBracketsInUserInfo() throws Exception {
724 URL url = new URL("http://user:[::1]@host");
725 assertEquals("user:[::1]", url.getUserInfo());
726 assertEquals("host", url.getHost());
727 }
728
729 public void testComposeUrl() throws Exception {
730 URL url = new URL("http", "host", "a");
731 assertEquals("http", url.getProtocol());
732 assertEquals("host", url.getAuthority());
733 assertEquals("host", url.getHost());
Jesse Wilsonc68609e2011-05-26 19:33:57 -0700734 assertEquals("/a", url.getFile()); // RI fails; doesn't insert '/' separator
Jesse Wilson52924102011-05-23 18:38:38 -0700735 assertEquals("http://host/a", url.toString()); // fails on RI
736 }
737
738 public void testComposeUrlWithNullHost() throws Exception {
739 URL url = new URL("http", null, "a");
740 assertEquals("http", url.getProtocol());
741 assertEquals(null, url.getAuthority());
742 assertEquals(null, url.getHost());
743 assertEquals("a", url.getFile());
744 assertEquals("http:a", url.toString()); // fails on RI
745 }
746
747 public void testFileUrlExtraLeadingSlashes() throws Exception {
748 URL url = new URL("file:////foo");
Jesse Wilson10527ac2011-05-25 14:50:18 -0700749 assertEquals("", url.getAuthority()); // RI returns null
Jesse Wilson52924102011-05-23 18:38:38 -0700750 assertEquals("//foo", url.getPath());
751 assertEquals("file:////foo", url.toString());
752 }
753
754 public void testFileUrlWithAuthority() throws Exception {
755 URL url = new URL("file://x/foo");
756 assertEquals("x", url.getAuthority());
757 assertEquals("/foo", url.getPath());
758 assertEquals("file://x/foo", url.toString());
759 }
760
761 /**
762 * The RI is not self-consistent on missing authorities, returning either
763 * null or the empty string depending on the number of slashes in the path.
764 * We always treat '//' as the beginning of an authority.
765 */
766 public void testEmptyAuthority() throws Exception {
767 URL url = new URL("http:///foo");
768 assertEquals("", url.getAuthority());
769 assertEquals("/foo", url.getPath());
Jesse Wilson10527ac2011-05-25 14:50:18 -0700770 assertEquals("http:///foo", url.toString()); // RI drops '//'
Jesse Wilson52924102011-05-23 18:38:38 -0700771 }
772
773 public void testHttpUrlExtraLeadingSlashes() throws Exception {
774 URL url = new URL("http:////foo");
Jesse Wilson10527ac2011-05-25 14:50:18 -0700775 assertEquals("", url.getAuthority()); // RI returns null
Jesse Wilson52924102011-05-23 18:38:38 -0700776 assertEquals("//foo", url.getPath());
777 assertEquals("http:////foo", url.toString());
778 }
779
780 public void testFileUrlRelativePath() throws Exception {
781 URL base = new URL("file:a/b/c");
782 assertEquals("file:a/b/d", new URL(base, "d").toString());
783 }
784
785 public void testFileUrlDottedPath() throws Exception {
786 URL url = new URL("file:../a/b");
787 assertEquals("../a/b", url.getPath());
788 assertEquals("file:../a/b", url.toString());
789 }
Jesse Wilson10527ac2011-05-25 14:50:18 -0700790
791 public void testParsingDotAsHostname() throws Exception {
792 URL url = new URL("http://./");
793 assertEquals(".", url.getAuthority());
794 assertEquals(".", url.getHost());
795 }
796
797 public void testSquareBracketsWithIPv4() throws Exception {
798 try {
799 new URL("http://[192.168.0.1]/");
800 fail();
801 } catch (MalformedURLException expected) {
802 }
Jesse Wilson98c564c2011-07-24 16:39:27 -0700803 URL url = new URL("http", "[192.168.0.1]", "/");
804 assertEquals("[192.168.0.1]", url.getHost());
Jesse Wilson10527ac2011-05-25 14:50:18 -0700805 }
806
807 public void testSquareBracketsWithHostname() throws Exception {
808 try {
809 new URL("http://[www.android.com]/");
810 fail();
811 } catch (MalformedURLException expected) {
812 }
Jesse Wilson98c564c2011-07-24 16:39:27 -0700813 URL url = new URL("http", "[www.android.com]", "/");
814 assertEquals("[www.android.com]", url.getHost());
Jesse Wilson10527ac2011-05-25 14:50:18 -0700815 }
816
817 public void testIPv6WithoutSquareBrackets() throws Exception {
818 try {
819 new URL("http://fe80::1234/");
820 fail();
821 } catch (MalformedURLException expected) {
822 }
Jesse Wilson98c564c2011-07-24 16:39:27 -0700823 URL url = new URL("http", "fe80::1234", "/");
824 assertEquals("[fe80::1234]", url.getHost());
825 }
826
827 public void testIpv6WithSquareBrackets() throws Exception {
828 URL url = new URL("http://[::1]:2/");
829 assertEquals("[::1]", url.getHost());
830 assertEquals(2, url.getPort());
Jesse Wilson10527ac2011-05-25 14:50:18 -0700831 }
832
833 public void testEqualityWithNoPath() throws Exception {
834 assertFalse(new URL("http://android.com").equals(new URL("http://android.com/")));
835 }
836
Jesse Wilsonc68609e2011-05-26 19:33:57 -0700837 public void testUrlDoesNotEncodeParts() throws Exception {
838 URL url = new URL("http", "host", 80, "/doc|search?q=green robots#over 6\"");
839 assertEquals("http", url.getProtocol());
840 assertEquals("host:80", url.getAuthority());
841 assertEquals("/doc|search", url.getPath());
842 assertEquals("q=green robots", url.getQuery());
843 assertEquals("over 6\"", url.getRef());
844 assertEquals("http://host:80/doc|search?q=green robots#over 6\"", url.toString());
845 }
846
847 public void testSchemeCaseIsCanonicalized() throws Exception {
848 URL url = new URL("HTTP://host/path");
849 assertEquals("http", url.getProtocol());
850 }
851
852 public void testEmptyAuthorityWithPath() throws Exception {
853 URL url = new URL("http:///path");
854 assertEquals("", url.getAuthority());
855 assertEquals("/path", url.getPath());
856 }
857
858 public void testEmptyAuthorityWithQuery() throws Exception {
859 URL url = new URL("http://?query");
860 assertEquals("", url.getAuthority());
861 assertEquals("", url.getPath());
862 assertEquals("query", url.getQuery());
863 }
864
865 public void testEmptyAuthorityWithFragment() throws Exception {
866 URL url = new URL("http://#fragment");
867 assertEquals("", url.getAuthority());
868 assertEquals("", url.getPath());
869 assertEquals("fragment", url.getRef());
870 }
871
872 public void testCombiningConstructorsMakeRelativePathsAbsolute() throws Exception {
873 assertEquals("/relative", new URL("http", "host", "relative").getPath());
874 assertEquals("/relative", new URL("http", "host", -1, "relative").getPath());
875 assertEquals("/relative", new URL("http", "host", -1, "relative", null).getPath());
876 }
877
878 public void testCombiningConstructorsDoNotMakeEmptyPathsAbsolute() throws Exception {
879 assertEquals("", new URL("http", "host", "").getPath());
880 assertEquals("", new URL("http", "host", -1, "").getPath());
881 assertEquals("", new URL("http", "host", -1, "", null).getPath());
882 }
883
Jesse Wilsond0d62662011-11-10 11:55:55 -0500884 public void testPartContainsSpace() throws Exception {
885 try {
886 new URL("ht tp://host/");
887 fail();
888 } catch (MalformedURLException expected) {
889 }
890 assertEquals("user name", new URL("http://user name@host/").getUserInfo());
891 assertEquals("ho st", new URL("http://ho st/").getHost());
892 try {
893 new URL("http://host:80 80/");
894 fail();
895 } catch (MalformedURLException expected) {
896 }
897 assertEquals("/fi le", new URL("http://host/fi le").getFile());
898 assertEquals("que ry", new URL("http://host/file?que ry").getQuery());
899 assertEquals("re f", new URL("http://host/file?query#re f").getRef());
900 }
901
Jesse Wilsondc24b1b2012-09-21 14:58:29 -0400902 // http://code.google.com/p/android/issues/detail?id=37577
903 public void testUnderscore() throws Exception {
904 URL url = new URL("http://a_b.c.d.net/");
905 assertEquals("a_b.c.d.net", url.getAuthority());
906 // The RFC's don't permit underscores in hostnames, but URL accepts them (unlike URI).
907 assertEquals("a_b.c.d.net", url.getHost());
908 }
909
Narayan Kamathb93dbae2016-02-01 15:54:33 +0000910 // http://b/26895969
911 // http://b/26798800
912 public void testHashCodeAndEqualsDoesNotPerformNetworkIo() throws Exception {
913 final BlockGuard.Policy oldPolicy = BlockGuard.getThreadPolicy();
914 BlockGuard.setThreadPolicy(new BlockGuard.Policy() {
915 @Override
916 public void onWriteToDisk() {
917 fail("Blockguard.Policy.onWriteToDisk");
918 }
919
920 @Override
921 public void onReadFromDisk() {
922 fail("Blockguard.Policy.onReadFromDisk");
923 }
924
925 @Override
926 public void onNetwork() {
927 fail("Blockguard.Policy.onNetwork");
928 }
929
930 @Override
Shubham Ajmera7b05c362016-06-09 18:58:20 +0100931 public void onUnbufferedIO() {
932 fail("Blockguard.Policy.onUnbufferedIO");
933 }
934
935 @Override
Narayan Kamathb93dbae2016-02-01 15:54:33 +0000936 public int getPolicyMask() {
937 return 0;
938 }
939 });
940
941 try {
942 URL url = new URL("http://www.google.com/");
943 URL url2 = new URL("http://www.nest.com/");
944
945 url.equals(url2);
946 url2.hashCode();
947 } finally {
948 BlockGuard.setThreadPolicy(oldPolicy);
949 }
950 }
Przemyslaw Szczepaniake56459a2016-04-04 15:02:56 +0100951
952 // http://27444667
953 public void testEmptyQueryAndAnchor() throws Exception {
954 assertEquals("/some/path", new URL("http://foobar.com/some/path?").getFile());
955 assertEquals("/some/path", new URL("http://foobar.com/some/path#").getFile());
956 assertEquals("/some/path", new URL("http://foobar.com/some/path?#").getFile());
957 }
Yi Kong78a43442016-10-19 15:46:47 +0100958
959 // http://b/31858037
960 public void testFragmentWithSlash() throws Exception {
961 final String host = "example.com";
962 final String fragment = "@not-a-host-name/a";
963 URL url = new URL(String.format("http://%s#%s", host, fragment));
964 assertNull(url.getUserInfo());
965 assertEquals(host, url.getAuthority());
966 assertEquals(host, url.getHost());
967 assertEquals(fragment, url.getRef());
968 }
969
970 // http://b/31858037
971 public void testFragmentWithQuery() throws Exception {
972 final String host = "example.com";
973 final String fragment = "@not-a-host-name?a";
974 URL url = new URL(String.format("http://%s#%s", host, fragment));
975 assertNull(url.getUserInfo());
976 assertEquals(host, url.getAuthority());
977 assertEquals(host, url.getHost());
978 assertEquals(fragment, url.getRef());
979 }
Yi Kong2e3689a2017-01-19 11:28:29 +0100980
981 // http://b/33351987
982 public void testMultipleUserField() throws Exception {
983 final String host = "http://multiple@users@url.com";
984 URL url = new URL(host);
985 assertNull(url.getUserInfo());
Yi Kongeca3a932017-01-30 11:17:40 +0800986 assertTrue(url.getHost().isEmpty());
Yi Kong2e3689a2017-01-19 11:28:29 +0100987 }
Elliott Hughes6470a302010-11-29 18:17:06 -0800988}