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 // Android patch: Add --omitCollationRules to genrb. 500 // RuleBasedCollator rcol = (RuleBasedCollator)Collator.getInstance(new Locale("da", "DK")); 501 // doAssert(rcol.getRules().length() != 0, "da_DK rules does not have length 0"); 502 // Android patch end. 503 504 try { 505 col = Collator.getInstance(Locale.FRENCH); 506 } catch (Exception e) { 507 errln("Creating French collation failed."); 508 return; 509 } 510 511 col.setStrength(Collator.PRIMARY); 512 logln("testing Collator.getStrength() method again ..."); 513 doAssert((col.getStrength() != Collator.TERTIARY), "collation object has the wrong strength"); 514 doAssert((col.getStrength() == Collator.PRIMARY), "collation object's strength is not primary difference"); 515 516 logln("testing French Collator.setStrength() method ..."); 517 col.setStrength(Collator.TERTIARY); 518 doAssert((col.getStrength() == Collator.TERTIARY), "collation object's strength is not tertiary difference"); 519 doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); 520 doAssert((col.getStrength() != Collator.SECONDARY), "collation object's strength is secondary difference"); 521 522 } 523 524 @Test 525 public void TestJunkCollator(){ 526 logln("Create junk collation: "); 527 Locale abcd = new Locale("ab", "CD", ""); 528 529 Collator junk = Collator.getInstance(abcd); 530 Collator col = Collator.getInstance(); 531 532 533 String colrules = ((RuleBasedCollator)col).getRules(); 534 String junkrules = ((RuleBasedCollator)junk).getRules(); 535 doAssert(colrules == junkrules || colrules.equals(junkrules), 536 "The default collation should be returned."); 537 Collator frCol = null; 538 try { 539 frCol = Collator.getInstance(Locale.CANADA_FRENCH); 540 } catch (Exception e) { 541 errln("Creating fr_CA collator failed."); 542 return; 543 } 544 545 doAssert(!(frCol.equals(junk)), "The junk is the same as the fr_CA collator."); 546 logln("Collator property test ended."); 547 548 } 549 550 /** 551 * This tests the RuleBasedCollator 552 * - constructor/destructor 553 * - getRules 554 */ 555 @Test 556 public void TestRuleBasedColl() { 557 RuleBasedCollator col1 = null, col2 = null, col3 = null, col4 = null; 558 559 String ruleset1 = "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E"; 560 String ruleset2 = "&9 < a, A < b, B < c, C < d, D, e, E"; 561 String ruleset3 = "&"; 562 563 try { 564 col1 = new RuleBasedCollator(ruleset1); 565 } catch (Exception e) { 566 // only first error needs to be a warning since we exit function 567 warnln("RuleBased Collator creation failed."); 568 return; 569 } 570 571 try { 572 col2 = new RuleBasedCollator(ruleset2); 573 } catch (Exception e) { 574 errln("RuleBased Collator creation failed."); 575 return; 576 } 577 578 try { 579 // empty rules fail 580 col3 = new RuleBasedCollator(ruleset3); 581 errln("Failure: Empty rules for the collator should fail"); 582 return; 583 } catch (MissingResourceException e) { 584 warnln(e.getMessage()); 585 } catch (Exception e) { 586 logln("PASS: Empty rules for the collator failed as expected"); 587 } 588 589 Locale locale = new Locale("aa", "AA"); 590 try { 591 col3 = (RuleBasedCollator)Collator.getInstance(locale); 592 } catch (Exception e) { 593 errln("Fallback Collator creation failed.: %s"); 594 return; 595 } 596 597 try { 598 col3 = (RuleBasedCollator)Collator.getInstance(); 599 } catch (Exception e) { 600 errln("Default Collator creation failed.: %s"); 601 return; 602 } 603 604 String rule1 = col1.getRules(); 605 String rule2 = col2.getRules(); 606 String rule3 = col3.getRules(); 607 608 doAssert(!rule1.equals(rule2), "Default collator getRules failed"); 609 doAssert(!rule2.equals(rule3), "Default collator getRules failed"); 610 doAssert(!rule1.equals(rule3), "Default collator getRules failed"); 611 612 try { 613 col4 = new RuleBasedCollator(rule2); 614 } catch (Exception e) { 615 errln("RuleBased Collator creation failed."); 616 return; 617 } 618 619 String rule4 = col4.getRules(); 620 doAssert(rule2.equals(rule4), "Default collator getRules failed"); 621 // tests that modifier ! is always ignored 622 String exclamationrules = "!&a<b"; 623 // java does not allow ! to be the start of the rule 624 String thaistr = "\u0e40\u0e01\u0e2d"; 625 try { 626 RuleBasedCollator col5 = new RuleBasedCollator(exclamationrules); 627 RuleBasedCollator encol = (RuleBasedCollator) 628 Collator.getInstance(Locale.ENGLISH); 629 CollationElementIterator col5iter 630 = col5.getCollationElementIterator(thaistr); 631 CollationElementIterator encoliter 632 = encol.getCollationElementIterator( 633 thaistr); 634 while (true) { 635 // testing with en since thai has its own tailoring 636 int ce = col5iter.next(); 637 int ce2 = encoliter.next(); 638 if (ce2 != ce) { 639 errln("! modifier test failed"); 640 } 641 if (ce == CollationElementIterator.NULLORDER) { 642 break; 643 } 644 } 645 } catch (Exception e) { 646 errln("RuleBased Collator creation failed for ! modifier."); 647 return; 648 } 649 } 650 651 /** 652 * This tests the RuleBasedCollator 653 * - getRules 654 */ 655 @Test 656 public void TestRules() { 657 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(new Locale("","","")); //root 658 // logln("PASS: RuleBased Collator creation passed"); 659 660 661 String rules = coll.getRules(); 662 if (rules != null && rules.length() != 0) { 663 errln("Root tailored rules failed"); 664 } 665 } 666 667 @Test 668 public void TestSafeClone() { 669 String test1 = "abCda"; 670 String test2 = "abcda"; 671 672 // one default collator & two complex ones 673 RuleBasedCollator someCollators[] = { 674 (RuleBasedCollator)Collator.getInstance(Locale.ENGLISH), 675 (RuleBasedCollator)Collator.getInstance(Locale.KOREA), 676 (RuleBasedCollator)Collator.getInstance(Locale.JAPAN) 677 }; 678 RuleBasedCollator someClonedCollators[] = new RuleBasedCollator[3]; 679 680 // change orig & clone & make sure they are independent 681 682 for (int index = 0; index < someCollators.length; index ++) 683 { 684 try { 685 someClonedCollators[index] 686 = (RuleBasedCollator)someCollators[index].clone(); 687 } catch (CloneNotSupportedException e) { 688 errln("Error cloning collator"); 689 } 690 691 someClonedCollators[index].setStrength(Collator.TERTIARY); 692 someCollators[index].setStrength(Collator.PRIMARY); 693 someClonedCollators[index].setCaseLevel(false); 694 someCollators[index].setCaseLevel(false); 695 696 doAssert(someClonedCollators[index].compare(test1, test2) > 0, 697 "Result should be \"abCda\" >>> \"abcda\" "); 698 doAssert(someCollators[index].compare(test1, test2) == 0, 699 "Result should be \"abCda\" == \"abcda\" "); 700 } 701 } 702 703 @Test 704 public void TestGetTailoredSet() 705 { 706 logln("testing getTailoredSet..."); 707 String rules[] = { 708 "&a < \u212b", 709 "& S < \u0161 <<< \u0160", 710 }; 711 String data[][] = { 712 { "\u212b", "A\u030a", "\u00c5" }, 713 { "\u0161", "s\u030C", "\u0160", "S\u030C" } 714 }; 715 716 int i = 0, j = 0; 717 718 RuleBasedCollator coll; 719 UnicodeSet set; 720 721 for(i = 0; i < rules.length; i++) { 722 try { 723 logln("Instantiating a collator from "+rules[i]); 724 coll = new RuleBasedCollator(rules[i]); 725 set = coll.getTailoredSet(); 726 logln("Got set: "+set.toPattern(true)); 727 if(set.size() < data[i].length) { 728 errln("Tailored set size smaller ("+set.size()+") than expected ("+data[i].length+")"); 729 } 730 for(j = 0; j < data[i].length; j++) { 731 logln("Checking to see whether "+data[i][j]+" is in set"); 732 if(!set.contains(data[i][j])) { 733 errln("Tailored set doesn't contain "+data[i][j]+"... It should"); 734 } 735 } 736 } catch (Exception e) { 737 warnln("Couldn't open collator with rules "+ rules[i]); 738 } 739 } 740 } 741 742 /** 743 * Simple test to see if Collator is subclassable. 744 * Also test coverage of base class methods that are overridden by RuleBasedCollator. 745 */ 746 @Test 747 public void TestSubClass() 748 { 749 class TestCollator extends Collator 750 { 751 @Override 752 public boolean equals(Object that) { 753 return this == that; 754 } 755 756 @Override 757 public int hashCode() { 758 return 0; 759 } 760 761 @Override 762 public int compare(String source, String target) { 763 return source.compareTo(target); 764 } 765 766 @Override 767 public CollationKey getCollationKey(String source) 768 { return new CollationKey(source, 769 getRawCollationKey(source, new RawCollationKey())); 770 } 771 772 @Override 773 public RawCollationKey getRawCollationKey(String source, 774 RawCollationKey key) 775 { 776 byte temp1[] = source.getBytes(); 777 byte temp2[] = new byte[temp1.length + 1]; 778 System.arraycopy(temp1, 0, temp2, 0, temp1.length); 779 temp2[temp1.length] = 0; 780 if (key == null) { 781 key = new RawCollationKey(); 782 } 783 key.bytes = temp2; 784 key.size = temp2.length; 785 return key; 786 } 787 788 @Override 789 public void setVariableTop(int ce) 790 { 791 if (isFrozen()) { 792 throw new UnsupportedOperationException("Attempt to modify frozen object"); 793 } 794 } 795 796 @Override 797 public int setVariableTop(String str) 798 { 799 if (isFrozen()) { 800 throw new UnsupportedOperationException("Attempt to modify frozen object"); 801 } 802 803 return 0; 804 } 805 806 @Override 807 public int getVariableTop() 808 { 809 return 0; 810 } 811 @Override 812 public VersionInfo getVersion() 813 { 814 return VersionInfo.getInstance(0); 815 } 816 @Override 817 public VersionInfo getUCAVersion() 818 { 819 return VersionInfo.getInstance(0); 820 } 821 } 822 823 Collator col1 = new TestCollator(); 824 Collator col2 = new TestCollator(); 825 if (col1.equals(col2)) { 826 errln("2 different instance of TestCollator should fail"); 827 } 828 if (col1.hashCode() != col2.hashCode()) { 829 errln("Every TestCollator has the same hashcode"); 830 } 831 String abc = "abc"; 832 String bcd = "bcd"; 833 if (col1.compare(abc, bcd) != abc.compareTo(bcd)) { 834 errln("TestCollator compare should be the same as the default " + 835 "string comparison"); 836 } 837 CollationKey key = col1.getCollationKey(abc); 838 byte temp1[] = abc.getBytes(); 839 byte temp2[] = new byte[temp1.length + 1]; 840 System.arraycopy(temp1, 0, temp2, 0, temp1.length); 841 temp2[temp1.length] = 0; 842 if (!java.util.Arrays.equals(key.toByteArray(), temp2) 843 || !key.getSourceString().equals(abc)) { 844 errln("TestCollator collationkey API is returning wrong values"); 845 } 846 UnicodeSet set = col1.getTailoredSet(); 847 if (!set.equals(new UnicodeSet(0, 0x10FFFF))) { 848 errln("Error getting default tailored set"); 849 } 850 851 // Base class code coverage. 852 // Most of these methods are dummies; 853 // they are overridden by any subclass that supports their features. 854 855 assertEquals("compare(strings as Object)", 0, 856 col1.compare(new StringBuilder("abc"), new StringBuffer("abc"))); 857 858 col1.setStrength(Collator.SECONDARY); 859 assertNotEquals("getStrength()", Collator.PRIMARY, col1.getStrength()); 860 861 // setStrength2() is @internal and returns this. 862 // The base class getStrength() always returns the same value, 863 // since the base class does not have a field to store the strength. 864 assertNotEquals("setStrength2().getStrength()", Collator.PRIMARY, 865 col1.setStrength2(Collator.IDENTICAL).getStrength()); 866 867 // (base class).setDecomposition() may or may not be implemented. 868 try { 869 col1.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 870 } catch (UnsupportedOperationException expected) { 871 } 872 assertNotEquals("getDecomposition()", -1, col1.getDecomposition()); // don't care about the value 873 874 // (base class).setMaxVariable() may or may not be implemented. 875 try { 876 col1.setMaxVariable(Collator.ReorderCodes.CURRENCY); 877 } catch (UnsupportedOperationException expected) { 878 } 879 assertNotEquals("getMaxVariable()", -1, col1.getMaxVariable()); // don't care about the value 880 881 // (base class).setReorderCodes() may or may not be implemented. 882 try { 883 col1.setReorderCodes(0, 1, 2); 884 } catch (UnsupportedOperationException expected) { 885 } 886 try { 887 col1.getReorderCodes(); 888 } catch (UnsupportedOperationException expected) { 889 } 890 891 assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN).isEmpty()); 892 assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN, Locale.ITALIAN).isEmpty()); 893 894 assertNotEquals("getLocale()", ULocale.GERMAN, col1.getLocale(ULocale.ACTUAL_LOCALE)); 895 896 // Cover Collator.setLocale() which is only package-visible. 897 Object token = Collator.registerInstance(new TestCollator(), new ULocale("de-Japn-419")); 898 Collator.unregister(token); 899 900 // Freezable default implementations. freeze() may or may not be implemented. 901 assertFalse("not yet frozen", col2.isFrozen()); 902 try { 903 col2.freeze(); 904 assertTrue("now frozen", col2.isFrozen()); 905 } catch (UnsupportedOperationException expected) { 906 } 907 try { 908 col2.setStrength(Collator.PRIMARY); 909 if (col2.isFrozen()) { 910 fail("(frozen Collator).setStrength() should throw an exception"); 911 } 912 } catch (UnsupportedOperationException expected) { 913 } 914 try { 915 Collator col3 = col2.cloneAsThawed(); 916 assertFalse("!cloneAsThawed().isFrozen()", col3.isFrozen()); 917 } catch (UnsupportedOperationException expected) { 918 } 919 } 920 921 /** 922 * Simple test the collator setter and getters. 923 * Similar to C++ apicoll.cpp TestAttribute(). 924 */ 925 @Test 926 public void TestSetGet() 927 { 928 RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(); 929 int decomp = collator.getDecomposition(); 930 int strength = collator.getStrength(); 931 boolean alt = collator.isAlternateHandlingShifted(); 932 boolean caselevel = collator.isCaseLevel(); 933 boolean french = collator.isFrenchCollation(); 934 boolean hquart = collator.isHiraganaQuaternary(); 935 boolean lowercase = collator.isLowerCaseFirst(); 936 boolean uppercase = collator.isUpperCaseFirst(); 937 938 collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 939 if (collator.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) { 940 errln("Setting decomposition failed"); 941 } 942 collator.setStrength(Collator.QUATERNARY); 943 if (collator.getStrength() != Collator.QUATERNARY) { 944 errln("Setting strength failed"); 945 } 946 collator.setAlternateHandlingShifted(!alt); 947 if (collator.isAlternateHandlingShifted() == alt) { 948 errln("Setting alternate handling failed"); 949 } 950 collator.setCaseLevel(!caselevel); 951 if (collator.isCaseLevel() == caselevel) { 952 errln("Setting case level failed"); 953 } 954 collator.setFrenchCollation(!french); 955 if (collator.isFrenchCollation() == french) { 956 errln("Setting french collation failed"); 957 } 958 collator.setHiraganaQuaternary(!hquart); 959 if (collator.isHiraganaQuaternary() != hquart) { 960 errln("Setting hiragana quartenary worked but should be a no-op since ICU 50"); 961 } 962 collator.setLowerCaseFirst(!lowercase); 963 if (collator.isLowerCaseFirst() == lowercase) { 964 errln("Setting lower case first failed"); 965 } 966 collator.setUpperCaseFirst(!uppercase); 967 if (collator.isUpperCaseFirst() == uppercase) { 968 errln("Setting upper case first failed"); 969 } 970 collator.setDecompositionDefault(); 971 if (collator.getDecomposition() != decomp) { 972 errln("Setting decomposition default failed"); 973 } 974 collator.setStrengthDefault(); 975 if (collator.getStrength() != strength) { 976 errln("Setting strength default failed"); 977 } 978 collator.setAlternateHandlingDefault(); 979 if (collator.isAlternateHandlingShifted() != alt) { 980 errln("Setting alternate handling default failed"); 981 } 982 collator.setCaseLevelDefault(); 983 if (collator.isCaseLevel() != caselevel) { 984 errln("Setting case level default failed"); 985 } 986 collator.setFrenchCollationDefault(); 987 if (collator.isFrenchCollation() != french) { 988 errln("Setting french handling default failed"); 989 } 990 collator.setHiraganaQuaternaryDefault(); 991 if (collator.isHiraganaQuaternary() != hquart) { 992 errln("Setting Hiragana Quartenary default failed"); 993 } 994 collator.setCaseFirstDefault(); 995 if (collator.isLowerCaseFirst() != lowercase 996 || collator.isUpperCaseFirst() != uppercase) { 997 errln("Setting case first handling default failed"); 998 } 999 } 1000 1001 @Test 1002 public void TestVariableTopSetting() { 1003 // Use the root collator, not the default collator. 1004 // This test fails with en_US_POSIX which tailors the dollar sign after 'A'. 1005 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(ULocale.ROOT); 1006 1007 int oldVarTop = coll.getVariableTop(); 1008 1009 // ICU 53+: The character must be in a supported reordering group, 1010 // and the variable top is pinned to the end of that group. 1011 try { 1012 coll.setVariableTop("A"); 1013 errln("setVariableTop(letter) did not detect illegal argument"); 1014 } catch(IllegalArgumentException expected) { 1015 } 1016 1017 // dollar sign (currency symbol) 1018 int newVarTop = coll.setVariableTop("$"); 1019 1020 if(newVarTop != coll.getVariableTop()) { 1021 errln("setVariableTop(dollar sign) != following getVariableTop()"); 1022 } 1023 1024 String dollar = "$"; 1025 String euro = "\u20AC"; 1026 int newVarTop2 = coll.setVariableTop(euro); 1027 assertEquals("setVariableTop(Euro sign) == following getVariableTop()", 1028 newVarTop2, coll.getVariableTop()); 1029 assertEquals("setVariableTop(Euro sign) == setVariableTop(dollar sign) (should pin to top of currency group)", 1030 newVarTop2, newVarTop); 1031 1032 coll.setAlternateHandlingShifted(true); 1033 assertEquals("empty==dollar", 0, coll.compare("", dollar)); // UCOL_EQUAL 1034 assertEquals("empty==euro", 0, coll.compare("", euro)); // UCOL_EQUAL 1035 assertEquals("dollar<zero", -1, coll.compare(dollar, "0")); // UCOL_LESS 1036 1037 coll.setVariableTop(oldVarTop); 1038 1039 int newerVarTop = coll.setVariableTop("$"); 1040 1041 if(newVarTop != newerVarTop) { 1042 errln("Didn't set vartop properly from String!\n"); 1043 } 1044 } 1045 1046 @Test 1047 public void TestMaxVariable() { 1048 RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(ULocale.ROOT); 1049 1050 try { 1051 coll.setMaxVariable(Collator.ReorderCodes.OTHERS); 1052 errln("setMaxVariable(others) did not detect illegal argument"); 1053 } catch(IllegalArgumentException expected) { 1054 } 1055 1056 coll.setMaxVariable(Collator.ReorderCodes.CURRENCY); 1057 1058 if(Collator.ReorderCodes.CURRENCY != coll.getMaxVariable()) { 1059 errln("setMaxVariable(currency) != following getMaxVariable()"); 1060 } 1061 1062 coll.setAlternateHandlingShifted(true); 1063 assertEquals("empty==dollar", 0, coll.compare("", "$")); // UCOL_EQUAL 1064 assertEquals("empty==euro", 0, coll.compare("", "\u20AC")); // UCOL_EQUAL 1065 assertEquals("dollar<zero", -1, coll.compare("$", "0")); // UCOL_LESS 1066 } 1067 1068 @Test 1069 public void TestGetLocale() { 1070 String rules = "&a<x<y<z"; 1071 1072 Collator coll = Collator.getInstance(new ULocale("root")); 1073 ULocale locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1074 if(!locale.equals(ULocale.ROOT)) { 1075 errln("Collator.getInstance(\"root\").getLocale(actual) != ULocale.ROOT; " + 1076 "getLocale().getName() = \"" + locale.getName() + "\""); 1077 } 1078 1079 coll = Collator.getInstance(new ULocale("")); 1080 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1081 if(!locale.equals(ULocale.ROOT)) { 1082 errln("Collator.getInstance(\"\").getLocale(actual) != ULocale.ROOT; " + 1083 "getLocale().getName() = \"" + locale.getName() + "\""); 1084 } 1085 1086 int i = 0; 1087 1088 String[][] testStruct = { 1089 // requestedLocale, validLocale, actualLocale 1090 // Note: ULocale.ROOT.getName() == "" not "root". 1091 { "de_DE", "de", "" }, 1092 { "sr_RS", "sr_Cyrl_RS", "sr" }, 1093 { "en_US_CALIFORNIA", "en_US", "" }, 1094 { "fr_FR_NONEXISTANT", "fr", "" }, 1095 // pinyin is the default, therefore suppressed. 1096 { "zh_CN", "zh_Hans_CN", "zh" }, 1097 // zh_Hant has default=stroke but the data is in zh. 1098 { "zh_TW", "zh_Hant_TW", "zh@collation=stroke" }, 1099 { "zh_TW@collation=pinyin", "zh_Hant_TW@collation=pinyin", "zh" }, 1100 { "zh_CN@collation=stroke", "zh_Hans_CN@collation=stroke", "zh@collation=stroke" }, 1101 // yue/yue_Hant aliased to zh_Hant, yue_Hans aliased to zh_Hans. 1102 { "yue", "zh_Hant", "zh@collation=stroke" }, 1103 { "yue_HK", "zh_Hant", "zh@collation=stroke" }, 1104 { "yue_Hant", "zh_Hant", "zh@collation=stroke" }, 1105 { "yue_Hant_HK", "zh_Hant", "zh@collation=stroke" }, 1106 { "yue@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, 1107 { "yue_HK@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, 1108 { "yue_CN", "zh_Hans", "zh" }, 1109 { "yue_Hans", "zh_Hans", "zh" }, 1110 { "yue_Hans_CN", "zh_Hans", "zh" }, 1111 { "yue_Hans@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" }, 1112 { "yue_CN@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" } 1113 }; 1114 1115 /* test opening collators for different locales */ 1116 for(i = 0; i<testStruct.length; i++) { 1117 String requestedLocale = testStruct[i][0]; 1118 String validLocale = testStruct[i][1]; 1119 String actualLocale = testStruct[i][2]; 1120 try { 1121 coll = Collator.getInstance(new ULocale(requestedLocale)); 1122 } catch(Exception e) { 1123 errln(String.format("Failed to open collator for %s with %s", requestedLocale, e)); 1124 continue; 1125 } 1126 // Note: C++ getLocale() recognizes ULOC_REQUESTED_LOCALE 1127 // which does not exist in Java. 1128 locale = coll.getLocale(ULocale.VALID_LOCALE); 1129 if(!locale.equals(new ULocale(validLocale))) { 1130 errln(String.format("[Coll %s]: Error in valid locale, expected %s, got %s", 1131 requestedLocale, validLocale, locale.getName())); 1132 } 1133 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1134 if(!locale.equals(new ULocale(actualLocale))) { 1135 errln(String.format("[Coll %s]: Error in actual locale, expected %s, got %s", 1136 requestedLocale, actualLocale, locale.getName())); 1137 } 1138 // If we open a collator for the actual locale, we should get an equivalent one again. 1139 Collator coll2; 1140 try { 1141 coll2 = Collator.getInstance(locale); 1142 } catch(Exception e) { 1143 errln(String.format("Failed to open collator for actual locale \"%s\" with %s", 1144 locale.getName(), e)); 1145 continue; 1146 } 1147 ULocale actual2 = coll2.getLocale(ULocale.ACTUAL_LOCALE); 1148 if(!actual2.equals(locale)) { 1149 errln(String.format("[Coll actual \"%s\"]: Error in actual locale, got different one: \"%s\"", 1150 locale.getName(), actual2.getName())); 1151 } 1152 if(!coll2.equals(coll)) { 1153 errln(String.format("[Coll actual \"%s\"]: Got different collator than before", 1154 locale.getName())); 1155 } 1156 } 1157 1158 /* completely non-existent locale for collator should get a root collator */ 1159 { 1160 try { 1161 coll = Collator.getInstance(new ULocale("blahaha")); 1162 } catch(Exception e) { 1163 errln("Failed to open collator with " + e); 1164 return; 1165 } 1166 ULocale valid = coll.getLocale(ULocale.VALID_LOCALE); 1167 String name = valid.getName(); 1168 if(name.length() != 0 && !name.equals("root")) { 1169 errln("Valid locale for nonexisting locale collator is \"" + name + "\" not root"); 1170 } 1171 ULocale actual = coll.getLocale(ULocale.ACTUAL_LOCALE); 1172 name = actual.getName(); 1173 if(name.length() != 0 && !name.equals("root")) { 1174 errln("Actual locale for nonexisting locale collator is \"" + name + "\" not root"); 1175 } 1176 } 1177 1178 /* collator instantiated from rules should have all locales null */ 1179 try { 1180 coll = new RuleBasedCollator(rules); 1181 } catch (Exception e) { 1182 errln("RuleBasedCollator(" + rules + ") failed: " + e); 1183 return; 1184 } 1185 locale = coll.getLocale(ULocale.VALID_LOCALE); 1186 if(locale != null) { 1187 errln(String.format("For collator instantiated from rules, valid locale %s is not bogus", 1188 locale.getName())); 1189 } 1190 locale = coll.getLocale(ULocale.ACTUAL_LOCALE); 1191 if(locale != null) { 1192 errln(String.format("For collator instantiated from rules, actual locale %s is not bogus", 1193 locale.getName())); 1194 } 1195 } 1196 1197 @Test 1198 public void TestBounds() 1199 { 1200 Collator coll = Collator.getInstance(new Locale("sh", "")); 1201 1202 String test[] = { "John Smith", "JOHN SMITH", 1203 "john SMITH", "j\u00F6hn sm\u00EFth", 1204 "J\u00F6hn Sm\u00EFth", "J\u00D6HN SM\u00CFTH", 1205 "john smithsonian", "John Smithsonian", 1206 }; 1207 1208 String testStr[] = { 1209 "\u010CAKI MIHALJ", 1210 "\u010CAKI MIHALJ", 1211 "\u010CAKI PIRO\u0160KA", 1212 "\u010CABAI ANDRIJA", 1213 "\u010CABAI LAJO\u0160", 1214 "\u010CABAI MARIJA", 1215 "\u010CABAI STEVAN", 1216 "\u010CABAI STEVAN", 1217 "\u010CABARKAPA BRANKO", 1218 "\u010CABARKAPA MILENKO", 1219 "\u010CABARKAPA MIROSLAV", 1220 "\u010CABARKAPA SIMO", 1221 "\u010CABARKAPA STANKO", 1222 "\u010CABARKAPA TAMARA", 1223 "\u010CABARKAPA TOMA\u0160", 1224 "\u010CABDARI\u0106 NIKOLA", 1225 "\u010CABDARI\u0106 ZORICA", 1226 "\u010CABI NANDOR", 1227 "\u010CABOVI\u0106 MILAN", 1228 "\u010CABRADI AGNEZIJA", 1229 "\u010CABRADI IVAN", 1230 "\u010CABRADI JELENA", 1231 "\u010CABRADI LJUBICA", 1232 "\u010CABRADI STEVAN", 1233 "\u010CABRDA MARTIN", 1234 "\u010CABRILO BOGDAN", 1235 "\u010CABRILO BRANISLAV", 1236 "\u010CABRILO LAZAR", 1237 "\u010CABRILO LJUBICA", 1238 "\u010CABRILO SPASOJA", 1239 "\u010CADE\u0160 ZDENKA", 1240 "\u010CADESKI BLAGOJE", 1241 "\u010CADOVSKI VLADIMIR", 1242 "\u010CAGLJEVI\u0106 TOMA", 1243 "\u010CAGOROVI\u0106 VLADIMIR", 1244 "\u010CAJA VANKA", 1245 "\u010CAJI\u0106 BOGOLJUB", 1246 "\u010CAJI\u0106 BORISLAV", 1247 "\u010CAJI\u0106 RADOSLAV", 1248 "\u010CAK\u0160IRAN MILADIN", 1249 "\u010CAKAN EUGEN", 1250 "\u010CAKAN EVGENIJE", 1251 "\u010CAKAN IVAN", 1252 "\u010CAKAN JULIJAN", 1253 "\u010CAKAN MIHAJLO", 1254 "\u010CAKAN STEVAN", 1255 "\u010CAKAN VLADIMIR", 1256 "\u010CAKAN VLADIMIR", 1257 "\u010CAKAN VLADIMIR", 1258 "\u010CAKARA ANA", 1259 "\u010CAKAREVI\u0106 MOMIR", 1260 "\u010CAKAREVI\u0106 NEDELJKO", 1261 "\u010CAKI \u0160ANDOR", 1262 "\u010CAKI AMALIJA", 1263 "\u010CAKI ANDRA\u0160", 1264 "\u010CAKI LADISLAV", 1265 "\u010CAKI LAJO\u0160", 1266 "\u010CAKI LASLO" }; 1267 1268 CollationKey testKey[] = new CollationKey[testStr.length]; 1269 for (int i = 0; i < testStr.length; i ++) { 1270 testKey[i] = coll.getCollationKey(testStr[i]); 1271 } 1272 1273 Arrays.sort(testKey); 1274 for(int i = 0; i < testKey.length - 1; i ++) { 1275 CollationKey lower 1276 = testKey[i].getBound(CollationKey.BoundMode.LOWER, 1277 Collator.SECONDARY); 1278 for (int j = i + 1; j < testKey.length; j ++) { 1279 CollationKey upper 1280 = testKey[j].getBound(CollationKey.BoundMode.UPPER, 1281 Collator.SECONDARY); 1282 for (int k = i; k <= j; k ++) { 1283 if (lower.compareTo(testKey[k]) > 0) { 1284 errln("Problem with lower bound at i = " + i + " j = " 1285 + j + " k = " + k); 1286 } 1287 if (upper.compareTo(testKey[k]) <= 0) { 1288 errln("Problem with upper bound at i = " + i + " j = " 1289 + j + " k = " + k); 1290 } 1291 } 1292 } 1293 } 1294 1295 for (int i = 0; i < test.length; i ++) 1296 { 1297 CollationKey key = coll.getCollationKey(test[i]); 1298 CollationKey lower = key.getBound(CollationKey.BoundMode.LOWER, 1299 Collator.SECONDARY); 1300 CollationKey upper = key.getBound(CollationKey.BoundMode.UPPER_LONG, 1301 Collator.SECONDARY); 1302 for (int j = i + 1; j < test.length; j ++) { 1303 key = coll.getCollationKey(test[j]); 1304 if (lower.compareTo(key) > 0) { 1305 errln("Problem with lower bound i = " + i + " j = " + j); 1306 } 1307 if (upper.compareTo(key) <= 0) { 1308 errln("Problem with upper bound i = " + i + " j = " + j); 1309 } 1310 } 1311 } 1312 } 1313 1314 @Test 1315 public final void TestGetAll() { 1316 Locale[] list = Collator.getAvailableLocales(); 1317 int errorCount = 0; 1318 for (int i = 0; i < list.length; ++i) { 1319 log("Locale name: "); 1320 log(list[i].toString()); 1321 log(" , the display name is : "); 1322 logln(list[i].getDisplayName()); 1323 try{ 1324 logln(" ...... Or display as: " + Collator.getDisplayName(list[i])); 1325 logln(" ...... and display in Chinese: " + 1326 Collator.getDisplayName(list[i],Locale.CHINA)); 1327 }catch(MissingResourceException ex){ 1328 errorCount++; 1329 logln("could not get displayName for " + list[i]); 1330 } 1331 } 1332 if(errorCount>0){ 1333 warnln("Could not load the locale data."); 1334 } 1335 } 1336 1337 private boolean 1338 doSetsTest(UnicodeSet ref, UnicodeSet set, String inSet, String outSet) { 1339 boolean ok = true; 1340 set.clear(); 1341 set.applyPattern(inSet); 1342 1343 if(!ref.containsAll(set)) { 1344 err("Some stuff from "+inSet+" is not present in the set.\nMissing:"+ 1345 set.removeAll(ref).toPattern(true)+"\n"); 1346 ok = false; 1347 } 1348 1349 set.clear(); 1350 set.applyPattern(outSet); 1351 if(!ref.containsNone(set)) { 1352 err("Some stuff from "+outSet+" is present in the set.\nUnexpected:"+ 1353 set.retainAll(ref).toPattern(true)+"\n"); 1354 ok = false; 1355 } 1356 return ok; 1357 } 1358 1359 // capitst.c/TestGetContractionsAndUnsafes() 1360 @Test 1361 public void TestGetContractions() throws Exception { 1362 /* static struct { 1363 const char* locale; 1364 const char* inConts; 1365 const char* outConts; 1366 const char* inExp; 1367 const char* outExp; 1368 const char* unsafeCodeUnits; 1369 const char* safeCodeUnits; 1370 } 1371 */ 1372 String tests[][] = { 1373 { "ru", 1374 "[{\u0418\u0306}{\u0438\u0306}]", 1375 "[\u0439\u0457]", 1376 "[\u00e6]", 1377 "[ae]", 1378 "[\u0418\u0438]", 1379 "[aAbBxv]" 1380 }, 1381 { "uk", 1382 "[{\u0406\u0308}{\u0456\u0308}{\u0418\u0306}{\u0438\u0306}]", 1383 "[\u0407\u0419\u0439\u0457]", 1384 "[\u00e6]", 1385 "[ae]", 1386 "[\u0406\u0456\u0418\u0438]", 1387 "[aAbBxv]" 1388 }, 1389 { "sh", 1390 "[{C\u0301}{C\u030C}{C\u0341}{DZ\u030C}{Dz\u030C}{D\u017D}{D\u017E}{lj}{nj}]", 1391 "[{\u309d\u3099}{\u30fd\u3099}]", 1392 "[\u00e6]", 1393 "[a]", 1394 "[nlcdzNLCDZ]", 1395 "[jabv]" 1396 }, 1397 { "ja", 1398 /* 1399 * The "collv2" builder omits mappings if the collator maps their 1400 * character sequences to the same CEs. 1401 * For example, it omits Japanese contractions for NFD forms 1402 * of the voiced iteration mark (U+309E = U+309D + U+3099), such as 1403 * {\u3053\u3099\u309D\u3099}{\u3053\u309D\u3099} 1404 * {\u30B3\u3099\u30FD\u3099}{\u30B3\u30FD\u3099}. 1405 * It does add mappings for the precomposed forms. 1406 */ 1407 "[{\u3053\u3099\u309D}{\u3053\u3099\u309E}{\u3053\u3099\u30FC}" + 1408 "{\u3053\u309D}{\u3053\u309E}{\u3053\u30FC}" + 1409 "{\u30B3\u3099\u30FC}{\u30B3\u3099\u30FD}{\u30B3\u3099\u30FE}" + 1410 "{\u30B3\u30FC}{\u30B3\u30FD}{\u30B3\u30FE}]", 1411 "[{\u30FD\u3099}{\u309D\u3099}{\u3053\u3099}{\u30B3\u3099}{lj}{nj}]", 1412 "[\u30FE\u00e6]", 1413 "[a]", 1414 "[\u3099]", 1415 "[]" 1416 } 1417 }; 1418 1419 RuleBasedCollator coll = null; 1420 int i = 0; 1421 UnicodeSet conts = new UnicodeSet(); 1422 UnicodeSet exp = new UnicodeSet(); 1423 UnicodeSet set = new UnicodeSet(); 1424 1425 for(i = 0; i < tests.length; i++) { 1426 logln("Testing locale: "+ tests[i][0]); 1427 coll = (RuleBasedCollator)Collator.getInstance(new ULocale(tests[i][0])); 1428 coll.getContractionsAndExpansions(conts, exp, true); 1429 boolean ok = true; 1430 logln("Contractions "+conts.size()+":\n"+conts.toPattern(true)); 1431 ok &= doSetsTest(conts, set, tests[i][1], tests[i][2]); 1432 logln("Expansions "+exp.size()+":\n"+exp.toPattern(true)); 1433 ok &= doSetsTest(exp, set, tests[i][3], tests[i][4]); 1434 if(!ok) { 1435 // In case of failure, log the rule string for better diagnostics. 1436 String rules = coll.getRules(false); 1437 logln("Collation rules (getLocale()="+ 1438 coll.getLocale(ULocale.ACTUAL_LOCALE).toString()+"): "+ 1439 Utility.escape(rules)); 1440 } 1441 1442 // No unsafe set in ICU4J 1443 //noConts = ucol_getUnsafeSet(coll, conts, &status); 1444 //doSetsTest(conts, set, tests[i][5], tests[i][6]); 1445 //log_verbose("Unsafes "+conts.size()+":\n"+conts.toPattern(true)+"\n"); 1446 } 1447 } 1448 private static final String bigone = "One"; 1449 private static final String littleone = "one"; 1450 1451 @Test 1452 public void TestClone() { 1453 logln("\ninit c0"); 1454 RuleBasedCollator c0 = (RuleBasedCollator)Collator.getInstance(); 1455 c0.setStrength(Collator.TERTIARY); 1456 dump("c0", c0); 1457 1458 logln("\ninit c1"); 1459 RuleBasedCollator c1 = (RuleBasedCollator)Collator.getInstance(); 1460 c1.setStrength(Collator.TERTIARY); 1461 c1.setUpperCaseFirst(!c1.isUpperCaseFirst()); 1462 dump("c0", c0); 1463 dump("c1", c1); 1464 try{ 1465 logln("\ninit c2"); 1466 RuleBasedCollator c2 = (RuleBasedCollator)c1.clone(); 1467 c2.setUpperCaseFirst(!c2.isUpperCaseFirst()); 1468 dump("c0", c0); 1469 dump("c1", c1); 1470 dump("c2", c2); 1471 if(c1.equals(c2)){ 1472 errln("The cloned objects refer to same data"); 1473 } 1474 }catch(CloneNotSupportedException ex){ 1475 errln("Could not clone the collator"); 1476 } 1477 } 1478 1479 private void dump(String msg, RuleBasedCollator c) { 1480 logln(msg + " " + c.compare(bigone, littleone) + 1481 " s: " + c.getStrength() + 1482 " u: " + c.isUpperCaseFirst()); 1483 } 1484 1485 @Test 1486 public void TestIterNumeric() throws Exception { // misnomer for Java, but parallel with C++ test 1487 // Regression test for ticket #9915. 1488 // The collation code sometimes masked the continuation marker away 1489 // but later tested the result for isContinuation(). 1490 // This test case failed because the third bytes of the computed numeric-collation primaries 1491 // were permutated with the script reordering table. 1492 // It should have been possible to reproduce this with the root collator 1493 // and characters with appropriate 3-byte primary weights. 1494 // The effectiveness of this test depends completely on the collation elements 1495 // and on the implementation code. 1496 RuleBasedCollator coll = new RuleBasedCollator("[reorder Hang Hani]"); 1497 coll.setNumericCollation(true); 1498 int result = coll.compare("40", "72"); 1499 assertTrue("40<72", result < 0); 1500 } 1501 1502 /* 1503 * Tests the method public void setStrength(int newStrength) 1504 */ 1505 @Test 1506 public void TestSetStrength() { 1507 // Tests when if ((newStrength != PRIMARY) && ... ) is true 1508 int[] cases = { -1, 4, 5 }; 1509 for (int i = 0; i < cases.length; i++) { 1510 try { 1511 // Assuming -1 is not one of the values 1512 Collator c = Collator.getInstance(); 1513 c.setStrength(cases[i]); 1514 errln("Collator.setStrength(int) is suppose to return " 1515 + "an exception for an invalid newStrength value of " + cases[i]); 1516 } catch (Exception e) { 1517 } 1518 } 1519 } 1520 1521 /* 1522 * Tests the method public void setDecomposition(int decomposition) 1523 */ 1524 @Test 1525 public void TestSetDecomposition() { 1526 // Tests when if ((decomposition != NO_DECOMPOSITION) && ...) is true 1527 int[] cases = { 0, 1, 14, 15, 18, 19 }; 1528 for (int i = 0; i < cases.length; i++) { 1529 try { 1530 // Assuming -1 is not one of the values 1531 Collator c = Collator.getInstance(); 1532 c.setDecomposition(cases[i]); 1533 errln("Collator.setDecomposition(int) is suppose to return " 1534 + "an exception for an invalid decomposition value of " + cases[i]); 1535 } catch (Exception e) { 1536 } 1537 } 1538 } 1539 1540 /* 1541 * Tests the class CollatorFactory 1542 */ 1543 @Test 1544 public void TestCreateCollator() { 1545 // The following class override public Collator createCollator(Locale loc) 1546 class TestCreateCollator extends CollatorFactory { 1547 @Override 1548 public Set<String> getSupportedLocaleIDs() { 1549 return new HashSet<String>(); 1550 } 1551 1552 public TestCreateCollator() { 1553 super(); 1554 } 1555 1556 @Override 1557 public Collator createCollator(ULocale c) { 1558 return null; 1559 } 1560 } 1561 // The following class override public Collator createCollator(ULocale loc) 1562 class TestCreateCollator1 extends CollatorFactory { 1563 @Override 1564 public Set<String> getSupportedLocaleIDs() { 1565 return new HashSet<String>(); 1566 } 1567 1568 public TestCreateCollator1() { 1569 super(); 1570 } 1571 1572 @Override 1573 public Collator createCollator(Locale c) { 1574 return null; 1575 } 1576 @Override 1577 public boolean visible(){ 1578 return false; 1579 } 1580 } 1581 1582 /* 1583 * Tests the method public Collator createCollator(Locale loc) using TestCreateCollator1 class 1584 */ 1585 try { 1586 TestCreateCollator tcc = new TestCreateCollator(); 1587 tcc.createCollator(new Locale("en", "US")); 1588 } catch (Exception e) { 1589 errln("Collator.createCollator(Locale) was not suppose to " + "return an exception."); 1590 } 1591 1592 /* 1593 * Tests the method public Collator createCollator(ULocale loc) using TestCreateCollator1 class 1594 */ 1595 try { 1596 TestCreateCollator1 tcc = new TestCreateCollator1(); 1597 tcc.createCollator(new ULocale("en_US")); 1598 } catch (Exception e) { 1599 errln("Collator.createCollator(ULocale) was not suppose to " + "return an exception."); 1600 } 1601 1602 /* 1603 * Tests the method public String getDisplayName(Locale objectLocale, Locale displayLocale) using TestCreateCollator1 class 1604 */ 1605 try { 1606 TestCreateCollator tcc = new TestCreateCollator(); 1607 tcc.getDisplayName(new Locale("en", "US"), new Locale("jp", "JP")); 1608 } catch (Exception e) { 1609 errln("Collator.getDisplayName(Locale,Locale) was not suppose to return an exception."); 1610 } 1611 1612 /* 1613 * Tests the method public String getDisplayName(ULocale objectLocale, ULocale displayLocale) using TestCreateCollator1 class 1614 */ 1615 try { 1616 TestCreateCollator1 tcc = new TestCreateCollator1(); 1617 tcc.getDisplayName(new ULocale("en_US"), new ULocale("jp_JP")); 1618 } catch (Exception e) { 1619 errln("Collator.getDisplayName(ULocale,ULocale) was not suppose to return an exception."); 1620 } 1621 } 1622 /* Tests the method 1623 * public static final String[] getKeywordValues(String keyword) 1624 */ 1625 @SuppressWarnings("static-access") 1626 @Test 1627 public void TestGetKeywordValues(){ 1628 // Tests when "if (!keyword.equals(KEYWORDS[0]))" is true 1629 String[] cases = {"","dummy"}; 1630 for(int i=0; i<cases.length; i++){ 1631 try{ 1632 Collator c = Collator.getInstance(); 1633 @SuppressWarnings("unused") 1634 String[] s = c.getKeywordValues(cases[i]); 1635 errln("Collator.getKeywordValues(String) is suppose to return " + 1636 "an exception for an invalid keyword."); 1637 } catch(Exception e){} 1638 } 1639 } 1640 1641 @Test 1642 public void TestBadKeywords() { 1643 // Test locale IDs with errors. 1644 // Valid locale IDs are tested via data-driven tests. 1645 // Note: ICU4C tests with a bogus Locale. There is no such thing in ICU4J. 1646 1647 // Unknown value. 1648 String localeID = "it-u-ks-xyz"; 1649 try { 1650 Collator.getInstance(new ULocale(localeID)); 1651 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1652 } catch(IllegalArgumentException expected) { 1653 } catch(Exception other) { 1654 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1655 } 1656 1657 // Unsupported attributes. 1658 localeID = "it@colHiraganaQuaternary=true"; 1659 try { 1660 Collator.getInstance(new ULocale(localeID)); 1661 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1662 } catch(UnsupportedOperationException expected) { 1663 } catch(Exception other) { 1664 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1665 } 1666 1667 localeID = "it-u-vt-u24"; 1668 try { 1669 Collator.getInstance(new ULocale(localeID)); 1670 errln("Collator.getInstance(" + localeID + ") did not fail as expected"); 1671 } catch(UnsupportedOperationException expected) { 1672 } catch(Exception other) { 1673 errln("Collator.getInstance(" + localeID + ") did not fail as expected - " + other); 1674 } 1675 } 1676 1677 @Test 1678 public void TestGapTooSmall() { 1679 // Try to tailor >20k characters into a too-small primary gap between symbols 1680 // that have 3-byte primary weights. 1681 // In FractionalUCA.txt: 1682 // 263A; [0C BA D0, 05, 05] # Zyyy So [084A.0020.0002] * WHITE SMILING FACE 1683 // 263B; [0C BA D7, 05, 05] # Zyyy So [084B.0020.0002] * BLACK SMILING FACE 1684 try { 1685 new RuleBasedCollator("&☺<*\u4E00-\u9FFF"); 1686 errln("no exception for primary-gap overflow"); 1687 } catch (UnsupportedOperationException e) { 1688 assertTrue("exception message mentions 'gap'", e.getMessage().contains("gap")); 1689 } catch (Exception e) { 1690 errln("unexpected exception for primary-gap overflow: " + e); 1691 } 1692 1693 // CLDR 32/ICU 60 FractionalUCA.txt makes room at the end of the symbols range 1694 // for several 2-byte primaries, or a large number of 3-byters. 1695 // The reset point is primary-before what should be 1696 // the special currency-first-primary contraction, 1697 // which is hopefully fairly stable, but not guaranteed stable. 1698 // In FractionalUCA.txt: 1699 // FDD1 20AC; [0D 70 02, 05, 05] # CURRENCY first primary 1700 try { 1701 Collator coll = new RuleBasedCollator("&[before 1]\uFDD1€<*\u4E00-\u9FFF"); 1702 assertTrue("tailored Han before currency", coll.compare("\u4E00", "$") < 0); 1703 } catch (Exception e) { 1704 errln("unexpected exception for tailoring many characters at the end of symbols: " + e); 1705 } 1706 } 1707 1708 @Test 1709 public void TestBogusLocaleID() { 1710 try { 1711 Collator c1 = Collator.getInstance(new ULocale("en-US-u-kn-true")); 1712 Collator c2 = Collator.getInstance(new ULocale("en_US-u-kn-true")); 1713 1714 assertTrue("Comparison using \"normal\" collator failed", c1.compare("2", "10") < 0); 1715 assertTrue("Comparison using \"bad\" collator failed", c2.compare("2", "10") < 0); 1716 } catch (Exception e) { 1717 errln("Exception creating collators: " + e); 1718 } 1719 } 1720 } 1721