1 /* 2 * Copyright (c) 2018, 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 24 /* 25 * @test 26 * @bug 4533872 4985214 4985217 5017268 5017280 27 * @summary Unit tests for supplementary character support (JSR-204) 28 * @compile Supplementary.java 29 * @run main/timeout=600 Supplementary 30 */ 31 32 public class Supplementary { 33 private static final char MIN_HIGH = '\uD800'; 34 private static final char MAX_HIGH = '\uDBFF'; 35 private static final char MIN_LOW = MAX_HIGH + 1; 36 private static final char MAX_LOW = '\uDFFF'; 37 private static final int MIN_CODE_POINT = 0x000000; 38 private static final int MIN_SUPPLEMENTARY = 0x010000; 39 private static final int MAX_SUPPLEMENTARY = 0x10ffff; 40 41 public static void main(String[] args) { 42 // Do not change the order of test method calls since there 43 // are some interdependencies. 44 45 testConstants(); 46 47 test00(); 48 49 // Store all Unicode code points, except for surrogate code 50 // points, in cu[] through the loops below. Then, use the data 51 // for code point/code unit conversion and other tests later. 52 char[] cu = new char[(MAX_SUPPLEMENTARY+1) * 2]; 53 int length = test01(cu); 54 55 String str = new String(cu, 0, length); 56 cu = null; 57 test02(str); 58 test03(str.toCharArray()); 59 test04(str); 60 test05(str); 61 62 // Test unpaired surrogates 63 testUnpaired(); 64 65 // Test exceptions 66 testExceptions00(); 67 testExceptions01(str); 68 testExceptions02(str.toCharArray()); 69 } 70 71 static void testConstants() { 72 if (Character.MIN_HIGH_SURROGATE != MIN_HIGH) { 73 constantError("MIN_HIGH_SURROGATE", Character.MIN_HIGH_SURROGATE, MIN_HIGH); 74 } 75 if (Character.MAX_HIGH_SURROGATE != MAX_HIGH) { 76 constantError("MAX_HIGH_SURROGATE", Character.MAX_HIGH_SURROGATE, MAX_HIGH); 77 } 78 if (Character.MIN_LOW_SURROGATE != MIN_LOW) { 79 constantError("MIN_LOW_SURROGATE", Character.MIN_LOW_SURROGATE, MIN_LOW); 80 } 81 if (Character.MAX_LOW_SURROGATE != MAX_LOW) { 82 constantError("MAX_LOW_SURROGATE", Character.MAX_LOW_SURROGATE, MAX_LOW); 83 } 84 if (Character.MIN_SURROGATE != MIN_HIGH) { 85 constantError("MIN_SURROGATE", Character.MIN_SURROGATE, MIN_HIGH); 86 } 87 if (Character.MAX_SURROGATE != MAX_LOW) { 88 constantError("MAX_SURROGATE", Character.MAX_SURROGATE, MAX_LOW); 89 } 90 if (Character.MIN_SUPPLEMENTARY_CODE_POINT != MIN_SUPPLEMENTARY) { 91 constantError("MIN_SUPPLEMENTARY_CODE_POINT", 92 Character.MIN_SUPPLEMENTARY_CODE_POINT, MIN_SUPPLEMENTARY); 93 } 94 if (Character.MIN_CODE_POINT != MIN_CODE_POINT) { 95 constantError("MIN_CODE_POINT", Character.MIN_CODE_POINT, MIN_CODE_POINT); 96 } 97 if (Character.MAX_CODE_POINT != MAX_SUPPLEMENTARY) { 98 constantError("MAX_CODE_POINT", Character.MAX_CODE_POINT, MAX_SUPPLEMENTARY); 99 } 100 } 101 102 static void constantError(String name, int value, int expectedValue) { 103 throw new RuntimeException("Character." + name + " has a wrong value: got " 104 + toHexString(value) 105 + ", expected " + toHexString(expectedValue)); 106 } 107 108 /* 109 * Test isValidCodePoint(int) 110 * isSupplementaryCodePoint(int) 111 * charCount(int) 112 */ 113 static void test00() { 114 for (int cp = -MAX_SUPPLEMENTARY; cp <= MAX_SUPPLEMENTARY*2; cp++) { 115 boolean isValid = cp >= 0 && cp <= MAX_SUPPLEMENTARY; 116 if (Character.isValidCodePoint(cp) != isValid) { 117 throw new RuntimeException("isValidCodePoint failed with " 118 + toHexString(cp)); 119 } 120 boolean isSupplementary = cp >= MIN_SUPPLEMENTARY && cp <= MAX_SUPPLEMENTARY; 121 if (Character.isSupplementaryCodePoint(cp) != isSupplementary) { 122 throw new RuntimeException("isSupplementaryCodePoint failed with " 123 + toHexString(cp)); 124 } 125 int len = Character.charCount(cp); 126 if (isValid) { 127 if ((isSupplementary && len != 2) 128 || (!isSupplementary && len != 1)) { 129 throw new RuntimeException("wrong character length "+len+" for " 130 + toHexString(cp)); 131 } 132 } else if (len != 1 && len != 2) { 133 throw new RuntimeException("wrong character length "+len+" for " 134 + toHexString(cp)); 135 } 136 } 137 } 138 139 /** 140 * Test toChar(int) 141 * toChar(int, char[], int) 142 * isHighSurrogate(char) 143 * isLowSurrogate(char) 144 * isSurrogatePair(int, int) 145 * 146 * While testing those methods, this method generates all Unicode 147 * code points (except for surrogate code points) and store them 148 * in cu. 149 * 150 * @return the number of code units generated in cu 151 */ 152 static int test01(char[] cu) { 153 int index = 0; 154 // Test toChar(int) 155 // toChar(int, char[], int) 156 // isHighSurrogate(char) 157 // isLowSurrogate(char) 158 // with BMP code points 159 for (int i = 0; i <= Character.MAX_VALUE; i++) { 160 char[] u = Character.toChars(i); 161 if (u.length != 1 || u[0] != i) { 162 throw new RuntimeException("wrong toChars(int) result for BMP: " 163 + toHexString("u", u)); 164 } 165 int n = Character.toChars(i, cu, index); 166 if (n != 1 || cu[index] != i) { 167 throw new RuntimeException("wrong toChars(int, char[], int) result for BMP:" 168 + " len=" + n 169 + ", cu["+index+"]="+toHexString(cu[index])); 170 } 171 boolean isHigh = i >= MIN_HIGH && i <= MAX_HIGH; 172 if (Character.isHighSurrogate((char) i) != isHigh) { 173 throw new RuntimeException("wrong high-surrogate test for " 174 + toHexString(i)); 175 } 176 boolean isLow = i >= MIN_LOW && i <= MAX_LOW; 177 if (Character.isLowSurrogate((char)i) != isLow) { 178 throw new RuntimeException("wrong low-surrogate test for " 179 + toHexString(i)); 180 } 181 if (!isHigh && !isLow) { 182 index++; 183 } 184 } 185 186 // Test isSurrogatePair with all surrogate pairs 187 // Test toChars(int) 188 // toChars(int, char[], int) 189 // with all supplementary characters 190 int supplementary = MIN_SUPPLEMENTARY; 191 for (int i = Character.MAX_VALUE/2; i <= Character.MAX_VALUE; i++) { 192 char hi = (char) i; 193 boolean isHigh = Character.isHighSurrogate(hi); 194 195 for (int j = Character.MAX_VALUE/2; j <= Character.MAX_VALUE; j++) { 196 char lo = (char) j; 197 boolean isLow = Character.isLowSurrogate(lo); 198 boolean isSurrogatePair = isHigh && isLow; 199 if (Character.isSurrogatePair(hi, lo) != isSurrogatePair) { 200 throw new RuntimeException("wrong surrogate pair test for hi=" 201 + toHexString(hi) 202 + ", lo="+toHexString(lo)); 203 } 204 if (isSurrogatePair) { 205 int cp = Character.toCodePoint(hi, lo); 206 if (cp != supplementary) { 207 throw new RuntimeException("wrong code point: got " 208 + toHexString(cp) 209 + ", expected=" 210 + toHexString(supplementary)); 211 } 212 char[] u = Character.toChars(cp); 213 if (u.length != 2 || u[0] != hi || u[1] != lo) { 214 throw new RuntimeException("wrong toChars(int) result for supplementary: "+ 215 toHexString("u", u)); 216 } 217 int n = Character.toChars(cp, cu, index); 218 if (n != 2 || cu[index] != hi || cu[index+1] != lo) { 219 throw new RuntimeException("wrong toChars(int, char[], int) result " 220 + "for supplementary: len=" + n 221 + ", cu["+index+"]=" + toHexString(cu[index]) 222 + ", cu["+(index+1)+"]=" + toHexString(cu[index+1])); 223 } 224 index += n; 225 supplementary++; 226 } 227 } 228 } 229 if (supplementary != MAX_SUPPLEMENTARY + 1) { 230 throw new RuntimeException("wrong supplementary count (supplementary=" 231 + toHexString(supplementary)+")"); 232 } 233 234 int nCodeUnits = Character.MAX_VALUE + 1 - (MAX_LOW - MIN_HIGH + 1) 235 + ((MAX_SUPPLEMENTARY - MIN_SUPPLEMENTARY + 1) * 2); 236 if (index != nCodeUnits) { 237 throw new RuntimeException("wrong number of code units: " + index 238 + ", expected " + nCodeUnits); 239 } 240 return index; 241 } 242 243 /** 244 * Test codePointAt(CharSequence, int) 245 * codePointBefore(CharSequence, int) 246 */ 247 static void test02(CharSequence cs) { 248 int cp = 0; 249 int ch; 250 for (int i = 0; i < cs.length(); i += Character.charCount(ch)) { 251 ch = Character.codePointAt(cs, i); 252 if (ch != cp) { 253 throw new RuntimeException("wrong codePointAt(CharSequence, "+i+") value: got " 254 + toHexString(ch) 255 + ", expected "+toHexString(cp)); 256 } 257 cp++; 258 // Skip surrogates 259 if (cp == MIN_HIGH) { 260 cp = MAX_LOW + 1; 261 } 262 } 263 264 cp--; 265 for (int i = cs.length(); i > 0; i -= Character.charCount(ch)) { 266 ch = Character.codePointBefore(cs, i); 267 if (ch != cp) { 268 throw new RuntimeException("codePointBefore(CharSequence, "+i+") returned " 269 + toHexString(ch) 270 + ", expected " + toHexString(cp)); 271 } 272 cp--; 273 // Skip surrogates 274 if (cp == MAX_LOW) { 275 cp = MIN_HIGH - 1; 276 } 277 } 278 } 279 280 /** 281 * Test codePointAt(char[], int) 282 * codePointAt(char[], int, int) 283 * codePointBefore(char[], int) 284 * codePointBefore(char[], int, int) 285 */ 286 static void test03(char[] a) { 287 int cp = 0; 288 int ch; 289 for (int i = 0; i < a.length; i += Character.charCount(ch)) { 290 ch = Character.codePointAt(a, i); 291 if (ch != cp) { 292 throw new RuntimeException("codePointAt(char[], "+i+") returned " 293 + toHexString(ch) 294 + ", expected "+toHexString(cp)); 295 } 296 int x = Character.codePointAt(a, i, i+1); 297 if (x != a[i]) { 298 throw new RuntimeException(String.format( 299 "codePointAt(char[], %d, %d) returned 0x%04x, expected 0x%04x\n", 300 i, i+1, x, (int)a[i])); 301 } 302 cp++; 303 // Skip surrogates 304 if (cp == MIN_HIGH) { 305 cp = MAX_LOW + 1; 306 } 307 } 308 309 cp--; 310 for (int i = a.length; i > 0; i -= Character.charCount(ch)) { 311 ch = Character.codePointBefore(a, i); 312 if (ch != cp) { 313 throw new RuntimeException("codePointBefore(char[], "+i+") returned " 314 + toHexString(ch) 315 + ", expected " + toHexString(cp)); 316 } 317 int x = Character.codePointBefore(a, i, i-1); 318 if (x != a[i-1]) { 319 throw new RuntimeException(String.format( 320 "codePointAt(char[], %d, %d) returned 0x%04x, expected 0x%04x\n", 321 i, i-1, x, (int)a[i-1])); 322 } 323 cp--; 324 // Skip surrogates 325 if (cp == MAX_LOW) { 326 cp = MIN_HIGH - 1; 327 } 328 } 329 } 330 331 /** 332 * Test codePointCount(CharSequence, int, int) 333 * codePointCount(char[], int, int, int, int) 334 */ 335 static void test04(String str) { 336 int length = str.length(); 337 char[] a = str.toCharArray(); 338 339 for (int i = 0; i <= length; i += 99, length -= 29999) { 340 int n = Character.codePointCount(str, i, length); 341 int m = codePointCount(str.substring(i, length)); 342 checkCodePointCount(str, n, m); 343 n = Character.codePointCount(a, i, length - i); 344 checkCodePointCount(a, n, m); 345 } 346 347 // test special cases 348 length = str.length(); 349 int n = Character.codePointCount(str, 0, 0); 350 checkCodePointCount(str, n, 0); 351 n = Character.codePointCount(str, length, length); 352 checkCodePointCount(str, n, 0); 353 n = Character.codePointCount(a, 0, 0); 354 checkCodePointCount(a, n, 0); 355 n = Character.codePointCount(a, length, 0); 356 checkCodePointCount(a, n, 0); 357 } 358 359 // This method assumes that Character.codePointAt() and 360 // Character.charCount() work correctly. 361 private static int codePointCount(CharSequence seq) { 362 int n = 0, len; 363 for (int i = 0; i < seq.length(); i += len) { 364 int codepoint = Character.codePointAt(seq, i); 365 n++; 366 len = Character.charCount(codepoint); 367 } 368 return n; 369 } 370 371 private static void checkCodePointCount(Object data, int n, int expected) { 372 String type = getType(data); 373 if (n != expected) { 374 throw new RuntimeException("codePointCount(" + type + "...) returned " + n 375 + ", expected " + expected); 376 } 377 } 378 379 /** 380 * Test offsetByCodePoints(CharSequence, int, int) 381 * offsetByCodePoints(char[], int, int, int, int) 382 * 383 * This test case assumes that Character.codePointCount()s work 384 * correctly. 385 */ 386 static void test05(String str) { 387 int length = str.length(); 388 char[] a = str.toCharArray(); 389 390 for (int i = 0; i <= length; i += 99, length -= 29999) { 391 int nCodePoints = Character.codePointCount(a, i, length - i); 392 int index; 393 394 // offsetByCodePoints(CharSequence, int, int) 395 396 int expectedHighIndex = length; 397 // For forward CharSequence scan, we need to adjust the 398 // expected index in case the last char in the text range 399 // is a high surrogate and forms a valid supplementary 400 // code point with the next char. 401 if (length < a.length) { 402 int cp = Character.codePointAt(a, length - 1); 403 if (Character.isSupplementaryCodePoint(cp)) { 404 expectedHighIndex++; 405 } 406 } 407 index = Character.offsetByCodePoints(str, i, nCodePoints); 408 checkNewIndex(str, nCodePoints, index, expectedHighIndex); 409 int expectedLowIndex = i; 410 if (i > 0) { 411 int cp = Character.codePointBefore(a, i + 1); 412 if (Character.isSupplementaryCodePoint(cp)) { 413 expectedLowIndex--; 414 } 415 } 416 index = Character.offsetByCodePoints(str, length, -nCodePoints); 417 checkNewIndex(str, -nCodePoints, index, expectedLowIndex); 418 419 // offsetByCodePoints(char[], int, int, int, int) 420 421 int start = Math.max(0, i-1); 422 int limit = Math.min(a.length, length+1); 423 index = Character.offsetByCodePoints(a, start, limit - start, 424 i, nCodePoints); 425 checkNewIndex(a, nCodePoints, index, expectedHighIndex); 426 if (length != expectedHighIndex) { 427 index = Character.offsetByCodePoints(a, start, length - start, 428 i, nCodePoints); 429 checkNewIndex(a, nCodePoints, index, length); 430 } 431 index = Character.offsetByCodePoints(a, start, limit - start, 432 length, -nCodePoints); 433 checkNewIndex(a, -nCodePoints, index, expectedLowIndex); 434 if (i != expectedLowIndex) { 435 index = Character.offsetByCodePoints(a, i, limit - i, 436 length, -nCodePoints); 437 checkNewIndex(a, -nCodePoints, index, i); 438 } 439 } 440 441 // test special cases for 0-length text ranges. 442 length = str.length(); 443 int index = Character.offsetByCodePoints(str, 0, 0); 444 checkNewIndex(str, 0, index, 0); 445 index = Character.offsetByCodePoints(str, length, 0); 446 checkNewIndex(str, 0, index, length); 447 index = Character.offsetByCodePoints(a, 0, 0, 0, 0); 448 checkNewIndex(a, 0, index, 0); 449 index = Character.offsetByCodePoints(a, 0, length, 0, 0); 450 checkNewIndex(a, 0, index, 0); 451 index = Character.offsetByCodePoints(a, 0, length, length, 0); 452 checkNewIndex(a, 0, index, length); 453 index = Character.offsetByCodePoints(a, length, 0, length, 0); 454 checkNewIndex(a, 0, index, length); 455 } 456 457 private static void checkNewIndex(Object data, int offset, int result, int expected) { 458 String type = getType(data); 459 String offsetType = (offset > 0) ? "positive" : (offset < 0) ? "negative" : "0"; 460 if (result != expected) { 461 throw new RuntimeException("offsetByCodePoints(" + type + ", ...) [" 462 + offsetType + " offset]" 463 + " returned " + result 464 + ", expected " + expected); 465 } 466 } 467 468 // Test codePointAt(CharSequence, int) 469 // codePointBefore(CharSequence, int) 470 // codePointAt(char[], int) 471 // codePointBefore(char[], int) 472 // toChar(int) 473 // toChar(int, char[], int) 474 // with unpaired surrogates 475 static void testUnpaired() { 476 testCodePoint("\uD800", new int[] { 0xD800 }); 477 testCodePoint("\uDC00", new int[] { 0xDC00 }); 478 testCodePoint("a\uD800", new int[] { 'a', 0xD800 }); 479 testCodePoint("a\uDC00", new int[] { 'a', 0xDC00 }); 480 testCodePoint("\uD800a", new int[] { 0xD800, 'a' }); 481 testCodePoint("\uDBFFa", new int[] { 0xDBFF, 'a' }); 482 testCodePoint("a\uD800\uD801", new int[] { 'a', 0xD800, 0xD801 }); 483 testCodePoint("a\uD800x\uDC00", new int[] { 'a', 0xD800, 'x', 0xDC00 }); 484 testCodePoint("\uDC00\uD800", new int[] { 0xDC00, 0xD800 }); 485 testCodePoint("\uD800\uDC00\uDC00", new int[] { 0x10000, 0xDC00 }); 486 testCodePoint("\uD800\uD800\uDC00", new int[] { 0xD800, 0x10000 }); 487 testCodePoint("\uD800\uD800\uD800\uD800\uDC00\uDC00\uDC00\uDC00", 488 new int[] { 0xD800, 0xD800, 0xD800, 0x10000, 0xDC00, 0xDC00, 0xDC00}); 489 } 490 491 static void testCodePoint(String str, int[] codepoints) { 492 int c; 493 // Test Character.codePointAt/Before(CharSequence, int) 494 int j = 0; 495 for (int i = 0; i < str.length(); i += Character.charCount(c)) { 496 c = Character.codePointAt(str, i); 497 if (c != codepoints[j++]) { 498 throw new RuntimeException("codePointAt(CharSequence, " + i + ") returned " 499 + toHexString(c) 500 + ", expected " + toHexString(codepoints[j-1])); 501 } 502 } 503 if (j != codepoints.length) { 504 throw new RuntimeException("j != codepoints.length after codePointAt(CharSequence, int)" 505 + " (j=" + j + ")" 506 + ", expected: " + codepoints.length); 507 } 508 509 j = codepoints.length; 510 for (int i = str.length(); i > 0 ; i -= Character.charCount(c)) { 511 c = Character.codePointBefore(str, i); 512 if (c != codepoints[--j]) { 513 throw new RuntimeException("codePointBefore(CharSequence, " + i + ") returned " 514 + toHexString(c) 515 + ", expected " + toHexString(codepoints[j])); 516 } 517 } 518 if (j != 0) { 519 throw new RuntimeException("j != 0 after codePointBefore(CharSequence, int)" 520 + " (j=" + j + ")"); 521 } 522 523 // Test Character.codePointAt/Before(char[], int) 524 char[] a = str.toCharArray(); 525 j = 0; 526 for (int i = 0; i < a.length; i += Character.charCount(c)) { 527 c = Character.codePointAt(a, i); 528 if (c != codepoints[j++]) { 529 throw new RuntimeException("codePointAt(char[], " + i + ") returned " 530 + toHexString(c) 531 + ", expected " + toHexString(codepoints[j-1])); 532 } 533 } 534 if (j != codepoints.length) { 535 throw new RuntimeException("j != codepoints.length after codePointAt(char[], int)" 536 + " (j=" + j + ")" 537 + ", expected: " + codepoints.length); 538 } 539 540 j = codepoints.length; 541 for (int i = a.length; i > 0 ; i -= Character.charCount(c)) { 542 c = Character.codePointBefore(a, i); 543 if (c != codepoints[--j]) { 544 throw new RuntimeException("codePointBefore(char[], " + i + ") returned " 545 + toHexString(c) 546 + ", expected " + toHexString(codepoints[j])); 547 } 548 } 549 if (j != 0) { 550 throw new RuntimeException("j != 0 after codePointBefore(char[], int)" 551 + " (j=" + j + ")"); 552 } 553 554 // Test toChar(int) 555 j = 0; 556 for (int i = 0; i < codepoints.length; i++) { 557 a = Character.toChars(codepoints[i]); 558 for (int k = 0; k < a.length; k++) { 559 if (str.charAt(j++) != a[k]) { 560 throw new RuntimeException("toChars(int) returned " + toHexString("result", a) 561 + " from codepoint=" + toHexString(codepoints[i])); 562 } 563 } 564 } 565 566 // Test toChars(int, char[], int) 567 a = new char[codepoints.length * 2]; 568 j = 0; 569 for (int i = 0; i < codepoints.length; i++) { 570 int n = Character.toChars(codepoints[i], a, j); 571 j += n; 572 } 573 String s = new String(a, 0, j); 574 if (!str.equals(s)) { 575 throw new RuntimeException("toChars(int, char[], int) returned " 576 + toHexString("dst", s.toCharArray()) 577 + ", expected " + toHexString("data", str.toCharArray())); 578 } 579 } 580 581 // Test toChar(int) 582 // toChar(int, char[], int) 583 // for exceptions 584 static void testExceptions00() { 585 callToChars1(-1, IllegalArgumentException.class); 586 callToChars1(MAX_SUPPLEMENTARY + 1, IllegalArgumentException.class); 587 588 callToChars3(MAX_SUPPLEMENTARY, null, 0, NullPointerException.class); 589 callToChars3(-MIN_SUPPLEMENTARY, new char[2], 0, IllegalArgumentException.class); 590 callToChars3(MAX_SUPPLEMENTARY + 1, new char[2], 0, IllegalArgumentException.class); 591 callToChars3('A', new char[0], 0, IndexOutOfBoundsException.class); 592 callToChars3('A', new char[1], -1, IndexOutOfBoundsException.class); 593 callToChars3('A', new char[1], 1, IndexOutOfBoundsException.class); 594 callToChars3(MIN_SUPPLEMENTARY, new char[0], 0, IndexOutOfBoundsException.class); 595 callToChars3(MIN_SUPPLEMENTARY, new char[1], 0, IndexOutOfBoundsException.class); 596 callToChars3(MIN_SUPPLEMENTARY, new char[2], -1, IndexOutOfBoundsException.class); 597 callToChars3(MIN_SUPPLEMENTARY, new char[2], 1, IndexOutOfBoundsException.class); 598 } 599 600 static final boolean At = true, Before = false; 601 602 /** 603 * Test codePointAt(CharSequence, int) 604 * codePointBefore(CharSequence, int) 605 * codePointCount(CharSequence, int, int) 606 * offsetByCodePoints(CharSequence, int, int) 607 * for exceptions 608 */ 609 static void testExceptions01(CharSequence cs) { 610 CharSequence nullSeq = null; 611 // codePointAt 612 callCodePoint(At, nullSeq, 0, NullPointerException.class); 613 callCodePoint(At, cs, -1, IndexOutOfBoundsException.class); 614 callCodePoint(At, cs, cs.length(), IndexOutOfBoundsException.class); 615 callCodePoint(At, cs, cs.length()*3, IndexOutOfBoundsException.class); 616 617 // codePointBefore 618 callCodePoint(Before, nullSeq, 0, NullPointerException.class); 619 callCodePoint(Before, cs, -1, IndexOutOfBoundsException.class); 620 callCodePoint(Before, cs, 0, IndexOutOfBoundsException.class); 621 callCodePoint(Before, cs, cs.length()+1, IndexOutOfBoundsException.class); 622 623 // codePointCount 624 callCodePointCount(nullSeq, 0, 0, NullPointerException.class); 625 callCodePointCount(cs, -1, 1, IndexOutOfBoundsException.class); 626 callCodePointCount(cs, 0, cs.length()+1, IndexOutOfBoundsException.class); 627 callCodePointCount(cs, 3, 1, IndexOutOfBoundsException.class); 628 629 // offsetByCodePoints 630 callOffsetByCodePoints(nullSeq, 0, 0, NullPointerException.class); 631 callOffsetByCodePoints(cs, -1, 1, IndexOutOfBoundsException.class); 632 callOffsetByCodePoints(cs, cs.length()+1, 1, IndexOutOfBoundsException.class); 633 callOffsetByCodePoints(cs, 0, cs.length()*2, IndexOutOfBoundsException.class); 634 callOffsetByCodePoints(cs, cs.length(), 1, IndexOutOfBoundsException.class); 635 callOffsetByCodePoints(cs, 0, -1, IndexOutOfBoundsException.class); 636 callOffsetByCodePoints(cs, cs.length(), -cs.length()*2, 637 IndexOutOfBoundsException.class); 638 callOffsetByCodePoints(cs, cs.length(), Integer.MIN_VALUE, 639 IndexOutOfBoundsException.class); 640 callOffsetByCodePoints(cs, 0, Integer.MAX_VALUE, IndexOutOfBoundsException.class); 641 } 642 643 /** 644 * Test codePointAt(char[], int) 645 * codePointAt(char[], int, int) 646 * codePointBefore(char[], int) 647 * codePointBefore(char[], int, int) 648 * codePointCount(char[], int, int) 649 * offsetByCodePoints(char[], int, int, int, int) 650 * for exceptions 651 */ 652 static void testExceptions02(char[] a) { 653 char[] nullArray = null; 654 callCodePoint(At, nullArray, 0, NullPointerException.class); 655 callCodePoint(At, a, -1, IndexOutOfBoundsException.class); 656 callCodePoint(At, a, a.length, IndexOutOfBoundsException.class); 657 callCodePoint(At, a, a.length*3, IndexOutOfBoundsException.class); 658 callCodePoint(Before, nullArray, 0, NullPointerException.class); 659 callCodePoint(Before, a, -1, IndexOutOfBoundsException.class); 660 callCodePoint(Before, a, 0, IndexOutOfBoundsException.class); 661 callCodePoint(Before, a, a.length+1, IndexOutOfBoundsException.class); 662 663 // tests for the methods with limit 664 callCodePoint(At, nullArray, 0, 1, NullPointerException.class); 665 callCodePoint(At, a, 0, -1, IndexOutOfBoundsException.class); 666 callCodePoint(At, a, 0, 0, IndexOutOfBoundsException.class); 667 callCodePoint(At, a, 0, a.length+1, IndexOutOfBoundsException.class); 668 callCodePoint(At, a, 2, 1, IndexOutOfBoundsException.class); 669 callCodePoint(At, a, -1, 1, IndexOutOfBoundsException.class); 670 callCodePoint(At, a, a.length, 1, IndexOutOfBoundsException.class); 671 callCodePoint(At, a, a.length*3, 1, IndexOutOfBoundsException.class); 672 callCodePoint(Before, nullArray, 1, 0, NullPointerException.class); 673 callCodePoint(Before, a, 2, -1, IndexOutOfBoundsException.class); 674 callCodePoint(Before, a, 2, 2, IndexOutOfBoundsException.class); 675 callCodePoint(Before, a, 2, 3, IndexOutOfBoundsException.class); 676 callCodePoint(Before, a, 2, a.length, IndexOutOfBoundsException.class); 677 callCodePoint(Before, a, -1, -1, IndexOutOfBoundsException.class); 678 callCodePoint(Before, a, 0, 0, IndexOutOfBoundsException.class); 679 callCodePoint(Before, a, a.length+1, a.length-1, IndexOutOfBoundsException.class); 680 681 // codePointCount 682 callCodePointCount(nullArray, 0, 0, NullPointerException.class); 683 callCodePointCount(a, -1, 1, IndexOutOfBoundsException.class); 684 callCodePointCount(a, 0, -1, IndexOutOfBoundsException.class); 685 callCodePointCount(a, 0, a.length+1, IndexOutOfBoundsException.class); 686 callCodePointCount(a, 1, a.length, IndexOutOfBoundsException.class); 687 callCodePointCount(a, a.length, 1, IndexOutOfBoundsException.class); 688 callCodePointCount(a, a.length+1, -1, IndexOutOfBoundsException.class); 689 690 // offsetByCodePoints 691 callOffsetByCodePoints(nullArray, 0, 0, 0, 0, NullPointerException.class); 692 callOffsetByCodePoints(a, -1, a.length, 1, 1, IndexOutOfBoundsException.class); 693 callOffsetByCodePoints(a, 0, a.length+1, 1, 1, IndexOutOfBoundsException.class); 694 callOffsetByCodePoints(a, 10, a.length, 1, 1, IndexOutOfBoundsException.class); 695 callOffsetByCodePoints(a, 10, a.length-10, 1, 1, IndexOutOfBoundsException.class); 696 callOffsetByCodePoints(a, 10, 10, 21, 1, IndexOutOfBoundsException.class); 697 callOffsetByCodePoints(a, 20, -10, 15, 1, IndexOutOfBoundsException.class); 698 callOffsetByCodePoints(a, 10, 10, 15, 20, IndexOutOfBoundsException.class); 699 callOffsetByCodePoints(a, 10, 10, 15, -20, IndexOutOfBoundsException.class); 700 callOffsetByCodePoints(a, 0, a.length, -1, 1, IndexOutOfBoundsException.class); 701 callOffsetByCodePoints(a, 0, a.length, a.length+1, 1, IndexOutOfBoundsException.class); 702 callOffsetByCodePoints(a, 0, a.length, 0, a.length*2, IndexOutOfBoundsException.class); 703 callOffsetByCodePoints(a, 0, a.length, a.length, 1, IndexOutOfBoundsException.class); 704 callOffsetByCodePoints(a, 0, a.length, 0, -1, IndexOutOfBoundsException.class); 705 callOffsetByCodePoints(a, 0, a.length, a.length, -a.length*2, 706 IndexOutOfBoundsException.class); 707 callOffsetByCodePoints(a, 0, a.length, a.length, Integer.MIN_VALUE, 708 IndexOutOfBoundsException.class); 709 callOffsetByCodePoints(a, 0, a.length, 0, Integer.MAX_VALUE, 710 IndexOutOfBoundsException.class); 711 } 712 713 /** 714 * Test the 1-arg toChars(int) for exceptions 715 */ 716 private static void callToChars1(int codePoint, Class expectedException) { 717 try { 718 char[] a = Character.toChars(codePoint); 719 } catch (Exception e) { 720 if (expectedException.isInstance(e)) { 721 return; 722 } 723 throw new RuntimeException("Unspecified exception", e); 724 } 725 throw new RuntimeException("toChars(int) didn't throw " + expectedException.getName()); 726 } 727 728 /** 729 * Test the 3-arg toChars(int, char[], int) for exceptions 730 */ 731 private static void callToChars3(int codePoint, char[] dst, int index, 732 Class expectedException) { 733 try { 734 int n = Character.toChars(codePoint, dst, index); 735 } catch (Exception e) { 736 if (expectedException.isInstance(e)) { 737 return; 738 } 739 throw new RuntimeException("Unspecified exception", e); 740 } 741 throw new RuntimeException("toChars(int,char[],int) didn't throw " 742 + expectedException.getName()); 743 } 744 745 private static void callCodePoint(boolean isAt, CharSequence cs, int index, 746 Class expectedException) { 747 try { 748 int c = isAt ? Character.codePointAt(cs, index) 749 : Character.codePointBefore(cs, index); 750 } catch (Exception e) { 751 if (expectedException.isInstance(e)) { 752 return; 753 } 754 throw new RuntimeException("Unspecified exception", e); 755 } 756 throw new RuntimeException("codePoint" + (isAt ? "At" : "Before") 757 + " didn't throw " + expectedException.getName()); 758 } 759 760 private static void callCodePoint(boolean isAt, char[] a, int index, 761 Class expectedException) { 762 try { 763 int c = isAt ? Character.codePointAt(a, index) 764 : Character.codePointBefore(a, index); 765 } catch (Exception e) { 766 if (expectedException.isInstance(e)) { 767 return; 768 } 769 throw new RuntimeException("Unspecified exception", e); 770 } 771 throw new RuntimeException("codePoint" + (isAt ? "At" : "Before") 772 + " didn't throw " + expectedException.getName()); 773 } 774 775 private static void callCodePoint(boolean isAt, char[] a, int index, int limit, 776 Class expectedException) { 777 try { 778 int c = isAt ? Character.codePointAt(a, index, limit) 779 : Character.codePointBefore(a, index, limit); 780 } catch (Exception e) { 781 if (expectedException.isInstance(e)) { 782 return; 783 } 784 throw new RuntimeException("Unspecified exception", e); 785 } 786 throw new RuntimeException("codePoint" + (isAt ? "At" : "Before") 787 + " didn't throw " + expectedException.getName()); 788 } 789 790 private static void callCodePointCount(Object data, int beginIndex, int endIndex, 791 Class expectedException) { 792 String type = getType(data); 793 try { 794 int n = (data instanceof CharSequence) ? 795 Character.codePointCount((CharSequence) data, beginIndex, endIndex) 796 : Character.codePointCount((char[]) data, beginIndex, endIndex); 797 } catch (Exception e) { 798 if (expectedException.isInstance(e)) { 799 return; 800 } 801 throw new RuntimeException("Unspecified exception", e); 802 } 803 throw new RuntimeException("codePointCount(" + type + "...) didn't throw " 804 + expectedException.getName()); 805 } 806 807 private static void callOffsetByCodePoints(CharSequence seq, int index, int offset, 808 Class expectedException) { 809 try { 810 int n = Character.offsetByCodePoints(seq, index, offset); 811 } catch (Exception e) { 812 if (expectedException.isInstance(e)) { 813 return; 814 } 815 throw new RuntimeException("Unspecified exception", e); 816 } 817 throw new RuntimeException("offsetCodePointCounts(CharSequnce...) didn't throw " 818 + expectedException.getName()); 819 } 820 821 822 private static void callOffsetByCodePoints(char[] a, int start, int count, 823 int index, int offset, 824 Class expectedException) { 825 try { 826 int n = Character.offsetByCodePoints(a, start, count, index, offset); 827 } catch (Exception e) { 828 if (expectedException.isInstance(e)) { 829 return; 830 } 831 throw new RuntimeException("Unspecified exception", e); 832 } 833 throw new RuntimeException("offsetCodePointCounts(char[]...) didn't throw " 834 + expectedException.getName()); 835 } 836 837 private static String getType(Object data) { 838 return (data instanceof CharSequence) ? "CharSequence" : "char[]"; 839 } 840 841 private static String toHexString(int c) { 842 return "0x" + Integer.toHexString(c); 843 } 844 845 private static String toHexString(String name, char[] a) { 846 StringBuffer sb = new StringBuffer(); 847 for (int i = 0; i < a.length; i++) { 848 if (i > 0) { 849 sb.append(", "); 850 } 851 sb.append(name).append('[').append(i).append("]="); 852 sb.append(toHexString(a[i])); 853 } 854 return sb.toString(); 855 } 856 }