1 /*
   2  * Copyright (c) 1999, 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 test Bug 4199484
  27  * @modules jdk.charsets
  28  * @run main ConverterTest
  29  * @bug 4199484 4199599 4199601 4199602 4159519 4201529 4199604 4201532 4947038 6217210
  30 */
  31 
  32 import java.util.*;
  33 import java.io.*;
  34 
  35 /*
  36  * (C) Copyright IBM Corp. 1999 - All Rights Reserved
  37  *
  38  * The original version of this source code and documentation is
  39  * copyrighted and owned by IBM. These materials are provided
  40  * under terms of a License Agreement between IBM and Sun.
  41  * This technology is protected by multiple US and International
  42  * patents. This notice and attribution to IBM may not be removed.
  43  */
  44 public class ConverterTest extends TestFmwk {
  45     public static void main(String[] args) throws Exception {
  46         new ConverterTest().run(args);
  47     }
  48 
  49     public void test4199484() throws Exception {
  50         checkPages(new String[] { "Cp33722" });
  51     }
  52 
  53     public void test4199599() throws Exception {
  54         checkPages(new String[] { "Cp930", "Cp939" });
  55     }
  56 
  57     public void test4199601() throws Exception {
  58         checkPages(new String[] { "Cp942" });
  59     }
  60 
  61     public void test4199602() throws Exception {
  62         checkPages(new String[] { "Cp943" });
  63     }
  64 
  65     public void test6217210() throws Exception {
  66         checkPages(new String[] { "Cp833" });
  67     }
  68 
  69     public void test4159519() throws Exception {
  70         checkPages(new String[] { "Cp037", "Cp1025", "Cp1026", "Cp1112" });
  71         checkPages(new String[] { "Cp1122", "Cp1123", "Cp273", "Cp277" });
  72         checkPages(new String[] { "Cp278", "Cp280", "Cp284", "Cp285" });
  73         checkPages(new String[] { "Cp297", "Cp420", "Cp424", "Cp500" });
  74         checkPages(new String[] { "Cp838", "Cp870", "Cp871", "Cp875" });
  75         checkPages(new String[] { "Cp918", "Cp930", "Cp935", "Cp937" });
  76         checkPages(new String[] { "Cp939" });
  77     }
  78 
  79     public void test4201529() throws Exception {
  80         // Test fallback mapping for U+00B7
  81         byte[] b = new String("\u00B7").getBytes("Cp1381");
  82 
  83         int b1 = b[0] & 0xff;
  84         int b2 = b[1] & 0xff;
  85 
  86         if (b.length != 2 || b1 != 0xa1 || b2 != 0xa4)
  87             errln("Error in Converter: Cp1381");
  88     }
  89 
  90     public void test4199604() throws Exception {
  91         checkPages(new String[] { "Cp970" });
  92     }
  93 
  94     public void test4201532() throws Exception {
  95         checkPages(new String[] { "Cp1383" });
  96     }
  97 
  98     private static class Parameter {
  99         public final String value;
 100         public final boolean statefull;
 101         private final Vector nativeValues = new Vector();
 102         private final Vector unicodeValues = new Vector();
 103 
 104         public Parameter(final String param) throws IOException {
 105             final int ndx = param.indexOf(":");
 106             if (ndx >= 0) {
 107                 value = param.substring(0, ndx);
 108             } else {
 109                 value = param;
 110             }
 111             final String args = (ndx < 0) ? "" : param.substring(ndx+1);
 112             boolean isStatefull = false;
 113             for (int i = 0; i < args.length(); i++) {
 114                 final char flag = args.charAt(i);
 115                 switch (flag) {
 116                 case 's':
 117                     isStatefull = true;
 118                     break;
 119                 default:
 120                 }
 121             }
 122 
 123             final String fileName = value+".b2c";
 124             final FileReader f = new FileReader(new File(System.getProperty("test.src", "."), fileName));
 125             final BufferedReader in = new BufferedReader(f);
 126             String line = in.readLine();
 127             while (line != null) {
 128                 if (line.startsWith("#")) {
 129                     //ignore all comments except ones that indicate this is a
 130                     //statefull conversion.
 131                     if (line.indexOf("STATEFULL") > 0) {
 132                         isStatefull = true;
 133                     }
 134                 } else {
 135                     final StringTokenizer tokenizer = new StringTokenizer(line);
 136                     String key = tokenizer.nextToken();
 137                     String value = tokenizer.nextToken();
 138                     if (key.startsWith("0x")) key = key.substring(2);
 139                     if (value.startsWith("0x")) value = value.substring(2);
 140 
 141                     final char c = (char)Integer.parseInt(value, 16);
 142                     final String unicodeValue = String.valueOf(c);
 143 
 144                     final long keyValue = Long.parseLong(key, 16);
 145                     if (isStatefull) {
 146                         final int keyLength = key.length();
 147                         if (keyLength == 2) {
 148                             byte[] nativeValue = new byte[1];
 149                             nativeValue[0] = (byte)((keyValue) & 0x00FF);
 150                             nativeValues.addElement(nativeValue);
 151                             unicodeValues.addElement(unicodeValue);
 152                         } else if (keyLength == 8) {
 153                             byte[] nativeValue = new byte[4];
 154                             nativeValue[0] = 0x0E;
 155                             nativeValue[1] = (byte)((keyValue >> 16) & 0x00FF);
 156                             nativeValue[2] = (byte)((keyValue >> 8) & 0x00FF);
 157                             nativeValue[3] = 0x0F;
 158                             nativeValues.addElement(nativeValue);
 159                             unicodeValues.addElement(unicodeValue);
 160                         } else {
 161                             System.err.println("Agh!");
 162                         }
 163                     } else {
 164                         if (key.length() == 2) {
 165                             byte[] nativeValue = new byte[1];
 166                             nativeValue[0] = (byte)(keyValue & 0x00FF);
 167                             nativeValues.addElement(nativeValue);
 168                             unicodeValues.addElement(unicodeValue);
 169                         } else if (key.length() == 4) {
 170                             byte[] nativeValue = new byte[2];
 171                             nativeValue[0] = (byte)((keyValue >> 8) & 0x00FF);
 172                             nativeValue[1] = (byte)((keyValue) & 0x00FF);
 173                             nativeValues.addElement(nativeValue);
 174                             unicodeValues.addElement(unicodeValue);
 175                         } else {
 176                             byte[] nativeValue = new byte[3];
 177                             nativeValue[0] = (byte)((keyValue >> 16) & 0x00FF);
 178                             nativeValue[1] = (byte)((keyValue >> 8) & 0x00FF);
 179                             nativeValue[2] = (byte)((keyValue) & 0x00FF);
 180                             nativeValues.addElement(nativeValue);
 181                             unicodeValues.addElement(unicodeValue);
 182                         }
 183                     }
 184                 }
 185                 line = in.readLine();
 186             }
 187             statefull = isStatefull;
 188         }
 189 
 190         public String toString() {
 191             return value;
 192         }
 193 
 194         public void getMapping(final Vector keys, final Vector values, final boolean toUnicode)
 195                 throws IOException {
 196             final Hashtable temp = new Hashtable();
 197             for (int i = nativeValues.size() - 1; i >= 0; --i) {
 198                 final byte[] key = (byte[])nativeValues.elementAt(i);
 199                 final String value = (String)unicodeValues.elementAt(i);
 200 
 201                 if (toUnicode) {
 202                     final String keyString = printable(key);
 203                     if (temp.get(keyString) == null) {
 204                         temp.put(keyString, keyString);
 205                         keys.addElement(key);
 206                         values.addElement(value);
 207                     }
 208                 } else {
 209                     if (temp.get(value) == null) {
 210                         temp.put(value, value);
 211                         keys.addElement(value);
 212                         values.addElement(key);
 213                     }
 214                 }
 215             }
 216         }
 217     }
 218 
 219     public void checkPages(String[] args) {
 220         for (int j = 0; j < args.length; j++) {
 221             logln("Checking converter: "+args[j]);
 222             boolean err = false;
 223             try {
 224                 final Parameter param = new Parameter(args[j]);
 225 
 226                 final Vector keys = new Vector();
 227                 final Vector values = new Vector();
 228 
 229                 param.getMapping(keys, values, true);
 230                 for (int i = 0; i < keys.size(); i++) {
 231                     final byte[] key = (byte[])keys.elementAt(i);
 232                     final String value = (String)values.elementAt(i);
 233                     try {
 234                         final String actualValue = new String(key, param.value);
 235                         if (!value.equals(actualValue)) {
 236                             logln(printable(key)+" ==> "+printable(value)+" produced "+printable(actualValue));
 237                             err = true;
 238                         }
 239                     } catch (UnsupportedEncodingException e) {
 240                         logln(param.value+" encoding not supported: "+e);
 241                         err = true;
 242                         break;
 243                     }
 244                 }
 245 
 246                 keys.removeAllElements();
 247                 values.removeAllElements();
 248                 param.getMapping(keys, values, false);
 249                 for (int i = 0; i < keys.size(); i++) {
 250                     final String key = (String)keys.elementAt(i);
 251                     final byte[] value = (byte[])values.elementAt(i);
 252                     try {
 253                         final byte[] actualValue = key.getBytes(param.value);
 254                         boolean diff = false;
 255                         if (value.length != actualValue.length) {
 256                             logln(printable(key)+" ==> "+printable(value)+" produced "+printable(actualValue));
 257                             err = true;
 258                         } else {
 259                             for (int k = 0; k < value.length; k++) {
 260                                 if (value[k] != actualValue[k]) {
 261                                     logln(printable(key)+" ==> "+printable(value)+" produced "+printable(actualValue));
 262                                     err = true;
 263                                     break;
 264                                 }
 265                             }
 266                         }
 267                     } catch (UnsupportedEncodingException e) {
 268                         logln(param.value+" encoding not supported: "+e);
 269                         err = true;
 270                         break;
 271                     }
 272                 }
 273             } catch (IOException e) {
 274                 logln("Could not load table: "+e);
 275                 err = true;
 276             }
 277             if (err) {
 278                 errln("Error in converter: "+args[j]);
 279             } else {
 280                 logln("    passed.");
 281             }
 282         }
 283     }
 284 
 285     protected static String printable(String c) {
 286         final StringBuffer buffer = new StringBuffer();
 287         for (int i = 0; i < c.length(); i++) {
 288             buffer.append(printable(c.charAt(i)));
 289         }
 290         return buffer.toString();
 291     }
 292 
 293     protected static String printable(byte c) {
 294         final StringBuffer buffer = new StringBuffer("0x");
 295         final int value = ((int)c) & 0x00FF;
 296         buffer.append(HEX_DIGIT[(value & 0x00F0) >> 4]);
 297         buffer.append(HEX_DIGIT[(value & 0x000F)]);
 298         return buffer.toString();
 299     }
 300 
 301     protected static String printable(byte[] c) {
 302         final StringBuffer buffer = new StringBuffer("[");
 303         for (int i = 0; i < c.length; i++) {
 304             final int value = ((int)c[i]) & 0x00FF;
 305             buffer.append(HEX_DIGIT[(value & 0x00F0) >> 4]);
 306             buffer.append(HEX_DIGIT[(value & 0x000F)]);
 307             buffer.append(" ");
 308         }
 309         buffer.append("]");
 310         return buffer.toString();
 311     }
 312 
 313     protected static String printable(char[] c) {
 314         final StringBuffer buffer = new StringBuffer("[");
 315         for (int i = 0; i < c.length; i++) {
 316             buffer.append(printable(c[i]));
 317         }
 318         buffer.append("]");
 319         return buffer.toString();
 320     }
 321 
 322     protected static String printable(char c) {
 323         final StringBuffer buffer = new StringBuffer("\\u");
 324         final int value = ((int)c) & 0xFFFF;
 325         buffer.append(HEX_DIGIT[(value & 0xF000) >> 12]);
 326         buffer.append(HEX_DIGIT[(value & 0x0F00) >> 8]);
 327         buffer.append(HEX_DIGIT[(value & 0x00F0) >> 4]);
 328         buffer.append(HEX_DIGIT[(value & 0x000F)]);
 329         return buffer.toString();
 330     }
 331 
 332     static final char[] HEX_DIGIT = {'0','1','2','3','4','5','6','7',
 333                      '8','9','A','B','C','D','E','F'};
 334 
 335 }