/* * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test @bug 4779029 4924625 6392664 6730652 @summary Test decoding of various permutations of valid ISO-2022-CN byte sequences */ /* * Regression test for NIO ISO-2022-CN decoder. Passes various valid * ISO-2022-CN byte sequences to the decoder using the java.io * InputStreamReader API */ import java.io.*; import java.nio.*; import java.nio.charset.*; public class TestISO2022CNDecoder { private static String encodingName = "ISO2022CN"; // // Positive tests -- test both output and input processing against // various "known good" data // private static boolean decodeTest ( byte encoded[], char decoded[], String label) { boolean retval = true; int i = 0; try { // // Ensure that reading decodes correctly // ByteArrayInputStream in; InputStreamReader reader; in = new ByteArrayInputStream(encoded); reader = new InputStreamReader(in, encodingName); for (i = 0; i < decoded.length; i++) { int c = reader.read(); if (c != decoded[i]) { System.err.print(label + ": read failed, char " + i); System.err.print(" ... expected 0x" + Integer.toHexString(decoded[i])); if (c == -1) System.err.println(", got EOF"); else System.err.println(", got 0x" + Integer.toHexString(c)); retval = false; if (c == -1) return retval; } } int testChar; if ((testChar = reader.read()) != -1) { System.err.println(label + ": read failed, no EOF"); System.err.println("testChar is " + Integer.toHexString((int)testChar)); return false; } String decodedString = new String(encoded, "ISO2022CN"); for (i = 0; i < decodedString.length(); i++) { if (decodedString.charAt(i) != decoded[i]) System.err.println(label + ": read failed, char " + i); } CharsetDecoder dec = Charset.forName("ISO2022CN") .newDecoder() .onUnmappableCharacter(CodingErrorAction.REPLACE) .onMalformedInput(CodingErrorAction.REPLACE); ByteBuffer bb = ByteBuffer.allocateDirect(encoded.length).put(encoded); bb.flip(); CharBuffer cb = ByteBuffer.allocateDirect(2*encoded.length*(int)dec.maxCharsPerByte()) .asCharBuffer(); if (bb.hasArray() || cb.hasArray()) { System.err.println(label + ": directBuffer failed, "); return false; } if (!dec.decode(bb, cb, true).isUnderflow()) { System.err.println(label + ": decoder's decode() failed!"); return false; } cb.flip(); for (i = 0; i < cb.limit(); i++) { if (cb.get() != decoded[i]) System.err.println(label + ": decoder failed, char " + i); } } catch (Exception e) { System.err.println(label + ": failed " + "(i = " + i + "), " + e.getClass().getName() + ", " + e.getMessage()); e.printStackTrace(); return false; } return retval; } private static boolean equal(CoderResult a, CoderResult b) { return (a == CoderResult.OVERFLOW && b == CoderResult.OVERFLOW) || (a == CoderResult.UNDERFLOW && b == CoderResult.UNDERFLOW) || ((a.isError() == b.isError()) && (a.isMalformed() == b.isMalformed()) && (a.isUnmappable() == b.isUnmappable()) && (a.length() == b.length())); } private static boolean decodeResultTest (byte encoded[], CoderResult expected, String label) { CharsetDecoder dec = Charset.forName("ISO2022CN").newDecoder(); ByteBuffer bb = ByteBuffer.wrap(encoded); CharBuffer cb = CharBuffer.allocate(encoded.length*(int)dec.maxCharsPerByte()); CoderResult result = dec.decode(bb, cb, true); if (!equal(result, expected)) { System.err.println(label + ": decoder's decode() failed!"); return false; } bb = ByteBuffer.allocateDirect(encoded.length).put(encoded); bb.flip(); cb = ByteBuffer.allocateDirect(2*encoded.length*(int)dec.maxCharsPerByte()) .asCharBuffer(); if (bb.hasArray() || cb.hasArray()) { System.err.println(label + ": directBuffer failed, "); return false; } result = dec.reset().decode(bb, cb, true); if (!equal(result, expected)) { System.err.println(label + ": decoder's decode() - direct failed!"); return false; } return true; } // // Negative tests -- only for input processing, make sure that // invalid or corrupt characters are rejected. // private static boolean negative (byte encoded [], String label) { try { ByteArrayInputStream in; InputStreamReader reader; int c; in = new ByteArrayInputStream(encoded); reader = new InputStreamReader(in, encodingName); c = reader.read(); System.err.print (label + ": read failed, "); if (c == -1) System.err.println("reported EOF"); else System.err.println("returned char 0x" + Integer.toHexString(c) + ", expected exception"); return false; } catch (CharConversionException e) { return true; } catch (Throwable t) { System.err.println(label + ": failed, threw " + t.getClass().getName() + ", " + t.getMessage()); } return false; } private static boolean decodeTest6392664 () { try { CharsetDecoder dec = Charset.forName("ISO-2022-CN-GB").newDecoder(); dec.decode(ByteBuffer.wrap(new byte[] {(byte)0x0e, (byte)0x42, (byte)0x43 })); } catch (Exception e) { e.printStackTrace(); return false; } return true; } // // TEST #0: 7-bit unshifted values, // shift-in of a valid decodable GB2312-80 // character and an unmappable GB2312-80 char // This is a positive test. // private static byte test0_bytes[] = { (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x0E, (byte)0x21, (byte)0x2f, (byte)0x0E, (byte)0xDD, (byte)0x9f }; private static char test0_chars[] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x2019, 0xFFFD }; private static byte test1_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x21, (byte)0x2f }; private static char test1_chars[] = { 0x21, 0x2f }; private static byte test2_bytes[] = { (byte)0x0e, (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x21, (byte)0x2f }; private static char test2_chars[] = { 0x2019 }; private static byte test3_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x0e, (byte)0x21, (byte)0x2f }; private static byte test3a_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x41, (byte)0x0e, (byte)0x21, (byte)0x2f }; private static char test3_chars[] = { 0x2019 }; private static byte test4_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x0f, (byte)0x21, (byte)0x2f }; private static char test4_chars[] = { 0x21, 0x2f }; private static byte test5_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x0e, (byte)0x21, (byte)0x2e, (byte)0x0f, (byte)0x21, (byte)0x2f }; private static char test5_chars[] = { 0x2018, 0x21, 0x2f }; private static byte test6_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x0e, (byte)0x21, (byte)0x2e, (byte)0x21, (byte)0x2f }; private static char test6_chars[] = { 0x2018, 0x2019 }; private static byte test7_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)'G', (byte)0x0e, (byte)0x21, (byte)0x2e, (byte)0x21, (byte)0x2f }; private static char test7_chars[] = { 0xFE50, 0xFE51 }; private static byte test8_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)'G', (byte)0x0e, (byte)0x21, (byte)0x2e, (byte)0x0f, (byte)0x21, (byte)0x2f }; private static char test8_chars[] = { 0xFE50, 0x21, 0x2f }; private static byte test9_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x2a, (byte)'H', (byte)0x1b, (byte)0x4e, (byte)0x21, (byte)0x2f }; private static char test9_chars[] = { 0x4e0e }; /* * Plane 3 support provided for compatibility with * sun.io ISO2022_CN decoder. Officially ISO-2022-CN * just handles planes 1/2 of CNS-11643 (1986) * Test case data below verifies this compatibility * */ private static byte test10_bytes[] = { (byte)0x1b, (byte)0x24, (byte)'+', (byte)'I', (byte)0x1b, (byte)0x4f, (byte)0x21, (byte)0x2f }; private static char test10_chars[] = { 0x51e2 }; private static byte test11_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, //SO Designator (byte)0x0e, //SO (byte)0x21, (byte)0x2e, //GB2312 char (byte)0x1b, (byte)0x24, (byte)0x2a, (byte)'H', //SS2 Designator (byte)0x1b, (byte)0x4e, //SS2 (byte)0x21, (byte)0x2f, //CNS-P2 char (byte)0x21, (byte)0x2f //GB2312 char }; private static char test11_chars[] = { 0x2018, 0x4e0e, 0x2019 }; private static byte test12_bytes[] = { (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, //SO Designator (byte)0x0e, //SO (byte)0x21, (byte)0x2e, //GB2312 char (byte)0x1b, (byte)0x24, (byte)'+', (byte)'I', //SS3 Designator (byte)0x1b, (byte)0x4f, //SS3 (byte)0x21, (byte)0x2f, //CNS-P2 char (byte)0x21, (byte)0x2f //GB2312 char }; private static char test12_chars[] = { 0x2018, 0x51e2, 0x2019 }; private static byte test13_bytes[] = { (byte)0x0f0, // byte with MSB }; private static char test13_chars[] = { 0x00f0, }; private static byte test14_bytes[] = { (byte)0x0E, (byte)0x21, (byte)0x2f, (byte)0x0E, (byte)0xDD, (byte)0x9f }; private static CoderResult test14_result = CoderResult.unmappableForLength(2); // Current ISO2022CN treats the "out of range" code points as "unmappable" private static byte test15_bytes[] = { (byte)0x1b, (byte)0x4f, // SS3 (byte)0x20, (byte)0x2f, // "out of range" CNS-P2 char }; private static CoderResult test15_result = CoderResult.unmappableForLength(4); private static boolean encodeTest6730652 () throws Exception { //sample p3 codepoints String strCNSP3 = "\u4e28\u4e36\u4e3f\u4e85\u4e05\u4e04\u5369\u53b6\u4e2a\u4e87\u4e49\u51e2\u56b8\u56b9\u56c4\u8053\u92b0"; return strCNSP3.equals(new String(strCNSP3.getBytes("x-ISO-2022-CN-CNS"), "x-ISO-2022-CN-CNS")); } /** * Main program to test ISO2022CN conformance * */ public static void main (String argv []) throws Exception { boolean pass = true; System.out.println (""); System.out.println ("------ checking ISO2022CN decoder -----"); // This regtest must be the first one. pass &= decodeTest6392664(); try { new InputStreamReader (System.in, "ISO2022CN"); } catch (Exception e) { encodingName = "ISO2022CN"; System.out.println ("... requires nonstandard encoding name " + encodingName); pass &= false; } // // Positive tests -- good data is dealt with correctly // pass &= decodeTest(test0_bytes, test0_chars, "first batch"); pass &= decodeTest(test1_bytes, test1_chars, "escapes1"); pass &= decodeTest(test2_bytes, test2_chars, "escapes2"); pass &= decodeTest(test3_bytes, test3_chars, "escapes3"); pass &= decodeTest(test3a_bytes, test3_chars, "escapes3a"); pass &= decodeTest(test4_bytes, test4_chars, "escapes4"); pass &= decodeTest(test5_bytes, test5_chars, "escapes5"); pass &= decodeTest(test6_bytes, test6_chars, "escapes6"); pass &= decodeTest(test7_bytes, test7_chars, "escapes7"); pass &= decodeTest(test8_bytes, test8_chars, "escapes8"); pass &= decodeTest(test9_bytes, test9_chars, "escapes9"); pass &= decodeTest(test10_bytes, test10_chars, "escapes10"); pass &= decodeTest(test11_bytes, test11_chars, "escapes11"); pass &= decodeTest(test12_bytes, test12_chars, "escapes12"); pass &= decodeTest(test13_bytes, test13_chars, "escapes13"); pass &= decodeResultTest(test14_bytes, test14_result, "escapes14"); pass &= decodeResultTest(test15_bytes, test15_result, "escapes15"); pass &= encodeTest6730652 (); // PASS/FAIL status is what the whole thing is about. // if (! pass) { throw new Exception("FAIL -- incorrect ISO-2022-CN"); } } }