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