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