| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package libcore.java.net; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URLDecoder; |
| import java.net.URLEncoder; |
| import java.nio.charset.IllegalCharsetNameException; |
| import java.nio.charset.UnsupportedCharsetException; |
| import junit.framework.TestCase; |
| |
| public final class UrlEncodingTest extends TestCase { |
| |
| public void testUriRetainsOriginalEncoding() throws Exception { |
| assertEquals("%61", new URI("http://foo#%61").getRawFragment()); |
| } |
| |
| /** |
| * URLDecoder and URI disagree on what '+' should decode to. |
| */ |
| public void testDecodingPlus() throws Exception { |
| assertEquals("a b", URLDecoder.decode("a+b")); |
| assertEquals("a b", URLDecoder.decode("a+b", "UTF-8")); |
| assertEquals("a+b", new URI("http://foo#a+b").getFragment()); |
| } |
| |
| public void testEncodingPlus() throws Exception { |
| assertEquals("a%2Bb", URLEncoder.encode("a+b")); |
| assertEquals("a%2Bb", URLEncoder.encode("a+b", "UTF-8")); |
| assertEquals("a+b", new URI("http", "foo", "/", "a+b").getRawFragment()); |
| } |
| |
| public void testDecodingSpace() throws Exception { |
| assertEquals("a b", URLDecoder.decode("a b")); |
| assertEquals("a b", URLDecoder.decode("a b", "UTF-8")); |
| try { |
| new URI("http://foo#a b"); |
| fail(); |
| } catch (URISyntaxException expected) { |
| } |
| } |
| |
| public void testEncodingSpace() throws Exception { |
| assertEquals("a+b", URLEncoder.encode("a b")); |
| assertEquals("a+b", URLEncoder.encode("a b", "UTF-8")); |
| assertEquals("a%20b", new URI("http", "foo", "/", "a b").getRawFragment()); |
| } |
| |
| public void testUriDecodingPartial() throws Exception { |
| try { |
| new URI("http://foo#%"); |
| fail(); |
| } catch (URISyntaxException expected) { |
| } |
| try { |
| new URI("http://foo#%0"); |
| fail(); |
| } catch (URISyntaxException expected) { |
| } |
| } |
| |
| public void testUrlDecoderDecodingPartial() throws Exception { |
| try { |
| URLDecoder.decode("%"); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| try { |
| URLDecoder.decode("%0"); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| public void testUriDecodingInvalid() { |
| try { |
| new URI("http://foo#%0g"); |
| fail(); |
| } catch (URISyntaxException expected) { |
| } |
| } |
| |
| public void testUrlDecoderDecodingInvalid() { |
| try { |
| URLDecoder.decode("%0g"); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| public void testUrlDecoderFailsOnNullCharset() throws Exception { |
| try { |
| URLDecoder.decode("ab", null); |
| fail(); |
| } catch (IllegalCharsetNameException expected) { |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testUrlDecoderFailsOnEmptyCharset() { |
| try { |
| URLDecoder.decode("ab", ""); |
| fail(); |
| } catch (IllegalCharsetNameException expected) { |
| } catch (UnsupportedEncodingException expected) { |
| } |
| } |
| |
| public void testUrlEncoderFailsOnNullCharset() throws Exception { |
| try { |
| URLEncoder.encode("ab", null); |
| fail(); |
| } catch (IllegalCharsetNameException expected) { |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testUrlEncoderFailsOnEmptyCharset() { |
| try { |
| URLEncoder.encode("ab", ""); |
| fail(); |
| } catch (IllegalCharsetNameException expected) { |
| } catch (UnsupportedEncodingException expected) { |
| } |
| } |
| |
| /** |
| * The RI looks up the charset lazily; Android looks it up eagerly. Either |
| * behavior is acceptable. |
| */ |
| public void testUrlDecoderIgnoresUnnecessaryCharset() throws Exception { |
| try { |
| assertEquals("ab", URLDecoder.decode("ab", "no-such-charset")); |
| // no fail() |
| } catch (UnsupportedCharsetException expected) { |
| } |
| } |
| |
| public void testUrlEncoderFailsOnInvalidCharset() throws Exception { |
| try { |
| URLEncoder.encode("ab", "no-such-charset"); |
| fail(); |
| } catch (UnsupportedCharsetException expected) { |
| } catch (UnsupportedEncodingException expected) { |
| } |
| } |
| |
| public void testDecoding() throws Exception { |
| assertDecoded("a\u0000b", "a%00b"); |
| assertDecoded("a b", "a%20b"); |
| assertDecoded("a+b", "a%2bb"); |
| assertDecoded("a%b", "a%25b"); |
| assertDecoded("a\u007fb", "a%7fb"); |
| } |
| |
| public void testEncoding() throws Exception { |
| assertEncoded("a%25b", "a%b"); |
| assertEncoded("a%7Fb", "a\u007fb"); |
| } |
| |
| public void testDecodingLiterals() throws Exception { |
| assertDecoded("\ud842\udf9f", "\ud842\udf9f"); |
| } |
| |
| public void testDecodingBrokenUtf8SequenceYieldsReplacementCharacter() throws Exception { |
| assertDecoded("a\ufffdb", "a%ffb"); |
| } |
| |
| public void testDecodingBrokenUtf8SequenceYieldsReplacementCharacterSequence() |
| throws Exception { |
| assertDecoded("a%\ufffd%b", "a%25%ff%25b"); |
| } |
| |
| public void testDecodingUtf8Octets() throws Exception { |
| assertDecoded("\u20AC", "%e2%82%ac"); |
| assertDecoded("\ud842\udf9f", "%f0%a0%ae%9f"); |
| } |
| |
| public void testDecodingNonUsDigits() throws Exception { |
| try { |
| new URI("http://foo#" + "%\u0664\u0661"); |
| fail(); |
| } catch (URISyntaxException expected) { |
| } |
| try { |
| URLDecoder.decode("%\u0664\u0661"); |
| fail(); // RI fails this test returning "A" |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| /** |
| * Android's URLEncoder.encode() failed for surrogate pairs, encoding them |
| * as two replacement characters ("??"). http://b/3436051 |
| */ |
| public void testUrlEncoderEncodesNonPrintableNonAsciiCharacters() throws Exception { |
| assertEquals("%00", URLEncoder.encode("\u0000", "UTF-8")); |
| assertEquals("%00", URLEncoder.encode("\u0000")); |
| assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC", "UTF-8")); |
| assertEquals("%E2%82%AC", URLEncoder.encode("\u20AC")); |
| assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f", "UTF-8")); |
| assertEquals("%F0%A0%AE%9F", URLEncoder.encode("\ud842\udf9f")); |
| } |
| |
| public void testUriDoesNotEncodeNonPrintableNonAsciiCharacters() throws Exception { |
| assertEquals("\u20AC", new URI("http", "foo", "/", "\u20AC").getRawFragment()); |
| assertEquals("\ud842\udf9f", new URI("http", "foo", "/", "\ud842\udf9f").getRawFragment()); |
| } |
| |
| public void testUriEncodesControlCharacters() throws Exception { |
| assertEquals("%01", new URI("http", "foo", "/", "\u0001").getRawFragment()); |
| |
| // The RI fails this, encoding \u0001 but not \u0000 |
| assertEquals("%00", new URI("http", "foo", "/", "\u0000").getRawFragment()); |
| } |
| |
| public void testEncodeAndDecode() throws Exception { |
| assertRoundTrip("http://jcltest.apache.org/test?hl=en&q=te st", |
| "http%3A%2F%2Fjcltest.apache.org%2Ftest%3Fhl%3Den%26q%3Dte+st"); |
| assertRoundTrip ("file://a b/c/d.e-f*g_ l", |
| "file%3A%2F%2Fa+b%2Fc%2Fd.e-f*g_+l"); |
| assertRoundTrip("jar:file://a.jar !/b.c/\u1052", |
| "jar%3Afile%3A%2F%2Fa.jar+%21%2Fb.c%2F%E1%81%92"); |
| assertRoundTrip("ftp://test:pwd@localhost:2121/%D0%9C", |
| "ftp%3A%2F%2Ftest%3Apwd%40localhost%3A2121%2F%25D0%259C"); |
| } |
| |
| /** |
| * Asserts that {@code original} decodes to {@code decoded} using both URI |
| * and UrlDecoder. |
| */ |
| private void assertDecoded(String decoded, String original) throws Exception { |
| assertEquals(decoded, new URI("http://foo#" + original).getFragment()); |
| assertEquals(decoded, URLDecoder.decode(original)); |
| assertEquals(decoded, URLDecoder.decode(original, "UTF-8")); |
| } |
| |
| /** |
| * Asserts that {@code original} encodes to {@code encoded} using both URI |
| * and URLEncoder. |
| */ |
| private void assertEncoded(String encoded, String original) throws Exception { |
| assertEquals(encoded, URLEncoder.encode(original, "UTF-8")); |
| assertEquals(encoded, URLEncoder.encode(original)); |
| assertEquals(encoded, new URI("http", "foo", "/", original).getRawFragment()); |
| } |
| |
| private void assertRoundTrip(String original, String encoded) throws Exception { |
| assertEquals(encoded, URLEncoder.encode(original, "UTF-8")); |
| assertEquals(original, URLDecoder.decode(encoded, "UTF-8")); |
| } |
| } |