Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2015 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 
     17 package libcore.libcore.net;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import java.net.URISyntaxException;
     22 import java.nio.charset.StandardCharsets;
     23 import libcore.net.UriCodec;
     24 
     25 /**
     26  * Tests for {@link UriCodec}
     27  */
     28 public class UriCodecTest extends TestCase {
     29     private static final UriCodec CODEC = new UriCodec() {
     30         @Override
     31         protected boolean isRetained(char c) {
     32             return c == '$';
     33         }
     34     };
     35 
     36     private static final String VALID_ENCODED_STRING = "a0b$CD%01a%23b%45c%67%89%abd%cd%efq";
     37 
     38     public void testValidate_stringOK_passes() throws Exception {
     39         assertEquals(
     40                 VALID_ENCODED_STRING,
     41                 CODEC.validate(
     42                         VALID_ENCODED_STRING, 0, VALID_ENCODED_STRING.length(), "test OK string"));
     43     }
     44 
     45     // Hex codes in upper case are valid as well.
     46     public void testValidate_stringUppercaseOK_passes() throws Exception {
     47         String stringOKUpperCase = VALID_ENCODED_STRING.toUpperCase();
     48         CODEC.validate(stringOKUpperCase, 0, stringOKUpperCase.length(), "test OK UC string");
     49     }
     50 
     51     // Characters before the start index are ignored.
     52     public void testValidate_wrongCharsBeforeStart_passes() throws Exception {
     53         assertEquals(VALID_ENCODED_STRING, CODEC.validate(
     54                 "%p" + VALID_ENCODED_STRING,
     55                 2,
     56                 VALID_ENCODED_STRING.length() + 2,
     57                 "test string"));
     58     }
     59 
     60     // Fails with character 'p', invalid after '%'
     61     public void testValidate_wrongCharsAtStart_fails() throws Exception {
     62         try {
     63             CODEC.validate(
     64                     "%p" + VALID_ENCODED_STRING,
     65                     0,
     66                     VALID_ENCODED_STRING.length() + 2,
     67                     "test string");
     68             fail("Expected URISyntaxException");
     69         } catch (URISyntaxException expected) {
     70             // Expected.
     71         }
     72     }
     73 
     74     // Fails with character 'p', invalid after '%'
     75     public void testValidate_wrongCharsBeyondEnd_passes() throws Exception {
     76         assertEquals(VALID_ENCODED_STRING, CODEC.validate(
     77                 VALID_ENCODED_STRING + "%p",
     78                 0,
     79                 VALID_ENCODED_STRING.length(),
     80                 "test string"));
     81     }
     82 
     83     // Fails with character 'p', invalid after '%'
     84     public void testValidate_wrongCharsAtEnd_fails() throws Exception {
     85         try {
     86             CODEC.validate(
     87                     VALID_ENCODED_STRING + "%p",
     88                     0,
     89                     VALID_ENCODED_STRING.length() + 2,
     90                     "test string");
     91             fail("Expected URISyntaxException");
     92         } catch (URISyntaxException expected) {
     93             // Expected.
     94         }
     95     }
     96 
     97     public void testValidate_secondDigitWrong_fails() throws Exception {
     98         try {
     99             CODEC.validate(
    100                     VALID_ENCODED_STRING + "%1p",
    101                     0,
    102                     VALID_ENCODED_STRING.length() + 2,
    103                     "test string");
    104             fail("Expected URISyntaxException");
    105         } catch (URISyntaxException expected) {
    106             // Expected.
    107         }
    108     }
    109 
    110     public void testValidate_emptyString_passes() throws Exception {
    111         assertEquals("", CODEC.validate("", 0, 0, "empty string"));
    112     }
    113 
    114     public void testValidate_stringEndingWithPercent_fails() throws Exception {
    115         try {
    116             CODEC.validate("a%", 0, 0, "a% string");
    117         } catch (URISyntaxException expected) {
    118             // Expected.
    119         }
    120     }
    121 
    122     public void testValidate_stringEndingWithPercentAndSingleDigit_fails() throws Exception {
    123         try {
    124             CODEC.validate("a%1", 0, 0, "a%1 string");
    125         } catch (URISyntaxException expected) {
    126             // Expected.
    127         }
    128     }
    129 
    130     public void testValidateSimple_stringOK_passes() throws Exception {
    131         UriCodec.validateSimple(VALID_ENCODED_STRING, "$%");
    132     }
    133 
    134     // Hex codes in upper case are valid as well.
    135     public void testValidateSimple_stringUppercaseOK_passes() throws Exception {
    136         UriCodec.validateSimple(VALID_ENCODED_STRING.toUpperCase(), "$%");
    137     }
    138 
    139     // Fails with character 'p', invalid after '%'
    140     public void testValidateSimple_wrongCharsAtStart_fails() throws Exception {
    141         try {
    142             UriCodec.validateSimple("%/" + VALID_ENCODED_STRING, "$%");
    143             fail("Expected URISyntaxException");
    144         } catch (URISyntaxException expected) {
    145             // Expected.
    146         }
    147     }
    148 
    149     // Fails with character 'p', invalid after '%'
    150     public void testValidateSimple_wrongCharsAtEnd_fails() throws Exception {
    151         try {
    152             UriCodec.validateSimple(VALID_ENCODED_STRING + "%/", "$%");
    153             fail("Expected URISyntaxException");
    154         } catch (URISyntaxException expected) {
    155             // Expected.
    156         }
    157     }
    158 
    159     public void testValidateSimple_emptyString_passes() throws Exception {
    160         UriCodec.validateSimple("", "$%");
    161     }
    162 
    163     public void testValidateSimple_stringEndingWithPercent_passes() throws Exception {
    164         UriCodec.validateSimple("a%", "$%");
    165     }
    166 
    167     public void testValidateSimple_stringEndingWithPercentAndSingleDigit_passes() throws Exception {
    168         UriCodec.validateSimple("a%1", "$%");
    169     }
    170 
    171     public void testEncode_emptyString_returnsEmptyString() {
    172         assertEquals("", CODEC.encode("", StandardCharsets.UTF_8));
    173     }
    174 
    175     public void testEncode() {
    176         assertEquals("ab%2F$%C4%82%2512", CODEC.encode("ab/$\u0102%12", StandardCharsets.UTF_8));
    177     }
    178 
    179     public void testEncode_convertWhitespace() {
    180         // Whitespace is not retained, output %20.
    181         assertEquals("ab%2F$%C4%82%2512%20",
    182                 CODEC.encode("ab/$\u0102%12 ", StandardCharsets.UTF_8));
    183 
    184         UriCodec withWhitespaceRetained = new UriCodec() {
    185             @Override
    186             protected boolean isRetained(char c) {
    187                 return c == '$' || c == ' ';
    188             }
    189         };
    190         // Whitespace is retained, convert to plus.
    191         assertEquals("ab%2F$%C4%82%2512+",
    192                 withWhitespaceRetained.encode("ab/$\u0102%12 ", StandardCharsets.UTF_8));
    193     }
    194 
    195     /** Confirm that '%' can be retained, disabling '%' encoding. http://b/24806835 */
    196     public void testEncode_percentRetained() {
    197         UriCodec withPercentRetained = new UriCodec() {
    198             @Override
    199             protected boolean isRetained(char c) {
    200                 return c == '%';
    201             }
    202         };
    203         // Percent is retained
    204         assertEquals("ab%34%20", withPercentRetained.encode("ab%34 ", StandardCharsets.UTF_8));
    205     }
    206 
    207     public void testEncode_partially_returnsPercentUnchanged() {
    208         StringBuilder stringBuilder = new StringBuilder();
    209         // Check it's really appending instead of returning a new builder.
    210         stringBuilder.append("pp");
    211         CODEC.appendPartiallyEncoded(stringBuilder, "ab/$\u0102%");
    212         // Returns % at the end instead of %25.
    213         assertEquals("ppab%2F$%C4%82%", stringBuilder.toString());
    214     }
    215 
    216     public void testEncode_partially_returnsCharactersAfterPercentEncoded() {
    217         StringBuilder stringBuilder = new StringBuilder();
    218         // Check it's really appending instead of returning a new builder.
    219         stringBuilder.append("pp");
    220         CODEC.appendPartiallyEncoded(stringBuilder, "ab/$\u0102%\u0102");
    221         // Returns %C4%82 at the end.
    222         assertEquals("ppab%2F$%C4%82%%C4%82", stringBuilder.toString());
    223     }
    224 
    225     public void testEncode_partially_returnsDigitsAfterPercentUnchanged() {
    226         StringBuilder stringBuilder = new StringBuilder();
    227         // Check it's really appending instead of returning a new builder.
    228         stringBuilder.append("pp");
    229         CODEC.appendPartiallyEncoded(stringBuilder, "ab/$\u0102%38");
    230         // Returns %38 at the end.
    231         assertEquals("ppab%2F$%C4%82%38", stringBuilder.toString());
    232     }
    233 
    234     // Last character needs encoding (make sure we are flushing the buffer with chars to encode).
    235     public void testEncode_lastCharacter() {
    236         assertEquals("ab%2F$%C4%82%25%E0%A1%80",
    237                 CODEC.encode("ab/$\u0102%\u0840", StandardCharsets.UTF_8));
    238     }
    239 
    240     // Last character needs encoding (make sure we are flushing the buffer with chars to encode).
    241     public void testEncode_flushBufferBeforePlusFromSpace() {
    242         UriCodec withSpaceRetained = new UriCodec() {
    243             @Override
    244             protected boolean isRetained(char c) {
    245                 return c == ' ';
    246             }
    247         };
    248         assertEquals("%2F+",
    249                 withSpaceRetained.encode("/ ", StandardCharsets.UTF_8));
    250     }
    251 
    252     public void testDecode_emptyString_returnsEmptyString() {
    253         assertEquals("", UriCodec.decode(""));
    254     }
    255 
    256     public void testDecode_wrongHexDigit_fails() {
    257         try {
    258             // %p in the end.
    259             UriCodec.decode("ab%2f$%C4%82%25%e0%a1%80%p");
    260             fail("Expected URISyntaxException");
    261         } catch (IllegalArgumentException expected) {
    262             // Expected.
    263         }
    264     }
    265 
    266     public void testDecode_secondHexDigitWrong_fails() {
    267         try {
    268             // %1p in the end.
    269             UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%1p");
    270             fail("Expected URISyntaxException");
    271         } catch (IllegalArgumentException expected) {
    272             // Expected.
    273         }
    274     }
    275 
    276     public void testDecode_endsWithPercent_fails() {
    277         try {
    278             // % in the end.
    279             UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%");
    280             fail("Expected URISyntaxException");
    281         } catch (IllegalArgumentException expected) {
    282             // Expected.
    283         }
    284     }
    285 
    286     public void testDecode_dontThrowException_appendsUnknownCharacter() {
    287         assertEquals("ab/$\u0102%\u0840\ufffd",
    288                 UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%",
    289                         false /* convertPlus */,
    290                         StandardCharsets.UTF_8,
    291                         false /* throwOnFailure */));
    292     }
    293 
    294     public void testDecode_convertPlus() {
    295         assertEquals("ab/$\u0102% \u0840",
    296                 UriCodec.decode("ab%2f$%c4%82%25+%e0%a1%80",
    297                         true /* convertPlus */,
    298                         StandardCharsets.UTF_8,
    299                         false /* throwOnFailure */));
    300     }
    301 
    302     // Last character needs decoding (make sure we are flushing the buffer with chars to decode).
    303     public void testDecode_lastCharacter() {
    304         assertEquals("ab/$\u0102%\u0840",
    305                 UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80"));
    306     }
    307 
    308     // Check that a second row of encoded characters is decoded properly (internal buffers are
    309     // reset properly).
    310     public void testDecode_secondRowOfEncoded() {
    311         assertEquals("ab/$\u0102%\u0840aa\u0840",
    312                 UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80"));
    313     }
    314 }
    315