1 /*
   2  * Copyright (c) 2010, 2019, 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 /* @test
  25  * @bug 4712786 8229960
  26  * @summary Check charsets against reference files
  27  * @modules jdk.charsets
  28  *
  29  * @build Util
  30  * @run main Check shift_jis ref.shift_jis
  31  */
  32 
  33 import java.io.*;
  34 import java.nio.*;
  35 import java.nio.channels.*;
  36 import java.nio.charset.*;
  37 import java.util.*;
  38 import java.util.regex.*;
  39 
  40 
  41 public class Check {
  42 
  43     private static PrintStream log = System.err;
  44 
  45     private static final int UNICODE_SIZE = (1 << 16);
  46 
  47     private final String csName;
  48     private final String refName;
  49     private byte[][] bytes = new byte[UNICODE_SIZE][]; // Indexed by char
  50 
  51     private int errors = 0;
  52 
  53     private Check(String csn, String refn) {
  54         csName = csn;
  55         refName = refn;
  56     }
  57 
  58     private Check load()
  59         throws IOException
  60     {
  61         File fn = new File(System.getProperty("test.src", "."), refName);
  62         FileChannel fc = new FileInputStream(fn).getChannel();
  63         ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
  64         CharBuffer cb = Charset.forName("US-ASCII").decode(bb);
  65         Pattern p = Pattern.compile("^(\\p{XDigit}+) +(\\p{XDigit}+)$",
  66                                     Pattern.MULTILINE);
  67         Matcher m = p.matcher(cb);
  68         while (m.find()) {
  69             char c = (char)Integer.parseInt(m.group(1), 16);
  70             String v = m.group(2);
  71             int nb = v.length() >> 1;
  72             byte[] ba = new byte[nb];
  73             for (int i = 0; i < nb; i++) {
  74                 ba[i] = (byte)Integer.parseInt(v.substring(i << 1, (i << 1) + 2),
  75                                                16);
  76             }
  77             bytes[c] = ba;
  78         }
  79         return this;
  80     }
  81 
  82     private void error() {
  83         if (++errors >= 100)
  84             throw new RuntimeException("100 errors occurred (there might be more)");
  85     }
  86 
  87     private void mismatch(String s, byte[] expected, byte[] got) {
  88         log.println("Encoding mismatch on \""
  89                     + Util.toString(s)
  90                     + "\": Expected {"
  91                     + Util.toString(expected)
  92                     + "}, got {"
  93                     + Util.toString(got)
  94                     + "}");
  95         error();
  96     }
  97 
  98     private void mismatch(int i, byte[] ba, String expected, String got) {
  99         log.println("Decoding mismatch on \""
 100                     + Util.toString((char)i)
 101                     + "\", input {"
 102                     + Util.toString(ba)
 103                     + "}: Expected \""
 104                     + Util.toString(expected)
 105                     + "\", got \""
 106                     + Util.toString(got)
 107                     + "\"");
 108         error();
 109     }
 110 
 111     private void check()
 112         throws IOException
 113     {
 114 
 115         // String.getBytes(String csn)
 116         for (int i = 0; i < UNICODE_SIZE; i++) {
 117             if (bytes[i] == null)
 118                 continue;
 119             String s = new String(new char[]{ (char)i });
 120             byte[] ba = s.getBytes(csName);
 121             if (Util.cmp(ba, bytes[i]) >= 0)
 122                 mismatch(s, bytes[i], ba);
 123         }
 124         log.println("String.getBytes(\"" + csName + "\") okay");
 125 
 126         // String(byte[] ba, String csn)
 127         for (int i = 0; i < UNICODE_SIZE; i++) {
 128             if (bytes[i] == null)
 129                 continue;
 130             String r = new String(new char[]{ (char)i });
 131             String s = new String(bytes[i], csName);
 132             if (!r.equals(s))
 133                 mismatch(i, bytes[i], r, s);
 134         }
 135         log.println("String(byte[] ba, \"" + csName + "\") okay");
 136 
 137         // To be really thorough we should test OutputStreamWriter,
 138         // InputStreamReader, and Charset{De,En}Coder here also,
 139         // but the above will do for now.
 140 
 141         if (errors > 0) {
 142             throw new RuntimeException(errors + " error(s) occurred");
 143         }
 144 
 145     }
 146 
 147     // Usage: Check charsetName referenceFileName
 148     public static void main(String[] args) throws Exception {
 149         new Check(args[0], args[1]).load().check();
 150     }
 151 
 152 }