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