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