1 /*
   2  * Copyright (c) 2005, 2020, 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 /*
  25  * @test
  26  * @summary Unit test for jdk.internal.icu.text.StringPrep
  27  * @bug 4737170 8060097 8174270
  28  * @modules java.base/jdk.internal.icu.text
  29  * @library .
  30  * @compile -XDignore.symbol.file TestStringPrep.java NFS4StringPrep.java
  31  *     TestData.java
  32  * @run main/othervm -ea TestStringPrep
  33  * @author Edward Wang
  34  */
  35 /*
  36  *******************************************************************************
  37  * Copyright (C) 2003-2004, International Business Machines Corporation and    *
  38  * others. All Rights Reserved.                                                *
  39  *******************************************************************************
  40 */
  41 
  42 import java.text.ParseException;
  43 import java.io.InputStream;
  44 import java.util.Locale;
  45 
  46 import jdk.internal.icu.text.StringPrep;
  47 import jdk.internal.icu.text.UCharacterIterator;
  48 
  49 public class TestStringPrep {
  50     public static void main(String[] args) throws Exception {
  51         TestNFS4MixedPrep();
  52         TestCISPrep();
  53         TestCSPrep();
  54         TestNamePrepConformance();
  55     }
  56     /*
  57        There are several special identifiers ("who") which need to be
  58        understood universally, rather than in the context of a particular
  59        DNS domain.  Some of these identifiers cannot be understood when an
  60        NFS client accesses the server, but have meaning when a local process
  61        accesses the file.  The ability to display and modify these
  62        permissions is permitted over NFS, even if none of the access methods
  63        on the server understands the identifiers.
  64 
  65         Who                    Description
  66        _______________________________________________________________
  67 
  68        "OWNER"                The owner of the file.
  69        "GROUP"                The group associated with the file.
  70        "EVERYONE"             The world.
  71        "INTERACTIVE"          Accessed from an interactive terminal.
  72        "NETWORK"              Accessed via the network.
  73        "DIALUP"               Accessed as a dialup user to the server.
  74        "BATCH"                Accessed from a batch job.
  75        "ANONYMOUS"            Accessed without any authentication.
  76        "AUTHENTICATED"        Any authenticated user (opposite of
  77                               ANONYMOUS)
  78        "SERVICE"              Access from a system service.
  79 
  80        To avoid conflict, these special identifiers are distinguish by an
  81        appended "@" and should appear in the form "xxxx@" (note: no domain
  82        name after the "@").  For example: ANONYMOUS@.
  83     */
  84     private static String[] mixed_prep_data ={
  85         "OWNER@",
  86         "GROUP@",
  87         "EVERYONE@",
  88         "INTERACTIVE@",
  89         "NETWORK@",
  90         "DIALUP@",
  91         "BATCH@",
  92         "ANONYMOUS@",
  93         "AUTHENTICATED@",
  94         "\u0930\u094D\u092E\u094D\u0915\u094D\u0937\u0947\u0924\u094D@slip129-37-118-146.nc.us.ibm.net",
  95         "\u0936\u094d\u0930\u0940\u092e\u0926\u094d@saratoga.pe.utexas.edu",
  96         "\u092d\u0917\u0935\u0926\u094d\u0917\u0940\u0924\u093e@dial-120-45.ots.utexas.edu",
  97         "\u0905\u0927\u094d\u092f\u093e\u092f@woo-085.dorms.waller.net",
  98         "\u0905\u0930\u094d\u091c\u0941\u0928@hd30-049.hil.compuserve.com",
  99         "\u0935\u093f\u0937\u093e\u0926@pem203-31.pe.ttu.edu",
 100         "\u092f\u094b\u0917@56K-227.MaxTNT3.pdq.net",
 101         "\u0927\u0943\u0924\u0930\u093e\u0937\u094d\u091f\u094d\u0930@dial-36-2.ots.utexas.edu",
 102         "\u0909\u0935\u093E\u091A\u0943@slip129-37-23-152.ga.us.ibm.net",
 103         "\u0927\u0930\u094d\u092e\u0915\u094d\u0937\u0947\u0924\u094d\u0930\u0947@ts45ip119.cadvision.com",
 104         "\u0915\u0941\u0930\u0941\u0915\u094d\u0937\u0947\u0924\u094d\u0930\u0947@sdn-ts-004txaustP05.dialsprint.net",
 105         "\u0938\u092e\u0935\u0947\u0924\u093e@bar-tnt1s66.erols.com",
 106         "\u092f\u0941\u092f\u0941\u0924\u094d\u0938\u0935\u0903@101.st-louis-15.mo.dial-access.att.net",
 107         "\u092e\u093e\u092e\u0915\u093e\u0903@h92-245.Arco.COM",
 108         "\u092a\u093e\u0923\u094d\u0921\u0935\u093e\u0936\u094d\u091a\u0948\u0935@dial-13-2.ots.utexas.edu",
 109         "\u0915\u093f\u092e\u0915\u0941\u0930\u094d\u0935\u0924@net-redynet29.datamarkets.com.ar",
 110         "\u0938\u0902\u091c\u0935@ccs-shiva28.reacciun.net.ve",
 111         "\u0c30\u0c18\u0c41\u0c30\u0c3e\u0c2e\u0c4d@7.houston-11.tx.dial-access.att.net",
 112         "\u0c35\u0c3f\u0c36\u0c4d\u0c35\u0c28\u0c3e\u0c27@ingw129-37-120-26.mo.us.ibm.net",
 113         "\u0c06\u0c28\u0c02\u0c26\u0c4d@dialup6.austintx.com",
 114         "\u0C35\u0C26\u0C4D\u0C26\u0C3F\u0C30\u0C3E\u0C1C\u0C41@dns2.tpao.gov.tr",
 115         "\u0c30\u0c3e\u0c1c\u0c40\u0c35\u0c4d@slip129-37-119-194.nc.us.ibm.net",
 116         "\u0c15\u0c36\u0c30\u0c2c\u0c3e\u0c26@cs7.dillons.co.uk.203.119.193.in-addr.arpa",
 117         "\u0c38\u0c02\u0c1c\u0c40\u0c35\u0c4d@swprd1.innovplace.saskatoon.sk.ca",
 118         "\u0c15\u0c36\u0c30\u0c2c\u0c3e\u0c26@bikini.bologna.maraut.it",
 119         "\u0c38\u0c02\u0c1c\u0c40\u0c2c\u0c4d@node91.subnet159-198-79.baxter.com",
 120         "\u0c38\u0c46\u0c28\u0c4d\u0c17\u0c41\u0c2a\u0c4d\u0c24@cust19.max5.new-york.ny.ms.uu.net",
 121         "\u0c05\u0c2e\u0c30\u0c47\u0c02\u0c26\u0c4d\u0c30@balexander.slip.andrew.cmu.edu",
 122         "\u0c39\u0c28\u0c41\u0c2e\u0c3e\u0c28\u0c41\u0c32@pool029.max2.denver.co.dynip.alter.net",
 123         "\u0c30\u0c35\u0c3f@cust49.max9.new-york.ny.ms.uu.net",
 124         "\u0c15\u0c41\u0c2e\u0c3e\u0c30\u0c4d@s61.abq-dialin2.hollyberry.com",
 125         "\u0c35\u0c3f\u0c36\u0c4d\u0c35\u0c28\u0c3e\u0c27@\u0917\u0928\u0947\u0936.sanjose.ibm.com",
 126         "\u0c06\u0c26\u0c3f\u0c24\u0c4d\u0c2f@www.\u00E0\u00B3\u00AF.com",
 127         "\u0C15\u0C02\u0C26\u0C4D\u0C30\u0C47\u0C17\u0C41\u0c32@www.\u00C2\u00A4.com",
 128         "\u0c36\u0c4d\u0c30\u0c40\u0C27\u0C30\u0C4D@www.\u00C2\u00A3.com",
 129         "\u0c15\u0c02\u0c1f\u0c2e\u0c36\u0c46\u0c1f\u0c4d\u0c1f\u0c3f@\u0025",
 130         "\u0c2e\u0c3e\u0c27\u0c35\u0c4d@\u005C\u005C",
 131         "\u0c26\u0c46\u0c36\u0c46\u0c1f\u0c4d\u0c1f\u0c3f@www.\u0021.com",
 132         "test@www.\u0024.com",
 133         "help@\u00C3\u00BC.com",
 134     };
 135     public static void TestNFS4MixedPrep(){
 136         for(int i=0; i< mixed_prep_data.length; i++){
 137             try{
 138                 String src = mixed_prep_data[i];
 139                 byte[] dest = NFS4StringPrep.mixed_prepare(src.getBytes("UTF-8"));
 140                 String destString = new String(dest, "UTF-8");
 141                 int destIndex = destString.indexOf('@');
 142                 if(destIndex < 0){
 143                     fail("Delimiter @ disappeared from the output!");
 144                 }
 145             }catch(Exception e){
 146                 fail("mixed_prepare for string: " + mixed_prep_data[i] +" failed with " + e.toString());
 147             }
 148         }
 149         /* test the error condition */
 150         {
 151             String src = "OWNER@oss.software.ibm.com";
 152             try{
 153                 byte[] dest = NFS4StringPrep.mixed_prepare(src.getBytes("UTF-8"));
 154                 if(dest!=null){
 155                     fail("Did not get the expected exception");
 156                 }
 157             }catch(Exception e){
 158                 System.out.println("mixed_prepare for string: " + src +" passed with " + e.toString());
 159             }
 160 
 161          }
 162     }
 163     public static void TestCISPrep(){
 164 
 165         for(int i=0;i< (TestData.conformanceTestCases.length);i++){
 166             TestData.ConformanceTestCase testCase = TestData.conformanceTestCases[i];
 167             String src = testCase.input;
 168             Exception expected = testCase.expected;
 169             String expectedDest = testCase.output;
 170             try{
 171                 byte[] dest =NFS4StringPrep.cis_prepare(src.getBytes("UTF-8"));
 172                 String destString = new String(dest, "UTF-8");
 173                 if(!expectedDest.equalsIgnoreCase(destString)){
 174                       fail("Did not get the expected output for nfs4_cis_prep at index " + i);
 175                 }
 176             }catch(Exception e){
 177                 if(!((expected instanceof ParseException) && (e instanceof ParseException))) {
 178                     fail("Did not get the expected exception");
 179                 }
 180             }
 181 
 182         }
 183     }
 184 
 185     public static void TestCSPrep(){
 186 
 187         // Checking for bidi is turned off
 188         String src = "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774\u0644\u064A\u0647\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74";
 189         try{
 190             NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), false);
 191         }catch(Exception e){
 192             fail("Got unexpected exception: " + e.toString());
 193         }
 194 
 195         // normalization is turned off
 196         try{
 197             src = "www.\u00E0\u00B3\u00AF.com";
 198             byte[] dest = NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), false);
 199             String destStr = new String(dest, "UTF-8");
 200             if(!src.equals(destStr)){
 201                 fail("Did not get expected output. Expected: "+ prettify(src)+
 202                       " Got: " + prettify(destStr));
 203             }
 204         }catch(Exception e){
 205             fail("Got unexpected exception: " + e.toString());
 206         }
 207 
 208         // test case insensitive string
 209         try{
 210             src = "THISISATEST";
 211             byte[] dest = NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), false);
 212             String destStr = new String(dest, "UTF-8");
 213             if(!src.toLowerCase(Locale.ROOT).equals(destStr)){
 214                 fail("Did not get expected output. Expected: "+ prettify(src)+
 215                       " Got: " + prettify(destStr));
 216             }
 217         }catch(Exception e){
 218             fail("Got unexpected exception: " + e.toString());
 219         }
 220         // test case sensitive string
 221         try{
 222             src = "THISISATEST";
 223             byte[] dest = NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), true);
 224             String destStr = new String(dest, "UTF-8");
 225             if(!src.equals(destStr)){
 226                 fail("Did not get expected output. Expected: "+ prettify(src)+
 227                       " Got: " + prettify(destStr));
 228             }
 229         }catch(Exception e){
 230             fail("Got unexpected exception: " + e.toString());
 231         }
 232     }
 233 
 234     public static void TestNamePrepConformance() throws Exception {
 235         InputStream stream = StringPrep.class.getModule()
 236                                              .getResourceAsStream("sun/net/idn/uidna.spp");
 237         StringPrep namePrep = new StringPrep(stream);
 238         stream.close();
 239         int i;
 240         for(i=0; i<TestData.conformanceTestCases.length;i++){
 241             TestData.ConformanceTestCase testCase = TestData.conformanceTestCases[i];
 242             try{
 243                 UCharacterIterator iter = UCharacterIterator.getInstance(testCase.input);
 244                 StringBuffer output = namePrep.prepare(iter, testCase.flags);
 245                 if(testCase.output !=null && output!=null && !testCase.output.equals(output.toString())){
 246                     fail("Did not get the expected output. Expected: " + prettify(testCase.output)+
 247                             " Got: "+ prettify(output.toString()) );
 248                 }
 249             } catch(ParseException ex) {
 250                 if (testCase.expected == null) {
 251                     fail("get the unexpected exception for source: " +testCase.input +" Got:  "+ ex.toString());
 252                 }
 253             }
 254         }
 255         System.out.println("Nameprep test count: " + i);
 256     }
 257 
 258     private static void fail(String msg) {
 259         throw new RuntimeException(msg);
 260     }
 261 
 262     private static String prettify(String s) {
 263         StringBuffer result = new StringBuffer();
 264         for (int i = 0; i < s.length(); ++i) {
 265             char ch =s.charAt(i);
 266             if(ch > 0x7f){
 267                 result.append("\\u");
 268                 result.append(hex(ch));
 269             }else{
 270                 result.append(ch);
 271             }
 272 
 273         }
 274         return result.toString();
 275     }
 276 
 277     private static String hex(char ch) {
 278         StringBuffer result = new StringBuffer();
 279         String foo = Integer.toString(ch,16).toUpperCase(Locale.ROOT);
 280         for (int i = foo.length(); i < 4; ++i) {
 281             result.append('0');
 282         }
 283         return result + foo;
 284     }
 285 }