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
192    @SmallTest
193    public void testBuildUponOpaqueUri() {
194        Uri a = Uri.fromParts("foo", "bar", "tee");
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 testBuildUponEncodedOpaqueUri() {
203        Uri a = new Uri.Builder()
204                .scheme("foo")
205                .encodedOpaquePart("bar")
206                .fragment("tee")
207                .build();
208        Uri b = a.buildUpon().fragment("new").build();
209        assertEquals("new", b.getFragment());
210        assertEquals("bar", b.getSchemeSpecificPart());
211        assertEquals("foo", b.getScheme());
212    }
213
214    @SmallTest
215    public void testPathSegmentDecoding() {
216        Uri uri = Uri.parse("foo://bar/a%20a/b%20b");
217        assertEquals("a a", uri.getPathSegments().get(0));
218        assertEquals("b b", uri.getPathSegments().get(1));
219    }
220
221    @SmallTest
222    public void testSms() {
223        Uri base = Uri.parse("content://sms");
224        Uri appended = base.buildUpon()
225                .appendEncodedPath("conversations/addr=555-1212")
226                .build();
227        assertEquals("content://sms/conversations/addr=555-1212",
228                appended.toString());
229        assertEquals(2, appended.getPathSegments().size());
230        assertEquals("conversations", appended.getPathSegments().get(0));
231        assertEquals("addr=555-1212", appended.getPathSegments().get(1));
232    }
233
234    @SmallTest
235    public void testEncodeWithAllowedChars() {
236        String encoded = Uri.encode("Bob:/", "/");
237        assertEquals(-1, encoded.indexOf(':'));
238        assertTrue(encoded.indexOf('/') > -1);
239    }
240
241    @SmallTest
242    public void testEncodeDecode() {
243        code(null);
244        code("");
245        code("Bob");
246        code(":Bob");
247        code("::Bob");
248        code("Bob::Lee");
249        code("Bob:Lee");
250        code("Bob::");
251        code("Bob:");
252        code("::Bob::");
253    }
254
255    private void code(String s) {
256        assertEquals(s, Uri.decode(Uri.encode(s, null)));
257    }
258
259    @SmallTest
260    public void testFile() {
261        File f = new File("/tmp/bob");
262
263        Uri uri = Uri.fromFile(f);
264
265        assertEquals("file:///tmp/bob", uri.toString());
266    }
267
268    @SmallTest
269    public void testQueryParameters() {
270        Uri uri = Uri.parse("content://user");
271
272        assertEquals(null, uri.getQueryParameter("a"));
273
274        uri = uri.buildUpon().appendQueryParameter("a", "b").build();
275
276        assertEquals("b", uri.getQueryParameter("a"));
277
278        uri = uri.buildUpon().appendQueryParameter("a", "b2").build();
279
280        assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a"));
281
282        uri = uri.buildUpon().appendQueryParameter("c", "d").build();
283
284        assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a"));
285        assertEquals("d", uri.getQueryParameter("c"));
286    }
287
288    // http://b/2337042
289    @SmallTest
290    public void testHostWithTrailingDot() {
291        Uri uri = Uri.parse("http://google.com./b/c/g");
292        assertEquals("google.com.", uri.getHost());
293        assertEquals("/b/c/g", uri.getPath());
294    }
295
296    @SmallTest
297    public void testSchemeOnly() {
298        Uri uri = Uri.parse("empty:");
299        assertEquals("empty", uri.getScheme());
300        assertTrue(uri.isAbsolute());
301        assertNull(uri.getPath());
302    }
303
304    @SmallTest
305    public void testEmptyPath() {
306        Uri uri = Uri.parse("content://user");
307        assertEquals(0, uri.getPathSegments().size());
308    }
309
310    @SmallTest
311    public void testPathOperations() {
312        Uri uri = Uri.parse("content://user/a/b");
313
314        assertEquals(2, uri.getPathSegments().size());
315        assertEquals("b", uri.getLastPathSegment());
316
317        Uri first = uri;
318        uri = uri.buildUpon().appendPath("c").build();
319
320        assertEquals(3, uri.getPathSegments().size());
321        assertEquals("c", uri.getLastPathSegment());
322        assertEquals("content://user/a/b/c", uri.toString());
323
324        uri = ContentUris.withAppendedId(uri, 100);
325
326        assertEquals(4, uri.getPathSegments().size());
327        assertEquals("100", uri.getLastPathSegment());
328        assertEquals(100, ContentUris.parseId(uri));
329        assertEquals("content://user/a/b/c/100", uri.toString());
330
331        // Make sure the original URI is still intact.
332        assertEquals(2, first.getPathSegments().size());
333        assertEquals("b", first.getLastPathSegment());
334
335        try {
336            first.getPathSegments().get(2);
337            fail();
338        } catch (IndexOutOfBoundsException e) {}
339
340        assertEquals(null, Uri.EMPTY.getLastPathSegment());
341
342        Uri withC = Uri.parse("foo:/a/b/").buildUpon().appendPath("c").build();
343        assertEquals("/a/b/c", withC.getPath());
344    }
345
346    @SmallTest
347    public void testOpaqueUri() {
348        Uri uri = Uri.parse("mailto:nobody");
349        testOpaqueUri(uri);
350
351        uri = uri.buildUpon().build();
352        testOpaqueUri(uri);
353
354        uri = Uri.fromParts("mailto", "nobody", null);
355        testOpaqueUri(uri);
356
357        uri = uri.buildUpon().build();
358        testOpaqueUri(uri);
359
360        uri = new Uri.Builder()
361                .scheme("mailto")
362                .opaquePart("nobody")
363                .build();
364        testOpaqueUri(uri);
365
366        uri = uri.buildUpon().build();
367        testOpaqueUri(uri);
368    }
369
370    private void testOpaqueUri(Uri uri) {
371        assertEquals("mailto", uri.getScheme());
372        assertEquals("nobody", uri.getSchemeSpecificPart());
373        assertEquals("nobody", uri.getEncodedSchemeSpecificPart());
374
375        assertNull(uri.getFragment());
376        assertTrue(uri.isAbsolute());
377        assertTrue(uri.isOpaque());
378        assertFalse(uri.isRelative());
379        assertFalse(uri.isHierarchical());
380
381        assertNull(uri.getAuthority());
382        assertNull(uri.getEncodedAuthority());
383        assertNull(uri.getPath());
384        assertNull(uri.getEncodedPath());
385        assertNull(uri.getUserInfo());
386        assertNull(uri.getEncodedUserInfo());
387        assertNull(uri.getQuery());
388        assertNull(uri.getEncodedQuery());
389        assertNull(uri.getHost());
390        assertEquals(-1, uri.getPort());
391
392        assertTrue(uri.getPathSegments().isEmpty());
393        assertNull(uri.getLastPathSegment());
394
395        assertEquals("mailto:nobody", uri.toString());
396
397        Uri withFragment = uri.buildUpon().fragment("top").build();
398        assertEquals("mailto:nobody#top", withFragment.toString());
399    }
400
401    @SmallTest
402    public void testHierarchicalUris() {
403        testHierarchical("http", "google.com", "/p1/p2", "query", "fragment");
404        testHierarchical("file", null, "/p1/p2", null, null);
405        testHierarchical("content", "contact", "/p1/p2", null, null);
406        testHierarchical("http", "google.com", "/p1/p2", null, "fragment");
407        testHierarchical("http", "google.com", "", null, "fragment");
408        testHierarchical("http", "google.com", "", "query", "fragment");
409        testHierarchical("http", "google.com", "", "query", null);
410        testHierarchical("http", null, "/", "query", null);
411    }
412
413    private static void testHierarchical(String scheme, String authority,
414            String path, String query, String fragment) {
415        StringBuilder sb = new StringBuilder();
416
417        if (authority != null) {
418            sb.append("//").append(authority);
419        }
420        if (path != null) {
421            sb.append(path);
422        }
423        if (query != null) {
424            sb.append('?').append(query);
425        }
426
427        String ssp = sb.toString();
428
429        if (scheme != null) {
430            sb.insert(0, scheme + ":");
431        }
432        if (fragment != null) {
433            sb.append('#').append(fragment);
434        }
435
436        String uriString = sb.toString();
437
438        Uri uri = Uri.parse(uriString);
439
440        // Run these twice to test caching.
441        compareHierarchical(
442                uriString, ssp, uri, scheme, authority, path, query, fragment);
443        compareHierarchical(
444                uriString, ssp, uri, scheme, authority, path, query, fragment);
445
446        // Test rebuilt version.
447        uri = uri.buildUpon().build();
448
449        // Run these twice to test caching.
450        compareHierarchical(
451                uriString, ssp, uri, scheme, authority, path, query, fragment);
452        compareHierarchical(
453                uriString, ssp, uri, scheme, authority, path, query, fragment);
454
455        // The decoded and encoded versions of the inputs are all the same.
456        // We'll test the actual encoding decoding separately.
457
458        // Test building with encoded versions.
459        Uri built = new Uri.Builder()
460                .scheme(scheme)
461                .encodedAuthority(authority)
462                .encodedPath(path)
463                .encodedQuery(query)
464                .encodedFragment(fragment)
465                .build();
466
467        compareHierarchical(
468                uriString, ssp, built, scheme, authority, path, query, fragment);
469        compareHierarchical(
470                uriString, ssp, built, scheme, authority, path, query, fragment);
471
472        // Test building with decoded versions.
473        built = new Uri.Builder()
474                .scheme(scheme)
475                .authority(authority)
476                .path(path)
477                .query(query)
478                .fragment(fragment)
479                .build();
480
481        compareHierarchical(
482                uriString, ssp, built, scheme, authority, path, query, fragment);
483        compareHierarchical(
484                uriString, ssp, built, scheme, authority, path, query, fragment);
485
486        // Rebuild.
487        built = built.buildUpon().build();
488
489        compareHierarchical(
490                uriString, ssp, built, scheme, authority, path, query, fragment);
491        compareHierarchical(
492                uriString, ssp, built, scheme, authority, path, query, fragment);
493    }
494
495    private static void compareHierarchical(String uriString, String ssp,
496            Uri uri,
497            String scheme, String authority, String path, String query,
498            String fragment) {
499        assertEquals(scheme, uri.getScheme());
500        assertEquals(authority, uri.getAuthority());
501        assertEquals(authority, uri.getEncodedAuthority());
502        assertEquals(path, uri.getPath());
503        assertEquals(path, uri.getEncodedPath());
504        assertEquals(query, uri.getQuery());
505        assertEquals(query, uri.getEncodedQuery());
506        assertEquals(fragment, uri.getFragment());
507        assertEquals(fragment, uri.getEncodedFragment());
508        assertEquals(ssp, uri.getSchemeSpecificPart());
509
510        if (scheme != null) {
511            assertTrue(uri.isAbsolute());
512            assertFalse(uri.isRelative());
513        } else {
514            assertFalse(uri.isAbsolute());
515            assertTrue(uri.isRelative());
516        }
517
518        assertFalse(uri.isOpaque());
519        assertTrue(uri.isHierarchical());
520
521        assertEquals(uriString, uri.toString());
522    }
523
524    public void testEmptyToStringNotNull() {
525        assertNotNull(Uri.EMPTY.toString());
526    }
527
528    @SmallTest
529    public void testParcellingWithoutFragment() {
530        parcelAndUnparcel(Uri.parse("foo:bob%20lee"));
531        parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment"));
532        parcelAndUnparcel(new Uri.Builder()
533            .scheme("http")
534            .authority("crazybob.org")
535            .path("/rss/")
536            .encodedQuery("a=b")
537            .build());
538    }
539
540    public void testGetQueryParameter() {
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", nestedUrl).build();
545        assertEquals(nestedUrl, uri.getQueryParameter("nested"));
546        assertEquals(nestedUrl, uri.getQueryParameters("nested").get(0));
547    }
548
549    public void testGetQueryParameterWorkaround() {
550        // This was a workaround for a bug where getQueryParameter called
551        // getQuery() instead of getEncodedQuery().
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", Uri.encode(nestedUrl)).build();
556        assertEquals(nestedUrl, Uri.decode(uri.getQueryParameter("nested")));
557        assertEquals(nestedUrl,
558                Uri.decode(uri.getQueryParameters("nested").get(0)));
559    }
560
561    public void testGetQueryParameterEdgeCases() {
562        Uri uri;
563
564        // key at beginning of URL
565        uri = Uri.parse("http://test/").buildUpon()
566            .appendQueryParameter("key", "a b")
567            .appendQueryParameter("keya", "c d")
568            .appendQueryParameter("bkey", "e f")
569            .build();
570        assertEquals("a b", uri.getQueryParameter("key"));
571
572        // key in middle of URL
573        uri = Uri.parse("http://test/").buildUpon()
574            .appendQueryParameter("akeyb", "a b")
575            .appendQueryParameter("keya", "c d")
576            .appendQueryParameter("key", "e f")
577            .appendQueryParameter("bkey", "g h")
578            .build();
579        assertEquals("e f", uri.getQueryParameter("key"));
580
581        // key at end of URL
582        uri = Uri.parse("http://test/").buildUpon()
583            .appendQueryParameter("akeyb", "a b")
584            .appendQueryParameter("keya", "c d")
585            .appendQueryParameter("key", "y z")
586            .build();
587        assertEquals("y z", uri.getQueryParameter("key"));
588
589        // key is a substring of parameters, but not present
590        uri = Uri.parse("http://test/").buildUpon()
591            .appendQueryParameter("akeyb", "a b")
592            .appendQueryParameter("keya", "c d")
593            .appendQueryParameter("bkey", "e f")
594            .build();
595        assertNull(uri.getQueryParameter("key"));
596
597        // key is a prefix or suffix of the query
598        uri = Uri.parse("http://test/?qq=foo");
599        assertNull(uri.getQueryParameter("q"));
600        assertNull(uri.getQueryParameter("oo"));
601
602        // escaped keys
603        uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
604        assertEquals("foo", uri.getQueryParameter("a b"));
605        assertEquals("", uri.getQueryParameter("c d"));
606        assertNull(uri.getQueryParameter("e f"));
607        assertNull(uri.getQueryParameter("b"));
608        assertNull(uri.getQueryParameter("c"));
609        assertNull(uri.getQueryParameter(" d"));
610
611        // empty values
612        uri = Uri.parse("http://www.google.com/?a=&b=&&c=");
613        assertEquals("", uri.getQueryParameter("a"));
614        assertEquals("", uri.getQueryParameter("b"));
615        assertEquals("", uri.getQueryParameter("c"));
616    }
617
618    public void testGetQueryParameterEmptyKey() {
619        Uri uri = Uri.parse("http://www.google.com/?=b");
620        assertEquals("b", uri.getQueryParameter(""));
621    }
622
623    public void testGetQueryParameterEmptyKey2() {
624      Uri uri = Uri.parse("http://www.google.com/?a=b&&c=d");
625      assertEquals("", uri.getQueryParameter(""));
626    }
627
628    public void testGetQueryParameterEmptyKey3() {
629      Uri uri = Uri.parse("http://www.google.com?");
630      assertEquals("", uri.getQueryParameter(""));
631    }
632
633    public void testGetQueryParameterEmptyKey4() {
634      Uri uri = Uri.parse("http://www.google.com?a=b&");
635      assertEquals("", uri.getQueryParameter(""));
636    }
637
638    public void testGetQueryParametersEmptyKey() {
639        Uri uri = Uri.parse("http://www.google.com/?=b&");
640        List<String> values = uri.getQueryParameters("");
641        assertEquals(2, values.size());
642        assertEquals("b", values.get(0));
643        assertEquals("", values.get(1));
644    }
645
646    public void testGetQueryParametersEmptyKey2() {
647        Uri uri = Uri.parse("http://www.google.com?");
648        List<String> values = uri.getQueryParameters("");
649        assertEquals(1, values.size());
650        assertEquals("", values.get(0));
651    }
652
653    public void testGetQueryParametersEmptyKey3() {
654      Uri uri = Uri.parse("http://www.google.com/?a=b&&c=d");
655      List<String> values = uri.getQueryParameters("");
656      assertEquals(1, values.size());
657      assertEquals("", values.get(0));
658    }
659
660    public void testGetQueryParameterNames() {
661        Uri uri = Uri.parse("http://test?a=1");
662        Set<String> names = uri.getQueryParameterNames();
663        assertEquals(1, names.size());
664        assertEquals("a", names.iterator().next());
665    }
666
667    public void testGetQueryParameterNamesEmptyKey() {
668        Uri uri = Uri.parse("http://www.google.com/?a=x&&c=z");
669        Set<String> names = uri.getQueryParameterNames();
670        Iterator<String> iter = names.iterator();
671        assertEquals(3, names.size());
672        assertEquals("a", iter.next());
673        assertEquals("", iter.next());
674        assertEquals("c", iter.next());
675    }
676
677    public void testGetQueryParameterNamesEmptyKey2() {
678        Uri uri = Uri.parse("http://www.google.com/?a=x&=d&c=z");
679        Set<String> names = uri.getQueryParameterNames();
680        Iterator<String> iter = names.iterator();
681        assertEquals(3, names.size());
682        assertEquals("a", iter.next());
683        assertEquals("", iter.next());
684        assertEquals("c", iter.next());
685    }
686
687    public void testGetQueryParameterNamesEmptyValues() {
688        Uri uri = Uri.parse("http://www.google.com/?a=foo&b=&c=");
689        Set<String> names = uri.getQueryParameterNames();
690        Iterator<String> iter = names.iterator();
691        assertEquals(3, names.size());
692        assertEquals("a", iter.next());
693        assertEquals("b", iter.next());
694        assertEquals("c", iter.next());
695    }
696
697    public void testGetQueryParameterNamesEdgeCases() {
698        Uri uri = Uri.parse("http://foo?a=bar&b=bar&c=&&d=baz&e&f&g=buzz&&&a&b=bar&h");
699        Set<String> names = uri.getQueryParameterNames();
700        Iterator<String> iter = names.iterator();
701        assertEquals(9, names.size());
702        assertEquals("a", iter.next());
703        assertEquals("b", iter.next());
704        assertEquals("c", iter.next());
705        assertEquals("", iter.next());
706        assertEquals("d", iter.next());
707        assertEquals("e", iter.next());
708        assertEquals("f", iter.next());
709        assertEquals("g", iter.next());
710        assertEquals("h", iter.next());
711    }
712
713    public void testGetQueryParameterNamesEscapedKeys() {
714        Uri uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
715        Set<String> names = uri.getQueryParameterNames();
716        assertEquals(2, names.size());
717        Iterator<String> iter = names.iterator();
718        assertEquals("a b", iter.next());
719        assertEquals("c d", iter.next());
720    }
721
722    public void testGetQueryParameterEscapedKeys() {
723        Uri uri = Uri.parse("http://www.google.com/?a%20b=foo&c%20d=");
724        String value = uri.getQueryParameter("a b");
725        assertEquals("foo", value);
726    }
727
728    public void testClearQueryParameters() {
729        Uri uri = Uri.parse("http://www.google.com/?a=x&b=y&c=z").buildUpon()
730            .clearQuery().appendQueryParameter("foo", "bar").build();
731        Set<String> names = uri.getQueryParameterNames();
732        assertEquals(1, names.size());
733        assertEquals("foo", names.iterator().next());
734    }
735
736    /**
737     * Query parameters may omit the '='. http://b/3124097
738     */
739    public void testGetQueryParametersEmptyValue() {
740        assertEquals(Arrays.asList(""),
741                Uri.parse("http://foo/path?abc").getQueryParameters("abc"));
742        assertEquals(Arrays.asList(""),
743                Uri.parse("http://foo/path?foo=bar&abc").getQueryParameters("abc"));
744        assertEquals(Arrays.asList(""),
745                Uri.parse("http://foo/path?abcd=abc&abc").getQueryParameters("abc"));
746        assertEquals(Arrays.asList("a", "", ""),
747                Uri.parse("http://foo/path?abc=a&abc=&abc").getQueryParameters("abc"));
748        assertEquals(Arrays.asList("a", "", ""),
749                Uri.parse("http://foo/path?abc=a&abc=&abc=").getQueryParameters("abc"));
750    }
751
752    // http://code.google.com/p/android/issues/detail?id=21064
753    public void testPlusCharacterInQuery() {
754        assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c"));
755        assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c"));
756    }
757
758    public void testPathPrefixMatch() {
759        // Exact match
760        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
761                Uri.parse("content://com.example/path/")));
762        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
763                Uri.parse("content://com.example/path")));
764        assertTrue(Uri.parse("content://com.example///path///").isPathPrefixMatch(
765                Uri.parse("content://com.example/path/")));
766        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
767                Uri.parse("content://com.example///path///")));
768
769        // Child match
770        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
771                Uri.parse("content://com.example/path/")));
772        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
773                Uri.parse("content://com.example/path")));
774
775        // Extra parameters
776        assertTrue(Uri.parse("content://com.example/path#fragment").isPathPrefixMatch(
777                Uri.parse("content://com.example/path/")));
778        assertTrue(Uri.parse("content://com.example/path?q=v").isPathPrefixMatch(
779                Uri.parse("content://com.example/path/")));
780        assertTrue(Uri.parse("content://com.example/path/?q=v").isPathPrefixMatch(
781                Uri.parse("content://com.example/path/")));
782
783        // Different path
784        assertFalse(Uri.parse("content://com.example/path").isPathPrefixMatch(
785                Uri.parse("content://com.example/path/deeper/")));
786        assertFalse(Uri.parse("content://com.example/path2").isPathPrefixMatch(
787                Uri.parse("content://com.example/path")));
788
789        // Top-level match
790        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
791                Uri.parse("content://com.example/")));
792        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
793                Uri.parse("content://com.example")));
794
795        // Different prefixes
796        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
797                Uri.parse("file://com.example/path/")));
798        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
799                Uri.parse("content://org.example/path/")));
800
801        // Escaping
802        assertTrue(Uri.parse("content://com.example/path path/").isPathPrefixMatch(
803                Uri.parse("content://com.example/path%20path/")));
804        assertFalse(Uri.parse("content://com.example/path/path").isPathPrefixMatch(
805                Uri.parse("content://com.example/path%2Fpath")));
806    }
807}
808