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