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