UrlEncodingTest.java revision 32559028b14b9b321b10eede050afd554a376569
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 public void testDecodingNonUsDigits() throws Exception { 173 try { 174 new URI("http://foo#" + "%\u0664\u0661"); 175 fail(); 176 } catch (URISyntaxException expected) { 177 } 178 try { 179 URLDecoder.decode("%\u0664\u0661"); 180 fail(); // RI fails this test returning "A" 181 } catch (IllegalArgumentException expected) { 182 } 183 } 184 185 /** 186 * Android's URLEncoder.encode() failed for surrogate pairs, encoding them 187 * as two replacement characters ("??"). http://b/3436051 188 */ 189 public void testUrlEncoderEncodesNonPrintableNonAsciiCharacters() throws Exception { 190 assertEquals("%00", URLEncoder.encode("\u0000", "UTF-8")); 191 assertEquals("%00", URLEncoder.encode("\u0000")); 192 assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC", "UTF-8")); 193 assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC")); 194 assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f", "UTF-8")); 195 assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f")); 196 } 197 198 public void testUriDoesNotEncodeNonPrintableNonAsciiCharacters() throws Exception { 199 assertEquals("\u20AC", new URI("http", "foo", "/", "\u20AC").getRawFragment()); 200 assertEquals("\ud842\udf9f", new URI("http", "foo", "/", "\ud842\udf9f").getRawFragment()); 201 } 202 203 public void testUriEncodesControlCharacters() throws Exception { 204 assertEquals("%01", new URI("http", "foo", "/", "\u0001").getRawFragment()); 205 206 // The RI fails this, encoding \u0001 but not \u0000 207 assertEquals("%00", new URI("http", "foo", "/", "\u0000").getRawFragment()); 208 } 209 210 /** 211 * Asserts that {@code original} decodes to {@code decoded} using both URI 212 * and UrlDecoder. 213 */ 214 private void assertDecoded(String decoded, String original) throws Exception { 215 assertEquals(decoded, new URI("http://foo#" + original).getFragment()); 216 assertEquals(decoded, URLDecoder.decode(original)); 217 assertEquals(decoded, URLDecoder.decode(original, "UTF-8")); 218 } 219 220 /** 221 * Asserts that {@code original} encodes to {@code encoded} using both URI 222 * and URLEncoder. 223 */ 224 private void assertEncoded(String encoded, String original) throws Exception { 225 assertEquals(encoded, URLEncoder.encode(original, "UTF-8")); 226 assertEquals(encoded, URLEncoder.encode(original)); 227 assertEquals(encoded, new URI("http", "foo", "/", original).getRawFragment()); 228 } 229} 230