1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2002-2016, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 */ 9 10 /** 11 * Port From: ICU4C v2.1 : cintltest 12 * Source File: $ICU4CRoot/source/test/cintltest/cmsccoll.c 13 */ 14 15 package com.ibm.icu.dev.test.collator; 16 17 import java.util.Arrays; 18 import java.util.Locale; 19 import java.util.Set; 20 import java.util.TreeSet; 21 22 import org.junit.Test; 23 import org.junit.runner.RunWith; 24 import org.junit.runners.JUnit4; 25 26 import com.ibm.icu.dev.test.TestFmwk; 27 import com.ibm.icu.impl.ICUData; 28 import com.ibm.icu.impl.ICUResourceBundle; 29 import com.ibm.icu.impl.Utility; 30 import com.ibm.icu.lang.UScript; 31 import com.ibm.icu.text.CollationElementIterator; 32 import com.ibm.icu.text.CollationKey; 33 import com.ibm.icu.text.CollationKey.BoundMode; 34 import com.ibm.icu.text.Collator; 35 import com.ibm.icu.text.Collator.ReorderCodes; 36 import com.ibm.icu.text.Normalizer; 37 import com.ibm.icu.text.RawCollationKey; 38 import com.ibm.icu.text.RuleBasedCollator; 39 import com.ibm.icu.text.UTF16; 40 import com.ibm.icu.text.UnicodeSet; 41 import com.ibm.icu.text.UnicodeSetIterator; 42 import com.ibm.icu.util.ULocale; 43 import com.ibm.icu.util.UResourceBundle; 44 45 @RunWith(JUnit4.class) 46 public class CollationMiscTest extends TestFmwk { 47 //private static final int NORM_BUFFER_TEST_LEN_ = 32; 48 private static final class Tester 49 { 50 int u; 51 String NFC; 52 String NFD; 53 } 54 55 private static final boolean hasCollationElements(Locale locale) 56 { 57 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_COLLATION_BASE_NAME,locale); 58 if (rb != null) { 59 try { 60 String collkey = rb.getStringWithFallback("collations/default"); 61 ICUResourceBundle elements = rb.getWithFallback("collations/" + collkey); 62 if (elements != null) { 63 return true; 64 } 65 } catch (Exception e) { 66 } 67 } 68 return false; 69 } 70 71 @Test 72 public void TestComposeDecompose() 73 { 74 Tester t[] = new Tester[0x30000]; 75 t[0] = new Tester(); 76 logln("Testing UCA extensively\n"); 77 RuleBasedCollator coll; 78 try { 79 coll = (RuleBasedCollator)Collator.getInstance(Locale.ENGLISH); 80 } 81 catch (Exception e) { 82 warnln("Error opening collator\n"); 83 return; 84 } 85 86 int noCases = 0; 87 for (int u = 0; u < 0x30000; u ++) { 88 String comp = UTF16.valueOf(u); 89 int len = comp.length(); 90 t[noCases].NFC = Normalizer.normalize(u, Normalizer.NFC); 91 t[noCases].NFD = Normalizer.normalize(u, Normalizer.NFD); 92 93 if (t[noCases].NFC.length() != t[noCases].NFD.length() 94 || (t[noCases].NFC.compareTo(t[noCases].NFD) != 0) 95 || (len != t[noCases].NFD.length()) 96 || (comp.compareTo(t[noCases].NFD) != 0)) { 97 t[noCases].u = u; 98 if (len != t[noCases].NFD.length() 99 || (comp.compareTo(t[noCases].NFD) != 0)) { 100 t[noCases].NFC = comp; 101 } 102 noCases ++; 103 t[noCases] = new Tester(); 104 } 105 } 106 107 for (int u = 0; u < noCases; u ++) { 108 if (!coll.equals(t[u].NFC, t[u].NFD)) { 109 errln("Failure: codePoint \\u" + Integer.toHexString(t[u].u) 110 + " fails TestComposeDecompose in the UCA"); 111 CollationTest.doTest(this, coll, t[u].NFC, t[u].NFD, 0); 112 } 113 } 114 115 logln("Testing locales, number of cases = " + noCases); 116 Locale loc[] = Collator.getAvailableLocales(); 117 for (int i = 0; i < loc.length; i ++) { 118 if (hasCollationElements(loc[i])) { 119 logln("Testing locale " + loc[i].getDisplayName()); 120 coll = (RuleBasedCollator)Collator.getInstance(loc[i]); 121 coll.setStrength(Collator.IDENTICAL); 122 123 for (int u = 0; u < noCases; u ++) { 124 if (!coll.equals(t[u].NFC, t[u].NFD)) { 125 errln("Failure: codePoint \\u" 126 + Integer.toHexString(t[u].u) 127 + " fails TestComposeDecompose for locale " 128 + loc[i].getDisplayName()); 129 // this tests for the iterators too 130 CollationTest.doTest(this, coll, t[u].NFC, t[u].NFD, 131 0); 132 } 133 } 134 } 135 } 136 } 137 138 @Test 139 public void TestRuleOptions() { 140 // values here are hardcoded and are correct for the current UCA when 141 // the UCA changes, one might be forced to change these values. 142 143 /* 144 * These strings contain the last character before [variable top] 145 * and the first and second characters (by primary weights) after it. 146 * See FractionalUCA.txt. For example: 147 [last variable [0C FE, 05, 05]] # U+10A7F OLD SOUTH ARABIAN NUMERIC INDICATOR 148 [variable top = 0C FE] 149 [first regular [0D 0A, 05, 05]] # U+0060 GRAVE ACCENT 150 and 151 00B4; [0D 0C, 05, 05] 152 * 153 * Note: Starting with UCA 6.0, the [variable top] collation element 154 * is not the weight of any character or string, 155 * which means that LAST_VARIABLE_CHAR_STRING sorts before [last variable]. 156 */ 157 String LAST_VARIABLE_CHAR_STRING = "\\U00010A7F"; 158 String FIRST_REGULAR_CHAR_STRING = "\\u0060"; 159 String SECOND_REGULAR_CHAR_STRING = "\\u00B4"; 160 161 /* 162 * This string has to match the character that has the [last regular] weight 163 * which changes with each UCA version. 164 * See the bottom of FractionalUCA.txt which says something like 165 [last regular [7A FE, 05, 05]] # U+1342E EGYPTIAN HIEROGLYPH AA032 166 * 167 * Note: Starting with UCA 6.0, the [last regular] collation element 168 * is not the weight of any character or string, 169 * which means that LAST_REGULAR_CHAR_STRING sorts before [last regular]. 170 */ 171 String LAST_REGULAR_CHAR_STRING = "\\U0001342E"; 172 173 String[] rules = { 174 // cannot test this anymore, as [last primary ignorable] doesn't 175 // have a code point associated to it anymore 176 // "&[before 3][last primary ignorable]<<<k", 177 // - all befores here amount to zero 178 /* "you cannot go before ...": The parser now sets an error for such nonsensical rules. 179 "&[before 3][first tertiary ignorable]<<<a", 180 "&[before 3][last tertiary ignorable]<<<a", */ 181 /* 182 * However, there is a real secondary ignorable (artificial addition in FractionalUCA.txt), 183 * and it *is* possible to "go before" that. 184 */ 185 "&[before 3][first secondary ignorable]<<<a", 186 "&[before 3][last secondary ignorable]<<<a", 187 // 'normal' befores 188 /* 189 * Note: With a "SPACE first primary" boundary CE in FractionalUCA.txt, 190 * it is not possible to tailor &[first primary ignorable]<a or &[last primary ignorable]<a 191 * because there is no tailoring space before that boundary. 192 * Made the tests work by tailoring to a space instead. 193 */ 194 "&[before 3][first primary ignorable]<<<c<<<b &' '<a", /* was &[first primary ignorable]<a */ 195 // we don't have a code point that corresponds to the last primary 196 // ignorable 197 "&[before 3][last primary ignorable]<<<c<<<b &' '<a", /* was &[last primary ignorable]<a */ 198 "&[before 3][first variable]<<<c<<<b &[first variable]<a", 199 "&[last variable]<a &[before 3][last variable]<<<c<<<b ", 200 "&[first regular]<a &[before 1][first regular]<b", 201 "&[before 1][last regular]<b &[last regular]<a", 202 "&[before 1][first implicit]<b &[first implicit]<a", 203 /* The current builder does not support tailoring to unassigned-implicit CEs (seems unnecessary, adds complexity). 204 "&[before 1][last implicit]<b &[last implicit]<a", */ 205 "&[last variable]<z" + 206 "&' '<x" + /* was &[last primary ignorable]<x, see above */ 207 "&[last secondary ignorable]<<y&[last tertiary ignorable]<<<w&[top]<u", 208 }; 209 String[][] data = { 210 // {"k", "\u20e3"}, 211 /* "you cannot go before ...": The parser now sets an error for such nonsensical rules. 212 {"\\u0000", "a"}, // you cannot go before first tertiary ignorable 213 {"\\u0000", "a"}, // you cannot go before last tertiary ignorable */ 214 /* 215 * However, there is a real secondary ignorable (artificial addition in FractionalUCA.txt), 216 * and it *is* possible to "go before" that. 217 */ 218 {"\\u0000", "a"}, 219 {"\\u0000", "a"}, 220 /* 221 * Note: With a "SPACE first primary" boundary CE in FractionalUCA.txt, 222 * it is not possible to tailor &[first primary ignorable]<a or &[last primary ignorable]<a 223 * because there is no tailoring space before that boundary. 224 * Made the tests work by tailoring to a space instead. 225 */ 226 {"c", "b", "\\u0332", "a"}, 227 {"\\u0332", "\\u20e3", "c", "b", "a"}, 228 {"c", "b", "\\u0009", "a", "\\u000a"}, 229 {LAST_VARIABLE_CHAR_STRING, "c", "b", /* [last variable] */ "a", FIRST_REGULAR_CHAR_STRING}, 230 {"b", FIRST_REGULAR_CHAR_STRING, "a", SECOND_REGULAR_CHAR_STRING}, 231 // The character in the second ordering test string 232 // has to match the character that has the [last regular] weight 233 // which changes with each UCA version. 234 // See the bottom of FractionalUCA.txt which says something like 235 // [last regular [CE 27, 05, 05]] # U+1342E EGYPTIAN HIEROGLYPH AA032 236 {LAST_REGULAR_CHAR_STRING, "b", /* [last regular] */ "a", "\\u4e00"}, 237 {"b", "\\u4e00", "a", "\\u4e01"}, 238 /* The current builder does not support tailoring to unassigned-implicit CEs (seems unnecessary, adds complexity). 239 {"b", "\\U0010FFFD", "a"}, */ 240 {"\ufffb", "w", "y", "\u20e3", "x", LAST_VARIABLE_CHAR_STRING, "z", "u"}, 241 }; 242 243 for (int i = 0; i< rules.length; i++) { 244 logln(String.format("rules[%d] = \"%s\"", i, rules[i])); 245 genericRulesStarter(rules[i], data[i]); 246 } 247 } 248 249 void genericRulesStarter(String rules, String[] s) { 250 genericRulesStarterWithResult(rules, s, -1); 251 } 252 253 void genericRulesStarterWithResult(String rules, String[] s, int result) { 254 255 RuleBasedCollator coll = null; 256 try { 257 coll = new RuleBasedCollator(rules); 258 // logln("Rules starter for " + rules); 259 genericOrderingTestWithResult(coll, s, result); 260 } catch (Exception e) { 261 warnln("Unable to open collator with rules " + rules + ": " + e); 262 } 263 } 264 265 void genericRulesStarterWithOptionsAndResult(String rules, String[] s, String[] atts, Object[] attVals, int result) { 266 RuleBasedCollator coll = null; 267 try { 268 coll = new RuleBasedCollator(rules); 269 genericOptionsSetter(coll, atts, attVals); 270 genericOrderingTestWithResult(coll, s, result); 271 } catch (Exception e) { 272 warnln("Unable to open collator with rules " + rules); 273 } 274 } 275 void genericOrderingTestWithResult(Collator coll, String[] s, int result) { 276 String t1 = ""; 277 String t2 = ""; 278 279 for(int i = 0; i < s.length - 1; i++) { 280 for(int j = i+1; j < s.length; j++) { 281 t1 = Utility.unescape(s[i]); 282 t2 = Utility.unescape(s[j]); 283 // System.out.println(i + " " + j); 284 CollationTest.doTest(this, (RuleBasedCollator)coll, t1, t2, 285 result); 286 } 287 } 288 } 289 290 void reportCResult(String source, String target, CollationKey sourceKey, CollationKey targetKey, 291 int compareResult, int keyResult, int incResult, int expectedResult ) { 292 if (expectedResult < -1 || expectedResult > 1) { 293 errln("***** invalid call to reportCResult ****"); 294 return; 295 } 296 boolean ok1 = (compareResult == expectedResult); 297 boolean ok2 = (keyResult == expectedResult); 298 boolean ok3 = (incResult == expectedResult); 299 if (ok1 && ok2 && ok3 /* synwee to undo && !isVerbose()*/) { 300 return; 301 } else { 302 String msg1 = ok1? "Ok: compare(\"" : "FAIL: compare(\""; 303 String msg2 = "\", \""; 304 String msg3 = "\") returned "; 305 String msg4 = "; expected "; 306 String sExpect = new String(""); 307 String sResult = new String(""); 308 sResult = CollationTest.appendCompareResult(compareResult, sResult); 309 sExpect = CollationTest.appendCompareResult(expectedResult, sExpect); 310 if (ok1) { 311 // logln(msg1 + source + msg2 + target + msg3 + sResult); 312 } else { 313 errln(msg1 + source + msg2 + target + msg3 + sResult + msg4 + sExpect); 314 } 315 msg1 = ok2 ? "Ok: key(\"" : "FAIL: key(\""; 316 msg2 = "\").compareTo(key(\""; 317 msg3 = "\")) returned "; 318 sResult = CollationTest.appendCompareResult(keyResult, sResult); 319 if (ok2) { 320 // logln(msg1 + source + msg2 + target + msg3 + sResult); 321 } else { 322 errln(msg1 + source + msg2 + target + msg3 + sResult + msg4 + sExpect); 323 msg1 = " "; 324 msg2 = " vs. "; 325 errln(msg1 + CollationTest.prettify(sourceKey) + msg2 + CollationTest.prettify(targetKey)); 326 } 327 msg1 = ok3 ? "Ok: incCompare(\"" : "FAIL: incCompare(\""; 328 msg2 = "\", \""; 329 msg3 = "\") returned "; 330 sResult = CollationTest.appendCompareResult(incResult, sResult); 331 if (ok3) { 332 // logln(msg1 + source + msg2 + target + msg3 + sResult); 333 } else { 334 errln(msg1 + source + msg2 + target + msg3 + sResult + msg4 + sExpect); 335 } 336 } 337 } 338 339 @Test 340 public void TestBeforePrefixFailure() { 341 String[] rules = { 342 "&g <<< a&[before 3]\uff41 <<< x", 343 "&\u30A7=\u30A7=\u3047=\uff6a&\u30A8=\u30A8=\u3048=\uff74&[before 3]\u30a7<<<\u30a9", 344 "&[before 3]\u30a7<<<\u30a9&\u30A7=\u30A7=\u3047=\uff6a&\u30A8=\u30A8=\u3048=\uff74", 345 }; 346 String[][] data = { 347 {"x", "\uff41"}, 348 {"\u30a9", "\u30a7"}, 349 {"\u30a9", "\u30a7"}, 350 }; 351 352 for(int i = 0; i< rules.length; i++) { 353 genericRulesStarter(rules[i], data[i]); 354 } 355 } 356 357 @Test 358 public void TestContractionClosure() { 359 // Note: This was also ported to the data-driven test, see collationtest.txt. 360 String[] rules = { 361 "&b=\u00e4\u00e4", 362 "&b=\u00C5", 363 }; 364 String[][] data = { 365 { "b", "\u00e4\u00e4", "a\u0308a\u0308", "\u00e4a\u0308", "a\u0308\u00e4" }, 366 { "b", "\u00C5", "A\u030A", "\u212B" }, 367 }; 368 369 for(int i = 0; i< rules.length; i++) { 370 genericRulesStarterWithResult(rules[i], data[i], 0); 371 } 372 } 373 374 @Test 375 public void TestPrefixCompose() { 376 String rule1 = "&\u30a7<<<\u30ab|\u30fc=\u30ac|\u30fc"; 377 378 String string = rule1; 379 try { 380 RuleBasedCollator coll = new RuleBasedCollator(string); 381 logln("rule:" + coll.getRules()); 382 } catch (Exception e) { 383 warnln("Error open RuleBasedCollator rule = " + string); 384 } 385 } 386 387 @Test 388 public void TestStrCollIdenticalPrefix() { 389 String rule = "&\ud9b0\udc70=\ud9b0\udc71"; 390 String test[] = { 391 "ab\ud9b0\udc70", 392 "ab\ud9b0\udc71" 393 }; 394 genericRulesStarterWithResult(rule, test, 0); 395 } 396 397 @Test 398 public void TestPrefix() { 399 String[] rules = { 400 "&z <<< z|a", 401 "&z <<< z| a", 402 "[strength I]&a=\ud900\udc25&z<<<\ud900\udc25|a", 403 }; 404 String[][] data = { 405 {"zz", "za"}, 406 {"zz", "za"}, 407 {"aa", "az", "\ud900\udc25z", "\ud900\udc25a", "zz"}, 408 }; 409 410 for(int i = 0; i<rules.length; i++) { 411 genericRulesStarter(rules[i], data[i]); 412 } 413 } 414 415 @Test 416 public void TestNewJapanese() { 417 418 String test1[] = { 419 "\u30b7\u30e3\u30fc\u30ec", 420 "\u30b7\u30e3\u30a4", 421 "\u30b7\u30e4\u30a3", 422 "\u30b7\u30e3\u30ec", 423 "\u3061\u3087\u3053", 424 "\u3061\u3088\u3053", 425 "\u30c1\u30e7\u30b3\u30ec\u30fc\u30c8", 426 "\u3066\u30fc\u305f", 427 "\u30c6\u30fc\u30bf", 428 "\u30c6\u30a7\u30bf", 429 "\u3066\u3048\u305f", 430 "\u3067\u30fc\u305f", 431 "\u30c7\u30fc\u30bf", 432 "\u30c7\u30a7\u30bf", 433 "\u3067\u3048\u305f", 434 "\u3066\u30fc\u305f\u30fc", 435 "\u30c6\u30fc\u30bf\u30a1", 436 "\u30c6\u30a7\u30bf\u30fc", 437 "\u3066\u3047\u305f\u3041", 438 "\u3066\u3048\u305f\u30fc", 439 "\u3067\u30fc\u305f\u30fc", 440 "\u30c7\u30fc\u30bf\u30a1", 441 "\u3067\u30a7\u305f\u30a1", 442 "\u30c7\u3047\u30bf\u3041", 443 "\u30c7\u30a8\u30bf\u30a2", 444 "\u3072\u3086", 445 "\u3073\u3085\u3042", 446 "\u3074\u3085\u3042", 447 "\u3073\u3085\u3042\u30fc", 448 "\u30d3\u30e5\u30a2\u30fc", 449 "\u3074\u3085\u3042\u30fc", 450 "\u30d4\u30e5\u30a2\u30fc", 451 "\u30d2\u30e5\u30a6", 452 "\u30d2\u30e6\u30a6", 453 "\u30d4\u30e5\u30a6\u30a2", 454 "\u3073\u3085\u30fc\u3042\u30fc", 455 "\u30d3\u30e5\u30fc\u30a2\u30fc", 456 "\u30d3\u30e5\u30a6\u30a2\u30fc", 457 "\u3072\u3085\u3093", 458 "\u3074\u3085\u3093", 459 "\u3075\u30fc\u308a", 460 "\u30d5\u30fc\u30ea", 461 "\u3075\u3045\u308a", 462 "\u3075\u30a5\u308a", 463 "\u3075\u30a5\u30ea", 464 "\u30d5\u30a6\u30ea", 465 "\u3076\u30fc\u308a", 466 "\u30d6\u30fc\u30ea", 467 "\u3076\u3045\u308a", 468 "\u30d6\u30a5\u308a", 469 "\u3077\u3046\u308a", 470 "\u30d7\u30a6\u30ea", 471 "\u3075\u30fc\u308a\u30fc", 472 "\u30d5\u30a5\u30ea\u30fc", 473 "\u3075\u30a5\u308a\u30a3", 474 "\u30d5\u3045\u308a\u3043", 475 "\u30d5\u30a6\u30ea\u30fc", 476 "\u3075\u3046\u308a\u3043", 477 "\u30d6\u30a6\u30ea\u30a4", 478 "\u3077\u30fc\u308a\u30fc", 479 "\u3077\u30a5\u308a\u30a4", 480 "\u3077\u3046\u308a\u30fc", 481 "\u30d7\u30a6\u30ea\u30a4", 482 "\u30d5\u30fd", 483 "\u3075\u309e", 484 "\u3076\u309d", 485 "\u3076\u3075", 486 "\u3076\u30d5", 487 "\u30d6\u3075", 488 "\u30d6\u30d5", 489 "\u3076\u309e", 490 "\u3076\u3077", 491 "\u30d6\u3077", 492 "\u3077\u309d", 493 "\u30d7\u30fd", 494 "\u3077\u3075", 495 }; 496 497 String test2[] = { 498 "\u306f\u309d", // H\u309d 499 "\u30cf\u30fd", // K\u30fd 500 "\u306f\u306f", // HH 501 "\u306f\u30cf", // HK 502 "\u30cf\u30cf", // KK 503 "\u306f\u309e", // H\u309e 504 "\u30cf\u30fe", // K\u30fe 505 "\u306f\u3070", // HH\u309b 506 "\u30cf\u30d0", // KK\u309b 507 "\u306f\u3071", // HH\u309c 508 "\u30cf\u3071", // KH\u309c 509 "\u30cf\u30d1", // KK\u309c 510 "\u3070\u309d", // H\u309b\u309d 511 "\u30d0\u30fd", // K\u309b\u30fd 512 "\u3070\u306f", // H\u309bH 513 "\u30d0\u30cf", // K\u309bK 514 "\u3070\u309e", // H\u309b\u309e 515 "\u30d0\u30fe", // K\u309b\u30fe 516 "\u3070\u3070", // H\u309bH\u309b 517 "\u30d0\u3070", // K\u309bH\u309b 518 "\u30d0\u30d0", // K\u309bK\u309b 519 "\u3070\u3071", // H\u309bH\u309c 520 "\u30d0\u30d1", // K\u309bK\u309c 521 "\u3071\u309d", // H\u309c\u309d 522 "\u30d1\u30fd", // K\u309c\u30fd 523 "\u3071\u306f", // H\u309cH 524 "\u30d1\u30cf", // K\u309cK 525 "\u3071\u3070", // H\u309cH\u309b 526 "\u3071\u30d0", // H\u309cK\u309b 527 "\u30d1\u30d0", // K\u309cK\u309b 528 "\u3071\u3071", // H\u309cH\u309c 529 "\u30d1\u30d1", // K\u309cK\u309c 530 }; 531 532 String[] att = { "strength", }; 533 Object[] val = { new Integer(Collator.QUATERNARY), }; 534 535 String[] attShifted = { "strength", "AlternateHandling"}; 536 Object valShifted[] = { new Integer(Collator.QUATERNARY), 537 Boolean.TRUE }; 538 539 genericLocaleStarterWithOptions(Locale.JAPANESE, test1, att, val); 540 genericLocaleStarterWithOptions(Locale.JAPANESE, test2, att, val); 541 542 genericLocaleStarterWithOptions(Locale.JAPANESE, test1, attShifted, 543 valShifted); 544 genericLocaleStarterWithOptions(Locale.JAPANESE, test2, attShifted, 545 valShifted); 546 } 547 548 void genericLocaleStarter(Locale locale, String s[]) { 549 RuleBasedCollator coll = null; 550 try { 551 coll = (RuleBasedCollator)Collator.getInstance(locale); 552 553 } catch (Exception e) { 554 warnln("Unable to open collator for locale " + locale); 555 return; 556 } 557 // logln("Locale starter for " + locale); 558 genericOrderingTest(coll, s); 559 } 560 561 void genericLocaleStarterWithOptions(Locale locale, String[] s, String[] attrs, Object[] values) { 562 genericLocaleStarterWithOptionsAndResult(locale, s, attrs, values, -1); 563 } 564 565 private void genericOptionsSetter(RuleBasedCollator coll, String[] attrs, Object[] values) { 566 for(int i = 0; i < attrs.length; i++) { 567 if (attrs[i].equals("strength")) { 568 coll.setStrength(((Integer)values[i]).intValue()); 569 } 570 else if (attrs[i].equals("decomp")) { 571 coll.setDecomposition(((Integer)values[i]).intValue()); 572 } 573 else if (attrs[i].equals("AlternateHandling")) { 574 coll.setAlternateHandlingShifted(((Boolean)values[i] 575 ).booleanValue()); 576 } 577 else if (attrs[i].equals("NumericCollation")) { 578 coll.setNumericCollation(((Boolean)values[i]).booleanValue()); 579 } 580 else if (attrs[i].equals("UpperFirst")) { 581 coll.setUpperCaseFirst(((Boolean)values[i]).booleanValue()); 582 } 583 else if (attrs[i].equals("LowerFirst")) { 584 coll.setLowerCaseFirst(((Boolean)values[i]).booleanValue()); 585 } 586 else if (attrs[i].equals("CaseLevel")) { 587 coll.setCaseLevel(((Boolean)values[i]).booleanValue()); 588 } 589 } 590 } 591 592 void genericLocaleStarterWithOptionsAndResult(Locale locale, String[] s, String[] attrs, Object[] values, int result) { 593 RuleBasedCollator coll = null; 594 try { 595 coll = (RuleBasedCollator)Collator.getInstance(locale); 596 } catch (Exception e) { 597 warnln("Unable to open collator for locale " + locale); 598 return; 599 } 600 // logln("Locale starter for " +locale); 601 602 // logln("Setting attributes"); 603 genericOptionsSetter(coll, attrs, values); 604 605 genericOrderingTestWithResult(coll, s, result); 606 } 607 608 void genericOrderingTest(Collator coll, String[] s) { 609 genericOrderingTestWithResult(coll, s, -1); 610 } 611 612 @Test 613 public void TestNonChars() { 614 String test[] = { 615 "\u0000", /* ignorable */ 616 "\uFFFE", /* special merge-sort character with minimum non-ignorable weights */ 617 "\uFDD0", "\uFDEF", 618 "\\U0001FFFE", "\\U0001FFFF", /* UCA 6.0: noncharacters are treated like unassigned, */ 619 "\\U0002FFFE", "\\U0002FFFF", /* not like ignorable. */ 620 "\\U0003FFFE", "\\U0003FFFF", 621 "\\U0004FFFE", "\\U0004FFFF", 622 "\\U0005FFFE", "\\U0005FFFF", 623 "\\U0006FFFE", "\\U0006FFFF", 624 "\\U0007FFFE", "\\U0007FFFF", 625 "\\U0008FFFE", "\\U0008FFFF", 626 "\\U0009FFFE", "\\U0009FFFF", 627 "\\U000AFFFE", "\\U000AFFFF", 628 "\\U000BFFFE", "\\U000BFFFF", 629 "\\U000CFFFE", "\\U000CFFFF", 630 "\\U000DFFFE", "\\U000DFFFF", 631 "\\U000EFFFE", "\\U000EFFFF", 632 "\\U000FFFFE", "\\U000FFFFF", 633 "\\U0010FFFE", "\\U0010FFFF", 634 "\uFFFF" /* special character with maximum primary weight */ 635 }; 636 Collator coll = null; 637 try { 638 coll = Collator.getInstance(new Locale("en", "US")); 639 } catch (Exception e) { 640 warnln("Unable to open collator"); 641 return; 642 } 643 // logln("Test non characters"); 644 645 genericOrderingTestWithResult(coll, test, -1); 646 } 647 648 @Test 649 public void TestExtremeCompression() { 650 String[] test = new String[4]; 651 652 for(int i = 0; i<4; i++) { 653 StringBuffer temp = new StringBuffer(); 654 for (int j = 0; j < 2047; j++) { 655 temp.append('a'); 656 } 657 temp.append((char)('a' + i)); 658 test[i] = temp.toString(); 659 } 660 661 genericLocaleStarter(new Locale("en", "US"), test); 662 } 663 664 /** 665 * Tests surrogate support. 666 */ 667 @Test 668 public void TestSurrogates() { 669 String test[] = {"z","\ud900\udc25", "\ud805\udc50", "\ud800\udc00y", 670 "\ud800\udc00r", "\ud800\udc00f", "\ud800\udc00", 671 "\ud800\udc00c", "\ud800\udc00b", "\ud800\udc00fa", 672 "\ud800\udc00fb", "\ud800\udc00a", "c", "b"}; 673 674 String rule = "&z < \ud900\udc25 < \ud805\udc50 < \ud800\udc00y " 675 + "< \ud800\udc00r < \ud800\udc00f << \ud800\udc00 " 676 + "< \ud800\udc00fa << \ud800\udc00fb < \ud800\udc00a " 677 + "< c < b"; 678 genericRulesStarter(rule, test); 679 } 680 681 @Test 682 public void TestBocsuCoverage() { 683 String test = "\u0041\u0441\u4441\\U00044441\u4441\u0441\u0041"; 684 Collator coll = Collator.getInstance(); 685 coll.setStrength(Collator.IDENTICAL); 686 CollationKey key = coll.getCollationKey(test); 687 logln("source:" + key.getSourceString()); 688 } 689 690 @Test 691 public void TestCyrillicTailoring() { 692 String test[] = { 693 "\u0410b", 694 "\u0410\u0306a", 695 "\u04d0A" 696 }; 697 698 // Most of the following are commented out because UCA 8.0 699 // drops most of the Cyrillic contractions from the default order. 700 // See CLDR ticket #7246 "root collation: remove Cyrillic contractions". 701 702 // genericLocaleStarter(new Locale("en", ""), test); 703 // genericRulesStarter("&\u0410 = \u0410", test); 704 // genericRulesStarter("&Z < \u0410", test); 705 genericRulesStarter("&\u0410 = \u0410 < \u04d0", test); 706 genericRulesStarter("&Z < \u0410 < \u04d0", test); 707 // genericRulesStarter("&\u0410 = \u0410 < \u0410\u0301", test); 708 // genericRulesStarter("&Z < \u0410 < \u0410\u0301", test); 709 } 710 711 @Test 712 public void TestSuppressContractions() { 713 String testNoCont2[] = { 714 "\u0410\u0302a", 715 "\u0410\u0306b", 716 "\u0410c" 717 }; 718 String testNoCont[] = { 719 "a\u0410", 720 "A\u0410\u0306", 721 "\uFF21\u0410\u0302" 722 }; 723 724 genericRulesStarter("[suppressContractions [\u0400-\u047f]]", testNoCont); 725 genericRulesStarter("[suppressContractions [\u0400-\u047f]]", testNoCont2); 726 } 727 728 @Test 729 public void TestCase() { 730 String gRules = "\u0026\u0030\u003C\u0031\u002C\u2460\u003C\u0061\u002C\u0041"; 731 String[] testCase = { 732 "1a", "1A", "\u2460a", "\u2460A" 733 }; 734 int[][] caseTestResults = { 735 { -1, -1, -1, 0, -1, -1, 0, 0, -1 }, 736 { 1, -1, -1, 0, -1, -1, 0, 0, 1 }, 737 { -1, -1, -1, 0, 1, -1, 0, 0, -1 }, 738 { 1, -1, 1, 0, -1, -1, 0, 0, 1 } 739 740 }; 741 boolean[][] caseTestAttributes = { 742 { false, false}, 743 { true, false}, 744 { false, true}, 745 { true, true} 746 }; 747 748 int i,j,k; 749 Collator myCollation; 750 try { 751 myCollation = Collator.getInstance(new Locale("en", "US")); 752 } catch (Exception e) { 753 warnln("ERROR: in creation of rule based collator "); 754 return; 755 } 756 // logln("Testing different case settings"); 757 myCollation.setStrength(Collator.TERTIARY); 758 759 for(k = 0; k <4; k++) { 760 if (caseTestAttributes[k][0] == true) { 761 // upper case first 762 ((RuleBasedCollator)myCollation).setUpperCaseFirst(true); 763 } 764 else { 765 // upper case first 766 ((RuleBasedCollator)myCollation).setLowerCaseFirst(true); 767 } 768 ((RuleBasedCollator)myCollation).setCaseLevel( 769 caseTestAttributes[k][1]); 770 771 // logln("Case first = " + caseTestAttributes[k][0] + ", Case level = " + caseTestAttributes[k][1]); 772 for (i = 0; i < 3 ; i++) { 773 for(j = i+1; j<4; j++) { 774 CollationTest.doTest(this, 775 (RuleBasedCollator)myCollation, 776 testCase[i], testCase[j], 777 caseTestResults[k][3*i+j-1]); 778 } 779 } 780 } 781 try { 782 myCollation = new RuleBasedCollator(gRules); 783 } catch (Exception e) { 784 warnln("ERROR: in creation of rule based collator"); 785 return; 786 } 787 // logln("Testing different case settings with custom rules"); 788 myCollation.setStrength(Collator.TERTIARY); 789 790 for(k = 0; k<4; k++) { 791 if (caseTestAttributes[k][0] == true) { 792 ((RuleBasedCollator)myCollation).setUpperCaseFirst(true); 793 } 794 else { 795 ((RuleBasedCollator)myCollation).setUpperCaseFirst(false); 796 } 797 ((RuleBasedCollator)myCollation).setCaseLevel( 798 caseTestAttributes[k][1]); 799 for (i = 0; i < 3 ; i++) { 800 for(j = i+1; j<4; j++) { 801 CollationTest.doTest(this, 802 (RuleBasedCollator)myCollation, 803 testCase[i], testCase[j], 804 caseTestResults[k][3*i+j-1]); 805 } 806 } 807 } 808 809 { 810 String[] lowerFirst = { 811 "h", 812 "H", 813 "ch", 814 "Ch", 815 "CH", 816 "cha", 817 "chA", 818 "Cha", 819 "ChA", 820 "CHa", 821 "CHA", 822 "i", 823 "I" 824 }; 825 826 String[] upperFirst = { 827 "H", 828 "h", 829 "CH", 830 "Ch", 831 "ch", 832 "CHA", 833 "CHa", 834 "ChA", 835 "Cha", 836 "chA", 837 "cha", 838 "I", 839 "i" 840 }; 841 // logln("mixed case test"); 842 // logln("lower first, case level off"); 843 genericRulesStarter("[caseFirst lower]&H<ch<<<Ch<<<CH", lowerFirst); 844 // logln("upper first, case level off"); 845 genericRulesStarter("[caseFirst upper]&H<ch<<<Ch<<<CH", upperFirst); 846 // logln("lower first, case level on"); 847 genericRulesStarter("[caseFirst lower][caseLevel on]&H<ch<<<Ch<<<CH", lowerFirst); 848 // logln("upper first, case level on"); 849 genericRulesStarter("[caseFirst upper][caseLevel on]&H<ch<<<Ch<<<CH", upperFirst); 850 } 851 } 852 853 @Test 854 public void TestIncompleteCnt() { 855 String[] cnt1 = { 856 "AA", 857 "AC", 858 "AZ", 859 "AQ", 860 "AB", 861 "ABZ", 862 "ABQ", 863 "Z", 864 "ABC", 865 "Q", 866 "B" 867 }; 868 869 String[] cnt2 = { 870 "DA", 871 "DAD", 872 "DAZ", 873 "MAR", 874 "Z", 875 "DAVIS", 876 "MARK", 877 "DAV", 878 "DAVI" 879 }; 880 RuleBasedCollator coll = null; 881 String temp = " & Z < ABC < Q < B"; 882 try { 883 coll = new RuleBasedCollator(temp); 884 } catch (Exception e) { 885 warnln("fail to create RuleBasedCollator"); 886 return; 887 } 888 889 int size = cnt1.length; 890 for(int i = 0; i < size-1; i++) { 891 for(int j = i+1; j < size; j++) { 892 String t1 = cnt1[i]; 893 String t2 = cnt1[j]; 894 CollationTest.doTest(this, coll, t1, t2, -1); 895 } 896 } 897 898 temp = " & Z < DAVIS < MARK <DAV"; 899 try { 900 coll = new RuleBasedCollator(temp); 901 } catch (Exception e) { 902 warnln("fail to create RuleBasedCollator"); 903 return; 904 } 905 906 size = cnt2.length; 907 for(int i = 0; i < size-1; i++) { 908 for(int j = i+1; j < size; j++) { 909 String t1 = cnt2[i]; 910 String t2 = cnt2[j]; 911 CollationTest.doTest(this, coll, t1, t2, -1); 912 } 913 } 914 } 915 916 @Test 917 public void TestBlackBird() { 918 String[] shifted = { 919 "black bird", 920 "black-bird", 921 "blackbird", 922 "black Bird", 923 "black-Bird", 924 "blackBird", 925 "black birds", 926 "black-birds", 927 "blackbirds" 928 }; 929 int[] shiftedTert = { 930 0, 931 0, 932 0, 933 -1, 934 0, 935 0, 936 -1, 937 0, 938 0 939 }; 940 String[] nonignorable = { 941 "black bird", 942 "black Bird", 943 "black birds", 944 "black-bird", 945 "black-Bird", 946 "black-birds", 947 "blackbird", 948 "blackBird", 949 "blackbirds" 950 }; 951 int i = 0, j = 0; 952 int size = 0; 953 Collator coll = Collator.getInstance(new Locale("en", "US")); 954 //ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); 955 //ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status); 956 ((RuleBasedCollator)coll).setAlternateHandlingShifted(false); 957 size = nonignorable.length; 958 for(i = 0; i < size-1; i++) { 959 for(j = i+1; j < size; j++) { 960 String t1 = nonignorable[i]; 961 String t2 = nonignorable[j]; 962 CollationTest.doTest(this, (RuleBasedCollator)coll, t1, t2, -1); 963 } 964 } 965 ((RuleBasedCollator)coll).setAlternateHandlingShifted(true); 966 coll.setStrength(Collator.QUATERNARY); 967 size = shifted.length; 968 for(i = 0; i < size-1; i++) { 969 for(j = i+1; j < size; j++) { 970 String t1 = shifted[i]; 971 String t2 = shifted[j]; 972 CollationTest.doTest(this, (RuleBasedCollator)coll, t1, t2, -1); 973 } 974 } 975 coll.setStrength(Collator.TERTIARY); 976 size = shifted.length; 977 for(i = 1; i < size; i++) { 978 String t1 = shifted[i-1]; 979 String t2 = shifted[i]; 980 CollationTest.doTest(this, (RuleBasedCollator)coll, t1, t2, 981 shiftedTert[i]); 982 } 983 } 984 985 @Test 986 public void TestFunkyA() { 987 String[] testSourceCases = { 988 "\u0041\u0300\u0301", 989 "\u0041\u0300\u0316", 990 "\u0041\u0300", 991 "\u00C0\u0301", 992 // this would work with forced normalization 993 "\u00C0\u0316", 994 }; 995 996 String[] testTargetCases = { 997 "\u0041\u0301\u0300", 998 "\u0041\u0316\u0300", 999 "\u00C0", 1000 "\u0041\u0301\u0300", 1001 // this would work with forced normalization 1002 "\u0041\u0316\u0300", 1003 }; 1004 1005 int[] results = { 1006 1, 1007 0, 1008 0, 1009 1, 1010 0 1011 }; 1012 1013 Collator myCollation; 1014 try { 1015 myCollation = Collator.getInstance(new Locale("en", "US")); 1016 } catch (Exception e) { 1017 warnln("ERROR: in creation of rule based collator"); 1018 return; 1019 } 1020 // logln("Testing some A letters, for some reason"); 1021 myCollation.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 1022 myCollation.setStrength(Collator.TERTIARY); 1023 for (int i = 0; i < 4 ; i++) 1024 { 1025 CollationTest.doTest(this, (RuleBasedCollator)myCollation, 1026 testSourceCases[i], testTargetCases[i], 1027 results[i]); 1028 } 1029 } 1030 1031 @Test 1032 public void TestChMove() { 1033 String[] chTest = { 1034 "c", 1035 "C", 1036 "ca", "cb", "cx", "cy", "CZ", 1037 "c\u030C", "C\u030C", 1038 "h", 1039 "H", 1040 "ha", "Ha", "harly", "hb", "HB", "hx", "HX", "hy", "HY", 1041 "ch", "cH", "Ch", "CH", 1042 "cha", "charly", "che", "chh", "chch", "chr", 1043 "i", "I", "iarly", 1044 "r", "R", 1045 "r\u030C", "R\u030C", 1046 "s", 1047 "S", 1048 "s\u030C", "S\u030C", 1049 "z", "Z", 1050 "z\u030C", "Z\u030C" 1051 }; 1052 Collator coll = null; 1053 try { 1054 coll = Collator.getInstance(new Locale("cs", "")); 1055 } catch (Exception e) { 1056 warnln("Cannot create Collator"); 1057 return; 1058 } 1059 int size = chTest.length; 1060 for(int i = 0; i < size-1; i++) { 1061 for(int j = i+1; j < size; j++) { 1062 String t1 = chTest[i]; 1063 String t2 = chTest[j]; 1064 CollationTest.doTest(this, (RuleBasedCollator)coll, t1, t2, -1); 1065 } 1066 } 1067 } 1068 1069 @Test 1070 public void TestImplicitTailoring() { 1071 String rules[] = { 1072 /* Tailor b and c before U+4E00. */ 1073 "&[before 1]\u4e00 < b < c " + 1074 /* Now, before U+4E00 is c; put d and e after that. */ 1075 "&[before 1]\u4e00 < d < e", 1076 "&\u4e00 < a <<< A < b <<< B", 1077 "&[before 1]\u4e00 < \u4e01 < \u4e02", 1078 "&[before 1]\u4e01 < \u4e02 < \u4e03", 1079 }; 1080 String cases[][] = { 1081 { "b", "c", "d", "e", "\u4e00" }, 1082 { "\u4e00", "a", "A", "b", "B", "\u4e01" }, 1083 { "\u4e01", "\u4e02", "\u4e00" }, 1084 { "\u4e02", "\u4e03", "\u4e01" }, 1085 }; 1086 1087 int i = 0; 1088 1089 for(i = 0; i < rules.length; i++) { 1090 genericRulesStarter(rules[i], cases[i]); 1091 } 1092 } 1093 1094 @Test 1095 public void TestFCDProblem() { 1096 String s1 = "\u0430\u0306\u0325"; 1097 String s2 = "\u04D1\u0325"; 1098 Collator coll = null; 1099 try { 1100 coll = Collator.getInstance(); 1101 } catch (Exception e) { 1102 warnln("Can't create collator"); 1103 return; 1104 } 1105 1106 coll.setDecomposition(Collator.NO_DECOMPOSITION); 1107 CollationTest.doTest(this, (RuleBasedCollator)coll, s1, s2, 0); 1108 coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 1109 CollationTest.doTest(this, (RuleBasedCollator)coll, s1, s2, 0); 1110 } 1111 1112 @Test 1113 public void TestEmptyRule() { 1114 String rulez = ""; 1115 try { 1116 RuleBasedCollator coll = new RuleBasedCollator(rulez); 1117 logln("rule:" + coll.getRules()); 1118 } catch (Exception e) { 1119 warnln(e.getMessage()); 1120 } 1121 } 1122 1123 /* superseded by TestBeforePinyin, since Chinese collation rules have changed */ 1124 /* 1125 @Test 1126 public void TestJ784() { 1127 String[] data = { 1128 "A", "\u0101", "\u00e1", "\u01ce", "\u00e0", 1129 "E", "\u0113", "\u00e9", "\u011b", "\u00e8", 1130 "I", "\u012b", "\u00ed", "\u01d0", "\u00ec", 1131 "O", "\u014d", "\u00f3", "\u01d2", "\u00f2", 1132 "U", "\u016b", "\u00fa", "\u01d4", "\u00f9", 1133 "\u00fc", "\u01d6", "\u01d8", "\u01da", "\u01dc" 1134 }; 1135 genericLocaleStarter(new Locale("zh", ""), data); 1136 } 1137 */ 1138 1139 @Test 1140 public void TestJ815() { 1141 String data[] = { 1142 "aa", 1143 "Aa", 1144 "ab", 1145 "Ab", 1146 "ad", 1147 "Ad", 1148 "ae", 1149 "Ae", 1150 "\u00e6", 1151 "\u00c6", 1152 "af", 1153 "Af", 1154 "b", 1155 "B" 1156 }; 1157 genericLocaleStarter(new Locale("fr", ""), data); 1158 genericRulesStarter("[backwards 2]&A<<\u00e6/e<<<\u00c6/E", data); 1159 } 1160 1161 @Test 1162 public void TestJ3087() 1163 { 1164 String rule[] = { 1165 "&h<H&CH=\u0427", 1166 /* 1167 * The ICU 53 builder adheres to the principle that 1168 * a rule is affected by previous rules but not following ones. 1169 * Therefore, setting CH=\u0427 and then re-tailoring H makes CH != \u0427. 1170 "&CH=\u0427&h<H", */ 1171 "&CH=\u0427" 1172 }; 1173 RuleBasedCollator rbc = null; 1174 CollationElementIterator iter1; 1175 CollationElementIterator iter2; 1176 for (int i = 0; i < rule.length; i ++) { 1177 try { 1178 rbc = new RuleBasedCollator(rule[i]); 1179 } catch (Exception e) { 1180 warnln(e.getMessage()); 1181 continue; 1182 } 1183 iter1 = rbc.getCollationElementIterator("CH"); 1184 iter2 = rbc.getCollationElementIterator("\u0427"); 1185 int ce1 = CollationElementIterator.IGNORABLE; 1186 int ce2 = CollationElementIterator.IGNORABLE; 1187 // The ICU 53 builder code sets the uppercase flag only on the first CE. 1188 int mask = ~0; 1189 while (ce1 != CollationElementIterator.NULLORDER 1190 && ce2 != CollationElementIterator.NULLORDER) { 1191 ce1 = iter1.next(); 1192 ce2 = iter2.next(); 1193 if ((ce1 & mask) != (ce2 & mask)) { 1194 errln("Error generating RuleBasedCollator with the rule " 1195 + rule[i]); 1196 errln("CH != \\u0427"); 1197 } 1198 mask = ~0xc0; // mask off case/continuation bits 1199 } 1200 } 1201 } 1202 1203 @Test 1204 public void TestUpperCaseFirst() { 1205 String[] data = { 1206 "I", 1207 "i", 1208 "Y", 1209 "y" 1210 }; 1211 genericLocaleStarter(new Locale("da", ""), data); 1212 } 1213 1214 @Test 1215 public void TestBefore() { 1216 String data[] = { 1217 "\u0101", "\u00e1", "\u01ce", "\u00e0", "A", 1218 "\u0113", "\u00e9", "\u011b", "\u00e8", "E", 1219 "\u012b", "\u00ed", "\u01d0", "\u00ec", "I", 1220 "\u014d", "\u00f3", "\u01d2", "\u00f2", "O", 1221 "\u016b", "\u00fa", "\u01d4", "\u00f9", "U", 1222 "\u01d6", "\u01d8", "\u01da", "\u01dc", "\u00fc" 1223 }; 1224 genericRulesStarter( 1225 "&[before 1]a<\u0101<\u00e1<\u01ce<\u00e0" 1226 + "&[before 1]e<\u0113<\u00e9<\u011b<\u00e8" 1227 + "&[before 1]i<\u012b<\u00ed<\u01d0<\u00ec" 1228 + "&[before 1]o<\u014d<\u00f3<\u01d2<\u00f2" 1229 + "&[before 1]u<\u016b<\u00fa<\u01d4<\u00f9" 1230 + "&u<\u01d6<\u01d8<\u01da<\u01dc<\u00fc", data); 1231 } 1232 1233 @Test 1234 public void TestHangulTailoring() { 1235 String[] koreanData = { 1236 "\uac00", "\u4f3d", "\u4f73", "\u5047", "\u50f9", "\u52a0", "\u53ef", "\u5475", 1237 "\u54e5", "\u5609", "\u5ac1", "\u5bb6", "\u6687", "\u67b6", "\u67b7", "\u67ef", 1238 "\u6b4c", "\u73c2", "\u75c2", "\u7a3c", "\u82db", "\u8304", "\u8857", "\u8888", 1239 "\u8a36", "\u8cc8", "\u8dcf", "\u8efb", "\u8fe6", "\u99d5", 1240 "\u4EEE", "\u50A2", "\u5496", "\u54FF", "\u5777", "\u5B8A", "\u659D", "\u698E", 1241 "\u6A9F", "\u73C8", "\u7B33", "\u801E", "\u8238", "\u846D", "\u8B0C" 1242 }; 1243 1244 String rules = 1245 "&\uac00 <<< \u4f3d <<< \u4f73 <<< \u5047 <<< \u50f9 <<< \u52a0 <<< \u53ef <<< \u5475 " 1246 + "<<< \u54e5 <<< \u5609 <<< \u5ac1 <<< \u5bb6 <<< \u6687 <<< \u67b6 <<< \u67b7 <<< \u67ef " 1247 + "<<< \u6b4c <<< \u73c2 <<< \u75c2 <<< \u7a3c <<< \u82db <<< \u8304 <<< \u8857 <<< \u8888 " 1248 + "<<< \u8a36 <<< \u8cc8 <<< \u8dcf <<< \u8efb <<< \u8fe6 <<< \u99d5 " 1249 + "<<< \u4EEE <<< \u50A2 <<< \u5496 <<< \u54FF <<< \u5777 <<< \u5B8A <<< \u659D <<< \u698E " 1250 + "<<< \u6A9F <<< \u73C8 <<< \u7B33 <<< \u801E <<< \u8238 <<< \u846D <<< \u8B0C"; 1251 1252 String rlz = rules; 1253 1254 Collator coll = null; 1255 try { 1256 coll = new RuleBasedCollator(rlz); 1257 } catch (Exception e) { 1258 warnln("Unable to open collator with rules" + rules); 1259 return; 1260 } 1261 // logln("Using start of korean rules\n"); 1262 genericOrderingTest(coll, koreanData); 1263 1264 // no such locale in icu4j 1265 // logln("Using ko__LOTUS locale\n"); 1266 // genericLocaleStarter(new Locale("ko__LOTUS", ""), koreanData); 1267 } 1268 1269 @Test 1270 public void TestIncrementalNormalize() { 1271 Collator coll = null; 1272 // logln("Test 1 ...."); 1273 { 1274 /* Test 1. Run very long unnormalized strings, to force overflow of*/ 1275 /* most buffers along the way.*/ 1276 1277 try { 1278 coll = Collator.getInstance(new Locale("en", "US")); 1279 } catch (Exception e) { 1280 warnln("Cannot get default instance!"); 1281 return; 1282 } 1283 char baseA =0x41; 1284 char ccMix[] = {0x316, 0x321, 0x300}; 1285 int sLen; 1286 int i; 1287 StringBuffer strA = new StringBuffer(); 1288 StringBuffer strB = new StringBuffer(); 1289 1290 coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 1291 1292 for (sLen = 1000; sLen<1001; sLen++) { 1293 strA.delete(0, strA.length()); 1294 strA.append(baseA); 1295 strB.delete(0, strB.length()); 1296 strB.append(baseA); 1297 for (i=1; i< sLen; i++) { 1298 strA.append(ccMix[i % 3]); 1299 strB.insert(1, ccMix[i % 3]); 1300 } 1301 coll.setStrength(Collator.TERTIARY); // Do test with default strength, which runs 1302 CollationTest.doTest(this, (RuleBasedCollator)coll, 1303 strA.toString(), strB.toString(), 0); // optimized functions in the impl 1304 coll.setStrength(Collator.IDENTICAL); // Do again with the slow, general impl. 1305 CollationTest.doTest(this, (RuleBasedCollator)coll, 1306 strA.toString(), strB.toString(), 0); 1307 } 1308 } 1309 /* Test 2: Non-normal sequence in a string that extends to the last character*/ 1310 /* of the string. Checks a couple of edge cases.*/ 1311 // logln("Test 2 ...."); 1312 { 1313 String strA = "AA\u0300\u0316"; 1314 String strB = "A\u00c0\u0316"; 1315 coll.setStrength(Collator.TERTIARY); 1316 CollationTest.doTest(this, (RuleBasedCollator)coll, strA, strB, 0); 1317 } 1318 /* Test 3: Non-normal sequence is terminated by a surrogate pair.*/ 1319 // logln("Test 3 ...."); 1320 { 1321 String strA = "AA\u0300\u0316\uD800\uDC01"; 1322 String strB = "A\u00c0\u0316\uD800\uDC00"; 1323 coll.setStrength(Collator.TERTIARY); 1324 CollationTest.doTest(this, (RuleBasedCollator)coll, strA, strB, 1); 1325 } 1326 /* Test 4: Imbedded nulls do not terminate a string when length is specified.*/ 1327 // logln("Test 4 ...."); 1328 /* 1329 * not a valid test since string are null-terminated in java{ 1330 char strA[] = {0x41, 0x00, 0x42}; 1331 char strB[] = {0x41, 0x00, 0x00}; 1332 1333 int result = coll.compare(new String(strA), new String(strB)); 1334 if (result != 1) { 1335 errln("ERROR 1 in test 4\n"); 1336 } 1337 1338 result = coll.compare(new String(strA, 0, 1), new String(strB, 0, 1)); 1339 if (result != 0) { 1340 errln("ERROR 1 in test 4\n"); 1341 } 1342 1343 CollationKey sortKeyA = coll.getCollationKey(new String(strA)); 1344 CollationKey sortKeyB = coll.getCollationKey(new String(strB)); 1345 1346 int r = sortKeyA.compareTo(sortKeyB); 1347 if (r <= 0) { 1348 errln("Error 4 in test 4\n"); 1349 } 1350 1351 coll.setStrength(Collator.IDENTICAL); 1352 sortKeyA = coll.getCollationKey(new String(strA)); 1353 sortKeyB = coll.getCollationKey(new String(strB)); 1354 1355 r = sortKeyA.compareTo(sortKeyB); 1356 if (r <= 0) { 1357 errln("Error 7 in test 4\n"); 1358 } 1359 1360 coll.setStrength(Collator.TERTIARY); 1361 } 1362 */ 1363 /* Test 5: Null characters in non-normal source strings.*/ 1364 // logln("Test 5 ...."); 1365 /* 1366 * not a valid test since string are null-terminated in java{ 1367 { 1368 char strA[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x42,}; 1369 char strB[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x00,}; 1370 1371 1372 int result = coll.compare(new String(strA, 0, 6), new String(strB, 0, 6)); 1373 if (result < 0) { 1374 errln("ERROR 1 in test 5\n"); 1375 } 1376 result = coll.compare(new String(strA, 0, 4), new String(strB, 0, 4)); 1377 if (result != 0) { 1378 errln("ERROR 2 in test 5\n"); 1379 } 1380 1381 CollationKey sortKeyA = coll.getCollationKey(new String(strA)); 1382 CollationKey sortKeyB = coll.getCollationKey(new String(strB)); 1383 int r = sortKeyA.compareTo(sortKeyB); 1384 if (r <= 0) { 1385 errln("Error 4 in test 5\n"); 1386 } 1387 1388 coll.setStrength(Collator.IDENTICAL); 1389 1390 sortKeyA = coll.getCollationKey(new String(strA)); 1391 sortKeyB = coll.getCollationKey(new String(strB)); 1392 r = sortKeyA.compareTo(sortKeyB); 1393 if (r <= 0) { 1394 errln("Error 7 in test 5\n"); 1395 } 1396 1397 coll.setStrength(Collator.TERTIARY); 1398 } 1399 */ 1400 /* Test 6: Null character as base of a non-normal combining sequence.*/ 1401 // logln("Test 6 ...."); 1402 /* 1403 * not a valid test since string are null-terminated in java{ 1404 { 1405 char strA[] = {0x41, 0x0, 0x300, 0x316, 0x41, 0x302,}; 1406 char strB[] = {0x41, 0x0, 0x302, 0x316, 0x41, 0x300,}; 1407 1408 int result = coll.compare(new String(strA, 0, 5), new String(strB, 0, 5)); 1409 if (result != -1) { 1410 errln("Error 1 in test 6\n"); 1411 } 1412 result = coll.compare(new String(strA, 0, 1), new String(strB, 0, 1)); 1413 if (result != 0) { 1414 errln("Error 2 in test 6\n"); 1415 } 1416 } 1417 */ 1418 } 1419 1420 @Test 1421 public void TestContraction() { 1422 String[] testrules = { 1423 "&A = AB / B", 1424 "&A = A\\u0306/\\u0306", 1425 "&c = ch / h", 1426 }; 1427 String[] testdata = { 1428 "AB", "AB", "A\u0306", "ch" 1429 }; 1430 String[] testdata2 = { 1431 "\u0063\u0067", 1432 "\u0063\u0068", 1433 "\u0063\u006C", 1434 }; 1435 /* 1436 * These pairs of rule strings are not guaranteed to yield the very same mappings. 1437 * In fact, LDML 24 recommends an improved way of creating mappings 1438 * which always yields different mappings for such pairs. See 1439 * http://www.unicode.org/reports/tr35/tr35-33/tr35-collation.html#Orderings 1440 String[] testrules3 = { 1441 "&z < xyz &xyzw << B", 1442 "&z < xyz &xyz << B / w", 1443 "&z < ch &achm << B", 1444 "&z < ch &a << B / chm", 1445 "&\ud800\udc00w << B", 1446 "&\ud800\udc00 << B / w", 1447 "&a\ud800\udc00m << B", 1448 "&a << B / \ud800\udc00m", 1449 }; */ 1450 1451 RuleBasedCollator coll = null; 1452 for (int i = 0; i < testrules.length; i ++) { 1453 CollationElementIterator iter1 = null; 1454 int j = 0; 1455 // logln("Rule " + testrules[i] + " for testing\n"); 1456 String rule = testrules[i]; 1457 try { 1458 coll = new RuleBasedCollator(rule); 1459 } catch (Exception e) { 1460 warnln("Collator creation failed " + testrules[i]); 1461 return; 1462 } 1463 try { 1464 iter1 = coll.getCollationElementIterator(testdata[i]); 1465 } catch (Exception e) { 1466 errln("Collation iterator creation failed\n"); 1467 return; 1468 } 1469 while (j < 2) { 1470 CollationElementIterator iter2; 1471 int ce; 1472 try { 1473 iter2 = coll.getCollationElementIterator(String.valueOf(testdata[i].charAt(j))); 1474 1475 }catch (Exception e) { 1476 errln("Collation iterator creation failed\n"); 1477 return; 1478 } 1479 ce = iter2.next(); 1480 while (ce != CollationElementIterator.NULLORDER) { 1481 if (iter1.next() != ce) { 1482 errln("Collation elements in contraction split does not match\n"); 1483 return; 1484 } 1485 ce = iter2.next(); 1486 } 1487 j ++; 1488 } 1489 if (iter1.next() != CollationElementIterator.NULLORDER) { 1490 errln("Collation elements not exhausted\n"); 1491 return; 1492 } 1493 } 1494 String rule = "& a < b < c < ch < d & c = ch / h"; 1495 try { 1496 coll = new RuleBasedCollator(rule); 1497 } catch (Exception e) { 1498 errln("cannot create rulebased collator"); 1499 return; 1500 } 1501 1502 if (coll.compare(testdata2[0], testdata2[1]) != -1) { 1503 errln("Expected " + testdata2[0] + " < " + testdata2[1]); 1504 return; 1505 } 1506 if (coll.compare(testdata2[1], testdata2[2]) != -1) { 1507 errln("Expected " + testdata2[1] + " < " + testdata2[2]); 1508 return; 1509 } 1510 /* see above -- for (int i = 0; i < testrules3.length; i += 2) { 1511 RuleBasedCollator coll1, coll2; 1512 CollationElementIterator iter1, iter2; 1513 char ch = 0x0042; 1514 int ce; 1515 rule = testrules3[i]; 1516 try { 1517 coll1 = new RuleBasedCollator(rule); 1518 } catch (Exception e) { 1519 errln("Fail: cannot create rulebased collator, rule:" + rule); 1520 return; 1521 } 1522 rule = testrules3[i + 1]; 1523 try { 1524 coll2 = new RuleBasedCollator(rule); 1525 } catch (Exception e) { 1526 errln("Collator creation failed " + testrules[i]); 1527 return; 1528 } 1529 try { 1530 iter1 = coll1.getCollationElementIterator(String.valueOf(ch)); 1531 iter2 = coll2.getCollationElementIterator(String.valueOf(ch)); 1532 } catch (Exception e) { 1533 errln("Collation iterator creation failed\n"); 1534 return; 1535 } 1536 ce = iter1.next(); 1537 1538 while (ce != CollationElementIterator.NULLORDER) { 1539 if (ce != iter2.next()) { 1540 errln("CEs does not match\n"); 1541 return; 1542 } 1543 ce = iter1.next(); 1544 } 1545 if (iter2.next() != CollationElementIterator.NULLORDER) { 1546 errln("CEs not exhausted\n"); 1547 return; 1548 } 1549 } */ 1550 } 1551 1552 @Test 1553 public void TestExpansion() { 1554 String[] testrules = { 1555 /* 1556 * This seems to have tested that M was not mapped to an expansion. 1557 * I believe the old builder just did that because it computed the extension CEs 1558 * at the very end, which was a bug. 1559 * Among other problems, it violated the core tailoring principle 1560 * by making an earlier rule depend on a later one. 1561 * And, of course, if M did not get an expansion, then it was primary different from K, 1562 * unlike what the rule &K<<M says. 1563 "&J << K / B & K << M", 1564 */ 1565 "&J << K / B << M" 1566 }; 1567 String[] testdata = { 1568 "JA", "MA", "KA", "KC", "JC", "MC", 1569 }; 1570 1571 Collator coll; 1572 for (int i = 0; i < testrules.length; i++) { 1573 // logln("Rule " + testrules[i] + " for testing\n"); 1574 String rule = testrules[i]; 1575 try { 1576 coll = new RuleBasedCollator(rule); 1577 } catch (Exception e) { 1578 warnln("Collator creation failed " + testrules[i]); 1579 return; 1580 } 1581 1582 for (int j = 0; j < 5; j ++) { 1583 CollationTest.doTest(this, (RuleBasedCollator)coll, 1584 testdata[j], testdata[j + 1], -1); 1585 } 1586 } 1587 } 1588 1589 @Test 1590 public void TestContractionEndCompare() 1591 { 1592 String rules = "&b=ch"; 1593 String src = "bec"; 1594 String tgt = "bech"; 1595 Collator coll = null; 1596 try { 1597 coll = new RuleBasedCollator(rules); 1598 } catch (Exception e) { 1599 warnln("Collator creation failed " + rules); 1600 return; 1601 } 1602 CollationTest.doTest(this, (RuleBasedCollator)coll, src, tgt, 1); 1603 } 1604 1605 @Test 1606 public void TestLocaleRuleBasedCollators() { 1607 if (TestFmwk.getExhaustiveness() < 5) { 1608 // not serious enough to run this 1609 return; 1610 } 1611 Locale locale[] = Collator.getAvailableLocales(); 1612 String prevrule = null; 1613 for (int i = 0; i < locale.length; i ++) { 1614 Locale l = locale[i]; 1615 try { 1616 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_COLLATION_BASE_NAME,l); 1617 String collkey = rb.getStringWithFallback("collations/default"); 1618 ICUResourceBundle elements = rb.getWithFallback("collations/" + collkey); 1619 if (elements == null) { 1620 continue; 1621 } 1622 String rule = null; 1623 /* 1624 Object[][] colldata = (Object[][])elements; 1625 // %%CollationBin 1626 if (colldata[0][1] instanceof byte[]){ 1627 rule = (String)colldata[1][1]; 1628 } 1629 else { 1630 rule = (String)colldata[0][1]; 1631 } 1632 */ 1633 rule = elements.getString("Sequence"); 1634 1635 RuleBasedCollator col1 = 1636 (RuleBasedCollator)Collator.getInstance(l); 1637 if (!rule.equals(col1.getRules())) { 1638 errln("Rules should be the same in the RuleBasedCollator and Locale"); 1639 } 1640 if (rule != null && rule.length() > 0 1641 && !rule.equals(prevrule)) { 1642 RuleBasedCollator col2 = new RuleBasedCollator(rule); 1643 if (!col1.equals(col2)) { 1644 errln("Error creating RuleBasedCollator from " + 1645 "locale rules for " + l.toString()); 1646 } 1647 } 1648 prevrule = rule; 1649 } catch (Exception e) { 1650 warnln("Error retrieving resource bundle for testing: " + e.toString()); 1651 } 1652 } 1653 } 1654 1655 @Test 1656 public void TestOptimize() { 1657 /* this is not really a test - just trying out 1658 * whether copying of UCA contents will fail 1659 * Cannot really test, since the functionality 1660 * remains the same. 1661 */ 1662 String rules[] = { 1663 "[optimize [\\uAC00-\\uD7FF]]" 1664 }; 1665 String data[][] = { 1666 { "a", "b"} 1667 }; 1668 int i = 0; 1669 1670 for(i = 0; i<rules.length; i++) { 1671 genericRulesStarter(rules[i], data[i]); 1672 } 1673 } 1674 1675 @Test 1676 public void TestIdenticalCompare() 1677 { 1678 try { 1679 RuleBasedCollator coll 1680 = new RuleBasedCollator("& \uD800\uDC00 = \uD800\uDC01"); 1681 String strA = "AA\u0300\u0316\uD800\uDC01"; 1682 String strB = "A\u00c0\u0316\uD800\uDC00"; 1683 coll.setStrength(Collator.IDENTICAL); 1684 CollationTest.doTest(this, coll, strA, strB, 1); 1685 } catch (Exception e) { 1686 warnln(e.getMessage()); 1687 } 1688 } 1689 1690 @Test 1691 public void TestMergeSortKeys() 1692 { 1693 String cases[] = {"abc", "abcd", "abcde"}; 1694 String prefix = "foo"; 1695 String suffix = "egg"; 1696 CollationKey mergedPrefixKeys[] = new CollationKey[cases.length]; 1697 CollationKey mergedSuffixKeys[] = new CollationKey[cases.length]; 1698 1699 Collator coll = Collator.getInstance(Locale.ENGLISH); 1700 genericLocaleStarter(Locale.ENGLISH, cases); 1701 1702 int strength = Collator.PRIMARY; 1703 while (strength <= Collator.IDENTICAL) { 1704 coll.setStrength(strength); 1705 CollationKey prefixKey = coll.getCollationKey(prefix); 1706 CollationKey suffixKey = coll.getCollationKey(suffix); 1707 for (int i = 0; i < cases.length; i ++) { 1708 CollationKey key = coll.getCollationKey(cases[i]); 1709 mergedPrefixKeys[i] = prefixKey.merge(key); 1710 mergedSuffixKeys[i] = suffixKey.merge(key); 1711 if (mergedPrefixKeys[i].getSourceString() != null 1712 || mergedSuffixKeys[i].getSourceString() != null) { 1713 errln("Merged source string error: expected null"); 1714 } 1715 if (i > 0) { 1716 if (mergedPrefixKeys[i-1].compareTo(mergedPrefixKeys[i]) 1717 >= 0) { 1718 errln("Error while comparing prefixed keys @ strength " 1719 + strength); 1720 errln(CollationTest.prettify(mergedPrefixKeys[i-1])); 1721 errln(CollationTest.prettify(mergedPrefixKeys[i])); 1722 } 1723 if (mergedSuffixKeys[i-1].compareTo(mergedSuffixKeys[i]) 1724 >= 0) { 1725 errln("Error while comparing suffixed keys @ strength " 1726 + strength); 1727 errln(CollationTest.prettify(mergedSuffixKeys[i-1])); 1728 errln(CollationTest.prettify(mergedSuffixKeys[i])); 1729 } 1730 } 1731 } 1732 if (strength == Collator.QUATERNARY) { 1733 strength = Collator.IDENTICAL; 1734 } 1735 else { 1736 strength ++; 1737 } 1738 } 1739 } 1740 1741 @Test 1742 public void TestVariableTop() 1743 { 1744 // ICU 53+: The character must be in a supported reordering group, 1745 // and the variable top is pinned to the end of that group. 1746 // parseNextToken is not released as public so i create my own rules 1747 String rules = "& ' ' < b < c < de < fg & hi = j"; 1748 try { 1749 RuleBasedCollator coll = new RuleBasedCollator(rules); 1750 String tokens[] = {" ", "b", "c", "de", "fg", "hi", "j", "ab"}; 1751 coll.setAlternateHandlingShifted(true); 1752 for (int i = 0; i < tokens.length; i ++) { 1753 int varTopOriginal = coll.getVariableTop(); 1754 try { 1755 int varTop = coll.setVariableTop(tokens[i]); 1756 if (i > 4) { 1757 errln("Token " + tokens[i] + " expected to fail"); 1758 } 1759 if (varTop != coll.getVariableTop()) { 1760 errln("Error setting and getting variable top"); 1761 } 1762 CollationKey key1 = coll.getCollationKey(tokens[i]); 1763 for (int j = 0; j < i; j ++) { 1764 CollationKey key2 = coll.getCollationKey(tokens[j]); 1765 if (key2.compareTo(key1) < 0) { 1766 errln("Setting variable top shouldn't change the comparison sequence"); 1767 } 1768 byte sortorder[] = key2.toByteArray(); 1769 if (sortorder.length > 0 1770 && (key2.toByteArray())[0] > 1) { 1771 errln("Primary sort order should be 0"); 1772 } 1773 } 1774 } catch (Exception e) { 1775 CollationElementIterator iter 1776 = coll.getCollationElementIterator(tokens[i]); 1777 /*int ce =*/ iter.next(); 1778 int ce2 = iter.next(); 1779 if (ce2 == CollationElementIterator.NULLORDER) { 1780 errln("Token " + tokens[i] + " not expected to fail"); 1781 } 1782 if (coll.getVariableTop() != varTopOriginal) { 1783 errln("When exception is thrown variable top should " 1784 + "not be changed"); 1785 } 1786 } 1787 coll.setVariableTop(varTopOriginal); 1788 if (varTopOriginal != coll.getVariableTop()) { 1789 errln("Couldn't restore old variable top\n"); 1790 } 1791 } 1792 1793 // Testing calling with error set 1794 try { 1795 coll.setVariableTop(""); 1796 errln("Empty string should throw an IllegalArgumentException"); 1797 } catch (IllegalArgumentException e) { 1798 logln("PASS: Empty string failed as expected"); 1799 } 1800 try { 1801 coll.setVariableTop(null); 1802 errln("Null string should throw an IllegalArgumentException"); 1803 } catch (IllegalArgumentException e) { 1804 logln("PASS: null string failed as expected"); 1805 } 1806 } catch (Exception e) { 1807 warnln("Error creating RuleBasedCollator"); 1808 } 1809 } 1810 1811 // ported from cmsccoll.c 1812 @Test 1813 public void TestVariableTopSetting() { 1814 int varTopOriginal = 0, varTop1, varTop2; 1815 Collator coll = Collator.getInstance(ULocale.ROOT); 1816 1817 String empty = ""; 1818 String space = " "; 1819 String dot = "."; /* punctuation */ 1820 String degree = "\u00b0"; /* symbol */ 1821 String dollar = "$"; /* currency symbol */ 1822 String zero = "0"; /* digit */ 1823 1824 varTopOriginal = coll.getVariableTop(); 1825 logln(String.format("coll.getVariableTop(root) -> %08x", varTopOriginal)); 1826 ((RuleBasedCollator)coll).setAlternateHandlingShifted(true); 1827 1828 varTop1 = coll.setVariableTop(space); 1829 varTop2 = coll.getVariableTop(); 1830 logln(String.format("coll.setVariableTop(space) -> %08x", varTop1)); 1831 if(varTop1 != varTop2 || 1832 !coll.equals(empty, space) || 1833 coll.equals(empty, dot) || 1834 coll.equals(empty, degree) || 1835 coll.equals(empty, dollar) || 1836 coll.equals(empty, zero) || 1837 coll.compare(space, dot) >= 0) { 1838 errln("coll.setVariableTop(space) did not work"); 1839 } 1840 1841 varTop1 = coll.setVariableTop(dot); 1842 varTop2 = coll.getVariableTop(); 1843 logln(String.format("coll.setVariableTop(dot) -> %08x", varTop1)); 1844 if(varTop1 != varTop2 || 1845 !coll.equals(empty, space) || 1846 !coll.equals(empty, dot) || 1847 coll.equals(empty, degree) || 1848 coll.equals(empty, dollar) || 1849 coll.equals(empty, zero) || 1850 coll.compare(dot, degree) >= 0) { 1851 errln("coll.setVariableTop(dot) did not work"); 1852 } 1853 1854 varTop1 = coll.setVariableTop(degree); 1855 varTop2 = coll.getVariableTop(); 1856 logln(String.format("coll.setVariableTop(degree) -> %08x", varTop1)); 1857 if(varTop1 != varTop2 || 1858 !coll.equals(empty, space) || 1859 !coll.equals(empty, dot) || 1860 !coll.equals(empty, degree) || 1861 coll.equals(empty, dollar) || 1862 coll.equals(empty, zero) || 1863 coll.compare(degree, dollar) >= 0) { 1864 errln("coll.setVariableTop(degree) did not work"); 1865 } 1866 1867 varTop1 = coll.setVariableTop(dollar); 1868 varTop2 = coll.getVariableTop(); 1869 logln(String.format("coll.setVariableTop(dollar) -> %08x", varTop1)); 1870 if(varTop1 != varTop2 || 1871 !coll.equals(empty, space) || 1872 !coll.equals(empty, dot) || 1873 !coll.equals(empty, degree) || 1874 !coll.equals(empty, dollar) || 1875 coll.equals(empty, zero) || 1876 coll.compare(dollar, zero) >= 0) { 1877 errln("coll.setVariableTop(dollar) did not work"); 1878 } 1879 1880 logln("Testing setting variable top to contractions"); 1881 try { 1882 coll.setVariableTop("@P"); 1883 errln("Invalid contraction succeded in setting variable top!"); 1884 } catch(Exception expected) { 1885 } 1886 1887 logln("Test restoring variable top"); 1888 coll.setVariableTop(varTopOriginal); 1889 if(varTopOriginal != coll.getVariableTop()) { 1890 errln("Couldn't restore old variable top"); 1891 } 1892 } 1893 1894 // ported from cmsccoll.c 1895 @Test 1896 public void TestMaxVariable() { 1897 int oldMax, max; 1898 1899 String empty = ""; 1900 String space = " "; 1901 String dot = "."; /* punctuation */ 1902 String degree = "\u00b0"; /* symbol */ 1903 String dollar = "$"; /* currency symbol */ 1904 String zero = "0"; /* digit */ 1905 1906 Collator coll = Collator.getInstance(ULocale.ROOT); 1907 1908 oldMax = coll.getMaxVariable(); 1909 logln(String.format("coll.getMaxVariable(root) -> %04x", oldMax)); 1910 ((RuleBasedCollator)coll).setAlternateHandlingShifted(true); 1911 1912 coll.setMaxVariable(Collator.ReorderCodes.SPACE); 1913 max = coll.getMaxVariable(); 1914 logln(String.format("coll.setMaxVariable(space) -> %04x", max)); 1915 if(max != Collator.ReorderCodes.SPACE || 1916 !coll.equals(empty, space) || 1917 coll.equals(empty, dot) || 1918 coll.equals(empty, degree) || 1919 coll.equals(empty, dollar) || 1920 coll.equals(empty, zero) || 1921 coll.compare(space, dot) >= 0) { 1922 errln("coll.setMaxVariable(space) did not work"); 1923 } 1924 1925 coll.setMaxVariable(Collator.ReorderCodes.PUNCTUATION); 1926 max = coll.getMaxVariable(); 1927 logln(String.format("coll.setMaxVariable(punctuation) -> %04x", max)); 1928 if(max != Collator.ReorderCodes.PUNCTUATION || 1929 !coll.equals(empty, space) || 1930 !coll.equals(empty, dot) || 1931 coll.equals(empty, degree) || 1932 coll.equals(empty, dollar) || 1933 coll.equals(empty, zero) || 1934 coll.compare(dot, degree) >= 0) { 1935 errln("coll.setMaxVariable(punctuation) did not work"); 1936 } 1937 1938 coll.setMaxVariable(Collator.ReorderCodes.SYMBOL); 1939 max = coll.getMaxVariable(); 1940 logln(String.format("coll.setMaxVariable(symbol) -> %04x", max)); 1941 if(max != Collator.ReorderCodes.SYMBOL || 1942 !coll.equals(empty, space) || 1943 !coll.equals(empty, dot) || 1944 !coll.equals(empty, degree) || 1945 coll.equals(empty, dollar) || 1946 coll.equals(empty, zero) || 1947 coll.compare(degree, dollar) >= 0) { 1948 errln("coll.setMaxVariable(symbol) did not work"); 1949 } 1950 1951 coll.setMaxVariable(Collator.ReorderCodes.CURRENCY); 1952 max = coll.getMaxVariable(); 1953 logln(String.format("coll.setMaxVariable(currency) -> %04x", max)); 1954 if(max != Collator.ReorderCodes.CURRENCY || 1955 !coll.equals(empty, space) || 1956 !coll.equals(empty, dot) || 1957 !coll.equals(empty, degree) || 1958 !coll.equals(empty, dollar) || 1959 coll.equals(empty, zero) || 1960 coll.compare(dollar, zero) >= 0) { 1961 errln("coll.setMaxVariable(currency) did not work"); 1962 } 1963 1964 logln("Test restoring maxVariable"); 1965 coll.setMaxVariable(oldMax); 1966 if(oldMax != coll.getMaxVariable()) { 1967 errln("Couldn't restore old maxVariable"); 1968 } 1969 } 1970 1971 @Test 1972 public void TestUCARules() 1973 { 1974 try { 1975 // only root locale can have empty tailorings .. not English! 1976 RuleBasedCollator coll 1977 = (RuleBasedCollator)Collator.getInstance(new Locale("","","")); 1978 String rule 1979 = coll.getRules(false); 1980 if (!rule.equals("")) { 1981 errln("Empty rule string should have empty rules " + rule); 1982 } 1983 rule = coll.getRules(true); 1984 if (rule.equals("")) { 1985 errln("UCA rule string should not be empty"); 1986 } 1987 coll = new RuleBasedCollator(rule); 1988 } catch (Exception e) { 1989 // Android patch: Add --omitCollationRules to genrb. 1990 logln(e.getMessage()); 1991 // Android patch end. 1992 } 1993 } 1994 1995 /** 1996 * Jitterbug 2726 1997 */ 1998 @Test 1999 public void TestShifted() 2000 { 2001 RuleBasedCollator collator = (RuleBasedCollator) Collator.getInstance(); 2002 collator.setStrength(Collator.PRIMARY); 2003 collator.setAlternateHandlingShifted(true); 2004 CollationTest.doTest(this, collator, " a", "a", 0); // works properly 2005 CollationTest.doTest(this, collator, "a", "a ", 0); // inconsistent results 2006 } 2007 2008 /** 2009 * Test for CollationElementIterator previous and next for the whole set of 2010 * unicode characters with normalization on. 2011 */ 2012 @Test 2013 public void TestNumericCollation() 2014 { 2015 String basicTestStrings[] = {"hello1", "hello2", "hello123456"}; 2016 String preZeroTestStrings[] = {"avery1", 2017 "avery01", 2018 "avery001", 2019 "avery0001"}; 2020 String thirtyTwoBitNumericStrings[] = {"avery42949672960", 2021 "avery42949672961", 2022 "avery42949672962", 2023 "avery429496729610"}; 2024 2025 String supplementaryDigits[] = {"\uD835\uDFCE", // 0 2026 "\uD835\uDFCF", // 1 2027 "\uD835\uDFD0", // 2 2028 "\uD835\uDFD1", // 3 2029 "\uD835\uDFCF\uD835\uDFCE", // 10 2030 "\uD835\uDFCF\uD835\uDFCF", // 11 2031 "\uD835\uDFCF\uD835\uDFD0", // 12 2032 "\uD835\uDFD0\uD835\uDFCE", // 20 2033 "\uD835\uDFD0\uD835\uDFCF", // 21 2034 "\uD835\uDFD0\uD835\uDFD0" // 22 2035 }; 2036 2037 String foreignDigits[] = {"\u0661", 2038 "\u0662", 2039 "\u0663", 2040 "\u0661\u0660", 2041 "\u0661\u0662", 2042 "\u0661\u0663", 2043 "\u0662\u0660", 2044 "\u0662\u0662", 2045 "\u0662\u0663", 2046 "\u0663\u0660", 2047 "\u0663\u0662", 2048 "\u0663\u0663" 2049 }; 2050 2051 //Additional tests to cover bug reported in #9476 2052 String lastDigitDifferent[]={"2004","2005", 2053 "110005", "110006", 2054 "11005", "11006", 2055 "100000000005","100000000006"}; 2056 2057 // Open our collator. 2058 RuleBasedCollator coll 2059 = (RuleBasedCollator)Collator.getInstance(Locale.ENGLISH); 2060 String att[] = {"NumericCollation"}; 2061 Boolean val[] = {Boolean.TRUE}; 2062 genericLocaleStarterWithOptions(Locale.ENGLISH, basicTestStrings, att, 2063 val); 2064 genericLocaleStarterWithOptions(Locale.ENGLISH, 2065 thirtyTwoBitNumericStrings, att, val); 2066 genericLocaleStarterWithOptions(Locale.ENGLISH, foreignDigits, att, 2067 val); 2068 genericLocaleStarterWithOptions(Locale.ENGLISH, supplementaryDigits, 2069 att, val); 2070 2071 // Setting up our collator to do digits. 2072 coll.setNumericCollation(true); 2073 2074 // Testing that prepended zeroes still yield the correct collation 2075 // behavior. 2076 // We expect that every element in our strings array will be equal. 2077 for (int i = 0; i < preZeroTestStrings.length - 1; i ++) { 2078 for (int j = i + 1; j < preZeroTestStrings.length; j ++) { 2079 CollationTest.doTest(this, coll, preZeroTestStrings[i], 2080 preZeroTestStrings[j],0); 2081 } 2082 } 2083 2084 //Testing that the behavior reported in #9476 is fixed 2085 //We expect comparisons between adjacent pairs will result in -1 2086 for (int i=0; i < lastDigitDifferent.length -1; i=i+2 ) { 2087 CollationTest.doTest(this, coll, lastDigitDifferent[i], lastDigitDifferent[i+1], -1); 2088 } 2089 2090 2091 //cover setNumericCollationDefault, getNumericCollation 2092 assertTrue("The Numeric Collation setting is on", coll.getNumericCollation()); 2093 coll.setNumericCollationDefault(); 2094 logln("After set Numeric to default, the setting is: " + coll.getNumericCollation()); 2095 } 2096 2097 @Test 2098 public void Test3249() 2099 { 2100 String rule = "&x < a &z < a"; 2101 try { 2102 RuleBasedCollator coll = new RuleBasedCollator(rule); 2103 if(coll!=null){ 2104 logln("Collator did not throw an exception"); 2105 } 2106 } catch (Exception e) { 2107 warnln("Error creating RuleBasedCollator with " + rule + " failed"); 2108 } 2109 } 2110 2111 @Test 2112 public void TestTibetanConformance() 2113 { 2114 String test[] = {"\u0FB2\u0591\u0F71\u0061", "\u0FB2\u0F71\u0061"}; 2115 try { 2116 Collator coll = Collator.getInstance(); 2117 coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 2118 if (coll.compare(test[0], test[1]) != 0) { 2119 errln("Tibetan comparison error"); 2120 } 2121 CollationTest.doTest(this, (RuleBasedCollator)coll, 2122 test[0], test[1], 0); 2123 } catch (Exception e) { 2124 warnln("Error creating UCA collator"); 2125 } 2126 } 2127 2128 @Test 2129 public void TestJ3347() 2130 { 2131 try { 2132 Collator coll = Collator.getInstance(Locale.FRENCH); 2133 ((RuleBasedCollator)coll).setAlternateHandlingShifted(true); 2134 if (coll.compare("6", "!6") != 0) { 2135 errln("Jitterbug 3347 failed"); 2136 } 2137 } catch (Exception e) { 2138 warnln("Error creating UCA collator"); 2139 } 2140 } 2141 2142 @Test 2143 public void TestPinyinProblem() 2144 { 2145 String test[] = { "\u4E56\u4E56\u7761", "\u4E56\u5B69\u5B50" }; 2146 genericLocaleStarter(new Locale("zh", "", "PINYIN"), test); 2147 } 2148 2149 /* supercedes TestJ784 */ 2150 @Test 2151 public void TestBeforePinyin() { 2152 String rules = 2153 "&[before 2]A << \u0101 <<< \u0100 << \u00E1 <<< \u00C1 << \u01CE <<< \u01CD << \u00E0 <<< \u00C0" + 2154 "&[before 2]e << \u0113 <<< \u0112 << \u00E9 <<< \u00C9 << \u011B <<< \u011A << \u00E8 <<< \u00C8" + 2155 "&[before 2] i << \u012B <<< \u012A << \u00ED <<< \u00CD << \u01D0 <<< \u01CF << \u00EC <<< \u00CC" + 2156 "&[before 2] o << \u014D <<< \u014C << \u00F3 <<< \u00D3 << \u01D2 <<< \u01D1 << \u00F2 <<< \u00D2" + 2157 "&[before 2]u << \u016B <<< \u016A << \u00FA <<< \u00DA << \u01D4 <<< \u01D3 << \u00F9 <<< \u00D9" + 2158 "&U << \u01D6 <<< \u01D5 << \u01D8 <<< \u01D7 << \u01DA <<< \u01D9 << \u01DC <<< \u01DB << \u00FC"; 2159 2160 String test[] = { 2161 "l\u0101", 2162 "la", 2163 "l\u0101n", 2164 "lan ", 2165 "l\u0113", 2166 "le", 2167 "l\u0113n", 2168 "len" 2169 }; 2170 2171 String test2[] = { 2172 "x\u0101", 2173 "x\u0100", 2174 "X\u0101", 2175 "X\u0100", 2176 "x\u00E1", 2177 "x\u00C1", 2178 "X\u00E1", 2179 "X\u00C1", 2180 "x\u01CE", 2181 "x\u01CD", 2182 "X\u01CE", 2183 "X\u01CD", 2184 "x\u00E0", 2185 "x\u00C0", 2186 "X\u00E0", 2187 "X\u00C0", 2188 "xa", 2189 "xA", 2190 "Xa", 2191 "XA", 2192 "x\u0101x", 2193 "x\u0100x", 2194 "x\u00E1x", 2195 "x\u00C1x", 2196 "x\u01CEx", 2197 "x\u01CDx", 2198 "x\u00E0x", 2199 "x\u00C0x", 2200 "xax", 2201 "xAx" 2202 }; 2203 /* TODO: port builder fixes to before */ 2204 genericRulesStarter(rules, test); 2205 genericLocaleStarter(new Locale("zh","",""), test); 2206 genericRulesStarter(rules, test2); 2207 genericLocaleStarter(new Locale("zh","",""), test2); 2208 } 2209 2210 @Test 2211 public void TestUpperFirstQuaternary() 2212 { 2213 String tests[] = { "B", "b", "Bb", "bB" }; 2214 String[] att = { "strength", "UpperFirst" }; 2215 Object attVals[] = { new Integer(Collator.QUATERNARY), Boolean.TRUE }; 2216 genericLocaleStarterWithOptions(new Locale("root","",""), tests, att, attVals); 2217 } 2218 2219 @Test 2220 public void TestJ4960() 2221 { 2222 String tests[] = { "\\u00e2T", "aT" }; 2223 String att[] = { "strength", "CaseLevel" }; 2224 Object attVals[] = { new Integer(Collator.PRIMARY), Boolean.TRUE }; 2225 String tests2[] = { "a", "A" }; 2226 String rule = "&[first tertiary ignorable]=A=a"; 2227 String att2[] = { "CaseLevel" }; 2228 Object attVals2[] = { Boolean.TRUE }; 2229 // Test whether we correctly ignore primary ignorables on case level when 2230 // we have only primary & case level 2231 genericLocaleStarterWithOptionsAndResult(new Locale("root", ""), tests, att, attVals, 0); 2232 // Test whether ICU4J will make case level for sortkeys that have primary strength 2233 // and case level 2234 genericLocaleStarterWithOptions(new Locale("root", ""), tests2, att, attVals); 2235 // Test whether completely ignorable letters have case level info (they shouldn't) 2236 genericRulesStarterWithOptionsAndResult(rule, tests2, att2, attVals2, 0); 2237 } 2238 2239 @Test 2240 public void TestJB5298(){ 2241 ULocale[] locales = Collator.getAvailableULocales(); 2242 logln("Number of collator locales returned : " + locales.length); 2243 // double-check keywords 2244 String[] keywords = Collator.getKeywords(); 2245 if (keywords.length != 1 || !keywords[0].equals("collation")) { 2246 throw new IllegalArgumentException("internal collation error"); 2247 } 2248 2249 String[] values = Collator.getKeywordValues("collation"); 2250 log("Collator.getKeywordValues returned: "); 2251 for(int i=0; i<values.length;i++){ 2252 log(values[i]+", "); 2253 } 2254 logln(""); 2255 logln("Number of collation keyword values returned : " + values.length); 2256 for(int i=0; i<values.length;i++){ 2257 if (values[i].startsWith("private-")) { 2258 errln("Collator.getKeywordValues() returns private collation keyword: " + values[i]); 2259 } 2260 } 2261 2262 Set foundValues = new TreeSet(Arrays.asList(values)); 2263 2264 for (int i = 0; i < locales.length; ++i) { 2265 for (int j = 0; j < values.length; ++j) { 2266 ULocale tryLocale = values[j].equals("standard") 2267 ? locales[i] : new ULocale(locales[i] + "@collation=" + values[j]); 2268 // only append if not standard 2269 ULocale canon = Collator.getFunctionalEquivalent("collation",tryLocale); 2270 if (!canon.equals(tryLocale)) { 2271 continue; // has a different 2272 }else {// functional equivalent, so skip 2273 logln(tryLocale + " : "+canon+", "); 2274 } 2275 String can = canon.toString(); 2276 int idx = can.indexOf("@collation="); 2277 String val = idx >= 0 ? can.substring(idx+11, can.length()) : ""; 2278 if(val.length()>0 && !foundValues.contains(val)){ 2279 errln("Unknown collation found "+ can); 2280 } 2281 } 2282 } 2283 logln(" "); 2284 } 2285 2286 @Test 2287 public void TestJ5367() 2288 { 2289 String[] test = { "a", "y" }; 2290 String rules = "&Ny << Y &[first secondary ignorable] <<< a"; 2291 genericRulesStarter(rules, test); 2292 } 2293 2294 @Test 2295 public void TestVI5913() 2296 { 2297 2298 String rules[] = { 2299 "&a < \u00e2 <<< \u00c2", 2300 "&a < \u1FF3 ", // OMEGA WITH YPOGEGRAMMENI 2301 "&s < \u0161 ", // &s < s with caron 2302 /* 2303 * Note: Just tailoring &z<ae^ does not work as expected: 2304 * The UCA spec requires for discontiguous contractions that they 2305 * extend an *existing match* by one combining mark at a time. 2306 * Therefore, ae must be a contraction so that the builder finds 2307 * discontiguous contractions for ae^, for example with an intervening underdot. 2308 * Only then do we get the expected tail closure with a\u1EC7, a\u1EB9\u0302, etc. 2309 */ 2310 "&x < ae &z < a\u00EA", // &x < ae &z < a+e with circumflex 2311 }; 2312 String cases[][] = { 2313 { "\u1EAC", "A\u0323\u0302", "\u1EA0\u0302", "\u00C2\u0323", }, 2314 { "\u1FA2", "\u03C9\u0313\u0300\u0345", "\u1FF3\u0313\u0300", 2315 "\u1F60\u0300\u0345", "\u1f62\u0345", "\u1FA0\u0300", }, 2316 { "\u1E63\u030C", "s\u0323\u030C", "s\u030C\u0323"}, 2317 { "a\u1EC7", // a+ e with dot below and circumflex 2318 "a\u1EB9\u0302", // a + e with dot below + combining circumflex 2319 "a\u00EA\u0323", // a + e with circumflex + combining dot below 2320 } 2321 }; 2322 2323 2324 for(int i = 0; i < rules.length; i++) { 2325 2326 RuleBasedCollator coll = null; 2327 try { 2328 coll = new RuleBasedCollator(rules[i]); 2329 } catch (Exception e) { 2330 warnln("Unable to open collator with rules " + rules[i]); 2331 } 2332 2333 logln("Test case["+i+"]:"); 2334 CollationKey expectingKey = coll.getCollationKey(cases[i][0]); 2335 for (int j=1; j<cases[i].length; j++) { 2336 CollationKey key = coll.getCollationKey(cases[i][j]); 2337 if ( key.compareTo(expectingKey)!=0) { 2338 errln("Error! Test case["+i+"]:"+"source:" + key.getSourceString()); 2339 errln("expecting:"+CollationTest.prettify(expectingKey)+ "got:"+ CollationTest.prettify(key)); 2340 } 2341 logln(" Key:"+ CollationTest.prettify(key)); 2342 } 2343 } 2344 2345 2346 RuleBasedCollator vi_vi = null; 2347 try { 2348 vi_vi = (RuleBasedCollator)Collator.getInstance( 2349 new Locale("vi", "")); 2350 logln("VI sort:"); 2351 CollationKey expectingKey = vi_vi.getCollationKey(cases[0][0]); 2352 for (int j=1; j<cases[0].length; j++) { 2353 CollationKey key = vi_vi.getCollationKey(cases[0][j]); 2354 if ( key.compareTo(expectingKey)!=0) { 2355 // TODO (claireho): change the logln to errln after vi.res is up-to-date. 2356 // errln("source:" + key.getSourceString()); 2357 // errln("expecting:"+prettify(expectingKey)+ "got:"+ prettify(key)); 2358 logln("Error!! in Vietnese sort - source:" + key.getSourceString()); 2359 logln("expecting:"+CollationTest.prettify(expectingKey)+ "got:"+ CollationTest.prettify(key)); 2360 } 2361 // logln("source:" + key.getSourceString()); 2362 logln(" Key:"+ CollationTest.prettify(key)); 2363 } 2364 } catch (Exception e) { 2365 warnln("Error creating Vietnese collator"); 2366 return; 2367 } 2368 2369 } 2370 2371 2372 @Test 2373 public void Test6179() 2374 { 2375 String rules[] = { 2376 "&[last primary ignorable]<< a &[first primary ignorable]<<b ", 2377 "&[last secondary ignorable]<<< a &[first secondary ignorable]<<<b", 2378 }; 2379 // defined in UCA5.1 2380 String firstPrimIgn = "\u0332"; 2381 String lastPrimIgn = "\uD800\uDDFD"; 2382 String firstVariable = "\u0009"; 2383 byte[] secIgnKey = {1,1,4,0}; 2384 2385 int i=0; 2386 { 2387 2388 RuleBasedCollator coll = null; 2389 try { 2390 coll = new RuleBasedCollator(rules[i]); 2391 } catch (Exception e) { 2392 warnln("Unable to open collator with rules " + rules[i] + ": " + e); 2393 return; 2394 } 2395 2396 logln("Test rule["+i+"]"+rules[i]); 2397 2398 CollationKey keyA = coll.getCollationKey("a"); 2399 logln("Key for \"a\":"+ CollationTest.prettify(keyA)); 2400 if (keyA.compareTo(coll.getCollationKey(lastPrimIgn))<=0) { 2401 CollationKey key = coll.getCollationKey(lastPrimIgn); 2402 logln("Collation key for 0xD800 0xDDFD: "+CollationTest.prettify(key)); 2403 errln("Error! String \"a\" must be greater than \uD800\uDDFD -"+ 2404 "[Last Primary Ignorable]"); 2405 } 2406 if (keyA.compareTo(coll.getCollationKey(firstVariable))>=0) { 2407 CollationKey key = coll.getCollationKey(firstVariable); 2408 logln("Collation key for 0x0009: "+CollationTest.prettify(key)); 2409 errln("Error! String \"a\" must be less than 0x0009 - [First Variable]"); 2410 } 2411 CollationKey keyB = coll.getCollationKey("b"); 2412 logln("Key for \"b\":"+ CollationTest.prettify(keyB)); 2413 if (keyB.compareTo(coll.getCollationKey(firstPrimIgn))<=0) { 2414 CollationKey key = coll.getCollationKey(firstPrimIgn); 2415 logln("Collation key for 0x0332: "+CollationTest.prettify(key)); 2416 errln("Error! String \"b\" must be greater than 0x0332 -"+ 2417 "[First Primary Ignorable]"); 2418 } 2419 if (keyB.compareTo(coll.getCollationKey(firstVariable))>=0) { 2420 CollationKey key = coll.getCollationKey(firstVariable); 2421 logln("Collation key for 0x0009: "+CollationTest.prettify(key)); 2422 errln("Error! String \"b\" must be less than 0x0009 - [First Variable]"); 2423 } 2424 } 2425 { 2426 i=1; 2427 RuleBasedCollator coll = null; 2428 try { 2429 coll = new RuleBasedCollator(rules[i]); 2430 } catch (Exception e) { 2431 warnln("Unable to open collator with rules " + rules[i]); 2432 } 2433 2434 logln("Test rule["+i+"]"+rules[i]); 2435 2436 CollationKey keyA = coll.getCollationKey("a"); 2437 logln("Key for \"a\":"+ CollationTest.prettify(keyA)); 2438 byte[] keyAInBytes = keyA.toByteArray(); 2439 for (int j=0; j<keyAInBytes.length && j<secIgnKey.length; j++) { 2440 if (keyAInBytes[j]!=secIgnKey[j]) { 2441 if ((char)keyAInBytes[j]<=(char)secIgnKey[j]) { 2442 logln("Error! String \"a\" must be greater than [Last Secondary Ignorable]"); 2443 } 2444 break; 2445 } 2446 } 2447 if (keyA.compareTo(coll.getCollationKey(firstVariable))>=0) { 2448 errln("Error! String \"a\" must be less than 0x0009 - [First Variable]"); 2449 CollationKey key = coll.getCollationKey(firstVariable); 2450 logln("Collation key for 0x0009: "+CollationTest.prettify(key)); 2451 } 2452 CollationKey keyB = coll.getCollationKey("b"); 2453 logln("Key for \"b\":"+ CollationTest.prettify(keyB)); 2454 byte[] keyBInBytes = keyB.toByteArray(); 2455 for (int j=0; j<keyBInBytes.length && j<secIgnKey.length; j++) { 2456 if (keyBInBytes[j]!=secIgnKey[j]) { 2457 if ((char)keyBInBytes[j]<=(char)secIgnKey[j]) { 2458 errln("Error! String \"b\" must be greater than [Last Secondary Ignorable]"); 2459 } 2460 break; 2461 } 2462 } 2463 if (keyB.compareTo(coll.getCollationKey(firstVariable))>=0) { 2464 CollationKey key = coll.getCollationKey(firstVariable); 2465 logln("Collation key for 0x0009: "+CollationTest.prettify(key)); 2466 errln("Error! String \"b\" must be less than 0x0009 - [First Variable]"); 2467 } 2468 } 2469 } 2470 2471 @Test 2472 public void TestUCAPrecontext() 2473 { 2474 String rules[] = { 2475 "& \u00B7<a ", 2476 "& L\u00B7 << a", // 'a' is an expansion. 2477 }; 2478 String cases[] = { 2479 "\u00B7", 2480 "\u0387", 2481 "a", 2482 "l", 2483 "L\u0332", 2484 "l\u00B7", 2485 "l\u0387", 2486 "L\u0387", 2487 "la\u0387", 2488 "La\u00b7", 2489 }; 2490 2491 // Test en sort 2492 RuleBasedCollator en = null; 2493 2494 logln("EN sort:"); 2495 try { 2496 en = (RuleBasedCollator)Collator.getInstance( 2497 new Locale("en", "")); 2498 for (int j=0; j<cases.length; j++) { 2499 CollationKey key = en.getCollationKey(cases[j]); 2500 if (j>0) { 2501 CollationKey prevKey = en.getCollationKey(cases[j-1]); 2502 if (key.compareTo(prevKey)<0) { 2503 errln("Error! EN test["+j+"]:source:" + cases[j]+ 2504 " is not >= previous test string."); 2505 } 2506 } 2507 /* 2508 if ( key.compareTo(expectingKey)!=0) { 2509 errln("Error! Test case["+i+"]:"+"source:" + key.getSourceString()); 2510 errln("expecting:"+prettify(expectingKey)+ "got:"+ prettify(key)); 2511 } 2512 */ 2513 logln("String:"+cases[j]+" Key:"+ CollationTest.prettify(key)); 2514 } 2515 } catch (Exception e) { 2516 warnln("Error creating English collator"); 2517 return; 2518 } 2519 2520 // Test ja sort 2521 RuleBasedCollator ja = null; 2522 logln("JA sort:"); 2523 try { 2524 ja = (RuleBasedCollator)Collator.getInstance( 2525 new Locale("ja", "")); 2526 for (int j=0; j<cases.length; j++) { 2527 CollationKey key = ja.getCollationKey(cases[j]); 2528 if (j>0) { 2529 CollationKey prevKey = ja.getCollationKey(cases[j-1]); 2530 if (key.compareTo(prevKey)<0) { 2531 errln("Error! JA test["+j+"]:source:" + cases[j]+ 2532 " is not >= previous test string."); 2533 } 2534 } 2535 logln("String:"+cases[j]+" Key:"+ CollationTest.prettify(key)); 2536 } 2537 } catch (Exception e) { 2538 warnln("Error creating Japanese collator"); 2539 return; 2540 } 2541 for(int i = 0; i < rules.length; i++) { 2542 2543 RuleBasedCollator coll = null; 2544 logln("Tailoring rule:"+rules[i]); 2545 try { 2546 coll = new RuleBasedCollator(rules[i]); 2547 } catch (Exception e) { 2548 warnln("Unable to open collator with rules " + rules[i]); 2549 continue; 2550 } 2551 2552 for (int j=0; j<cases.length; j++) { 2553 CollationKey key = coll.getCollationKey(cases[j]); 2554 if (j>0) { 2555 CollationKey prevKey = coll.getCollationKey(cases[j-1]); 2556 if (i==1 && j==3) { 2557 if (key.compareTo(prevKey)>0) { 2558 errln("Error! Rule:"+rules[i]+" test["+j+"]:source:"+ 2559 cases[j]+" is not <= previous test string."); 2560 } 2561 } 2562 else { 2563 if (key.compareTo(prevKey)<0) { 2564 errln("Error! Rule:"+rules[i]+" test["+j+"]:source:"+ 2565 cases[j]+" is not >= previous test string."); 2566 } 2567 } 2568 } 2569 logln("String:"+cases[j]+" Key:"+ CollationTest.prettify(key)); 2570 } 2571 } 2572 } 2573 2574 2575 /** 2576 * Stores a test case for collation testing. 2577 */ 2578 private class OneTestCase { 2579 /** The first value to compare. **/ 2580 public String m_source_; 2581 2582 /** The second value to compare. **/ 2583 public String m_target_; 2584 2585 /** 2586 * 0 if the two values sort equal, 2587 * -1 if the first value sorts before the second 2588 * 1 if the first value sorts after the first 2589 */ 2590 public int m_result_; 2591 2592 public OneTestCase(String source, String target, int result) { 2593 m_source_ = source; 2594 m_target_ = target; 2595 m_result_ = result; 2596 } 2597 } 2598 2599 /** 2600 * Convenient function to test collation rules. 2601 * @param testCases 2602 * @param rules Collation rules in ICU format. All the strings in this 2603 * array represent the same rule, expressed in different forms. 2604 */ 2605 private void doTestCollation( 2606 OneTestCase[] testCases, String[] rules) { 2607 2608 Collator myCollation; 2609 for (String rule : rules) { 2610 try { 2611 myCollation = new RuleBasedCollator(rule); 2612 } catch (Exception e) { 2613 warnln("ERROR: in creation of rule based collator: " + e); 2614 return; 2615 } 2616 2617 myCollation.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 2618 myCollation.setStrength(Collator.TERTIARY); 2619 for (OneTestCase testCase : testCases) { 2620 CollationTest.doTest(this, (RuleBasedCollator)myCollation, 2621 testCase.m_source_, 2622 testCase.m_target_, 2623 testCase.m_result_); 2624 } 2625 } 2626 } 2627 2628 // Test cases to check whether the rules equivalent to 2629 // "&a<b<c<d &b<<k<<l<<m &k<<<x<<<y<<<z &a=1=2=3" are working fine. 2630 private OneTestCase[] m_rangeTestCases_ = { 2631 // Left Right Result 2632 new OneTestCase( "\u0061", "\u0062", -1 ), // "a" < "b" 2633 new OneTestCase( "\u0062", "\u0063", -1 ), // "b" < "c" 2634 new OneTestCase( "\u0061", "\u0063", -1 ), // "a" < "c" 2635 2636 new OneTestCase( "\u0062", "\u006b", -1 ), // "b" << "k" 2637 new OneTestCase( "\u006b", "\u006c", -1 ), // "k" << "l" 2638 new OneTestCase( "\u0062", "\u006c", -1 ), // "b" << "l" 2639 new OneTestCase( "\u0061", "\u006c", -1 ), // "a" << "l" 2640 new OneTestCase( "\u0061", "\u006d", -1 ), // "a" << "m" 2641 2642 new OneTestCase( "\u0079", "\u006d", -1 ), // "y" < "f" 2643 new OneTestCase( "\u0079", "\u0067", -1 ), // "y" < "g" 2644 new OneTestCase( "\u0061", "\u0068", -1 ), // "y" < "h" 2645 new OneTestCase( "\u0061", "\u0065", -1 ), // "g" < "e" 2646 2647 new OneTestCase( "\u0061", "\u0031", 0 ), // "a" == "1" 2648 new OneTestCase( "\u0061", "\u0032", 0 ), // "a" == "2" 2649 new OneTestCase( "\u0061", "\u0033", 0 ), // "a" == "3" 2650 new OneTestCase( "\u0061", "\u0066", -1 ), // "a" < "f", 2651 new OneTestCase( "\u006c\u0061", "\u006b\u0062", -1 ), // "la" < "kb" 2652 new OneTestCase( "\u0061\u0061\u0061", "\u0031\u0032\u0033", 0 ), // "aaa" == "123" 2653 new OneTestCase( "\u0062", "\u007a", -1 ), // "b" < "z" 2654 new OneTestCase( "\u0061\u007a\u0062", "\u0032\u0079\u006d", -1 ), // "azm" < "2yc" 2655 }; 2656 2657 // Test cases to check whether the rules equivalent to 2658 // "&\ufffe<\uffff<\U00010000<\U00010001<\U00010002 2659 // &\U00010000<<\U00020001<<\U00020002<<\U00020002 2660 // &\U00020001=\U0003001=\U0004001=\U0004002 2661 // &\U00040008<\U00030008<\UU00020008" 2662 // are working fine. 2663 private OneTestCase[] m_rangeTestCasesSupplemental_ = { 2664 // Left Right Result 2665 new OneTestCase( "\u4e00", "\ufffb", -1 ), 2666 new OneTestCase( "\ufffb", "\ud800\udc00", -1 ), // U+FFFB < U+10000 2667 new OneTestCase( "\ud800\udc00", "\ud800\udc01", -1 ), // U+10000 < U+10001 2668 2669 new OneTestCase( "\u4e00", "\ud800\udc01", -1 ), // U+4E00 < U+10001 2670 new OneTestCase( "\ud800\udc01", "\ud800\udc02", -1 ), // U+10001 < U+10002 2671 new OneTestCase( "\ud800\udc00", "\ud840\udc02", -1 ), // U+10000 < U+10002 2672 new OneTestCase( "\u4e00", "\u0d840\udc02", -1 ), // U+4E00 < U+10002 2673 2674 }; 2675 2676 // Test cases in disjoint random code points. To test only the compact syntax. 2677 // Rule: &q<w<e<r &w<<t<<y<<u &t<<<i<<<o<<<p &o=a=s=d 2678 private OneTestCase[] m_qwertCollationTestCases_ = { 2679 new OneTestCase("q", "w" , -1), 2680 new OneTestCase("w", "e" , -1), 2681 2682 new OneTestCase("y", "u" , -1), 2683 new OneTestCase("q", "u" , -1), 2684 2685 new OneTestCase("t", "i" , -1), 2686 new OneTestCase("o", "p" , -1), 2687 2688 new OneTestCase("y", "e" , -1), 2689 new OneTestCase("i", "u" , -1), 2690 2691 new OneTestCase("quest", "were" , -1), 2692 new OneTestCase("quack", "quest", -1) 2693 }; 2694 2695 // Tests the compact list with ASCII codepoints. 2696 @Test 2697 public void TestSameStrengthList() { 2698 String[] rules = new String[] { 2699 // Normal 2700 "&a<b<c<d &b<<k<<l<<m &k<<<x<<<y<<<z &y<f<g<h<e &a=1=2=3", 2701 2702 // Lists 2703 "&a<*bcd &b<<*klm &k<<<*xyz &y<*fghe &a=*123", 2704 2705 // Lists with quoted characters 2706 "&'\u0061'<*bcd &b<<*klm &k<<<*xyz &y<*f'\u0067\u0068'e &a=*123", 2707 }; 2708 doTestCollation(m_rangeTestCases_, rules); 2709 } 2710 2711 @Test 2712 public void TestSameStrengthListQuoted() { 2713 String[] rules = new String[] { 2714 "&'\u0061'<*bcd &b<<*klm &k<<<*xyz &y<*f'\u0067\u0068'e &a=1=2=3", 2715 "&'\u0061'<*b'\u0063'd &b<<*klm &k<<<*xyz &'\u0079'<*fgh'\u0065' " + 2716 "&a=*'\u0031\u0032\u0033'", 2717 2718 "&'\u0061'<*'\u0062'c'\u0064' &b<<*klm &k<<<*xyz &y<*fghe " + 2719 "&a=*'\u0031\u0032\u0033'", 2720 }; 2721 doTestCollation(m_rangeTestCases_, rules); 2722 } 2723 2724 // Tests the compact list with ASCII codepoints in non-codepoint order. 2725 @Test 2726 public void TestSameStrengthListQwerty() { 2727 String[] rules = new String[] { 2728 "&q<w<e<r &w<<t<<y<<u &t<<<i<<<o<<<p &o=a=s=d", // Normal 2729 "&q<*wer &w<<*tyu &t<<<*iop &o=*asd", // Lists 2730 }; 2731 2732 doTestCollation(m_qwertCollationTestCases_, rules); 2733 } 2734 2735 // Tests the compact list with supplemental codepoints. 2736 @Test 2737 public void TestSameStrengthListWithSupplementalCharacters() { 2738 String[] rules = new String[] { 2739 // ** Rule without compact list syntax ** 2740 // \u4e00 < \ufffb < \U00010000 < \U00010001 < \U00010002 2741 "&\u4e00<\ufffb<'\ud800\udc00'<'\ud800\udc01'<'\ud800\udc02' " + 2742 // \U00010000 << \U00020001 << \U00020002 \U00020002 2743 "&'\ud800\udc00'<<'\ud840\udc01'<<'\ud840\udc02'<<'\ud840\udc02' " + 2744 // \U00020001 = \U0003001 = \U0004001 = \U0004002 2745 "&'\ud840\udc01'='\ud880\udc01'='\ud8c0\udc01'='\ud8c0\udc02'", 2746 2747 // ** Rule with compact list syntax ** 2748 // \u4e00 <* \ufffb\U00010000 \U00010001 2749 "&\u4e00<*'\ufffb\ud800\udc00\ud800\udc01\ud800\udc02' " + 2750 // \U00010000 <<* \U00020001 \U00020002 2751 "&'\ud800\udc00'<<*'\ud840\udc01\ud840\udc02\ud840\udc03' " + 2752 // \U00020001 =* \U0003001 \U0003002 \U0003003 \U0004001 2753 "&'\ud840\udc01'=*'\ud880\udc01\ud880\udc02\ud880\udc03\ud8c0\udc01' " 2754 2755 }; 2756 doTestCollation(m_rangeTestCasesSupplemental_, rules); 2757 } 2758 2759 2760 // Tests the compact range syntax with ASCII codepoints. 2761 @Test 2762 public void TestSameStrengthListRanges() { 2763 String[] rules = new String[] { 2764 // Ranges 2765 "&a<*b-d &b<<*k-m &k<<<*x-z &y<*f-he &a=*1-3", 2766 2767 // Ranges with quoted characters 2768 "&'\u0061'<*'\u0062'-'\u0064' &b<<*klm &k<<<*xyz " + 2769 "&'\u0079'<*'\u0066'-'\u0068e' &a=*123", 2770 "&'\u0061'<*'\u0062'-'\u0064' " + 2771 "&b<<*'\u006B'-m &k<<<*x-'\u007a' " + 2772 "&'\u0079'<*'\u0066'-h'\u0065' &a=*'\u0031\u0032\u0033'", 2773 }; 2774 2775 doTestCollation(m_rangeTestCases_, rules); 2776 } 2777 2778 // Tests the compact range syntax with supplemental codepoints. 2779 @Test 2780 public void TestSameStrengthListRangesWithSupplementalCharacters() { 2781 String[] rules = new String[] { 2782 // \u4e00 <* \ufffb\U00010000 \U00010001 2783 "&\u4e00<*'\ufffb'\ud800\udc00-'\ud800\udc02' " + 2784 // \U00010000 <<* \U00020001 - \U00020003 2785 "&'\ud800\udc00'<<*'\ud840\udc01'-'\ud840\udc03' " + 2786 // \U00020001 =* \U0003001 \U0004001 2787 "&'\ud840\udc01'=*'\ud880\udc01'-'\ud880\udc03\ud8c0\udc01' " 2788 }; 2789 doTestCollation(m_rangeTestCasesSupplemental_, rules); 2790 } 2791 2792 // Tests the compact range syntax with special characters used as syntax characters in rules. 2793 @Test 2794 public void TestSpecialCharacters() { 2795 String rules[] = new String[] { 2796 // Normal 2797 "&';'<'+'<','<'-'<'&'<'*'", 2798 2799 // List 2800 "&';'<*'+,-&*'", 2801 2802 // Range 2803 "&';'<*'+'-'-&*'", 2804 2805 "&'\u003b'<'\u002b'<'\u002c'<'\u002d'<'\u0026'<'\u002a'", 2806 2807 "&'\u003b'<*'\u002b\u002c\u002d\u0026\u002a'", 2808 "&'\u003b'<*'\u002b\u002c\u002d\u0026\u002a'", 2809 "&'\u003b'<*'\u002b'-'\u002d\u0026\u002a'", 2810 "&'\u003b'<*'\u002b'-'\u002d\u0026\u002a'", 2811 }; 2812 OneTestCase[] testCases = new OneTestCase[] { 2813 new OneTestCase("\u003b", "\u002b", -1), // ; < + 2814 new OneTestCase("\u002b", "\u002c", -1), // + < , 2815 new OneTestCase("\u002c", "\u002d", -1), // , < - 2816 new OneTestCase("\u002d", "\u0026", -1), // - < & 2817 }; 2818 doTestCollation(testCases, rules); 2819 } 2820 2821 @Test 2822 public void TestInvalidListsAndRanges() { 2823 String[] invalidRules = new String[] { 2824 // Range not in starred expression 2825 "&\u4e00<\ufffb-'\ud800\udc02'", 2826 2827 // Range without start 2828 "&a<*-c", 2829 2830 // Range without end 2831 "&a<*b-", 2832 2833 // More than one hyphen 2834 "&a<*b-g-l", 2835 2836 // Range in the wrong order 2837 "&a<*k-b", 2838 }; 2839 for (String rule : invalidRules) { 2840 try { 2841 Collator myCollation = new RuleBasedCollator(rule); 2842 warnln("ERROR: Creation of collator didn't fail for " + rule + " when it should."); 2843 CollationTest.doTest(this, (RuleBasedCollator)myCollation, 2844 "x", 2845 "y", 2846 -1); 2847 2848 } catch (Exception e) { 2849 continue; 2850 } 2851 throw new IllegalArgumentException("ERROR: Invalid collator with rule " + rule + " worked fine."); 2852 } 2853 } 2854 2855 // This is the same example above with ' and space added. 2856 // They work a little different than expected. Desired rules are commented out. 2857 @Test 2858 public void TestQuoteAndSpace() { 2859 String rules[] = new String[] { 2860 // These are working as expected. 2861 "&';'<'+'<','<'-'<'&'<''<'*'<' '", 2862 2863 // List. Desired rule is 2864 // "&';'<*'+,-&''* '", 2865 // but it doesn't work. Instead, '' should be outside quotes as below. 2866 "&';'<*'+,-&''''* '", 2867 2868 // Range. Similar issues here as well. The following are working. 2869 //"&';'<*'+'-'-&''* '", 2870 //"&';'<*'+'-'-&'\\u0027'* '", 2871 "&';'<*'+'-'-&''''* '", 2872 //"&';'<*'+'-'-&'\\u0027'* '", 2873 2874 // The following rules are not working. 2875 // "&';'<'+'<','<'-'<'&'<\\u0027<'*'<' '", 2876 //"&'\u003b'<'\u002b'<'\u002c'<'\u002d'<'\u0026'<'\u0027'<\u002a'<'\u0020'", 2877 //"&'\u003b'<'\u002b'<'\u002c'<'\u002d'<'\u0026'<\\u0027<\u002a'<'\u0020'", 2878 }; 2879 2880 OneTestCase[] testCases = new OneTestCase[] { 2881 new OneTestCase("\u003b", "\u002b", -1), // ; < , 2882 new OneTestCase("\u002b", "\u002c", -1), // ; < , 2883 new OneTestCase("\u002c", "\u002d", -1), // , < - 2884 new OneTestCase("\u002d", "\u0026", -1), // - < & 2885 new OneTestCase("\u0026", "\u0027", -1), // & < ' 2886 new OneTestCase("\u0027", "\u002a", -1), // ' < * 2887 // new OneTestCase("\u002a", "\u0020", -1), // * < <space> 2888 }; 2889 doTestCollation(testCases, rules); 2890 } 2891 2892 /* 2893 * Tests the method public boolean equals(Object target) in CollationKey 2894 */ 2895 @Test 2896 public void TestCollationKeyEquals() { 2897 CollationKey ck = new CollationKey("", (byte[]) null); 2898 2899 // Tests when "if (!(target instanceof CollationKey))" is true 2900 if (ck.equals(new Object())) { 2901 errln("CollationKey.equals() was not suppose to return false " 2902 + "since it is comparing to a non Collation Key object."); 2903 } 2904 if (ck.equals("")) { 2905 errln("CollationKey.equals() was not suppose to return false " 2906 + "since it is comparing to a non Collation Key object."); 2907 } 2908 if (ck.equals(0)) { 2909 errln("CollationKey.equals() was not suppose to return false " 2910 + "since it is comparing to a non Collation Key object."); 2911 } 2912 if (ck.equals(0.0)) { 2913 errln("CollationKey.equals() was not suppose to return false " 2914 + "since it is comparing to a non Collation Key object."); 2915 } 2916 2917 // Tests when "if (target == null)" is true 2918 if (ck.equals((CollationKey) null)) { 2919 errln("CollationKey.equals() was not suppose to return false " 2920 + "since it is comparing to a null Collation Key object."); 2921 } 2922 } 2923 2924 /* 2925 * Tests the method public int hashCode() in CollationKey 2926 */ 2927 @Test 2928 public void TestCollationKeyHashCode() { 2929 CollationKey ck = new CollationKey("", (byte[]) null); 2930 2931 // Tests when "if (m_key_ == null)" is true 2932 if (ck.hashCode() != 1) { 2933 errln("CollationKey.hashCode() was suppose to return 1 " 2934 + "when m_key is null due a null parameter in the " + "constructor."); 2935 } 2936 } 2937 2938 /* 2939 * Tests the method public CollationKey getBound(int boundType, int noOfLevels) 2940 */ 2941 @Test 2942 public void TestGetBound() { 2943 CollationKey ck = new CollationKey("", (byte[]) null); 2944 2945 // Tests when "if (noOfLevels > Collator.PRIMARY)" is false 2946 // Tests when "default: " is true for "switch (boundType)" 2947 try { 2948 ck.getBound(BoundMode.COUNT, -1); 2949 errln("CollationKey.getBound(int,int) was suppose to return an " 2950 + "exception for an invalid boundType value."); 2951 } catch (Exception e) { 2952 } 2953 2954 // Tests when "if (noOfLevels > 0)" 2955 byte b[] = {}; 2956 CollationKey ck1 = new CollationKey("", b); 2957 try { 2958 ck1.getBound(0, 1); 2959 errln("CollationKey.getBound(int,int) was suppose to return an " 2960 + "exception a value of noOfLevels that exceeds expected."); 2961 } catch (Exception e) { 2962 } 2963 } 2964 2965 /* 2966 * Tests the method public CollationKey merge(CollationKey source) 2967 */ 2968 @Test 2969 public void TestMerge() { 2970 byte b[] = {}; 2971 CollationKey ck = new CollationKey("", b); 2972 2973 // Tests when "if (source == null || source.getLength() == 0)" is true 2974 try { 2975 ck.merge(null); 2976 errln("Collationkey.merge(CollationKey) was suppose to return " + "an exception for a null parameter."); 2977 } catch (Exception e) { 2978 } 2979 try { 2980 ck.merge(ck); 2981 errln("Collationkey.merge(CollationKey) was suppose to return " + "an exception for a null parameter."); 2982 } catch (Exception e) { 2983 } 2984 } 2985 2986 /* Test the method public int compareTo(RawCollationKey rhs) */ 2987 @Test 2988 public void TestRawCollationKeyCompareTo(){ 2989 RawCollationKey rck = new RawCollationKey(); 2990 byte[] b = {(byte) 10, (byte) 20}; 2991 RawCollationKey rck100 = new RawCollationKey(b, 2); 2992 2993 if(rck.compareTo(rck) != 0){ 2994 errln("RawCollatonKey.compareTo(RawCollationKey) was suppose to return 0 " + 2995 "for two idential RawCollationKey objects."); 2996 } 2997 2998 if(rck.compareTo(rck100) == 0){ 2999 errln("RawCollatonKey.compareTo(RawCollationKey) was not suppose to return 0 " + 3000 "for two different RawCollationKey objects."); 3001 } 3002 } 3003 3004 /* Track7223: CollationElementIterator does not return correct order for Hungarian */ 3005 @Test 3006 public void TestHungarianTailoring(){ 3007 String rules = new String("&DZ<dzs<<<Dzs<<<DZS" + 3008 "&G<gy<<<Gy<<<GY" + 3009 "&L<ly<<<Ly<<<LY" + 3010 "&N<ny<<<Ny<<<NY" + 3011 "&S<sz<<<Sz<<<SZ" + 3012 "&T<ty<<<Ty<<<TY" + 3013 "&Z<zs<<<Zs<<<ZS" + 3014 "&O<\u00f6<<<\u00d6<<\u0151<<<\u0150" + 3015 "&U<\u00fc<<<\u00dc<<\u0171<<<\u0171" + 3016 "&cs<<<ccs/cs" + 3017 "&Cs<<<Ccs/cs" + 3018 "&CS<<<CCS/CS" + 3019 "&dz<<<ddz/dz" + 3020 "&Dz<<<Ddz/dz" + 3021 "&DZ<<<DDZ/DZ" + 3022 "&dzs<<<ddzs/dzs" + 3023 "&Dzs<<<Ddzs/dzs" + 3024 "&DZS<<<DDZS/DZS" + 3025 "&gy<<<ggy/gy" + 3026 "&Gy<<<Ggy/gy" + 3027 "&GY<<<GGY/GY"); 3028 RuleBasedCollator coll; 3029 try { 3030 String str1 = "ggy"; 3031 String str2 = "GGY"; 3032 coll = new RuleBasedCollator(rules); 3033 if (coll.compare("ggy", "GGY") >= 0) { 3034 errln("TestHungarianTailoring.compare(" + str1 + ","+ str2 + 3035 ") was suppose to return -1 "); 3036 } 3037 CollationKey sortKey1 = coll.getCollationKey(str1); 3038 CollationKey sortKey2 = coll.getCollationKey(str2); 3039 if (sortKey1.compareTo(sortKey2) >= 0) { 3040 errln("TestHungarianTailoring getCollationKey(\"" + str1 +"\") was suppose "+ 3041 "less than getCollationKey(\""+ str2 + "\")."); 3042 errln(" getCollationKey(\"ggy\"):" + CollationTest.prettify(sortKey1) + 3043 " getCollationKey(\"GGY\"):" + CollationTest.prettify(sortKey2)); 3044 } 3045 3046 CollationElementIterator iter1 = coll.getCollationElementIterator(str1); 3047 CollationElementIterator iter2 = coll.getCollationElementIterator(str2); 3048 int ce1, ce2; 3049 while((ce1 = iter1.next()) != CollationElementIterator.NULLORDER && 3050 (ce2 = iter2.next()) != CollationElementIterator.NULLORDER) { 3051 if (ce1 > ce2) { 3052 errln("TestHungarianTailoring.CollationElementIterator(" + str1 + 3053 ","+ str2 + ") was suppose to return -1 "); 3054 } 3055 } 3056 } catch (Exception e) { 3057 e.printStackTrace(); 3058 } 3059 } 3060 3061 @Test 3062 public void TestImport(){ 3063 try{ 3064 RuleBasedCollator vicoll = (RuleBasedCollator)Collator.getInstance(new ULocale("vi")); 3065 RuleBasedCollator escoll = (RuleBasedCollator)Collator.getInstance(new ULocale("es")); 3066 RuleBasedCollator viescoll = new RuleBasedCollator(vicoll.getRules() + escoll.getRules()); 3067 RuleBasedCollator importviescoll = new RuleBasedCollator("[import vi][import es]"); 3068 3069 UnicodeSet tailoredSet = viescoll.getTailoredSet(); 3070 UnicodeSet importTailoredSet = importviescoll.getTailoredSet(); 3071 3072 if(!tailoredSet.equals(importTailoredSet)){ 3073 warnln("Tailored set not equal"); 3074 } 3075 3076 for (UnicodeSetIterator it = new UnicodeSetIterator(tailoredSet); it.next();) { 3077 String t = it.getString(); 3078 CollationKey sk1 = viescoll.getCollationKey(t); 3079 CollationKey sk2 = importviescoll.getCollationKey(t); 3080 if(!sk1.equals(sk2)){ 3081 warnln("Collation key's not equal for " + t); 3082 } 3083 } 3084 3085 }catch(Exception e){ 3086 // Android patch: Add --omitCollationRules to genrb. 3087 logln("ERROR: in creation of rule based collator"); 3088 // Android patch end. 3089 } 3090 } 3091 3092 @Test 3093 public void TestImportWithType(){ 3094 try{ 3095 RuleBasedCollator vicoll = (RuleBasedCollator)Collator.getInstance(new ULocale("vi")); 3096 RuleBasedCollator decoll = (RuleBasedCollator)Collator.getInstance(ULocale.forLanguageTag("de-u-co-phonebk")); 3097 RuleBasedCollator videcoll = new RuleBasedCollator(vicoll.getRules() + decoll.getRules()); 3098 RuleBasedCollator importvidecoll = new RuleBasedCollator("[import vi][import de-u-co-phonebk]"); 3099 3100 UnicodeSet tailoredSet = videcoll.getTailoredSet(); 3101 UnicodeSet importTailoredSet = importvidecoll.getTailoredSet(); 3102 3103 if(!tailoredSet.equals(importTailoredSet)){ 3104 warnln("Tailored set not equal"); 3105 } 3106 3107 for (UnicodeSetIterator it = new UnicodeSetIterator(tailoredSet); it.next();) { 3108 String t = it.getString(); 3109 CollationKey sk1 = videcoll.getCollationKey(t); 3110 CollationKey sk2 = importvidecoll.getCollationKey(t); 3111 if(!sk1.equals(sk2)){ 3112 warnln("Collation key's not equal for " + t); 3113 } 3114 } 3115 3116 }catch(Exception e){ 3117 // Android patch: Add --omitCollationRules to genrb. 3118 logln("ERROR: in creation of rule based collator"); 3119 // Android patch end. 3120 } 3121 } 3122 3123 /* 3124 * This test ensures that characters placed before a character in a different script have the same lead byte 3125 * in their collation key before and after script reordering. 3126 */ 3127 @Test 3128 public void TestBeforeRuleWithScriptReordering() throws Exception 3129 { 3130 /* build collator */ 3131 String rules = "&[before 1]\u03b1 < \u0e01"; 3132 int[] reorderCodes = {UScript.GREEK}; 3133 int result; 3134 3135 Collator myCollation = new RuleBasedCollator(rules); 3136 myCollation.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 3137 myCollation.setStrength(Collator.TERTIARY); 3138 3139 String base = "\u03b1"; /* base */ 3140 String before = "\u0e01"; /* ko kai */ 3141 3142 /* check collation results - before rule applied but not script reordering */ 3143 result = myCollation.compare(base, before); 3144 if (!(result > 0)) { 3145 errln("Collation result not correct before script reordering."); 3146 } 3147 3148 /* check the lead byte of the collation keys before script reordering */ 3149 CollationKey baseKey = myCollation.getCollationKey(base); 3150 CollationKey beforeKey = myCollation.getCollationKey(before); 3151 byte[] baseKeyBytes = baseKey.toByteArray(); 3152 byte[] beforeKeyBytes = beforeKey.toByteArray(); 3153 if (baseKeyBytes[0] != beforeKeyBytes[0]) { 3154 errln("Different lead byte for sort keys using before rule and before script reordering. base character lead byte = " 3155 + baseKeyBytes[0] + ", before character lead byte = " + beforeKeyBytes[0]); 3156 } 3157 3158 /* reorder the scripts */ 3159 myCollation.setReorderCodes(reorderCodes); 3160 3161 /* check collation results - before rule applied and after script reordering */ 3162 result = myCollation.compare(base, before); 3163 if (!(result > 0)) { 3164 errln("Collation result not correct after script reordering."); 3165 } 3166 3167 /* check the lead byte of the collation keys after script reordering */ 3168 baseKey = myCollation.getCollationKey(base); 3169 beforeKey = myCollation.getCollationKey(before); 3170 baseKeyBytes = baseKey.toByteArray(); 3171 beforeKeyBytes = beforeKey.toByteArray(); 3172 if (baseKeyBytes[0] != beforeKeyBytes[0]) { 3173 errln("Different lead byte for sort keys using before rule and before script reordering. base character lead byte = " 3174 + baseKeyBytes[0] + ", before character lead byte = " + beforeKeyBytes[0]); 3175 } 3176 } 3177 3178 /* 3179 * Test that in a primary-compressed sort key all bytes except the first one are unchanged under script reordering. 3180 */ 3181 @Test 3182 public void TestNonLeadBytesDuringCollationReordering() throws Exception 3183 { 3184 Collator myCollation; 3185 byte[] baseKey; 3186 byte[] reorderKey; 3187 int[] reorderCodes = {UScript.GREEK}; 3188 String testString = "\u03b1\u03b2\u03b3"; 3189 3190 /* build collator tertiary */ 3191 myCollation = new RuleBasedCollator(""); 3192 myCollation.setStrength(Collator.TERTIARY); 3193 baseKey = myCollation.getCollationKey(testString).toByteArray(); 3194 3195 myCollation.setReorderCodes(reorderCodes); 3196 reorderKey = myCollation.getCollationKey(testString).toByteArray(); 3197 3198 if (baseKey.length != reorderKey.length) { 3199 errln("Key lengths not the same during reordering.\n"); 3200 } 3201 3202 for (int i = 1; i < baseKey.length; i++) { 3203 if (baseKey[i] != reorderKey[i]) { 3204 errln("Collation key bytes not the same at position " + i); 3205 } 3206 } 3207 3208 /* build collator tertiary */ 3209 myCollation = new RuleBasedCollator(""); 3210 myCollation.setStrength(Collator.QUATERNARY); 3211 baseKey = myCollation.getCollationKey(testString).toByteArray(); 3212 3213 myCollation.setReorderCodes(reorderCodes); 3214 reorderKey = myCollation.getCollationKey(testString).toByteArray(); 3215 3216 if (baseKey.length != reorderKey.length) { 3217 errln("Key lengths not the same during reordering.\n"); 3218 } 3219 3220 for (int i = 1; i < baseKey.length; i++) { 3221 if (baseKey[i] != reorderKey[i]) { 3222 errln("Collation key bytes not the same at position " + i); 3223 } 3224 } 3225 } 3226 3227 /* 3228 * Test reordering API. 3229 */ 3230 @Test 3231 public void TestReorderingAPI() throws Exception 3232 { 3233 Collator myCollation; 3234 int[] reorderCodes = {UScript.GREEK, UScript.HAN, ReorderCodes.PUNCTUATION}; 3235 int[] duplicateReorderCodes = {UScript.HIRAGANA, UScript.GREEK, ReorderCodes.CURRENCY, UScript.KATAKANA}; 3236 int[] reorderCodesStartingWithDefault = {ReorderCodes.DEFAULT, UScript.GREEK, UScript.HAN, ReorderCodes.PUNCTUATION}; 3237 int[] retrievedReorderCodes; 3238 String greekString = "\u03b1"; 3239 String punctuationString = "\u203e"; 3240 3241 /* build collator tertiary */ 3242 myCollation = new RuleBasedCollator(""); 3243 myCollation.setStrength(Collator.TERTIARY); 3244 3245 /* set the reorderding */ 3246 myCollation.setReorderCodes(reorderCodes); 3247 3248 retrievedReorderCodes = myCollation.getReorderCodes(); 3249 if (!Arrays.equals(reorderCodes, retrievedReorderCodes)) { 3250 errln("ERROR: retrieved reorder codes do not match set reorder codes."); 3251 } 3252 if (!(myCollation.compare(greekString, punctuationString) < 0)) { 3253 errln("ERROR: collation result should have been less."); 3254 } 3255 3256 /* clear the reordering */ 3257 myCollation.setReorderCodes(null); 3258 retrievedReorderCodes = myCollation.getReorderCodes(); 3259 if (retrievedReorderCodes.length != 0) { 3260 errln("ERROR: retrieved reorder codes was not null."); 3261 } 3262 3263 if (!(myCollation.compare(greekString, punctuationString) > 0)) { 3264 errln("ERROR: collation result should have been greater."); 3265 } 3266 3267 // do it again with an empty but non-null array 3268 3269 /* set the reorderding */ 3270 myCollation.setReorderCodes(reorderCodes); 3271 3272 retrievedReorderCodes = myCollation.getReorderCodes(); 3273 if (!Arrays.equals(reorderCodes, retrievedReorderCodes)) { 3274 errln("ERROR: retrieved reorder codes do not match set reorder codes."); 3275 } 3276 if (!(myCollation.compare(greekString, punctuationString) < 0)) { 3277 errln("ERROR: collation result should have been less."); 3278 } 3279 3280 /* clear the reordering */ 3281 myCollation.setReorderCodes(new int[]{}); 3282 retrievedReorderCodes = myCollation.getReorderCodes(); 3283 if (retrievedReorderCodes.length != 0) { 3284 errln("ERROR: retrieved reorder codes was not null."); 3285 } 3286 3287 if (!(myCollation.compare(greekString, punctuationString) > 0)) { 3288 errln("ERROR: collation result should have been greater."); 3289 } 3290 3291 /* clear the reordering using [NONE] */ 3292 myCollation.setReorderCodes(new int[]{ ReorderCodes.NONE }); 3293 retrievedReorderCodes = myCollation.getReorderCodes(); 3294 if (retrievedReorderCodes.length != 0) { 3295 errln("ERROR: [NONE] retrieved reorder codes was not null."); 3296 } 3297 3298 boolean gotException = false; 3299 /* set duplicates in the reorder codes */ 3300 try { 3301 myCollation.setReorderCodes(duplicateReorderCodes); 3302 } catch (IllegalArgumentException e) { 3303 // expect exception on illegal arguments 3304 gotException = true; 3305 } 3306 if (!gotException) { 3307 errln("ERROR: exception was not thrown for illegal reorder codes argument."); 3308 } 3309 3310 /* set duplicate reorder codes */ 3311 gotException = false; 3312 try { 3313 myCollation.setReorderCodes(reorderCodesStartingWithDefault); 3314 } catch (IllegalArgumentException e) { 3315 gotException = true; 3316 } 3317 if (!gotException) { 3318 errln("ERROR: reorder codes following a 'default' code should have thrown an exception but did not."); 3319 } 3320 } 3321 3322 /* 3323 * Test reordering API. 3324 */ 3325 @Test 3326 public void TestReorderingAPIWithRuleCreatedCollator() throws Exception 3327 { 3328 Collator myCollation; 3329 String rules = "[reorder Hani Grek]"; 3330 int[] rulesReorderCodes = {UScript.HAN, UScript.GREEK}; 3331 int[] reorderCodes = {UScript.GREEK, UScript.HAN, ReorderCodes.PUNCTUATION}; 3332 int[] retrievedReorderCodes; 3333 3334 3335 /* build collator tertiary */ 3336 myCollation = new RuleBasedCollator(rules); 3337 myCollation.setStrength(Collator.TERTIARY); 3338 3339 retrievedReorderCodes = myCollation.getReorderCodes(); 3340 if (!Arrays.equals(rulesReorderCodes, retrievedReorderCodes)) { 3341 errln("ERROR: retrieved reorder codes do not match set reorder codes."); 3342 } 3343 3344 /* clear the reordering */ 3345 myCollation.setReorderCodes(null); 3346 retrievedReorderCodes = myCollation.getReorderCodes(); 3347 if (retrievedReorderCodes.length != 0) { 3348 errln("ERROR: retrieved reorder codes was not null."); 3349 } 3350 3351 /* set the reorderding */ 3352 myCollation.setReorderCodes(reorderCodes); 3353 3354 retrievedReorderCodes = myCollation.getReorderCodes(); 3355 if (!Arrays.equals(reorderCodes, retrievedReorderCodes)) { 3356 errln("ERROR: retrieved reorder codes do not match set reorder codes."); 3357 } 3358 3359 /* reset the reordering */ 3360 myCollation.setReorderCodes(ReorderCodes.DEFAULT); 3361 retrievedReorderCodes = myCollation.getReorderCodes(); 3362 if (!Arrays.equals(rulesReorderCodes, retrievedReorderCodes)) { 3363 errln("ERROR: retrieved reorder codes do not match set reorder codes."); 3364 } 3365 } 3366 3367 static boolean containsExpectedScript(int[] scripts, int expectedScript) { 3368 for (int i = 0; i < scripts.length; ++i) { 3369 if (expectedScript == scripts[i]) { return true; } 3370 } 3371 return false; 3372 } 3373 3374 @Test 3375 public void TestEquivalentReorderingScripts() { 3376 // Beginning with ICU 55, collation reordering moves single scripts 3377 // rather than groups of scripts, 3378 // except where scripts share a range and sort primary-equal. 3379 final int[] expectedScripts = { 3380 UScript.HIRAGANA, 3381 UScript.KATAKANA, 3382 UScript.KATAKANA_OR_HIRAGANA 3383 }; 3384 3385 int[] equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.GOTHIC); 3386 if (equivalentScripts.length != 1 || equivalentScripts[0] != UScript.GOTHIC) { 3387 errln(String.format("ERROR/Gothic: retrieved equivalent scripts wrong: " + 3388 "length expected 1, was = %d; expected [%d] was [%d]", 3389 equivalentScripts.length, UScript.GOTHIC, equivalentScripts[0])); 3390 } 3391 3392 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.HIRAGANA); 3393 if (equivalentScripts.length != expectedScripts.length) { 3394 errln(String.format("ERROR/Hiragana: retrieved equivalent script length wrong: " + 3395 "expected %d, was = %d", 3396 expectedScripts.length, equivalentScripts.length)); 3397 } 3398 int prevScript = -1; 3399 for (int i = 0; i < equivalentScripts.length; ++i) { 3400 int script = equivalentScripts[i]; 3401 if (script <= prevScript) { 3402 errln("ERROR/Hiragana: equivalent scripts out of order at index " + i); 3403 } 3404 prevScript = script; 3405 } 3406 for (int code : expectedScripts) { 3407 if (!containsExpectedScript(equivalentScripts, code)) { 3408 errln("ERROR/Hiragana: equivalent scripts do not contain " + code); 3409 } 3410 } 3411 3412 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.KATAKANA); 3413 if (equivalentScripts.length != expectedScripts.length) { 3414 errln(String.format("ERROR/Katakana: retrieved equivalent script length wrong: " + 3415 "expected %d, was = %d", 3416 expectedScripts.length, equivalentScripts.length)); 3417 } 3418 for (int code : expectedScripts) { 3419 if (!containsExpectedScript(equivalentScripts, code)) { 3420 errln("ERROR/Katakana: equivalent scripts do not contain " + code); 3421 } 3422 } 3423 3424 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.KATAKANA_OR_HIRAGANA); 3425 if (equivalentScripts.length != expectedScripts.length) { 3426 errln(String.format("ERROR/Hrkt: retrieved equivalent script length wrong: " + 3427 "expected %d, was = %d", 3428 expectedScripts.length, equivalentScripts.length)); 3429 } 3430 3431 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.HAN); 3432 if (equivalentScripts.length != 3) { 3433 errln("ERROR/Hani: retrieved equivalent script length wrong: " + 3434 "expected 3, was = " + equivalentScripts.length); 3435 } 3436 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.SIMPLIFIED_HAN); 3437 if (equivalentScripts.length != 3) { 3438 errln("ERROR/Hans: retrieved equivalent script length wrong: " + 3439 "expected 3, was = " + equivalentScripts.length); 3440 } 3441 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.TRADITIONAL_HAN); 3442 if (equivalentScripts.length != 3) { 3443 errln("ERROR/Hant: retrieved equivalent script length wrong: " + 3444 "expected 3, was = " + equivalentScripts.length); 3445 } 3446 3447 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.MEROITIC_CURSIVE); 3448 if (equivalentScripts.length != 2) { 3449 errln("ERROR/Merc: retrieved equivalent script length wrong: " + 3450 "expected 2, was = " + equivalentScripts.length); 3451 } 3452 equivalentScripts = RuleBasedCollator.getEquivalentReorderCodes(UScript.MEROITIC_HIEROGLYPHS); 3453 if (equivalentScripts.length != 2) { 3454 errln("ERROR/Mero: retrieved equivalent script length wrong: " + 3455 "expected 2, was = " + equivalentScripts.length); 3456 } 3457 } 3458 3459 @Test 3460 public void TestGreekFirstReorderCloning() { 3461 String[] testSourceCases = { 3462 "\u0041", 3463 "\u03b1\u0041", 3464 "\u0061", 3465 "\u0041\u0061", 3466 "\u0391", 3467 }; 3468 3469 String[] testTargetCases = { 3470 "\u03b1", 3471 "\u0041\u03b1", 3472 "\u0391", 3473 "\u0391\u03b1", 3474 "\u0391", 3475 }; 3476 3477 int[] results = { 3478 1, 3479 -1, 3480 1, 3481 1, 3482 0 3483 }; 3484 3485 Collator originalCollation; 3486 Collator myCollation; 3487 String rules = "[reorder Grek]"; 3488 try { 3489 originalCollation = new RuleBasedCollator(rules); 3490 } catch (Exception e) { 3491 warnln("ERROR: in creation of rule based collator"); 3492 return; 3493 } 3494 try { 3495 myCollation = (Collator) originalCollation.clone(); 3496 } catch (Exception e) { 3497 warnln("ERROR: in creation of rule based collator"); 3498 return; 3499 } 3500 myCollation.setDecomposition(Collator.CANONICAL_DECOMPOSITION); 3501 myCollation.setStrength(Collator.TERTIARY); 3502 for (int i = 0; i < testSourceCases.length ; i++) 3503 { 3504 CollationTest.doTest(this, (RuleBasedCollator)myCollation, 3505 testSourceCases[i], testTargetCases[i], 3506 results[i]); 3507 } 3508 } 3509 3510 /* 3511 * Utility function to test one collation reordering test case. 3512 * @param testcases Array of test cases. 3513 * @param n_testcases Size of the array testcases. 3514 * @param str_rules Array of rules. These rules should be specifying the same rule in different formats. 3515 * @param n_rules Size of the array str_rules. 3516 */ 3517 private void doTestOneReorderingAPITestCase(OneTestCase testCases[], int reorderTokens[]) 3518 { 3519 Collator myCollation = Collator.getInstance(ULocale.ENGLISH); 3520 myCollation.setReorderCodes(reorderTokens); 3521 3522 for (OneTestCase testCase : testCases) { 3523 CollationTest.doTest(this, (RuleBasedCollator)myCollation, 3524 testCase.m_source_, 3525 testCase.m_target_, 3526 testCase.m_result_); 3527 } 3528 } 3529 3530 @Test 3531 public void TestGreekFirstReorder() 3532 { 3533 String[] strRules = { 3534 "[reorder Grek]" 3535 }; 3536 3537 int[] apiRules = { 3538 UScript.GREEK 3539 }; 3540 3541 OneTestCase[] privateUseCharacterStrings = { 3542 new OneTestCase("\u0391", "\u0391", 0), 3543 new OneTestCase("\u0041", "\u0391", 1), 3544 new OneTestCase("\u03B1\u0041", "\u03B1\u0391", 1), 3545 new OneTestCase("\u0060", "\u0391", -1), 3546 new OneTestCase("\u0391", "\ue2dc", -1), 3547 new OneTestCase("\u0391", "\u0060", 1), 3548 }; 3549 3550 /* Test rules creation */ 3551 doTestCollation(privateUseCharacterStrings, strRules); 3552 3553 /* Test collation reordering API */ 3554 doTestOneReorderingAPITestCase(privateUseCharacterStrings, apiRules); 3555 } 3556 3557 @Test 3558 public void TestGreekLastReorder() 3559 { 3560 String[] strRules = { 3561 "[reorder Zzzz Grek]" 3562 }; 3563 3564 int[] apiRules = { 3565 UScript.UNKNOWN, UScript.GREEK 3566 }; 3567 3568 OneTestCase[] privateUseCharacterStrings = { 3569 new OneTestCase("\u0391", "\u0391", 0), 3570 new OneTestCase("\u0041", "\u0391", -1), 3571 new OneTestCase("\u03B1\u0041", "\u03B1\u0391", -1), 3572 new OneTestCase("\u0060", "\u0391", -1), 3573 new OneTestCase("\u0391", "\ue2dc", 1), 3574 }; 3575 3576 /* Test rules creation */ 3577 doTestCollation(privateUseCharacterStrings, strRules); 3578 3579 /* Test collation reordering API */ 3580 doTestOneReorderingAPITestCase(privateUseCharacterStrings, apiRules); 3581 } 3582 3583 @Test 3584 public void TestNonScriptReorder() 3585 { 3586 String[] strRules = { 3587 "[reorder Grek Symbol DIGIT Latn Punct space Zzzz cURRENCy]" 3588 }; 3589 3590 int[] apiRules = { 3591 UScript.GREEK, ReorderCodes.SYMBOL, ReorderCodes.DIGIT, UScript.LATIN, 3592 ReorderCodes.PUNCTUATION, ReorderCodes.SPACE, UScript.UNKNOWN, 3593 ReorderCodes.CURRENCY 3594 }; 3595 3596 OneTestCase[] privateUseCharacterStrings = { 3597 new OneTestCase("\u0391", "\u0041", -1), 3598 new OneTestCase("\u0041", "\u0391", 1), 3599 new OneTestCase("\u0060", "\u0041", -1), 3600 new OneTestCase("\u0060", "\u0391", 1), 3601 new OneTestCase("\u0024", "\u0041", 1), 3602 }; 3603 3604 /* Test rules creation */ 3605 doTestCollation(privateUseCharacterStrings, strRules); 3606 3607 /* Test collation reordering API */ 3608 doTestOneReorderingAPITestCase(privateUseCharacterStrings, apiRules); 3609 } 3610 3611 @Test 3612 public void TestHaniReorder() 3613 { 3614 String[] strRules = { 3615 "[reorder Hani]" 3616 }; 3617 int[] apiRules = { 3618 UScript.HAN 3619 }; 3620 3621 OneTestCase[] privateUseCharacterStrings = { 3622 new OneTestCase("\u4e00", "\u0041", -1), 3623 new OneTestCase("\u4e00", "\u0060", 1), 3624 new OneTestCase("\uD86D\uDF40", "\u0041", -1), 3625 new OneTestCase("\uD86D\uDF40", "\u0060", 1), 3626 new OneTestCase("\u4e00", "\uD86D\uDF40", -1), 3627 new OneTestCase("\ufa27", "\u0041", -1), 3628 new OneTestCase("\uD869\uDF00", "\u0041", -1), 3629 }; 3630 3631 /* Test rules creation */ 3632 doTestCollation(privateUseCharacterStrings, strRules); 3633 3634 /* Test collation reordering API */ 3635 doTestOneReorderingAPITestCase(privateUseCharacterStrings, apiRules); 3636 } 3637 3638 @Test 3639 public void TestHaniReorderWithOtherRules() 3640 { 3641 String[] strRules = { 3642 "[reorder Hani] &b<a" 3643 }; 3644 3645 OneTestCase[] privateUseCharacterStrings = { 3646 new OneTestCase("\u4e00", "\u0041", -1), 3647 new OneTestCase("\u4e00", "\u0060", 1), 3648 new OneTestCase("\uD86D\uDF40", "\u0041", -1), 3649 new OneTestCase("\uD86D\uDF40", "\u0060", 1), 3650 new OneTestCase("\u4e00", "\uD86D\uDF40", -1), 3651 new OneTestCase("\ufa27", "\u0041", -1), 3652 new OneTestCase("\uD869\uDF00", "\u0041", -1), 3653 new OneTestCase("b", "a", -1), 3654 }; 3655 3656 /* Test rules creation */ 3657 doTestCollation(privateUseCharacterStrings, strRules); 3658 } 3659 3660 @Test 3661 public void TestMultipleReorder() 3662 { 3663 String[] strRules = { 3664 "[reorder Grek Zzzz DIGIT Latn Hani]" 3665 }; 3666 3667 int[] apiRules = { 3668 UScript.GREEK, UScript.UNKNOWN, ReorderCodes.DIGIT, UScript.LATIN, UScript.HAN 3669 }; 3670 3671 OneTestCase[] collationTestCases = { 3672 new OneTestCase("\u0391", "\u0041", -1), 3673 new OneTestCase("\u0031", "\u0041", -1), 3674 new OneTestCase("u0041", "\u4e00", -1), 3675 }; 3676 3677 /* Test rules creation */ 3678 doTestCollation(collationTestCases, strRules); 3679 3680 /* Test collation reordering API */ 3681 doTestOneReorderingAPITestCase(collationTestCases, apiRules); 3682 } 3683 3684 @Test 3685 public void TestFrozeness() 3686 { 3687 Collator myCollation = Collator.getInstance(ULocale.CANADA); 3688 boolean exceptionCaught = false; 3689 3690 myCollation.freeze(); 3691 assertTrue("Collator not frozen.", myCollation.isFrozen()); 3692 3693 try { 3694 myCollation.setStrength(Collator.SECONDARY); 3695 } catch (UnsupportedOperationException e) { 3696 // expected 3697 exceptionCaught = true; 3698 } 3699 assertTrue("Frozen collator allowed change.", exceptionCaught); 3700 exceptionCaught = false; 3701 3702 try { 3703 myCollation.setReorderCodes(ReorderCodes.DEFAULT); 3704 } catch (UnsupportedOperationException e) { 3705 // expected 3706 exceptionCaught = true; 3707 } 3708 assertTrue("Frozen collator allowed change.", exceptionCaught); 3709 exceptionCaught = false; 3710 3711 try { 3712 myCollation.setVariableTop(12); 3713 } catch (UnsupportedOperationException e) { 3714 // expected 3715 exceptionCaught = true; 3716 } 3717 assertTrue("Frozen collator allowed change.", exceptionCaught); 3718 exceptionCaught = false; 3719 3720 Collator myClone = null; 3721 try { 3722 myClone = (Collator) myCollation.clone(); 3723 } catch (CloneNotSupportedException e) { 3724 // should not happen - clone is implemented in Collator 3725 errln("ERROR: unable to clone collator."); 3726 } 3727 assertTrue("Clone not frozen as expected.", myClone.isFrozen()); 3728 3729 myClone = myClone.cloneAsThawed(); 3730 assertFalse("Clone not thawed as expected.", myClone.isFrozen()); 3731 } 3732 3733 // Test case for Ticket#9409 3734 // Unknown collation type should be ignored, without printing stack trace 3735 @Test 3736 public void TestUnknownCollationKeyword() { 3737 Collator coll1 = Collator.getInstance(new ULocale("en_US@collation=bogus")); 3738 Collator coll2 = Collator.getInstance(new ULocale("en_US")); 3739 assertEquals("Unknown collation keyword 'bogus' should be ignored", coll1, coll2); 3740 } 3741 } 3742