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