Path: blob/master/test/jdk/java/lang/StringBuilder/Supplementary.java
41149 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24*25* @test26* @bug 4533872 4915683 4985217 501728027* @summary Unit tests for supplementary character support (JSR-204)28*/2930public class Supplementary {3132public static void main(String[] args) {33test1(); // Test for codePointAt(int index)34test2(); // Test for codePointBefore(int index)35test3(); // Test for reverse()36test4(); // Test for appendCodePoint(int codePoint)37test5(); // Test for codePointCount(int beginIndex, int endIndex)38test6(); // Test for offsetByCodePoints(int index, int offset)39testDontReadOutOfBoundsTrailingSurrogate();40}4142/* Text strings which are used as input data.43* The comment above each text string means the index of each 16-bit char44* for convenience.45*/46static final String[] input = {47/* 111 1 111111 22222480123 4 5678 9 012 3 456789 01234 */49"abc\uD800\uDC00def\uD800\uD800ab\uD800\uDC00cdefa\uDC00bcdef",50/* 1 1111 1111 1 222510 12345 6789 0 1234 5678 9 012 */52"\uD800defg\uD800hij\uD800\uDC00klm\uDC00nop\uDC00\uD800rt\uDC00",53/* 11 1 1111 1 112 222540 12345 6 78901 2 3456 7 890 123 */55"\uDC00abcd\uDBFF\uDFFFefgh\uD800\uDC009ik\uDC00\uDC00lm\uDC00no\uD800",56/* 111 111111 1 22 2570 1 2345 678 9 012 345678 9 01 2 */58"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",5960// includes an undefined supplementary character in Unicode 4.0.061/* 1 11 1 1111 1620 1 2345 6 789 0 12 3 4567 8 */63"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",64};656667/* Expected results for:68* test1(): for codePointAt()69*70* Each character in each array is the golden data for each text string71* in the above input data. For example, the first data in each array is72* for the first input string.73*/74static final int[][] golden1 = {75{'a', 0xD800, 0xDC00, 0x10000, 0xE0200}, // codePointAt(0)76{0xD800, 0x10000, 'g', 0xDC00, 0xE0202}, // codePointAt(9)77{'f', 0xDC00, 0xD800, 0xDC00, 0xDE02}, // codePointAt(length-1)78};7980/*81* Test for codePointAt(int index) method82*/83static void test1() {8485for (int i = 0; i < input.length; i++) {86StringBuilder sb = new StringBuilder(input[i]);8788/*89* Normal case90*/91testCodePoint(At, sb, 0, golden1[0][i]);92testCodePoint(At, sb, 9, golden1[1][i]);93testCodePoint(At, sb, sb.length()-1, golden1[2][i]);9495/*96* Abnormal case - verify that an exception is thrown.97*/98testCodePoint(At, sb, -1);99testCodePoint(At, sb, sb.length());100}101}102103104/* Expected results for:105* test2(): for codePointBefore()106*107* Each character in each array is the golden data for each text string108* in the above input data. For example, the first data in each array is109* for the first input string.110*/111static final int[][] golden2 = {112{'a', 0xD800, 0xDC00, 0xD800, 0xDB40}, // codePointBefore(1)113{0xD800, 'l', 0x10000, 0xDC00, 0xDB40}, // codePointBefore(13)114{'f', 0xDC00, 0xD800, 0x10000, 0xE0202}, // codePointBefore(length)115};116117/*118* Test for codePointBefore(int index) method119*/120static void test2() {121122for (int i = 0; i < input.length; i++) {123StringBuilder sb = new StringBuilder(input[i]);124125/*126* Normal case127*/128testCodePoint(Before, sb, 1, golden2[0][i]);129testCodePoint(Before, sb, 13, golden2[1][i]);130testCodePoint(Before, sb, sb.length(), golden2[2][i]);131132/*133* Abnormal case - verify that an exception is thrown.134*/135testCodePoint(Before, sb, 0);136testCodePoint(Before, sb, sb.length()+1);137}138}139140141/* Expected results for:142* test3(): for reverse()143*144* Unlike golden1 and golden2, each array is the golden data for each text145* string in the above input data. For example, the first array is for146* the first input string.147*/148static final String[] golden3 = {149"fedcb\uDC00afedc\uD800\uDC00ba\uD800\uD800fed\uD800\uDC00cba",150"\uDC00tr\uD800\uDC00pon\uDC00mlk\uD800\uDC00jih\uD800gfed\uD800",151"\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",152"\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",153154// includes an undefined supplementary character in Unicode 4.0.0155"\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",156};157158// Additional input data & expected result for test3()159static final String[][] testdata1 = {160{"a\uD800\uDC00", "\uD800\uDC00a"},161{"a\uDC00\uD800", "\uD800\uDC00a"},162{"\uD800\uDC00a", "a\uD800\uDC00"},163{"\uDC00\uD800a", "a\uD800\uDC00"},164{"\uDC00\uD800\uD801", "\uD801\uD800\uDC00"},165{"\uDC00\uD800\uDC01", "\uD800\uDC01\uDC00"},166{"\uD801\uD800\uDC00", "\uD800\uDC00\uD801"},167{"\uD800\uDC01\uDC00", "\uDC00\uD800\uDC01"},168{"\uD800\uDC00\uDC01\uD801", "\uD801\uDC01\uD800\uDC00"},169};170171/*172* Test for reverse() method173*/174static void test3() {175for (int i = 0; i < input.length; i++) {176StringBuilder sb = new StringBuilder(input[i]).reverse();177178check(!golden3[i].equals(sb.toString()),179"reverse() for <" + toHexString(input[i]) + ">",180sb, golden3[i]);181}182183for (int i = 0; i < testdata1.length; i++) {184StringBuilder sb = new StringBuilder(testdata1[i][0]).reverse();185186check(!testdata1[i][1].equals(sb.toString()),187"reverse() for <" + toHexString(testdata1[i][0]) + ">",188sb, testdata1[i][1]);189}190}191192/**193* Test for appendCodePoint() method194*/195static void test4() {196for (int i = 0; i < input.length; i++) {197String s = input[i];198StringBuilder sb = new StringBuilder();199int c;200for (int j = 0; j < s.length(); j += Character.charCount(c)) {201c = s.codePointAt(j);202StringBuilder rsb = sb.appendCodePoint(c);203check(sb != rsb, "appendCodePoint returned a wrong object");204int sbc = sb.codePointAt(j);205check(sbc != c, "appendCodePoint("+j+") != c", sbc, c);206}207check(!s.equals(sb.toString()),208"appendCodePoint() produced a wrong result with input["+i+"]");209}210211// test exception212testAppendCodePoint(-1, IllegalArgumentException.class);213testAppendCodePoint(Character.MAX_CODE_POINT+1, IllegalArgumentException.class);214}215216/**217* Test codePointCount(int, int)218*219* This test case assumes that220* Character.codePointCount(CharSequence, int, int) works221* correctly.222*/223static void test5() {224for (int i = 0; i < input.length; i++) {225String s = input[i];226StringBuilder sb = new StringBuilder(s);227int length = sb.length();228for (int j = 0; j <= length; j++) {229int result = sb.codePointCount(j, length);230int expected = Character.codePointCount(sb, j, length);231check(result != expected, "codePointCount(input["+i+"], "+j+", "+length+")",232result, expected);233}234for (int j = length; j >= 0; j--) {235int result = sb.codePointCount(0, j);236int expected = Character.codePointCount(sb, 0, j);237check(result != expected, "codePointCount(input["+i+"], 0, "+j+")",238result, expected);239}240241// test exceptions242testCodePointCount(null, 0, 0, NullPointerException.class);243testCodePointCount(sb, -1, length, IndexOutOfBoundsException.class);244testCodePointCount(sb, 0, length+1, IndexOutOfBoundsException.class);245testCodePointCount(sb, length, length-1, IndexOutOfBoundsException.class);246}247}248249/**250* Test offsetByCodePoints(int, int)251*252* This test case assumes that253* Character.codePointCount(CharSequence, int, int) works254* correctly.255*/256static void test6() {257for (int i = 0; i < input.length; i++) {258String s = input[i];259StringBuilder sb = new StringBuilder(s);260int length = s.length();261for (int j = 0; j <= length; j++) {262int nCodePoints = Character.codePointCount(sb, j, length);263int result = sb.offsetByCodePoints(j, nCodePoints);264check(result != length,265"offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",266result, length);267result = sb.offsetByCodePoints(length, -nCodePoints);268int expected = j;269if (j > 0 && j < length) {270int cp = sb.codePointBefore(j+1);271if (Character.isSupplementaryCodePoint(cp)) {272expected--;273}274}275check(result != expected,276"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",277result, expected);278}279for (int j = length; j >= 0; j--) {280int nCodePoints = Character.codePointCount(sb, 0, j);281int result = sb.offsetByCodePoints(0, nCodePoints);282int expected = j;283if (j > 0 && j < length) {284int cp = sb.codePointAt(j-1);285if (Character.isSupplementaryCodePoint(cp)) {286expected++;287}288}289check(result != expected,290"offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",291result, expected);292result = sb.offsetByCodePoints(j, -nCodePoints);293check(result != 0,294"offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",295result, 0);296}297298// test exceptions299testOffsetByCodePoints(null, 0, 0, NullPointerException.class);300testOffsetByCodePoints(sb, -1, length, IndexOutOfBoundsException.class);301testOffsetByCodePoints(sb, 0, length+1, IndexOutOfBoundsException.class);302testOffsetByCodePoints(sb, 1, -2, IndexOutOfBoundsException.class);303testOffsetByCodePoints(sb, length, length-1, IndexOutOfBoundsException.class);304testOffsetByCodePoints(sb, length, -(length+1), IndexOutOfBoundsException.class);305}306}307308static void testDontReadOutOfBoundsTrailingSurrogate() {309StringBuilder sb = new StringBuilder();310int suppl = Character.MIN_SUPPLEMENTARY_CODE_POINT;311sb.appendCodePoint(suppl);312check(sb.codePointAt(0) != (int) suppl,313"codePointAt(0)", sb.codePointAt(0), suppl);314check(sb.length() != 2, "sb.length()");315sb.setLength(1);316check(sb.length() != 1, "sb.length()");317check(sb.codePointAt(0) != Character.highSurrogate(suppl),318"codePointAt(0)",319sb.codePointAt(0), Character.highSurrogate(suppl));320}321322static final boolean At = true, Before = false;323324static void testCodePoint(boolean isAt, StringBuilder sb, int index, int expected) {325int c = isAt ? sb.codePointAt(index) : sb.codePointBefore(index);326327check(c != expected,328"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"329+ sb + ">", c, expected);330}331332static void testCodePoint(boolean isAt, StringBuilder sb, int index) {333boolean exceptionOccurred = false;334335try {336int c = isAt ? sb.codePointAt(index) : sb.codePointBefore(index);337}338catch (StringIndexOutOfBoundsException e) {339exceptionOccurred = true;340}341check(!exceptionOccurred,342"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"343+ sb + "> should throw StringIndexOutOfBoundsPointerException.");344}345346static void testAppendCodePoint(int codePoint, Class expectedException) {347try {348new StringBuilder().appendCodePoint(codePoint);349} catch (Exception e) {350if (expectedException.isInstance(e)) {351return;352}353throw new RuntimeException("Error: Unexpected exception", e);354}355check(true, "appendCodePoint(" + toHexString(codePoint) + ") didn't throw "356+ expectedException.getName());357}358359static void testCodePointCount(StringBuilder sb, int beginIndex, int endIndex,360Class expectedException) {361try {362int n = sb.codePointCount(beginIndex, endIndex);363} catch (Exception e) {364if (expectedException.isInstance(e)) {365return;366}367throw new RuntimeException("Error: Unexpected exception", e);368}369check(true, "codePointCount() didn't throw " + expectedException.getName());370}371372static void testOffsetByCodePoints(StringBuilder sb, int index, int offset,373Class expectedException) {374try {375int n = sb.offsetByCodePoints(index, offset);376} catch (Exception e) {377if (expectedException.isInstance(e)) {378return;379}380throw new RuntimeException("Error: Unexpected exception", e);381}382check(true, "offsetByCodePoints() didn't throw " + expectedException.getName());383}384385static void check(boolean err, String msg) {386if (err) {387throw new RuntimeException("Error: " + msg);388}389}390391static void check(boolean err, String s, int got, int expected) {392if (err) {393throw new RuntimeException("Error: " + s394+ " returned an unexpected value. got "395+ toHexString(got)396+ ", expected "397+ toHexString(expected));398}399}400401static void check(boolean err, String s, StringBuilder got, String expected) {402if (err) {403throw new RuntimeException("Error: " + s404+ " returned an unexpected value. got <"405+ toHexString(got.toString())406+ ">, expected <"407+ toHexString(expected)408+ ">");409}410}411412private static String toHexString(int c) {413return "0x" + Integer.toHexString(c);414}415416private static String toHexString(String s) {417StringBuilder sb = new StringBuilder();418for (int i = 0; i < s.length(); i++) {419char c = s.charAt(i);420421sb.append(" 0x");422if (c < 0x10) sb.append('0');423if (c < 0x100) sb.append('0');424if (c < 0x1000) sb.append('0');425sb.append(Integer.toHexString(c));426}427sb.append(' ');428return sb.toString();429}430}431432433