2f426cd68b
Reviewed-by: alanb
894 lines
39 KiB
Java
894 lines
39 KiB
Java
/*
|
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 4533872 4985214 4985217 4993841 5017268 5017280 8298033
|
|
* @summary Unit tests for supplementary character support (JSR-204)
|
|
* @compile Supplementary.java
|
|
* @run main/timeout=600 Supplementary
|
|
*/
|
|
|
|
public class Supplementary {
|
|
private static final char MIN_HIGH = '\uD800';
|
|
private static final char MAX_HIGH = '\uDBFF';
|
|
private static final char MIN_LOW = MAX_HIGH + 1;
|
|
private static final char MAX_LOW = '\uDFFF';
|
|
private static final int MIN_CODE_POINT = 0x000000;
|
|
private static final int MIN_SUPPLEMENTARY = 0x010000;
|
|
private static final int MAX_SUPPLEMENTARY = 0x10ffff;
|
|
|
|
public static void main(String[] args) {
|
|
// Do not change the order of test method calls since there
|
|
// are some interdependencies.
|
|
|
|
testConstants();
|
|
|
|
test00();
|
|
|
|
// Store all Unicode code points, except for surrogate code
|
|
// points, in cu[] through the loops below. Then, use the data
|
|
// for code point/code unit conversion and other tests later.
|
|
char[] cu = new char[(MAX_SUPPLEMENTARY+1) * 2];
|
|
int length = test01(cu);
|
|
|
|
String str = new String(cu, 0, length);
|
|
cu = null;
|
|
test02(str);
|
|
test03(str.toCharArray());
|
|
test04(str);
|
|
test05(str);
|
|
|
|
// Test for toString(int)
|
|
test06();
|
|
|
|
// Test unpaired surrogates
|
|
testUnpaired();
|
|
|
|
// Test exceptions
|
|
testExceptions00();
|
|
testExceptions01(str);
|
|
testExceptions02(str.toCharArray());
|
|
}
|
|
|
|
static void testConstants() {
|
|
if (Character.MIN_HIGH_SURROGATE != MIN_HIGH) {
|
|
constantError("MIN_HIGH_SURROGATE", Character.MIN_HIGH_SURROGATE, MIN_HIGH);
|
|
}
|
|
if (Character.MAX_HIGH_SURROGATE != MAX_HIGH) {
|
|
constantError("MAX_HIGH_SURROGATE", Character.MAX_HIGH_SURROGATE, MAX_HIGH);
|
|
}
|
|
if (Character.MIN_LOW_SURROGATE != MIN_LOW) {
|
|
constantError("MIN_LOW_SURROGATE", Character.MIN_LOW_SURROGATE, MIN_LOW);
|
|
}
|
|
if (Character.MAX_LOW_SURROGATE != MAX_LOW) {
|
|
constantError("MAX_LOW_SURROGATE", Character.MAX_LOW_SURROGATE, MAX_LOW);
|
|
}
|
|
if (Character.MIN_SURROGATE != MIN_HIGH) {
|
|
constantError("MIN_SURROGATE", Character.MIN_SURROGATE, MIN_HIGH);
|
|
}
|
|
if (Character.MAX_SURROGATE != MAX_LOW) {
|
|
constantError("MAX_SURROGATE", Character.MAX_SURROGATE, MAX_LOW);
|
|
}
|
|
if (Character.MIN_SUPPLEMENTARY_CODE_POINT != MIN_SUPPLEMENTARY) {
|
|
constantError("MIN_SUPPLEMENTARY_CODE_POINT",
|
|
Character.MIN_SUPPLEMENTARY_CODE_POINT, MIN_SUPPLEMENTARY);
|
|
}
|
|
if (Character.MIN_CODE_POINT != MIN_CODE_POINT) {
|
|
constantError("MIN_CODE_POINT", Character.MIN_CODE_POINT, MIN_CODE_POINT);
|
|
}
|
|
if (Character.MAX_CODE_POINT != MAX_SUPPLEMENTARY) {
|
|
constantError("MAX_CODE_POINT", Character.MAX_CODE_POINT, MAX_SUPPLEMENTARY);
|
|
}
|
|
}
|
|
|
|
static void constantError(String name, int value, int expectedValue) {
|
|
throw new RuntimeException("Character." + name + " has a wrong value: got "
|
|
+ toHexString(value)
|
|
+ ", expected " + toHexString(expectedValue));
|
|
}
|
|
|
|
/*
|
|
* Test isValidCodePoint(int)
|
|
* isSupplementaryCodePoint(int)
|
|
* charCount(int)
|
|
*/
|
|
static void test00() {
|
|
for (int cp = -MAX_SUPPLEMENTARY; cp <= MAX_SUPPLEMENTARY*2; cp++) {
|
|
boolean isValid = cp >= 0 && cp <= MAX_SUPPLEMENTARY;
|
|
if (Character.isValidCodePoint(cp) != isValid) {
|
|
throw new RuntimeException("isValidCodePoint failed with "
|
|
+ toHexString(cp));
|
|
}
|
|
boolean isSupplementary = cp >= MIN_SUPPLEMENTARY && cp <= MAX_SUPPLEMENTARY;
|
|
if (Character.isSupplementaryCodePoint(cp) != isSupplementary) {
|
|
throw new RuntimeException("isSupplementaryCodePoint failed with "
|
|
+ toHexString(cp));
|
|
}
|
|
int len = Character.charCount(cp);
|
|
if (isValid) {
|
|
if ((isSupplementary && len != 2)
|
|
|| (!isSupplementary && len != 1)) {
|
|
throw new RuntimeException("wrong character length "+len+" for "
|
|
+ toHexString(cp));
|
|
}
|
|
} else if (len != 1 && len != 2) {
|
|
throw new RuntimeException("wrong character length "+len+" for "
|
|
+ toHexString(cp));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test toChar(int)
|
|
* toChar(int, char[], int)
|
|
* isHighSurrogate(char)
|
|
* isLowSurrogate(char)
|
|
* isSurrogatePair(int, int)
|
|
*
|
|
* While testing those methods, this method generates all Unicode
|
|
* code points (except for surrogate code points) and store them
|
|
* in cu.
|
|
*
|
|
* @return the number of code units generated in cu
|
|
*/
|
|
static int test01(char[] cu) {
|
|
int index = 0;
|
|
// Test toChar(int)
|
|
// toChar(int, char[], int)
|
|
// isHighSurrogate(char)
|
|
// isLowSurrogate(char)
|
|
// with BMP code points
|
|
for (int i = 0; i <= Character.MAX_VALUE; i++) {
|
|
char[] u = Character.toChars(i);
|
|
if (u.length != 1 || u[0] != i) {
|
|
throw new RuntimeException("wrong toChars(int) result for BMP: "
|
|
+ toHexString("u", u));
|
|
}
|
|
int n = Character.toChars(i, cu, index);
|
|
if (n != 1 || cu[index] != i) {
|
|
throw new RuntimeException("wrong toChars(int, char[], int) result for BMP:"
|
|
+ " len=" + n
|
|
+ ", cu["+index+"]="+toHexString(cu[index]));
|
|
}
|
|
boolean isHigh = i >= MIN_HIGH && i <= MAX_HIGH;
|
|
if (Character.isHighSurrogate((char) i) != isHigh) {
|
|
throw new RuntimeException("wrong high-surrogate test for "
|
|
+ toHexString(i));
|
|
}
|
|
boolean isLow = i >= MIN_LOW && i <= MAX_LOW;
|
|
if (Character.isLowSurrogate((char)i) != isLow) {
|
|
throw new RuntimeException("wrong low-surrogate test for "
|
|
+ toHexString(i));
|
|
}
|
|
if (!isHigh && !isLow) {
|
|
index++;
|
|
}
|
|
}
|
|
|
|
// Test isSurrogatePair with all surrogate pairs
|
|
// Test toChars(int)
|
|
// toChars(int, char[], int)
|
|
// with all supplementary characters
|
|
int supplementary = MIN_SUPPLEMENTARY;
|
|
for (int i = Character.MAX_VALUE/2; i <= Character.MAX_VALUE; i++) {
|
|
char hi = (char) i;
|
|
boolean isHigh = Character.isHighSurrogate(hi);
|
|
|
|
for (int j = Character.MAX_VALUE/2; j <= Character.MAX_VALUE; j++) {
|
|
char lo = (char) j;
|
|
boolean isLow = Character.isLowSurrogate(lo);
|
|
boolean isSurrogatePair = isHigh && isLow;
|
|
if (Character.isSurrogatePair(hi, lo) != isSurrogatePair) {
|
|
throw new RuntimeException("wrong surrogate pair test for hi="
|
|
+ toHexString(hi)
|
|
+ ", lo="+toHexString(lo));
|
|
}
|
|
if (isSurrogatePair) {
|
|
int cp = Character.toCodePoint(hi, lo);
|
|
if (cp != supplementary) {
|
|
throw new RuntimeException("wrong code point: got "
|
|
+ toHexString(cp)
|
|
+ ", expected="
|
|
+ toHexString(supplementary));
|
|
}
|
|
char[] u = Character.toChars(cp);
|
|
if (u.length != 2 || u[0] != hi || u[1] != lo) {
|
|
throw new RuntimeException("wrong toChars(int) result for supplementary: "+
|
|
toHexString("u", u));
|
|
}
|
|
int n = Character.toChars(cp, cu, index);
|
|
if (n != 2 || cu[index] != hi || cu[index+1] != lo) {
|
|
throw new RuntimeException("wrong toChars(int, char[], int) result "
|
|
+ "for supplementary: len=" + n
|
|
+ ", cu["+index+"]=" + toHexString(cu[index])
|
|
+ ", cu["+(index+1)+"]=" + toHexString(cu[index+1]));
|
|
}
|
|
index += n;
|
|
supplementary++;
|
|
}
|
|
}
|
|
}
|
|
if (supplementary != MAX_SUPPLEMENTARY + 1) {
|
|
throw new RuntimeException("wrong supplementary count (supplementary="
|
|
+ toHexString(supplementary)+")");
|
|
}
|
|
|
|
int nCodeUnits = Character.MAX_VALUE + 1 - (MAX_LOW - MIN_HIGH + 1)
|
|
+ ((MAX_SUPPLEMENTARY - MIN_SUPPLEMENTARY + 1) * 2);
|
|
if (index != nCodeUnits) {
|
|
throw new RuntimeException("wrong number of code units: " + index
|
|
+ ", expected " + nCodeUnits);
|
|
}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* Test codePointAt(CharSequence, int)
|
|
* codePointBefore(CharSequence, int)
|
|
*/
|
|
static void test02(CharSequence cs) {
|
|
int cp = 0;
|
|
int ch;
|
|
for (int i = 0; i < cs.length(); i += Character.charCount(ch)) {
|
|
ch = Character.codePointAt(cs, i);
|
|
if (ch != cp) {
|
|
throw new RuntimeException("wrong codePointAt(CharSequence, "+i+") value: got "
|
|
+ toHexString(ch)
|
|
+ ", expected "+toHexString(cp));
|
|
}
|
|
cp++;
|
|
// Skip surrogates
|
|
if (cp == MIN_HIGH) {
|
|
cp = MAX_LOW + 1;
|
|
}
|
|
}
|
|
|
|
cp--;
|
|
for (int i = cs.length(); i > 0; i -= Character.charCount(ch)) {
|
|
ch = Character.codePointBefore(cs, i);
|
|
if (ch != cp) {
|
|
throw new RuntimeException("codePointBefore(CharSequence, "+i+") returned "
|
|
+ toHexString(ch)
|
|
+ ", expected " + toHexString(cp));
|
|
}
|
|
cp--;
|
|
// Skip surrogates
|
|
if (cp == MAX_LOW) {
|
|
cp = MIN_HIGH - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test codePointAt(char[], int)
|
|
* codePointAt(char[], int, int)
|
|
* codePointBefore(char[], int)
|
|
* codePointBefore(char[], int, int)
|
|
*/
|
|
static void test03(char[] a) {
|
|
int cp = 0;
|
|
int ch;
|
|
for (int i = 0; i < a.length; i += Character.charCount(ch)) {
|
|
ch = Character.codePointAt(a, i);
|
|
if (ch != cp) {
|
|
throw new RuntimeException("codePointAt(char[], "+i+") returned "
|
|
+ toHexString(ch)
|
|
+ ", expected "+toHexString(cp));
|
|
}
|
|
int x = Character.codePointAt(a, i, i+1);
|
|
if (x != a[i]) {
|
|
throw new RuntimeException(String.format(
|
|
"codePointAt(char[], %d, %d) returned 0x%04x, expected 0x%04x\n",
|
|
i, i+1, x, (int)a[i]));
|
|
}
|
|
cp++;
|
|
// Skip surrogates
|
|
if (cp == MIN_HIGH) {
|
|
cp = MAX_LOW + 1;
|
|
}
|
|
}
|
|
|
|
cp--;
|
|
for (int i = a.length; i > 0; i -= Character.charCount(ch)) {
|
|
ch = Character.codePointBefore(a, i);
|
|
if (ch != cp) {
|
|
throw new RuntimeException("codePointBefore(char[], "+i+") returned "
|
|
+ toHexString(ch)
|
|
+ ", expected " + toHexString(cp));
|
|
}
|
|
int x = Character.codePointBefore(a, i, i-1);
|
|
if (x != a[i-1]) {
|
|
throw new RuntimeException(String.format(
|
|
"codePointAt(char[], %d, %d) returned 0x%04x, expected 0x%04x\n",
|
|
i, i-1, x, (int)a[i-1]));
|
|
}
|
|
cp--;
|
|
// Skip surrogates
|
|
if (cp == MAX_LOW) {
|
|
cp = MIN_HIGH - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test codePointCount(CharSequence, int, int)
|
|
* codePointCount(char[], int, int, int, int)
|
|
*/
|
|
static void test04(String str) {
|
|
int length = str.length();
|
|
char[] a = str.toCharArray();
|
|
|
|
for (int i = 0; i <= length; i += 99, length -= 29999) {
|
|
int n = Character.codePointCount(str, i, length);
|
|
int m = codePointCount(str.substring(i, length));
|
|
checkCodePointCount(str, n, m);
|
|
n = Character.codePointCount(a, i, length - i);
|
|
checkCodePointCount(a, n, m);
|
|
}
|
|
|
|
// test special cases
|
|
length = str.length();
|
|
int n = Character.codePointCount(str, 0, 0);
|
|
checkCodePointCount(str, n, 0);
|
|
n = Character.codePointCount(str, length, length);
|
|
checkCodePointCount(str, n, 0);
|
|
n = Character.codePointCount(a, 0, 0);
|
|
checkCodePointCount(a, n, 0);
|
|
n = Character.codePointCount(a, length, 0);
|
|
checkCodePointCount(a, n, 0);
|
|
}
|
|
|
|
// This method assumes that Character.codePointAt() and
|
|
// Character.charCount() work correctly.
|
|
private static int codePointCount(CharSequence seq) {
|
|
int n = 0, len;
|
|
for (int i = 0; i < seq.length(); i += len) {
|
|
int codepoint = Character.codePointAt(seq, i);
|
|
n++;
|
|
len = Character.charCount(codepoint);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
private static void checkCodePointCount(Object data, int n, int expected) {
|
|
String type = getType(data);
|
|
if (n != expected) {
|
|
throw new RuntimeException("codePointCount(" + type + "...) returned " + n
|
|
+ ", expected " + expected);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test offsetByCodePoints(CharSequence, int, int)
|
|
* offsetByCodePoints(char[], int, int, int, int)
|
|
*
|
|
* This test case assumes that Character.codePointCount()s work
|
|
* correctly.
|
|
*/
|
|
static void test05(String str) {
|
|
int length = str.length();
|
|
char[] a = str.toCharArray();
|
|
|
|
for (int i = 0; i <= length; i += 99, length -= 29999) {
|
|
int nCodePoints = Character.codePointCount(a, i, length - i);
|
|
int index;
|
|
|
|
// offsetByCodePoints(CharSequence, int, int)
|
|
|
|
int expectedHighIndex = length;
|
|
// For forward CharSequence scan, we need to adjust the
|
|
// expected index in case the last char in the text range
|
|
// is a high surrogate and forms a valid supplementary
|
|
// code point with the next char.
|
|
if (length < a.length) {
|
|
int cp = Character.codePointAt(a, length - 1);
|
|
if (Character.isSupplementaryCodePoint(cp)) {
|
|
expectedHighIndex++;
|
|
}
|
|
}
|
|
index = Character.offsetByCodePoints(str, i, nCodePoints);
|
|
checkNewIndex(str, nCodePoints, index, expectedHighIndex);
|
|
int expectedLowIndex = i;
|
|
if (i > 0) {
|
|
int cp = Character.codePointBefore(a, i + 1);
|
|
if (Character.isSupplementaryCodePoint(cp)) {
|
|
expectedLowIndex--;
|
|
}
|
|
}
|
|
index = Character.offsetByCodePoints(str, length, -nCodePoints);
|
|
checkNewIndex(str, -nCodePoints, index, expectedLowIndex);
|
|
|
|
// offsetByCodePoints(char[], int, int, int, int)
|
|
|
|
int start = Math.max(0, i-1);
|
|
int limit = Math.min(a.length, length+1);
|
|
index = Character.offsetByCodePoints(a, start, limit - start,
|
|
i, nCodePoints);
|
|
checkNewIndex(a, nCodePoints, index, expectedHighIndex);
|
|
if (length != expectedHighIndex) {
|
|
index = Character.offsetByCodePoints(a, start, length - start,
|
|
i, nCodePoints);
|
|
checkNewIndex(a, nCodePoints, index, length);
|
|
}
|
|
index = Character.offsetByCodePoints(a, start, limit - start,
|
|
length, -nCodePoints);
|
|
checkNewIndex(a, -nCodePoints, index, expectedLowIndex);
|
|
if (i != expectedLowIndex) {
|
|
index = Character.offsetByCodePoints(a, i, limit - i,
|
|
length, -nCodePoints);
|
|
checkNewIndex(a, -nCodePoints, index, i);
|
|
}
|
|
}
|
|
|
|
// test special cases for 0-length text ranges.
|
|
length = str.length();
|
|
int index = Character.offsetByCodePoints(str, 0, 0);
|
|
checkNewIndex(str, 0, index, 0);
|
|
index = Character.offsetByCodePoints(str, length, 0);
|
|
checkNewIndex(str, 0, index, length);
|
|
index = Character.offsetByCodePoints(a, 0, 0, 0, 0);
|
|
checkNewIndex(a, 0, index, 0);
|
|
index = Character.offsetByCodePoints(a, 0, length, 0, 0);
|
|
checkNewIndex(a, 0, index, 0);
|
|
index = Character.offsetByCodePoints(a, 0, length, length, 0);
|
|
checkNewIndex(a, 0, index, length);
|
|
index = Character.offsetByCodePoints(a, length, 0, length, 0);
|
|
checkNewIndex(a, 0, index, length);
|
|
}
|
|
|
|
/**
|
|
* Test toString(int)
|
|
*
|
|
* This test case assumes that Character.toChars()/String(char[]) work
|
|
* correctly.
|
|
*/
|
|
static void test06() {
|
|
for (int cp = Character.MIN_CODE_POINT; cp <= Character.MAX_CODE_POINT; cp++) {
|
|
String result = Character.toString(cp);
|
|
String expected = new String(Character.toChars(cp));
|
|
if (!result.equals(expected)) {
|
|
throw new RuntimeException("Wrong string is created. code point: " +
|
|
cp + ", result: " + result + ", expected: " + expected);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void checkNewIndex(Object data, int offset, int result, int expected) {
|
|
String type = getType(data);
|
|
String offsetType = (offset > 0) ? "positive" : (offset < 0) ? "negative" : "0";
|
|
if (result != expected) {
|
|
throw new RuntimeException("offsetByCodePoints(" + type + ", ...) ["
|
|
+ offsetType + " offset]"
|
|
+ " returned " + result
|
|
+ ", expected " + expected);
|
|
}
|
|
}
|
|
|
|
// Test codePointAt(CharSequence, int)
|
|
// codePointBefore(CharSequence, int)
|
|
// codePointAt(char[], int)
|
|
// codePointBefore(char[], int)
|
|
// toChar(int)
|
|
// toChar(int, char[], int)
|
|
// with unpaired surrogates
|
|
static void testUnpaired() {
|
|
testCodePoint("\uD800", new int[] { 0xD800 });
|
|
testCodePoint("\uDC00", new int[] { 0xDC00 });
|
|
testCodePoint("a\uD800", new int[] { 'a', 0xD800 });
|
|
testCodePoint("a\uDC00", new int[] { 'a', 0xDC00 });
|
|
testCodePoint("\uD800a", new int[] { 0xD800, 'a' });
|
|
testCodePoint("\uDBFFa", new int[] { 0xDBFF, 'a' });
|
|
testCodePoint("a\uD800\uD801", new int[] { 'a', 0xD800, 0xD801 });
|
|
testCodePoint("a\uD800x\uDC00", new int[] { 'a', 0xD800, 'x', 0xDC00 });
|
|
testCodePoint("\uDC00\uD800", new int[] { 0xDC00, 0xD800 });
|
|
testCodePoint("\uD800\uDC00\uDC00", new int[] { 0x10000, 0xDC00 });
|
|
testCodePoint("\uD800\uD800\uDC00", new int[] { 0xD800, 0x10000 });
|
|
testCodePoint("\uD800\uD800\uD800\uD800\uDC00\uDC00\uDC00\uDC00",
|
|
new int[] { 0xD800, 0xD800, 0xD800, 0x10000, 0xDC00, 0xDC00, 0xDC00});
|
|
}
|
|
|
|
static void testCodePoint(String str, int[] codepoints) {
|
|
int c;
|
|
// Test Character.codePointAt/Before(CharSequence, int)
|
|
int j = 0;
|
|
for (int i = 0; i < str.length(); i += Character.charCount(c)) {
|
|
c = Character.codePointAt(str, i);
|
|
if (c != codepoints[j++]) {
|
|
throw new RuntimeException("codePointAt(CharSequence, " + i + ") returned "
|
|
+ toHexString(c)
|
|
+ ", expected " + toHexString(codepoints[j-1]));
|
|
}
|
|
}
|
|
if (j != codepoints.length) {
|
|
throw new RuntimeException("j != codepoints.length after codePointAt(CharSequence, int)"
|
|
+ " (j=" + j + ")"
|
|
+ ", expected: " + codepoints.length);
|
|
}
|
|
|
|
j = codepoints.length;
|
|
for (int i = str.length(); i > 0 ; i -= Character.charCount(c)) {
|
|
c = Character.codePointBefore(str, i);
|
|
if (c != codepoints[--j]) {
|
|
throw new RuntimeException("codePointBefore(CharSequence, " + i + ") returned "
|
|
+ toHexString(c)
|
|
+ ", expected " + toHexString(codepoints[j]));
|
|
}
|
|
}
|
|
if (j != 0) {
|
|
throw new RuntimeException("j != 0 after codePointBefore(CharSequence, int)"
|
|
+ " (j=" + j + ")");
|
|
}
|
|
|
|
// Test Character.codePointAt/Before(char[], int)
|
|
char[] a = str.toCharArray();
|
|
j = 0;
|
|
for (int i = 0; i < a.length; i += Character.charCount(c)) {
|
|
c = Character.codePointAt(a, i);
|
|
if (c != codepoints[j++]) {
|
|
throw new RuntimeException("codePointAt(char[], " + i + ") returned "
|
|
+ toHexString(c)
|
|
+ ", expected " + toHexString(codepoints[j-1]));
|
|
}
|
|
}
|
|
if (j != codepoints.length) {
|
|
throw new RuntimeException("j != codepoints.length after codePointAt(char[], int)"
|
|
+ " (j=" + j + ")"
|
|
+ ", expected: " + codepoints.length);
|
|
}
|
|
|
|
j = codepoints.length;
|
|
for (int i = a.length; i > 0 ; i -= Character.charCount(c)) {
|
|
c = Character.codePointBefore(a, i);
|
|
if (c != codepoints[--j]) {
|
|
throw new RuntimeException("codePointBefore(char[], " + i + ") returned "
|
|
+ toHexString(c)
|
|
+ ", expected " + toHexString(codepoints[j]));
|
|
}
|
|
}
|
|
if (j != 0) {
|
|
throw new RuntimeException("j != 0 after codePointBefore(char[], int)"
|
|
+ " (j=" + j + ")");
|
|
}
|
|
|
|
// Test toChar(int)
|
|
j = 0;
|
|
for (int i = 0; i < codepoints.length; i++) {
|
|
a = Character.toChars(codepoints[i]);
|
|
for (int k = 0; k < a.length; k++) {
|
|
if (str.charAt(j++) != a[k]) {
|
|
throw new RuntimeException("toChars(int) returned " + toHexString("result", a)
|
|
+ " from codepoint=" + toHexString(codepoints[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test toChars(int, char[], int)
|
|
a = new char[codepoints.length * 2];
|
|
j = 0;
|
|
for (int i = 0; i < codepoints.length; i++) {
|
|
int n = Character.toChars(codepoints[i], a, j);
|
|
j += n;
|
|
}
|
|
String s = new String(a, 0, j);
|
|
if (!str.equals(s)) {
|
|
throw new RuntimeException("toChars(int, char[], int) returned "
|
|
+ toHexString("dst", s.toCharArray())
|
|
+ ", expected " + toHexString("data", str.toCharArray()));
|
|
}
|
|
}
|
|
|
|
// Test toChar(int)
|
|
// toChar(int, char[], int)
|
|
// toString(int)
|
|
// for exceptions
|
|
static void testExceptions00() {
|
|
callToChars1(-1, IllegalArgumentException.class);
|
|
callToChars1(MAX_SUPPLEMENTARY + 1, IllegalArgumentException.class);
|
|
|
|
callToChars3(MAX_SUPPLEMENTARY, null, 0, NullPointerException.class);
|
|
callToChars3(-MIN_SUPPLEMENTARY, new char[2], 0, IllegalArgumentException.class);
|
|
callToChars3(MAX_SUPPLEMENTARY + 1, new char[2], 0, IllegalArgumentException.class);
|
|
callToChars3('A', new char[0], 0, IndexOutOfBoundsException.class);
|
|
callToChars3('A', new char[1], -1, IndexOutOfBoundsException.class);
|
|
callToChars3('A', new char[1], 1, IndexOutOfBoundsException.class);
|
|
callToChars3(MIN_SUPPLEMENTARY, new char[0], 0, IndexOutOfBoundsException.class);
|
|
callToChars3(MIN_SUPPLEMENTARY, new char[1], 0, IndexOutOfBoundsException.class);
|
|
callToChars3(MIN_SUPPLEMENTARY, new char[2], -1, IndexOutOfBoundsException.class);
|
|
callToChars3(MIN_SUPPLEMENTARY, new char[2], 1, IndexOutOfBoundsException.class);
|
|
|
|
callToString(Character.MIN_CODE_POINT - 1, IllegalArgumentException.class);
|
|
callToString(Character.MAX_CODE_POINT + 1, IllegalArgumentException.class);
|
|
}
|
|
|
|
static final boolean At = true, Before = false;
|
|
|
|
/**
|
|
* Test codePointAt(CharSequence, int)
|
|
* codePointBefore(CharSequence, int)
|
|
* codePointCount(CharSequence, int, int)
|
|
* offsetByCodePoints(CharSequence, int, int)
|
|
* for exceptions
|
|
*/
|
|
static void testExceptions01(CharSequence cs) {
|
|
CharSequence nullSeq = null;
|
|
// codePointAt
|
|
callCodePoint(At, nullSeq, 0, NullPointerException.class);
|
|
callCodePoint(At, cs, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, cs, cs.length(), IndexOutOfBoundsException.class);
|
|
callCodePoint(At, cs, cs.length()*3, IndexOutOfBoundsException.class);
|
|
|
|
// codePointBefore
|
|
callCodePoint(Before, nullSeq, 0, NullPointerException.class);
|
|
callCodePoint(Before, cs, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, cs, 0, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, cs, cs.length()+1, IndexOutOfBoundsException.class);
|
|
|
|
// codePointCount
|
|
callCodePointCount(nullSeq, 0, 0, NullPointerException.class);
|
|
callCodePointCount(cs, -1, 1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(cs, 0, cs.length()+1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(cs, 3, 1, IndexOutOfBoundsException.class);
|
|
|
|
// offsetByCodePoints
|
|
callOffsetByCodePoints(nullSeq, 0, 0, NullPointerException.class);
|
|
callOffsetByCodePoints(cs, -1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, cs.length()+1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, 0, cs.length()*2, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, cs.length(), 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, 0, -1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, cs.length(), -cs.length()*2,
|
|
IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, cs.length(), Integer.MIN_VALUE,
|
|
IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(cs, 0, Integer.MAX_VALUE, IndexOutOfBoundsException.class);
|
|
}
|
|
|
|
/**
|
|
* Test codePointAt(char[], int)
|
|
* codePointAt(char[], int, int)
|
|
* codePointBefore(char[], int)
|
|
* codePointBefore(char[], int, int)
|
|
* codePointCount(char[], int, int)
|
|
* offsetByCodePoints(char[], int, int, int, int)
|
|
* for exceptions
|
|
*/
|
|
static void testExceptions02(char[] a) {
|
|
char[] nullArray = null;
|
|
callCodePoint(At, nullArray, 0, NullPointerException.class);
|
|
callCodePoint(At, a, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, a.length, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, a.length*3, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, nullArray, 0, NullPointerException.class);
|
|
callCodePoint(Before, a, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, 0, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, a.length+1, IndexOutOfBoundsException.class);
|
|
|
|
// tests for the methods with limit
|
|
callCodePoint(At, nullArray, 0, 1, NullPointerException.class);
|
|
callCodePoint(At, a, 0, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, 0, 0, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, 0, a.length+1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, 2, 1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, -1, 1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, a.length, 1, IndexOutOfBoundsException.class);
|
|
callCodePoint(At, a, a.length*3, 1, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, nullArray, 1, 0, NullPointerException.class);
|
|
callCodePoint(Before, a, 2, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, 2, 2, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, 2, 3, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, 2, a.length, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, -1, -1, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, 0, 0, IndexOutOfBoundsException.class);
|
|
callCodePoint(Before, a, a.length+1, a.length-1, IndexOutOfBoundsException.class);
|
|
|
|
// codePointCount
|
|
callCodePointCount(nullArray, 0, 0, NullPointerException.class);
|
|
callCodePointCount(a, -1, 1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(a, 0, -1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(a, 0, a.length+1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(a, 1, a.length, IndexOutOfBoundsException.class);
|
|
callCodePointCount(a, a.length, 1, IndexOutOfBoundsException.class);
|
|
callCodePointCount(a, a.length+1, -1, IndexOutOfBoundsException.class);
|
|
|
|
// offsetByCodePoints
|
|
callOffsetByCodePoints(nullArray, 0, 0, 0, 0, NullPointerException.class);
|
|
callOffsetByCodePoints(a, -1, a.length, 1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length+1, 1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 10, a.length, 1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 10, a.length-10, 1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 10, 10, 21, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 20, -10, 15, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 10, 10, 15, 20, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 10, 10, 15, -20, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, -1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, a.length+1, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, 0, a.length*2, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, a.length, 1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, 0, -1, IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, a.length, -a.length*2,
|
|
IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, a.length, Integer.MIN_VALUE,
|
|
IndexOutOfBoundsException.class);
|
|
callOffsetByCodePoints(a, 0, a.length, 0, Integer.MAX_VALUE,
|
|
IndexOutOfBoundsException.class);
|
|
}
|
|
|
|
/**
|
|
* Test the 1-arg toChars(int) for exceptions
|
|
*/
|
|
private static void callToChars1(int codePoint, Class expectedException) {
|
|
try {
|
|
char[] a = Character.toChars(codePoint);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("toChars(int) didn't throw " + expectedException.getName());
|
|
}
|
|
|
|
/**
|
|
* Test the 3-arg toChars(int, char[], int) for exceptions
|
|
*/
|
|
private static void callToChars3(int codePoint, char[] dst, int index,
|
|
Class expectedException) {
|
|
try {
|
|
int n = Character.toChars(codePoint, dst, index);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("toChars(int,char[],int) didn't throw "
|
|
+ expectedException.getName());
|
|
}
|
|
|
|
private static void callCodePoint(boolean isAt, CharSequence cs, int index,
|
|
Class expectedException) {
|
|
try {
|
|
int c = isAt ? Character.codePointAt(cs, index)
|
|
: Character.codePointBefore(cs, index);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("codePoint" + (isAt ? "At" : "Before")
|
|
+ " didn't throw " + expectedException.getName());
|
|
}
|
|
|
|
private static void callCodePoint(boolean isAt, char[] a, int index,
|
|
Class expectedException) {
|
|
try {
|
|
int c = isAt ? Character.codePointAt(a, index)
|
|
: Character.codePointBefore(a, index);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("codePoint" + (isAt ? "At" : "Before")
|
|
+ " didn't throw " + expectedException.getName());
|
|
}
|
|
|
|
private static void callCodePoint(boolean isAt, char[] a, int index, int limit,
|
|
Class<? extends Exception> expectedException) {
|
|
try {
|
|
int c = isAt ? Character.codePointAt(a, index, limit)
|
|
: Character.codePointBefore(a, index, limit);
|
|
} catch (Exception e) {
|
|
if (expectedException == e.getClass()) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("codePoint" + (isAt ? "At" : "Before")
|
|
+ " didn't throw " + expectedException.getName());
|
|
}
|
|
|
|
private static void callCodePointCount(Object data, int beginIndex, int endIndex,
|
|
Class expectedException) {
|
|
String type = getType(data);
|
|
try {
|
|
int n = (data instanceof CharSequence) ?
|
|
Character.codePointCount((CharSequence) data, beginIndex, endIndex)
|
|
: Character.codePointCount((char[]) data, beginIndex, endIndex);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("codePointCount(" + type + "...) didn't throw "
|
|
+ expectedException.getName());
|
|
}
|
|
|
|
private static void callOffsetByCodePoints(CharSequence seq, int index, int offset,
|
|
Class expectedException) {
|
|
try {
|
|
int n = Character.offsetByCodePoints(seq, index, offset);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("offsetCodePointCounts(CharSequnce...) didn't throw "
|
|
+ expectedException.getName());
|
|
}
|
|
|
|
|
|
private static void callOffsetByCodePoints(char[] a, int start, int count,
|
|
int index, int offset,
|
|
Class expectedException) {
|
|
try {
|
|
int n = Character.offsetByCodePoints(a, start, count, index, offset);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("offsetCodePointCounts(char[]...) didn't throw "
|
|
+ expectedException.getName());
|
|
}
|
|
|
|
private static void callToString(int codePoint, Class expectedException) {
|
|
try {
|
|
String s = Character.toString(codePoint);
|
|
} catch (Exception e) {
|
|
if (expectedException.isInstance(e)) {
|
|
return;
|
|
}
|
|
throw new RuntimeException("Unspecified exception", e);
|
|
}
|
|
throw new RuntimeException("toString(int) didn't throw "
|
|
+ expectedException.getName());
|
|
}
|
|
|
|
private static String getType(Object data) {
|
|
return (data instanceof CharSequence) ? "CharSequence" : "char[]";
|
|
}
|
|
|
|
private static String toHexString(int c) {
|
|
return "0x" + Integer.toHexString(c);
|
|
}
|
|
|
|
private static String toHexString(String name, char[] a) {
|
|
StringBuffer sb = new StringBuffer();
|
|
for (int i = 0; i < a.length; i++) {
|
|
if (i > 0) {
|
|
sb.append(", ");
|
|
}
|
|
sb.append(name).append('[').append(i).append("]=");
|
|
sb.append(toHexString(a[i]));
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|