1/* 2 * Copyright (C) 2007 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 com.android.unit_tests; 18 19import android.net.Uri; 20import android.content.ContentUris; 21import android.os.Parcel; 22import android.test.suitebuilder.annotation.SmallTest; 23import junit.framework.TestCase; 24 25import java.io.File; 26import java.util.Arrays; 27 28public class UriTest extends TestCase { 29 30 @SmallTest 31 public void testToStringWithPathOnly() { 32 Uri.Builder builder = new Uri.Builder(); 33 34 // Not a valid path, but this came from a user's test case. 35 builder.path("//foo"); 36 Uri uri = builder.build(); 37 assertEquals("//foo", uri.toString()); 38 } 39 40 @SmallTest 41 public void testParcelling() { 42 parcelAndUnparcel(Uri.parse("foo:bob%20lee")); 43 parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment")); 44 parcelAndUnparcel(new Uri.Builder() 45 .scheme("http") 46 .authority("crazybob.org") 47 .path("/rss/") 48 .encodedQuery("a=b") 49 .fragment("foo") 50 .build()); 51 } 52 53 private void parcelAndUnparcel(Uri u) { 54 Parcel p = Parcel.obtain(); 55 Uri.writeToParcel(p, u); 56 p.setDataPosition(0); 57 assertEquals(u, Uri.CREATOR.createFromParcel(p)); 58 59 p.setDataPosition(0); 60 u = u.buildUpon().build(); 61 Uri.writeToParcel(p, u); 62 p.setDataPosition(0); 63 assertEquals(u, Uri.CREATOR.createFromParcel(p)); 64 } 65 66 @SmallTest 67 public void testBuildUponOpaqueStringUri() { 68 Uri u = Uri.parse("bob:lee").buildUpon().scheme("robert").build(); 69 assertEquals("robert", u.getScheme()); 70 assertEquals("lee", u.getEncodedSchemeSpecificPart()); 71 assertEquals("lee", u.getSchemeSpecificPart()); 72 assertNull(u.getQuery()); 73 assertNull(u.getPath()); 74 assertNull(u.getAuthority()); 75 assertNull(u.getHost()); 76 } 77 78 @SmallTest 79 public void testStringUri() { 80 assertEquals("bob lee", 81 Uri.parse("foo:bob%20lee").getSchemeSpecificPart()); 82 assertEquals("bob%20lee", 83 Uri.parse("foo:bob%20lee").getEncodedSchemeSpecificPart()); 84 assertEquals("/bob%20lee", 85 Uri.parse("foo:/bob%20lee").getEncodedPath()); 86 assertNull(Uri.parse("foo:bob%20lee").getPath()); 87 assertEquals("bob%20lee", 88 Uri.parse("foo:?bob%20lee").getEncodedQuery()); 89 assertNull(Uri.parse("foo:bar#?bob%20lee").getQuery()); 90 assertEquals("bob%20lee", 91 Uri.parse("foo:#bob%20lee").getEncodedFragment()); 92 } 93 94 @SmallTest 95 public void testStringUriIsHierarchical() { 96 assertTrue(Uri.parse("bob").isHierarchical()); 97 assertFalse(Uri.parse("bob:").isHierarchical()); 98 } 99 100 @SmallTest 101 public void testNullUriString() { 102 try { 103 Uri.parse(null); 104 fail(); 105 } catch (NullPointerException e) {} 106 } 107 108 @SmallTest 109 public void testNullFile() { 110 try { 111 Uri.fromFile(null); 112 fail(); 113 } catch (NullPointerException e) {} 114 } 115 116 @SmallTest 117 public void testCompareTo() { 118 Uri a = Uri.parse("foo:a"); 119 Uri b = Uri.parse("foo:b"); 120 Uri b2 = Uri.parse("foo:b"); 121 122 assertTrue(a.compareTo(b) < 0); 123 assertTrue(b.compareTo(a) > 0); 124 assertEquals(0, b.compareTo(b2)); 125 } 126 127 @SmallTest 128 public void testEqualsAndHashCode() { 129 130 Uri a = Uri.parse("http://crazybob.org/test/?foo=bar#tee"); 131 132 Uri b = new Uri.Builder() 133 .scheme("http") 134 .authority("crazybob.org") 135 .path("/test/") 136 .encodedQuery("foo=bar") 137 .fragment("tee") 138 .build(); 139 140 // Try alternate builder methods. 141 Uri c = new Uri.Builder() 142 .scheme("http") 143 .encodedAuthority("crazybob.org") 144 .encodedPath("/test/") 145 .encodedQuery("foo=bar") 146 .encodedFragment("tee") 147 .build(); 148 149 assertFalse(Uri.EMPTY.equals(null)); 150 151 assertEquals(a, b); 152 assertEquals(b, c); 153 assertEquals(c, a); 154 155 assertEquals(a.hashCode(), b.hashCode()); 156 assertEquals(b.hashCode(), c.hashCode()); 157 } 158 159 @SmallTest 160 public void testAuthorityParsing() { 161 Uri uri = Uri.parse("http://localhost:42"); 162 assertEquals("localhost", uri.getHost()); 163 assertEquals(42, uri.getPort()); 164 165 uri = Uri.parse("http://bob@localhost:42"); 166 assertEquals("bob", uri.getUserInfo()); 167 assertEquals("localhost", uri.getHost()); 168 assertEquals(42, uri.getPort()); 169 170 uri = Uri.parse("http://bob%20lee@localhost:42"); 171 assertEquals("bob lee", uri.getUserInfo()); 172 assertEquals("bob%20lee", uri.getEncodedUserInfo()); 173 174 uri = Uri.parse("http://localhost"); 175 assertEquals("localhost", uri.getHost()); 176 assertEquals(-1, uri.getPort()); 177 } 178 179 @SmallTest 180 public void testBuildUponOpaqueUri() { 181 Uri a = Uri.fromParts("foo", "bar", "tee"); 182 Uri b = a.buildUpon().fragment("new").build(); 183 assertEquals("new", b.getFragment()); 184 assertEquals("bar", b.getSchemeSpecificPart()); 185 assertEquals("foo", b.getScheme()); 186 } 187 188 @SmallTest 189 public void testBuildUponEncodedOpaqueUri() { 190 Uri a = new Uri.Builder() 191 .scheme("foo") 192 .encodedOpaquePart("bar") 193 .fragment("tee") 194 .build(); 195 Uri b = a.buildUpon().fragment("new").build(); 196 assertEquals("new", b.getFragment()); 197 assertEquals("bar", b.getSchemeSpecificPart()); 198 assertEquals("foo", b.getScheme()); 199 } 200 201 @SmallTest 202 public void testPathSegmentDecoding() { 203 Uri uri = Uri.parse("foo://bar/a%20a/b%20b"); 204 assertEquals("a a", uri.getPathSegments().get(0)); 205 assertEquals("b b", uri.getPathSegments().get(1)); 206 } 207 208 @SmallTest 209 public void testSms() { 210 Uri base = Uri.parse("content://sms"); 211 Uri appended = base.buildUpon() 212 .appendEncodedPath("conversations/addr=555-1212") 213 .build(); 214 assertEquals("content://sms/conversations/addr=555-1212", 215 appended.toString()); 216 assertEquals(2, appended.getPathSegments().size()); 217 assertEquals("conversations", appended.getPathSegments().get(0)); 218 assertEquals("addr=555-1212", appended.getPathSegments().get(1)); 219 } 220 221 @SmallTest 222 public void testEncodeWithAllowedChars() { 223 String encoded = Uri.encode("Bob:/", "/"); 224 assertEquals(-1, encoded.indexOf(':')); 225 assertTrue(encoded.indexOf('/') > -1); 226 } 227 228 @SmallTest 229 public void testEncodeDecode() { 230 code(null); 231 code(""); 232 code("Bob"); 233 code(":Bob"); 234 code("::Bob"); 235 code("Bob::Lee"); 236 code("Bob:Lee"); 237 code("Bob::"); 238 code("Bob:"); 239 code("::Bob::"); 240 } 241 242 private void code(String s) { 243 assertEquals(s, Uri.decode(Uri.encode(s, null))); 244 } 245 246 @SmallTest 247 public void testFile() { 248 File f = new File("/tmp/bob"); 249 250 Uri uri = Uri.fromFile(f); 251 252 assertEquals("file:///tmp/bob", uri.toString()); 253 } 254 255 @SmallTest 256 public void testQueryParameters() { 257 Uri uri = Uri.parse("content://user"); 258 259 assertEquals(null, uri.getQueryParameter("a")); 260 261 uri = uri.buildUpon().appendQueryParameter("a", "b").build(); 262 263 assertEquals("b", uri.getQueryParameter("a")); 264 265 uri = uri.buildUpon().appendQueryParameter("a", "b2").build(); 266 267 assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); 268 269 uri = uri.buildUpon().appendQueryParameter("c", "d").build(); 270 271 assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); 272 assertEquals("d", uri.getQueryParameter("c")); 273 } 274 275 @SmallTest 276 public void testSchemeOnly() { 277 Uri uri = Uri.parse("empty:"); 278 assertEquals("empty", uri.getScheme()); 279 assertTrue(uri.isAbsolute()); 280 assertNull(uri.getPath()); 281 } 282 283 @SmallTest 284 public void testEmptyPath() { 285 Uri uri = Uri.parse("content://user"); 286 assertEquals(0, uri.getPathSegments().size()); 287 } 288 289 @SmallTest 290 public void testPathOperations() { 291 Uri uri = Uri.parse("content://user/a/b"); 292 293 assertEquals(2, uri.getPathSegments().size()); 294 assertEquals("b", uri.getLastPathSegment()); 295 296 Uri first = uri; 297 uri = uri.buildUpon().appendPath("c").build(); 298 299 assertEquals(3, uri.getPathSegments().size()); 300 assertEquals("c", uri.getLastPathSegment()); 301 assertEquals("content://user/a/b/c", uri.toString()); 302 303 uri = ContentUris.withAppendedId(uri, 100); 304 305 assertEquals(4, uri.getPathSegments().size()); 306 assertEquals("100", uri.getLastPathSegment()); 307 assertEquals(100, ContentUris.parseId(uri)); 308 assertEquals("content://user/a/b/c/100", uri.toString()); 309 310 // Make sure the original URI is still intact. 311 assertEquals(2, first.getPathSegments().size()); 312 assertEquals("b", first.getLastPathSegment()); 313 314 try { 315 first.getPathSegments().get(2); 316 fail(); 317 } catch (IndexOutOfBoundsException e) {} 318 319 assertEquals(null, Uri.EMPTY.getLastPathSegment()); 320 321 Uri withC = Uri.parse("foo:/a/b/").buildUpon().appendPath("c").build(); 322 assertEquals("/a/b/c", withC.getPath()); 323 } 324 325 @SmallTest 326 public void testOpaqueUri() { 327 Uri uri = Uri.parse("mailto:nobody"); 328 testOpaqueUri(uri); 329 330 uri = uri.buildUpon().build(); 331 testOpaqueUri(uri); 332 333 uri = Uri.fromParts("mailto", "nobody", null); 334 testOpaqueUri(uri); 335 336 uri = uri.buildUpon().build(); 337 testOpaqueUri(uri); 338 339 uri = new Uri.Builder() 340 .scheme("mailto") 341 .opaquePart("nobody") 342 .build(); 343 testOpaqueUri(uri); 344 345 uri = uri.buildUpon().build(); 346 testOpaqueUri(uri); 347 } 348 349 private void testOpaqueUri(Uri uri) { 350 assertEquals("mailto", uri.getScheme()); 351 assertEquals("nobody", uri.getSchemeSpecificPart()); 352 assertEquals("nobody", uri.getEncodedSchemeSpecificPart()); 353 354 assertNull(uri.getFragment()); 355 assertTrue(uri.isAbsolute()); 356 assertTrue(uri.isOpaque()); 357 assertFalse(uri.isRelative()); 358 assertFalse(uri.isHierarchical()); 359 360 assertNull(uri.getAuthority()); 361 assertNull(uri.getEncodedAuthority()); 362 assertNull(uri.getPath()); 363 assertNull(uri.getEncodedPath()); 364 assertNull(uri.getUserInfo()); 365 assertNull(uri.getEncodedUserInfo()); 366 assertNull(uri.getQuery()); 367 assertNull(uri.getEncodedQuery()); 368 assertNull(uri.getHost()); 369 assertEquals(-1, uri.getPort()); 370 371 assertTrue(uri.getPathSegments().isEmpty()); 372 assertNull(uri.getLastPathSegment()); 373 374 assertEquals("mailto:nobody", uri.toString()); 375 376 Uri withFragment = uri.buildUpon().fragment("top").build(); 377 assertEquals("mailto:nobody#top", withFragment.toString()); 378 } 379 380 @SmallTest 381 public void testHierarchicalUris() { 382 testHierarchical("http", "google.com", "/p1/p2", "query", "fragment"); 383 testHierarchical("file", null, "/p1/p2", null, null); 384 testHierarchical("content", "contact", "/p1/p2", null, null); 385 testHierarchical("http", "google.com", "/p1/p2", null, "fragment"); 386 testHierarchical("http", "google.com", "", null, "fragment"); 387 testHierarchical("http", "google.com", "", "query", "fragment"); 388 testHierarchical("http", "google.com", "", "query", null); 389 testHierarchical("http", null, "/", "query", null); 390 } 391 392 private static void testHierarchical(String scheme, String authority, 393 String path, String query, String fragment) { 394 StringBuilder sb = new StringBuilder(); 395 396 if (authority != null) { 397 sb.append("//").append(authority); 398 } 399 if (path != null) { 400 sb.append(path); 401 } 402 if (query != null) { 403 sb.append('?').append(query); 404 } 405 406 String ssp = sb.toString(); 407 408 if (scheme != null) { 409 sb.insert(0, scheme + ":"); 410 } 411 if (fragment != null) { 412 sb.append('#').append(fragment); 413 } 414 415 String uriString = sb.toString(); 416 417 Uri uri = Uri.parse(uriString); 418 419 // Run these twice to test caching. 420 compareHierarchical( 421 uriString, ssp, uri, scheme, authority, path, query, fragment); 422 compareHierarchical( 423 uriString, ssp, uri, scheme, authority, path, query, fragment); 424 425 // Test rebuilt version. 426 uri = uri.buildUpon().build(); 427 428 // Run these twice to test caching. 429 compareHierarchical( 430 uriString, ssp, uri, scheme, authority, path, query, fragment); 431 compareHierarchical( 432 uriString, ssp, uri, scheme, authority, path, query, fragment); 433 434 // The decoded and encoded versions of the inputs are all the same. 435 // We'll test the actual encoding decoding separately. 436 437 // Test building with encoded versions. 438 Uri built = new Uri.Builder() 439 .scheme(scheme) 440 .encodedAuthority(authority) 441 .encodedPath(path) 442 .encodedQuery(query) 443 .encodedFragment(fragment) 444 .build(); 445 446 compareHierarchical( 447 uriString, ssp, built, scheme, authority, path, query, fragment); 448 compareHierarchical( 449 uriString, ssp, built, scheme, authority, path, query, fragment); 450 451 // Test building with decoded versions. 452 built = new Uri.Builder() 453 .scheme(scheme) 454 .authority(authority) 455 .path(path) 456 .query(query) 457 .fragment(fragment) 458 .build(); 459 460 compareHierarchical( 461 uriString, ssp, built, scheme, authority, path, query, fragment); 462 compareHierarchical( 463 uriString, ssp, built, scheme, authority, path, query, fragment); 464 465 // Rebuild. 466 built = built.buildUpon().build(); 467 468 compareHierarchical( 469 uriString, ssp, built, scheme, authority, path, query, fragment); 470 compareHierarchical( 471 uriString, ssp, built, scheme, authority, path, query, fragment); 472 } 473 474 private static void compareHierarchical(String uriString, String ssp, 475 Uri uri, 476 String scheme, String authority, String path, String query, 477 String fragment) { 478 assertEquals(scheme, uri.getScheme()); 479 assertEquals(authority, uri.getAuthority()); 480 assertEquals(authority, uri.getEncodedAuthority()); 481 assertEquals(path, uri.getPath()); 482 assertEquals(path, uri.getEncodedPath()); 483 assertEquals(query, uri.getQuery()); 484 assertEquals(query, uri.getEncodedQuery()); 485 assertEquals(fragment, uri.getFragment()); 486 assertEquals(fragment, uri.getEncodedFragment()); 487 assertEquals(ssp, uri.getSchemeSpecificPart()); 488 489 if (scheme != null) { 490 assertTrue(uri.isAbsolute()); 491 assertFalse(uri.isRelative()); 492 } else { 493 assertFalse(uri.isAbsolute()); 494 assertTrue(uri.isRelative()); 495 } 496 497 assertFalse(uri.isOpaque()); 498 assertTrue(uri.isHierarchical()); 499 500 assertEquals(uriString, uri.toString()); 501 } 502 503 public void testEmptyToStringNotNull() { 504 assertNotNull(Uri.EMPTY.toString()); 505 } 506 507 @SmallTest 508 public void testParcellingWithoutFragment() { 509 parcelAndUnparcel(Uri.parse("foo:bob%20lee")); 510 parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment")); 511 parcelAndUnparcel(new Uri.Builder() 512 .scheme("http") 513 .authority("crazybob.org") 514 .path("/rss/") 515 .encodedQuery("a=b") 516 .build()); 517 } 518 519 public void testGetQueryParameter() { 520 String nestedUrl = "http://crazybob.org/?a=1&b=2"; 521 Uri uri = Uri.parse("http://test/").buildUpon() 522 .appendQueryParameter("foo", "bar") 523 .appendQueryParameter("nested", nestedUrl).build(); 524 assertEquals(nestedUrl, uri.getQueryParameter("nested")); 525 assertEquals(nestedUrl, uri.getQueryParameters("nested").get(0)); 526 } 527 528 public void testGetQueryParameterWorkaround() { 529 // This was a workaround for a bug where getQueryParameter called 530 // getQuery() instead of getEncodedQuery(). 531 String nestedUrl = "http://crazybob.org/?a=1&b=2"; 532 Uri uri = Uri.parse("http://test/").buildUpon() 533 .appendQueryParameter("foo", "bar") 534 .appendQueryParameter("nested", Uri.encode(nestedUrl)).build(); 535 assertEquals(nestedUrl, Uri.decode(uri.getQueryParameter("nested"))); 536 assertEquals(nestedUrl, 537 Uri.decode(uri.getQueryParameters("nested").get(0))); 538 } 539} 540