// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html#License /* ******************************************************************************* * Copyright (C) 2002-2014, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* */ /** * Port From: ICU4C v2.1 : collate/CollationAPITest * Source File: $ICU4CRoot/source/test/intltest/apicoll.cpp **/ package com.ibm.icu.dev.test.collator; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.MissingResourceException; import java.util.Set; import org.junit.Test; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.impl.Utility; import com.ibm.icu.lang.UCharacter; import com.ibm.icu.text.CollationElementIterator; import com.ibm.icu.text.CollationKey; import com.ibm.icu.text.Collator; import com.ibm.icu.text.Collator.CollatorFactory; import com.ibm.icu.text.RawCollationKey; import com.ibm.icu.text.RuleBasedCollator; import com.ibm.icu.text.UCharacterIterator; import com.ibm.icu.text.UnicodeSet; import com.ibm.icu.util.ULocale; import com.ibm.icu.util.VersionInfo; public class CollationAPITest extends TestFmwk { /** * This tests the collation key related APIs. * - constructor/destructor * - Collator.getCollationKey * - == and != operators * - comparison between collation keys * - creating collation key with a byte array and vice versa */ @Test public void TestCollationKey() { logln("testing CollationKey begins..."); Collator col = Collator.getInstance(); col.setStrength(Collator.TERTIARY); String test1 = "Abcda"; String test2 = "abcda"; logln("Testing weird arguments"); CollationKey sortk1 = col.getCollationKey(""); // key gets reset here byte[] bytes = sortk1.toByteArray(); doAssert(bytes.length == 3 && bytes[0] == 1 && bytes[1] == 1 && bytes[2] == 0, "Empty string should return a collation key with empty levels"); // Most control codes and CGJ are completely ignorable. // A string with only completely ignorables must compare equal to an empty string. CollationKey sortkIgnorable = col.getCollationKey("\u0001\u034f"); doAssert(sortkIgnorable != null && sortkIgnorable.toByteArray().length == 3, "Completely ignorable string should return a collation key with empty levels"); doAssert(sortkIgnorable.compareTo(sortk1) == 0, "Completely ignorable string should compare equal to empty string"); // bogus key returned here sortk1 = col.getCollationKey(null); doAssert(sortk1 == null, "Error code should return bogus collation key"); logln("Use tertiary comparison level testing ...."); sortk1 = col.getCollationKey(test1); CollationKey sortk2 = col.getCollationKey(test2); doAssert((sortk1.compareTo(sortk2)) > 0, "Result should be \"Abcda\" >>> \"abcda\""); CollationKey sortkNew; sortkNew = sortk1; doAssert(!(sortk1.equals(sortk2)), "The sort keys should be different"); doAssert((sortk1.hashCode() != sortk2.hashCode()), "sort key hashCode() failed"); doAssert((sortk1.equals(sortkNew)), "The sort keys assignment failed"); doAssert((sortk1.hashCode() == sortkNew.hashCode()), "sort key hashCode() failed"); // port from apicoll try { col = Collator.getInstance(); } catch (Exception e) { errln("Collator.getInstance() failed"); } if (col.getStrength() != Collator.TERTIARY){ errln("Default collation did not have tertiary strength"); } // Need to use identical strength col.setStrength(Collator.IDENTICAL); CollationKey key1 = col.getCollationKey(test1); CollationKey key2 = col.getCollationKey(test2); CollationKey key3 = col.getCollationKey(test2); doAssert(key1.compareTo(key2) > 0, "Result should be \"Abcda\" > \"abcda\""); doAssert(key2.compareTo(key1) < 0, "Result should be \"abcda\" < \"Abcda\""); doAssert(key2.compareTo(key3) == 0, "Result should be \"abcda\" == \"abcda\""); byte key2identical[] = key2.toByteArray(); logln("Use secondary comparision level testing ..."); col.setStrength(Collator.SECONDARY); key1 = col.getCollationKey(test1); key2 = col.getCollationKey(test2); key3 = col.getCollationKey(test2); doAssert(key1.compareTo(key2) == 0, "Result should be \"Abcda\" == \"abcda\""); doAssert(key2.compareTo(key3) == 0, "Result should be \"abcda\" == \"abcda\""); byte tempkey[] = key2.toByteArray(); byte subkey2compat[] = new byte[tempkey.length]; System.arraycopy(key2identical, 0, subkey2compat, 0, tempkey.length); subkey2compat[subkey2compat.length - 1] = 0; doAssert(Arrays.equals(tempkey, subkey2compat), "Binary format for 'abcda' sortkey different for secondary strength!"); logln("testing sortkey ends..."); } @Test public void TestRawCollationKey() { // testing constructors RawCollationKey key = new RawCollationKey(); if (key.bytes != null || key.size != 0) { errln("Empty default constructor expected to leave the bytes null " + "and size 0"); } byte array[] = new byte[128]; key = new RawCollationKey(array); if (key.bytes != array || key.size != 0) { errln("Constructor taking an array expected to adopt it and " + "retaining its size 0"); } try { key = new RawCollationKey(array, 129); errln("Constructor taking an array and a size > array.length " + "expected to throw an exception"); } catch (IndexOutOfBoundsException e) { logln("PASS: Constructor failed as expected"); } try { key = new RawCollationKey(array, -1); errln("Constructor taking an array and a size < 0 " + "expected to throw an exception"); } catch (IndexOutOfBoundsException e) { logln("PASS: Constructor failed as expected"); } key = new RawCollationKey(array, array.length >> 1); if (key.bytes != array || key.size != (array.length >> 1)) { errln("Constructor taking an array and a size, " + "expected to adopt it and take the size specified"); } key = new RawCollationKey(10); if (key.bytes == null || key.bytes.length != 10 || key.size != 0) { errln("Constructor taking a specified capacity expected to " + "create a new internal byte array with length 10 and " + "retain size 0"); } } void doAssert(boolean conditions, String message) { if (!conditions) { errln(message); } } /** * This tests the comparison convenience methods of a collator object. * - greater than * - greater than or equal to * - equal to */ @Test public void TestCompare() { logln("The compare tests begin : "); Collator col = Collator.getInstance(Locale.ENGLISH); String test1 = "Abcda"; String test2 = "abcda"; logln("Use tertiary comparison level testing ...."); doAssert((!col.equals(test1, test2) ), "Result should be \"Abcda\" != \"abcda\""); doAssert((col.compare(test1, test2) > 0 ), "Result should be \"Abcda\" >>> \"abcda\""); col.setStrength(Collator.SECONDARY); logln("Use secondary comparison level testing ...."); doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.compare(test1, test2) == 0), "Result should be \"Abcda\" == \"abcda\""); col.setStrength(Collator.PRIMARY); logln("Use primary comparison level testing ...."); doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.compare(test1, test2) == 0 ), "Result should be \"Abcda\" == \"abcda\""); logln("The compare tests end."); } /** * Tests decomposition setting */ @Test public void TestDecomposition() { Collator en_US = null, el_GR = null, vi_VN = null; en_US = Collator.getInstance(new Locale("en", "US")); el_GR = Collator.getInstance(new Locale("el", "GR")); vi_VN = Collator.getInstance(new Locale("vi", "VN")); // there is no reason to have canonical decomposition in en_US OR default locale */ if (vi_VN.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) { errln("vi_VN collation did not have cannonical decomposition for normalization!"); } if (el_GR.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) { errln("el_GR collation did not have cannonical decomposition for normalization!"); } if (en_US.getDecomposition() != Collator.NO_DECOMPOSITION) { errln("en_US collation had cannonical decomposition for normalization!"); } } /** * This tests the duplication of a collator object. */ @Test public void TestDuplicate() { //Clone does not be implemented Collator col1 = Collator.getInstance(Locale.ENGLISH); // Collator col2 = (Collator)col1.clone(); // doAssert(col1.equals(col2), "Cloned object is not equal to the orginal"); String ruleset = "&9 < a, A < b, B < c, C < d, D, e, E"; RuleBasedCollator col3 = null; try { col3 = new RuleBasedCollator(ruleset); } catch (Exception e) { errln("Failure creating RuleBasedCollator with rule: \"" + ruleset + "\"\n" + e); return; } doAssert(!col1.equals(col3), "Cloned object is equal to some dummy"); col3 = (RuleBasedCollator)col1; doAssert(col1.equals(col3), "Copied object is not equal to the orginal"); } /** * This tests the CollationElementIterator related APIs. * - creation of a CollationElementIterator object * - == and != operators * - iterating forward * - reseting the iterator index * - requesting the order properties(primary, secondary or tertiary) */ @Test public void TestElemIter() { // logln("testing sortkey begins..."); Collator col = Collator.getInstance(Locale.ENGLISH); String testString1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; String testString2 = "Xf_ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; // logln("Constructors and comparison testing...."); CollationElementIterator iterator1 = ((RuleBasedCollator)col).getCollationElementIterator(testString1); CharacterIterator chariter=new StringCharacterIterator(testString1); // copy ctor CollationElementIterator iterator2 = ((RuleBasedCollator)col).getCollationElementIterator(chariter); UCharacterIterator uchariter=UCharacterIterator.getInstance(testString2); CollationElementIterator iterator3 = ((RuleBasedCollator)col).getCollationElementIterator(uchariter); int offset = 0; offset = iterator1.getOffset(); if (offset != 0) { errln("Error in getOffset for collation element iterator"); return; } iterator1.setOffset(6); iterator1.setOffset(0); int order1, order2, order3; order1 = iterator1.next(); doAssert(!(iterator1.equals(iterator2)), "The first iterator advance failed"); order2 = iterator2.next(); // Code coverage for dummy "not designed" hashCode() which does "assert false". try { iterator1.hashCode(); // We don't expect any particular value. } catch (AssertionError ignored) { // Expected to be thrown if assertions are enabled. } // In ICU 52 and earlier we had iterator1.equals(iterator2) // but in ICU 53 this fails because the iterators differ (String vs. CharacterIterator). // doAssert((iterator1.equals(iterator2)), "The second iterator advance failed"); doAssert(iterator1.getOffset() == iterator2.getOffset(), "The second iterator advance failed"); doAssert((order1 == order2), "The order result should be the same"); order3 = iterator3.next(); doAssert((CollationElementIterator.primaryOrder(order1) == CollationElementIterator.primaryOrder(order3)), "The primary orders should be the same"); doAssert((CollationElementIterator.secondaryOrder(order1) == CollationElementIterator.secondaryOrder(order3)), "The secondary orders should be the same"); doAssert((CollationElementIterator.tertiaryOrder(order1) == CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be the same"); order1 = iterator1.next(); order3 = iterator3.next(); doAssert((CollationElementIterator.primaryOrder(order1) == CollationElementIterator.primaryOrder(order3)), "The primary orders should be identical"); doAssert((CollationElementIterator.tertiaryOrder(order1) != CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be different"); order1 = iterator1.next(); order3 = iterator3.next(); // invalid test wrong in UCA // doAssert((CollationElementIterator.secondaryOrder(order1) != // CollationElementIterator.secondaryOrder(order3)), "The secondary orders should not be the same"); doAssert((order1 != CollationElementIterator.NULLORDER), "Unexpected end of iterator reached"); iterator1.reset(); iterator2.reset(); iterator3.reset(); order1 = iterator1.next(); doAssert(!(iterator1.equals(iterator2)), "The first iterator advance failed"); order2 = iterator2.next(); // In ICU 52 and earlier we had iterator1.equals(iterator2) // but in ICU 53 this fails because the iterators differ (String vs. CharacterIterator). // doAssert((iterator1.equals(iterator2)), "The second iterator advance failed"); doAssert(iterator1.getOffset() == iterator2.getOffset(), "The second iterator advance failed"); doAssert((order1 == order2), "The order result should be the same"); order3 = iterator3.next(); doAssert((CollationElementIterator.primaryOrder(order1) == CollationElementIterator.primaryOrder(order3)), "The primary orders should be the same"); doAssert((CollationElementIterator.secondaryOrder(order1) == CollationElementIterator.secondaryOrder(order3)), "The secondary orders should be the same"); doAssert((CollationElementIterator.tertiaryOrder(order1) == CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be the same"); order1 = iterator1.next(); order2 = iterator2.next(); order3 = iterator3.next(); doAssert((CollationElementIterator.primaryOrder(order1) == CollationElementIterator.primaryOrder(order3)), "The primary orders should be identical"); doAssert((CollationElementIterator.tertiaryOrder(order1) != CollationElementIterator.tertiaryOrder(order3)), "The tertiary orders should be different"); order1 = iterator1.next(); order3 = iterator3.next(); // obsolete invalid test, removed // doAssert((CollationElementIterator.secondaryOrder(order1) != // CollationElementIterator.secondaryOrder(order3)), "The secondary orders should not be the same"); doAssert((order1 != CollationElementIterator.NULLORDER), "Unexpected end of iterator reached"); doAssert(!(iterator2.equals(iterator3)), "The iterators should be different"); logln("testing CollationElementIterator ends..."); } /** * This tests the hashCode method of a collator object. */ @Test public void TestHashCode() { logln("hashCode tests begin."); Collator col1 = Collator.getInstance(Locale.ENGLISH); Collator col2 = null; Locale dk = new Locale("da", "DK", ""); try { col2 = Collator.getInstance(dk); } catch (Exception e) { errln("Danish collation creation failed."); return; } Collator col3 = null; try { col3 = Collator.getInstance(Locale.ENGLISH); } catch (Exception e) { errln("2nd default collation creation failed."); return; } logln("Collator.hashCode() testing ..."); doAssert(col1.hashCode() != col2.hashCode(), "Hash test1 result incorrect" ); doAssert(!(col1.hashCode() == col2.hashCode()), "Hash test2 result incorrect" ); doAssert(col1.hashCode() == col3.hashCode(), "Hash result not equal" ); logln("hashCode tests end."); String test1 = "Abcda"; String test2 = "abcda"; CollationKey sortk1, sortk2, sortk3; sortk1 = col3.getCollationKey(test1); sortk2 = col3.getCollationKey(test2); sortk3 = col3.getCollationKey(test2); doAssert(sortk1.hashCode() != sortk2.hashCode(), "Hash test1 result incorrect"); doAssert(sortk2.hashCode() == sortk3.hashCode(), "Hash result not equal" ); } /** * This tests the properties of a collator object. * - constructor * - factory method getInstance * - compare and getCollationKey * - get/set decomposition mode and comparison level */ @Test public void TestProperty() { /* All the collations have the same version in an ICU version. ICU 2.0 currVersionArray = {0x18, 0xC0, 0x02, 0x02}; ICU 2.1 currVersionArray = {0x19, 0x00, 0x03, 0x03}; ICU 2.8 currVersionArray = {0x29, 0x80, 0x00, 0x04}; */ logln("The property tests begin : "); logln("Test ctors : "); Collator col = Collator.getInstance(Locale.ENGLISH); logln("Test getVersion"); // Check for a version greater than some value rather than equality // so that we need not update the expected version each time. VersionInfo expectedVersion = VersionInfo.getInstance(0x31, 0xC0, 0x00, 0x05); // from ICU 4.4/UCA 5.2 doAssert(col.getVersion().compareTo(expectedVersion) >= 0, "Expected minimum version "+expectedVersion.toString()+" got "+col.getVersion().toString()); logln("Test getUCAVersion"); // Assume that the UCD and UCA versions are the same, // rather than hardcoding (and updating each time) a particular UCA version. VersionInfo ucdVersion = UCharacter.getUnicodeVersion(); VersionInfo ucaVersion = col.getUCAVersion(); doAssert(ucaVersion.equals(ucdVersion), "Expected UCA version "+ucdVersion.toString()+" got "+col.getUCAVersion().toString()); doAssert((col.compare("ab", "abc") < 0), "ab < abc comparison failed"); doAssert((col.compare("ab", "AB") < 0), "ab < AB comparison failed"); doAssert((col.compare("blackbird", "black-bird") > 0), "black-bird > blackbird comparison failed"); doAssert((col.compare("black bird", "black-bird") < 0), "black bird > black-bird comparison failed"); doAssert((col.compare("Hello", "hello") > 0), "Hello > hello comparison failed"); logln("Test ctors ends."); logln("testing Collator.getStrength() method ..."); doAssert((col.getStrength() == Collator.TERTIARY), "collation object has the wrong strength"); doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); logln("testing Collator.setStrength() method ..."); col.setStrength(Collator.SECONDARY); doAssert((col.getStrength() != Collator.TERTIARY), "collation object's strength is secondary difference"); doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); doAssert((col.getStrength() == Collator.SECONDARY), "collation object has the wrong strength"); logln("testing Collator.setDecomposition() method ..."); col.setDecomposition(Collator.NO_DECOMPOSITION); doAssert((col.getDecomposition() != Collator.CANONICAL_DECOMPOSITION), "Decomposition mode != Collator.CANONICAL_DECOMPOSITION"); doAssert((col.getDecomposition() == Collator.NO_DECOMPOSITION), "Decomposition mode = Collator.NO_DECOMPOSITION"); // Android patch: Add --omitCollationRules to genrb. // RuleBasedCollator rcol = (RuleBasedCollator)Collator.getInstance(new Locale("da", "DK")); // doAssert(rcol.getRules().length() != 0, "da_DK rules does not have length 0"); // Android patch end. try { col = Collator.getInstance(Locale.FRENCH); } catch (Exception e) { errln("Creating French collation failed."); return; } col.setStrength(Collator.PRIMARY); logln("testing Collator.getStrength() method again ..."); doAssert((col.getStrength() != Collator.TERTIARY), "collation object has the wrong strength"); doAssert((col.getStrength() == Collator.PRIMARY), "collation object's strength is not primary difference"); logln("testing French Collator.setStrength() method ..."); col.setStrength(Collator.TERTIARY); doAssert((col.getStrength() == Collator.TERTIARY), "collation object's strength is not tertiary difference"); doAssert((col.getStrength() != Collator.PRIMARY), "collation object's strength is primary difference"); doAssert((col.getStrength() != Collator.SECONDARY), "collation object's strength is secondary difference"); } @Test public void TestJunkCollator(){ logln("Create junk collation: "); Locale abcd = new Locale("ab", "CD", ""); Collator junk = Collator.getInstance(abcd); Collator col = Collator.getInstance(); String colrules = ((RuleBasedCollator)col).getRules(); String junkrules = ((RuleBasedCollator)junk).getRules(); doAssert(colrules == junkrules || colrules.equals(junkrules), "The default collation should be returned."); Collator frCol = null; try { frCol = Collator.getInstance(Locale.CANADA_FRENCH); } catch (Exception e) { errln("Creating fr_CA collator failed."); return; } doAssert(!(frCol.equals(junk)), "The junk is the same as the fr_CA collator."); logln("Collator property test ended."); } /** * This tests the RuleBasedCollator * - constructor/destructor * - getRules */ @Test public void TestRuleBasedColl() { RuleBasedCollator col1 = null, col2 = null, col3 = null, col4 = null; String ruleset1 = "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E"; String ruleset2 = "&9 < a, A < b, B < c, C < d, D, e, E"; String ruleset3 = "&"; try { col1 = new RuleBasedCollator(ruleset1); } catch (Exception e) { // only first error needs to be a warning since we exit function warnln("RuleBased Collator creation failed."); return; } try { col2 = new RuleBasedCollator(ruleset2); } catch (Exception e) { errln("RuleBased Collator creation failed."); return; } try { // empty rules fail col3 = new RuleBasedCollator(ruleset3); errln("Failure: Empty rules for the collator should fail"); return; } catch (MissingResourceException e) { warnln(e.getMessage()); } catch (Exception e) { logln("PASS: Empty rules for the collator failed as expected"); } Locale locale = new Locale("aa", "AA"); try { col3 = (RuleBasedCollator)Collator.getInstance(locale); } catch (Exception e) { errln("Fallback Collator creation failed.: %s"); return; } try { col3 = (RuleBasedCollator)Collator.getInstance(); } catch (Exception e) { errln("Default Collator creation failed.: %s"); return; } String rule1 = col1.getRules(); String rule2 = col2.getRules(); String rule3 = col3.getRules(); doAssert(!rule1.equals(rule2), "Default collator getRules failed"); doAssert(!rule2.equals(rule3), "Default collator getRules failed"); doAssert(!rule1.equals(rule3), "Default collator getRules failed"); try { col4 = new RuleBasedCollator(rule2); } catch (Exception e) { errln("RuleBased Collator creation failed."); return; } String rule4 = col4.getRules(); doAssert(rule2.equals(rule4), "Default collator getRules failed"); // tests that modifier ! is always ignored String exclamationrules = "!&a 0, "Result should be \"abCda\" >>> \"abcda\" "); doAssert(someCollators[index].compare(test1, test2) == 0, "Result should be \"abCda\" == \"abcda\" "); } } @Test public void TestGetTailoredSet() { logln("testing getTailoredSet..."); String rules[] = { "&a < \u212b", "& S < \u0161 <<< \u0160", }; String data[][] = { { "\u212b", "A\u030a", "\u00c5" }, { "\u0161", "s\u030C", "\u0160", "S\u030C" } }; int i = 0, j = 0; RuleBasedCollator coll; UnicodeSet set; for(i = 0; i < rules.length; i++) { try { logln("Instantiating a collator from "+rules[i]); coll = new RuleBasedCollator(rules[i]); set = coll.getTailoredSet(); logln("Got set: "+set.toPattern(true)); if(set.size() < data[i].length) { errln("Tailored set size smaller ("+set.size()+") than expected ("+data[i].length+")"); } for(j = 0; j < data[i].length; j++) { logln("Checking to see whether "+data[i][j]+" is in set"); if(!set.contains(data[i][j])) { errln("Tailored set doesn't contain "+data[i][j]+"... It should"); } } } catch (Exception e) { warnln("Couldn't open collator with rules "+ rules[i]); } } } /** * Simple test to see if Collator is subclassable. * Also test coverage of base class methods that are overridden by RuleBasedCollator. */ @Test public void TestSubClass() { class TestCollator extends Collator { @Override public boolean equals(Object that) { return this == that; } @Override public int hashCode() { return 0; } @Override public int compare(String source, String target) { return source.compareTo(target); } @Override public CollationKey getCollationKey(String source) { return new CollationKey(source, getRawCollationKey(source, new RawCollationKey())); } @Override public RawCollationKey getRawCollationKey(String source, RawCollationKey key) { byte temp1[] = source.getBytes(); byte temp2[] = new byte[temp1.length + 1]; System.arraycopy(temp1, 0, temp2, 0, temp1.length); temp2[temp1.length] = 0; if (key == null) { key = new RawCollationKey(); } key.bytes = temp2; key.size = temp2.length; return key; } @Override public void setVariableTop(int ce) { if (isFrozen()) { throw new UnsupportedOperationException("Attempt to modify frozen object"); } } @Override public int setVariableTop(String str) { if (isFrozen()) { throw new UnsupportedOperationException("Attempt to modify frozen object"); } return 0; } @Override public int getVariableTop() { return 0; } @Override public VersionInfo getVersion() { return VersionInfo.getInstance(0); } @Override public VersionInfo getUCAVersion() { return VersionInfo.getInstance(0); } } Collator col1 = new TestCollator(); Collator col2 = new TestCollator(); if (col1.equals(col2)) { errln("2 different instance of TestCollator should fail"); } if (col1.hashCode() != col2.hashCode()) { errln("Every TestCollator has the same hashcode"); } String abc = "abc"; String bcd = "bcd"; if (col1.compare(abc, bcd) != abc.compareTo(bcd)) { errln("TestCollator compare should be the same as the default " + "string comparison"); } CollationKey key = col1.getCollationKey(abc); byte temp1[] = abc.getBytes(); byte temp2[] = new byte[temp1.length + 1]; System.arraycopy(temp1, 0, temp2, 0, temp1.length); temp2[temp1.length] = 0; if (!java.util.Arrays.equals(key.toByteArray(), temp2) || !key.getSourceString().equals(abc)) { errln("TestCollator collationkey API is returning wrong values"); } UnicodeSet set = col1.getTailoredSet(); if (!set.equals(new UnicodeSet(0, 0x10FFFF))) { errln("Error getting default tailored set"); } // Base class code coverage. // Most of these methods are dummies; // they are overridden by any subclass that supports their features. assertEquals("compare(strings as Object)", 0, col1.compare(new StringBuilder("abc"), new StringBuffer("abc"))); col1.setStrength(Collator.SECONDARY); assertNotEquals("getStrength()", Collator.PRIMARY, col1.getStrength()); // setStrength2() is @internal and returns this. // The base class getStrength() always returns the same value, // since the base class does not have a field to store the strength. assertNotEquals("setStrength2().getStrength()", Collator.PRIMARY, col1.setStrength2(Collator.IDENTICAL).getStrength()); // (base class).setDecomposition() may or may not be implemented. try { col1.setDecomposition(Collator.CANONICAL_DECOMPOSITION); } catch (UnsupportedOperationException expected) { } assertNotEquals("getDecomposition()", -1, col1.getDecomposition()); // don't care about the value // (base class).setMaxVariable() may or may not be implemented. try { col1.setMaxVariable(Collator.ReorderCodes.CURRENCY); } catch (UnsupportedOperationException expected) { } assertNotEquals("getMaxVariable()", -1, col1.getMaxVariable()); // don't care about the value // (base class).setReorderCodes() may or may not be implemented. try { col1.setReorderCodes(0, 1, 2); } catch (UnsupportedOperationException expected) { } try { col1.getReorderCodes(); } catch (UnsupportedOperationException expected) { } assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN).isEmpty()); assertFalse("getDisplayName()", Collator.getDisplayName(Locale.GERMAN, Locale.ITALIAN).isEmpty()); assertNotEquals("getLocale()", ULocale.GERMAN, col1.getLocale(ULocale.ACTUAL_LOCALE)); // Cover Collator.setLocale() which is only package-visible. Object token = Collator.registerInstance(new TestCollator(), new ULocale("de-Japn-419")); Collator.unregister(token); // Freezable default implementations. freeze() may or may not be implemented. assertFalse("not yet frozen", col2.isFrozen()); try { col2.freeze(); assertTrue("now frozen", col2.isFrozen()); } catch (UnsupportedOperationException expected) { } try { col2.setStrength(Collator.PRIMARY); if (col2.isFrozen()) { fail("(frozen Collator).setStrength() should throw an exception"); } } catch (UnsupportedOperationException expected) { } try { Collator col3 = col2.cloneAsThawed(); assertFalse("!cloneAsThawed().isFrozen()", col3.isFrozen()); } catch (UnsupportedOperationException expected) { } } /** * Simple test the collator setter and getters. * Similar to C++ apicoll.cpp TestAttribute(). */ @Test public void TestSetGet() { RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(); int decomp = collator.getDecomposition(); int strength = collator.getStrength(); boolean alt = collator.isAlternateHandlingShifted(); boolean caselevel = collator.isCaseLevel(); boolean french = collator.isFrenchCollation(); boolean hquart = collator.isHiraganaQuaternary(); boolean lowercase = collator.isLowerCaseFirst(); boolean uppercase = collator.isUpperCaseFirst(); collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); if (collator.getDecomposition() != Collator.CANONICAL_DECOMPOSITION) { errln("Setting decomposition failed"); } collator.setStrength(Collator.QUATERNARY); if (collator.getStrength() != Collator.QUATERNARY) { errln("Setting strength failed"); } collator.setAlternateHandlingShifted(!alt); if (collator.isAlternateHandlingShifted() == alt) { errln("Setting alternate handling failed"); } collator.setCaseLevel(!caselevel); if (collator.isCaseLevel() == caselevel) { errln("Setting case level failed"); } collator.setFrenchCollation(!french); if (collator.isFrenchCollation() == french) { errln("Setting french collation failed"); } collator.setHiraganaQuaternary(!hquart); if (collator.isHiraganaQuaternary() != hquart) { errln("Setting hiragana quartenary worked but should be a no-op since ICU 50"); } collator.setLowerCaseFirst(!lowercase); if (collator.isLowerCaseFirst() == lowercase) { errln("Setting lower case first failed"); } collator.setUpperCaseFirst(!uppercase); if (collator.isUpperCaseFirst() == uppercase) { errln("Setting upper case first failed"); } collator.setDecompositionDefault(); if (collator.getDecomposition() != decomp) { errln("Setting decomposition default failed"); } collator.setStrengthDefault(); if (collator.getStrength() != strength) { errln("Setting strength default failed"); } collator.setAlternateHandlingDefault(); if (collator.isAlternateHandlingShifted() != alt) { errln("Setting alternate handling default failed"); } collator.setCaseLevelDefault(); if (collator.isCaseLevel() != caselevel) { errln("Setting case level default failed"); } collator.setFrenchCollationDefault(); if (collator.isFrenchCollation() != french) { errln("Setting french handling default failed"); } collator.setHiraganaQuaternaryDefault(); if (collator.isHiraganaQuaternary() != hquart) { errln("Setting Hiragana Quartenary default failed"); } collator.setCaseFirstDefault(); if (collator.isLowerCaseFirst() != lowercase || collator.isUpperCaseFirst() != uppercase) { errln("Setting case first handling default failed"); } } @Test public void TestVariableTopSetting() { // Use the root collator, not the default collator. // This test fails with en_US_POSIX which tailors the dollar sign after 'A'. RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(ULocale.ROOT); int oldVarTop = coll.getVariableTop(); // ICU 53+: The character must be in a supported reordering group, // and the variable top is pinned to the end of that group. try { coll.setVariableTop("A"); errln("setVariableTop(letter) did not detect illegal argument"); } catch(IllegalArgumentException expected) { } // dollar sign (currency symbol) int newVarTop = coll.setVariableTop("$"); if(newVarTop != coll.getVariableTop()) { errln("setVariableTop(dollar sign) != following getVariableTop()"); } String dollar = "$"; String euro = "\u20AC"; int newVarTop2 = coll.setVariableTop(euro); assertEquals("setVariableTop(Euro sign) == following getVariableTop()", newVarTop2, coll.getVariableTop()); assertEquals("setVariableTop(Euro sign) == setVariableTop(dollar sign) (should pin to top of currency group)", newVarTop2, newVarTop); coll.setAlternateHandlingShifted(true); assertEquals("empty==dollar", 0, coll.compare("", dollar)); // UCOL_EQUAL assertEquals("empty==euro", 0, coll.compare("", euro)); // UCOL_EQUAL assertEquals("dollar 0) { errln("Problem with lower bound at i = " + i + " j = " + j + " k = " + k); } if (upper.compareTo(testKey[k]) <= 0) { errln("Problem with upper bound at i = " + i + " j = " + j + " k = " + k); } } } } for (int i = 0; i < test.length; i ++) { CollationKey key = coll.getCollationKey(test[i]); CollationKey lower = key.getBound(CollationKey.BoundMode.LOWER, Collator.SECONDARY); CollationKey upper = key.getBound(CollationKey.BoundMode.UPPER_LONG, Collator.SECONDARY); for (int j = i + 1; j < test.length; j ++) { key = coll.getCollationKey(test[j]); if (lower.compareTo(key) > 0) { errln("Problem with lower bound i = " + i + " j = " + j); } if (upper.compareTo(key) <= 0) { errln("Problem with upper bound i = " + i + " j = " + j); } } } } public final void TestGetAll() { Locale[] list = Collator.getAvailableLocales(); int errorCount = 0; for (int i = 0; i < list.length; ++i) { log("Locale name: "); log(list[i].toString()); log(" , the display name is : "); logln(list[i].getDisplayName()); try{ logln(" ...... Or display as: " + Collator.getDisplayName(list[i])); logln(" ...... and display in Chinese: " + Collator.getDisplayName(list[i],Locale.CHINA)); }catch(MissingResourceException ex){ errorCount++; logln("could not get displayName for " + list[i]); } } if(errorCount>0){ warnln("Could not load the locale data."); } } private boolean doSetsTest(UnicodeSet ref, UnicodeSet set, String inSet, String outSet) { boolean ok = true; set.clear(); set.applyPattern(inSet); if(!ref.containsAll(set)) { err("Some stuff from "+inSet+" is not present in the set.\nMissing:"+ set.removeAll(ref).toPattern(true)+"\n"); ok = false; } set.clear(); set.applyPattern(outSet); if(!ref.containsNone(set)) { err("Some stuff from "+outSet+" is present in the set.\nUnexpected:"+ set.retainAll(ref).toPattern(true)+"\n"); ok = false; } return ok; } // capitst.c/TestGetContractionsAndUnsafes() @Test public void TestGetContractions() throws Exception { /* static struct { const char* locale; const char* inConts; const char* outConts; const char* inExp; const char* outExp; const char* unsafeCodeUnits; const char* safeCodeUnits; } */ String tests[][] = { { "ru", "[{\u0418\u0306}{\u0438\u0306}]", "[\u0439\u0457]", "[\u00e6]", "[ae]", "[\u0418\u0438]", "[aAbBxv]" }, { "uk", "[{\u0406\u0308}{\u0456\u0308}{\u0418\u0306}{\u0438\u0306}]", "[\u0407\u0419\u0439\u0457]", "[\u00e6]", "[ae]", "[\u0406\u0456\u0418\u0438]", "[aAbBxv]" }, { "sh", "[{C\u0301}{C\u030C}{C\u0341}{DZ\u030C}{Dz\u030C}{D\u017D}{D\u017E}{lj}{nj}]", "[{\u309d\u3099}{\u30fd\u3099}]", "[\u00e6]", "[a]", "[nlcdzNLCDZ]", "[jabv]" }, { "ja", /* * The "collv2" builder omits mappings if the collator maps their * character sequences to the same CEs. * For example, it omits Japanese contractions for NFD forms * of the voiced iteration mark (U+309E = U+309D + U+3099), such as * {\u3053\u3099\u309D\u3099}{\u3053\u309D\u3099} * {\u30B3\u3099\u30FD\u3099}{\u30B3\u30FD\u3099}. * It does add mappings for the precomposed forms. */ "[{\u3053\u3099\u309D}{\u3053\u3099\u309E}{\u3053\u3099\u30FC}" + "{\u3053\u309D}{\u3053\u309E}{\u3053\u30FC}" + "{\u30B3\u3099\u30FC}{\u30B3\u3099\u30FD}{\u30B3\u3099\u30FE}" + "{\u30B3\u30FC}{\u30B3\u30FD}{\u30B3\u30FE}]", "[{\u30FD\u3099}{\u309D\u3099}{\u3053\u3099}{\u30B3\u3099}{lj}{nj}]", "[\u30FE\u00e6]", "[a]", "[\u3099]", "[]" } }; RuleBasedCollator coll = null; int i = 0; UnicodeSet conts = new UnicodeSet(); UnicodeSet exp = new UnicodeSet(); UnicodeSet set = new UnicodeSet(); for(i = 0; i < tests.length; i++) { logln("Testing locale: "+ tests[i][0]); coll = (RuleBasedCollator)Collator.getInstance(new ULocale(tests[i][0])); coll.getContractionsAndExpansions(conts, exp, true); boolean ok = true; logln("Contractions "+conts.size()+":\n"+conts.toPattern(true)); ok &= doSetsTest(conts, set, tests[i][1], tests[i][2]); logln("Expansions "+exp.size()+":\n"+exp.toPattern(true)); ok &= doSetsTest(exp, set, tests[i][3], tests[i][4]); if(!ok) { // In case of failure, log the rule string for better diagnostics. String rules = coll.getRules(false); logln("Collation rules (getLocale()="+ coll.getLocale(ULocale.ACTUAL_LOCALE).toString()+"): "+ Utility.escape(rules)); } // No unsafe set in ICU4J //noConts = ucol_getUnsafeSet(coll, conts, &status); //doSetsTest(conts, set, tests[i][5], tests[i][6]); //log_verbose("Unsafes "+conts.size()+":\n"+conts.toPattern(true)+"\n"); } } private static final String bigone = "One"; private static final String littleone = "one"; @Test public void TestClone() { logln("\ninit c0"); RuleBasedCollator c0 = (RuleBasedCollator)Collator.getInstance(); c0.setStrength(Collator.TERTIARY); dump("c0", c0); logln("\ninit c1"); RuleBasedCollator c1 = (RuleBasedCollator)Collator.getInstance(); c1.setStrength(Collator.TERTIARY); c1.setUpperCaseFirst(!c1.isUpperCaseFirst()); dump("c0", c0); dump("c1", c1); try{ logln("\ninit c2"); RuleBasedCollator c2 = (RuleBasedCollator)c1.clone(); c2.setUpperCaseFirst(!c2.isUpperCaseFirst()); dump("c0", c0); dump("c1", c1); dump("c2", c2); if(c1.equals(c2)){ errln("The cloned objects refer to same data"); } }catch(CloneNotSupportedException ex){ errln("Could not clone the collator"); } } private void dump(String msg, RuleBasedCollator c) { logln(msg + " " + c.compare(bigone, littleone) + " s: " + c.getStrength() + " u: " + c.isUpperCaseFirst()); } @Test public void TestIterNumeric() throws Exception { // misnomer for Java, but parallel with C++ test // Regression test for ticket #9915. // The collation code sometimes masked the continuation marker away // but later tested the result for isContinuation(). // This test case failed because the third bytes of the computed numeric-collation primaries // were permutated with the script reordering table. // It should have been possible to reproduce this with the root collator // and characters with appropriate 3-byte primary weights. // The effectiveness of this test depends completely on the collation elements // and on the implementation code. RuleBasedCollator coll = new RuleBasedCollator("[reorder Hang Hani]"); coll.setNumericCollation(true); int result = coll.compare("40", "72"); assertTrue("40<72", result < 0); } /* * Tests the method public void setStrength(int newStrength) */ @Test public void TestSetStrength() { // Tests when if ((newStrength != PRIMARY) && ... ) is true int[] cases = { -1, 4, 5 }; for (int i = 0; i < cases.length; i++) { try { // Assuming -1 is not one of the values Collator c = Collator.getInstance(); c.setStrength(cases[i]); errln("Collator.setStrength(int) is suppose to return " + "an exception for an invalid newStrength value of " + cases[i]); } catch (Exception e) { } } } /* * Tests the method public void setDecomposition(int decomposition) */ @Test public void TestSetDecomposition() { // Tests when if ((decomposition != NO_DECOMPOSITION) && ...) is true int[] cases = { 0, 1, 14, 15, 18, 19 }; for (int i = 0; i < cases.length; i++) { try { // Assuming -1 is not one of the values Collator c = Collator.getInstance(); c.setDecomposition(cases[i]); errln("Collator.setDecomposition(int) is suppose to return " + "an exception for an invalid decomposition value of " + cases[i]); } catch (Exception e) { } } } /* * Tests the class CollatorFactory */ @Test public void TestCreateCollator() { // The following class override public Collator createCollator(Locale loc) class TestCreateCollator extends CollatorFactory { @Override public Set getSupportedLocaleIDs() { return new HashSet(); } public TestCreateCollator() { super(); } @Override public Collator createCollator(ULocale c) { return null; } } // The following class override public Collator createCollator(ULocale loc) class TestCreateCollator1 extends CollatorFactory { @Override public Set getSupportedLocaleIDs() { return new HashSet(); } public TestCreateCollator1() { super(); } @Override public Collator createCollator(Locale c) { return null; } @Override public boolean visible(){ return false; } } /* * Tests the method public Collator createCollator(Locale loc) using TestCreateCollator1 class */ try { TestCreateCollator tcc = new TestCreateCollator(); tcc.createCollator(new Locale("en_US")); } catch (Exception e) { errln("Collator.createCollator(Locale) was not suppose to " + "return an exception."); } /* * Tests the method public Collator createCollator(ULocale loc) using TestCreateCollator1 class */ try { TestCreateCollator1 tcc = new TestCreateCollator1(); tcc.createCollator(new ULocale("en_US")); } catch (Exception e) { errln("Collator.createCollator(ULocale) was not suppose to " + "return an exception."); } /* * Tests the method public String getDisplayName(Locale objectLocale, Locale displayLocale) using TestCreateCollator1 class */ try { TestCreateCollator tcc = new TestCreateCollator(); tcc.getDisplayName(new Locale("en_US"), new Locale("jp_JP")); } catch (Exception e) { errln("Collator.getDisplayName(Locale,Locale) was not suppose to return an exception."); } /* * Tests the method public String getDisplayName(ULocale objectLocale, ULocale displayLocale) using TestCreateCollator1 class */ try { TestCreateCollator1 tcc = new TestCreateCollator1(); tcc.getDisplayName(new ULocale("en_US"), new ULocale("jp_JP")); } catch (Exception e) { errln("Collator.getDisplayName(ULocale,ULocale) was not suppose to return an exception."); } } /* Tests the method * public static final String[] getKeywordValues(String keyword) */ @SuppressWarnings("static-access") @Test public void TestGetKeywordValues(){ // Tests when "if (!keyword.equals(KEYWORDS[0]))" is true String[] cases = {"","dummy"}; for(int i=0; i