/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2004, International Business Machines Corporation and
+ * Copyright (c) 1997-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
//===============================================================================
#if !UCONFIG_NO_COLLATION
+#include "unicode/localpointer.h"
#include "unicode/coll.h"
#include "unicode/tblcoll.h"
#include "unicode/coleitr.h"
#include "unicode/chariter.h"
#include "unicode/schriter.h"
#include "unicode/ustring.h"
+#include "unicode/ucol.h"
#include "sfwdchit.h"
#include "cmemory.h"
+#include <stdlib.h>
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
void
CollationAPITest::doAssert(UBool condition, const char *message)
UErrorCode success = U_ZERO_ERROR;
Collator *col = 0;
/*
- 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.2 currVersionArray = {0x21, 0x40, 0x04, 0x04};
- ICU 2.4 currVersionArray = {0x21, 0x40, 0x04, 0x04};
- ICU 2.6 currVersionArray = {0x21, 0x40, 0x03, 0x03};
- */
- UVersionInfo currVersionArray = {0x29, 0x80, 0x00, 0x04};
+ * Expected version of the English collator.
+ * Currently, the major/minor version numbers change when the builder code
+ * changes,
+ * number 2 is from the tailoring data version and
+ * number 3 is the UCA version.
+ * This changes with every UCA version change, and the expected value
+ * needs to be adjusted.
+ * Same in cintltst/capitst.c.
+ */
+ UVersionInfo currVersionArray = {0x31, 0xC0, 0x05, 0x2A}; // from ICU 4.4/UCA 5.2
UVersionInfo versionArray;
- int i = 0;
logln("The property tests begin : ");
logln("Test ctors : ");
col = Collator::createInstance(Locale::getEnglish(), success);
+ if (U_FAILURE(success)){
+ errcheckln(success, "Default Collator creation failed. - %s", u_errorName(success));
+ return;
+ }
- if (U_FAILURE(success))
- {
- errln("Default Collator creation failed.");
+ StringEnumeration* kwEnum = col->getKeywordValuesForLocale("", Locale::getEnglish(),true,success);
+ if (U_FAILURE(success)){
+ errcheckln(success, "Get Keyword Values for Locale failed. - %s", u_errorName(success));
return;
}
+ delete kwEnum;
col->getVersion(versionArray);
- for (i=0; i<4; ++i) {
- if (versionArray[i] != currVersionArray[i]) {
- errln("Testing ucol_getVersion() - unexpected result: %d.%d.%d.%d",
+ // Check for a version greater than some value rather than equality
+ // so that we need not update the expected version each time.
+ if (uprv_memcmp(versionArray, currVersionArray, 4)<0) {
+ errln("Testing Collator::getVersion() - unexpected result: %02x.%02x.%02x.%02x",
+ versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
+ } else {
+ logln("Collator::getVersion() result: %02x.%02x.%02x.%02x",
versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
- break;
- }
}
doAssert((col->compare("ab", "abc") == Collator::LESS), "ab < abc comparison failed");
doAssert((col->compare("blackbird", "black-bird") == Collator::GREATER), "black-bird > blackbird comparison failed");
doAssert((col->compare("black bird", "black-bird") == Collator::LESS), "black bird > black-bird comparison failed");
doAssert((col->compare("Hello", "hello") == Collator::GREATER), "Hello > hello comparison failed");
+ doAssert((col->compare("","",success) == UCOL_EQUAL), "Comparison between empty strings failed");
+ doAssert((col->compareUTF8("\x61\x62\xc3\xa4", "\x61\x62\xc3\x9f", success) == UCOL_LESS), "ab a-umlaut < ab sharp-s UTF-8 comparison failed");
+ success = U_ZERO_ERROR;
+ {
+ UnicodeString abau=UNICODE_STRING_SIMPLE("\\x61\\x62\\xe4").unescape();
+ UnicodeString abss=UNICODE_STRING_SIMPLE("\\x61\\x62\\xdf").unescape();
+ UCharIterator abauIter, abssIter;
+ uiter_setReplaceable(&abauIter, &abau);
+ uiter_setReplaceable(&abssIter, &abss);
+ doAssert((col->compare(abauIter, abssIter, success) == UCOL_LESS), "ab a-umlaut < ab sharp-s UCharIterator comparison failed");
+ success = U_ZERO_ERROR;
+ }
/*start of update [Bertrand A. D. 02/10/98]*/
doAssert((col->compare("ab", "abc", 2) == Collator::EQUAL), "ab = abc with length 2 comparison failed");
doAssert(((RuleBasedCollator *)col)->getRules() == ((RuleBasedCollator *)junk)->getRules(),
"The default collation should be returned.");
- Collator *frCol = Collator::createInstance(Locale::getFrance(), success);
+ Collator *frCol = Collator::createInstance(Locale::getCanadaFrench(), success);
if (U_FAILURE(success))
{
- errln("Creating French collator failed.");
- delete col; delete junk;
+ errln("Creating fr_CA collator failed.");
+ delete col;
+ delete junk;
return;
}
- doAssert((*frCol != *junk), "The junk is the same as the French collator.");
+ // If the default locale isn't French, the French and non-French collators
+ // should be different
+ if (frCol->getLocale(ULOC_ACTUAL_LOCALE, success) != Locale::getCanadaFrench()) {
+ doAssert((*frCol != *junk), "The junk is the same as the fr_CA collator.");
+ }
Collator *aFrCol = frCol->clone();
- doAssert((*frCol == *aFrCol), "The cloning of a French collator failed.");
+ doAssert((*frCol == *aFrCol), "The cloning of a fr_CA collator failed.");
logln("Collator property test ended.");
delete col;
col1 = new RuleBasedCollator(ruleset1, status);
if (U_FAILURE(status)) {
- errln("RuleBased Collator creation failed.\n");
+ errcheckln(status, "RuleBased Collator creation failed. - %s", u_errorName(status));
return;
}
else {
coll = (RuleBasedCollator *)Collator::createInstance(Locale::getEnglish(), status);
if (U_FAILURE(status)) {
- errln("English Collator creation failed.\n");
+ errcheckln(status, "English Collator creation failed. - %s", u_errorName(status));
return;
}
else {
}
coll->getRules(UCOL_TAILORING_ONLY, rules);
- if (rules.length() != 0x0a) {
- errln("English tailored rules failed - length is 0x%x expected 0x%x", rules.length(), 0x0e);
+ if (rules.length() != 0x00) {
+ errln("English tailored rules failed - length is 0x%x expected 0x%x", rules.length(), 0x00);
}
coll->getRules(UCOL_FULL_RULES, rules);
*vi_VN = Collator::createInstance("vi_VN", status);
if (U_FAILURE(status)) {
- errln("ERROR: collation creation failed.\n");
+ errcheckln(status, "ERROR: collation creation failed. - %s", u_errorName(status));
return;
}
someCollators[1] = Collator::createInstance("ko", err);
someCollators[2] = Collator::createInstance("ja_JP", err);
if(U_FAILURE(err)) {
- errln("Couldn't instantiate collators. Error: %s", u_errorName(err));
+ errcheckln(err, "Couldn't instantiate collators. Error: %s", u_errorName(err));
delete someCollators[0];
delete someCollators[1];
delete someCollators[2];
col1 = Collator::createInstance(Locale::getEnglish(), success);
if (U_FAILURE(success))
{
- errln("Default collation creation failed.");
+ errcheckln(success, "Default collation creation failed. - %s", u_errorName(success));
return;
}
col = Collator::createInstance(Locale::getEnglish(), success);
if (U_FAILURE(success))
{
- errln("Default collation creation failed.");
+ errcheckln(success, "Default collation creation failed. - %s", u_errorName(success));
return;
}
col->setStrength(Collator::TERTIARY);
// bogus key returned here
key1Status = U_ILLEGAL_ARGUMENT_ERROR;
col->getCollationKey(NULL, 0, sortk1, key1Status);
- doAssert(sortk1.getByteArray(length) == NULL && length == 0,
+ doAssert(sortk1.isBogus() && (sortk1.getByteArray(length), length) == 0,
"Error code should return bogus collation key");
key1Status = U_ZERO_ERROR;
const uint8_t* byteArray1 = sortk1.getByteArray(cnt1);
const uint8_t* byteArray2 = sortk2.getByteArray(cnt2);
- /*
- this is a bad test since it is dependent on the version of uca data,
- which changes
- will remove it.
- const char sortk2_compat[] = {
- // this is a 1.8 sortkey
- 0x17, 0x19, 0x1B, 0x1D, 0x17, 0x01, 0x08, 0x01, 0x08, 0x00
- };
- */
-
const uint8_t* byteArray3 = 0;
byteArray3 = sortk1.getByteArray(cnt3);
CollationKey sortk4(byteArray1, cnt1), sortk5(byteArray2, cnt2);
CollationKey sortk6(byteArray3, cnt3), sortk7(byteArray4, cnt4);
- /*
- doAssert(memcmp(byteArray2, sortk2_compat, strlen(sortk2_compat)) == 0,
- "Binary format for 'abcda' sortkey different!");
- */
doAssert(sortk1.compareTo(sortk4) == Collator::EQUAL, "CollationKey::toByteArray(sortk1) Failed.");
doAssert(sortk2.compareTo(sortk5) == Collator::EQUAL, "CollationKey::toByteArray(sortk2) Failed.");
doAssert(sortk4.compareTo(sortk5) == Collator::GREATER, "sortk4 >>> sortk5 Failed");
col = Collator::createInstance(Locale::getEnglish(), success);
if (U_FAILURE(success))
{
- errln("Default collation creation failed.");
+ errcheckln(success, "Default collation creation failed. - %s", u_errorName(success));
return;
}
UnicodeString ruleset2("< a, A < b, B < c, C < d, D, e, E");
RuleBasedCollator *col1 = new RuleBasedCollator(ruleset1, success);
if (U_FAILURE(success)) {
- errln("RuleBasedCollator creation failed.");
+ errcheckln(success, "RuleBasedCollator creation failed. - %s", u_errorName(success));
return;
}
success = U_ZERO_ERROR;
}
Collator *col2 = col1->clone();
doAssert((*col1 == *col2), "Cloned object is not equal to the orginal");
- UnicodeString ruleset("< a, A < b, B < c, C < d, D, e, E");
- RuleBasedCollator *col3 = new RuleBasedCollator(ruleset, status);
+ UnicodeString *ruleset = new UnicodeString("< a, A < b, B < c, C < d, D, e, E");
+ RuleBasedCollator *col3 = new RuleBasedCollator(*ruleset, status);
doAssert((*col1 != *col3), "Cloned object is equal to some dummy");
*col3 = *((RuleBasedCollator*)col1);
doAssert((*col1 == *col3), "Copied object is not equal to the orginal");
+
+ if (U_FAILURE(status)) {
+ logln("Collation tailoring failed.");
+ return;
+ }
+
+ UCollationResult res;
+ UnicodeString first((UChar)0x0061);
+ UnicodeString second((UChar)0x0062);
+ UnicodeString copiedEnglishRules(((RuleBasedCollator*)col1)->getRules());
+
delete col1;
+ delete ruleset;
+
+ // Try using the cloned collators after deleting the original data
+ res = col2->compare(first, second, status);
+ if(res != UCOL_LESS) {
+ errln("a should be less then b after tailoring");
+ }
+ if (((RuleBasedCollator*)col2)->getRules() != copiedEnglishRules) {
+ errln(UnicodeString("English rule difference. ")
+ + copiedEnglishRules + UnicodeString("\ngetRules=") + ((RuleBasedCollator*)col2)->getRules());
+ }
+ res = col3->compare(first, second, status);
+ if(res != UCOL_LESS) {
+ errln("a should be less then b after tailoring");
+ }
+ if (col3->getRules() != copiedEnglishRules) {
+ errln(UnicodeString("English rule difference. ")
+ + copiedEnglishRules + UnicodeString("\ngetRules=") + col3->getRules());
+ }
+
delete col2;
delete col3;
}
UErrorCode success = U_ZERO_ERROR;
col = Collator::createInstance(Locale::getEnglish(), success);
if (U_FAILURE(success)) {
- errln("Default collation creation failed.");
+ errcheckln(success, "Default collation creation failed. - %s", u_errorName(success));
return;
}
UnicodeString test1("Abcda"), test2("abcda");
void
CollationAPITest::TestGetAll(/* char* par */)
{
- int32_t count;
- const Locale* list = Collator::getAvailableLocales(count);
- for (int32_t i = 0; i < count; ++i) {
- UnicodeString locName, dispName;
- log("Locale name: ");
- log(list[i].getName());
- log(" , the display name is : ");
- logln(list[i].getDisplayName(dispName));
+ int32_t count1, count2;
+ UErrorCode status = U_ZERO_ERROR;
+
+ logln("Trying Collator::getAvailableLocales(int&)");
+
+ const Locale* list = Collator::getAvailableLocales(count1);
+ for (int32_t i = 0; i < count1; ++i) {
+ UnicodeString dispName;
+ logln(UnicodeString("Locale name: ")
+ + UnicodeString(list[i].getName())
+ + UnicodeString(" , the display name is : ")
+ + UnicodeString(list[i].getDisplayName(dispName)));
+ }
+
+ if (count1 == 0 || list == NULL) {
+ dataerrln("getAvailableLocales(int&) returned an empty list");
+ }
+
+ logln("Trying Collator::getAvailableLocales()");
+ StringEnumeration* localeEnum = Collator::getAvailableLocales();
+ const UnicodeString* locStr;
+ const char *locCStr;
+ count2 = 0;
+
+ if (localeEnum == NULL) {
+ dataerrln("getAvailableLocales() returned NULL");
+ return;
+ }
+
+ while ((locStr = localeEnum->snext(status)) != NULL)
+ {
+ logln(UnicodeString("Locale name is: ") + *locStr);
+ count2++;
+ }
+ if (count1 != count2) {
+ errln("getAvailableLocales(int&) returned %d and getAvailableLocales() returned %d", count1, count2);
}
+
+ logln("Trying Collator::getAvailableLocales() clone");
+ count1 = 0;
+ StringEnumeration* localeEnum2 = localeEnum->clone();
+ localeEnum2->reset(status);
+ while ((locCStr = localeEnum2->next(NULL, status)) != NULL)
+ {
+ logln(UnicodeString("Locale name is: ") + UnicodeString(locCStr));
+ count1++;
+ }
+ if (count1 != count2) {
+ errln("getAvailableLocales(3rd time) returned %d and getAvailableLocales(2nd time) returned %d", count1, count2);
+ }
+ if (localeEnum->count(status) != count1) {
+ errln("localeEnum->count() returned %d and getAvailableLocales() returned %d", localeEnum->count(status), count1);
+ }
+ delete localeEnum;
+ delete localeEnum2;
}
void CollationAPITest::TestSortKey()
*/
Collator *col = Collator::createInstance(Locale::getEnglish(), status);
if (U_FAILURE(status)) {
- errln("ERROR: Default collation creation failed.: %s\n", u_errorName(status));
+ errcheckln(status, "ERROR: Default collation creation failed.: %s\n", u_errorName(status));
return;
}
/* Need to use identical strength */
col->setAttribute(UCOL_STRENGTH, UCOL_IDENTICAL, status);
- uint8_t key2compat[] = {
- /* 2.6.1 key */
- 0x26, 0x28, 0x2A, 0x2C, 0x26, 0x01,
- 0x09, 0x01, 0x09, 0x01, 0x25, 0x01,
- 0x92, 0x93, 0x94, 0x95, 0x92, 0x00
-
- /* 2.2 key */
- /*
- 0x1D, 0x1F, 0x21, 0x23, 0x1D, 0x01,
- 0x09, 0x01, 0x09, 0x01, 0x1C, 0x01,
- 0x92, 0x93, 0x94, 0x95, 0x92, 0x00
- */
- /* 2.0 key */
- /*
- 0x19, 0x1B, 0x1D, 0x1F, 0x19,
- 0x01, 0x09, 0x01, 0x09, 0x01,
- 0x18, 0x01,
- 0x92, 0x93, 0x94, 0x95, 0x92,
- 0x00
- */
- /* 1.8.1 key.*/
- /*
- 0x19, 0x1B, 0x1D, 0x1F, 0x19,
- 0x01, 0x0A, 0x01, 0x0A, 0x01,
- 0x92, 0x93, 0x94, 0x95, 0x92,
- 0x00
- */
- };
-
UChar test1[6] = {0x41, 0x62, 0x63, 0x64, 0x61, 0},
test2[6] = {0x61, 0x62, 0x63, 0x64, 0x61, 0},
test3[6] = {0x61, 0x62, 0x63, 0x64, 0x61, 0};
doAssert(key2.compareTo(key3) == Collator::EQUAL,
"Result should be \"abcda\" == \"abcda\"");
+ // Clone the key2 sortkey for later.
int32_t keylength = 0;
- doAssert(strcmp((const char *)(key2.getByteArray(keylength)),
- (const char *)key2compat) == 0,
- "Binary format for 'abcda' sortkey different!");
+ const uint8_t *key2primary_alias = key2.getByteArray(keylength);
+ LocalArray<uint8_t> key2primary(new uint8_t[keylength]);
+ memcpy(key2primary.getAlias(), key2primary_alias, keylength);
col->getSortKey(test1, sortkey1, 64);
col->getSortKey(test2, sortkey2, 64);
"Result should be \"abcda\" == \"abcda\"");
tempkey = key2.getByteArray(keylength);
- doAssert(memcmp(tempkey, key2compat, keylength - 1) == 0,
- "Binary format for 'abcda' sortkey different!");
+ doAssert(memcmp(tempkey, key2primary.getAlias(), keylength - 1) == 0,
+ "Binary format for 'abcda' sortkey different for secondary strength!");
col->getSortKey(test1, sortkey1, 64);
col->getSortKey(test2, sortkey2, 64);
delete col;
}
+void CollationAPITest::TestSortKeyOverflow() {
+ IcuTestErrorCode errorCode(*this, "TestSortKeyOverflow()");
+ LocalPointer<Collator> col(Collator::createInstance(Locale::getEnglish(), errorCode));
+ if (errorCode.logDataIfFailureAndReset("Collator::createInstance(English) failed")) {
+ return;
+ }
+ col->setAttribute(UCOL_STRENGTH, UCOL_PRIMARY, errorCode);
+ UChar i_and_phi[] = { 0x438, 0x3c6 }; // Cyrillic small i & Greek small phi.
+ // The sort key should be 6 bytes:
+ // 2 bytes for the Cyrillic i, 1 byte for the primary-compression terminator,
+ // 2 bytes for the Greek phi, and 1 byte for the NUL terminator.
+ uint8_t sortKey[12];
+ int32_t length = col->getSortKey(i_and_phi, 2, sortKey, LENGTHOF(sortKey));
+ uint8_t sortKey2[12];
+ for (int32_t capacity = 0; capacity < length; ++capacity) {
+ uprv_memset(sortKey2, 2, LENGTHOF(sortKey2));
+ int32_t length2 = col->getSortKey(i_and_phi, 2, sortKey2, capacity);
+ if (length2 != length || 0 != uprv_memcmp(sortKey, sortKey2, capacity)) {
+ errln("getSortKey(i_and_phi, capacity=%d) failed to write proper prefix", capacity);
+ } else if (sortKey2[capacity] != 2 || sortKey2[capacity + 1] != 2) {
+ errln("getSortKey(i_and_phi, capacity=%d) wrote beyond capacity", capacity);
+ }
+ }
+
+ // Now try to break getCollationKey().
+ // Internally, it always starts with a large stack buffer.
+ // Since we cannot control the initial capacity, we throw an increasing number
+ // of characters at it, with the problematic part at the end.
+ const int32_t longCapacity = 2000;
+ // Each 'a' in the prefix should result in one primary sort key byte.
+ // For i_and_phi we expect 6 bytes, then the NUL terminator.
+ const int32_t maxPrefixLength = longCapacity - 6 - 1;
+ LocalArray<uint8_t> longSortKey(new uint8_t[longCapacity]);
+ UnicodeString s(FALSE, i_and_phi, 2);
+ for (int32_t prefixLength = 0; prefixLength < maxPrefixLength; ++prefixLength) {
+ length = col->getSortKey(s, longSortKey.getAlias(), longCapacity);
+ CollationKey collKey;
+ col->getCollationKey(s, collKey, errorCode);
+ int32_t collKeyLength;
+ const uint8_t *collSortKey = collKey.getByteArray(collKeyLength);
+ if (collKeyLength != length || 0 != uprv_memcmp(longSortKey.getAlias(), collSortKey, length)) {
+ errln("getCollationKey(prefix[%d]+i_and_phi) failed to write proper sort key", prefixLength);
+ }
+
+ // Insert an 'a' to match ++prefixLength.
+ s.insert(prefixLength, (UChar)0x61);
+ }
+}
+
void CollationAPITest::TestMaxExpansion()
{
UErrorCode status = U_ZERO_ERROR;
UnicodeString rule("&a < ab < c/aba < d < z < ch");
RuleBasedCollator coll(rule, status);
if(U_FAILURE(status)) {
- errln("Collator creation failed with error %s", u_errorName(status));
+ errcheckln(status, "Collator creation failed with error %s", u_errorName(status));
return;
}
UnicodeString str(ch);
size = coll.getMaxExpansion(order);
if (U_FAILURE(status) || size < count) {
- errln("Failure at codepoint %d, maximum expansion count < %d\n",
- ch, count);
+ errln("Failure at codepoint U+%04X, maximum expansion count %d < %d",
+ ch, size, count);
}
}
/* testing for exact max expansion */
+ int32_t size;
ch = 0;
while (ch < 0x61) {
uint32_t order;
- int32_t size;
str.setCharAt(0, ch);
iter->setText(str, status);
order = iter->previous(status);
size = coll.getMaxExpansion(order);
if (U_FAILURE(status) || size != 1) {
- errln("Failure at codepoint %d, maximum expansion count < %d\n",
- ch, 1);
+ errln("Failure at codepoint U+%04X, maximum expansion count %d < %d",
+ ch, size, 1);
}
ch ++;
}
str.setTo(ch);
iter->setText(str, status);
temporder = iter->previous(status);
-
- if (U_FAILURE(status) || coll.getMaxExpansion(temporder) != 3) {
- errln("Failure at codepoint %d, maximum expansion count != %d\n",
- ch, 3);
+ size = coll.getMaxExpansion(temporder);
+ if (U_FAILURE(status) || size != 3) {
+ errln("Failure at codepoint U+%04X, CE %08x, maximum expansion count %d != %d",
+ ch, temporder, size, 3);
}
ch = 0x64;
str.setTo(ch);
iter->setText(str, status);
temporder = iter->previous(status);
-
- if (U_FAILURE(status) || coll.getMaxExpansion(temporder) != 1) {
- errln("Failure at codepoint %d, maximum expansion count != %d\n",
- ch, 3);
+ size = coll.getMaxExpansion(temporder);
+ if (U_FAILURE(status) || size != 1) {
+ errln("Failure at codepoint U+%04X, CE %08x, maximum expansion count %d != %d",
+ ch, temporder, size, 1);
}
str.setTo(unassigned);
iter->setText(str, status);
sorder = iter->previous(status);
-
- if (U_FAILURE(status) || coll.getMaxExpansion(sorder) != 2) {
- errln("Failure at supplementary codepoints, maximum expansion count < %d\n",
- 2);
+ size = coll.getMaxExpansion(sorder);
+ if (U_FAILURE(status) || size != 2) {
+ errln("Failure at supplementary codepoints, maximum expansion count %d < %d",
+ size, 2);
}
/* testing jamo */
str.setTo(ch);
iter->setText(str, status);
temporder = iter->previous(status);
- if (U_FAILURE(status) || coll.getMaxExpansion(temporder) > 3) {
- errln("Failure at codepoint %d, maximum expansion count > %d\n",
- ch, 3);
+ size = coll.getMaxExpansion(temporder);
+ if (U_FAILURE(status) || size > 3) {
+ errln("Failure at codepoint U+%04X, maximum expansion count %d > %d",
+ ch, size, 3);
}
delete iter;
RuleBasedCollator jamocoll(rule, status);
iter = jamocoll.createCollationElementIterator(str);
temporder = iter->previous(status);
- if (U_FAILURE(status) || iter->getMaxExpansion(temporder) != 6) {
- errln("Failure at codepoint %d, maximum expansion count > %d\n",
- ch, 5);
+ size = iter->getMaxExpansion(temporder);
+ if (U_FAILURE(status) || size != 6) {
+ errln("Failure at codepoint U+%04X, maximum expansion count %d > %d",
+ ch, size, 5);
}
delete iter;
UErrorCode error = U_ZERO_ERROR;
Collator *coll = Collator::createInstance("en_US", error);
if (U_FAILURE(error)) {
- errln("Failure creating english collator");
+ errcheckln(error, "Failure creating english collator - %s", u_errorName(error));
return;
}
UnicodeString name;
Collator *coll = Collator::createInstance(error);
if (U_FAILURE(error)) {
- errln("Creation of default collator failed");
+ errcheckln(error, "Creation of default collator failed - %s", u_errorName(error));
return;
}
Collator *coll = Collator::createInstance(status);
if(U_FAILURE(status)) {
delete coll;
- errln("Collator creation failed with error %s", u_errorName(status));
+ errcheckln(status, "Collator creation failed with error %s", u_errorName(status));
return;
}
Collator *coll = Collator::createInstance(Locale("sh"), status);
if(U_FAILURE(status)) {
delete coll;
- errln("Collator creation failed with %s", u_errorName(status));
+ errcheckln(status, "Collator creation failed with %s", u_errorName(status));
return;
}
uint8_t sortkey[512], lower[512], upper[512];
UChar buffer[512];
- const char *test[] = {
+ static const char * const test[] = {
"John Smith",
"JOHN SMITH",
"john SMITH",
"John Smithsonian"
};
- static struct teststruct tests[] = {
+ struct teststruct tests[] = {
{"\\u010CAKI MIHALJ", {0}},
{"\\u010CAKI MIHALJ", {0}},
{"\\u010CAKI PIRO\\u0160KA", {0}},
}
delete set;
} else {
- errln("Couldn't open collator with rules %s\n", setTest[i].rules);
+ errcheckln(status, "Couldn't open collator with rules %s - %s", setTest[i].rules, u_errorName(status));
}
delete coll;
}
= (RuleBasedCollator *)Collator::createInstance(status);
if(U_FAILURE(status)) {
delete coll;
- errln("Collator creation failed with %s", u_errorName(status));
+ errcheckln(status, "Collator creation failed with %s", u_errorName(status));
return;
}
id = *((char *)coll->getDynamicClassID());
public:
virtual Collator* clone(void) const;
- // dang, markus says we can't use 'using' in ICU. I hate doing this for
- // deprecated methods...
-
- // using Collator::compare;
-
- virtual EComparisonResult compare(const UnicodeString& source,
- const UnicodeString& target) const
- {
- return Collator::compare(source, target);
- }
-
- virtual EComparisonResult compare(const UnicodeString& source,
- const UnicodeString& target,
- int32_t length) const
- {
- return Collator::compare(source, target, length);
- }
-
- virtual EComparisonResult compare(const UChar* source,
- int32_t sourceLength,
- const UChar* target,
- int32_t targetLength) const
- {
- return Collator::compare(source, sourceLength, target, targetLength);
- }
-
+ using Collator::compare;
virtual UCollationResult compare(const UnicodeString& source,
const UnicodeString& target,
CollationKey& key,
UErrorCode& status) const;
virtual int32_t hashCode(void) const;
- virtual const Locale getLocale(ULocDataLocaleType type,
- UErrorCode& status) const;
+ virtual Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const;
virtual ECollationStrength getStrength(void) const;
virtual void setStrength(ECollationStrength newStrength);
virtual UClassID getDynamicClassID(void) const;
virtual void setAttribute(UColAttribute attr, UColAttributeValue value,
UErrorCode &status);
virtual UColAttributeValue getAttribute(UColAttribute attr,
- UErrorCode &status);
+ UErrorCode &status) const;
virtual uint32_t setVariableTop(const UChar *varTop, int32_t len,
UErrorCode &status);
- virtual uint32_t setVariableTop(const UnicodeString varTop,
+ virtual uint32_t setVariableTop(const UnicodeString &varTop,
UErrorCode &status);
- virtual void setVariableTop(const uint32_t varTop, UErrorCode &status);
+ virtual void setVariableTop(uint32_t varTop, UErrorCode &status);
virtual uint32_t getVariableTop(UErrorCode &status) const;
- virtual Collator* safeClone(void);
virtual int32_t getSortKey(const UnicodeString& source,
uint8_t* result,
int32_t resultLength) const;
virtual int32_t getSortKey(const UChar*source, int32_t sourceLength,
uint8_t*result, int32_t resultLength) const;
virtual UnicodeSet *getTailoredSet(UErrorCode &status) const;
- virtual UBool operator!=(const Collator& other) const;
- virtual void setLocales(const Locale& requestedLocale, const Locale& validLocale);
+ virtual UBool operator==(const Collator& other) const;
+ // Collator::operator!= calls !Collator::operator== which works for all subclasses.
+ virtual void setLocales(const Locale& requestedLocale, const Locale& validLocale, const Locale& actualLocale);
TestCollator() : Collator() {};
TestCollator(UCollationStrength collationStrength,
UNormalizationMode decompositionMode) : Collator(collationStrength, decompositionMode) {};
};
-inline UBool TestCollator::operator!=(const Collator& other) const {
- return Collator::operator!=(other);
-}
+inline UBool TestCollator::operator==(const Collator& other) const {
+ // TestCollator has no fields, so we test for identity.
+ return this == &other;
-#define returnEComparisonResult(data) \
- if (data < 0) return Collator::LESS;\
- if (data > 0) return Collator::GREATER;\
- return Collator::EQUAL;
+ // Normally, subclasses should do something like the following:
+ // if (this == &other) { return TRUE; }
+ // if (!Collator::operator==(other)) { return FALSE; } // not the same class
+ //
+ // const TestCollator &o = (const TestCollator&)other;
+ // (compare this vs. o's subclass fields)
+}
Collator* TestCollator::clone() const
{
return 0;
}
-const Locale TestCollator::getLocale(ULocDataLocaleType type,
- UErrorCode& status) const
+Locale TestCollator::getLocale(ULocDataLocaleType type, UErrorCode& status) const
{
// api not used, this is to make the compiler happy
if (U_FAILURE(status)) {
}
UColAttributeValue TestCollator::getAttribute(UColAttribute attr,
- UErrorCode &status)
+ UErrorCode &status) const
{
// api not used, this is to make the compiler happy
if (U_FAILURE(status) || attr == UCOL_ATTRIBUTE_COUNT) {
return 0;
}
-uint32_t TestCollator::setVariableTop(const UnicodeString varTop,
+uint32_t TestCollator::setVariableTop(const UnicodeString &varTop,
UErrorCode &status)
{
// api not used, this is to make the compiler happy
return 0;
}
-void TestCollator::setVariableTop(const uint32_t varTop, UErrorCode &status)
+void TestCollator::setVariableTop(uint32_t varTop, UErrorCode &status)
{
// api not used, this is to make the compiler happy
if (U_SUCCESS(status) && varTop == 0) {
return (uint32_t)(0xFFFFFFFFu);
}
-Collator* TestCollator::safeClone(void)
-{
- return new TestCollator();
-}
-
UnicodeSet * TestCollator::getTailoredSet(UErrorCode &status) const
{
return Collator::getTailoredSet(status);
}
-void TestCollator::setLocales(const Locale& requestedLocale, const Locale& validLocale)
+void TestCollator::setLocales(const Locale& requestedLocale, const Locale& validLocale, const Locale& actualLocale)
{
- Collator::setLocales(requestedLocale, validLocale);
+ Collator::setLocales(requestedLocale, validLocale, actualLocale);
}
{
TestCollator col1;
TestCollator col2;
- doAssert(col1 != col2, "2 instance of TestCollator should be different");
+ doAssert(col1 != col2, "2 instances of TestCollator should be different");
if (col1.hashCode() != col2.hashCode()) {
errln("Every TestCollator has the same hashcode");
}
// use base class implementation
Locale loc1 = Locale::getGermany();
Locale loc2 = Locale::getFrance();
- col1.setLocales(loc1, loc2); // default implementation has no effect
+ col1.setLocales(loc1, loc2, loc2); // default implementation has no effect
UnicodeString displayName;
col1.getDisplayName(loc1, loc2, displayName); // de_DE collator in fr_FR locale
UnicodeString second((UChar)0);
RuleBasedCollator *coll = new RuleBasedCollator(UnicodeString(buf, len), status);
if(U_FAILURE(status)) {
- errln("Failed to open collator");
+ delete coll;
+ errcheckln(status, "Failed to open collator - %s", u_errorName(status));
+ return;
}
UCollationResult res = coll->compare(first, second, status);
if(res != UCOL_LESS) {
delete coll;
}
+void CollationAPITest::TestClone() {
+ logln("\ninit c0");
+ UErrorCode status = U_ZERO_ERROR;
+ RuleBasedCollator* c0 = (RuleBasedCollator*)Collator::createInstance(status);
+
+ if (U_FAILURE(status)) {
+ errcheckln(status, "Collator::CreateInstance(status) failed with %s", u_errorName(status));
+ return;
+ }
+
+ c0->setStrength(Collator::TERTIARY);
+ dump("c0", c0, status);
+
+ logln("\ninit c1");
+ RuleBasedCollator* c1 = (RuleBasedCollator*)Collator::createInstance(status);
+ c1->setStrength(Collator::TERTIARY);
+ UColAttributeValue val = c1->getAttribute(UCOL_CASE_FIRST, status);
+ if(val == UCOL_LOWER_FIRST){
+ c1->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
+ }else{
+ c1->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
+ }
+ dump("c0", c0, status);
+ dump("c1", c1, status);
+
+ logln("\ninit c2");
+ RuleBasedCollator* c2 = (RuleBasedCollator*)c1->clone();
+ val = c2->getAttribute(UCOL_CASE_FIRST, status);
+ if(val == UCOL_LOWER_FIRST){
+ c2->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
+ }else{
+ c2->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
+ }
+ if(U_FAILURE(status)){
+ errln("set and get attributes of collator failed. %s\n", u_errorName(status));
+ return;
+ }
+ dump("c0", c0, status);
+ dump("c1", c1, status);
+ dump("c2", c2, status);
+ if(*c1 == *c2){
+ errln("The cloned objects refer to same data");
+ }
+ delete c0;
+ delete c1;
+ delete c2;
+}
+
+ void CollationAPITest::dump(UnicodeString msg, RuleBasedCollator* c, UErrorCode& status) {
+ const char* bigone = "One";
+ const char* littleone = "one";
+
+ logln(msg + " " + c->compare(bigone, littleone) +
+ " s: " + c->getStrength() +
+ " u: " + c->getAttribute(UCOL_CASE_FIRST, status));
+}
void CollationAPITest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */)
{
if (exec) logln("TestSuite CollationAPITest: ");
- switch (index) {
- case 0: name = "TestProperty"; if (exec) TestProperty(/* par */); break;
- case 1: name = "TestOperators"; if (exec) TestOperators(/* par */); break;
- case 2: name = "TestDuplicate"; if (exec) TestDuplicate(/* par */); break;
- case 3: name = "TestCompare"; if (exec) TestCompare(/* par */); break;
- case 4: name = "TestHashCode"; if (exec) TestHashCode(/* par */); break;
- case 5: name = "TestCollationKey"; if (exec) TestCollationKey(/* par */); break;
- case 6: name = "TestElemIter"; if (exec) TestElemIter(/* par */); break;
- case 7: name = "TestGetAll"; if (exec) TestGetAll(/* par */); break;
- case 8: name = "TestRuleBasedColl"; if (exec) TestRuleBasedColl(/* par */); break;
- case 9: name = "TestDecomposition"; if (exec) TestDecomposition(/* par */); break;
- case 10: name = "TestSafeClone"; if (exec) TestSafeClone(/* par */); break;
- case 11: name = "TestSortKey"; if (exec) TestSortKey(); break;
- case 12: name = "TestMaxExpansion"; if (exec) TestMaxExpansion(); break;
- case 13: name = "TestDisplayName"; if (exec) TestDisplayName(); break;
- case 14: name = "TestAttribute"; if (exec) TestAttribute(); break;
- case 15: name = "TestVariableTopSetting"; if (exec) TestVariableTopSetting(); break;
- case 16: name = "TestRules"; if (exec) TestRules(); break;
- case 17: name = "TestGetLocale"; if (exec) TestGetLocale(); break;
- case 18: name = "TestBounds"; if (exec) TestBounds(); break;
- case 19: name = "TestGetTailoredSet"; if (exec) TestGetTailoredSet(); break;
- case 20: name = "TestUClassID"; if (exec) TestUClassID(); break;
- case 21: name = "TestSubclass"; if (exec) TestSubclass(); break;
- case 22: name = "TestNULLCharTailoring"; if (exec) TestNULLCharTailoring(); break;
- default: name = ""; break;
- }
+ TESTCASE_AUTO_BEGIN;
+ TESTCASE_AUTO(TestProperty);
+ TESTCASE_AUTO(TestOperators);
+ TESTCASE_AUTO(TestDuplicate);
+ TESTCASE_AUTO(TestCompare);
+ TESTCASE_AUTO(TestHashCode);
+ TESTCASE_AUTO(TestCollationKey);
+ TESTCASE_AUTO(TestElemIter);
+ TESTCASE_AUTO(TestGetAll);
+ TESTCASE_AUTO(TestRuleBasedColl);
+ TESTCASE_AUTO(TestDecomposition);
+ TESTCASE_AUTO(TestSafeClone);
+ TESTCASE_AUTO(TestSortKey);
+ TESTCASE_AUTO(TestSortKeyOverflow);
+ TESTCASE_AUTO(TestMaxExpansion);
+ TESTCASE_AUTO(TestDisplayName);
+ TESTCASE_AUTO(TestAttribute);
+ TESTCASE_AUTO(TestVariableTopSetting);
+ TESTCASE_AUTO(TestRules);
+ TESTCASE_AUTO(TestGetLocale);
+ TESTCASE_AUTO(TestBounds);
+ TESTCASE_AUTO(TestGetTailoredSet);
+ TESTCASE_AUTO(TestUClassID);
+ TESTCASE_AUTO(TestSubclass);
+ TESTCASE_AUTO(TestNULLCharTailoring);
+ TESTCASE_AUTO(TestClone);
+ TESTCASE_AUTO_END;
}
#endif /* #if !UCONFIG_NO_COLLATION */