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