1 /* 2 * Copyright (c) 2000, 2013, 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 6636323 6636319 7040220 7096080 7183053 8080248 26 * @summary Test if StringCoding and NIO result have the same de/encoding result 27 * @modules java.base/sun.nio.cs 28 * @run main/othervm/timeout=2000 TestStringCoding 29 * @key randomness 30 */ 31 32 import java.util.*; 33 import java.nio.*; 34 import java.nio.charset.*; 35 36 public class TestStringCoding { 37 public static void main(String[] args) throws Throwable { 38 39 for (Boolean hasSM: new boolean[] { false, true }) { 40 if (hasSM) 41 System.setSecurityManager(new PermissiveSecurityManger()); 42 for (Charset cs: Charset.availableCharsets().values()) { 43 if ("ISO-2022-CN".equals(cs.name()) || 44 "x-COMPOUND_TEXT".equals(cs.name()) || 45 "x-JISAutoDetect".equals(cs.name())) 46 continue; 47 System.out.printf("Testing(sm=%b) " + cs.name() + "....", hasSM); 48 // full bmp first 49 char[] bmpCA = new char[0x10000]; 50 for (int i = 0; i < 0x10000; i++) { 51 bmpCA[i] = (char)i; 52 } 53 byte[] sbBA = new byte[0x100]; 54 for (int i = 0; i < 0x100; i++) { 55 sbBA[i] = (byte)i; 56 } 57 test(cs, bmpCA, sbBA); 58 // "randomed" sizes 59 Random rnd = new Random(); 60 for (int i = 0; i < 10; i++) { 61 int clen = rnd.nextInt(0x10000); 62 int blen = rnd.nextInt(0x100); 63 //System.out.printf(" blen=%d, clen=%d%n", blen, clen); 64 test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen)); 65 //add a pair of surrogates 66 int pos = clen / 2; 67 if ((pos + 1) < blen) { 68 bmpCA[pos] = '\uD800'; 69 bmpCA[pos+1] = '\uDC00'; 70 } 71 test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen)); 72 } 73 74 testMixed(cs); 75 System.out.println("done!"); 76 } 77 } 78 } 79 80 static void testMixed(Charset cs) throws Throwable { 81 CharsetDecoder dec = cs.newDecoder() 82 .onMalformedInput(CodingErrorAction.REPLACE) 83 .onUnmappableCharacter(CodingErrorAction.REPLACE); 84 CharsetEncoder enc = cs.newEncoder() 85 .onMalformedInput(CodingErrorAction.REPLACE) 86 .onUnmappableCharacter(CodingErrorAction.REPLACE); 87 List<Integer> cps = new ArrayList<>(0x10000); 88 int off = 0; 89 int cp = 0; 90 while (cp < 0x10000) { 91 if (enc.canEncode((char)cp)) { 92 cps.add(cp); 93 } 94 cp++; 95 } 96 Collections.shuffle(cps); 97 char[] bmpCA = new char[cps.size()]; 98 for (int i = 0; i < cps.size(); i++) 99 bmpCA[i] = (char)(int)cps.get(i); 100 String bmpStr = new String(bmpCA); 101 //getBytes(csn); 102 byte[] bmpBA = bmpStr.getBytes(cs.name()); 103 ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA)); 104 byte[] baNIO = new byte[bf.limit()]; 105 bf.get(baNIO, 0, baNIO.length); 106 if (!Arrays.equals(bmpBA, baNIO)) { 107 throw new RuntimeException("getBytes(csn) failed -> " + cs.name()); 108 } 109 110 //getBytes(cs); 111 bmpBA = bmpStr.getBytes(cs); 112 if (!Arrays.equals(bmpBA, baNIO)) 113 throw new RuntimeException("getBytes(cs) failed -> " + cs.name()); 114 115 //new String(csn); 116 String strSC = new String(bmpBA, cs.name()); 117 String strNIO = dec.reset().decode(ByteBuffer.wrap(bmpBA)).toString(); 118 if(!strNIO.equals(strSC)) { 119 throw new RuntimeException("new String(csn) failed -> " + cs.name()); 120 } 121 122 //new String(cs); 123 strSC = new String(bmpBA, cs); 124 if (!strNIO.equals(strSC)) 125 throw new RuntimeException("new String(cs) failed -> " + cs.name()); 126 127 } 128 129 static void test(Charset cs, char[] bmpCA, byte[] sbBA) throws Throwable { 130 String bmpStr = new String(bmpCA); 131 CharsetDecoder dec = cs.newDecoder() 132 .onMalformedInput(CodingErrorAction.REPLACE) 133 .onUnmappableCharacter(CodingErrorAction.REPLACE); 134 CharsetEncoder enc = cs.newEncoder() 135 .onMalformedInput(CodingErrorAction.REPLACE) 136 .onUnmappableCharacter(CodingErrorAction.REPLACE); 137 138 //getBytes(csn); 139 byte[] baSC = bmpStr.getBytes(cs.name()); 140 ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA)); 141 byte[] baNIO = new byte[bf.limit()]; 142 bf.get(baNIO, 0, baNIO.length); 143 if (!Arrays.equals(baSC, baNIO)) 144 throw new RuntimeException("getBytes(csn) failed -> " + cs.name()); 145 146 //getBytes(cs); 147 baSC = bmpStr.getBytes(cs); 148 if (!Arrays.equals(baSC, baNIO)) 149 throw new RuntimeException("getBytes(cs) failed -> " + cs.name()); 150 151 //new String(csn); 152 String strSC = new String(sbBA, cs.name()); 153 String strNIO = dec.reset().decode(ByteBuffer.wrap(sbBA)).toString(); 154 155 if(!strNIO.equals(strSC)) 156 throw new RuntimeException("new String(csn) failed -> " + cs.name()); 157 158 //new String(cs); 159 strSC = new String(sbBA, cs); 160 if (!strNIO.equals(strSC)) 161 throw new RuntimeException("new String(cs) failed -> " + cs.name()); 162 163 //encode unmappable surrogates 164 if (enc instanceof sun.nio.cs.ArrayEncoder && 165 cs.contains(Charset.forName("ASCII"))) { 166 if (cs.name().equals("UTF-8") || // utf8 handles surrogates 167 cs.name().equals("CESU-8")) // utf8 handles surrogates 168 return; 169 enc.replaceWith(new byte[] { (byte)'A'}); 170 sun.nio.cs.ArrayEncoder cae = (sun.nio.cs.ArrayEncoder)enc; 171 172 String str = "ab\uD800\uDC00\uD800\uDC00cd"; 173 byte[] ba = new byte[str.length() - 2]; 174 int n = cae.encode(str.toCharArray(), 0, str.length(), ba); 175 if (n != 6 || !"abAAcd".equals(new String(ba, cs.name()))) 176 throw new RuntimeException("encode1(surrogates) failed -> " 177 + cs.name()); 178 179 ba = new byte[str.length()]; 180 n = cae.encode(str.toCharArray(), 0, str.length(), ba); 181 if (n != 6 || !"abAAcd".equals(new String(ba, 0, n, 182 cs.name()))) 183 throw new RuntimeException("encode2(surrogates) failed -> " 184 + cs.name()); 185 str = "ab\uD800B\uDC00Bcd"; 186 ba = new byte[str.length()]; 187 n = cae.encode(str.toCharArray(), 0, str.length(), ba); 188 if (n != 8 || !"abABABcd".equals(new String(ba, 0, n, 189 cs.name()))) 190 throw new RuntimeException("encode3(surrogates) failed -> " 191 + cs.name()); 192 /* sun.nio.cs.ArrayDeEncoder works on the assumption that the 193 invoker (StringCoder) allocates enough output buf, utf8 194 and double-byte coder does not check the output buffer limit. 195 ba = new byte[str.length() - 1]; 196 n = cae.encode(str.toCharArray(), 0, str.length(), ba); 197 if (n != 7 || !"abABABc".equals(new String(ba, 0, n, cs.name()))) { 198 throw new RuntimeException("encode4(surrogates) failed -> " 199 + cs.name()); 200 } 201 */ 202 } 203 204 //encode mappable surrogates for hkscs 205 if (cs.name().equals("Big5-HKSCS") || cs.name().equals("x-MS950-HKSCS")) { 206 String str = "ab\uD840\uDD0Ccd"; 207 byte[] expected = new byte[] {(byte)'a', (byte)'b', 208 (byte)0x88, (byte)0x45, (byte)'c', (byte)'d' }; 209 if (!Arrays.equals(str.getBytes(cs.name()), expected) || 210 !Arrays.equals(str.getBytes(cs), expected)) { 211 throw new RuntimeException("encode(surrogates) failed -> " 212 + cs.name()); 213 } 214 } 215 } 216 217 static class PermissiveSecurityManger extends SecurityManager { 218 @Override public void checkPermission(java.security.Permission p) {} 219 } 220 }