1 /* 2 * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24 /* @test 25 @bug 4779029 4924625 6392664 26 @summary Test decoding of various permutations of valid ISO-2022-CN byte sequences 27 */ 28 29 /* 30 * Regression test for NIO ISO-2022-CN decoder. Passes various valid 31 * ISO-2022-CN byte sequences to the decoder using the java.io 32 * InputStreamReader API 33 */ 34 35 import java.io.*; 36 import java.nio.*; 37 import java.nio.charset.*; 38 39 public class TestISO2022CNDecoder 40 { 41 private static String encodingName = "ISO2022CN"; 42 43 // 44 // Positive tests -- test both output and input processing against 45 // various "known good" data 46 // 47 private static boolean decodeTest ( 48 byte encoded[], 49 char decoded[], 50 String label) 51 { 52 boolean retval = true; 53 int i = 0; 54 55 try { 56 // 57 // Ensure that reading decodes correctly 58 // 59 ByteArrayInputStream in; 60 InputStreamReader reader; 61 62 in = new ByteArrayInputStream(encoded); 63 reader = new InputStreamReader(in, encodingName); 64 65 for (i = 0; i < decoded.length; i++) { 66 int c = reader.read(); 67 68 if (c != decoded[i]) { 69 System.err.print(label + ": read failed, char " + i); 70 System.err.print(" ... expected 0x" 71 + Integer.toHexString(decoded[i])); 72 if (c == -1) 73 System.err.println(", got EOF"); 74 else 75 System.err.println(", got 0x" 76 + Integer.toHexString(c)); 77 retval = false; 78 if (c == -1) 79 return retval; 80 } 81 } 82 83 int testChar; 84 if ((testChar = reader.read()) != -1) { 85 System.err.println(label + ": read failed, no EOF"); 86 System.err.println("testChar is " + 87 Integer.toHexString((int)testChar)); 88 return false; 89 } 90 String decodedString = new String(encoded, "ISO2022CN"); 91 92 for (i = 0; i < decodedString.length(); i++) { 93 if (decodedString.charAt(i) != decoded[i]) 94 System.err.println(label + ": read failed, char " + i); 95 } 96 97 CharsetDecoder dec = Charset.forName("ISO2022CN") 98 .newDecoder() 99 .onUnmappableCharacter(CodingErrorAction.REPLACE) 100 .onMalformedInput(CodingErrorAction.REPLACE); 101 ByteBuffer bb = ByteBuffer.allocateDirect(encoded.length).put(encoded); 102 bb.flip(); 103 CharBuffer cb = ByteBuffer.allocateDirect(2*encoded.length*(int)dec.maxCharsPerByte()) 104 .asCharBuffer(); 105 if (bb.hasArray() || cb.hasArray()) { 106 System.err.println(label + ": directBuffer failed, "); 107 return false; 108 } 109 if (!dec.decode(bb, cb, true).isUnderflow()) { 110 System.err.println(label + ": decoder's decode() failed!"); 111 return false; 112 } 113 cb.flip(); 114 for (i = 0; i < cb.limit(); i++) { 115 if (cb.get() != decoded[i]) 116 System.err.println(label + ": decoder failed, char " + i); 117 } 118 119 } catch (Exception e) { 120 System.err.println(label + ": failed " 121 + "(i = " + i + "), " 122 + e.getClass().getName() 123 + ", " + e.getMessage()); 124 e.printStackTrace(); 125 return false; 126 } 127 return retval; 128 } 129 130 private static boolean equal(CoderResult a, CoderResult b) { 131 return (a == CoderResult.OVERFLOW && b == CoderResult.OVERFLOW) || 132 (a == CoderResult.UNDERFLOW && b == CoderResult.UNDERFLOW) || 133 ((a.isError() == b.isError()) && 134 (a.isMalformed() == b.isMalformed()) && 135 (a.isUnmappable() == b.isUnmappable()) && 136 (a.length() == b.length())); 137 } 138 139 private static boolean decodeResultTest (byte encoded[], 140 CoderResult expected, 141 String label) { 142 CharsetDecoder dec = Charset.forName("ISO2022CN").newDecoder(); 143 ByteBuffer bb = ByteBuffer.wrap(encoded); 144 CharBuffer cb = CharBuffer.allocate(encoded.length*(int)dec.maxCharsPerByte()); 145 CoderResult result = dec.decode(bb, cb, true); 146 if (!equal(result, expected)) { 147 System.err.println(label + ": decoder's decode() failed!"); 148 return false; 149 } 150 151 bb = ByteBuffer.allocateDirect(encoded.length).put(encoded); 152 bb.flip(); 153 cb = ByteBuffer.allocateDirect(2*encoded.length*(int)dec.maxCharsPerByte()) 154 .asCharBuffer(); 155 if (bb.hasArray() || cb.hasArray()) { 156 System.err.println(label + ": directBuffer failed, "); 157 return false; 158 } 159 result = dec.reset().decode(bb, cb, true); 160 if (!equal(result, expected)) { 161 System.err.println(label + ": decoder's decode() - direct failed!"); 162 return false; 163 } 164 return true; 165 } 166 167 // 168 // Negative tests -- only for input processing, make sure that 169 // invalid or corrupt characters are rejected. 170 // 171 private static boolean negative (byte encoded [], String label) 172 { 173 try { 174 ByteArrayInputStream in; 175 InputStreamReader reader; 176 int c; 177 178 in = new ByteArrayInputStream(encoded); 179 reader = new InputStreamReader(in, encodingName); 180 181 c = reader.read(); 182 System.err.print (label + ": read failed, "); 183 184 if (c == -1) 185 System.err.println("reported EOF"); 186 else 187 System.err.println("returned char 0x" 188 + Integer.toHexString(c) 189 + ", expected exception"); 190 return false; 191 192 } catch (CharConversionException e) { 193 return true; 194 195 } catch (Throwable t) { 196 System.err.println(label + ": failed, threw " 197 + t.getClass().getName() 198 + ", " + t.getMessage()); 199 } 200 return false; 201 } 202 203 private static boolean decodeTest6392664 () { 204 try { 205 CharsetDecoder dec = Charset.forName("ISO-2022-CN-GB").newDecoder(); 206 dec.decode(ByteBuffer.wrap(new byte[] {(byte)0x0e, (byte)0x42, (byte)0x43 })); 207 } catch (Exception e) { 208 e.printStackTrace(); 209 return false; 210 } 211 return true; 212 } 213 214 // 215 // TEST #0: 7-bit unshifted values, 216 // shift-in of a valid decodable GB2312-80 217 // character and an unmappable GB2312-80 char 218 // This is a positive test. 219 // 220 private static byte test0_bytes[] = { 221 (byte)0x00, 222 (byte)0x01, (byte)0x02, (byte)0x03, 223 (byte)0x0E, (byte)0x21, (byte)0x2f, 224 (byte)0x0E, (byte)0xDD, (byte)0x9f 225 }; 226 227 private static char test0_chars[] = { 228 0x0000, 229 0x0001, 0x0002, 0x0003, 230 0x2019, 231 0xFFFD 232 }; 233 234 private static byte test1_bytes[] = { 235 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, (byte)0x21, 236 (byte)0x2f }; 237 238 private static char test1_chars[] = { 239 0x21, 0x2f 240 }; 241 242 private static byte test2_bytes[] = { 243 (byte)0x0e, 244 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, 245 (byte)0x21, (byte)0x2f }; 246 247 private static char test2_chars[] = { 248 0x2019 249 }; 250 251 private static byte test3_bytes[] = { 252 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, 253 (byte)0x0e, 254 (byte)0x21, (byte)0x2f }; 255 256 private static byte test3a_bytes[] = { 257 (byte)0x1b, (byte)0x24, (byte)0x41, 258 (byte)0x0e, 259 (byte)0x21, (byte)0x2f }; 260 261 private static char test3_chars[] = { 262 0x2019 263 }; 264 265 private static byte test4_bytes[] = { 266 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, 267 (byte)0x0f, 268 (byte)0x21, (byte)0x2f }; 269 270 private static char test4_chars[] = { 271 0x21, 0x2f 272 }; 273 274 private static byte test5_bytes[] = { 275 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, 276 (byte)0x0e, (byte)0x21, (byte)0x2e, 277 (byte)0x0f, (byte)0x21, (byte)0x2f }; 278 279 private static char test5_chars[] = { 280 0x2018, 0x21, 0x2f 281 }; 282 283 private static byte test6_bytes[] = { 284 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, 285 (byte)0x0e, (byte)0x21, (byte)0x2e, 286 (byte)0x21, (byte)0x2f }; 287 288 private static char test6_chars[] = { 289 0x2018, 0x2019 290 }; 291 292 private static byte test7_bytes[] = { 293 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)'G', 294 (byte)0x0e, (byte)0x21, (byte)0x2e, 295 (byte)0x21, (byte)0x2f }; 296 297 private static char test7_chars[] = { 298 0xFE50, 0xFE51 299 }; 300 301 private static byte test8_bytes[] = { 302 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)'G', 303 (byte)0x0e, (byte)0x21, (byte)0x2e, 304 (byte)0x0f, (byte)0x21, (byte)0x2f }; 305 306 private static char test8_chars[] = { 307 0xFE50, 0x21, 0x2f 308 }; 309 310 private static byte test9_bytes[] = { 311 (byte)0x1b, (byte)0x24, (byte)0x2a, (byte)'H', 312 (byte)0x1b, (byte)0x4e, 313 (byte)0x21, (byte)0x2f }; 314 315 private static char test9_chars[] = { 316 0x4e0e 317 }; 318 319 /* 320 * Plane 3 support provided for compatibility with 321 * sun.io ISO2022_CN decoder. Officially ISO-2022-CN 322 * just handles planes 1/2 of CNS-11643 (1986) 323 * Test case data below verifies this compatibility 324 * 325 */ 326 327 private static byte test10_bytes[] = { 328 (byte)0x1b, (byte)0x24, (byte)'+', (byte)'I', 329 (byte)0x1b, (byte)0x4f, 330 (byte)0x21, (byte)0x2f }; 331 332 private static char test10_chars[] = { 333 0x51e2 334 }; 335 336 private static byte test11_bytes[] = { 337 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, //SO Designator 338 (byte)0x0e, //SO 339 (byte)0x21, (byte)0x2e, //GB2312 char 340 (byte)0x1b, (byte)0x24, (byte)0x2a, (byte)'H', //SS2 Designator 341 (byte)0x1b, (byte)0x4e, //SS2 342 (byte)0x21, (byte)0x2f, //CNS-P2 char 343 (byte)0x21, (byte)0x2f //GB2312 char 344 }; 345 346 private static char test11_chars[] = { 347 0x2018, 348 0x4e0e, 349 0x2019 350 }; 351 352 private static byte test12_bytes[] = { 353 (byte)0x1b, (byte)0x24, (byte)0x29, (byte)0x41, //SO Designator 354 (byte)0x0e, //SO 355 (byte)0x21, (byte)0x2e, //GB2312 char 356 (byte)0x1b, (byte)0x24, (byte)'+', (byte)'I', //SS3 Designator 357 (byte)0x1b, (byte)0x4f, //SS3 358 (byte)0x21, (byte)0x2f, //CNS-P2 char 359 (byte)0x21, (byte)0x2f //GB2312 char 360 }; 361 362 private static char test12_chars[] = { 363 0x2018, 364 0x51e2, 365 0x2019 366 }; 367 368 369 private static byte test13_bytes[] = { 370 (byte)0x0f0, // byte with MSB 371 }; 372 373 private static char test13_chars[] = { 374 0x00f0, 375 }; 376 377 private static byte test14_bytes[] = { 378 (byte)0x0E, (byte)0x21, (byte)0x2f, 379 (byte)0x0E, (byte)0xDD, (byte)0x9f 380 }; 381 private static CoderResult test14_result = CoderResult.unmappableForLength(2); 382 383 // Current ISO2022CN treats the "out of range" code points as "unmappable" 384 private static byte test15_bytes[] = { 385 (byte)0x1b, (byte)0x4f, // SS3 386 (byte)0x20, (byte)0x2f, // "out of range" CNS-P2 char 387 }; 388 private static CoderResult test15_result = CoderResult.unmappableForLength(4); 389 390 /** 391 * Main program to test ISO2022CN conformance 392 * 393 */ 394 public static void main (String argv []) throws Exception 395 { 396 boolean pass = true; 397 398 System.out.println (""); 399 System.out.println ("------ checking ISO2022CN decoder -----"); 400 401 // This regtest must be the first one. 402 pass &= decodeTest6392664(); 403 404 try { 405 new InputStreamReader (System.in, "ISO2022CN"); 406 } catch (Exception e) { 407 encodingName = "ISO2022CN"; 408 System.out.println ("... requires nonstandard encoding name " 409 + encodingName); 410 pass &= false; 411 } 412 413 // 414 // Positive tests -- good data is dealt with correctly 415 // 416 pass &= decodeTest(test0_bytes, test0_chars, "first batch"); 417 pass &= decodeTest(test1_bytes, test1_chars, "escapes1"); 418 pass &= decodeTest(test2_bytes, test2_chars, "escapes2"); 419 pass &= decodeTest(test3_bytes, test3_chars, "escapes3"); 420 pass &= decodeTest(test3a_bytes, test3_chars, "escapes3a"); 421 pass &= decodeTest(test4_bytes, test4_chars, "escapes4"); 422 pass &= decodeTest(test5_bytes, test5_chars, "escapes5"); 423 pass &= decodeTest(test6_bytes, test6_chars, "escapes6"); 424 pass &= decodeTest(test7_bytes, test7_chars, "escapes7"); 425 pass &= decodeTest(test8_bytes, test8_chars, "escapes8"); 426 pass &= decodeTest(test9_bytes, test9_chars, "escapes9"); 427 pass &= decodeTest(test10_bytes, test10_chars, "escapes10"); 428 pass &= decodeTest(test11_bytes, test11_chars, "escapes11"); 429 pass &= decodeTest(test12_bytes, test12_chars, "escapes12"); 430 pass &= decodeTest(test13_bytes, test13_chars, "escapes13"); 431 pass &= decodeResultTest(test14_bytes, test14_result, "escapes14"); 432 pass &= decodeResultTest(test15_bytes, test15_result, "escapes15"); 433 // PASS/FAIL status is what the whole thing is about. 434 // 435 if (! pass) { 436 throw new Exception("FAIL -- incorrect ISO-2022-CN"); 437 } 438 439 } 440 }