1/*
2 * Copyright (c) 2015, 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
24import java.util.Arrays;
25
26import org.testng.annotations.Test;
27
28import static org.testng.Assert.assertEquals;
29import static org.testng.Assert.assertTrue;
30
31/*
32 * @test
33 * @bug 8054307 8077559
34 * @summary Tests Compact String. This test is testing StringBuilder
35 *          behavior related to Compact String.
36 * @run testng/othervm -XX:+CompactStrings CompactStringBuilder
37 * @run testng/othervm -XX:-CompactStrings CompactStringBuilder
38 */
39
40public class CompactStringBuilder {
41
42    /*
43     * Tests for "A"
44     */
45    @Test
46    public void testCompactStringBuilderForLatinA() {
47        final String ORIGIN = "A";
48        /*
49         * Because right now ASCII is the default encoding parameter for source
50         * code in JDK build environment, so we escape them. same as below.
51         */
52        check(new StringBuilder(ORIGIN).append(new char[] { '\uFF21' }),
53                "A\uFF21");
54        check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
55                "A\uFF21");
56        check(new StringBuilder(ORIGIN).append("\uFF21"), "A\uFF21");
57        check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
58                "A\uFF21");
59        check(new StringBuilder(ORIGIN).delete(0, 1), "");
60        check(new StringBuilder(ORIGIN).delete(0, 0), "A");
61        check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
62        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 0);
63        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), -1);
64        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
65        assertEquals(new StringBuilder(ORIGIN).insert(1, "\uD801\uDC00")
66                .indexOf("A", 0), 0);
67        assertEquals(new StringBuilder(ORIGIN).insert(0, "\uD801\uDC00")
68                .indexOf("A", 0), 2);
69        check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "A");
70        check(new StringBuilder(ORIGIN).insert(1, new char[] { '\uFF21' }),
71                "A\uFF21");
72        check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
73                "\uFF21A");
74        check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("\uFF21")),
75                "\uFF21A");
76        check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("\uFF21")),
77                "A\uFF21");
78        check(new StringBuilder(ORIGIN).insert(0, ""), "A");
79        check(new StringBuilder(ORIGIN).insert(0, "\uFF21"), "\uFF21A");
80        check(new StringBuilder(ORIGIN).insert(1, "\uFF21"), "A\uFF21");
81        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
82        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
83        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
84        check(new StringBuilder(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A");
85        check(new StringBuilder(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21");
86        checkSetCharAt(new StringBuilder(ORIGIN), 0, '\uFF21', "\uFF21");
87        checkSetLength(new StringBuilder(ORIGIN), 0, "");
88        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
89        check(new StringBuilder(ORIGIN).substring(0), "A");
90        check(new StringBuilder(ORIGIN).substring(1), "");
91    }
92
93    /*
94     * Tests for "\uFF21"
95     */
96    @Test
97    public void testCompactStringBuilderForNonLatinA() {
98        final String ORIGIN = "\uFF21";
99        check(new StringBuilder(ORIGIN).append(new char[] { 'A' }), "\uFF21A");
100        check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
101        check(new StringBuilder(ORIGIN).append("A"), "\uFF21A");
102        check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
103        check(new StringBuilder(ORIGIN).delete(0, 1), "");
104        check(new StringBuilder(ORIGIN).delete(0, 0), "\uFF21");
105        check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
106        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), -1);
107        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
108        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
109        check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "\uFF21");
110        check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A");
111        check(new StringBuilder(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21");
112        check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("A")),
113                "A\uFF21");
114        check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("A")),
115                "\uFF21A");
116        check(new StringBuilder(ORIGIN).insert(0, ""), "\uFF21");
117        check(new StringBuilder(ORIGIN).insert(0, "A"), "A\uFF21");
118        check(new StringBuilder(ORIGIN).insert(1, "A"), "\uFF21A");
119        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
120        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
121        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
122        check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21");
123        check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "A");
124        checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "A");
125        checkSetLength(new StringBuilder(ORIGIN), 0, "");
126        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
127        check(new StringBuilder(ORIGIN).substring(0), "\uFF21");
128        check(new StringBuilder(ORIGIN).substring(1), "");
129    }
130
131    /*
132     * Tests for "\uFF21A"
133     */
134    @Test
135    public void testCompactStringBuilderForMixedA1() {
136        final String ORIGIN = "\uFF21A";
137        check(new StringBuilder(ORIGIN).delete(0, 1), "A");
138        check(new StringBuilder(ORIGIN).delete(1, 2), "\uFF21");
139        check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uFF21");
140        check(new StringBuilder(ORIGIN).deleteCharAt(0), "A");
141        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 1);
142        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
143        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
144        check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }),
145                "\uFF21AA");
146        check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
147                "\uFF21\uFF21A");
148        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 1);
149        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
150        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 2);
151        check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21A");
152        check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "AA");
153        checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "AA");
154        checkSetLength(new StringBuilder(ORIGIN), 0, "");
155        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
156        check(new StringBuilder(ORIGIN).substring(0), "\uFF21A");
157        check(new StringBuilder(ORIGIN).substring(1), "A");
158    }
159
160    /*
161     * Tests for "A\uFF21"
162     */
163    @Test
164    public void testCompactStringBuilderForMixedA2() {
165        final String ORIGIN = "A\uFF21";
166        check(new StringBuilder(ORIGIN).replace(1, 2, "A"), "AA");
167        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
168        check(new StringBuilder(ORIGIN).substring(0), "A\uFF21");
169        check(new StringBuilder(ORIGIN).substring(1), "\uFF21");
170        check(new StringBuilder(ORIGIN).substring(0, 1), "A");
171    }
172
173    /*
174     * Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"
175     */
176    @Test
177    public void testCompactStringBuilderForDuplicatedMixedA1() {
178        final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
179        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
180        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 5);
181        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 6);
182        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 9);
183        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 8);
184        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 10);
185        check(new StringBuilder(ORIGIN).substring(9), "A");
186        check(new StringBuilder(ORIGIN).substring(8), "\uFF21A");
187    }
188
189    /*
190     * Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"
191     */
192    @Test
193    public void testCompactStringBuilderForDuplicatedMixedA2() {
194        final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
195        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
196        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 6);
197        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 5);
198        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 8);
199        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 9);
200        check(new StringBuilder(ORIGIN).substring(9), "\uFF21");
201        check(new StringBuilder(ORIGIN).substring(8), "A\uFF21");
202    }
203
204    /*
205     * Tests for "\uD801\uDC00\uD801\uDC01"
206     */
207    @Test
208    public void testCompactStringForSupplementaryCodePoint() {
209        final String ORIGIN = "\uD801\uDC00\uD801\uDC01";
210        check(new StringBuilder(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A");
211        check(new StringBuilder(ORIGIN).append("\uFF21"),
212                "\uD801\uDC00\uD801\uDC01\uFF21");
213        check(new StringBuilder(ORIGIN).appendCodePoint('A'),
214                "\uD801\uDC00\uD801\uDC01A");
215        check(new StringBuilder(ORIGIN).appendCodePoint('\uFF21'),
216                "\uD801\uDC00\uD801\uDC01\uFF21");
217        assertEquals(new StringBuilder(ORIGIN).charAt(0), '\uD801');
218        assertEquals(new StringBuilder(ORIGIN).codePointAt(0),
219                Character.codePointAt(ORIGIN, 0));
220        assertEquals(new StringBuilder(ORIGIN).codePointAt(1),
221                Character.codePointAt(ORIGIN, 1));
222        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
223                Character.codePointAt(ORIGIN, 0));
224        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
225        check(new StringBuilder(ORIGIN).delete(0, 2), "\uD801\uDC01");
226        check(new StringBuilder(ORIGIN).delete(0, 3), "\uDC01");
227        check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01");
228        checkGetChars(new StringBuilder(ORIGIN), 0, 3, new char[] { '\uD801',
229                '\uDC00', '\uD801' });
230        assertEquals(new StringBuilder(ORIGIN).indexOf("\uD801\uDC01"), 2);
231        assertEquals(new StringBuilder(ORIGIN).indexOf("\uDC01"), 3);
232        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), -1);
233        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), -1);
234        check(new StringBuilder(ORIGIN).insert(0, "\uFF21"),
235                "\uFF21\uD801\uDC00\uD801\uDC01");
236        check(new StringBuilder(ORIGIN).insert(1, "\uFF21"),
237                "\uD801\uFF21\uDC00\uD801\uDC01");
238        check(new StringBuilder(ORIGIN).insert(1, "A"),
239                "\uD801A\uDC00\uD801\uDC01");
240        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uDC00\uD801"), 1);
241        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uD801"), 2);
242        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
243        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
244        assertEquals(new StringBuilder(ORIGIN).length(), 4);
245        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
246        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
247        check(new StringBuilder(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01");
248        check(new StringBuilder(ORIGIN).replace(0, 3, "A"), "A\uDC01");
249        check(new StringBuilder(ORIGIN).replace(0, 2, "\uFF21"),
250                "\uFF21\uD801\uDC01");
251        check(new StringBuilder(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01");
252        check(new StringBuilder(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00");
253        checkSetCharAt(new StringBuilder(ORIGIN), 1, '\uDC01',
254                "\uD801\uDC01\uD801\uDC01");
255        checkSetCharAt(new StringBuilder(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01");
256        checkSetLength(new StringBuilder(ORIGIN), 2, "\uD801\uDC00");
257        checkSetLength(new StringBuilder(ORIGIN), 3, "\uD801\uDC00\uD801");
258        check(new StringBuilder(ORIGIN).substring(1, 3), "\uDC00\uD801");
259    }
260
261    /*
262     * Tests for "A\uD801\uDC00\uFF21"
263     */
264    @Test
265    public void testCompactStringForSupplementaryCodePointMixed1() {
266        final String ORIGIN = "A\uD801\uDC00\uFF21";
267        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
268                Character.codePointAt(ORIGIN, 1));
269        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uD801');
270        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
271        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
272        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
273        check(new StringBuilder(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21");
274        check(new StringBuilder(ORIGIN).delete(0, 1).delete(2, 3),
275                "\uD801\uDC00");
276        check(new StringBuilder(ORIGIN).deleteCharAt(3).deleteCharAt(0),
277                "\uD801\uDC00");
278        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), 3);
279        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 0);
280        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 3);
281        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
282        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
283        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 3);
284        check(new StringBuilder(ORIGIN).replace(1, 3, "A"), "AA\uFF21");
285        check(new StringBuilder(ORIGIN).replace(1, 4, "A"), "AA");
286        check(new StringBuilder(ORIGIN).replace(1, 4, ""), "A");
287        check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uD801\uDC00A");
288        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
289        check(new StringBuilder(ORIGIN).substring(0, 1), "A");
290    }
291
292    /*
293     * Tests for "\uD801\uDC00\uFF21A"
294     */
295    @Test
296    public void testCompactStringForSupplementaryCodePointMixed2() {
297        final String ORIGIN = "\uD801\uDC00\uFF21A";
298        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
299                Character.codePointAt(ORIGIN, 2));
300        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
301                Character.codePointAt(ORIGIN, 0));
302        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
303        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
304        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
305        check(new StringBuilder(ORIGIN).delete(0, 2), "\uFF21A");
306        check(new StringBuilder(ORIGIN).delete(0, 3), "A");
307        check(new StringBuilder(ORIGIN).deleteCharAt(0).deleteCharAt(0)
308                .deleteCharAt(0), "A");
309        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 3);
310        assertEquals(new StringBuilder(ORIGIN).delete(0, 3).indexOf("A"), 0);
311        assertEquals(new StringBuilder(ORIGIN).replace(0, 3, "B").indexOf("A"),
312                1);
313        assertEquals(new StringBuilder(ORIGIN).substring(3, 4).indexOf("A"), 0);
314        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
315        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
316        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
317        check(new StringBuilder(ORIGIN).replace(0, 3, "B"), "BA");
318        check(new StringBuilder(ORIGIN).reverse(), "A\uFF21\uD801\uDC00");
319    }
320
321    /*
322     * Tests for "\uD801A\uDC00\uFF21"
323     */
324    @Test
325    public void testCompactStringForSupplementaryCodePointMixed3() {
326        final String ORIGIN = "\uD801A\uDC00\uFF21";
327        assertEquals(new StringBuilder(ORIGIN).codePointAt(1), 'A');
328        assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uFF21');
329        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
330        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), 'A');
331        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uDC00');
332        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
333        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
334        assertEquals(new StringBuilder(ORIGIN).delete(0, 1).delete(1, 3)
335                .indexOf("A"), 0);
336        assertEquals(
337                new StringBuilder(ORIGIN).replace(0, 1, "B").replace(2, 4, "C")
338                        .indexOf("A"), 1);
339        assertEquals(new StringBuilder(ORIGIN).substring(1, 4).substring(0, 1)
340                .indexOf("A"), 0);
341        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
342        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
343        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
344        check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uDC00A\uD801");
345    }
346
347    /*
348     * Tests for "A\uDC01\uFF21\uD801"
349     */
350    @Test
351    public void testCompactStringForSupplementaryCodePointMixed4() {
352        final String ORIGIN = "A\uDC01\uFF21\uD801";
353        assertEquals(new StringBuilder(ORIGIN).codePointAt(1), '\uDC01');
354        assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uD801');
355        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
356        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uDC01');
357        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uFF21');
358        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
359        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
360        assertEquals(new StringBuilder(ORIGIN).delete(1, 4).indexOf("A"), 0);
361        assertEquals(new StringBuilder(ORIGIN).replace(1, 4, "B").indexOf("A"),
362                0);
363        assertEquals(new StringBuilder(ORIGIN).substring(0, 1).indexOf("A"), 0);
364        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
365        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
366        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
367        check(new StringBuilder(ORIGIN).reverse(), "\uD801\uFF21\uDC01A");
368    }
369
370    private void checkGetChars(StringBuilder sb, int srcBegin, int srcEnd,
371            char expected[]) {
372        char[] dst = new char[srcEnd - srcBegin];
373        sb.getChars(srcBegin, srcEnd, dst, 0);
374        assertTrue(Arrays.equals(dst, expected));
375    }
376
377    private void checkSetCharAt(StringBuilder sb, int index, char ch,
378            String expected) {
379        sb.setCharAt(index, ch);
380        check(sb, expected);
381    }
382
383    private void checkSetLength(StringBuilder sb, int newLength, String expected) {
384        sb.setLength(newLength);
385        check(sb, expected);
386    }
387
388    private void check(StringBuilder sb, String expected) {
389        check(sb.toString(), expected);
390    }
391
392    private void check(String str, String expected) {
393        assertTrue(str.equals(expected), String.format(
394                "Get (%s) but expect (%s), ", escapeNonASCIIs(str),
395                escapeNonASCIIs(expected)));
396    }
397
398    /*
399     * Because right now system default charset in JPRT environment is only
400     * guaranteed to support ASCII characters in log, so we escape them.
401     */
402    private String escapeNonASCIIs(String str) {
403        StringBuilder sb = new StringBuilder();
404        for (int i = 0; i < str.length(); i++) {
405            char c = str.charAt(i);
406            if (c > 0x7F) {
407                sb.append("\\u").append(Integer.toHexString((int) c));
408            } else {
409                sb.append(c);
410            }
411        }
412        return sb.toString();
413    }
414}
415