12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci ******************************************************************************* 52e5b6d6dSopenharmony_ci * Copyright (C) 2003-2016, International Business Machines Corporation and 62e5b6d6dSopenharmony_ci * others. All Rights Reserved. 72e5b6d6dSopenharmony_ci ******************************************************************************* 82e5b6d6dSopenharmony_ci */ 92e5b6d6dSopenharmony_ci 102e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 112e5b6d6dSopenharmony_ci 122e5b6d6dSopenharmony_ci#if !UCONFIG_NO_COLLATION 132e5b6d6dSopenharmony_ci 142e5b6d6dSopenharmony_ci#include "svccoll.h" 152e5b6d6dSopenharmony_ci#include "unicode/coll.h" 162e5b6d6dSopenharmony_ci#include "unicode/strenum.h" 172e5b6d6dSopenharmony_ci#include "cmemory.h" 182e5b6d6dSopenharmony_ci#include "hash.h" 192e5b6d6dSopenharmony_ci#include "uassert.h" 202e5b6d6dSopenharmony_ci 212e5b6d6dSopenharmony_ci#include "cstring.h" // internal api used to compare locale strings 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_civoid CollationServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par */) 242e5b6d6dSopenharmony_ci{ 252e5b6d6dSopenharmony_ci if (exec) logln("TestSuite CollationServiceTest: "); 262e5b6d6dSopenharmony_ci switch (index) { 272e5b6d6dSopenharmony_ci TESTCASE(0, TestRegister); 282e5b6d6dSopenharmony_ci TESTCASE(1, TestRegisterFactory); 292e5b6d6dSopenharmony_ci TESTCASE(2, TestSeparateTree); 302e5b6d6dSopenharmony_ci default: name = ""; break; 312e5b6d6dSopenharmony_ci } 322e5b6d6dSopenharmony_ci} 332e5b6d6dSopenharmony_ci 342e5b6d6dSopenharmony_civoid CollationServiceTest::TestRegister() 352e5b6d6dSopenharmony_ci{ 362e5b6d6dSopenharmony_ci#if !UCONFIG_NO_SERVICE 372e5b6d6dSopenharmony_ci // register a singleton 382e5b6d6dSopenharmony_ci const Locale& FR = Locale::getFrance(); 392e5b6d6dSopenharmony_ci const Locale& US = Locale::getUS(); 402e5b6d6dSopenharmony_ci const Locale US_FOO("en", "US", "FOO"); 412e5b6d6dSopenharmony_ci 422e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 432e5b6d6dSopenharmony_ci 442e5b6d6dSopenharmony_ci Collator* frcol = Collator::createInstance(FR, status); 452e5b6d6dSopenharmony_ci Collator* uscol = Collator::createInstance(US, status); 462e5b6d6dSopenharmony_ci if(U_FAILURE(status)) { 472e5b6d6dSopenharmony_ci errcheckln(status, "Failed to create collators with %s", u_errorName(status)); 482e5b6d6dSopenharmony_ci delete frcol; 492e5b6d6dSopenharmony_ci delete uscol; 502e5b6d6dSopenharmony_ci return; 512e5b6d6dSopenharmony_ci } 522e5b6d6dSopenharmony_ci 532e5b6d6dSopenharmony_ci { // try override en_US collator 542e5b6d6dSopenharmony_ci Collator *clone = frcol->clone(); 552e5b6d6dSopenharmony_ci URegistryKey key = Collator::registerInstance(frcol, US, status); 562e5b6d6dSopenharmony_ci // frcol has been adopted. We must not use it any more, nor rely on its attributes. 572e5b6d6dSopenharmony_ci frcol = NULL; 582e5b6d6dSopenharmony_ci 592e5b6d6dSopenharmony_ci Collator* ncol = Collator::createInstance(US_FOO, status); 602e5b6d6dSopenharmony_ci if (*clone != *ncol) { 612e5b6d6dSopenharmony_ci errln("register of french collator for en_US failed on request for en_US_FOO"); 622e5b6d6dSopenharmony_ci } 632e5b6d6dSopenharmony_ci delete clone; 642e5b6d6dSopenharmony_ci 652e5b6d6dSopenharmony_ci // The requested locale may be the same as the valid locale, 662e5b6d6dSopenharmony_ci // or may not be supported at all. See ticket #10477. 672e5b6d6dSopenharmony_ci Locale loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status); 682e5b6d6dSopenharmony_ci if (U_SUCCESS(status) && loc != US_FOO && loc != US) { 692e5b6d6dSopenharmony_ci errln(UnicodeString("requested locale for en_US_FOO is not en_US_FOO nor en_US but ") + loc.getName()); 702e5b6d6dSopenharmony_ci } 712e5b6d6dSopenharmony_ci status = U_ZERO_ERROR; 722e5b6d6dSopenharmony_ci loc = ncol->getLocale(ULOC_VALID_LOCALE, status); 732e5b6d6dSopenharmony_ci if (loc != US) { 742e5b6d6dSopenharmony_ci errln(UnicodeString("valid locale for en_US_FOO is not en_US but ") + loc.getName()); 752e5b6d6dSopenharmony_ci } 762e5b6d6dSopenharmony_ci loc = ncol->getLocale(ULOC_ACTUAL_LOCALE, status); 772e5b6d6dSopenharmony_ci if (loc != US) { 782e5b6d6dSopenharmony_ci errln(UnicodeString("actual locale for en_US_FOO is not en_US but ") + loc.getName()); 792e5b6d6dSopenharmony_ci } 802e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 812e5b6d6dSopenharmony_ci 822e5b6d6dSopenharmony_ci if (!Collator::unregister(key, status)) { 832e5b6d6dSopenharmony_ci errln("failed to unregister french collator"); 842e5b6d6dSopenharmony_ci } 852e5b6d6dSopenharmony_ci 862e5b6d6dSopenharmony_ci ncol = Collator::createInstance(US, status); 872e5b6d6dSopenharmony_ci if (*uscol != *ncol) { 882e5b6d6dSopenharmony_ci errln("collator after unregister does not match original"); 892e5b6d6dSopenharmony_ci } 902e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 912e5b6d6dSopenharmony_ci } 922e5b6d6dSopenharmony_ci 932e5b6d6dSopenharmony_ci // recreate frcol 942e5b6d6dSopenharmony_ci frcol = Collator::createInstance(FR, status); 952e5b6d6dSopenharmony_ci 962e5b6d6dSopenharmony_ci LocalUCollatorPointer frFR(ucol_open("fr_FR", &status)); 972e5b6d6dSopenharmony_ci 982e5b6d6dSopenharmony_ci { // try create collator for new locale 992e5b6d6dSopenharmony_ci Locale fu_FU_FOO("fu", "FU", "FOO"); 1002e5b6d6dSopenharmony_ci Locale fu_FU("fu", "FU", ""); 1012e5b6d6dSopenharmony_ci 1022e5b6d6dSopenharmony_ci Collator* fucol = Collator::createInstance(fu_FU, status); 1032e5b6d6dSopenharmony_ci Collator *clone = frcol->clone(); 1042e5b6d6dSopenharmony_ci URegistryKey key = Collator::registerInstance(frcol, fu_FU, status); 1052e5b6d6dSopenharmony_ci frcol = NULL; // frcol has been adopted. 1062e5b6d6dSopenharmony_ci Collator* ncol = Collator::createInstance(fu_FU_FOO, status); 1072e5b6d6dSopenharmony_ci if (*clone != *ncol) { 1082e5b6d6dSopenharmony_ci errln("register of fr collator for fu_FU failed"); 1092e5b6d6dSopenharmony_ci } 1102e5b6d6dSopenharmony_ci delete clone; 1112e5b6d6dSopenharmony_ci 1122e5b6d6dSopenharmony_ci UnicodeString locName = fu_FU.getName(); 1132e5b6d6dSopenharmony_ci StringEnumeration* localeEnum = Collator::getAvailableLocales(); 1142e5b6d6dSopenharmony_ci UBool found = false; 1152e5b6d6dSopenharmony_ci const UnicodeString* locStr, *ls2; 1162e5b6d6dSopenharmony_ci for (locStr = localeEnum->snext(status); 1172e5b6d6dSopenharmony_ci !found && locStr != NULL; 1182e5b6d6dSopenharmony_ci locStr = localeEnum->snext(status)) { 1192e5b6d6dSopenharmony_ci // 1202e5b6d6dSopenharmony_ci if (locName == *locStr) { 1212e5b6d6dSopenharmony_ci found = true; 1222e5b6d6dSopenharmony_ci } 1232e5b6d6dSopenharmony_ci } 1242e5b6d6dSopenharmony_ci 1252e5b6d6dSopenharmony_ci StringEnumeration *le2 = NULL; 1262e5b6d6dSopenharmony_ci localeEnum->reset(status); 1272e5b6d6dSopenharmony_ci int32_t i, count; 1282e5b6d6dSopenharmony_ci count = localeEnum->count(status); 1292e5b6d6dSopenharmony_ci for(i = 0; i < count; ++i) { 1302e5b6d6dSopenharmony_ci if(i == count / 2) { 1312e5b6d6dSopenharmony_ci le2 = localeEnum->clone(); 1322e5b6d6dSopenharmony_ci if(le2 == NULL || count != le2->count(status)) { 1332e5b6d6dSopenharmony_ci errln("ServiceEnumeration.clone() failed"); 1342e5b6d6dSopenharmony_ci break; 1352e5b6d6dSopenharmony_ci } 1362e5b6d6dSopenharmony_ci } 1372e5b6d6dSopenharmony_ci if(i >= count / 2) { 1382e5b6d6dSopenharmony_ci locStr = localeEnum->snext(status); 1392e5b6d6dSopenharmony_ci ls2 = le2->snext(status); 1402e5b6d6dSopenharmony_ci if(*locStr != *ls2) { 1412e5b6d6dSopenharmony_ci errln("ServiceEnumeration.clone() failed for item %d", i); 1422e5b6d6dSopenharmony_ci } 1432e5b6d6dSopenharmony_ci } else { 1442e5b6d6dSopenharmony_ci localeEnum->snext(status); 1452e5b6d6dSopenharmony_ci } 1462e5b6d6dSopenharmony_ci } 1472e5b6d6dSopenharmony_ci 1482e5b6d6dSopenharmony_ci delete localeEnum; 1492e5b6d6dSopenharmony_ci delete le2; 1502e5b6d6dSopenharmony_ci 1512e5b6d6dSopenharmony_ci if (!found) { 1522e5b6d6dSopenharmony_ci errln("new locale fu_FU not reported as supported locale"); 1532e5b6d6dSopenharmony_ci } 1542e5b6d6dSopenharmony_ci 1552e5b6d6dSopenharmony_ci UnicodeString displayName; 1562e5b6d6dSopenharmony_ci Collator::getDisplayName(fu_FU, displayName); 1572e5b6d6dSopenharmony_ci /* The locale display pattern for the locale ja, ko, and zh are different. */ 1582e5b6d6dSopenharmony_ci const UChar zh_fuFU_Array[] = { 0x0066, 0x0075, 0xff08, 0x0046, 0x0055, 0xff09, 0 }; 1592e5b6d6dSopenharmony_ci const UnicodeString zh_fuFU(zh_fuFU_Array); 1602e5b6d6dSopenharmony_ci const Locale& defaultLocale = Locale::getDefault(); 1612e5b6d6dSopenharmony_ci if (displayName != "fu (FU)" && 1622e5b6d6dSopenharmony_ci ((defaultLocale == Locale::getKorean() && defaultLocale == Locale::getJapanese()) && displayName == "fu(FU)") && 1632e5b6d6dSopenharmony_ci ((defaultLocale == Locale::getChinese()) && displayName != zh_fuFU)) { 1642e5b6d6dSopenharmony_ci errln(UnicodeString("found ") + displayName + " for fu_FU"); 1652e5b6d6dSopenharmony_ci } 1662e5b6d6dSopenharmony_ci 1672e5b6d6dSopenharmony_ci Collator::getDisplayName(fu_FU, fu_FU, displayName); 1682e5b6d6dSopenharmony_ci if (displayName != "fu (FU)" && 1692e5b6d6dSopenharmony_ci ((defaultLocale == Locale::getKorean() && defaultLocale == Locale::getJapanese()) && displayName == "fu(FU)") && 1702e5b6d6dSopenharmony_ci ((defaultLocale == Locale::getChinese()) && displayName != zh_fuFU)) { 1712e5b6d6dSopenharmony_ci errln(UnicodeString("found ") + displayName + " for fu_FU"); 1722e5b6d6dSopenharmony_ci } 1732e5b6d6dSopenharmony_ci 1742e5b6d6dSopenharmony_ci // test ucol_open 1752e5b6d6dSopenharmony_ci LocalUCollatorPointer fufu(ucol_open("fu_FU_FOO", &status)); 1762e5b6d6dSopenharmony_ci if (fufu.isNull()) { 1772e5b6d6dSopenharmony_ci errln("could not open fu_FU_FOO with ucol_open"); 1782e5b6d6dSopenharmony_ci } else { 1792e5b6d6dSopenharmony_ci if (*Collator::fromUCollator(fufu.getAlias()) != 1802e5b6d6dSopenharmony_ci *Collator::fromUCollator(frFR.getAlias())) { 1812e5b6d6dSopenharmony_ci errln("collator fufu != collator frFR"); 1822e5b6d6dSopenharmony_ci } 1832e5b6d6dSopenharmony_ci } 1842e5b6d6dSopenharmony_ci 1852e5b6d6dSopenharmony_ci if (!Collator::unregister(key, status)) { 1862e5b6d6dSopenharmony_ci errln("failed to unregister french collator"); 1872e5b6d6dSopenharmony_ci } 1882e5b6d6dSopenharmony_ci // !!! note frcoll invalid again, but we're no longer using it 1892e5b6d6dSopenharmony_ci 1902e5b6d6dSopenharmony_ci // other collators should still work ok 1912e5b6d6dSopenharmony_ci Locale nloc = ncol->getLocale(ULOC_VALID_LOCALE, status); 1922e5b6d6dSopenharmony_ci if (nloc != fu_FU) { 1932e5b6d6dSopenharmony_ci errln(UnicodeString("asked for nloc valid locale after close and got") + nloc.getName()); 1942e5b6d6dSopenharmony_ci } 1952e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 1962e5b6d6dSopenharmony_ci 1972e5b6d6dSopenharmony_ci if (fufu.isValid()) { 1982e5b6d6dSopenharmony_ci const char* nlocstr = ucol_getLocaleByType(fufu.getAlias(), ULOC_VALID_LOCALE, &status); 1992e5b6d6dSopenharmony_ci if (uprv_strcmp(nlocstr, "fu_FU") != 0) { 2002e5b6d6dSopenharmony_ci errln(UnicodeString("asked for uloc valid locale after close and got ") + nlocstr); 2012e5b6d6dSopenharmony_ci } 2022e5b6d6dSopenharmony_ci } 2032e5b6d6dSopenharmony_ci 2042e5b6d6dSopenharmony_ci ncol = Collator::createInstance(fu_FU, status); 2052e5b6d6dSopenharmony_ci if (*fucol != *ncol) { 2062e5b6d6dSopenharmony_ci errln("collator after unregister does not match original fu_FU"); 2072e5b6d6dSopenharmony_ci } 2082e5b6d6dSopenharmony_ci delete uscol; uscol = NULL; 2092e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 2102e5b6d6dSopenharmony_ci delete fucol; fucol = NULL; 2112e5b6d6dSopenharmony_ci } 2122e5b6d6dSopenharmony_ci#endif 2132e5b6d6dSopenharmony_ci} 2142e5b6d6dSopenharmony_ci 2152e5b6d6dSopenharmony_ci// ------------------ 2162e5b6d6dSopenharmony_ci 2172e5b6d6dSopenharmony_ci#if !UCONFIG_NO_SERVICE 2182e5b6d6dSopenharmony_cistruct CollatorInfo { 2192e5b6d6dSopenharmony_ci Locale locale; 2202e5b6d6dSopenharmony_ci Collator* collator; 2212e5b6d6dSopenharmony_ci Hashtable* displayNames; // locale name -> string 2222e5b6d6dSopenharmony_ci 2232e5b6d6dSopenharmony_ci CollatorInfo(const Locale& locale, Collator* collatorToAdopt, Hashtable* displayNamesToAdopt); 2242e5b6d6dSopenharmony_ci ~CollatorInfo(); 2252e5b6d6dSopenharmony_ci UnicodeString& getDisplayName(const Locale& displayLocale, UnicodeString& name) const; 2262e5b6d6dSopenharmony_ci}; 2272e5b6d6dSopenharmony_ci 2282e5b6d6dSopenharmony_ciCollatorInfo::CollatorInfo(const Locale& _locale, Collator* _collator, Hashtable* _displayNames) 2292e5b6d6dSopenharmony_ci : locale(_locale) 2302e5b6d6dSopenharmony_ci , collator(_collator) 2312e5b6d6dSopenharmony_ci , displayNames(_displayNames) 2322e5b6d6dSopenharmony_ci{ 2332e5b6d6dSopenharmony_ci collator->setLocales(locale, locale, locale); 2342e5b6d6dSopenharmony_ci} 2352e5b6d6dSopenharmony_ci 2362e5b6d6dSopenharmony_ciCollatorInfo::~CollatorInfo() { 2372e5b6d6dSopenharmony_ci delete collator; 2382e5b6d6dSopenharmony_ci delete displayNames; 2392e5b6d6dSopenharmony_ci} 2402e5b6d6dSopenharmony_ci 2412e5b6d6dSopenharmony_ciUnicodeString& 2422e5b6d6dSopenharmony_ciCollatorInfo::getDisplayName(const Locale& displayLocale, UnicodeString& name) const { 2432e5b6d6dSopenharmony_ci if (displayNames) { 2442e5b6d6dSopenharmony_ci UnicodeString* val = (UnicodeString*)displayNames->get(displayLocale.getName()); 2452e5b6d6dSopenharmony_ci if (val) { 2462e5b6d6dSopenharmony_ci name = *val; 2472e5b6d6dSopenharmony_ci return name; 2482e5b6d6dSopenharmony_ci } 2492e5b6d6dSopenharmony_ci } 2502e5b6d6dSopenharmony_ci 2512e5b6d6dSopenharmony_ci return locale.getDisplayName(displayLocale, name); 2522e5b6d6dSopenharmony_ci} 2532e5b6d6dSopenharmony_ci 2542e5b6d6dSopenharmony_ci// --------------- 2552e5b6d6dSopenharmony_ci 2562e5b6d6dSopenharmony_ciclass TestFactory : public CollatorFactory { 2572e5b6d6dSopenharmony_ci CollatorInfo** info; 2582e5b6d6dSopenharmony_ci int32_t count; 2592e5b6d6dSopenharmony_ci UnicodeString* ids; 2602e5b6d6dSopenharmony_ci 2612e5b6d6dSopenharmony_ci const CollatorInfo* getInfo(const Locale& loc) const { 2622e5b6d6dSopenharmony_ci for (CollatorInfo** p = info; *p; ++p) { 2632e5b6d6dSopenharmony_ci if (loc == (**p).locale) { 2642e5b6d6dSopenharmony_ci return *p; 2652e5b6d6dSopenharmony_ci } 2662e5b6d6dSopenharmony_ci } 2672e5b6d6dSopenharmony_ci return NULL; 2682e5b6d6dSopenharmony_ci } 2692e5b6d6dSopenharmony_ci 2702e5b6d6dSopenharmony_cipublic: 2712e5b6d6dSopenharmony_ci TestFactory(CollatorInfo** _info) 2722e5b6d6dSopenharmony_ci : info(_info) 2732e5b6d6dSopenharmony_ci , count(0) 2742e5b6d6dSopenharmony_ci , ids(NULL) 2752e5b6d6dSopenharmony_ci { 2762e5b6d6dSopenharmony_ci CollatorInfo** p; 2772e5b6d6dSopenharmony_ci for (p = info; *p; ++p) {} 2782e5b6d6dSopenharmony_ci count = (int32_t)(p - info); 2792e5b6d6dSopenharmony_ci } 2802e5b6d6dSopenharmony_ci 2812e5b6d6dSopenharmony_ci ~TestFactory() { 2822e5b6d6dSopenharmony_ci for (CollatorInfo** p = info; *p; ++p) { 2832e5b6d6dSopenharmony_ci delete *p; 2842e5b6d6dSopenharmony_ci } 2852e5b6d6dSopenharmony_ci delete[] info; 2862e5b6d6dSopenharmony_ci delete[] ids; 2872e5b6d6dSopenharmony_ci } 2882e5b6d6dSopenharmony_ci 2892e5b6d6dSopenharmony_ci virtual Collator* createCollator(const Locale& loc) override { 2902e5b6d6dSopenharmony_ci const CollatorInfo* ci = getInfo(loc); 2912e5b6d6dSopenharmony_ci if (ci) { 2922e5b6d6dSopenharmony_ci return ci->collator->clone(); 2932e5b6d6dSopenharmony_ci } 2942e5b6d6dSopenharmony_ci return NULL; 2952e5b6d6dSopenharmony_ci } 2962e5b6d6dSopenharmony_ci 2972e5b6d6dSopenharmony_ci virtual UnicodeString& getDisplayName(const Locale& objectLocale, 2982e5b6d6dSopenharmony_ci const Locale& displayLocale, 2992e5b6d6dSopenharmony_ci UnicodeString& result) override 3002e5b6d6dSopenharmony_ci { 3012e5b6d6dSopenharmony_ci const CollatorInfo* ci = getInfo(objectLocale); 3022e5b6d6dSopenharmony_ci if (ci) { 3032e5b6d6dSopenharmony_ci ci->getDisplayName(displayLocale, result); 3042e5b6d6dSopenharmony_ci } else { 3052e5b6d6dSopenharmony_ci result.setToBogus(); 3062e5b6d6dSopenharmony_ci } 3072e5b6d6dSopenharmony_ci return result; 3082e5b6d6dSopenharmony_ci } 3092e5b6d6dSopenharmony_ci 3102e5b6d6dSopenharmony_ci const UnicodeString* getSupportedIDs(int32_t& _count, UErrorCode& status) override { 3112e5b6d6dSopenharmony_ci if (U_SUCCESS(status)) { 3122e5b6d6dSopenharmony_ci if (!ids) { 3132e5b6d6dSopenharmony_ci ids = new UnicodeString[count]; 3142e5b6d6dSopenharmony_ci if (!ids) { 3152e5b6d6dSopenharmony_ci status = U_MEMORY_ALLOCATION_ERROR; 3162e5b6d6dSopenharmony_ci _count = 0; 3172e5b6d6dSopenharmony_ci return NULL; 3182e5b6d6dSopenharmony_ci } 3192e5b6d6dSopenharmony_ci 3202e5b6d6dSopenharmony_ci for (int i = 0; i < count; ++i) { 3212e5b6d6dSopenharmony_ci ids[i] = info[i]->locale.getName(); 3222e5b6d6dSopenharmony_ci } 3232e5b6d6dSopenharmony_ci } 3242e5b6d6dSopenharmony_ci 3252e5b6d6dSopenharmony_ci _count = count; 3262e5b6d6dSopenharmony_ci return ids; 3272e5b6d6dSopenharmony_ci } 3282e5b6d6dSopenharmony_ci return NULL; 3292e5b6d6dSopenharmony_ci } 3302e5b6d6dSopenharmony_ci 3312e5b6d6dSopenharmony_ci virtual inline UClassID getDynamicClassID() const override { 3322e5b6d6dSopenharmony_ci return (UClassID)&gClassID; 3332e5b6d6dSopenharmony_ci } 3342e5b6d6dSopenharmony_ci 3352e5b6d6dSopenharmony_ci static UClassID getStaticClassID() { 3362e5b6d6dSopenharmony_ci return (UClassID)&gClassID; 3372e5b6d6dSopenharmony_ci } 3382e5b6d6dSopenharmony_ci 3392e5b6d6dSopenharmony_ciprivate: 3402e5b6d6dSopenharmony_ci static char gClassID; 3412e5b6d6dSopenharmony_ci}; 3422e5b6d6dSopenharmony_ci 3432e5b6d6dSopenharmony_cichar TestFactory::gClassID = 0; 3442e5b6d6dSopenharmony_ci#endif 3452e5b6d6dSopenharmony_ci 3462e5b6d6dSopenharmony_civoid CollationServiceTest::TestRegisterFactory(void) 3472e5b6d6dSopenharmony_ci{ 3482e5b6d6dSopenharmony_ci#if !UCONFIG_NO_SERVICE 3492e5b6d6dSopenharmony_ci int32_t n1, n2, n3; 3502e5b6d6dSopenharmony_ci Locale fu_FU("fu", "FU", ""); 3512e5b6d6dSopenharmony_ci Locale fu_FU_FOO("fu", "FU", "FOO"); 3522e5b6d6dSopenharmony_ci 3532e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 3542e5b6d6dSopenharmony_ci 3552e5b6d6dSopenharmony_ci Hashtable* fuFUNames = new Hashtable(false, status); 3562e5b6d6dSopenharmony_ci if (!fuFUNames) { 3572e5b6d6dSopenharmony_ci errln("memory allocation error"); 3582e5b6d6dSopenharmony_ci return; 3592e5b6d6dSopenharmony_ci } 3602e5b6d6dSopenharmony_ci fuFUNames->setValueDeleter(uprv_deleteUObject); 3612e5b6d6dSopenharmony_ci 3622e5b6d6dSopenharmony_ci fuFUNames->put(fu_FU.getName(), new UnicodeString("ze leetle bunny Fu-Fu"), status); 3632e5b6d6dSopenharmony_ci fuFUNames->put(fu_FU_FOO.getName(), new UnicodeString("zee leetel bunny Foo-Foo"), status); 3642e5b6d6dSopenharmony_ci fuFUNames->put(Locale::getDefault().getName(), new UnicodeString("little bunny Foo Foo"), status); 3652e5b6d6dSopenharmony_ci 3662e5b6d6dSopenharmony_ci Collator* frcol = Collator::createInstance(Locale::getFrance(), status); 3672e5b6d6dSopenharmony_ci Collator* gecol = Collator::createInstance(Locale::getGermany(), status); 3682e5b6d6dSopenharmony_ci Collator* jpcol = Collator::createInstance(Locale::getJapan(), status); 3692e5b6d6dSopenharmony_ci if(U_FAILURE(status)) { 3702e5b6d6dSopenharmony_ci errcheckln(status, "Failed to create collators with %s", u_errorName(status)); 3712e5b6d6dSopenharmony_ci delete frcol; 3722e5b6d6dSopenharmony_ci delete gecol; 3732e5b6d6dSopenharmony_ci delete jpcol; 3742e5b6d6dSopenharmony_ci delete fuFUNames; 3752e5b6d6dSopenharmony_ci return; 3762e5b6d6dSopenharmony_ci } 3772e5b6d6dSopenharmony_ci 3782e5b6d6dSopenharmony_ci CollatorInfo** info = new CollatorInfo*[4]; 3792e5b6d6dSopenharmony_ci if (!info) { 3802e5b6d6dSopenharmony_ci errln("memory allocation error"); 3812e5b6d6dSopenharmony_ci return; 3822e5b6d6dSopenharmony_ci } 3832e5b6d6dSopenharmony_ci 3842e5b6d6dSopenharmony_ci info[0] = new CollatorInfo(Locale::getUS(), frcol, NULL); 3852e5b6d6dSopenharmony_ci info[1] = new CollatorInfo(Locale::getFrance(), gecol, NULL); 3862e5b6d6dSopenharmony_ci info[2] = new CollatorInfo(fu_FU, jpcol, fuFUNames); 3872e5b6d6dSopenharmony_ci info[3] = NULL; 3882e5b6d6dSopenharmony_ci 3892e5b6d6dSopenharmony_ci TestFactory* factory = new TestFactory(info); 3902e5b6d6dSopenharmony_ci if (!factory) { 3912e5b6d6dSopenharmony_ci errln("memory allocation error"); 3922e5b6d6dSopenharmony_ci return; 3932e5b6d6dSopenharmony_ci } 3942e5b6d6dSopenharmony_ci 3952e5b6d6dSopenharmony_ci Collator* uscol = Collator::createInstance(Locale::getUS(), status); 3962e5b6d6dSopenharmony_ci Collator* fucol = Collator::createInstance(fu_FU, status); 3972e5b6d6dSopenharmony_ci 3982e5b6d6dSopenharmony_ci { 3992e5b6d6dSopenharmony_ci n1 = checkAvailable("before registerFactory"); 4002e5b6d6dSopenharmony_ci 4012e5b6d6dSopenharmony_ci URegistryKey key = Collator::registerFactory(factory, status); 4022e5b6d6dSopenharmony_ci 4032e5b6d6dSopenharmony_ci n2 = checkAvailable("after registerFactory"); 4042e5b6d6dSopenharmony_ci assertTrue("count after > count before", n2 > n1); 4052e5b6d6dSopenharmony_ci 4062e5b6d6dSopenharmony_ci Collator* ncol = Collator::createInstance(Locale::getUS(), status); 4072e5b6d6dSopenharmony_ci if (*frcol != *ncol) { 4082e5b6d6dSopenharmony_ci errln("frcoll for en_US failed"); 4092e5b6d6dSopenharmony_ci } 4102e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 4112e5b6d6dSopenharmony_ci 4122e5b6d6dSopenharmony_ci ncol = Collator::createInstance(fu_FU_FOO, status); 4132e5b6d6dSopenharmony_ci if (*jpcol != *ncol) { 4142e5b6d6dSopenharmony_ci errln("jpcol for fu_FU_FOO failed"); 4152e5b6d6dSopenharmony_ci } 4162e5b6d6dSopenharmony_ci 4172e5b6d6dSopenharmony_ci // The requested locale may be the same as the valid locale, 4182e5b6d6dSopenharmony_ci // or may not be supported at all. See ticket #10477. 4192e5b6d6dSopenharmony_ci Locale loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status); 4202e5b6d6dSopenharmony_ci if (U_SUCCESS(status) && loc != fu_FU_FOO && loc != fu_FU) { 4212e5b6d6dSopenharmony_ci errln(UnicodeString("requested locale for fu_FU_FOO is not fu_FU_FOO nor fu_FU but ") + loc.getName()); 4222e5b6d6dSopenharmony_ci } 4232e5b6d6dSopenharmony_ci status = U_ZERO_ERROR; 4242e5b6d6dSopenharmony_ci loc = ncol->getLocale(ULOC_VALID_LOCALE, status); 4252e5b6d6dSopenharmony_ci if (loc != fu_FU) { 4262e5b6d6dSopenharmony_ci errln(UnicodeString("valid locale for fu_FU_FOO is not fu_FU but ") + loc.getName()); 4272e5b6d6dSopenharmony_ci } 4282e5b6d6dSopenharmony_ci delete ncol; ncol = NULL; 4292e5b6d6dSopenharmony_ci 4302e5b6d6dSopenharmony_ci UnicodeString locName = fu_FU.getName(); 4312e5b6d6dSopenharmony_ci StringEnumeration* localeEnum = Collator::getAvailableLocales(); 4322e5b6d6dSopenharmony_ci UBool found = false; 4332e5b6d6dSopenharmony_ci const UnicodeString* locStr; 4342e5b6d6dSopenharmony_ci for (locStr = localeEnum->snext(status); 4352e5b6d6dSopenharmony_ci !found && locStr != NULL; 4362e5b6d6dSopenharmony_ci locStr = localeEnum->snext(status)) 4372e5b6d6dSopenharmony_ci { 4382e5b6d6dSopenharmony_ci if (locName == *locStr) { 4392e5b6d6dSopenharmony_ci found = true; 4402e5b6d6dSopenharmony_ci } 4412e5b6d6dSopenharmony_ci } 4422e5b6d6dSopenharmony_ci delete localeEnum; 4432e5b6d6dSopenharmony_ci 4442e5b6d6dSopenharmony_ci if (!found) { 4452e5b6d6dSopenharmony_ci errln("new locale fu_FU not reported as supported locale"); 4462e5b6d6dSopenharmony_ci } 4472e5b6d6dSopenharmony_ci 4482e5b6d6dSopenharmony_ci UnicodeString name; 4492e5b6d6dSopenharmony_ci Collator::getDisplayName(fu_FU, name); 4502e5b6d6dSopenharmony_ci if (name != "little bunny Foo Foo") { 4512e5b6d6dSopenharmony_ci errln(UnicodeString("found ") + name + " for fu_FU"); 4522e5b6d6dSopenharmony_ci } 4532e5b6d6dSopenharmony_ci 4542e5b6d6dSopenharmony_ci Collator::getDisplayName(fu_FU, fu_FU_FOO, name); 4552e5b6d6dSopenharmony_ci if (name != "zee leetel bunny Foo-Foo") { 4562e5b6d6dSopenharmony_ci errln(UnicodeString("found ") + name + " for fu_FU in fu_FU_FOO"); 4572e5b6d6dSopenharmony_ci } 4582e5b6d6dSopenharmony_ci 4592e5b6d6dSopenharmony_ci if (!Collator::unregister(key, status)) { 4602e5b6d6dSopenharmony_ci errln("failed to unregister factory"); 4612e5b6d6dSopenharmony_ci } 4622e5b6d6dSopenharmony_ci // ja, fr, ge collators no longer valid 4632e5b6d6dSopenharmony_ci 4642e5b6d6dSopenharmony_ci ncol = Collator::createInstance(fu_FU, status); 4652e5b6d6dSopenharmony_ci if (*fucol != *ncol) { 4662e5b6d6dSopenharmony_ci errln("collator after unregister does not match original fu_FU"); 4672e5b6d6dSopenharmony_ci } 4682e5b6d6dSopenharmony_ci delete ncol; 4692e5b6d6dSopenharmony_ci 4702e5b6d6dSopenharmony_ci n3 = checkAvailable("after unregister"); 4712e5b6d6dSopenharmony_ci assertTrue("count after unregister == count before register", n3 == n1); 4722e5b6d6dSopenharmony_ci } 4732e5b6d6dSopenharmony_ci 4742e5b6d6dSopenharmony_ci delete fucol; 4752e5b6d6dSopenharmony_ci delete uscol; 4762e5b6d6dSopenharmony_ci#endif 4772e5b6d6dSopenharmony_ci} 4782e5b6d6dSopenharmony_ci 4792e5b6d6dSopenharmony_ci/** 4802e5b6d6dSopenharmony_ci * Iterate through the given iterator, checking to see that all the strings 4812e5b6d6dSopenharmony_ci * in the expected array are present. 4822e5b6d6dSopenharmony_ci * @param expected array of strings we expect to see, or NULL 4832e5b6d6dSopenharmony_ci * @param expectedCount number of elements of expected, or 0 4842e5b6d6dSopenharmony_ci */ 4852e5b6d6dSopenharmony_ciint32_t CollationServiceTest::checkStringEnumeration(const char* msg, 4862e5b6d6dSopenharmony_ci StringEnumeration& iter, 4872e5b6d6dSopenharmony_ci const char** expected, 4882e5b6d6dSopenharmony_ci int32_t expectedCount) { 4892e5b6d6dSopenharmony_ci UErrorCode ec = U_ZERO_ERROR; 4902e5b6d6dSopenharmony_ci U_ASSERT(expectedCount >= 0 && expectedCount < 31); // [sic] 31 not 32 4912e5b6d6dSopenharmony_ci int32_t i = 0, idxAfterReset = 0, n = iter.count(ec); 4922e5b6d6dSopenharmony_ci assertSuccess("count", ec); 4932e5b6d6dSopenharmony_ci UnicodeString buf, buffAfterReset; 4942e5b6d6dSopenharmony_ci int32_t seenMask = 0; 4952e5b6d6dSopenharmony_ci for (;; ++i) { 4962e5b6d6dSopenharmony_ci const UnicodeString* s = iter.snext(ec); 4972e5b6d6dSopenharmony_ci if (!assertSuccess("snext", ec) || s == NULL) 4982e5b6d6dSopenharmony_ci break; 4992e5b6d6dSopenharmony_ci if (i != 0) 5002e5b6d6dSopenharmony_ci buf.append(UNICODE_STRING_SIMPLE(", ")); 5012e5b6d6dSopenharmony_ci buf.append(*s); 5022e5b6d6dSopenharmony_ci // check expected list 5032e5b6d6dSopenharmony_ci for (int32_t j=0, bit=1; j<expectedCount; ++j, bit<<=1) { 5042e5b6d6dSopenharmony_ci if ((seenMask&bit)==0) { 5052e5b6d6dSopenharmony_ci UnicodeString exp(expected[j], (char*)NULL); 5062e5b6d6dSopenharmony_ci if (*s == exp) { 5072e5b6d6dSopenharmony_ci seenMask |= bit; 5082e5b6d6dSopenharmony_ci logln((UnicodeString)"Ok: \"" + exp + "\" seen"); 5092e5b6d6dSopenharmony_ci } 5102e5b6d6dSopenharmony_ci } 5112e5b6d6dSopenharmony_ci } 5122e5b6d6dSopenharmony_ci } 5132e5b6d6dSopenharmony_ci // can't get pesky operator+(const US&, foo) to cooperate; use toString 5142e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING 5152e5b6d6dSopenharmony_ci logln(UnicodeString() + msg + " = [" + buf + "] (" + toString(i) + ")"); 5162e5b6d6dSopenharmony_ci#else 5172e5b6d6dSopenharmony_ci logln(UnicodeString() + msg + " = [" + buf + "] (??? NO_FORMATTING)"); 5182e5b6d6dSopenharmony_ci#endif 5192e5b6d6dSopenharmony_ci assertTrue("count verified", i==n); 5202e5b6d6dSopenharmony_ci iter.reset(ec); 5212e5b6d6dSopenharmony_ci for (;; ++idxAfterReset) { 5222e5b6d6dSopenharmony_ci const UChar *s = iter.unext(NULL, ec); 5232e5b6d6dSopenharmony_ci if (!assertSuccess("unext", ec) || s == NULL) 5242e5b6d6dSopenharmony_ci break; 5252e5b6d6dSopenharmony_ci if (idxAfterReset != 0) 5262e5b6d6dSopenharmony_ci buffAfterReset.append(UNICODE_STRING_SIMPLE(", ")); 5272e5b6d6dSopenharmony_ci buffAfterReset.append(s); 5282e5b6d6dSopenharmony_ci } 5292e5b6d6dSopenharmony_ci assertTrue("idxAfterReset verified", idxAfterReset==n); 5302e5b6d6dSopenharmony_ci assertTrue("buffAfterReset verified", buffAfterReset==buf); 5312e5b6d6dSopenharmony_ci // did we see all expected strings? 5322e5b6d6dSopenharmony_ci if (((1<<expectedCount)-1) != seenMask) { 5332e5b6d6dSopenharmony_ci for (int32_t j=0, bit=1; j<expectedCount; ++j, bit<<=1) { 5342e5b6d6dSopenharmony_ci if ((seenMask&bit)==0) { 5352e5b6d6dSopenharmony_ci errln((UnicodeString)"FAIL: \"" + expected[j] + "\" not seen"); 5362e5b6d6dSopenharmony_ci } 5372e5b6d6dSopenharmony_ci } 5382e5b6d6dSopenharmony_ci } 5392e5b6d6dSopenharmony_ci return n; 5402e5b6d6dSopenharmony_ci} 5412e5b6d6dSopenharmony_ci 5422e5b6d6dSopenharmony_ci/** 5432e5b6d6dSopenharmony_ci * Check the integrity of the results of Collator::getAvailableLocales(). 5442e5b6d6dSopenharmony_ci * Return the number of items returned. 5452e5b6d6dSopenharmony_ci */ 5462e5b6d6dSopenharmony_ci#if !UCONFIG_NO_SERVICE 5472e5b6d6dSopenharmony_ciint32_t CollationServiceTest::checkAvailable(const char* msg) { 5482e5b6d6dSopenharmony_ci StringEnumeration *iter = Collator::getAvailableLocales(); 5492e5b6d6dSopenharmony_ci if (!assertTrue("getAvailableLocales != NULL", iter!=NULL)) return -1; 5502e5b6d6dSopenharmony_ci int32_t n = checkStringEnumeration(msg, *iter, NULL, 0); 5512e5b6d6dSopenharmony_ci delete iter; 5522e5b6d6dSopenharmony_ci return n; 5532e5b6d6dSopenharmony_ci} 5542e5b6d6dSopenharmony_ci#endif 5552e5b6d6dSopenharmony_ci 5562e5b6d6dSopenharmony_cistatic const char* KW[] = { 5572e5b6d6dSopenharmony_ci "collation" 5582e5b6d6dSopenharmony_ci}; 5592e5b6d6dSopenharmony_cistatic const int32_t KW_COUNT = UPRV_LENGTHOF(KW); 5602e5b6d6dSopenharmony_ci 5612e5b6d6dSopenharmony_cistatic const char* KWVAL[] = { 5622e5b6d6dSopenharmony_ci "phonebook", 5632e5b6d6dSopenharmony_ci "stroke", 5642e5b6d6dSopenharmony_ci "emoji", 5652e5b6d6dSopenharmony_ci "eor" 5662e5b6d6dSopenharmony_ci}; 5672e5b6d6dSopenharmony_cistatic const int32_t KWVAL_COUNT = UPRV_LENGTHOF(KWVAL); 5682e5b6d6dSopenharmony_ci 5692e5b6d6dSopenharmony_civoid CollationServiceTest::TestSeparateTree() { 5702e5b6d6dSopenharmony_ci UErrorCode ec = U_ZERO_ERROR; 5712e5b6d6dSopenharmony_ci StringEnumeration *iter = Collator::getKeywords(ec); 5722e5b6d6dSopenharmony_ci if (!assertTrue("getKeywords != NULL", iter!=NULL)) return; 5732e5b6d6dSopenharmony_ci if (!assertSuccess("getKeywords", ec)) return; 5742e5b6d6dSopenharmony_ci checkStringEnumeration("getKeywords", *iter, KW, KW_COUNT); 5752e5b6d6dSopenharmony_ci delete iter; 5762e5b6d6dSopenharmony_ci 5772e5b6d6dSopenharmony_ci iter = Collator::getKeywordValues(KW[0], ec); 5782e5b6d6dSopenharmony_ci if (!assertTrue("getKeywordValues != NULL", iter!=NULL, false, true)) return; 5792e5b6d6dSopenharmony_ci if (!assertSuccess("getKeywordValues", ec)) return; 5802e5b6d6dSopenharmony_ci checkStringEnumeration("getKeywordValues", *iter, KWVAL, KWVAL_COUNT); 5812e5b6d6dSopenharmony_ci delete iter; 5822e5b6d6dSopenharmony_ci 5832e5b6d6dSopenharmony_ci UBool isAvailable; 5842e5b6d6dSopenharmony_ci Locale equiv = Collator::getFunctionalEquivalent("collation", 5852e5b6d6dSopenharmony_ci Locale::createFromName("de"), 5862e5b6d6dSopenharmony_ci isAvailable, ec); 5872e5b6d6dSopenharmony_ci assertSuccess("getFunctionalEquivalent", ec); 5882e5b6d6dSopenharmony_ci assertEquals("getFunctionalEquivalent(de)", "", equiv.getName()); 5892e5b6d6dSopenharmony_ci assertTrue("getFunctionalEquivalent(de).isAvailable==true", 5902e5b6d6dSopenharmony_ci isAvailable == true); 5912e5b6d6dSopenharmony_ci 5922e5b6d6dSopenharmony_ci equiv = Collator::getFunctionalEquivalent("collation", 5932e5b6d6dSopenharmony_ci Locale::createFromName("de_DE"), 5942e5b6d6dSopenharmony_ci isAvailable, ec); 5952e5b6d6dSopenharmony_ci assertSuccess("getFunctionalEquivalent", ec); 5962e5b6d6dSopenharmony_ci assertEquals("getFunctionalEquivalent(de_DE)", "", equiv.getName()); 5972e5b6d6dSopenharmony_ci assertTrue("getFunctionalEquivalent(de_DE).isAvailable==false", 5982e5b6d6dSopenharmony_ci isAvailable == false); 5992e5b6d6dSopenharmony_ci 6002e5b6d6dSopenharmony_ci equiv = Collator::getFunctionalEquivalent("collation", 6012e5b6d6dSopenharmony_ci Locale::createFromName("sv"), 6022e5b6d6dSopenharmony_ci isAvailable, ec); 6032e5b6d6dSopenharmony_ci assertSuccess("getFunctionalEquivalent", ec); 6042e5b6d6dSopenharmony_ci assertEquals("getFunctionalEquivalent(sv)", "sv", equiv.getName()); 6052e5b6d6dSopenharmony_ci assertTrue("getFunctionalEquivalent(sv).isAvailable==true", 6062e5b6d6dSopenharmony_ci isAvailable == true); 6072e5b6d6dSopenharmony_ci 6082e5b6d6dSopenharmony_ci equiv = Collator::getFunctionalEquivalent("collation", 6092e5b6d6dSopenharmony_ci Locale::createFromName("sv_SE"), 6102e5b6d6dSopenharmony_ci isAvailable, ec); 6112e5b6d6dSopenharmony_ci assertSuccess("getFunctionalEquivalent", ec); 6122e5b6d6dSopenharmony_ci assertEquals("getFunctionalEquivalent(sv_SE)", "sv", equiv.getName()); 6132e5b6d6dSopenharmony_ci assertTrue("getFunctionalEquivalent(sv_SE).isAvailable==false", 6142e5b6d6dSopenharmony_ci isAvailable == false); 6152e5b6d6dSopenharmony_ci} 6162e5b6d6dSopenharmony_ci 6172e5b6d6dSopenharmony_ci#endif 618