Path: blob/master/test/jdk/java/lang/StringBuffer/Supplementary.java
41149 views
/*1* Copyright (c) 2003, 2020, 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 5017280 693711227* @summary Unit tests for supplementary character support (JSR-204)28*/2930import java.util.HexFormat;3132public class Supplementary {3334public static void main(String[] args) {35test1(); // Test for codePointAt(int index)36test2(); // Test for codePointBefore(int index)37test3(); // Test for reverse()38test4(); // Test for appendCodePoint(int codePoint)39test5(); // Test for codePointCount(int beginIndex, int endIndex)40test6(); // Test for offsetByCodePoints(int index, int offset)41}4243/* Text strings which are used as input data.44* The comment above each text string means the index of each 16-bit char45* for convenience.46*/47static final String[] input = {48/* 111 1 111111 22222490123 4 5678 9 012 3 456789 01234 */50"abc\uD800\uDC00def\uD800\uD800ab\uD800\uDC00cdefa\uDC00bcdef",51/* 1 1111 1111 1 222520 12345 6789 0 1234 5678 9 012 */53"\uD800defg\uD800hij\uD800\uDC00klm\uDC00nop\uDC00\uD800rt\uDC00",54/* 11 1 1111 1 112 222550 12345 6 78901 2 3456 7 890 123 */56"\uDC00abcd\uDBFF\uDFFFefgh\uD800\uDC009ik\uDC00\uDC00lm\uDC00no\uD800",57/* 111 111111 1 22 2580 1 2345 678 9 012 345678 9 01 2 */59"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",6061// includes an undefined supplementary character in Unicode 4.0.062/* 1 11 1 1111 1630 1 2345 6 789 0 12 3 4567 8 */64"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",65};666768/* Expected results for:69* test1(): for codePointAt()70*71* Each character in each array is the golden data for each text string72* in the above input data. For example, the first data in each array is73* for the first input string.74*/75static final int[][] golden1 = {76{'a', 0xD800, 0xDC00, 0x10000, 0xE0200}, // codePointAt(0)77{0xD800, 0x10000, 'g', 0xDC00, 0xE0202}, // codePointAt(9)78{'f', 0xDC00, 0xD800, 0xDC00, 0xDE02}, // codePointAt(length-1)79};8081/*82* Test for codePointAt(int index) method83*/84static void test1() {8586for (int i = 0; i < input.length; i++) {87StringBuffer sb = new StringBuffer(input[i]);8889/*90* Normal case91*/92testCodePoint(At, sb, 0, golden1[0][i]);93testCodePoint(At, sb, 9, golden1[1][i]);94testCodePoint(At, sb, sb.length()-1, golden1[2][i]);9596/*97* Abnormal case - verify that an exception is thrown.98*/99testCodePoint(At, sb, -1);100testCodePoint(At, sb, sb.length());101}102}103104105/* Expected results for:106* test2(): for codePointBefore()107*108* Each character in each array is the golden data for each text string109* in the above input data. For example, the first data in each array is110* for the first input string.111*/112static final int[][] golden2 = {113{'a', 0xD800, 0xDC00, 0xD800, 0xDB40}, // codePointBefore(1)114{0xD800, 'l', 0x10000, 0xDC00, 0xDB40}, // codePointBefore(13)115{'f', 0xDC00, 0xD800, 0x10000, 0xE0202}, // codePointBefore(length)116};117118/*119* Test for codePointBefore(int index) method120*/121static void test2() {122123for (int i = 0; i < input.length; i++) {124StringBuffer sb = new StringBuffer(input[i]);125126/*127* Normal case128*/129testCodePoint(Before, sb, 1, golden2[0][i]);130testCodePoint(Before, sb, 13, golden2[1][i]);131testCodePoint(Before, sb, sb.length(), golden2[2][i]);132133/*134* Abnormal case - verify that an exception is thrown.135*/136testCodePoint(Before, sb, 0);137testCodePoint(Before, sb, sb.length()+1);138}139}140141142/* Expected results for:143* test3(): for reverse()144*145* Unlike golden1 and golden2, each array is the golden data for each text146* string in the above input data. For example, the first array is for147* the first input string.148*/149static final String[] golden3 = {150"fedcb\uDC00afedc\uD800\uDC00ba\uD800\uD800fed\uD800\uDC00cba",151"\uDC00tr\uD800\uDC00pon\uDC00mlk\uD800\uDC00jih\uD800gfed\uD800",152"\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",153"\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",154155// includes an undefined supplementary character in Unicode 4.0.0156"\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",157};158159// Additional input data & expected result for test3()160static final String[][] testdata1 = {161{"a\uD800\uDC00", "\uD800\uDC00a"},162{"a\uDC00\uD800", "\uD800\uDC00a"},163{"\uD800\uDC00a", "a\uD800\uDC00"},164{"\uDC00\uD800a", "a\uD800\uDC00"},165{"\uDC00\uD800\uD801", "\uD801\uD800\uDC00"},166{"\uDC00\uD800\uDC01", "\uD800\uDC01\uDC00"},167{"\uD801\uD800\uDC00", "\uD800\uDC00\uD801"},168{"\uD800\uDC01\uDC00", "\uDC00\uD800\uDC01"},169{"\uD800\uDC00\uDC01\uD801", "\uD801\uDC01\uD800\uDC00"},170};171172/*173* Test for reverse() method174*/175static void test3() {176for (int i = 0; i < input.length; i++) {177StringBuffer sb = new StringBuffer(input[i]).reverse();178179check(!golden3[i].equals(new String(sb)),180"reverse() for <" + toHexString(input[i]) + ">",181sb, golden3[i]);182}183184for (int i = 0; i < testdata1.length; i++) {185StringBuffer sb = new StringBuffer(testdata1[i][0]).reverse();186187check(!testdata1[i][1].equals(new String(sb)),188"reverse() for <" + toHexString(testdata1[i][0]) + ">",189sb, testdata1[i][1]);190}191}192193/**194* Test for appendCodePoint() method195*/196static void test4() {197for (int i = 0; i < input.length; i++) {198String s = input[i];199StringBuffer sb = new StringBuffer();200int c;201for (int j = 0; j < s.length(); j += Character.charCount(c)) {202c = s.codePointAt(j);203StringBuffer rsb = sb.appendCodePoint(c);204check(sb != rsb, "appendCodePoint returned a wrong object");205int sbc = sb.codePointAt(j);206check(sbc != c, "appendCodePoint(j) != c", sbc, c);207}208check(!s.equals(sb.toString()),209"appendCodePoint() produced a wrong result with input["+i+"]");210}211212// test exception213testAppendCodePoint(-1, IllegalArgumentException.class);214testAppendCodePoint(Character.MAX_CODE_POINT+1, IllegalArgumentException.class);215}216217/**218* Test codePointCount(int, int)219*220* This test case assumes that221* Character.codePointCount(CharSequence, int, int) works222* correctly.223*/224static void test5() {225for (int i = 0; i < input.length; i++) {226String s = input[i];227StringBuffer sb = new StringBuffer(s);228int length = sb.length();229for (int j = 0; j <= length; j++) {230int result = sb.codePointCount(j, length);231int expected = Character.codePointCount(sb, j, length);232check(result != expected, "codePointCount(input["+i+"], "+j+", "+length+")",233result, expected);234}235for (int j = length; j >= 0; j--) {236int result = sb.codePointCount(0, j);237int expected = Character.codePointCount(sb, 0, j);238check(result != expected, "codePointCount(input["+i+"], 0, "+j+")",239result, expected);240}241242// test exceptions243testCodePointCount(null, 0, 0, NullPointerException.class);244testCodePointCount(sb, -1, length, IndexOutOfBoundsException.class);245testCodePointCount(sb, 0, length+1, IndexOutOfBoundsException.class);246testCodePointCount(sb, length, length-1, IndexOutOfBoundsException.class);247}248}249250/**251* Test offsetByCodePoints(int, int)252*253* This test case assumes that254* Character.codePointCount(CharSequence, int, int) works255* correctly.256*/257static void test6() {258for (int i = 0; i < input.length; i++) {259String s = input[i];260StringBuffer sb = new StringBuffer(s);261int length = s.length();262for (int j = 0; j <= length; j++) {263int nCodePoints = Character.codePointCount(sb, j, length);264int result = sb.offsetByCodePoints(j, nCodePoints);265check(result != length,266"offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",267result, length);268result = sb.offsetByCodePoints(length, -nCodePoints);269int expected = j;270if (j > 0 && j < length) {271int cp = sb.codePointBefore(j+1);272if (Character.isSupplementaryCodePoint(cp)) {273expected--;274}275}276check(result != expected,277"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",278result, expected);279}280for (int j = length; j >= 0; j--) {281int nCodePoints = Character.codePointCount(sb, 0, j);282int result = sb.offsetByCodePoints(0, nCodePoints);283int expected = j;284if (j > 0 && j < length) {285int cp = sb.codePointAt(j-1);286if (Character.isSupplementaryCodePoint(cp)) {287expected++;288}289}290check(result != expected,291"offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",292result, expected);293result = sb.offsetByCodePoints(j, -nCodePoints);294check(result != 0,295"offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",296result, 0);297}298299// test exceptions300testOffsetByCodePoints(null, 0, 0, NullPointerException.class);301testOffsetByCodePoints(sb, -1, length, IndexOutOfBoundsException.class);302testOffsetByCodePoints(sb, 0, length+1, IndexOutOfBoundsException.class);303testOffsetByCodePoints(sb, 1, -2, IndexOutOfBoundsException.class);304testOffsetByCodePoints(sb, length, length-1, IndexOutOfBoundsException.class);305testOffsetByCodePoints(sb, length, -(length+1), IndexOutOfBoundsException.class);306}307}308309310static final boolean At = true, Before = false;311312static void testCodePoint(boolean isAt, StringBuffer sb, int index, int expected) {313int c = isAt ? sb.codePointAt(index) : sb.codePointBefore(index);314315check(c != expected,316"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"317+ sb + ">", c, expected);318}319320static void testCodePoint(boolean isAt, StringBuffer sb, int index) {321boolean exceptionOccurred = false;322323try {324int c = isAt ? sb.codePointAt(index) : sb.codePointBefore(index);325}326catch (StringIndexOutOfBoundsException e) {327exceptionOccurred = true;328}329check(!exceptionOccurred,330"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"331+ sb + "> should throw StringIndexOutOfBoundsPointerException.");332}333334static void testAppendCodePoint(int codePoint, Class expectedException) {335try {336new StringBuffer().appendCodePoint(codePoint);337} catch (Exception e) {338if (expectedException.isInstance(e)) {339return;340}341throw new RuntimeException("Error: Unexpected exception", e);342}343check(true, "appendCodePoint(" + toHexString(codePoint) + ") didn't throw "344+ expectedException.getName());345}346347static void testCodePointCount(StringBuffer sb, int beginIndex, int endIndex,348Class expectedException) {349try {350int n = sb.codePointCount(beginIndex, endIndex);351} catch (Exception e) {352if (expectedException.isInstance(e)) {353return;354}355throw new RuntimeException("Error: Unexpected exception", e);356}357check(true, "codePointCount() didn't throw " + expectedException.getName());358}359360static void testOffsetByCodePoints(StringBuffer sb, int index, int offset,361Class expectedException) {362try {363int n = sb.offsetByCodePoints(index, offset);364} catch (Exception e) {365if (expectedException.isInstance(e)) {366return;367}368throw new RuntimeException("Error: Unexpected exception", e);369}370check(true, "offsetByCodePoints() didn't throw " + expectedException.getName());371}372373static void check(boolean err, String msg) {374if (err) {375throw new RuntimeException("Error: " + msg);376}377}378379static void check(boolean err, String s, int got, int expected) {380if (err) {381throw new RuntimeException("Error: " + s382+ " returned an unexpected value. got "383+ toHexString(got)384+ ", expected "385+ toHexString(expected));386}387}388389static void check(boolean err, String s, StringBuffer got, String expected) {390if (err) {391throw new RuntimeException("Error: " + s392+ " returned an unexpected value. got <"393+ toHexString(new String(got))394+ ">, expected <"395+ toHexString(expected)396+ ">");397}398}399400private static String toHexString(int c) {401return "0x" + Integer.toHexString(c);402}403404private static String toHexString(String s) {405HexFormat format = HexFormat.of();406StringBuilder sb = new StringBuilder();407for (int i = 0; i < s.length(); i++) {408char c = s.charAt(i);409410sb.append(" 0x");411sb.append(format.toHexDigits(c));412}413sb.append(' ');414return sb.toString();415}416}417418419