UrlEncodingTest.java revision 56099d23fcb002b164bff8fb7f14d6ec0453509e
1/*
2 * Copyright (C) 2011 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 libcore.java.net;
18
19import java.io.UnsupportedEncodingException;
20import java.net.URI;
21import java.net.URISyntaxException;
22import java.net.URLDecoder;
23import java.net.URLEncoder;
24import java.nio.charset.IllegalCharsetNameException;
25import java.nio.charset.UnsupportedCharsetException;
26import junit.framework.TestCase;
27
28public final class UrlEncodingTest extends TestCase {
29
30    public void testUriRetainsOriginalEncoding() throws Exception {
31        assertEquals("%61", new URI("http://foo#%61").getRawFragment());
32    }
33
34    /**
35     * URLDecoder and URI disagree on what '+' should decode to.
36     */
37    public void testDecodingPlus() throws Exception {
38        assertEquals("a b", URLDecoder.decode("a+b"));
39        assertEquals("a b", URLDecoder.decode("a+b", "UTF-8"));
40        assertEquals("a+b", new URI("http://foo#a+b").getFragment());
41    }
42
43    public void testEncodingPlus() throws Exception {
44        assertEquals("a%2Bb", URLEncoder.encode("a+b"));
45        assertEquals("a%2Bb", URLEncoder.encode("a+b", "UTF-8"));
46        assertEquals("a+b", new URI("http", "foo", "/", "a+b").getRawFragment());
47    }
48
49    public void testDecodingSpace() throws Exception {
50        assertEquals("a b", URLDecoder.decode("a b"));
51        assertEquals("a b", URLDecoder.decode("a b", "UTF-8"));
52        try {
53            new URI("http://foo#a b");
54            fail();
55        } catch (URISyntaxException expected) {
56        }
57    }
58
59    public void testEncodingSpace() throws Exception {
60        assertEquals("a+b", URLEncoder.encode("a b"));
61        assertEquals("a+b", URLEncoder.encode("a b", "UTF-8"));
62        assertEquals("a%20b", new URI("http", "foo", "/", "a b").getRawFragment());
63    }
64
65    public void testUriDecodingPartial() throws Exception {
66        try {
67            new URI("http://foo#%");
68            fail();
69        } catch (URISyntaxException expected) {
70        }
71        try {
72            new URI("http://foo#%0");
73            fail();
74        } catch (URISyntaxException expected) {
75        }
76    }
77
78    public void testUrlDecoderDecodingPartial() throws Exception {
79        try {
80            URLDecoder.decode("%");
81            fail();
82        } catch (IllegalArgumentException expected) {
83        }
84        try {
85            URLDecoder.decode("%0");
86            fail();
87        } catch (IllegalArgumentException expected) {
88        }
89    }
90
91    public void testUriDecodingInvalid() {
92        try {
93            new URI("http://foo#%0g");
94            fail();
95        } catch (URISyntaxException expected) {
96        }
97    }
98
99    public void testUrlDecoderDecodingInvalid() {
100        try {
101            URLDecoder.decode("%0g");
102            fail();
103        } catch (IllegalArgumentException expected) {
104        }
105    }
106
107    public void testUrlDecoderFailsOnNullCharset() throws Exception {
108        try {
109            URLDecoder.decode("ab", null);
110            fail();
111        } catch (IllegalCharsetNameException expected) {
112        } catch (NullPointerException expected) {
113        }
114    }
115
116    public void testUrlEncoderFailsOnNullCharset() throws Exception {
117        try {
118            URLEncoder.encode("ab", null);
119            fail();
120        } catch (IllegalCharsetNameException expected) {
121        } catch (NullPointerException expected) {
122        }
123    }
124
125    /**
126     * The RI looks up the charset lazily; Android looks it up eagerly. Either
127     * behavior is acceptable.
128     */
129    public void testUrlDecoderIgnoresUnnecessaryCharset() throws Exception {
130        try {
131            assertEquals("ab", URLDecoder.decode("ab", "no-such-charset"));
132            // no fail()
133        } catch (UnsupportedCharsetException expected) {
134        }
135    }
136
137    public void testUrlEncoderFailsOnInvalidCharset() throws Exception {
138        try {
139            URLEncoder.encode("ab", "no-such-charset");
140            fail();
141        } catch (UnsupportedCharsetException expected) {
142        } catch (UnsupportedEncodingException expected) {
143        }
144    }
145
146    public void testDecoding() throws Exception {
147        assertDecoded("a\u0000b", "a%00b");
148        assertDecoded("a b", "a%20b");
149        assertDecoded("a+b", "a%2bb");
150        assertDecoded("a%b", "a%25b");
151        assertDecoded("a\u007fb", "a%7fb");
152    }
153
154    public void testEncoding() throws Exception {
155        assertEncoded("a%25b", "a%b");
156        assertEncoded("a%7Fb", "a\u007fb");
157    }
158
159    public void testDecodingLiterals() throws Exception {
160        assertDecoded("\ud842\udf9f", "\ud842\udf9f");
161    }
162
163    public void testDecodingBrokenUtf8SequenceYieldsReplacementCharacter() throws Exception {
164        assertDecoded("a\ufffdb", "a%ffb");
165    }
166
167    public void testDecodingUtf8Octets() throws Exception {
168        assertDecoded("\u20AC", "%e2%82%ac");
169        assertDecoded("\ud842\udf9f", "%f0%a0%ae%9f");
170    }
171
172    /**
173     * Android's URLEncoder.encode() failed for surrogate pairs, encoding them
174     * as two replacement characters ("??"). http://b/3436051
175     */
176    public void testUrlEncoderEncodesNonPrintableNonAsciiCharacters() throws Exception {
177        assertEquals("%00", URLEncoder.encode("\u0000", "UTF-8"));
178        assertEquals("%00", URLEncoder.encode("\u0000"));
179        assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC", "UTF-8"));
180        assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC"));
181        assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f", "UTF-8"));
182        assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f"));
183    }
184
185    public void testUriDoesNotEncodeNonPrintableNonAsciiCharacters() throws Exception {
186        assertEquals("\u20AC", new URI("http", "foo", "/", "\u20AC").getRawFragment());
187        assertEquals("\ud842\udf9f", new URI("http", "foo", "/", "\ud842\udf9f").getRawFragment());
188    }
189
190    public void testUriEncodesControlCharacters() throws Exception {
191        assertEquals("%01", new URI("http", "foo", "/", "\u0001").getRawFragment());
192
193        // The RI fails this, encoding \u0001 but not \u0000
194        assertEquals("%00", new URI("http", "foo", "/", "\u0000").getRawFragment());
195    }
196
197    /**
198     * Asserts that {@code original} decodes to {@code decoded} using both URI
199     * and UrlDecoder.
200     */
201    private void assertDecoded(String decoded, String original) throws Exception {
202        assertEquals(decoded, new URI("http://foo#" + original).getFragment());
203        assertEquals(decoded, URLDecoder.decode(original));
204        assertEquals(decoded, URLDecoder.decode(original, "UTF-8"));
205    }
206
207    /**
208     * Asserts that {@code original} encodes to {@code encoded} using both URI
209     * and URLEncoder.
210     */
211    private void assertEncoded(String encoded, String original) throws Exception {
212        assertEquals(encoded, URLEncoder.encode(original, "UTF-8"));
213        assertEquals(encoded, URLEncoder.encode(original));
214        assertEquals(encoded, new URI("http", "foo", "/", original).getRawFragment());
215    }
216}
217