8186801: Add regression test to test mapping based charsets (generated at build time)
Reviewed-by: alanb
This commit is contained in:
parent
e7360c4387
commit
cfe34ed89c
4976
jdk/make/data/charsetmapping/Big5_HKSCS.c2b
Normal file
4976
jdk/make/data/charsetmapping/Big5_HKSCS.c2b
Normal file
File diff suppressed because it is too large
Load Diff
18598
jdk/make/data/charsetmapping/Big5_HKSCS.map
Normal file
18598
jdk/make/data/charsetmapping/Big5_HKSCS.map
Normal file
File diff suppressed because it is too large
Load Diff
16
jdk/make/data/charsetmapping/Big5_HKSCS.nr
Normal file
16
jdk/make/data/charsetmapping/Big5_HKSCS.nr
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
0xA15A 0xFF3F #SPACING UNDERSCORE
|
||||||
|
0xA1FE 0x2571 #LT DIAG UP RIGHT TO LOW LEFT
|
||||||
|
0xA240 0x2572 #LT DIAG UP LEFT TO LOW RIGHTG
|
||||||
|
0xA2CC 0x5341 #HANGHZOU NUMERAL TEN
|
||||||
|
0xA2CE 0x5345 #HANGZHOU NUMERAL THIRTY
|
||||||
|
#
|
||||||
|
0xA27E 0x256D # BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
|
||||||
|
0xA2A1 0x256E # BOX DRAWINGS LIGHT ARC DOWN AND LEFT
|
||||||
|
0xA2A2 0x2570 # BOX DRAWINGS LIGHT ARC UP AND RIGHT
|
||||||
|
0xA2A3 0x256F # BOX DRAWINGS LIGHT ARC UP AND LEFT
|
||||||
|
0xA2A4 0x2550 # BOX DRAWINGS DOUBLE HORIZONTAL
|
||||||
|
0xA2A5 0x255E # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
|
||||||
|
0xA2A6 0x256A # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
|
||||||
|
0xA2A7 0x2561 # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
|
||||||
|
|
13706
jdk/make/data/charsetmapping/Big5_Solaris.map
Normal file
13706
jdk/make/data/charsetmapping/Big5_Solaris.map
Normal file
File diff suppressed because it is too large
Load Diff
13107
jdk/make/data/charsetmapping/EUC_JP.map
Normal file
13107
jdk/make/data/charsetmapping/EUC_JP.map
Normal file
File diff suppressed because it is too large
Load Diff
7040
jdk/make/data/charsetmapping/EUC_JP_LINUX.map
Normal file
7040
jdk/make/data/charsetmapping/EUC_JP_LINUX.map
Normal file
File diff suppressed because it is too large
Load Diff
13558
jdk/make/data/charsetmapping/EUC_JP_Open.map
Normal file
13558
jdk/make/data/charsetmapping/EUC_JP_Open.map
Normal file
File diff suppressed because it is too large
Load Diff
1
jdk/make/data/charsetmapping/EUC_TW.nr
Normal file
1
jdk/make/data/charsetmapping/EUC_TW.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
a4bf 5344
|
63491
jdk/make/data/charsetmapping/GB18030.map
Normal file
63491
jdk/make/data/charsetmapping/GB18030.map
Normal file
File diff suppressed because it is too large
Load Diff
1
jdk/make/data/charsetmapping/IBM1140.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1140.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1141.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1141.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1142.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1142.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1143.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1143.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1144.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1144.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1145.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1145.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1146.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1146.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1147.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1147.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1148.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1148.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1
jdk/make/data/charsetmapping/IBM1149.nr
Normal file
1
jdk/make/data/charsetmapping/IBM1149.nr
Normal file
@ -0,0 +1 @@
|
|||||||
|
0x25 U+000a
|
1599
jdk/make/data/charsetmapping/MS950_HKSCS_XP.map
Normal file
1599
jdk/make/data/charsetmapping/MS950_HKSCS_XP.map
Normal file
File diff suppressed because it is too large
Load Diff
@ -681,7 +681,7 @@ charset x-euc-jp-linux EUC_JP_LINUX
|
|||||||
alias euc_jp_linux # JDK historical
|
alias euc_jp_linux # JDK historical
|
||||||
alias euc-jp-linux
|
alias euc-jp-linux
|
||||||
|
|
||||||
charset x-eucjp-open EUC_JP_Open
|
charset x-eucJP-Open EUC_JP_Open
|
||||||
package sun.nio.cs.ext
|
package sun.nio.cs.ext
|
||||||
type template
|
type template
|
||||||
hisname EUC_JP_Solari
|
hisname EUC_JP_Solari
|
||||||
|
@ -82,7 +82,7 @@ public class EUC_TW {
|
|||||||
|
|
||||||
static void genClass(String pkg, String args[]) throws Exception
|
static void genClass(String pkg, String args[]) throws Exception
|
||||||
{
|
{
|
||||||
InputStream is = new FileInputStream(new File(args[0], "euc_tw.map"));
|
InputStream is = new FileInputStream(new File(args[0], "EUC_TW.map"));
|
||||||
PrintStream ps = new PrintStream(new File(args[1], "EUC_TWMapping.java"),
|
PrintStream ps = new PrintStream(new File(args[1], "EUC_TWMapping.java"),
|
||||||
"ISO-8859-1");
|
"ISO-8859-1");
|
||||||
String copyright = getCopyright(new File(args[7], "EUC_TW.java"));
|
String copyright = getCopyright(new File(args[7], "EUC_TW.java"));
|
||||||
|
@ -34,7 +34,7 @@ import static sun.nio.cs.CharsetMapping.*;
|
|||||||
|
|
||||||
public class MS932_0213 extends Charset {
|
public class MS932_0213 extends Charset {
|
||||||
public MS932_0213() {
|
public MS932_0213() {
|
||||||
super("x-MS932_0213", ExtendedCharsets.aliasesFor("MS932_0213"));
|
super("x-MS932_0213", ExtendedCharsets.aliasesFor("x-MS932_0213"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Charset cs) {
|
public boolean contains(Charset cs) {
|
||||||
|
@ -59,7 +59,7 @@ import sun.nio.cs.*;
|
|||||||
|
|
||||||
public class SJIS_0213 extends Charset {
|
public class SJIS_0213 extends Charset {
|
||||||
public SJIS_0213() {
|
public SJIS_0213() {
|
||||||
super("x-SJIS_0213", ExtendedCharsets.aliasesFor("SJIS_0213"));
|
super("x-SJIS_0213", ExtendedCharsets.aliasesFor("x-SJIS_0213"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Charset cs) {
|
public boolean contains(Charset cs) {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 4114080
|
* @bug 4114080 8186803
|
||||||
* @summary Make sure the euro converters, which are derived from
|
* @summary Make sure the euro converters, which are derived from
|
||||||
* existing converters, only differ from their parents at the expected
|
* existing converters, only differ from their parents at the expected
|
||||||
* code point.
|
* code point.
|
||||||
@ -98,9 +98,9 @@ public class EuroConverter {
|
|||||||
bytes[0] = (byte)j;
|
bytes[0] = (byte)j;
|
||||||
char euroValue = new String(bytes, euroEnc).charAt(0);
|
char euroValue = new String(bytes, euroEnc).charAt(0);
|
||||||
chars[0] = euroValue;
|
chars[0] = euroValue;
|
||||||
// NOTE: 0x15 doesn't round trip on the EBCDIC code pages,
|
// NOTE: 0x25 doesn't round trip on the EBCDIC code pages,
|
||||||
// so we don't check that code point in the sanity check.
|
// so we don't check that code point in the sanity check.
|
||||||
if (j != 0x0015) {
|
if (j != 0x0025) {
|
||||||
int euroRoundTrip = new String(chars).getBytes(euroEnc)[0];
|
int euroRoundTrip = new String(chars).getBytes(euroEnc)[0];
|
||||||
if (euroRoundTrip != j) {
|
if (euroRoundTrip != j) {
|
||||||
pass = false;
|
pass = false;
|
||||||
|
659
jdk/test/sun/nio/cs/TestCharsetMapping.java
Normal file
659
jdk/test/sun/nio/cs/TestCharsetMapping.java
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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 8186801
|
||||||
|
* @summary Test the charset mappings
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.nio.charset.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
import java.util.stream.*;
|
||||||
|
|
||||||
|
public class TestCharsetMapping {
|
||||||
|
|
||||||
|
private static final int BUFSIZ = 8192; // Initial buffer size
|
||||||
|
private static final int MAXERRS = 10; // Errors reported per test
|
||||||
|
|
||||||
|
private static final PrintStream log = System.out;
|
||||||
|
|
||||||
|
// Set by -v on the command line
|
||||||
|
private static boolean verbose = false;
|
||||||
|
|
||||||
|
// Test modes
|
||||||
|
private static final int ENCODE = 1;
|
||||||
|
private static final int DECODE = 2;
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
private static ByteBuffer expand(ByteBuffer bb) {
|
||||||
|
ByteBuffer nbb = ByteBuffer.allocate(bb.capacity() * 2);
|
||||||
|
bb.flip();
|
||||||
|
nbb.put(bb);
|
||||||
|
return nbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharBuffer expand(CharBuffer cb) {
|
||||||
|
CharBuffer ncb = CharBuffer.allocate(cb.capacity() * 2);
|
||||||
|
cb.flip();
|
||||||
|
ncb.put(cb);
|
||||||
|
return ncb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] parseBytes(String s) {
|
||||||
|
int nb = s.length() / 2;
|
||||||
|
byte[] bs = new byte[nb];
|
||||||
|
for (int i = 0; i < nb; i++) {
|
||||||
|
int j = i * 2;
|
||||||
|
if (j + 2 > s.length())
|
||||||
|
throw new RuntimeException("Malformed byte string: " + s);
|
||||||
|
bs[i] = (byte)Integer.parseInt(s.substring(j, j + 2), 16);
|
||||||
|
}
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String printBytes(byte[] bs) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
for (int i = 0; i < bs.length; i++) {
|
||||||
|
sb.append(Integer.toHexString((bs[i] >> 4) & 0xf));
|
||||||
|
sb.append(Integer.toHexString((bs[i] >> 0) & 0xf));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String printCodePoint(int cp) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append("U+");
|
||||||
|
if (cp > 0xffff)
|
||||||
|
sb.append(Integer.toHexString((cp >> 16) & 0xf));
|
||||||
|
sb.append(Integer.toHexString((cp >> 12) & 0xf));
|
||||||
|
sb.append(Integer.toHexString((cp >> 8) & 0xf));
|
||||||
|
sb.append(Integer.toHexString((cp >> 4) & 0xf));
|
||||||
|
sb.append(Integer.toHexString((cp >> 0) & 0xf));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getCodePoint(CharBuffer cb) {
|
||||||
|
char c = cb.get();
|
||||||
|
if (Character.isHighSurrogate(c))
|
||||||
|
return Character.toCodePoint(c, cb.get());
|
||||||
|
else
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String plural(int n) {
|
||||||
|
return (n == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCharsetMapping
|
||||||
|
private CharsetInfo csinfo;
|
||||||
|
private CharsetDecoder decoder = null;
|
||||||
|
private CharsetEncoder encoder = null;
|
||||||
|
|
||||||
|
// Stateful dbcs encoding has leading shift byte '0x0e'
|
||||||
|
// and trailing shift byte '0x0f'.
|
||||||
|
// The flag variable shiftHackDBCS is 'true' for stateful
|
||||||
|
// EBCDIC encodings, which indicates the need of adding/
|
||||||
|
// removing the shift bytes.
|
||||||
|
private boolean shiftHackDBCS = false;
|
||||||
|
|
||||||
|
private TestCharsetMapping(CharsetInfo csinfo) throws Exception {
|
||||||
|
this.csinfo = csinfo;
|
||||||
|
this.encoder = csinfo.cs.newEncoder()
|
||||||
|
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
||||||
|
.onMalformedInput(CodingErrorAction.REPLACE);
|
||||||
|
this.decoder = csinfo.cs.newDecoder()
|
||||||
|
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
||||||
|
.onMalformedInput(CodingErrorAction.REPLACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Test {
|
||||||
|
// An instance of this class tests all mappings for
|
||||||
|
// a particular bytesPerChar value
|
||||||
|
private int bytesPerChar;
|
||||||
|
|
||||||
|
// Reference data from .map/nr/c2b files
|
||||||
|
private ByteBuffer refBytes = ByteBuffer.allocate(BUFSIZ);
|
||||||
|
private CharBuffer refChars = CharBuffer.allocate(BUFSIZ);
|
||||||
|
|
||||||
|
private ByteBuffer dRefBytes = ByteBuffer.allocateDirect(BUFSIZ);
|
||||||
|
private CharBuffer dRefChars = ByteBuffer.allocateDirect(BUFSIZ*2).asCharBuffer();
|
||||||
|
|
||||||
|
private Test(int bpc) {
|
||||||
|
bytesPerChar = bpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shiftHackDBCS can add the leading/trailing shift bytesa
|
||||||
|
private void put(byte[] bs) {
|
||||||
|
if (refBytes.remaining() < bytesPerChar)
|
||||||
|
refBytes = expand(refBytes);
|
||||||
|
refBytes.put(bs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put(byte[] bs, char[] cc) {
|
||||||
|
if (bs.length != bytesPerChar)
|
||||||
|
throw new IllegalArgumentException(bs.length
|
||||||
|
+ " != "
|
||||||
|
+ bytesPerChar);
|
||||||
|
if (refBytes.remaining() < bytesPerChar)
|
||||||
|
refBytes = expand(refBytes);
|
||||||
|
refBytes.put(bs);
|
||||||
|
if (refChars.remaining() < cc.length)
|
||||||
|
refChars = expand(refChars);
|
||||||
|
refChars.put(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean decode(ByteBuffer refBytes, CharBuffer refChars)
|
||||||
|
throws Exception {
|
||||||
|
log.println(" decode" + (refBytes.isDirect()?" (direct)":""));
|
||||||
|
CharBuffer out = decoder.decode(refBytes);
|
||||||
|
|
||||||
|
refBytes.rewind();
|
||||||
|
byte[] bs = new byte[bytesPerChar];
|
||||||
|
int e = 0;
|
||||||
|
|
||||||
|
if (shiftHackDBCS && bytesPerChar == 2 && refBytes.get() != (byte)0x0e) {
|
||||||
|
log.println("Missing leading byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (refChars.hasRemaining()) {
|
||||||
|
refBytes.get(bs);
|
||||||
|
int rcp = getCodePoint(refChars);
|
||||||
|
int ocp = getCodePoint(out);
|
||||||
|
if (rcp != ocp) {
|
||||||
|
log.println(" Error: "
|
||||||
|
+ printBytes(bs)
|
||||||
|
+ " --> "
|
||||||
|
+ printCodePoint(ocp)
|
||||||
|
+ ", expected "
|
||||||
|
+ printCodePoint(rcp));
|
||||||
|
if (++e >= MAXERRS) {
|
||||||
|
log.println(" Too many errors, giving up");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
log.println(" "
|
||||||
|
+ printBytes(bs)
|
||||||
|
+ " --> "
|
||||||
|
+ printCodePoint(rcp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shiftHackDBCS && bytesPerChar == 2 && refBytes.get() != (byte)0x0f) {
|
||||||
|
log.println("Missing trailing byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e == 0 && (refChars.hasRemaining() || out.hasRemaining())) {
|
||||||
|
// Paranoia: Didn't consume everything
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
refBytes.rewind();
|
||||||
|
refChars.rewind();
|
||||||
|
return (e == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean encode(ByteBuffer refBytes, CharBuffer refChars)
|
||||||
|
throws Exception {
|
||||||
|
log.println(" encode" + (refBytes.isDirect()?" (direct)":""));
|
||||||
|
ByteBuffer out = encoder.encode(refChars);
|
||||||
|
refChars.rewind();
|
||||||
|
|
||||||
|
if (shiftHackDBCS && bytesPerChar == 2 && out.get() != refBytes.get()) {
|
||||||
|
log.println("Missing leading byte");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] rbs = new byte[bytesPerChar];
|
||||||
|
byte[] obs = new byte[bytesPerChar];
|
||||||
|
int e = 0;
|
||||||
|
while (refChars.hasRemaining()) {
|
||||||
|
int cp = getCodePoint(refChars);
|
||||||
|
refBytes.get(rbs);
|
||||||
|
out.get(obs);
|
||||||
|
boolean eq = true;
|
||||||
|
for (int i = 0; i < bytesPerChar; i++)
|
||||||
|
eq &= rbs[i] == obs[i];
|
||||||
|
if (!eq) {
|
||||||
|
log.println(" Error: "
|
||||||
|
+ printCodePoint(cp)
|
||||||
|
+ " --> "
|
||||||
|
+ printBytes(obs)
|
||||||
|
+ ", expected "
|
||||||
|
+ printBytes(rbs));
|
||||||
|
if (++e >= MAXERRS) {
|
||||||
|
log.println(" Too many errors, giving up");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
log.println(" "
|
||||||
|
+ printCodePoint(cp)
|
||||||
|
+ " --> "
|
||||||
|
+ printBytes(rbs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shiftHackDBCS && bytesPerChar == 2 && out.get() != refBytes.get()) {
|
||||||
|
log.println("Missing trailing byte");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e == 0 && (refBytes.hasRemaining() || out.hasRemaining())) {
|
||||||
|
// Paranoia: Didn't consume everything
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
refBytes.rewind();
|
||||||
|
refChars.rewind();
|
||||||
|
return (e == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean run(int mode) throws Exception {
|
||||||
|
log.println(" " + bytesPerChar
|
||||||
|
+ " byte" + plural(bytesPerChar) + "/char");
|
||||||
|
|
||||||
|
if (dRefBytes.capacity() < refBytes.capacity()) {
|
||||||
|
dRefBytes = ByteBuffer.allocateDirect(refBytes.capacity());
|
||||||
|
}
|
||||||
|
if (dRefChars.capacity() < refChars.capacity()) {
|
||||||
|
dRefChars = ByteBuffer.allocateDirect(refChars.capacity()*2)
|
||||||
|
.asCharBuffer();
|
||||||
|
}
|
||||||
|
refBytes.flip();
|
||||||
|
refChars.flip();
|
||||||
|
dRefBytes.clear();
|
||||||
|
dRefChars.clear();
|
||||||
|
|
||||||
|
dRefBytes.put(refBytes).flip();
|
||||||
|
dRefChars.put(refChars).flip();
|
||||||
|
refBytes.flip();
|
||||||
|
refChars.flip();
|
||||||
|
|
||||||
|
boolean rv = true;
|
||||||
|
if (mode != ENCODE) {
|
||||||
|
rv &= decode(refBytes, refChars);
|
||||||
|
rv &= decode(dRefBytes, dRefChars);
|
||||||
|
}
|
||||||
|
if (mode != DECODE) {
|
||||||
|
rv &= encode(refBytes, refChars);
|
||||||
|
rv &= encode(dRefBytes, dRefChars);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum bytes/char being tested
|
||||||
|
private int maxBytesPerChar = 0;
|
||||||
|
|
||||||
|
// Tests, indexed by bytesPerChar - 1
|
||||||
|
private Test[] tests;
|
||||||
|
|
||||||
|
private void clearTests() {
|
||||||
|
maxBytesPerChar = 0;
|
||||||
|
tests = new Test[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the test for the given bytes/char value,
|
||||||
|
// expanding the test array if needed
|
||||||
|
//
|
||||||
|
private Test testFor(int bpc) {
|
||||||
|
if (bpc > maxBytesPerChar) {
|
||||||
|
Test[] ts = new Test[bpc];
|
||||||
|
System.arraycopy(tests, 0, ts, 0, maxBytesPerChar);
|
||||||
|
for (int i = maxBytesPerChar; i < bpc; i++)
|
||||||
|
ts[i] = new Test(i + 1);
|
||||||
|
tests = ts;
|
||||||
|
maxBytesPerChar = bpc;
|
||||||
|
}
|
||||||
|
return tests[bpc - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean testStringConv() throws Exception {
|
||||||
|
if (shiftHackDBCS) {
|
||||||
|
log.println(" string de/encoding skipped for ebcdic");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
boolean rv = true;
|
||||||
|
log.println(" string de/encoding");
|
||||||
|
// for new String()
|
||||||
|
ByteArrayOutputStream baosDec = new ByteArrayOutputStream();
|
||||||
|
StringBuilder sbDec = new StringBuilder();
|
||||||
|
// for String.getBytes()
|
||||||
|
ByteArrayOutputStream baosEnc = new ByteArrayOutputStream();
|
||||||
|
StringBuilder sbEnc = new StringBuilder();
|
||||||
|
|
||||||
|
for (Entry e : csinfo.mappings) {
|
||||||
|
baosDec.write(e.bs);
|
||||||
|
sbDec.append(Character.toChars(e.cp));
|
||||||
|
if (e.cp2 != 0)
|
||||||
|
sbDec.append(e.cp2);
|
||||||
|
|
||||||
|
// non-roundtrip b2c, and c2b
|
||||||
|
if (csinfo.nr != null && csinfo.nr.containsKey(e.bb) ||
|
||||||
|
csinfo.c2b != null && !csinfo.c2b.containsKey(e.cp))
|
||||||
|
continue;
|
||||||
|
baosEnc.write(e.bs);
|
||||||
|
sbEnc.append(Character.toChars(e.cp));
|
||||||
|
if (e.cp2 != 0)
|
||||||
|
sbEnc.append(e.cp2);
|
||||||
|
}
|
||||||
|
log.println(" new String()");
|
||||||
|
if (!new String(baosDec.toByteArray(), csinfo.csName).equals(sbDec.toString())) {
|
||||||
|
log.println(" Error: new String() failed");
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
log.println(" String.getBytes()");
|
||||||
|
if (!Arrays.equals(baosEnc.toByteArray(), sbEnc.toString().getBytes(csinfo.csName))) {
|
||||||
|
log.println(" Error: String().getBytes() failed");
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean run() throws Exception {
|
||||||
|
boolean rv = true;
|
||||||
|
shiftHackDBCS = csinfo.type.equals("ebcdic"); // isStateful;
|
||||||
|
|
||||||
|
// (1) new String()/String.getBytes()
|
||||||
|
rv &= testStringConv();
|
||||||
|
|
||||||
|
// (2) DECODE:
|
||||||
|
clearTests();
|
||||||
|
if (shiftHackDBCS) {
|
||||||
|
testFor(2).put(new byte[] { 0x0e });
|
||||||
|
}
|
||||||
|
csinfo.mappings.forEach(e -> {
|
||||||
|
if (e.cp2 != 0)
|
||||||
|
return; // skip composite (base+cc) for now
|
||||||
|
byte[] bs = e.bs;
|
||||||
|
char[] cc = Character.toChars(e.cp);
|
||||||
|
testFor(bs.length).put(bs, cc);
|
||||||
|
});
|
||||||
|
if (shiftHackDBCS) {
|
||||||
|
testFor(2).put(new byte[] { 0x0f });
|
||||||
|
}
|
||||||
|
for (int i = 0; i < maxBytesPerChar; i++) {
|
||||||
|
rv &= tests[i].run(DECODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (3) ENCODE:
|
||||||
|
clearTests();
|
||||||
|
if (shiftHackDBCS) {
|
||||||
|
testFor(2).put(new byte[] { 0x0e });
|
||||||
|
}
|
||||||
|
csinfo.mappings.forEach(e -> {
|
||||||
|
if (e.cp2 != 0)
|
||||||
|
return; // skip composite (base+cc) for now
|
||||||
|
if (csinfo.nr != null && csinfo.nr.containsKey(e.bb))
|
||||||
|
return; // non-roundtrip b2c
|
||||||
|
if (csinfo.c2b != null && csinfo.c2b.containsKey(e.cp))
|
||||||
|
return; // c2b only mapping
|
||||||
|
byte[] bs = e.bs;
|
||||||
|
char[] cc = Character.toChars(e.cp);
|
||||||
|
testFor(bs.length).put(bs, cc);
|
||||||
|
});
|
||||||
|
if (csinfo.c2b != null)
|
||||||
|
csinfo.c2b.values().forEach(e -> {
|
||||||
|
byte[] bs = e.bs;
|
||||||
|
char[] cc = Character.toChars(e.cp);
|
||||||
|
testFor(bs.length).put(bs, cc);
|
||||||
|
});
|
||||||
|
if (shiftHackDBCS) {
|
||||||
|
testFor(2).put(new byte[] { 0x0f });
|
||||||
|
}
|
||||||
|
for (int i = 0; i < maxBytesPerChar; i++) {
|
||||||
|
rv &= tests[i].run(ENCODE);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Entry {
|
||||||
|
byte[] bs; // byte sequence reps
|
||||||
|
int cp; // Unicode codepoint
|
||||||
|
int cp2; // CC of composite
|
||||||
|
long bb; // bs in "long" form for nr lookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static int UNMAPPABLE = 0xFFFD;
|
||||||
|
private static final Pattern ptn = Pattern.compile("(?:0x)?(\\p{XDigit}++)\\s++(?:U\\+|0x)?(\\p{XDigit}++)(?:\\s++#.*)?");
|
||||||
|
private static final int G_BS = 1;
|
||||||
|
private static final int G_CP = 2;
|
||||||
|
private static final int G_CP2 = 3;
|
||||||
|
|
||||||
|
private static class CharsetInfo {
|
||||||
|
Charset cs;
|
||||||
|
String pkgName;
|
||||||
|
String clzName;
|
||||||
|
String csName;
|
||||||
|
String hisName;
|
||||||
|
String type;
|
||||||
|
boolean isInternal;
|
||||||
|
Set<String> aliases = new HashSet<>();
|
||||||
|
|
||||||
|
// mapping entries
|
||||||
|
List<Entry> mappings;
|
||||||
|
Map<Long, Entry> nr; // bytes -> entry
|
||||||
|
Map<Integer, Entry> c2b; // cp -> entry
|
||||||
|
|
||||||
|
CharsetInfo(String csName, String clzName) {
|
||||||
|
this.csName = csName;
|
||||||
|
this.clzName = clzName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry parse(Matcher m) {
|
||||||
|
Entry e = new Entry();
|
||||||
|
e.bb = Long.parseLong(m.group(G_BS), 16);
|
||||||
|
if (e.bb < 0x100)
|
||||||
|
e.bs = new byte[] { (byte)e.bb };
|
||||||
|
else
|
||||||
|
e.bs = parseBytes(m.group(G_BS));
|
||||||
|
e.cp = Integer.parseInt(m.group(G_CP), 16);
|
||||||
|
if (G_CP2 <= m.groupCount() && m.group(G_CP2) != null)
|
||||||
|
e.cp2 = Integer.parseInt(m.group(G_CP2), 16);
|
||||||
|
else
|
||||||
|
e.cp2 = 0;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean loadMappings(Path dir) throws IOException {
|
||||||
|
// xxx.map
|
||||||
|
Path path = dir.resolve(clzName + ".map");
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Matcher m = ptn.matcher("");
|
||||||
|
mappings = Files.lines(path)
|
||||||
|
.filter(ln -> !ln.startsWith("#") && m.reset(ln).lookingAt())
|
||||||
|
.map(ln -> parse(m))
|
||||||
|
.filter(e -> e.cp != UNMAPPABLE) // non-mapping
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// xxx.nr
|
||||||
|
path = dir.resolve(clzName + ".nr");
|
||||||
|
if (Files.exists(path)) {
|
||||||
|
nr = Files.lines(path)
|
||||||
|
.filter(ln -> !ln.startsWith("#") && m.reset(ln).lookingAt())
|
||||||
|
.map(ln -> parse(m))
|
||||||
|
.collect(Collectors.toMap(e -> e.bb, Function.identity()));
|
||||||
|
}
|
||||||
|
// xxx.c2b
|
||||||
|
path = dir.resolve(clzName + ".c2b");
|
||||||
|
if (Files.exists(path)) {
|
||||||
|
c2b = Files.lines(path)
|
||||||
|
.filter(ln -> !ln.startsWith("#") && m.reset(ln).lookingAt())
|
||||||
|
.map(ln -> parse(m))
|
||||||
|
.collect(Collectors.toMap(e -> e.cp, Function.identity()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<CharsetInfo> charsets(Path cslist) throws IOException {
|
||||||
|
Set<CharsetInfo> charsets = new LinkedHashSet<>();
|
||||||
|
Iterator<String> itr = Files.readAllLines(cslist).iterator();
|
||||||
|
CharsetInfo cs = null;
|
||||||
|
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
String line = itr.next();
|
||||||
|
if (line.startsWith("#") || line.length() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] tokens = line.split("\\s+");
|
||||||
|
if (tokens.length < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ("charset".equals(tokens[0])) {
|
||||||
|
if (cs != null) {
|
||||||
|
charsets.add(cs);
|
||||||
|
cs = null;
|
||||||
|
}
|
||||||
|
if (tokens.length < 3) {
|
||||||
|
throw new RuntimeException("Error: incorrect charset line [" + line + "]");
|
||||||
|
}
|
||||||
|
cs = new CharsetInfo(tokens[1], tokens[2]);
|
||||||
|
} else {
|
||||||
|
String key = tokens[1]; // leading empty str
|
||||||
|
switch (key) {
|
||||||
|
case "alias":
|
||||||
|
if (tokens.length < 3) {
|
||||||
|
throw new RuntimeException("Error: incorrect alias line [" + line + "]");
|
||||||
|
}
|
||||||
|
cs.aliases.add(tokens[2]); // ALIAS_NAME
|
||||||
|
break;
|
||||||
|
case "package":
|
||||||
|
cs.pkgName = tokens[2];
|
||||||
|
break;
|
||||||
|
case "type":
|
||||||
|
cs.type = tokens[2];
|
||||||
|
break;
|
||||||
|
case "hisname":
|
||||||
|
cs.hisName = tokens[2];
|
||||||
|
break;
|
||||||
|
case "internal":
|
||||||
|
cs.isInternal = Boolean.parseBoolean(tokens[2]);
|
||||||
|
break;
|
||||||
|
default: // ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cs != null) {
|
||||||
|
charsets.add(cs);
|
||||||
|
}
|
||||||
|
return charsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
Path dir = Paths.get(System.getProperty("test.src", ".") +
|
||||||
|
"/../../../../make/data/charsetmapping");
|
||||||
|
if (!Files.exists(dir)) {
|
||||||
|
// not inside jdk repo, no mappings, exit silently
|
||||||
|
log.println("Nothing done, not in a jdk repo: ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.length > 0 && "-v".equals(args[0])) {
|
||||||
|
// For debugging: java CoderTest [-v]
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
int tested = 0;
|
||||||
|
int skipped = 0;
|
||||||
|
int known = 0;
|
||||||
|
|
||||||
|
for (CharsetInfo csinfo : charsets(dir.resolve("charsets"))) {
|
||||||
|
String csname = csinfo.csName;
|
||||||
|
|
||||||
|
if (csinfo.isInternal) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.printf("%ntesting: %-16s", csname);
|
||||||
|
|
||||||
|
if (!Charset.isSupported(csname)) {
|
||||||
|
errors++;
|
||||||
|
log.println(" [error: charset is not supported]");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Charset cs = csinfo.cs = Charset.forName(csinfo.csName);
|
||||||
|
// test name()
|
||||||
|
if (!cs.name().equals(csinfo.csName)) {
|
||||||
|
errors++;
|
||||||
|
log.printf(" [error: wrong csname: " + csinfo.csName
|
||||||
|
+ " vs " + cs.name() + "]");
|
||||||
|
}
|
||||||
|
// test aliases()
|
||||||
|
if (!cs.aliases().equals(csinfo.aliases)) {
|
||||||
|
errors++;
|
||||||
|
log.printf(" [error wrong aliases]");
|
||||||
|
if (verbose) {
|
||||||
|
log.println();
|
||||||
|
log.println(" expected: " + csinfo.aliases);
|
||||||
|
log.println(" got: " + cs.aliases());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csinfo.type.equals("source")) {
|
||||||
|
log.println(" [skipped: source based]");
|
||||||
|
skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!csinfo.loadMappings(dir)) {
|
||||||
|
log.println(" [error loading mappings failed]");
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
log.println();
|
||||||
|
if (!new TestCharsetMapping(csinfo).run()) {
|
||||||
|
|
||||||
|
/////////////// known nr/c2b issues ////////////////
|
||||||
|
if (csinfo.csName.equals("x-IBM948") ||
|
||||||
|
csinfo.csName.equals("x-IBM950") ||
|
||||||
|
csinfo.csName.equals("x-IBM937") ||
|
||||||
|
csinfo.csName.equals("x-IBM1383"))
|
||||||
|
{
|
||||||
|
log.println(" [**** skipped, KNOWN nr/c2b mapping issue]");
|
||||||
|
known++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.println();
|
||||||
|
log.println(tested + " charset" + plural(tested) + " tested, "
|
||||||
|
+ skipped + " skipped, " + known + " known issue(s)");
|
||||||
|
log.println();
|
||||||
|
if (errors > 0)
|
||||||
|
throw new Exception("Errors detected in "
|
||||||
|
+ errors + " charset" + plural(errors));
|
||||||
|
}
|
||||||
|
}
|
73
jdk/test/sun/nio/cs/TestEBCDICLineFeed.java
Normal file
73
jdk/test/sun/nio/cs/TestEBCDICLineFeed.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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 8186803
|
||||||
|
* @summary Check if the linefeed is de/encoded correctly in ebcdic
|
||||||
|
* @modules jdk.charsets
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestEBCDICLineFeed {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
String[] csnames = new String[] {
|
||||||
|
"IBM037", "IBM1025", "IBM1026", "IBM1112", "IBM1122", "IBM1123",
|
||||||
|
"IBM1166", "IBM273", "IBM277", "IBM278", "IBM280", "IBM284",
|
||||||
|
"IBM285", "IBM297", "IBM420", "IBM424", "IBM500", "IBM838",
|
||||||
|
"IBM870", "IBM871", "IBM875", "IBM918", "IBM930", "IBM935",
|
||||||
|
"IBM937", "IBM939",
|
||||||
|
|
||||||
|
"IBM01140", "IBM01141", "IBM01142", "IBM01143", "IBM01144",
|
||||||
|
"IBM01145", "IBM01146", "IBM01147", "IBM01148", "IBM01149",
|
||||||
|
};
|
||||||
|
|
||||||
|
int errs = 0;
|
||||||
|
for (String cs : csnames) {
|
||||||
|
byte[] bb = "\n".getBytes(cs);
|
||||||
|
if (bb.length != 1 || bb[0] != 0x15) {
|
||||||
|
System.out.printf(" error: %s c2b u+000A -> %x%n",
|
||||||
|
cs, bb[0] & 0xff);
|
||||||
|
errs++;
|
||||||
|
}
|
||||||
|
bb = "\u0085".getBytes(cs);
|
||||||
|
if (bb.length != 1 || bb[0] != 0x15) {
|
||||||
|
System.out.printf(" error: %s c2b u+0085 -> %x%n",
|
||||||
|
cs, bb[0] & 0xff);
|
||||||
|
errs++;
|
||||||
|
}
|
||||||
|
String str = new String(new byte[] { 0x15 }, cs);
|
||||||
|
if (!str.equals("\n")) {
|
||||||
|
System.out.printf(" error: %s b2c 0015 -> 0x%x%n",
|
||||||
|
cs, str.toCharArray()[0] & 0xffff);
|
||||||
|
}
|
||||||
|
str = new String(new byte[] { 0x25 }, cs);
|
||||||
|
if (!str.equals("\n")) {
|
||||||
|
System.out.printf(" error: %s b2c 0025 -> 0x%x%n",
|
||||||
|
cs, str.toCharArray()[0] & 0xffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errs > 0)
|
||||||
|
throw new Exception(errs + " error(s) detected");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user