1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2002-2014, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 */ 9 10 /** 11 * Port From: ICU4C v2.1 : collate/CollationAPITest 12 * Source File: $ICU4CRoot/source/test/intltest/apicoll.cpp 13 **/ 14 15 package com.ibm.icu.dev.test.collator; 16 17 import java.text.CharacterIterator; 18 import java.text.StringCharacterIterator; 19 import java.util.Arrays; 20 import java.util.HashSet; 21 import java.util.Locale; 22 import java.util.MissingResourceException; 23 import java.util.Set; 24 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.junit.runners.JUnit4; 28 29 import com.ibm.icu.dev.test.TestFmwk; 30 import com.ibm.icu.impl.Utility; 31 import com.ibm.icu.lang.UCharacter; 32 import com.ibm.icu.text.CollationElementIterator; 33 import com.ibm.icu.text.CollationKey; 34 import com.ibm.icu.text.Collator; 35 import com.ibm.icu.text.Collator.CollatorFactory; 36 import com.ibm.icu.text.RawCollationKey; 37 import com.ibm.icu.text.RuleBasedCollator; 38 import com.ibm.icu.text.UCharacterIterator; 39 import com.ibm.icu.text.UnicodeSet; 40 import com.ibm.icu.util.ULocale; 41 import com.ibm.icu.util.VersionInfo; 42 43 @RunWith(JUnit4.class) 44 public class CollationAPITest extends TestFmwk { 45 /** 46 * This tests the collation key related APIs. 47 * - constructor/destructor 48 * - Collator.getCollationKey 49 * - == and != operators 50 * - comparison between collation keys 51 * - creating collation key with a byte array and vice versa 52 */ 53 @Test TestCollationKey()54 public void TestCollationKey() { 55 logln("testing CollationKey begins..."); 56 Collator col = Collator.getInstance(); 57 col.setStrength(Collator.TERTIARY); 58 59 String test1 = "Abcda"; 60 String test2 = "abcda"; 61 62 logln("Testing weird arguments"); 63 CollationKey sortk1 = col.getCollationKey(""); 64 // key gets reset here 65 byte[] bytes = sortk1.toByteArray(); 66 doAssert(bytes.length == 3 && bytes[0] == 1 && bytes[1] == 1 67 && bytes[2] == 0, 68 "Empty string should return a collation key with empty levels"); 69 70 // Most control codes and CGJ are completely ignorable. 71 // A string with only completely ignorables must compare equal to an empty string. 72 CollationKey sortkIgnorable = col.getCollationKey("\u0001\u034f"); 73 doAssert(sortkIgnorable != null && sortkIgnorable.toByteArray().length == 3, 74 "Completely ignorable string should return a collation key with empty levels"); 75 doAssert(sortkIgnorable.compareTo(sortk1) == 0, 76 "Completely ignorable string should compare equal to empty string"); 77 78 // bogus key returned here 79 sortk1 = col.getCollationKey(null); 80 doAssert(sortk1 == null, "Error code should return bogus collation key"); 81 82 logln("Use tertiary comparison level testing ...."); 83 sortk1 = col.getCollationKey(test1); 84 CollationKey sortk2 = col.getCollationKey(test2); 85 doAssert((sortk1.compareTo(sortk2)) > 0, "Result should be \"Abcda\" >>> \"abcda\""); 86 87 CollationKey sortkNew; 88 sortkNew = sortk1; 89 doAssert(!(sortk1.equals(sortk2)), "The sort keys should be different"); 90 doAssert((sortk1.hashCode() != sortk2.hashCode()), "sort key hashCode() failed"); 91 doAssert((sortk1.equals(sortkNew)), "The sort keys assignment failed"); 92 doAssert((sortk1.hashCode() == sortkNew.hashCode()), "sort key hashCode() failed"); 93 94 // port from apicoll 95 try { 96 col = Collator.getInstance(); 97 } catch (Exception e) { 98 errln("Collator.getInstance() failed"); 99 } 100 if (col.getStrength() != Collator.TERTIARY){ 101 errln("Default collation did not have tertiary strength"); 102 } 103 104 // Need to use identical strength 105 col.setStrength(Collator.IDENTICAL); 106 107 CollationKey key1 = col.getCollationKey(test1); 108 CollationKey key2 = col.getCollationKey(test2); 109 CollationKey key3 = col.getCollationKey(test2); 110 111 doAssert(key1.compareTo(key2) > 0, 112 "Result should be \"Abcda\" > \"abcda\""); 113 doAssert(key2.compareTo(key1) < 0, 114 "Result should be \"abcda\" < \"Abcda\""); 115 doAssert(key2.compareTo(key3) == 0, 116 "Result should be \"abcda\" == \"abcda\""); 117 118 byte key2identical[] = key2.toByteArray(); 119 120 logln("Use secondary comparison level testing ..."); 121 col.setStrength(Collator.SECONDARY); 122 123 key1 = col.getCollationKey(test1); 124 key2 = col.getCollationKey(test2); 125 key3 = col.getCollationKey(test2); 126 127 doAssert(key1.compareTo(key2) == 0, 128 "Result should be \"Abcda\" == \"abcda\""); 129 doAssert(key2.compareTo(key3) == 0, 130 "Result should be \"abcda\" == \"abcda\""); 131 132 byte tempkey[] = key2.toByteArray(); 133 byte subkey2compat[] = new byte[tempkey.length]; 134 System.arraycopy(key2identical, 0, subkey2compat, 0, tempkey.length); 135 subkey2compat[subkey2compat.length - 1] = 0; 136 doAssert(Arrays.equals(tempkey, subkey2compat), 137 "Binary format for 'abcda' sortkey different for secondary strength!"); 138 139 logln("testing sortkey ends..."); 140 } 141 142 @Test 143 public void TestRawCollationKey() 144 { 145 // testing constructors 146 RawCollationKey key = new RawCollationKey(); 147 if (key.bytes != null || key.size != 0) { 148 errln("Empty default constructor expected to leave the bytes null " 149 + "and size 0"); 150 } 151 byte array[] = new byte[128]; 152 key = new RawCollationKey(array); 153 if (key.bytes != array || key.size != 0) { 154 errln("Constructor taking an array expected to adopt it and " 155 + "retaining its size 0"); 156 } 157 try { 158 key = new RawCollationKey(array, 129); 159 errln("Constructor taking an array and a size > array.length " 160 + "expected to throw an exception"); 161 } catch (IndexOutOfBoundsException e) { 162 logln("PASS: Constructor failed as expected"); 163 } 164 try { 165 key = new RawCollationKey(array, -1); 166 errln("Constructor taking an array and a size < 0 " 167 + "expected to throw an exception"); 168 } catch (IndexOutOfBoundsException e) { 169 logln("PASS: Constructor failed as expected"); 170 } 171 key = new RawCollationKey(array, array.length >> 1); 172 if (key.bytes != array || key.size != (array.length >> 1)) { 173 errln("Constructor taking an array and a size, " 174 + "expected to adopt it and take the size specified"); 175 } 176 key = new RawCollationKey(10); 177 if (key.bytes == null || key.bytes.length != 10 || key.size != 0) { 178 errln("Constructor taking a specified capacity expected to " 179 + "create a new internal byte array with length 10 and " 180 + "retain size 0"); 181 } 182 } 183 doAssert(boolean conditions, String message)184 void doAssert(boolean conditions, String message) { 185 if (!conditions) { 186 errln(message); 187 } 188 } 189 190 /** 191 * This tests the comparison convenience methods of a collator object. 192 * - greater than 193 * - greater than or equal to 194 * - equal to 195 */ 196 @Test TestCompare()197 public void TestCompare() { 198 logln("The compare tests begin : "); 199 Collator col = Collator.getInstance(Locale.ENGLISH); 200 201 String test1 = "Abcda"; 202 String test2 = "abcda"; 203 logln("Use tertiary comparison level testing ...."); 204 205 doAssert((!col.equals(test1, test2) ), "Result should be \"Abcda\" != \"abcda\""); 206 doAssert((col.compare(test1, test2) > 0 ), "Result should be \"Abcda\" >>> \"abcda\""); 207 208 col.setStrength(Collator.SECONDARY); 209 logln("Use secondary comparison level testing ...."); 210 211 doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); 212 doAssert((col.compare(test1, test2) == 0), "Result should be \"Abcda\" == \"abcda\""); 213 214 col.setStrength(Collator.PRIMARY); 215 logln("Use primary comparison level testing ...."); 216 217 doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); 218 doAssert((col.compare(test1, test2) == 0 ), "Result should be \"Abcda\" == \"abcda\""); 219 logln("The compare tests end."); 220 } 221 222 /** 223 * Tests decomposition setting 224 */ 225 @Test TestDecomposition()226 public void TestDecomposition() { 227 Collator en_US = null, el_GR = null, vi_VN = null; 228 229 en_US = Collator.getInstance(new Locale("en", "US")); 230 el_GR = Collator.getInstance(new Locale("el", "GR")); 231 vi_VN = Collator.getInstance(new Locale("vi", "VN")); 232 233 234 // there is no reason to have canonical decomposition in en_US OR default locale */ 235 if (vi_VN.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) 236 { 237 errln("vi_VN collation did not have canonical decomposition for normalization!"); 238 } 239 240 if (el_GR.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) 241 { 242 errln("el_GR collation did not have canonical decomposition for normalization!"); 243 } 244 245 if (en_US.getDecomposition() != Collator.NO_DECOMPOSITION) 246 { 247 errln("en_US collation had canonical decomposition for normalization!"); 248 } 249 } 250 251 /** 252 * This tests the duplication of a collator object. 253 */ 254 @Test TestDuplicate()255 public void TestDuplicate() { 256 //Clone does not be implemented 257 Collator col1 = Collator.getInstance(Locale.ENGLISH); 258 259 // Collator col2 = (Collator)col1.clone(); 260 // doAssert(col1.equals(col2), "Cloned object is not equal to the original"); 261 String ruleset = "&9 < a, A < b, B < c, C < d, D, e, E"; 262 RuleBasedCollator col3 = null; 263 try { 264 col3 = new RuleBasedCollator(ruleset); 265 } catch (Exception e) { 266 errln("Failure creating RuleBasedCollator with rule: \"" + ruleset + "\"\n" + e); 267 return; 268 } 269 doAssert(!col1.equals(col3), "Cloned object is equal to some dummy"); 270 col3 = (RuleBasedCollator)col1; 271 doAssert(col1.equals(col3), "Copied object is not equal to the original"); 272 273 } 274 275 /** 276 * This tests the CollationElementIterator related APIs. 277 * - creation of a CollationElementIterator object 278 * - == and != operators 279 * - iterating forward 280 * - resetting the iterator index 281 * - requesting the order properties(primary, secondary or tertiary) 282 */ 283 @Test TestElemIter()284 public void TestElemIter() { 285 // logln("testing sortkey begins..."); 286 Collator col = Collator.getInstance(Locale.ENGLISH); 287 288 289 String testString1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; 290 String testString2 = "Xf_ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; 291 // logln("Constructors and comparison testing...."); 292 CollationElementIterator iterator1 = ((RuleBasedCollator)col).getCollationElementIterator(testString1); 293 294 CharacterIterator chariter=new StringCharacterIterator(testString1); 295 // copy ctor 296 CollationElementIterator iterator2 = ((RuleBasedCollator)col).getCollationElementIterator(chariter); 297 UCharacterIterator uchariter=UCharacterIterator.getInstance(testString2); 298 CollationElementIterator iterator3 = ((RuleBasedCollator)col).getCollationElementIterator(uchariter); 299 300 int offset = 0; 301 offset = iterator1.getOffset(); 302 if (offset != 0) { 303 errln("Error in getOffset for collation element iterator"); 304 return; 305 } 306 iterator1.setOffset(6); 307 iterator1.setOffset(0); 308 int order1, order2, order3; 309 310 order1 = iterator1.next(); 311 doAssert(!(iterator1.equals(iterator2)), "The first iterator advance failed"); 312 order2 = iterator2.next(); 313 314 // Code coverage for dummy "not designed" hashCode() which does "assert false". 315 try { 316 iterator1.hashCode(); // We don't expect any particular value. 317 } catch (AssertionError ignored) { 318 // Expected to be thrown if assertions are enabled. 319 } 320 321 // In ICU 52 and earlier we had iterator1.equals(iterator2) 322 // but in ICU 53 this fails because the iterators differ (String vs. CharacterIterator). 323 // doAssert((iterator1.equals(iterator2)), "The second iterator advance failed"); 324 doAssert(iterator1.getOffset() == iterator2.getOffset(), "The second iterator advance failed"); 325 doAssert((order1 == order2), "The order result should be the same"); 326 order3 = iterator3.next(); 327 328 doAssert((CollationElementIterator.primaryOrder(order1) == 329 CollationElementIterator.primaryOrder(order3)), "The primary orders should be the same"); 330 doAssert((CollationElementIterator.secondaryOrder(order1) == 331 CollationElementIterator.secondaryOrder(order3)), "The secondary orders should be the same"); 332 doAssert((CollationElementIterator.tertiaryOrder(order1) == 333 CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be the same"); 334 335 order1 = iterator1.next(); 336 order3 = iterator3.next(); 337 338 doAssert((CollationElementIterator.primaryOrder(order1) == 339 CollationElementIterator.primaryOrder(order3)), "The primary orders should be identical"); 340 doAssert((CollationElementIterator.tertiaryOrder(order1) != 341 CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be different"); 342 343 order1 = iterator1.next(); 344 order3 = iterator3.next(); 345 // invalid test wrong in UCA 346 // doAssert((CollationElementIterator.secondaryOrder(order1) != 347 // CollationElementIterator.secondaryOrder(order3)), "The secondary orders should not be the same"); 348 349 doAssert((order1 != CollationElementIterator.NULLORDER), "Unexpected end of iterator reached"); 350 351 iterator1.reset(); 352 iterator2.reset(); 353 iterator3.reset(); 354 order1 = iterator1.next(); 355 356 doAssert(!(iterator1.equals(iterator2)), "The first iterator advance failed"); 357 358 order2 = iterator2.next(); 359 360 // In ICU 52 and earlier we had iterator1.equals(iterator2) 361 // but in ICU 53 this fails because the iterators differ (String vs. CharacterIterator). 362 // doAssert((iterator1.equals(iterator2)), "The second iterator advance failed"); 363 doAssert(iterator1.getOffset() == iterator2.getOffset(), "The second iterator advance failed"); 364 doAssert((order1 == order2), "The order result should be the same"); 365 366 order3 = iterator3.next(); 367 368 doAssert((CollationElementIterator.primaryOrder(order1) == 369 CollationElementIterator.primaryOrder(order3)), "The primary orders should be the same"); 370 doAssert((CollationElementIterator.secondaryOrder(order1) == 371 CollationElementIterator.secondaryOrder(order3)), "The secondary orders should be the same"); 372 doAssert((CollationElementIterator.tertiaryOrder(order1) == 373 CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be the same"); 374 375 order1 = iterator1.next(); 376 order2 = iterator2.next(); 377 order3 = iterator3.next(); 378 379 doAssert((CollationElementIterator.primaryOrder(order1) == 380 CollationElementIterator.primaryOrder(order3)), "The primary orders should be identical"); 381 doAssert((CollationElementIterator.tertiaryOrder(order1) != 382 CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be different"); 383 384 order1 = iterator1.next(); 385 order3 = iterator3.next(); 386 387 // obsolete invalid test, removed 388 // doAssert((CollationElementIterator.secondaryOrder(order1) != 389 // CollationElementIterator.secondaryOrder(order3)), "The secondary orders should not be the same"); 390 doAssert((order1 != CollationElementIterator.NULLORDER), "Unexpected end of iterator reached"); 391 doAssert(!(iterator2.equals(iterator3)), "The iterators should be different"); 392 logln("testing CollationElementIterator ends..."); 393 } 394 395 /** 396 * This tests the hashCode method of a collator object. 397 */ 398 @Test TestHashCode()399 public void TestHashCode() { 400 logln("hashCode tests begin."); 401 Collator col1 = Collator.getInstance(Locale.ENGLISH); 402 403 Collator col2 = null; 404 Locale dk = new Locale("da", "DK", ""); 405 try { 406 col2 = Collator.getInstance(dk); 407 } catch (Exception e) { 408 errln("Danish collation creation failed."); 409 return; 410 } 411 412 Collator col3 = null; 413 try { 414 col3 = Collator.getInstance(Locale.ENGLISH); 415 } catch (Exception e) { 416 errln("2nd default collation creation failed."); 417 return; 418 } 419 420 logln("Collator.hashCode() testing ..."); 421 422 doAssert(col1.hashCode() != col2.hashCode(), "Hash test1 result incorrect" ); 423 doAssert(!(col1.hashCode() == col2.hashCode()), "Hash test2 result incorrect" ); 424 doAssert(col1.hashCode() == col3.hashCode(), "Hash result not equal" ); 425 426 logln("hashCode tests end."); 427 428 String test1 = "Abcda"; 429 String test2 = "abcda"; 430 431 CollationKey sortk1, sortk2, sortk3; 432 433 sortk1 = col3.getCollationKey(test1); 434 sortk2 = col3.getCollationKey(test2); 435 sortk3 = col3.getCollationKey(test2); 436 437 doAssert(sortk1.hashCode() != sortk2.hashCode(), "Hash test1 result incorrect"); 438 doAssert(sortk2.hashCode() == sortk3.hashCode(), "Hash result not equal" ); 439 } 440 441 /** 442 * This tests the properties of a collator object. 443 * - constructor 444 * - factory method getInstance 445 * - compare and getCollationKey 446 * - get/set decomposition mode and comparison level 447 */ 448 @Test TestProperty()449 public void TestProperty() { 450 /* 451 All the collations have the same version in an ICU 452 version. 453 ICU 2.0 currVersionArray = {0x18, 0xC0, 0x02, 0x02}; 454 ICU 2.1 currVersionArray = {0x19, 0x00, 0x03, 0x03}; 455 ICU 2.8 currVersionArray = {0x29, 0x80, 0x00, 0x04}; 456 */ 457 logln("The property tests begin : "); 458 logln("Test ctors : "); 459 Collator col = Collator.getInstance(Locale.ENGLISH); 460 461 logln("Test getVersion"); 462 // Check for a version greater than some value rather than equality 463 // so that we need not update the expected version each time. 464 VersionInfo expectedVersion = VersionInfo.getInstance(0x31, 0xC0, 0x00, 0x05); // from ICU 4.4/UCA 5.2 465 doAssert(col.getVersion().compareTo(expectedVersion) >= 0, "Expected minimum version "+expectedVersion.toString()+" got "+col.getVersion().toString()); 466 467 logln("Test getUCAVersion"); 468 // Assume that the UCD and UCA versions are the same, 469 // rather than hardcoding (and updating each time) a particular UCA version. 470 VersionInfo ucdVersion = UCharacter.getUnicodeVersion(); 471 VersionInfo ucaVersion = col.getUCAVersion(); 472 doAssert(ucaVersion.equals(ucdVersion), 473 "Expected UCA version "+ucdVersion.toString()+" got "+col.getUCAVersion().toString()); 474 475 doAssert((col.compare("ab", "abc") < 0), "ab < abc comparison failed"); 476 doAssert((col.compare("ab", "AB") < 0), "ab < AB comparison failed"); 477 doAssert((col.compare("blackbird", "black-bird") > 0), "black-bird > blackbird comparison failed"); 478 doAssert((col.compare("black bird", "black-bird") < 0), "black bird > black-bird comparison failed"); 479 doAssert((col.compare("Hello", "hello") > 0), "Hello > hello comparison failed"); 480 481 logln("Test ctors ends."); 482 483 logln("testing Collator.getStrength() method ..."); 484 doAssert((col.getStrength() == Collator.TERTIARY), "collation object has the wrong strength"); 485 doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); 486 487 logln("testing Collator.setStrength() method ..."); 488 col.setStrength(Collator.SECONDARY); 489 doAssert((col.getStrength() != Collator.TERTIARY), "collation object's strength is secondary difference"); 490 doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); 491 doAssert((col.getStrength() == Collator.SECONDARY), "collation object has the wrong strength"); 492 493 logln("testing Collator.setDecomposition() method ..."); 494 col.setDecomposition(Collator.NO_DECOMPOSITION); 495 doAssert((col.getDecomposition() != Collator.CANONICAL_DECOMPOSITION), "Decomposition mode != Collator.CANONICAL_DECOMPOSITION"); 496 doAssert((col.getDecomposition() == Collator.NO_DECOMPOSITION), "Decomposition mode = Collator.NO_DECOMPOSITION"); 497 498 499 RuleBasedCollator rcol = (RuleBasedCollator)Collator.getInstance(new Locale("da", "DK")); 500 doAssert(rcol.getRules().length() != 0, "da_DK rules does not have length 0"); 501 502 try { 503 col = Collator.getInstance(Locale.FRENCH); 504 } catch (Exception e) { 505 errln("Creating French collation failed."); 506 return; 507 } 508 509 col.setStrength(Collator.PRIMARY); 510 logln("testing Collator.getStrength() method again ..."); 511 doAssert((col.getStrength() != Collator.TERTIARY), "collation object has the wrong strength"); 512 doAssert((col.getStrength() == Collator.PRIMARY), "collation object's strength is not primary difference"); 513 514 logln("testing French Collator.setStrength() method ..."); 515 col.setStrength(Collator.TERTIARY); 516 doAssert((col.getStrength() == Collator.TERTIARY), "collation object's strength is not tertiary difference"); 517 doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); 518 doAssert((col.getStrength() != Collator.SECONDARY), "collation object's strength is secondary difference"); 519 520 } 521 522 @Test 523 public void TestJunkCollator(){ 524 logln("Create junk collation: "); 525 Locale abcd = new Locale("ab", "CD", ""); 526 527 Collator junk = Collator.getInstance(abcd); 528 Collator col = Collator.getInstance(); 529 530 531 String colrules = ((RuleBasedCollator)col).getRules(); 532 String junkrules = ((RuleBasedCollator)junk).getRules(); 533 doAssert(colrules == junkrules || colrules.equals(junkrules), 534 "The default collation should be returned."); 535 Collator frCol = null; 536 try { 537 frCol = Collator.getInstance(Locale.CANADA_FRENCH); 538 } catch (Exception e) { 539 errln("Creating fr_CA collator failed."); 540 return; 541 } 542 543 doAssert(!(frCol.equals(junk)), "The junk is the same as the fr_CA collator."); 544 logln("Collator property test ended."); 545 546 } 547 548 /** 549 * This tests the RuleBasedCollator 550 * - constructor/destructor 551 * - getRules 552 */ 553 @Test 554 public void TestRuleBasedColl() { 555 RuleBasedCollator col1 = null, col2 = null, col3 = null, col4 = null; 556 557 String ruleset1 = "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E"; 558 String ruleset2 = "&9 < a, A < b, B < c, C < d, D, e, E"; 559 String ruleset3 = "&"; 560 561 try { 562 col1 = new RuleBasedCollator(ruleset1); 563 } catch (Exception e) { 564 // only first error needs to be a warning since we exit function 565 warnln("RuleBased Collator creation failed."); 566 return; 567 } 568 569 try { 570 col2 = new RuleBasedCollator(ruleset2); 571 } catch (Exception e) { 572 errln("RuleBased Collator creation failed."); 573 return; 574 } 575 576 try { 577 // empty rules fail 578 col3 = new RuleBasedCollator(ruleset3); 579 errln("Failure: Empty rules for the collator should fail"); 580 return; 581 } catch (MissingResourceException e) { 582 warnln(e.getMessage()); 583 } catch (Exception e) { 584 logln("PASS: Empty rules for the collator failed as expected"); 585 } 586 587 Locale locale = new Locale("aa", "AA"); 588 try { 589 col3 = (RuleBasedCollator)Collator.getInstance(locale); 590 } catch (Exception e) { 591 errln("Fallback Collator creation failed.: %s"); 592 return; 593 } 594 595 try { 596 col3 = (RuleBasedCollator)Collator.getInstance(); 597 } catch (Exception e) { 598 errln("Default Collator creation failed.: %s"); 599 return; 600 } 601 602 String rule1 = col1.getRules(); 603 String rule2 = col2.getRules(); 604 String rule3 = col3.getRules(); 605 606 doAssert(!rule1.equals(rule2), "Default collator getRules failed"); 607 doAssert(!rule2.equals(rule3), "Default collator getRules failed"); 608 doAssert(!rule1.equals(rule3), "Default collator getRules failed"); 609 610 try { 611 col4 = new RuleBasedCollator(rule2); 612 } catch (Exception e) { 613 errln("RuleBased Collator creation failed."); 614 return; 615 } 616 617 String rule4 = col4.getRules(); 618 doAssert(rule2.equals(rule4), "Default collator getRules failed"); 619 // tests that modifier ! is always ignored 620 String exclamationrules = "!&a<b"; 621 // java does not allow ! to be the start of the rule 622 String thaistr = "\u0e40\u0e01\u0e2d"; 623 try { 624 RuleBasedCollator col5 = new RuleBasedCollator(exclamationrules); 625 RuleBasedCollator encol = (RuleBasedCollator) 626 Collator.getInstance(Locale.ENGLISH); 627 CollationElementIterator col5iter 628 = col5.getCollationElementIterator(thaistr); 629 CollationElementIterator encoliter 630 = encol.getCollationElementIterator( 631 thaistr); 632 while (true) { 633 // testing with en since thai has its own tailoring 634 int ce = col5iter.next(); 635 int ce2 = encoliter.next(); 636 if (ce2 != ce) { 637 errln("! modifier test failed"); 638 } 639 if (ce == CollationElementIterator.NULLORDER) { 640 break; 641 } 642 } 643 } catch (Exception e) { 644 errln("RuleBased Collator creation failed for ! modifier."); 645 return; 646 } 647 } 648 649 /** 650 * This tests the RuleBasedCollator 651 * - getRules 652 */ 653 @Test 654 public void TestRules() { 655 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(new Locale("","","")); //root 656 // logln("PASS: RuleBased Collator creation passed"); 657 658 659 String rules = coll.getRules(); 660 if (rules != null && rules.length() != 0) { 661 errln("Root tailored rules failed"); 662 } 663 } 664 665 @Test 666 public void TestSafeClone() { 667 String test1 = "abCda"; 668 String test2 = "abcda"; 669 670 // one default collator & two complex ones 671 RuleBasedCollator someCollators[] = { 672 (RuleBasedCollator)Collator.getInstance(Locale.ENGLISH), 673 (RuleBasedCollator)Collator.getInstance(Locale.KOREA), 674 (RuleBasedCollator)Collator.getInstance(Locale.JAPAN) 675 }; 676 RuleBasedCollator someClonedCollators[] = new RuleBasedCollator[3]; 677 678 // change orig & clone & make sure they are independent 679 680 for (int index = 0; index < someCollators.length; index ++) 681 { 682 try { 683 someClonedCollators[index] 684 = (RuleBasedCollator)someCollators[index].clone(); 685 } catch (CloneNotSupportedException e) { 686 errln("Error cloning collator"); 687 } 688 689 someClonedCollators[index].setStrength(Collator.TERTIARY); 690 someCollators[index].setStrength(Collator.PRIMARY); 691 someClonedCollators[index].setCaseLevel(false); 692 someCollators[index].setCaseLevel(false); 693 694 doAssert(someClonedCollators[index].compare(test1, test2) > 0, 695 "Result should be \"abCda\" >>> \"abcda\" "); 696 doAssert(someCollators[index].compare(test1, test2) == 0, 697 "Result should be \"abCda\" == \"abcda\" "); 698 } 699 } 700 701 @Test 702 public void TestGetTailoredSet() 703 { 704 logln("testing getTailoredSet..."); 705 String rules[] = { 706 "&a < \u212b", 707 "& S < \u0161 <<< \u0160", 708 }; 709 String data[][] = { 710 { "\u212b", "A\u030a", "\u00c5" }, 711 { "\u0161", "s\u030C", "\u0160", "S\u030C" } 712 }; 713 714 int i = 0, j = 0; 715 716 RuleBasedCollator coll; 717 UnicodeSet set; 718 719 for(i = 0; i < rules.length; i++) { 720 try { 721 logln("Instantiating a collator from "+rules[i]); 722 coll = new RuleBasedCollator(rules[i]); 723 set = coll.getTailoredSet(); 724 logln("Got set: "+set.toPattern(true)); 725 if(set.size() < data[i].length) { 726 errln("Tailored set size smaller ("+set.size()+") than expected ("+data[i].length+")"); 727 } 728 for(j = 0; j < data[i].length; j++) { 729 logln("Checking to see whether "+data[i][j]+" is in set"); 730 if(!set.contains(data[i][j])) { 731 errln("Tailored set doesn't contain "+data[i][j]+"... It should"); 732 } 733 } 734 } catch (Exception e) { 735 warnln("Couldn't open collator with rules "+ rules[i]); 736 } 737 } 738 } 739 740 /** 741 * Simple test to see if Collator is subclassable. 742 * Also test coverage of base class methods that are overridden by RuleBasedCollator. 743 */ 744 @Test 745 public void TestSubClass() 746 { 747 class TestCollator extends Collator 748 { 749 @Override 750 public boolean equals(Object that) { 751 return this == that; 752 } 753 754 @Override 755 public int hashCode() { 756 return 0; 757 } 758 759 @Override 760 public int compare(String source, String target) { 761 return source.compareTo(target); 762 } 763 764 @Override 765 public CollationKey getCollationKey(String source) 766 { return new CollationKey(source, 767 getRawCollationKey(source, new RawCollationKey())); 768 } 769 770 @Override 771 public RawCollationKey getRawCollationKey(String source, 772 RawCollationKey key) 773 { 774 byte temp1[] = source.getBytes(); 775 byte temp2[] = new byte[temp1.length + 1]; 776 System.arraycopy(temp1, 0, temp2, 0, temp1.length); 777 temp2[temp1.length] = 0; 778 if (key == null) { 779 key = new RawCollationKey(); 780 } 781 key.bytes = temp2; 782 key.size = temp2.length; 783 return key; 784 } 785 786 @Override 787 public void setVariableTop(int ce) 788 { 789 if (isFrozen()) { 790 throw new UnsupportedOperationException("Attempt to modify frozen object"); 791 } 792 } 793 794 @Override 795 public int setVariableTop(String str) 796 { 797 if (isFrozen()) { 798 throw new UnsupportedOperationException("Attempt to modify frozen object"); 799 } 800 801 return 0; 802 } 803 804 @Override 805 public int getVariableTop() 806 { 807 return 0; 808 } 809 @Override 810 public VersionInfo getVersion() 811 { 812 return VersionInfo.getInstance(0); 813 } 814 @Override 815 public VersionInfo getUCAVersion() 816 { 817 return VersionInfo.getInstance(0); 818 } 819 } 820 821 Collator col1 = new TestCollator(); 822 Collator col2 = new TestCollator(); 823 if (col1.equals(col2)) { 824 errln("2 different instance of TestCollator should fail"); 825 } 826 if (col1.hashCode() != col2.hashCode()) { 827 errln("Every TestCollator has the same hashcode"); 828 } 829 String abc = "abc"; 830 String bcd = "bcd"; 831 if (col1.compare(abc, bcd) != abc.compareTo(bcd)) { 832 errln("TestCollator compare should be the same as the default " + 833 "string comparison"); 834 } 835 CollationKey key = col1.getCollationKey(abc); 836 byte temp1[] = abc.getBytes(); 837 byte temp2[] = new byte[temp1.length + 1]; 838 System.arraycopy(temp1, 0, temp2, 0, temp1.length); 839 temp2[temp1.length] = 0; 840 if (!java.util.Arrays.equals(key.toByteArray(), temp2) 841 || !key.getSourceString().equals(abc)) { 842 errln("TestCollator collationkey API is returning wrong values"); 843 } 844 UnicodeSet set = col1.getTailoredSet(); 845 if (!set.equals(new UnicodeSet(0, 0x10FFFF))) { 846 errln("Error getting default tailored set"); 847 } 848 849 // Base class code coverage. 850 // Most of these methods are dummies; 851 // they are overridden by any subclass that supports their features. 852 853 assertEquals("compare(strings as Object)", 0, 854 col1.compare(new StringBuilder("abc"), new StringBuffer("abc"))); 855 856 col1.setStrength(Collator.SECONDARY); 857 assertNotEquals("getStrength()", Collator.PRIMARY, col1.getStrength()); 858 859 // setStrength2() is @internal and returns this. 860 // The base class getStrength() always returns the same value, 861 // since the base class does not have a field to store the strength. 862 assertNotEquals("setStrength2().getStrength()", Collator.PRIMARY, 863 col1.setStrength2(Collator.IDENTICAL).getStrength()); 864 865 // (base class).setDecomposition() may or may not be implemented. 866 try { 867 col1.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 868 } catch (UnsupportedOperationException expected) { 869 } 870 assertNotEquals("getDecomposition()", -1, col1.getDecomposition()); // don't care about the value 871 872 // (base class).setMaxVariable() may or may not be implemented. 873 try { 874 col1.setMaxVariable(Collator.ReorderCodes.CURRENCY); 875 } catch (UnsupportedOperationException expected) { 876 } 877 assertNotEquals("getMaxVariable()", -1, col1.getMaxVariable()); // don't care about the value 878 879 // (base class).setReorderCodes() may or may not be implemented. 880 try { 881 col1.setReorderCodes(0, 1, 2); 882 } catch (UnsupportedOperationException expected) { 883 } 884 try { 885 col1.getReorderCodes(); 886 } catch (UnsupportedOperationException expected) { 887 } 888 889 assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN).isEmpty()); 890 assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN, Locale.ITALIAN).isEmpty()); 891 892 assertNotEquals("getLocale()", ULocale.GERMAN, col1.getLocale(ULocale.ACTUAL_LOCALE)); 893 894 // Cover Collator.setLocale() which is only package-visible. 895 Object token = Collator.registerInstance(new TestCollator(), new ULocale("de-Japn-419")); 896 Collator.unregister(token); 897 898 // Freezable default implementations. freeze() may or may not be implemented. 899 assertFalse("not yet frozen", col2.isFrozen()); 900 try { 901 col2.freeze(); 902 assertTrue("now frozen", col2.isFrozen()); 903 } catch (UnsupportedOperationException expected) { 904 } 905 try { 906 col2.setStrength(Collator.PRIMARY); 907 if (col2.isFrozen()) { 908 fail("(frozen Collator).setStrength() should throw an exception"); 909 } 910 } catch (UnsupportedOperationException expected) { 911 } 912 try { 913 Collator col3 = col2.cloneAsThawed(); 914 assertFalse("!cloneAsThawed().isFrozen()", col3.isFrozen()); 915 } catch (UnsupportedOperationException expected) { 916 } 917 } 918 919 /** 920 * Simple test the collator setter and getters. 921 * Similar to C++ apicoll.cpp TestAttribute(). 922 */ 923 @Test 924 public void TestSetGet() 925 { 926 RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(); 927 int decomp = collator.getDecomposition(); 928 int strength = collator.getStrength(); 929 boolean alt = collator.isAlternateHandlingShifted(); 930 boolean caselevel = collator.isCaseLevel(); 931 boolean french = collator.isFrenchCollation(); 932 boolean hquart = collator.isHiraganaQuaternary(); 933 boolean lowercase = collator.isLowerCaseFirst(); 934 boolean uppercase = collator.isUpperCaseFirst(); 935 936 collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 937 if (collator.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) { 938 errln("Setting decomposition failed"); 939 } 940 collator.setStrength(Collator.QUATERNARY); 941 if (collator.getStrength() != Collator.QUATERNARY) { 942 errln("Setting strength failed"); 943 } 944 collator.setAlternateHandlingShifted(!alt); 945 if (collator.isAlternateHandlingShifted() == alt) { 946 errln("Setting alternate handling failed"); 947 } 948 collator.setCaseLevel(!caselevel); 949 if (collator.isCaseLevel() == caselevel) { 950 errln("Setting case level failed"); 951 } 952 collator.setFrenchCollation(!french); 953 if (collator.isFrenchCollation() == french) { 954 errln("Setting french collation failed"); 955 } 956 collator.setHiraganaQuaternary(!hquart); 957 if (collator.isHiraganaQuaternary() != hquart) { 958 errln("Setting hiragana quartenary worked but should be a no-op since ICU 50"); 959 } 960 collator.setLowerCaseFirst(!lowercase); 961 if (collator.isLowerCaseFirst() == lowercase) { 962 errln("Setting lower case first failed"); 963 } 964 collator.setUpperCaseFirst(!uppercase); 965 if (collator.isUpperCaseFirst() == uppercase) { 966 errln("Setting upper case first failed"); 967 } 968 collator.setDecompositionDefault(); 969 if (collator.getDecomposition() != decomp) { 970 errln("Setting decomposition default failed"); 971 } 972 collator.setStrengthDefault(); 973 if (collator.getStrength() != strength) { 974 errln("Setting strength default failed"); 975 } 976 collator.setAlternateHandlingDefault(); 977 if (collator.isAlternateHandlingShifted() != alt) { 978 errln("Setting alternate handling default failed"); 979 } 980 collator.setCaseLevelDefault(); 981 if (collator.isCaseLevel() != caselevel) { 982 errln("Setting case level default failed"); 983 } 984 collator.setFrenchCollationDefault(); 985 if (collator.isFrenchCollation() != french) { 986 errln("Setting french handling default failed"); 987 } 988 collator.setHiraganaQuaternaryDefault(); 989 if (collator.isHiraganaQuaternary() != hquart) { 990 errln("Setting Hiragana Quartenary default failed"); 991 } 992 collator.setCaseFirstDefault(); 993 if (collator.isLowerCaseFirst() != lowercase 994 || collator.isUpperCaseFirst() != uppercase) { 995 errln("Setting case first handling default failed"); 996 } 997 } 998 999 @Test 1000 public void TestVariableTopSetting() { 1001 // Use the root collator, not the default collator. 1002 // This test fails with en_US_POSIX which tailors the dollar sign after 'A'. 1003 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(ULocale.ROOT); 1004 1005 int oldVarTop = coll.getVariableTop(); 1006 1007 // ICU 53+: The character must be in a supported reordering group, 1008 // and the variable top is pinned to the end of that group. 1009 try { 1010 coll.setVariableTop("A"); 1011 errln("setVariableTop(letter) did not detect illegal argument"); 1012 } catch(IllegalArgumentException expected) { 1013 } 1014 1015 // dollar sign (currency symbol) 1016 int newVarTop = coll.setVariableTop("$"); 1017 1018 if(newVarTop != coll.getVariableTop()) { 1019 errln("setVariableTop(dollar sign) != following getVariableTop()"); 1020 } 1021 1022 String dollar = "$"; 1023 String euro = "\u20AC"; 1024 int newVarTop2 = coll.setVariableTop(euro); 1025 assertEquals("setVariableTop(Euro sign) == following getVariableTop()", 1026 newVarTop2, coll.getVariableTop()); 1027 assertEquals("setVariableTop(Euro sign) == setVariableTop(dollar sign) (should pin to top of currency group)", 1028 newVarTop2, newVarTop); 1029 1030 coll.setAlternateHandlingShifted(true); 1031 assertEquals("empty==dollar", 0, coll.compare("", dollar)); // UCOL_EQUAL 1032 assertEquals("empty==euro", 0, coll.compare("", euro)); // UCOL_EQUAL 1033 assertEquals("dollar<zero", -1, coll.compare(dollar, "0")); // UCOL_LESS 1034 1035 coll.setVariableTop(oldVarTop); 1036 1037 int newerVarTop = coll.setVariableTop("$"); 1038 1039 if(newVarTop != newerVarTop) { 1040 errln("Didn't set vartop properly from String!\n"); 1041 } 1042 } 1043 1044 @Test 1045 public void TestMaxVariable() { 1046 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(ULocale.ROOT); 1047 1048 try { 1049 coll.setMaxVariable(Collator.ReorderCodes.OTHERS); 1050 errln("setMaxVariable(others) did not detect illegal argument"); 1051 } catch(IllegalArgumentException expected) { 1052 } 1053 1054 coll.setMaxVariable(Collator.ReorderCodes.CURRENCY); 1055 1056 if(Collator.ReorderCodes.CURRENCY != coll.getMaxVariable()) { 1057 errln("setMaxVariable(currency) != following getMaxVariable()"); 1058 } 1059 1060 coll.setAlternateHandlingShifted(true); 1061 assertEquals("empty==dollar", 0, coll.compare("", "$")); // UCOL_EQUAL 1062 assertEquals("empty==euro", 0, coll.compare("", "\u20AC")); // UCOL_EQUAL 1063 assertEquals("dollar<zero", -1, coll.compare("$", "0")); // UCOL_LESS 1064 } 1065 1066 @Test 1067 public void TestGetLocale() { 1068 String rules = "&a<x<y<z"; 1069 1070 Collator coll = Collator.getInstance(new ULocale("root")); 1071 ULocale locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1072 if(!locale.equals(ULocale.ROOT)) { 1073 errln("Collator.getInstance(\"root\").getLocale(actual) != ULocale.ROOT; " + 1074 "getLocale().getName() = \"" + locale.getName() + "\""); 1075 } 1076 1077 coll = Collator.getInstance(new ULocale("")); 1078 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1079 if(!locale.equals(ULocale.ROOT)) { 1080 errln("Collator.getInstance(\"\").getLocale(actual) != ULocale.ROOT; " + 1081 "getLocale().getName() = \"" + locale.getName() + "\""); 1082 } 1083 1084 int i = 0; 1085 1086 String[][] testStruct = { 1087 // requestedLocale, validLocale, actualLocale 1088 // Note: ULocale.ROOT.getName() == "" not "root". 1089 { "de_DE", "de", "" }, 1090 { "sr_RS", "sr_Cyrl_RS", "sr" }, 1091 { "en_US_CALIFORNIA", "en_US", "" }, 1092 { "fr_FR_NONEXISTANT", "fr", "" }, 1093 // pinyin is the default, therefore suppressed. 1094 { "zh_CN", "zh_Hans_CN", "zh" }, 1095 // zh_Hant has default=stroke but the data is in zh. 1096 { "zh_TW", "zh_Hant_TW", "zh@collation=stroke" }, 1097 { "zh_TW@collation=pinyin", "zh_Hant_TW@collation=pinyin", "zh" }, 1098 { "zh_CN@collation=stroke", "zh_Hans_CN@collation=stroke", "zh@collation=stroke" }, 1099 // yue/yue_Hant aliased to zh_Hant, yue_Hans aliased to zh_Hans. 1100 { "yue", "zh_Hant", "zh@collation=stroke" }, 1101 { "yue_HK", "zh_Hant", "zh@collation=stroke" }, 1102 { "yue_Hant", "zh_Hant", "zh@collation=stroke" }, 1103 { "yue_Hant_HK", "zh_Hant", "zh@collation=stroke" }, 1104 { "yue@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, 1105 { "yue_HK@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, 1106 { "yue_CN", "zh_Hans", "zh" }, 1107 { "yue_Hans", "zh_Hans", "zh" }, 1108 { "yue_Hans_CN", "zh_Hans", "zh" }, 1109 { "yue_Hans@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" }, 1110 { "yue_CN@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" } 1111 }; 1112 1113 /* test opening collators for different locales */ 1114 for(i = 0; i<testStruct.length; i++) { 1115 String requestedLocale = testStruct[i][0]; 1116 String validLocale = testStruct[i][1]; 1117 String actualLocale = testStruct[i][2]; 1118 try { 1119 coll = Collator.getInstance(new ULocale(requestedLocale)); 1120 } catch(Exception e) { 1121 errln(String.format("Failed to open collator for %s with %s", requestedLocale, e)); 1122 continue; 1123 } 1124 // Note: C++ getLocale() recognizes ULOC_REQUESTED_LOCALE 1125 // which does not exist in Java. 1126 locale = coll.getLocale(ULocale.VALID_LOCALE); 1127 if(!locale.equals(new ULocale(validLocale))) { 1128 errln(String.format("[Coll %s]: Error in valid locale, expected %s, got %s", 1129 requestedLocale, validLocale, locale.getName())); 1130 } 1131 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1132 if(!locale.equals(new ULocale(actualLocale))) { 1133 errln(String.format("[Coll %s]: Error in actual locale, expected %s, got %s", 1134 requestedLocale, actualLocale, locale.getName())); 1135 } 1136 // If we open a collator for the actual locale, we should get an equivalent one again. 1137 Collator coll2; 1138 try { 1139 coll2 = Collator.getInstance(locale); 1140 } catch(Exception e) { 1141 errln(String.format("Failed to open collator for actual locale \"%s\" with %s", 1142 locale.getName(), e)); 1143 continue; 1144 } 1145 ULocale actual2 = coll2.getLocale(ULocale.ACTUAL_LOCALE); 1146 if(!actual2.equals(locale)) { 1147 errln(String.format("[Coll actual \"%s\"]: Error in actual locale, got different one: \"%s\"", 1148 locale.getName(), actual2.getName())); 1149 } 1150 if(!coll2.equals(coll)) { 1151 errln(String.format("[Coll actual \"%s\"]: Got different collator than before", 1152 locale.getName())); 1153 } 1154 } 1155 1156 /* completely non-existent locale for collator should get a root collator */ 1157 { 1158 try { 1159 coll = Collator.getInstance(new ULocale("blahaha")); 1160 } catch(Exception e) { 1161 errln("Failed to open collator with " + e); 1162 return; 1163 } 1164 ULocale valid = coll.getLocale(ULocale.VALID_LOCALE); 1165 String name = valid.getName(); 1166 if(name.length() != 0 && !name.equals("root")) { 1167 errln("Valid locale for nonexisting locale collator is \"" + name + "\" not root"); 1168 } 1169 ULocale actual = coll.getLocale(ULocale.ACTUAL_LOCALE); 1170 name = actual.getName(); 1171 if(name.length() != 0 && !name.equals("root")) { 1172 errln("Actual locale for nonexisting locale collator is \"" + name + "\" not root"); 1173 } 1174 } 1175 1176 /* collator instantiated from rules should have all locales null */ 1177 try { 1178 coll = new RuleBasedCollator(rules); 1179 } catch (Exception e) { 1180 errln("RuleBasedCollator(" + rules + ") failed: " + e); 1181 return; 1182 } 1183 locale = coll.getLocale(ULocale.VALID_LOCALE); 1184 if(locale != null) { 1185 errln(String.format("For collator instantiated from rules, valid locale %s is not bogus", 1186 locale.getName())); 1187 } 1188 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1189 if(locale != null) { 1190 errln(String.format("For collator instantiated from rules, actual locale %s is not bogus", 1191 locale.getName())); 1192 } 1193 } 1194 1195 @Test 1196 public void TestBounds() 1197 { 1198 Collator coll = Collator.getInstance(new Locale("sh", "")); 1199 1200 String test[] = { "John Smith", "JOHN SMITH", 1201 "john SMITH", "j\u00F6hn sm\u00EFth", 1202 "J\u00F6hn Sm\u00EFth", "J\u00D6HN SM\u00CFTH", 1203 "john smithsonian", "John Smithsonian", 1204 }; 1205 1206 String testStr[] = { 1207 "\u010CAKI MIHALJ", 1208 "\u010CAKI MIHALJ", 1209 "\u010CAKI PIRO\u0160KA", 1210 "\u010CABAI ANDRIJA", 1211 "\u010CABAI LAJO\u0160", 1212 "\u010CABAI MARIJA", 1213 "\u010CABAI STEVAN", 1214 "\u010CABAI STEVAN", 1215 "\u010CABARKAPA BRANKO", 1216 "\u010CABARKAPA MILENKO", 1217 "\u010CABARKAPA MIROSLAV", 1218 "\u010CABARKAPA SIMO", 1219 "\u010CABARKAPA STANKO", 1220 "\u010CABARKAPA TAMARA", 1221 "\u010CABARKAPA TOMA\u0160", 1222 "\u010CABDARI\u0106 NIKOLA", 1223 "\u010CABDARI\u0106 ZORICA", 1224 "\u010CABI NANDOR", 1225 "\u010CABOVI\u0106 MILAN", 1226 "\u010CABRADI AGNEZIJA", 1227 "\u010CABRADI IVAN", 1228 "\u010CABRADI JELENA", 1229 "\u010CABRADI LJUBICA", 1230 "\u010CABRADI STEVAN", 1231 "\u010CABRDA MARTIN", 1232 "\u010CABRILO BOGDAN", 1233 "\u010CABRILO BRANISLAV", 1234 "\u010CABRILO LAZAR", 1235 "\u010CABRILO LJUBICA", 1236 "\u010CABRILO SPASOJA", 1237 "\u010CADE\u0160 ZDENKA", 1238 "\u010CADESKI BLAGOJE", 1239 "\u010CADOVSKI VLADIMIR", 1240 "\u010CAGLJEVI\u0106 TOMA", 1241 "\u010CAGOROVI\u0106 VLADIMIR", 1242 "\u010CAJA VANKA", 1243 "\u010CAJI\u0106 BOGOLJUB", 1244 "\u010CAJI\u0106 BORISLAV", 1245 "\u010CAJI\u0106 RADOSLAV", 1246 "\u010CAK\u0160IRAN MILADIN", 1247 "\u010CAKAN EUGEN", 1248 "\u010CAKAN EVGENIJE", 1249 "\u010CAKAN IVAN", 1250 "\u010CAKAN JULIJAN", 1251 "\u010CAKAN MIHAJLO", 1252 "\u010CAKAN STEVAN", 1253 "\u010CAKAN VLADIMIR", 1254 "\u010CAKAN VLADIMIR", 1255 "\u010CAKAN VLADIMIR", 1256 "\u010CAKARA ANA", 1257 "\u010CAKAREVI\u0106 MOMIR", 1258 "\u010CAKAREVI\u0106 NEDELJKO", 1259 "\u010CAKI \u0160ANDOR", 1260 "\u010CAKI AMALIJA", 1261 "\u010CAKI ANDRA\u0160", 1262 "\u010CAKI LADISLAV", 1263 "\u010CAKI LAJO\u0160", 1264 "\u010CAKI LASLO" }; 1265 1266 CollationKey testKey[] = new CollationKey[testStr.length]; 1267 for (int i = 0; i < testStr.length; i ++) { 1268 testKey[i] = coll.getCollationKey(testStr[i]); 1269 } 1270 1271 Arrays.sort(testKey); 1272 for(int i = 0; i < testKey.length - 1; i ++) { 1273 CollationKey lower 1274 = testKey[i].getBound(CollationKey.BoundMode.LOWER, 1275 Collator.SECONDARY); 1276 for (int j = i + 1; j < testKey.length; j ++) { 1277 CollationKey upper 1278 = testKey[j].getBound(CollationKey.BoundMode.UPPER, 1279 Collator.SECONDARY); 1280 for (int k = i; k <= j; k ++) { 1281 if (lower.compareTo(testKey[k]) > 0) { 1282 errln("Problem with lower bound at i = " + i + " j = " 1283 + j + " k = " + k); 1284 } 1285 if (upper.compareTo(testKey[k]) <= 0) { 1286 errln("Problem with upper bound at i = " + i + " j = " 1287 + j + " k = " + k); 1288 } 1289 } 1290 } 1291 } 1292 1293 for (int i = 0; i < test.length; i ++) 1294 { 1295 CollationKey key = coll.getCollationKey(test[i]); 1296 CollationKey lower = key.getBound(CollationKey.BoundMode.LOWER, 1297 Collator.SECONDARY); 1298 CollationKey upper = key.getBound(CollationKey.BoundMode.UPPER_LONG, 1299 Collator.SECONDARY); 1300 for (int j = i + 1; j < test.length; j ++) { 1301 key = coll.getCollationKey(test[j]); 1302 if (lower.compareTo(key) > 0) { 1303 errln("Problem with lower bound i = " + i + " j = " + j); 1304 } 1305 if (upper.compareTo(key) <= 0) { 1306 errln("Problem with upper bound i = " + i + " j = " + j); 1307 } 1308 } 1309 } 1310 } 1311 1312 @Test 1313 public final void TestGetAll() { 1314 Locale[] list = Collator.getAvailableLocales(); 1315 int errorCount = 0; 1316 for (int i = 0; i < list.length; ++i) { 1317 log("Locale name: "); 1318 log(list[i].toString()); 1319 log(" , the display name is : "); 1320 logln(list[i].getDisplayName()); 1321 try{ 1322 logln(" ...... Or display as: " + Collator.getDisplayName(list[i])); 1323 logln(" ...... and display in Chinese: " + 1324 Collator.getDisplayName(list[i],Locale.CHINA)); 1325 }catch(MissingResourceException ex){ 1326 errorCount++; 1327 logln("could not get displayName for " + list[i]); 1328 } 1329 } 1330 if(errorCount>0){ 1331 warnln("Could not load the locale data."); 1332 } 1333 } 1334 1335 private boolean 1336 doSetsTest(UnicodeSet ref, UnicodeSet set, String inSet, String outSet) { 1337 boolean ok = true; 1338 set.clear(); 1339 set.applyPattern(inSet); 1340 1341 if(!ref.containsAll(set)) { 1342 err("Some stuff from "+inSet+" is not present in the set.\nMissing:"+ 1343 set.removeAll(ref).toPattern(true)+"\n"); 1344 ok = false; 1345 } 1346 1347 set.clear(); 1348 set.applyPattern(outSet); 1349 if(!ref.containsNone(set)) { 1350 err("Some stuff from "+outSet+" is present in the set.\nUnexpected:"+ 1351 set.retainAll(ref).toPattern(true)+"\n"); 1352 ok = false; 1353 } 1354 return ok; 1355 } 1356 1357 // capitst.c/TestGetContractionsAndUnsafes() 1358 @Test 1359 public void TestGetContractions() throws Exception { 1360 /* static struct { 1361 const char* locale; 1362 const char* inConts; 1363 const char* outConts; 1364 const char* inExp; 1365 const char* outExp; 1366 const char* unsafeCodeUnits; 1367 const char* safeCodeUnits; 1368 } 1369 */ 1370 String tests[][] = { 1371 { "ru", 1372 "[{\u0418\u0306}{\u0438\u0306}]", 1373 "[\u0439\u0457]", 1374 "[\u00e6]", 1375 "[ae]", 1376 "[\u0418\u0438]", 1377 "[aAbBxv]" 1378 }, 1379 { "uk", 1380 "[{\u0406\u0308}{\u0456\u0308}{\u0418\u0306}{\u0438\u0306}]", 1381 "[\u0407\u0419\u0439\u0457]", 1382 "[\u00e6]", 1383 "[ae]", 1384 "[\u0406\u0456\u0418\u0438]", 1385 "[aAbBxv]" 1386 }, 1387 { "sh", 1388 "[{C\u0301}{C\u030C}{C\u0341}{DZ\u030C}{Dz\u030C}{D\u017D}{D\u017E}{lj}{nj}]", 1389 "[{\u309d\u3099}{\u30fd\u3099}]", 1390 "[\u00e6]", 1391 "[a]", 1392 "[nlcdzNLCDZ]", 1393 "[jabv]" 1394 }, 1395 { "ja", 1396 /* 1397 * The "collv2" builder omits mappings if the collator maps their 1398 * character sequences to the same CEs. 1399 * For example, it omits Japanese contractions for NFD forms 1400 * of the voiced iteration mark (U+309E = U+309D + U+3099), such as 1401 * {\u3053\u3099\u309D\u3099}{\u3053\u309D\u3099} 1402 * {\u30B3\u3099\u30FD\u3099}{\u30B3\u30FD\u3099}. 1403 * It does add mappings for the precomposed forms. 1404 */ 1405 "[{\u3053\u3099\u309D}{\u3053\u3099\u309E}{\u3053\u3099\u30FC}" + 1406 "{\u3053\u309D}{\u3053\u309E}{\u3053\u30FC}" + 1407 "{\u30B3\u3099\u30FC}{\u30B3\u3099\u30FD}{\u30B3\u3099\u30FE}" + 1408 "{\u30B3\u30FC}{\u30B3\u30FD}{\u30B3\u30FE}]", 1409 "[{\u30FD\u3099}{\u309D\u3099}{\u3053\u3099}{\u30B3\u3099}{lj}{nj}]", 1410 "[\u30FE\u00e6]", 1411 "[a]", 1412 "[\u3099]", 1413 "[]" 1414 } 1415 }; 1416 1417 RuleBasedCollator coll = null; 1418 int i = 0; 1419 UnicodeSet conts = new UnicodeSet(); 1420 UnicodeSet exp = new UnicodeSet(); 1421 UnicodeSet set = new UnicodeSet(); 1422 1423 for(i = 0; i < tests.length; i++) { 1424 logln("Testing locale: "+ tests[i][0]); 1425 coll = (RuleBasedCollator)Collator.getInstance(new ULocale(tests[i][0])); 1426 coll.getContractionsAndExpansions(conts, exp, true); 1427 boolean ok = true; 1428 logln("Contractions "+conts.size()+":\n"+conts.toPattern(true)); 1429 ok &= doSetsTest(conts, set, tests[i][1], tests[i][2]); 1430 logln("Expansions "+exp.size()+":\n"+exp.toPattern(true)); 1431 ok &= doSetsTest(exp, set, tests[i][3], tests[i][4]); 1432 if(!ok) { 1433 // In case of failure, log the rule string for better diagnostics. 1434 String rules = coll.getRules(false); 1435 logln("Collation rules (getLocale()="+ 1436 coll.getLocale(ULocale.ACTUAL_LOCALE).toString()+"): "+ 1437 Utility.escape(rules)); 1438 } 1439 1440 // No unsafe set in ICU4J 1441 //noConts = ucol_getUnsafeSet(coll, conts, &status); 1442 //doSetsTest(conts, set, tests[i][5], tests[i][6]); 1443 //log_verbose("Unsafes "+conts.size()+":\n"+conts.toPattern(true)+"\n"); 1444 } 1445 } 1446 private static final String bigone = "One"; 1447 private static final String littleone = "one"; 1448 1449 @Test 1450 public void TestClone() { 1451 logln("\ninit c0"); 1452 RuleBasedCollator c0 = (RuleBasedCollator)Collator.getInstance(); 1453 c0.setStrength(Collator.TERTIARY); 1454 dump("c0", c0); 1455 1456 logln("\ninit c1"); 1457 RuleBasedCollator c1 = (RuleBasedCollator)Collator.getInstance(); 1458 c1.setStrength(Collator.TERTIARY); 1459 c1.setUpperCaseFirst(!c1.isUpperCaseFirst()); 1460 dump("c0", c0); 1461 dump("c1", c1); 1462 try{ 1463 logln("\ninit c2"); 1464 RuleBasedCollator c2 = (RuleBasedCollator)c1.clone(); 1465 c2.setUpperCaseFirst(!c2.isUpperCaseFirst()); 1466 dump("c0", c0); 1467 dump("c1", c1); 1468 dump("c2", c2); 1469 if(c1.equals(c2)){ 1470 errln("The cloned objects refer to same data"); 1471 } 1472 }catch(CloneNotSupportedException ex){ 1473 errln("Could not clone the collator"); 1474 } 1475 } 1476 1477 private void dump(String msg, RuleBasedCollator c) { 1478 logln(msg + " " + c.compare(bigone, littleone) + 1479 " s: " + c.getStrength() + 1480 " u: " + c.isUpperCaseFirst()); 1481 } 1482 1483 @Test 1484 public void TestIterNumeric() throws Exception { // misnomer for Java, but parallel with C++ test 1485 // Regression test for ticket #9915. 1486 // The collation code sometimes masked the continuation marker away 1487 // but later tested the result for isContinuation(). 1488 // This test case failed because the third bytes of the computed numeric-collation primaries 1489 // were permutated with the script reordering table. 1490 // It should have been possible to reproduce this with the root collator 1491 // and characters with appropriate 3-byte primary weights. 1492 // The effectiveness of this test depends completely on the collation elements 1493 // and on the implementation code. 1494 RuleBasedCollator coll = new RuleBasedCollator("[reorder Hang Hani]"); 1495 coll.setNumericCollation(true); 1496 int result = coll.compare("40", "72"); 1497 assertTrue("40<72", result < 0); 1498 } 1499 1500 /* 1501 * Tests the method public void setStrength(int newStrength) 1502 */ 1503 @Test 1504 public void TestSetStrength() { 1505 // Tests when if ((newStrength != PRIMARY) && ... ) is true 1506 int[] cases = { -1, 4, 5 }; 1507 for (int i = 0; i < cases.length; i++) { 1508 try { 1509 // Assuming -1 is not one of the values 1510 Collator c = Collator.getInstance(); 1511 c.setStrength(cases[i]); 1512 errln("Collator.setStrength(int) is suppose to return " 1513 + "an exception for an invalid newStrength value of " + cases[i]); 1514 } catch (Exception e) { 1515 } 1516 } 1517 } 1518 1519 /* 1520 * Tests the method public void setDecomposition(int decomposition) 1521 */ 1522 @Test 1523 public void TestSetDecomposition() { 1524 // Tests when if ((decomposition != NO_DECOMPOSITION) && ...) is true 1525 int[] cases = { 0, 1, 14, 15, 18, 19 }; 1526 for (int i = 0; i < cases.length; i++) { 1527 try { 1528 // Assuming -1 is not one of the values 1529 Collator c = Collator.getInstance(); 1530 c.setDecomposition(cases[i]); 1531 errln("Collator.setDecomposition(int) is suppose to return " 1532 + "an exception for an invalid decomposition value of " + cases[i]); 1533 } catch (Exception e) { 1534 } 1535 } 1536 } 1537 1538 /* 1539 * Tests the class CollatorFactory 1540 */ 1541 @Test 1542 public void TestCreateCollator() { 1543 // The following class override public Collator createCollator(Locale loc) 1544 class TestCreateCollator extends CollatorFactory { 1545 @Override 1546 public Set<String> getSupportedLocaleIDs() { 1547 return new HashSet<String>(); 1548 } 1549 1550 public TestCreateCollator() { 1551 super(); 1552 } 1553 1554 @Override 1555 public Collator createCollator(ULocale c) { 1556 return null; 1557 } 1558 } 1559 // The following class override public Collator createCollator(ULocale loc) 1560 class TestCreateCollator1 extends CollatorFactory { 1561 @Override 1562 public Set<String> getSupportedLocaleIDs() { 1563 return new HashSet<String>(); 1564 } 1565 1566 public TestCreateCollator1() { 1567 super(); 1568 } 1569 1570 @Override 1571 public Collator createCollator(Locale c) { 1572 return null; 1573 } 1574 @Override 1575 public boolean visible(){ 1576 return false; 1577 } 1578 } 1579 1580 /* 1581 * Tests the method public Collator createCollator(Locale loc) using TestCreateCollator1 class 1582 */ 1583 try { 1584 TestCreateCollator tcc = new TestCreateCollator(); 1585 tcc.createCollator(new Locale("en_US")); 1586 } catch (Exception e) { 1587 errln("Collator.createCollator(Locale) was not suppose to " + "return an exception."); 1588 } 1589 1590 /* 1591 * Tests the method public Collator createCollator(ULocale loc) using TestCreateCollator1 class 1592 */ 1593 try { 1594 TestCreateCollator1 tcc = new TestCreateCollator1(); 1595 tcc.createCollator(new ULocale("en_US")); 1596 } catch (Exception e) { 1597 errln("Collator.createCollator(ULocale) was not suppose to " + "return an exception."); 1598 } 1599 1600 /* 1601 * Tests the method public String getDisplayName(Locale objectLocale, Locale displayLocale) using TestCreateCollator1 class 1602 */ 1603 try { 1604 TestCreateCollator tcc = new TestCreateCollator(); 1605 tcc.getDisplayName(new Locale("en_US"), new Locale("jp_JP")); 1606 } catch (Exception e) { 1607 errln("Collator.getDisplayName(Locale,Locale) was not suppose to return an exception."); 1608 } 1609 1610 /* 1611 * Tests the method public String getDisplayName(ULocale objectLocale, ULocale displayLocale) using TestCreateCollator1 class 1612 */ 1613 try { 1614 TestCreateCollator1 tcc = new TestCreateCollator1(); 1615 tcc.getDisplayName(new ULocale("en_US"), new ULocale("jp_JP")); 1616 } catch (Exception e) { 1617 errln("Collator.getDisplayName(ULocale,ULocale) was not suppose to return an exception."); 1618 } 1619 } 1620 /* Tests the method 1621 * public static final String[] getKeywordValues(String keyword) 1622 */ 1623 @SuppressWarnings("static-access") 1624 @Test 1625 public void TestGetKeywordValues(){ 1626 // Tests when "if (!keyword.equals(KEYWORDS[0]))" is true 1627 String[] cases = {"","dummy"}; 1628 for(int i=0; i<cases.length; i++){ 1629 try{ 1630 Collator c = Collator.getInstance(); 1631 @SuppressWarnings("unused") 1632 String[] s = c.getKeywordValues(cases[i]); 1633 errln("Collator.getKeywordValues(String) is suppose to return " + 1634 "an exception for an invalid keyword."); 1635 } catch(Exception e){} 1636 } 1637 } 1638 1639 @Test 1640 public void TestBadKeywords() { 1641 // Test locale IDs with errors. 1642 // Valid locale IDs are tested via data-driven tests. 1643 // Note: ICU4C tests with a bogus Locale. There is no such thing in ICU4J. 1644 1645 // Unknown value. 1646 String localeID = "it-u-ks-xyz"; 1647 try { 1648 Collator.getInstance(new ULocale(localeID)); 1649 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1650 } catch(IllegalArgumentException expected) { 1651 } catch(Exception other) { 1652 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1653 } 1654 1655 // Unsupported attributes. 1656 localeID = "it@colHiraganaQuaternary=true"; 1657 try { 1658 Collator.getInstance(new ULocale(localeID)); 1659 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1660 } catch(UnsupportedOperationException expected) { 1661 } catch(Exception other) { 1662 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1663 } 1664 1665 localeID = "it-u-vt-u24"; 1666 try { 1667 Collator.getInstance(new ULocale(localeID)); 1668 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1669 } catch(UnsupportedOperationException expected) { 1670 } catch(Exception other) { 1671 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1672 } 1673 } 1674 1675 @Test 1676 public void TestGapTooSmall() { 1677 // Try to tailor >20k characters into a too-small primary gap between symbols 1678 // that have 3-byte primary weights. 1679 // In FractionalUCA.txt: 1680 // 263A; [0C BA D0, 05, 05] # Zyyy So [084A.0020.0002] * WHITE SMILING FACE 1681 // 263B; [0C BA D7, 05, 05] # Zyyy So [084B.0020.0002] * BLACK SMILING FACE 1682 try { 1683 new RuleBasedCollator("&☺<*\u4E00-\u9FFF"); 1684 errln("no exception for primary-gap overflow"); 1685 } catch (UnsupportedOperationException e) { 1686 assertTrue("exception message mentions 'gap'", e.getMessage().contains("gap")); 1687 } catch (Exception e) { 1688 errln("unexpected exception for primary-gap overflow: " + e); 1689 } 1690 1691 // CLDR 32/ICU 60 FractionalUCA.txt makes room at the end of the symbols range 1692 // for several 2-byte primaries, or a large number of 3-byters. 1693 // The reset point is primary-before what should be 1694 // the special currency-first-primary contraction, 1695 // which is hopefully fairly stable, but not guaranteed stable. 1696 // In FractionalUCA.txt: 1697 // FDD1 20AC; [0D 70 02, 05, 05] # CURRENCY first primary 1698 try { 1699 Collator coll = new RuleBasedCollator("&[before 1]\uFDD1€<*\u4E00-\u9FFF"); 1700 assertTrue("tailored Han before currency", coll.compare("\u4E00", "$") < 0); 1701 } catch (Exception e) { 1702 errln("unexpected exception for tailoring many characters at the end of symbols: " + e); 1703 } 1704 } 1705 1706 @Test 1707 public void TestBogusLocaleID() { 1708 try { 1709 Collator c1 = Collator.getInstance(new ULocale("en-US-u-kn-true")); 1710 Collator c2 = Collator.getInstance(new ULocale("en_US-u-kn-true")); 1711 1712 assertTrue("Comparison using \"normal\" collator failed", c1.compare("2", "10") < 0); 1713 assertTrue("Comparison using \"bad\" collator failed", c2.compare("2", "10") < 0); 1714 } catch (Exception e) { 1715 errln("Exception creating collators: " + e); 1716 } 1717 } 1718 } 1719