1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.net.URLDecoder;
  25 import java.net.URLEncoder;
  26 import java.nio.charset.StandardCharsets;
  27 import org.testng.Assert;
  28 import org.testng.annotations.DataProvider;
  29 import org.testng.annotations.Test;
  30 
  31 /**
  32  * @test
  33  * @bug 8183743
  34  * @summary Test to verify the new overload method with Charset functions the
  35  * same as the existing method that takes a charset name.
  36  * @run testng EncodingTest
  37  */
  38 public class EncodingTest {
  39     public static enum ParameterType {
  40         STRING,
  41         CHARSET
  42     }
  43 
  44     @DataProvider(name = "illegalArgument")
  45     public Object[][] getParameters() {
  46         return new Object[][]{
  47             {ParameterType.STRING},
  48             {ParameterType.CHARSET}
  49         };
  50     }
  51 
  52     @DataProvider(name = "decode")
  53     public Object[][] getDecodeParameters() {
  54         return new Object[][]{
  55             {"The string \u00FC@foo-bar"},
  56             // the string from javadoc example
  57 
  58             {""}, // an empty string
  59 
  60             {"x"}, // a string of length 1
  61 
  62             {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.*"},
  63             // the string of characters should remain the same
  64 
  65             {charactersRange('\u0000', '\u007F')},
  66             // a string of characters from 0 to 127
  67 
  68             {charactersRange('\u0080', '\u00FF')},
  69             // a string of characters from 128 to 255
  70 
  71             {"\u0100 \u0101 \u0555 \u07FD \u07FF"},
  72             // a string of Unicode values can be expressed as 2 bytes
  73 
  74             {"\u8000 \u8001 \uA000 \uFFFD \uFFFF"}, // a string of Unicode values can be expressed as 3 bytes
  75         };
  76     }
  77 
  78     /**
  79      * Verifies that IAE is thrown when decoding an invalid string using the
  80      * existing method or the new overload method.
  81      *
  82      * @param type the type of the argument, e.g a String charset name or
  83      * charset
  84      */
  85     @Test(dataProvider = "illegalArgument", expectedExceptions = IllegalArgumentException.class)
  86     public void testIllegalArgument(ParameterType type) throws Exception {
  87         String encoded = URLEncoder.encode("http://www.xyz.com/find?key=\u0100\u0101",
  88                 StandardCharsets.UTF_8.name());
  89         String illegal = "%" + encoded;
  90         String returned;
  91         if (type == ParameterType.STRING) {
  92             returned = URLDecoder.decode(illegal, StandardCharsets.UTF_8.name());
  93         } else {
  94             returned = URLDecoder.decode(illegal, StandardCharsets.UTF_8);
  95         }
  96     }
  97 
  98     /**
  99      * Verifies that the returned values of decoding with the existing
 100      * and the overload methods match.
 101      *
 102      * @param s the string to be encoded and then decoded with both existing
 103      * and the overload methods.
 104      * @throws Exception
 105      */
 106     @Test(dataProvider = "decode")
 107     public void decode(String s) throws Exception {
 108         String encoded = URLEncoder.encode(s, StandardCharsets.UTF_8.name());
 109         String returned1 = URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
 110         String returned2 = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
 111         Assert.assertEquals(returned1, returned2);
 112     }
 113 
 114     String charactersRange(char c1, char c2) {
 115         StringBuilder sb = new StringBuilder(c2 - c1);
 116         for (char c = c1; c < c2; c++) {
 117             sb.append(c);
 118         }
 119 
 120         return sb.toString();
 121     }
 122 }