Path: blob/master/test/jdk/java/lang/String/Supplementary.java
41149 views
/*1* Copyright (c) 2003, 2010, 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 4922962 4985217 5017280 6242664 658826027* @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 indexOf(int ch)36test4(); // Test for indexOf(int ch, int fromIndex)37test5(); // Test for lastIndexOf(int ch)38test6(); // Test for lastIndexOf(int ch, int fromIndex)39test7(); // Test for String(int[] codePoint, int offset, int count)40test8(); // Test for codePointCount(int beginIndex, int endIndex)41test9(); // Test for offsetByCodePoints(int index, int offset)42test10(); // Test for offsetByCodePoints(int index, int offset)43// To verify the fix for 624266444}4546/* Text strings which are used as input data.47* The comment above each text string means the index of each 16-bit char48* for convenience.49*/50static final String[] input = {51/* 111 1 111111 22222520123 4 5678 9 012 3 456789 01234 */53"abc\uD800\uDC00def\uD800\uD800ab\uD800\uDC00cdefa\uDC00bcdef",54/* 1 1111 1111 1 222550 12345 6789 0 1234 5678 9 012 */56"\uD800defg\uD800hij\uD800\uDC00klm\uDC00nop\uDC00\uD800rt\uDC00",57/* 11 1 1111 1 112 222580 12345 6 78901 2 3456 7 890 123 */59"\uDC00abcd\uDBFF\uDFFFefgh\uD800\uDC009ik\uDC00\uDC00lm\uDC00no\uD800",60/* 111 111111 1 22 2610 1 2345 678 9 012 345678 9 01 2 */62"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",6364// includes an undefined supplementary character in Unicode 4.0.065/* 1 11 1 1111 1660 1 2345 6 789 0 12 3 4567 8 */67"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",6869// all supplementary characters70/* 1 1710 1 2 3 4 5 6 7 8 9 0 1 */72"\uD800\uDC00\uD800\uDC01\uD800\uDC02\uD800\uDC03\uD800\uDC04\uD800\uDC05"+73/* 1 1 1 1 1 1 1 1 2 2 2 2742 3 4 5 6 7 8 9 0 1 2 3 */75"\uD800\uDC06\uD800\uDC07\uD800\uDC08\uD800\uDC08\uD800\uDC09\uD800\uDC0A"+76/* 2 2 2 2 2 2 3 3 3 3 3 3774 5 6 7 8 9 0 1 2 3 4 5 */78"\uD800\uDC0B\uD800\uDC0C\uD800\uDC0D\uD800\uDC0A\uD800\uDC0F\uD800\uDC10"79};808182/* Expected results for:83* test1(): for codePointAt()84*85* Each character in each array is the golden data for each text string86* in the above input data. For example, the first data in each array is87* for the first input string.88*/89static final int[][] golden1 = {90{'a', 0xD800, 0xDC00, 0x10000, 0xE0200, 0x10000},// codePointAt(0)91{0xD800, 0x10000, 'g', 0xDC00, 0xE0202, 0xDC04}, // codePointAt(9)92{'f', 0xDC00, 0xD800, 0xDC00, 0xDE02, 0xDC10}, // codePointAt(length-1)93{'f', 'p', 0xDC00, '^', 0xE0202, 0xDC08}, // codePointAt() for a substring94};9596/*97* Test for codePointAt(int index) method98*/99static void test1() {100101for (int i = 0; i < input.length; i++) {102String s = input[i];103104/*105* Normal case106*/107testCodePoint(At, s, 0, golden1[0][i]);108testCodePoint(At, s, 9, golden1[1][i]);109testCodePoint(At, s, s.length()-1, golden1[2][i]);110testCodePoint(At, s.substring(17), 0, golden1[3][i]);111112/*113* Abnormal case - verify that an exception is thrown.114*/115testCodePoint(At, s, -1);116testCodePoint(At, s, s.length());117}118}119120121/* Expected results for:122* test2(): for codePointBefore()123*124* Each character in each array is the golden data for each text string125* in the above input data. For example, the first data in each array is126* for the first input string.127*/128static final int[][] golden2 = {129{'a', 0xD800, 0xDC00, 0xD800, 0xDB40, 0xD800}, // codePointBefore(1)130{0xD800, 'l', 0x10000, 0xDC00, 0xDB40, 0xD800}, // codePointBefore(13)131{'f', 0xDC00, 0xD800, 0x10000, 0xE0202, 0x10010},// codePointBefore(length)132{'b', 'd', 'a', 0xDC00, 0xDE00, 0xDC00}, // codePointBefore() for a substring133};134135/*136* Test for codePointBefore(int index) method137*/138static void test2() {139140for (int i = 0; i < input.length; i++) {141String s = input[i];142143/*144* Normal case145*/146testCodePoint(Before, s, 1, golden2[0][i]);147testCodePoint(Before, s, 13, golden2[1][i]);148testCodePoint(Before, s, s.length(), golden2[2][i]);149testCodePoint(Before, s.substring(1), 1, golden2[3][i]);150151/*152* Abnormal case - verify that an exception is thrown.153*/154testCodePoint(Before, s, 0);155testCodePoint(Before, s, s.length()+1);156}157}158159160/* Expected results for:161* test3(): for indexOf(int ch)162* test4(): for indexOf(int ch, int fromIndex)163* test5(): for lastIndexOf(int ch)164* test6(): for lastIndexOf(int ch, int fromIndex)165*166* Unlike golden1 and golden2, golden3[m][] is the golden data for text167* string in input[m].168*169* The meaning of each element in golden3[][n]170* golden3[][0]: character which is searched.171* golden3[][2]: the golden data for indexOf(int ch)172* From golden3[][2] to golden3[][n-1]:173* the golden data for indexOf(int ch, int fromIndex)174* The golden3[][n-2]: the golden data for lastIndexOf(int ch)175* From golden3[][1] to golden3[][n-2]:176* the golden data for lastIndexOf(int ch, int fromIndex)177*178* In other words, the data format is179* { ch, -1, index1, index2, ..., -1}180* where index1, index2, ... are all indices of the ch occurrences.181*/182static final int[][] golden3 = {183/* ch indices */184{'b', -1, 1, 11, 20, -1},185{0xD800, -1, 0, 5, 9, 19, -1},186{0xDC00, -1, 0, 12, 16, 17, 20, -1},187{0x10000, -1, 0, 8, 21, -1},188{0xE0202, -1, 9, 17, -1},189{0x1000A, -1, 22, 30, -1}190};191192/*193* Test for indexOf(int ch) method194*/195static void test3() {196197for (int i = 0; i < input.length; i++) {198String s = input[i];199200/*201* Normal case202*/203testIndexOf(s, golden3[i][0], golden3[i][2]);204205/*206* Abnormal case - char which isn't included in the string.207*/208testIndexOf(s, 'Z', -1);209testIndexOf(s, 0xDB98, -1);210testIndexOf(s, 0xDE76, -1);211testIndexOf(s, 0x12345, -1);212testIndexOf(s, -1, -1);213testIndexOf(s, 0x110000, -1);214}215}216217/*218* Test for indexOf(int ch, int fromIndex) method219*/220static void test4() {221222for (int i = 0; i < input.length; i++) {223String s = input[i];224int ch = golden3[i][0];225226/*227* Normal case228*/229int fromIndex = 0;230for (int j = 2; j < golden3[i].length; j++) {231fromIndex = testIndexOf(s, fromIndex, ch,232golden3[i][j]) + 1;233}234235/*236* Abnormal case1 - char is included in the string but fromIndex237* is incorrect.238*/239testIndexOf(s, -1, ch, golden3[i][2]);240testIndexOf(s, s.length(), ch,241golden3[i][golden3[i].length-1]);242243/*244* Abnormal case2 - char which isn't included in the string.245*/246testIndexOf(s, 0, 'Z', -1);247testIndexOf(s, 0, 0xDB98, -1);248testIndexOf(s, 0, 0xDE76, -1);249testIndexOf(s, 0, 0x12345, -1);250testIndexOf(s, 0, -1, -1);251testIndexOf(s, 0, 0x110000, -1);252}253}254255/*256* Test for lastIndexOf(int ch) method257*/258static void test5() {259260for (int i = 0; i < input.length; i++) {261String s = input[i];262263/*264* Normal case265*/266testLastIndexOf(s, golden3[i][0],267golden3[i][golden3[i].length-2]);268269/*270* Abnormal case - char which isn't included in the string.271*/272testLastIndexOf(s, 'Z', -1);273testLastIndexOf(s, 0xDB98, -1);274testLastIndexOf(s, 0xDE76, -1);275testLastIndexOf(s, 0x12345, -1);276testLastIndexOf(s, -1, -1);277testLastIndexOf(s, 0x110000, -1);278}279}280281/*282* Test for lastIndexOf(int ch, int fromIndex) method283*/284static void test6() {285286for (int i = 0; i < input.length; i++) {287String s = input[i];288int ch = golden3[i][0];289int len = s.length();290291/*292* Normal case293*/294int fromIndex = len - 1;295for (int j = golden3[i].length - 2; j > 0; j--) {296fromIndex = testLastIndexOf(s, fromIndex, ch,297golden3[i][j]) - 1;298}299300/*301* Abnormal case1 - char is included in the string but fromIndex302* is incorrect.303*/304testLastIndexOf(s, -1, ch, golden3[i][1]);305testLastIndexOf(s, len, ch, golden3[i][golden3[i].length-2]);306307/*308* Abnormal case2 - char which isn't included in the string.309*/310testLastIndexOf(s, len, 'Z', -1);311testLastIndexOf(s, len, 0xDB98, -1);312testLastIndexOf(s, len, 0xDE76, -1);313testLastIndexOf(s, len, 0x12345, -1);314testLastIndexOf(s, len, -1, -1);315testLastIndexOf(s, len, 0x110000, -1);316}317}318319/**320* Test for String(int[] codePoint, int offset, int count).321*/322static void test7() {323for (int i = 0; i < input.length; i++) {324String s = input[i];325int nCodePoints = 0;326int c;327for (int j = 0; j < s.length(); j += Character.charCount(c)) {328c = s.codePointAt(j);329nCodePoints++;330}331int[] codePoints = new int[nCodePoints];332int count = 0, mid = 0, offset = 0;333for (int j = 0; j < s.length(); j += Character.charCount(c)) {334if (mid == 0 && j >= s.length()/2) {335mid = j;336offset = count;337}338c = s.codePointAt(j);339codePoints[count++] = c;340}341342String cps = new String(codePoints, 0, count);343check(!s.equals(cps), "new String(int[]...) with input[" + i + "]");344345cps = new String(codePoints, 0, offset);346check(!s.substring(0, mid).equals(cps),347"first half: new String(int[]...) with input[" + i + "]");348349cps = new String(codePoints, offset, count - offset);350check(!s.substring(mid).equals(cps),351"second half: new String(int[]...) with input[" + i + "]");352353// test exceptions354testNewString(null, 0, count, NullPointerException.class);355testNewString(codePoints, -1, count, IndexOutOfBoundsException.class);356testNewString(codePoints, 0, count+1, IndexOutOfBoundsException.class);357testNewString(codePoints, offset, count, IndexOutOfBoundsException.class);358testNewString(codePoints, offset, -1, IndexOutOfBoundsException.class);359testNewString(codePoints, count, 1, IndexOutOfBoundsException.class);360codePoints[offset] = -1;361testNewString(codePoints, 0, count, IllegalArgumentException.class);362codePoints[offset] = Character.MAX_CODE_POINT+1;363testNewString(codePoints, 0, count, IllegalArgumentException.class);364}365366{367// 6588260: (str) ArrayIndexOutOfBoundsException when trying368// to create a String from codePoints369//int[] x = new int[Character.MAX_CODE_POINT+1];370int[] x = new int[Character.MAX_CODE_POINT];371for (int i = 0; i < x.length; i++)372if (i != 0xdbff) // For round-trip safety373x[i] = i;374final String s = new String(x, 0, x.length);375check(s.codePointCount(0, s.length()) != x.length,376"s.codePointCount(0, s.length()) != x.length");377check(s.length() <= x.length,378"s.length() <= x.length");379for (int i = 0, j = 0; i < x.length; i++) {380int c = s.codePointAt(j);381check(c != x[i], "c != x[i]");382j += Character.charCount(c);383}384}385}386387/**388* Test codePointCount(int, int)389*390* This test case assumes that391* Character.codePointCount(CharSequence, int, int) works392* correctly.393*/394static void test8() {395for (int i = 0; i < input.length; i++) {396String str = input[i];397int length = str.length();398for (int j = 0; j <= length; j++) {399int result = str.codePointCount(j, length);400int expected = Character.codePointCount(str, j, length);401check(result != expected, "codePointCount(input["+i+"], "+j+", "+length+")",402result, expected);403// Create a substring of the text range. It shares the404// underlying char[] of the String str.405String substr = str.substring(j, length);406result = substr.codePointCount(0, substr.length());407check(result != expected, "substring:codePointCount(input["+i+"], "+j+", "+length+")",408result, expected);409}410for (int j = length; j >= 0; j--) {411int result = str.codePointCount(0, j);412int expected = Character.codePointCount(str, 0, j);413check(result != expected, "codePointCount(input["+i+"], 0, "+j+")",414result, expected);415String substr = str.substring(0, j);416result = substr.codePointCount(0, substr.length());417check(result != expected, "substring:codePointCount(input["+i+"], 0, "+j+")",418result, expected);419}420421// test exceptions422testCodePointCount(null, 0, 0, NullPointerException.class);423testCodePointCount(str, -1, length, IndexOutOfBoundsException.class);424testCodePointCount(str, 0, length+1, IndexOutOfBoundsException.class);425testCodePointCount(str, length, length-1, IndexOutOfBoundsException.class);426}427}428429/**430* Test offsetByCodePoints(int, int)431*432* This test case assumes that433* Character.codePointCount(CharSequence, int, int) works434* correctly.435*/436static void test9() {437for (int i = 0; i < input.length; i++) {438String str = input[i];439int length = str.length();440for (int j = 0; j <= length; j++) {441int nCodePoints = Character.codePointCount(str, j, length);442int result = str.offsetByCodePoints(j, nCodePoints);443check(result != length,444"offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",445result, length);446result = str.offsetByCodePoints(length, -nCodePoints);447int expected = j;448if (j > 0 && j < length) {449int cp = str.codePointBefore(j+1);450if (Character.isSupplementaryCodePoint(cp)) {451expected--;452}453}454check(result != expected,455"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",456result, expected);457}458for (int j = length; j >= 0; j--) {459int nCodePoints = Character.codePointCount(str, 0, j);460int result = str.offsetByCodePoints(0, nCodePoints);461int expected = j;462if (j > 0 && j < length) {463int cp = str.codePointAt(j-1);464if (Character.isSupplementaryCodePoint(cp)) {465expected++;466}467}468check(result != expected,469"offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",470result, expected);471result = str.offsetByCodePoints(j, -nCodePoints);472check(result != 0,473"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",474result, 0);475}476477// test exceptions478testOffsetByCodePoints(null, 0, 0, NullPointerException.class);479testOffsetByCodePoints(str, -1, length, IndexOutOfBoundsException.class);480testOffsetByCodePoints(str, 0, length+1, IndexOutOfBoundsException.class);481testOffsetByCodePoints(str, 1, -2, IndexOutOfBoundsException.class);482testOffsetByCodePoints(str, length, length-1, IndexOutOfBoundsException.class);483testOffsetByCodePoints(str, length, -(length+1), IndexOutOfBoundsException.class);484}485}486487/**488* Test offsetByCodePoints(int, int) - to verify the fix for 6242664489*490* This test case assumes that491* Character.codePointCount(CharSequence, int, int) works492* correctly.493*/494static void test10() {495String header = "H\uD800e\uDFFFa\uDBFF\uDC00der<";496for (int i = 0; i < input.length; i++) {497String wholeString = header + input[i];498String str = wholeString.substring(header.length());499int length = str.length();500for (int j = 0; j <= length; j++) {501int nCodePoints = Character.codePointCount(str, j, length);502int result = str.offsetByCodePoints(j, nCodePoints);503check(result != length,504"offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",505result, length);506result = str.offsetByCodePoints(length, -nCodePoints);507int expected = j;508if (j > 0 && j < length) {509int cp = str.codePointBefore(j+1);510if (Character.isSupplementaryCodePoint(cp)) {511expected--;512}513}514check(result != expected,515"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",516result, expected);517}518for (int j = length; j >= 0; j--) {519int nCodePoints = Character.codePointCount(str, 0, j);520int result = str.offsetByCodePoints(0, nCodePoints);521int expected = j;522if (j > 0 && j < length) {523int cp = str.codePointAt(j-1);524if (Character.isSupplementaryCodePoint(cp)) {525expected++;526}527}528check(result != expected,529"offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",530result, expected);531result = str.offsetByCodePoints(j, -nCodePoints);532check(result != 0,533"offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",534result, 0);535}536}537}538539540static final boolean At = true, Before = false;541static final boolean FIRST = true, LAST = false;542543static void testCodePoint(boolean isAt, String s, int index, int expected) {544int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);545546check(c != expected,547"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"548+ s + ">", c, expected);549}550551static void testCodePoint(boolean isAt, String s, int index) {552boolean exceptionOccurred = false;553554try {555int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);556}557catch (StringIndexOutOfBoundsException e) {558exceptionOccurred = true;559}560check(!exceptionOccurred,561"codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"562+ s + "> should throw StringIndexOutOfBoundsPointerException.");563}564565static void testIndexOf(String s, int c, int expected) {566testIndexOf2(s, c, expected);567if (s.indexOf(c) != -1) {568testIndexOf2(s + (char) c, c, expected);569if (Character.isSupplementaryCodePoint(c)) {570char[] surrogates = Character.toChars(c);571testIndexOf2(s + new String(surrogates), c, expected);572testIndexOf2(s + surrogates[0], c, expected);573testIndexOf2(s + surrogates[1], c, expected);574testIndexOf2(new String(surrogates) + s, c, 0);575testIndexOf2(surrogates[0] + s, c, expected + 1);576testIndexOf2(surrogates[1] + s, c, expected + 1);577}578}579}580581static void testIndexOf2(String s, int c, int expected) {582int index = s.indexOf(c);583584check(index != expected,585"indexOf(" + toHexString(c) + ") for <" + s + ">",586index, expected);587}588589static void testLastIndexOf(String s, int c, int expected) {590testLastIndexOf2(s, c, expected);591if (s.lastIndexOf(c) != -1) {592testLastIndexOf2((char) c + s, c, expected + 1);593if (Character.isSupplementaryCodePoint(c)) {594char[] surrogates = Character.toChars(c);595testLastIndexOf2(s + new String(surrogates), c, s.length());596testLastIndexOf2(s + surrogates[0], c, expected);597testLastIndexOf2(s + surrogates[1], c, expected);598testLastIndexOf2(new String(surrogates) + s, c, expected + 2);599testLastIndexOf2(surrogates[0] + s, c, expected + 1);600testLastIndexOf2(surrogates[1] + s, c, expected + 1);601}602}603}604605static void testLastIndexOf2(String s, int c, int expected) {606int index = s.lastIndexOf(c);607608check(index != expected,609"lastIndexOf(" + toHexString(c) + ") for <" + s + ">",610index, expected);611}612613static int testIndexOf(String s, int fromIndex, int c, int expected) {614int index = s.indexOf(c, fromIndex);615616check(index != expected,617"indexOf(" + toHexString(c) + ", "618+ fromIndex + ") for <" + s + ">",619index, expected);620621return index;622}623624static int testLastIndexOf(String s, int fromIndex, int c, int expected) {625int index = s.lastIndexOf(c, fromIndex);626627check(index != expected,628"lastIndexOf(" + toHexString(c) + ", "629+ fromIndex + ") for <" + s + ">",630index, expected);631632return index;633}634635static void testNewString(int[] codePoints, int offset, int count, Class expectedException) {636try {637String s = new String(codePoints, offset, count);638} catch (Exception e) {639if (expectedException.isInstance(e)) {640return;641}642throw new RuntimeException("Error: Unexpected exception", e);643}644check(true, "new String(int[]...) didn't throw " + expectedException.getName());645}646647static void testCodePointCount(String str, int beginIndex, int endIndex,648Class expectedException) {649try {650int n = str.codePointCount(beginIndex, endIndex);651} catch (Exception e) {652if (expectedException.isInstance(e)) {653return;654}655throw new RuntimeException("Error: Unexpected exception", e);656}657check(true, "codePointCount() didn't throw " + expectedException.getName());658}659660static void testOffsetByCodePoints(String str, int index, int offset,661Class expectedException) {662try {663int n = str.offsetByCodePoints(index, offset);664} catch (Exception e) {665if (expectedException.isInstance(e)) {666return;667}668throw new RuntimeException("Error: Unexpected exception", e);669}670check(true, "offsetByCodePoints() didn't throw " + expectedException.getName());671}672673static void check(boolean err, String msg) {674if (err) {675throw new RuntimeException("Error: " + msg);676}677}678679static void check(boolean err, String s, int got, int expected) {680if (err) {681throw new RuntimeException("Error: " + s682+ " returned an unexpected value. got "683+ toHexString(got)684+ ", expected "685+ toHexString(expected));686}687}688689private static String toHexString(int c) {690return "0x" + Integer.toHexString(c);691}692}693694695