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