1/*
2 * Copyright (c) 2008, 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   @bug 6346419
26   @summary Check correctness of the UTF-32 and its variant charsets
27 */
28
29import java.io.*;
30import java.nio.*;
31import java.nio.charset.*;
32
33public class TestUTF_32 {
34    private static void testDecode(String charset,
35                                   String expected,
36                                   byte[] input)
37        throws Exception
38    {
39        String out = new String(input, charset);
40        if (!out.equals(expected)) {
41            failureReport (out, expected);
42            throw new Exception("UTF_32 Decoding test failed: " + charset);
43        }
44    }
45
46    private static void testEncode(String charset,
47                                   String input,
48                                   byte[] expected)
49        throws Exception
50    {
51        byte[] testBytes = input.getBytes(charset);
52        for (int i = 0; i< expected.length; i++)
53            if (testBytes[i] != expected[i])
54                throw new Exception("UTF_32 Encoding test failed: [" + i + "]"+ charset);
55
56    }
57
58    private static void warn(String s) {
59        System.err.println("FAILED Test UTF-32:" +
60                            s) ;
61    }
62
63    private static void failureReport(String testStr,
64                                      String expected) {
65        System.err.println ("Expected Characters:");
66        for (int i = 0; i < expected.length() ; i++) {
67            warn("expected char[" + i + "] : " +
68                  Integer.toHexString((int)expected.charAt(i)) +
69                 "obtained char[" + i + "] : " +
70                  Integer.toHexString((int)testStr.charAt(i)));
71        }
72    }
73
74    private static void writeInt(OutputStream os, int i, boolean isBig)
75        throws Exception
76    {
77        if (isBig) {
78            os.write((i>>24) & 0xff);
79            os.write((i>>16) & 0xff);
80            os.write((i>>8) & 0xff);
81            os.write(i & 0xff);
82        } else {
83            os.write(i & 0xff);
84            os.write((i>>8) & 0xff);
85            os.write((i>>16) & 0xff);
86            os.write((i>>24) & 0xff);
87        }
88    }
89
90    private static byte[] getBytes(boolean doBOM, boolean isBig)
91        throws Exception
92    {
93        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024*1024);
94        if (doBOM)
95           writeInt(baos, 0xfeff, isBig);
96
97        for (int i = 0; i < 0xffff; i++) {
98            if (i < Character.MIN_SURROGATE ||
99                i > Character.MAX_SURROGATE)
100            writeInt(baos, i, isBig);
101        }
102        for (int i = 0x10000; i < 0x1ffff; i++) {
103            writeInt(baos, i, isBig);
104        }
105
106        for (int i = 0x100000; i < 0x10ffff; i++) {
107            writeInt(baos, i, isBig);
108        }
109        byte[] bb = baos.toByteArray();
110        baos.close();
111        return bb;
112    }
113
114    public static void main (String[] args) throws Exception {
115        byte[] bb;
116        String s;
117
118        // Test 1: UTF_32 BigEndian
119        bb = getBytes(false, true);
120        s = new String(bb, "UTF-32");
121        testDecode("UTF_32", s, bb);
122        testEncode("UTF_32", s, bb);
123
124        // Test 2: UTF_32 LittleEndian Decoding With BOM and
125        //         BigEndian Encoding
126        bb = getBytes(true, false);
127        s = new String(bb, "UTF-32");
128        bb = getBytes(false, true);
129        testDecode("UTF_32", s, bb);
130        testEncode("UTF_32", s, bb);
131
132
133        // Test 3: UTF_32BE
134        bb = getBytes(false, true);
135        s = new String(bb, "UTF-32BE");
136        testDecode("UTF_32BE", s, bb);
137        testEncode("UTF_32BE", s, bb);
138
139
140        // Test 4: UTF_32LE
141        bb = getBytes(false, false);
142        s = new String(bb, "UTF-32LE");
143        testDecode("UTF_32LE", s, bb);
144        testEncode("UTF_32LE", s, bb);
145
146        // Test 5: UTF_32BE_BOM
147        bb = getBytes(true, true);
148        s = new String(bb, "UTF-32BE-BOM");
149        testDecode("UTF_32BE_BOM", s, bb);
150        testEncode("UTF_32BE_BOM", s, bb);
151
152
153        // Test 6: UTF_32LE_BOM
154        bb = getBytes(true, false);
155        s = new String(bb, "UTF-32LE-BOM");
156        testDecode("UTF_32LE_BOM", s, bb);
157        testEncode("UTF_32LE_BOM", s, bb);
158
159        s = "\u4e00\ufffd\u4e01";
160        // Test 7: BigEndian with reverse BOM in middle
161        bb = new byte[] {
162            (byte)0x00,(byte)0x00,(byte)0x4e,(byte)0x00,
163            (byte)0xff,(byte)0xfe,(byte)0x00,(byte)0x00,
164            (byte)0x00,(byte)0x00,(byte)0x4e,(byte)0x01
165        };
166        if (!s.equals(new String(bb, "UTF_32")) ||
167            !s.equals(new String(bb, "UTF_32BE")) ||
168            !s.equals(new String(bb, "UTF_32BE_BOM")))
169            throw new Exception("UTF_32 Decoding test failed: ");
170
171        // Test 7: LittleEndian with reverse BOM in middle
172        bb = new byte[] {
173            (byte)0xff,(byte)0xfe,(byte)0x00,(byte)0x00,
174            (byte)0x00,(byte)0x4e,(byte)0x00,(byte)0x00,
175            (byte)0x00,(byte)0x00,(byte)0xfe,(byte)0xff,
176            (byte)0x01,(byte)0x4e,(byte)0x00,(byte)0x00
177        };
178        if (!s.equals(new String(bb, "UTF_32")) ||
179            !s.equals(new String(bb, "UTF_32LE")) ||
180            !s.equals(new String(bb, "UTF_32LE_BOM")))
181            throw new Exception("UTF_32 Decoding test failed: ");
182
183        // Test 8: Overflow
184        if (CoderResult.OVERFLOW !=
185            Charset.forName("UTF_32")
186            .newDecoder()
187            .decode((ByteBuffer.allocate(4)
188                                 .put(new byte[]
189                                      {(byte)0,(byte)1, (byte)0,(byte)01})
190                                 .flip()),
191                    CharBuffer.allocate(1),
192                    true)) {
193            throw new Exception ("Test UTF-32 Overflow test failed");
194        }
195        System.err.println ("OVERALL PASS OF UTF-32 Test");
196    }
197}
198