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