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.content.ContentUris;
20import android.os.Parcel;
21import android.test.suitebuilder.annotation.SmallTest;
22
23import junit.framework.TestCase;
24
25import java.io.File;
26import java.util.Arrays;
27import java.util.Iterator;
28import java.util.List;
29import java.util.Set;
30
31public class UriTest extends TestCase {
32
33    @SmallTest
34    public void testToStringWithPathOnly() {
35        Uri.Builder builder = new Uri.Builder();
36
37        // Not a valid path, but this came from a user's test case.
38        builder.path("//foo");
39        Uri uri = builder.build();
40        assertEquals("//foo", uri.toString());
41    }
42
43    @SmallTest
44    public void testParcelling() {
45        parcelAndUnparcel(Uri.parse("foo:bob%20lee"));
46        parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment"));
47        parcelAndUnparcel(new Uri.Builder()
48            .scheme("http")
49            .authority("crazybob.org")
50            .path("/rss/")
51            .encodedQuery("a=b")
52            .fragment("foo")
53            .build());
54    }
55
56    private void parcelAndUnparcel(Uri u) {
57        Parcel p = Parcel.obtain();
58        try {
59            Uri.writeToParcel(p, u);
60            p.setDataPosition(0);
61            assertEquals(u, Uri.CREATOR.createFromParcel(p));
62
63            p.setDataPosition(0);
64            u = u.buildUpon().build();
65            Uri.writeToParcel(p, u);
66            p.setDataPosition(0);
67            assertEquals(u, Uri.CREATOR.createFromParcel(p));
68        }
69        finally {
70            p.recycle();
71        }
72    }
73
74    @SmallTest
75    public void testBuildUponOpaqueStringUri() {
76        Uri u = Uri.parse("bob:lee").buildUpon().scheme("robert").build();
77        assertEquals("robert", u.getScheme());
78        assertEquals("lee", u.getEncodedSchemeSpecificPart());
79        assertEquals("lee", u.getSchemeSpecificPart());
80        assertNull(u.getQuery());
81        assertNull(u.getPath());
82        assertNull(u.getAuthority());
83        assertNull(u.getHost());
84    }
85
86    @SmallTest
87    public void testStringUri() {
88        assertEquals("bob lee",
89                Uri.parse("foo:bob%20lee").getSchemeSpecificPart());
90        assertEquals("bob%20lee",
91                Uri.parse("foo:bob%20lee").getEncodedSchemeSpecificPart());
92        assertEquals("/bob%20lee",
93                Uri.parse("foo:/bob%20lee").getEncodedPath());
94        assertNull(Uri.parse("foo:bob%20lee").getPath());
95        assertEquals("bob%20lee",
96                Uri.parse("foo:?bob%20lee").getEncodedQuery());
97        assertNull(Uri.parse("foo:bar#?bob%20lee").getQuery());
98        assertEquals("bob%20lee",
99                Uri.parse("foo:#bob%20lee").getEncodedFragment());
100    }
101
102    @SmallTest
103    public void testStringUriIsHierarchical() {
104        assertTrue(Uri.parse("bob").isHierarchical());
105        assertFalse(Uri.parse("bob:").isHierarchical());
106    }
107
108    @SmallTest
109    public void testNullUriString() {
110        try {
111            Uri.parse(null);
112            fail();
113        } catch (NullPointerException e) {}
114    }
115
116    @SmallTest
117    public void testNullFile() {
118        try {
119            Uri.fromFile(null);
120            fail();
121        } catch (NullPointerException e) {}
122    }
123
124    @SmallTest
125    public void testCompareTo() {
126        Uri a = Uri.parse("foo:a");
127        Uri b = Uri.parse("foo:b");
128        Uri b2 = Uri.parse("foo:b");
129
130        assertTrue(a.compareTo(b) < 0);
131        assertTrue(b.compareTo(a) > 0);
132        assertEquals(0, b.compareTo(b2));
133    }
134
135    @SmallTest
136    public void testEqualsAndHashCode() {
137
138        Uri a = Uri.parse("http://crazybob.org/test/?foo=bar#tee");
139
140        Uri b = new Uri.Builder()
141                .scheme("http")
142                .authority("crazybob.org")
143                .path("/test/")
144                .encodedQuery("foo=bar")
145                .fragment("tee")
146                .build();
147
148        // Try alternate builder methods.
149        Uri c = new Uri.Builder()
150                .scheme("http")
151                .encodedAuthority("crazybob.org")
152                .encodedPath("/test/")
153                .encodedQuery("foo=bar")
154                .encodedFragment("tee")
155                .build();
156
157        assertFalse(Uri.EMPTY.equals(null));
158
159        assertEquals(a, b);
160        assertEquals(b, c);
161        assertEquals(c, a);
162
163        assertEquals(a.hashCode(), b.hashCode());
164        assertEquals(b.hashCode(), c.hashCode());
165    }
166
167    @SmallTest
168    public void testAuthorityParsing() {
169        Uri uri = Uri.parse("http://localhost:42");
170        assertEquals("localhost", uri.getHost());
171        assertEquals(42, uri.getPort());
172
173        uri = Uri.parse("http://bob@localhost:42");
174        assertEquals("bob", uri.getUserInfo());
175        assertEquals("localhost", uri.getHost());
176        assertEquals(42, uri.getPort());
177
178        uri = Uri.parse("http://bob%20lee@localhost:42");
179        assertEquals("bob lee", uri.getUserInfo());
180        assertEquals("bob%20lee", uri.getEncodedUserInfo());
181
182        uri = Uri.parse("http://bob%40lee%3ajr@local%68ost:4%32");
183        assertEquals("bob@lee:jr", uri.getUserInfo());
184        assertEquals("localhost", uri.getHost());
185        assertEquals(42, uri.getPort());
186
187        uri = Uri.parse("http://localhost");
188        assertEquals("localhost", uri.getHost());
189        assertEquals(-1, uri.getPort());
190
191        uri = Uri.parse("http://a:a@example.com:a@example2.com/path");
192        assertEquals("a:a@example.com:a@example2.com", uri.getAuthority());
193        assertEquals("example2.com", uri.getHost());
194        assertEquals(-1, uri.getPort());
195        assertEquals("/path", uri.getPath());
196
197        uri = Uri.parse("http://a.foo.com\\.example.com/path");
198        assertEquals("a.foo.com", uri.getHost());
199        assertEquals(-1, uri.getPort());
200        assertEquals("\\.example.com/path", uri.getPath());
201    }
202
203    @SmallTest
204    public void testBuildUponOpaqueUri() {
205        Uri a = Uri.fromParts("foo", "bar", "tee");
206        Uri b = a.buildUpon().fragment("new").build();
207        assertEquals("new", b.getFragment());
208        assertEquals("bar", b.getSchemeSpecificPart());
209        assertEquals("foo", b.getScheme());
210    }
211
212    @SmallTest
213    public void testBuildUponEncodedOpaqueUri() {
214        Uri a = new Uri.Builder()
215                .scheme("foo")
216                .encodedOpaquePart("bar")
217                .fragment("tee")
218                .build();
219        Uri b = a.buildUpon().fragment("new").build();
220        assertEquals("new", b.getFragment());
221        assertEquals("bar", b.getSchemeSpecificPart());
222        assertEquals("foo", b.getScheme());
223    }
224
225    @SmallTest
226    public void testPathSegmentDecoding() {
227        Uri uri = Uri.parse("foo://bar/a%20a/b%20b");
228        assertEquals("a a", uri.getPathSegments().get(0));
229        assertEquals("b b", uri.getPathSegments().get(1));
230    }
231
232    @SmallTest
233    public void testSms() {
234        Uri base = Uri.parse("content://sms");
235        Uri appended = base.buildUpon()
236                .appendEncodedPath("conversations/addr=555-1212")
237                .build();
238        assertEquals("content://sms/conversations/addr=555-1212",
239                appended.toString());
240        assertEquals(2, appended.getPathSegments().size());
241        assertEquals("conversations", appended.getPathSegments().get(0));
242        assertEquals("addr=555-1212", appended.getPathSegments().get(1));
243    }
244
245    @SmallTest
246    public void testEncodeWithAllowedChars() {
247        String encoded = Uri.encode("Bob:/", "/");
248        assertEquals(-1, encoded.indexOf(':'));
249        assertTrue(encoded.indexOf('/') > -1);
250    }
251
252    @SmallTest
253    public void testEncodeDecode() {
254        code(null);
255        code("");
256        code("Bob");
257        code(":Bob");
258        code("::Bob");
259        code("Bob::Lee");
260        code("Bob:Lee");
261        code("Bob::");
262        code("Bob:");
263        code("::Bob::");
264    }
265
266    private void code(String s) {
267        assertEquals(s, Uri.decode(Uri.encode(s, null)));
268    }
269
270    @SmallTest
271    public void testFile() {
272        File f = new File("/tmp/bob");
273
274        Uri uri = Uri.fromFile(f);
275
276        assertEquals("file:///tmp/bob", uri.toString());
277    }
278
279    @SmallTest
280    public void testQueryParameters() {
281        Uri uri = Uri.parse("content://user");
282
283        assertEquals(null, uri.getQueryParameter("a"));
284
285        uri = uri.buildUpon().appendQueryParameter("a", "b").build();
286
287        assertEquals("b", uri.getQueryParameter("a"));
288
289        uri = uri.buildUpon().appendQueryParameter("a", "b2").build();
290
291        assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a"));
292
293        uri = uri.buildUpon().appendQueryParameter("c", "d").build();
294
295        assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a"));
296        assertEquals("d", uri.getQueryParameter("c"));
297    }
298
299    // http://b/2337042
300    @SmallTest
301    public void testHostWithTrailingDot() {
302        Uri uri = Uri.parse("http://google.com./b/c/g");
303        assertEquals("google.com.", uri.getHost());
304        assertEquals("/b/c/g", uri.getPath());
305    }
306
307    @SmallTest
308    public void testSchemeOnly() {
309        Uri uri = Uri.parse("empty:");
310        assertEquals("empty", uri.getScheme());
311        assertTrue(uri.isAbsolute());
312        assertNull(uri.getPath());
313    }
314
315    @SmallTest
316    public void testEmptyPath() {
317        Uri uri = Uri.parse("content://user");
318        assertEquals(0, uri.getPathSegments().size());
319    }
320
321    @SmallTest
322    public void testPathOperations() {
323        Uri uri = Uri.parse("content://user/a/b");
324
325        assertEquals(2, uri.getPathSegments().size());
326        assertEquals("b", uri.getLastPathSegment());
327
328        Uri first = uri;
329        uri = uri.buildUpon().appendPath("c").build();
330
331        assertEquals(3, uri.getPathSegments().size());
332        assertEquals("c", uri.getLastPathSegment());
333        assertEquals("content://user/a/b/c", uri.toString());
334
335        uri = ContentUris.withAppendedId(uri, 100);
336
337        assertEquals(4, uri.getPathSegments().size());
338        assertEquals("100", uri.getLastPathSegment());
339        assertEquals(100, ContentUris.parseId(uri));
340        assertEquals("content://user/a/b/c/100", uri.toString());
341
342        // Make sure the original URI is still intact.
343        assertEquals(2, first.getPathSegments().size());
344        assertEquals("b", first.getLastPathSegment());
345
346        try {
347            first.getPathSegments().get(2);
348            fail();
349        } catch (IndexOutOfBoundsException e) {}
350
351        assertEquals(null, Uri.EMPTY.getLastPathSegment());
352
353        Uri withC = Uri.parse("foo:/a/b/").buildUpon().appendPath("c").build();
354        assertEquals("/a/b/c", withC.getPath());
355    }
356
357    @SmallTest
358    public void testOpaqueUri() {
359        Uri uri = Uri.parse("mailto:nobody");
360        testOpaqueUri(uri);
361
362        uri = uri.buildUpon().build();
363        testOpaqueUri(uri);
364
365        uri = Uri.fromParts("mailto", "nobody", null);
366        testOpaqueUri(uri);
367
368        uri = uri.buildUpon().build();
369        testOpaqueUri(uri);
370
371        uri = new Uri.Builder()
372                .scheme("mailto")
373                .opaquePart("nobody")
374                .build();
375        testOpaqueUri(uri);
376
377        uri = uri.buildUpon().build();
378        testOpaqueUri(uri);
379    }
380
381    private void testOpaqueUri(Uri uri) {
382        assertEquals("mailto", uri.getScheme());
383        assertEquals("nobody", uri.getSchemeSpecificPart());
384        assertEquals("nobody", uri.getEncodedSchemeSpecificPart());
385
386        assertNull(uri.getFragment());
387        assertTrue(uri.isAbsolute());
388        assertTrue(uri.isOpaque());
389        assertFalse(uri.isRelative());
390        assertFalse(uri.isHierarchical());
391
392        assertNull(uri.getAuthority());
393        assertNull(uri.getEncodedAuthority());
394        assertNull(uri.getPath());
395        assertNull(uri.getEncodedPath());
396        assertNull(uri.getUserInfo());
397        assertNull(uri.getEncodedUserInfo());
398        assertNull(uri.getQuery());
399        assertNull(uri.getEncodedQuery());
400        assertNull(uri.getHost());
401        assertEquals(-1, uri.getPort());
402
403        assertTrue(uri.getPathSegments().isEmpty());
404        assertNull(uri.getLastPathSegment());
405
406        assertEquals("mailto:nobody", uri.toString());
407
408        Uri withFragment = uri.buildUpon().fragment("top").build();
409        assertEquals("mailto:nobody#top", withFragment.toString());
410    }
411
412    @SmallTest
413    public void testHierarchicalUris() {
414        testHierarchical("http", "google.com", "/p1/p2", "query", "fragment");
415        testHierarchical("file", null, "/p1/p2", null, null);
416        testHierarchical("content", "contact", "/p1/p2", null, null);
417        testHierarchical("http", "google.com", "/p1/p2", null, "fragment");
418        testHierarchical("http", "google.com", "", null, "fragment");
419        testHierarchical("http", "google.com", "", "query", "fragment");
420        testHierarchical("http", "google.com", "", "query", null);
421        testHierarchical("http", null, "/", "query", null);
422    }
423
424    private static void testHierarchical(String scheme, String authority,
425            String path, String query, String fragment) {
426        StringBuilder sb = new StringBuilder();
427
428        if (authority != null) {
429            sb.append("//").append(authority);
430        }
431        if (path != null) {
432            sb.append(path);
433        }
434        if (query != null) {
435            sb.append('?').append(query);
436        }
437
438        String ssp = sb.toString();
439
440        if (scheme != null) {
441            sb.insert(0, scheme + ":");
442        }
443        if (fragment != null) {
444            sb.append('#').append(fragment);
445        }
446
447        String uriString = sb.toString();
448
449        Uri uri = Uri.parse(uriString);
450
451        // Run these twice to test caching.
452        compareHierarchical(
453                uriString, ssp, uri, scheme, authority, path, query, fragment);
454        compareHierarchical(
455                uriString, ssp, uri, scheme, authority, path, query, fragment);
456
457        // Test rebuilt version.
458        uri = uri.buildUpon().build();
459
460        // Run these twice to test caching.
461        compareHierarchical(
462                uriString, ssp, uri, scheme, authority, path, query, fragment);
463        compareHierarchical(
464                uriString, ssp, uri, scheme, authority, path, query, fragment);
465
466        // The decoded and encoded versions of the inputs are all the same.
467        // We'll test the actual encoding decoding separately.
468
469        // Test building with encoded versions.
470        Uri built = new Uri.Builder()
471                .scheme(scheme)
472                .encodedAuthority(authority)
473                .encodedPath(path)
474                .encodedQuery(query)
475                .encodedFragment(fragment)
476                .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        // Test building with decoded versions.
484        built = new Uri.Builder()
485                .scheme(scheme)
486                .authority(authority)
487                .path(path)
488                .query(query)
489                .fragment(fragment)
490                .build();
491
492        compareHierarchical(
493                uriString, ssp, built, scheme, authority, path, query, fragment);
494        compareHierarchical(
495                uriString, ssp, built, scheme, authority, path, query, fragment);
496
497        // Rebuild.
498        built = built.buildUpon().build();
499
500        compareHierarchical(
501                uriString, ssp, built, scheme, authority, path, query, fragment);
502        compareHierarchical(
503                uriString, ssp, built, scheme, authority, path, query, fragment);
504    }
505
506    private static void compareHierarchical(String uriString, String ssp,
507            Uri uri,
508            String scheme, String authority, String path, String query,
509            String fragment) {
510        assertEquals(scheme, uri.getScheme());
511        assertEquals(authority, uri.getAuthority());
512        assertEquals(authority, uri.getEncodedAuthority());
513        assertEquals(path, uri.getPath());
514        assertEquals(path, uri.getEncodedPath());
515        assertEquals(query, uri.getQuery());
516        assertEquals(query, uri.getEncodedQuery());
517        assertEquals(fragment, uri.getFragment());
518        assertEquals(fragment, uri.getEncodedFragment());
519        assertEquals(ssp, uri.getSchemeSpecificPart());
520
521        if (scheme != null) {
522            assertTrue(uri.isAbsolute());
523            assertFalse(uri.isRelative());
524        } else {
525            assertFalse(uri.isAbsolute());
526            assertTrue(uri.isRelative());
527        }
528
529        assertFalse(uri.isOpaque());
530        assertTrue(uri.isHierarchical());
531
532        assertEquals(uriString, uri.toString());
533    }
534
535    public void testEmptyToStringNotNull() {
536        assertNotNull(Uri.EMPTY.toString());
537    }
538
539    @SmallTest
540    public void testParcellingWithoutFragment() {
541        parcelAndUnparcel(Uri.parse("foo:bob%20lee"));
542        parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment"));
543        parcelAndUnparcel(new Uri.Builder()
544            .scheme("http")
545            .authority("crazybob.org")
546            .path("/rss/")
547            .encodedQuery("a=b")
548            .build());
549    }
550
551    public void testGetQueryParameter() {
552        String nestedUrl = "http://crazybob.org/?a=1&b=2";
553        Uri uri = Uri.parse("http://test/").buildUpon()
554                .appendQueryParameter("foo", "bar")
555                .appendQueryParameter("nested", nestedUrl).build();
556        assertEquals(nestedUrl, uri.getQueryParameter("nested"));
557        assertEquals(nestedUrl, uri.getQueryParameters("nested").get(0));
558    }
559
560    public void testGetQueryParameterWorkaround() {
561        // This was a workaround for a bug where getQueryParameter called
562        // getQuery() instead of getEncodedQuery().
563        String nestedUrl = "http://crazybob.org/?a=1&b=2";
564        Uri uri = Uri.parse("http://test/").buildUpon()
565                .appendQueryParameter("foo", "bar")
566                .appendQueryParameter("nested", Uri.encode(nestedUrl)).build();
567        assertEquals(nestedUrl, Uri.decode(uri.getQueryParameter("nested")));
568        assertEquals(nestedUrl,
569                Uri.decode(uri.getQueryParameters("nested").get(0)));
570    }
571
572    public void testGetQueryParameterEdgeCases() {
573        Uri uri;
574
575        // key at beginning of URL
576        uri = Uri.parse("http://test/").buildUpon()
577            .appendQueryParameter("key", "a b")
578            .appendQueryParameter("keya", "c d")
579            .appendQueryParameter("bkey", "e f")
580            .build();
581        assertEquals("a b", uri.getQueryParameter("key"));
582
583        // key in middle of URL
584        uri = Uri.parse("http://test/").buildUpon()
585            .appendQueryParameter("akeyb", "a b")
586            .appendQueryParameter("keya", "c d")
587            .appendQueryParameter("key", "e f")
588            .appendQueryParameter("bkey", "g h")
589            .build();
590        assertEquals("e f", uri.getQueryParameter("key"));
591
592        // key at end of URL
593        uri = Uri.parse("http://test/").buildUpon()
594            .appendQueryParameter("akeyb", "a b")
595            .appendQueryParameter("keya", "c d")
596            .appendQueryParameter("key", "y z")
597            .build();
598        assertEquals("y z", uri.getQueryParameter("key"));
599
600        // key is a substring of parameters, but not present
601        uri = Uri.parse("http://test/").buildUpon()
602            .appendQueryParameter("akeyb", "a b")
603            .appendQueryParameter("keya", "c d")
604            .appendQueryParameter("bkey", "e f")
605            .build();
606        assertNull(uri.getQueryParameter("key"));
607
608        // key is a prefix or suffix of the query
609        uri = Uri.parse("http://test/?qq=foo");
610        assertNull(uri.getQueryParameter("q"));
611        assertNull(uri.getQueryParameter("oo"));
612
613        // escaped keys
614        uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
615        assertEquals("foo", uri.getQueryParameter("a b"));
616        assertEquals("", uri.getQueryParameter("c d"));
617        assertNull(uri.getQueryParameter("e f"));
618        assertNull(uri.getQueryParameter("b"));
619        assertNull(uri.getQueryParameter("c"));
620        assertNull(uri.getQueryParameter(" d"));
621
622        // empty values
623        uri = Uri.parse("http://www.google.com/?a=&b=&&c=");
624        assertEquals("", uri.getQueryParameter("a"));
625        assertEquals("", uri.getQueryParameter("b"));
626        assertEquals("", uri.getQueryParameter("c"));
627    }
628
629    public void testGetQueryParameterEmptyKey() {
630        Uri uri = Uri.parse("http://www.google.com/?=b");
631        assertEquals("b", uri.getQueryParameter(""));
632    }
633
634    public void testGetQueryParameterEmptyKey2() {
635      Uri uri = Uri.parse("http://www.google.com/?a=b&&c=d");
636      assertEquals("", uri.getQueryParameter(""));
637    }
638
639    public void testGetQueryParameterEmptyKey3() {
640      Uri uri = Uri.parse("http://www.google.com?");
641      assertEquals("", uri.getQueryParameter(""));
642    }
643
644    public void testGetQueryParameterEmptyKey4() {
645      Uri uri = Uri.parse("http://www.google.com?a=b&");
646      assertEquals("", uri.getQueryParameter(""));
647    }
648
649    public void testGetQueryParametersEmptyKey() {
650        Uri uri = Uri.parse("http://www.google.com/?=b&");
651        List<String> values = uri.getQueryParameters("");
652        assertEquals(2, values.size());
653        assertEquals("b", values.get(0));
654        assertEquals("", values.get(1));
655    }
656
657    public void testGetQueryParametersEmptyKey2() {
658        Uri uri = Uri.parse("http://www.google.com?");
659        List<String> values = uri.getQueryParameters("");
660        assertEquals(1, values.size());
661        assertEquals("", values.get(0));
662    }
663
664    public void testGetQueryParametersEmptyKey3() {
665      Uri uri = Uri.parse("http://www.google.com/?a=b&&c=d");
666      List<String> values = uri.getQueryParameters("");
667      assertEquals(1, values.size());
668      assertEquals("", values.get(0));
669    }
670
671    public void testGetQueryParameterNames() {
672        Uri uri = Uri.parse("http://test?a=1");
673        Set<String> names = uri.getQueryParameterNames();
674        assertEquals(1, names.size());
675        assertEquals("a", names.iterator().next());
676    }
677
678    public void testGetQueryParameterNamesEmptyKey() {
679        Uri uri = Uri.parse("http://www.google.com/?a=x&&c=z");
680        Set<String> names = uri.getQueryParameterNames();
681        Iterator<String> iter = names.iterator();
682        assertEquals(3, names.size());
683        assertEquals("a", iter.next());
684        assertEquals("", iter.next());
685        assertEquals("c", iter.next());
686    }
687
688    public void testGetQueryParameterNamesEmptyKey2() {
689        Uri uri = Uri.parse("http://www.google.com/?a=x&=d&c=z");
690        Set<String> names = uri.getQueryParameterNames();
691        Iterator<String> iter = names.iterator();
692        assertEquals(3, names.size());
693        assertEquals("a", iter.next());
694        assertEquals("", iter.next());
695        assertEquals("c", iter.next());
696    }
697
698    public void testGetQueryParameterNamesEmptyValues() {
699        Uri uri = Uri.parse("http://www.google.com/?a=foo&b=&c=");
700        Set<String> names = uri.getQueryParameterNames();
701        Iterator<String> iter = names.iterator();
702        assertEquals(3, names.size());
703        assertEquals("a", iter.next());
704        assertEquals("b", iter.next());
705        assertEquals("c", iter.next());
706    }
707
708    public void testGetQueryParameterNamesEdgeCases() {
709        Uri uri = Uri.parse("http://foo?a=bar&b=bar&c=&&d=baz&e&f&g=buzz&&&a&b=bar&h");
710        Set<String> names = uri.getQueryParameterNames();
711        Iterator<String> iter = names.iterator();
712        assertEquals(9, names.size());
713        assertEquals("a", iter.next());
714        assertEquals("b", iter.next());
715        assertEquals("c", iter.next());
716        assertEquals("", iter.next());
717        assertEquals("d", iter.next());
718        assertEquals("e", iter.next());
719        assertEquals("f", iter.next());
720        assertEquals("g", iter.next());
721        assertEquals("h", iter.next());
722    }
723
724    public void testGetQueryParameterNamesEscapedKeys() {
725        Uri uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
726        Set<String> names = uri.getQueryParameterNames();
727        assertEquals(2, names.size());
728        Iterator<String> iter = names.iterator();
729        assertEquals("a b", iter.next());
730        assertEquals("c d", iter.next());
731    }
732
733    public void testGetQueryParameterEscapedKeys() {
734        Uri uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
735        String value = uri.getQueryParameter("a b");
736        assertEquals("foo", value);
737    }
738
739    public void testClearQueryParameters() {
740        Uri uri = Uri.parse("http://www.google.com/?a=x&b=y&c=z").buildUpon()
741            .clearQuery().appendQueryParameter("foo", "bar").build();
742        Set<String> names = uri.getQueryParameterNames();
743        assertEquals(1, names.size());
744        assertEquals("foo", names.iterator().next());
745    }
746
747    /**
748     * Query parameters may omit the '='. http://b/3124097
749     */
750    public void testGetQueryParametersEmptyValue() {
751        assertEquals(Arrays.asList(""),
752                Uri.parse("http://foo/path?abc").getQueryParameters("abc"));
753        assertEquals(Arrays.asList(""),
754                Uri.parse("http://foo/path?foo=bar&abc").getQueryParameters("abc"));
755        assertEquals(Arrays.asList(""),
756                Uri.parse("http://foo/path?abcd=abc&abc").getQueryParameters("abc"));
757        assertEquals(Arrays.asList("a", "", ""),
758                Uri.parse("http://foo/path?abc=a&abc=&abc").getQueryParameters("abc"));
759        assertEquals(Arrays.asList("a", "", ""),
760                Uri.parse("http://foo/path?abc=a&abc=&abc=").getQueryParameters("abc"));
761    }
762
763    // http://code.google.com/p/android/issues/detail?id=21064
764    public void testPlusCharacterInQuery() {
765        assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c"));
766        assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c"));
767    }
768
769    public void testPathPrefixMatch() {
770        // Exact match
771        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
772                Uri.parse("content://com.example/path/")));
773        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
774                Uri.parse("content://com.example/path")));
775        assertTrue(Uri.parse("content://com.example///path///").isPathPrefixMatch(
776                Uri.parse("content://com.example/path/")));
777        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
778                Uri.parse("content://com.example///path///")));
779
780        // Child match
781        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
782                Uri.parse("content://com.example/path/")));
783        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
784                Uri.parse("content://com.example/path")));
785
786        // Extra parameters
787        assertTrue(Uri.parse("content://com.example/path#fragment").isPathPrefixMatch(
788                Uri.parse("content://com.example/path/")));
789        assertTrue(Uri.parse("content://com.example/path?q=v").isPathPrefixMatch(
790                Uri.parse("content://com.example/path/")));
791        assertTrue(Uri.parse("content://com.example/path/?q=v").isPathPrefixMatch(
792                Uri.parse("content://com.example/path/")));
793
794        // Different path
795        assertFalse(Uri.parse("content://com.example/path").isPathPrefixMatch(
796                Uri.parse("content://com.example/path/deeper/")));
797        assertFalse(Uri.parse("content://com.example/path2").isPathPrefixMatch(
798                Uri.parse("content://com.example/path")));
799
800        // Top-level match
801        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
802                Uri.parse("content://com.example/")));
803        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
804                Uri.parse("content://com.example")));
805
806        // Different prefixes
807        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
808                Uri.parse("file://com.example/path/")));
809        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
810                Uri.parse("content://org.example/path/")));
811
812        // Escaping
813        assertTrue(Uri.parse("content://com.example/path path/").isPathPrefixMatch(
814                Uri.parse("content://com.example/path%20path/")));
815        assertFalse(Uri.parse("content://com.example/path/path").isPathPrefixMatch(
816                Uri.parse("content://com.example/path%2Fpath")));
817    }
818
819    public void testToSafeString() {
820        checkToSafeString("tel:xxxxxx", "tel:Google");
821        checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");
822        checkToSafeString("tEl:xxx.xxx-xxxx", "tEl:123.456-7890");
823
824        checkToSafeString("sms:xxxxxx", "sms:123abc");
825        checkToSafeString("smS:xxx.xxx-xxxx", "smS:123.456-7890");
826
827        checkToSafeString("smsto:xxxxxx", "smsto:123abc");
828        checkToSafeString("SMSTo:xxx.xxx-xxxx", "SMSTo:123.456-7890");
829
830        checkToSafeString("mailto:xxxxxxx@xxxxxxx.xxx", "mailto:android@android.com");
831        checkToSafeString("Mailto:xxxxxxx@xxxxxxx.xxxxxxxxxx",
832                "Mailto:android@android.com/secret");
833
834        checkToSafeString("sip:xxxxxxx@xxxxxxx.xxxxxxxx", "sip:android@android.com:1234");
835        checkToSafeString("sIp:xxxxxxx@xxxxxxx.xxx", "sIp:android@android.com");
836
837        checkToSafeString("http://www.android.com/...", "http://www.android.com");
838        checkToSafeString("HTTP://www.android.com/...", "HTTP://www.android.com");
839        checkToSafeString("http://www.android.com/...", "http://www.android.com/");
840        checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
841        checkToSafeString("http://www.android.com/...",
842                "http://user:pwd@www.android.com/secretUrl?param");
843        checkToSafeString("http://www.android.com/...",
844                "http://user@www.android.com/secretUrl?param");
845        checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
846        checkToSafeString("http:///...", "http:///path?param");
847        checkToSafeString("http:///...", "http://");
848        checkToSafeString("http://:12345/...", "http://:12345/");
849
850        checkToSafeString("https://www.android.com/...", "https://www.android.com/secretUrl?param");
851        checkToSafeString("https://www.android.com:8443/...",
852                "https://user:pwd@www.android.com:8443/secretUrl?param");
853        checkToSafeString("https://www.android.com/...", "https://user:pwd@www.android.com");
854        checkToSafeString("Https://www.android.com/...", "Https://user:pwd@www.android.com");
855
856        checkToSafeString("ftp://ftp.android.com/...", "ftp://ftp.android.com/");
857        checkToSafeString("ftP://ftp.android.com/...", "ftP://anonymous@ftp.android.com/");
858        checkToSafeString("ftp://ftp.android.com:2121/...",
859                "ftp://root:love@ftp.android.com:2121/");
860
861        checkToSafeString("unsupported://ajkakjah/askdha/secret?secret",
862                "unsupported://ajkakjah/askdha/secret?secret");
863        checkToSafeString("unsupported:ajkakjah/askdha/secret?secret",
864                "unsupported:ajkakjah/askdha/secret?secret");
865    }
866
867    private void checkToSafeString(String expectedSafeString, String original) {
868        assertEquals(expectedSafeString, Uri.parse(original).toSafeString());
869    }
870}
871