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