X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..0f5d89e82340278ed3d7d50029f37cab2c41a57e:/icuSources/test/intltest/loctest.cpp?ds=sidebyside diff --git a/icuSources/test/intltest/loctest.cpp b/icuSources/test/intltest/loctest.cpp index 06264a7f..708c27c5 100644 --- a/icuSources/test/intltest/loctest.cpp +++ b/icuSources/test/intltest/loctest.cpp @@ -1,6 +1,8 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2006, International Business Machines Corporation and + * Copyright (c) 1997-2016, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -8,13 +10,21 @@ #include "unicode/decimfmt.h" #include "unicode/ucurr.h" #include "unicode/smpdtfmt.h" +#include "unicode/strenum.h" #include "unicode/dtfmtsym.h" #include "unicode/brkiter.h" #include "unicode/coll.h" +#include "unicode/ustring.h" +#include "charstr.h" +#include "cmemory.h" #include "cstring.h" #include +#include +#include "putilimp.h" +#include "hash.h" +#include "locmap.h" -const char* rawData[33][8] = { +static const char* const rawData[33][8] = { // language code { "en", "fr", "ca", "el", "no", "it", "xx", "zh" }, @@ -44,31 +54,31 @@ const char* rawData[33][8] = { // display name (English) // Updated no_NO_NY English display name for new pattern-based algorithm // (part of Euro support). - { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified Han, China)" }, + { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China)" }, // display langage (French) { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" }, // display script (French) - { "", "", "", "", "", "", "", "id\\u00E9ogrammes han (variante simplifi\\u00E9e)" }, + { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" }, // display country (French) { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine" }, // display variant (French) { "", "", "", "", "NY", "", "", "" }, // display name (French) //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" }, - { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (id\\u00E9ogrammes han (variante simplifi\\u00E9e), Chine)" }, // STILL not right + { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine)" }, /* display language (Catalan) */ - { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E9s" }, + { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" }, /* display script (Catalan) */ - { "", "", "", "", "", "", "", "Hans" }, + { "", "", "", "", "", "", "", "han simplificat" }, /* display country (Catalan) */ { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina" }, /* display variant (Catalan) */ { "", "", "", "", "NY", "", "" }, /* display name (Catalan) */ - { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E9s (Hans, Xina)" }, + { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina)" }, // display langage (Greek)[actual values listed below] { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", @@ -81,7 +91,7 @@ const char* rawData[33][8] = { "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC" }, // display script (Greek) - { "", "", "", "", "", "", "", "Hans" }, + { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" }, // display country (Greek)[actual values listed below] { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2", "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", @@ -102,7 +112,7 @@ const char* rawData[33][8] = { "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac", "", - "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (Hans, \\u039A\\u03AF\\u03BD\\u03B1)" + "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03b1, \\u039A\\u03AF\\u03BD\\u03B1)" }, // display langage () @@ -177,54 +187,53 @@ LocaleTest::~LocaleTest() void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { - switch (index) { - TESTCASE(0, TestBasicGetters); - TESTCASE(1, TestSimpleResourceInfo); - TESTCASE(2, TestDisplayNames); - TESTCASE(3, TestSimpleObjectStuff); - TESTCASE(4, TestPOSIXParsing); - TESTCASE(5, TestGetAvailableLocales); - TESTCASE(6, TestDataDirectory); - TESTCASE(7, TestISO3Fallback); - TESTCASE(8, TestGetLangsAndCountries); - TESTCASE(9, TestSimpleDisplayNames); - TESTCASE(10, TestUninstalledISO3Names); - TESTCASE(11, TestAtypicalLocales); + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(TestBug11421); // Must run early in list to trigger failure. + TESTCASE_AUTO(TestBasicGetters); + TESTCASE_AUTO(TestSimpleResourceInfo); + TESTCASE_AUTO(TestDisplayNames); + TESTCASE_AUTO(TestSimpleObjectStuff); + TESTCASE_AUTO(TestPOSIXParsing); + TESTCASE_AUTO(TestGetAvailableLocales); + TESTCASE_AUTO(TestDataDirectory); + TESTCASE_AUTO(TestISO3Fallback); + TESTCASE_AUTO(TestGetLangsAndCountries); + TESTCASE_AUTO(TestSimpleDisplayNames); + TESTCASE_AUTO(TestUninstalledISO3Names); + TESTCASE_AUTO(TestAtypicalLocales); #if !UCONFIG_NO_FORMATTING - TESTCASE(12, TestThaiCurrencyFormat); - TESTCASE(13, TestEuroSupport); + TESTCASE_AUTO(TestThaiCurrencyFormat); + TESTCASE_AUTO(TestEuroSupport); #endif - TESTCASE(14, TestToString); + TESTCASE_AUTO(TestToString); #if !UCONFIG_NO_FORMATTING - TESTCASE(15, Test4139940); - TESTCASE(16, Test4143951); + TESTCASE_AUTO(Test4139940); + TESTCASE_AUTO(Test4143951); #endif - TESTCASE(17, Test4147315); - TESTCASE(18, Test4147317); - TESTCASE(19, Test4147552); - TESTCASE(20, TestVariantParsing); + TESTCASE_AUTO(Test4147315); + TESTCASE_AUTO(Test4147317); + TESTCASE_AUTO(Test4147552); + TESTCASE_AUTO(TestVariantParsing); #if !UCONFIG_NO_FORMATTING - TESTCASE(21, Test4105828); + TESTCASE_AUTO(Test4105828); #endif - TESTCASE(22, TestSetIsBogus); - TESTCASE(23, TestParallelAPIValues); - TESTCASE(24, TestKeywordVariants); - TESTCASE(25, TestKeywordVariantParsing); - TESTCASE(26, TestGetBaseName); - TESTCASE(27, TestGetLocale); - TESTCASE(28, TestVariantWithOutCountry); - TESTCASE(29, TestCanonicalization); - - // keep the last index in sync with the condition in default: - - default: - if (index <= 28) { // keep this in sync with the last index! - name = "(test omitted by !UCONFIG_NO_FORMATTING)"; - } else { - name = ""; - } - break; //needed to end loop - } + TESTCASE_AUTO(TestSetIsBogus); + TESTCASE_AUTO(TestParallelAPIValues); + TESTCASE_AUTO(TestKeywordVariants); + TESTCASE_AUTO(TestKeywordVariantParsing); + TESTCASE_AUTO(TestSetKeywordValue); + TESTCASE_AUTO(TestGetBaseName); +#if !UCONFIG_NO_FILE_IO + TESTCASE_AUTO(TestGetLocale); +#endif + TESTCASE_AUTO(TestVariantWithOutCountry); + TESTCASE_AUTO(TestCanonicalization); + TESTCASE_AUTO(TestCurrencyByDate); + TESTCASE_AUTO(TestGetVariantWithKeywords); + TESTCASE_AUTO(TestIsRightToLeft); + TESTCASE_AUTO(TestBug13277); + TESTCASE_AUTO(TestBug13554); + TESTCASE_AUTO_END; } void LocaleTest::TestBasicGetters() { @@ -467,25 +476,40 @@ LocaleTest::TestDisplayNames() logln(" In locale = el_GR..."); doTestDisplayNames(greek, DLANG_EL); - /* test that the default locale has a display name for its own language */ UnicodeString s; - Locale().getDisplayLanguage(Locale(), s); - if(s.length()<=3 && s.charAt(0)<=0x7f) { - /* check <=3 to reject getting the language code as a display name */ - errln("unable to get a display string for the language of the default locale\n"); - } + UErrorCode status = U_ZERO_ERROR; - /* - * API coverage improvements: call - * Locale::getDisplayLanguage(UnicodeString &) and - * Locale::getDisplayCountry(UnicodeString &) - */ - s.remove(); - Locale().getDisplayLanguage(s); - if(s.length()<=3 && s.charAt(0)<=0x7f) { - errln("unable to get a display string for the language of the default locale [2]\n"); +#if !UCONFIG_NO_FORMATTING + DecimalFormatSymbols symb(status); + /* Check to see if ICU supports this locale */ + if (symb.getLocale(ULOC_VALID_LOCALE, status) != Locale("root")) { + /* test that the default locale has a display name for its own language */ + /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */ + if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) { + Locale().getDisplayLanguage(Locale(), s); + if(s.length()<=3 && s.charAt(0)<=0x7f) { + /* check <=3 to reject getting the language code as a display name */ + dataerrln("unable to get a display string for the language of the default locale: " + s); + } + + /* + * API coverage improvements: call + * Locale::getDisplayLanguage(UnicodeString &) and + * Locale::getDisplayCountry(UnicodeString &) + */ + s.remove(); + Locale().getDisplayLanguage(s); + if(s.length()<=3 && s.charAt(0)<=0x7f) { + dataerrln("unable to get a display string for the language of the default locale [2]: " + s); + } + } + } + else { + logln("Default locale %s is unsupported by ICU\n", Locale().getName()); } s.remove(); +#endif + french.getDisplayCountry(s); if(s.isEmpty()) { errln("unable to get any default-locale display string for the country of fr_FR\n"); @@ -658,7 +682,7 @@ void LocaleTest::TestGetAvailableLocales() const Locale* locList = Locale::getAvailableLocales(locCount); if (locCount == 0) - errln("getAvailableLocales() returned an empty list!"); + dataerrln("getAvailableLocales() returned an empty list!"); else { logln(UnicodeString("Number of locales returned = ") + locCount); UnicodeString temp; @@ -761,15 +785,15 @@ void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) expectedName = dataTable[DNAME_EN][i]; if (testLang != expectedLang) - errln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang); + dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang); if (testScript != expectedScript) - errln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript); + dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript); if (testCtry != expectedCtry) - errln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry); + dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry); if (testVar != expectedVar) - errln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar); + dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar); if (testName != expectedName) - errln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName); + dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName); } } @@ -845,8 +869,8 @@ LocaleTest::TestGetLangsAndCountries() ; /* TODO: Change this test to be more like the cloctst version? */ - if (testCount != 485) - errln("Expected getISOLanguages() to return 481 languages; it returned %d", testCount); + if (testCount != 595) + errln("Expected getISOLanguages() to return 595 languages; it returned %d", testCount); else { for (i = 0; i < 15; i++) { int32_t j; @@ -876,8 +900,8 @@ LocaleTest::TestGetLangsAndCountries() for(testCount=0;test[testCount];testCount++) ; - if (testCount != 244){ - errln("Expected getISOCountries to return 240 countries; it returned %d", testCount); + if (testCount != 256){ + errln("Expected getISOCountries to return 256 countries; it returned %d", testCount); }else { for (i = 0; i < spot2Len; i++) { int32_t j; @@ -893,8 +917,8 @@ LocaleTest::TestGetLangsAndCountries() errln("Couldn't find " + spotCheck2[i] + " in country list."); } } - for (i = 0; i < testCount; i++) { - UnicodeString testee(test[i],""); + for (i = 0; i < testCount; i++) { + UnicodeString testee(test[i],""); UnicodeString uc(test[i],""); if (testee != uc.toUpper()) errln(testee + " is not all upper case."); @@ -903,6 +927,26 @@ LocaleTest::TestGetLangsAndCountries() if (i > 0 && testee.compare(test[i - 1]) <= 0) errln(testee + " appears in an out-of-order position in the list."); } + + // This getAvailableLocales and getISO3Language + { + int32_t numOfLocales; + Locale enLoc ("en"); + const Locale *pLocales = Locale::getAvailableLocales(numOfLocales); + + for (int i = 0; i < numOfLocales; i++) { + const Locale &loc(pLocales[i]); + UnicodeString name; + char szName[200]; + + loc.getDisplayName (enLoc, name); + name.extract (0, 200, szName, sizeof(szName)); + + if (strlen(loc.getISO3Language()) == 0) { + errln("getISO3Language() returned an empty string for: " + name); + } + } + } } /** @@ -916,7 +960,7 @@ LocaleTest::TestSimpleDisplayNames() // names, and other stuff like that. This test just checks specific language // and country codes to make sure we have the correct names for them. char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" }; - UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish", + UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish", "Zhuang" }; for (int32_t i = 0; i < 6; i++) { @@ -924,7 +968,7 @@ LocaleTest::TestSimpleDisplayNames() Locale l(languageCodes[i], "", ""); l.getDisplayLanguage(Locale::getUS(), test); if (test != languageNames[i]) - errln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" + + dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" + languageNames[i] + "\", got \"" + test + "\"."); } } @@ -1005,7 +1049,7 @@ LocaleTest::TestAtypicalLocales() "espagnol (Allemagne)", "Croatie", CharsToUnicodeString("Su\\u00E8de"), - CharsToUnicodeString("Dominicaine, r\\u00E9publique"), + CharsToUnicodeString("R\\u00E9publique dominicaine"), "Belgique" }; UnicodeString spanishDisplayNames [] = { CharsToUnicodeString("alem\\u00E1n (Canad\\u00E1)"), @@ -1039,7 +1083,7 @@ LocaleTest::TestAtypicalLocales() logln(name); if (name != englishDisplayNames[i]) { - errln("Lookup in English failed: expected \"" + englishDisplayNames[i] + dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i] + "\", got \"" + name + "\""); logln("Locale name was-> " + (name=localesToTest[i].getName())); } @@ -1050,7 +1094,7 @@ LocaleTest::TestAtypicalLocales() localesToTest[i].getDisplayName(Locale("es", "ES"), name); logln(name); if (name != spanishDisplayNames[i]) - errln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i] + dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i] + "\", got \"" + name + "\""); } @@ -1059,7 +1103,7 @@ LocaleTest::TestAtypicalLocales() localesToTest[i].getDisplayName(Locale::getFrance(), name); logln(name); if (name != frenchDisplayNames[i]) - errln("Lookup in French failed: expected \"" + frenchDisplayNames[i] + dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i] + "\", got \"" + name + "\""); } @@ -1068,12 +1112,12 @@ LocaleTest::TestAtypicalLocales() localesToTest[i].getDisplayName(Locale("inv", "IN"), name); logln(name + " Locale fallback to be, and data fallback to root"); if (name != invDisplayNames[i]) - errln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) + dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) + "\", got \"" + prettify(name) + "\""); localesToTest[i].getDisplayName(Locale("inv", "BD"), name); logln(name + " Data fallback to root"); if (name != invDisplayNames[i]) - errln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) + dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) + "\", got \"" + prettify(name )+ "\""); } Locale::setDefault(saveLocale, status); @@ -1092,16 +1136,16 @@ LocaleTest::TestThaiCurrencyFormat() UErrorCode status = U_ZERO_ERROR; DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance( Locale("th", "TH"), status); - UChar posPrefix = 0x0e3f; + UnicodeString posPrefix("THB", 3, US_INV); // per cldrbug 7618 UnicodeString temp; if(U_FAILURE(status) || !thaiCurrency) { - errln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status))); + dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status))); return; } - if (thaiCurrency->getPositivePrefix(temp) != UnicodeString(&posPrefix, 1, 1)) - errln("Thai currency prefix wrong: expected 0x0e3f, got \"" + + if (thaiCurrency->getPositivePrefix(temp) != posPrefix) + errln("Thai currency prefix wrong: expected THB, got \"" + thaiCurrency->getPositivePrefix(temp) + "\""); if (thaiCurrency->getPositiveSuffix(temp) != "") errln("Thai currency suffix wrong: expected \"\", got \"" + @@ -1192,32 +1236,45 @@ LocaleTest::TestEuroSupport() ucurr_forLocale("en_US", tmp, 4, &status); resultStr.setTo(tmp); if (dollarStr != resultStr) { - errln("Fail: en_US didn't return USD"); + errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status)); } ucurr_forLocale("en_US_EURO", tmp, 4, &status); resultStr.setTo(tmp); if (euroStr != resultStr) { - errln("Fail: en_US_EURO didn't return EUR"); + errcheckln(status, "Fail: en_US_EURO didn't return EUR - %s", u_errorName(status)); } ucurr_forLocale("en_GB_EURO", tmp, 4, &status); resultStr.setTo(tmp); if (euroStr != resultStr) { - errln("Fail: en_GB_EURO didn't return EUR"); + errcheckln(status, "Fail: en_GB_EURO didn't return EUR - %s", u_errorName(status)); } ucurr_forLocale("en_US_PREEURO", tmp, 4, &status); resultStr.setTo(tmp); if (dollarStr != resultStr) { - errln("Fail: en_US_PREEURO didn't fallback to en_US"); + errcheckln(status, "Fail: en_US_PREEURO didn't fallback to en_US - %s", u_errorName(status)); } ucurr_forLocale("en_US_Q", tmp, 4, &status); resultStr.setTo(tmp); if (dollarStr != resultStr) { - errln("Fail: en_US_Q didn't fallback to en_US"); + errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status)); } int32_t invalidLen = ucurr_forLocale("en_QQ", tmp, 4, &status); if (invalidLen || U_SUCCESS(status)) { errln("Fail: en_QQ didn't return NULL"); } + + // The currency keyword value is as long as the destination buffer. + // It should detect the overflow internally, and default to the locale's currency. + tmp[0] = u'¤'; + status = U_ZERO_ERROR; + int32_t length = ucurr_forLocale("en_US@currency=euro", tmp, 4, &status); + if (U_FAILURE(status) || dollarStr != UnicodeString(tmp, length)) { + if (U_SUCCESS(status) && tmp[0] == u'¤') { + errln("Fail: ucurr_forLocale(en_US@currency=euro) succeeded without writing output"); + } else { + errln("Fail: ucurr_forLocale(en_US@currency=euro) != USD - %s", u_errorName(status)); + } + } } #endif @@ -1287,7 +1344,7 @@ LocaleTest::Test4139940() UErrorCode status = U_ZERO_ERROR; SimpleDateFormat df_full("EEEE", mylocale, status); if(U_FAILURE(status)){ - errln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: " )+ UnicodeString(u_errorName(status))); + dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status))); return; } UnicodeString str; @@ -1298,8 +1355,13 @@ LocaleTest::Test4139940() UChar ocf = 0x00f4; UChar oda = 0x0151; if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) { - errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d", - str.indexOf(oda), str.indexOf(ocf)); + /* If the default locale is "th" this test will fail because of the buddhist calendar. */ + if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) { + errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d", + str.indexOf(oda), str.indexOf(ocf)); + } else { + logln(UnicodeString("An error is produce in buddhist calendar.")); + } logln(UnicodeString("String is: ") + str ); } } @@ -1332,7 +1394,7 @@ LocaleTest::Test4143951() Calendar *cal = Calendar::createInstance(Locale("ru", "", ""), status); if(U_SUCCESS(status)) { if (cal->getFirstDayOfWeek(status) != UCAL_MONDAY) { - errln("Fail: First day of week in Russia should be Monday"); + dataerrln("Fail: First day of week in Russia should be Monday"); } } delete cal; @@ -1351,7 +1413,7 @@ LocaleTest::Test4147315() UnicodeString temp; // Try with codes that are the wrong length but happen to match text // at a valid offset in the mapping table - Locale locale("aaa", "CCC"); + Locale locale("xxx", "CCC"); const char *result = locale.getISO3Country(); @@ -1372,7 +1434,7 @@ LocaleTest::Test4147317() UnicodeString temp; // Try with codes that are the wrong length but happen to match text // at a valid offset in the mapping table - Locale locale("aaa", "CCC"); + Locale locale("xxx", "CCC"); const char *result = locale.getISO3Language(); @@ -1417,10 +1479,10 @@ LocaleTest::Test4147552() Locale loc = locales[i]; UnicodeString temp; if (loc.getDisplayName(temp) != englishDisplayNames[i]) - errln("English display-name mismatch: expected " + + dataerrln("English display-name mismatch: expected " + englishDisplayNames[i] + ", got " + loc.getDisplayName(temp)); if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i]) - errln("Norwegian display-name mismatch: expected " + + dataerrln("Norwegian display-name mismatch: expected " + norwegianDisplayNames[i] + ", got " + loc.getDisplayName(loc, temp)); } @@ -1446,9 +1508,9 @@ LocaleTest::TestVariantParsing() en_US_custom.getDisplayName(Locale::getUS(), got); if(got != dispName) { - errln("FAIL: getDisplayName()"); - errln("Wanted: " + dispName); - errln("Got : " + got); + dataerrln("FAIL: getDisplayName()"); + dataerrln("Wanted: " + dispName); + dataerrln("Got : " + got); } Locale shortVariant("fr", "FR", "foo"); @@ -1504,11 +1566,11 @@ LocaleTest::Test4105828() for (int32_t i = 0; i < 4; ++i) { NumberFormat *fmt = NumberFormat::createPercentInstance(LOC[i], status); if(U_FAILURE(status)) { - errln("Couldn't create NumberFormat"); + dataerrln("Couldn't create NumberFormat - %s", u_errorName(status)); return; } UnicodeString result; - FieldPosition pos(0); + FieldPosition pos(FieldPosition::DONT_CARE); fmt->format((int32_t)1, result, pos); UnicodeString temp; if(result != "100%") { @@ -1538,7 +1600,7 @@ LocaleTest::TestSetIsBogus() { void LocaleTest::TestKeywordVariants(void) { - struct { + static const struct { const char *localeID; const char *expectedLocaleID; //const char *expectedLocaleIDNoKeywords; @@ -1576,7 +1638,7 @@ LocaleTest::TestKeywordVariants(void) { const UnicodeString *keywordString; int32_t keywordLen = 0; - for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) { + for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { status = U_ZERO_ERROR; Locale l(testCases[i].localeID); keywords = l.createKeywords(status); @@ -1645,7 +1707,7 @@ LocaleTest::TestKeywordVariants(void) { void LocaleTest::TestKeywordVariantParsing(void) { - struct { + static const struct { const char *localeID; const char *keyword; const char *expectedValue; @@ -1662,10 +1724,11 @@ LocaleTest::TestKeywordVariantParsing(void) { int32_t resultLen = 0; char buffer[256]; - for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) { + for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { *buffer = 0; Locale l(testCases[i].localeID); resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status); + (void)resultLen; // Suppress unused variable warning. if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) { err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n", testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer); @@ -1673,20 +1736,56 @@ LocaleTest::TestKeywordVariantParsing(void) { } } +void +LocaleTest::TestSetKeywordValue(void) { + static const struct { + const char *keyword; + const char *value; + } testCases[] = { + { "collation", "phonebook" }, + { "currency", "euro" }, + { "calendar", "buddhist" } + }; + + UErrorCode status = U_ZERO_ERROR; + + int32_t i = 0; + int32_t resultLen = 0; + char buffer[256]; + + Locale l(Locale::getGerman()); + + for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { + l.setKeywordValue(testCases[i].keyword, testCases[i].value, status); + if(U_FAILURE(status)) { + err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status)); + } + + *buffer = 0; + resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status); + (void)resultLen; // Suppress unused variable warning. + if(uprv_strcmp(testCases[i].value, buffer) != 0) { + err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n", + testCases[i].value, testCases[i].keyword, buffer); + } + } +} + void LocaleTest::TestGetBaseName(void) { - struct { + static const struct { const char *localeID; const char *baseName; } testCases[] = { { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" }, { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" }, - { "ja@calendar = buddhist", "ja" } + { "ja@calendar = buddhist", "ja" }, + { "de-u-co-phonebk", "de"} }; int32_t i = 0; - for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) { + for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { Locale loc(testCases[i].localeID); if(strcmp(testCases[i].baseName, loc.getBaseName())) { errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"", @@ -1694,6 +1793,20 @@ LocaleTest::TestGetBaseName(void) { return; } } + + // Verify that adding a keyword to an existing Locale doesn't change the base name. + UErrorCode status = U_ZERO_ERROR; + Locale loc2("en-US"); + if (strcmp("en_US", loc2.getBaseName())) { + errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName()); + } + loc2.setKeywordValue("key", "value", status); + if (strcmp("en_US@key=value", loc2.getName())) { + errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__, __LINE__, loc2.getName()); + } + if (strcmp("en_US", loc2.getBaseName())) { + errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName()); + } } /** @@ -1743,7 +1856,7 @@ void LocaleTest::_checklocs(const char* label, logln("%s; req=%s, valid=%s, actual=%s", label, req, valid, actual); } else { - errln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)", + dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)", label, req, valid, actual, expReqValid, expValidActual); } @@ -1751,129 +1864,164 @@ void LocaleTest::_checklocs(const char* label, void LocaleTest::TestGetLocale(void) { #if !UCONFIG_NO_SERVICE - UErrorCode ec = U_ZERO_ERROR; const char *req; Locale valid, actual, reqLoc; // Calendar #if !UCONFIG_NO_FORMATTING - req = "en_US_BROOKLYN"; - Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec); - if (U_FAILURE(ec)) { - errln("FAIL: Calendar::createInstance failed"); - } else { - valid = cal->getLocale(ULOC_VALID_LOCALE, ec); - actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec); + { + UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code + req = "en_US_BROOKLYN"; + Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec); if (U_FAILURE(ec)) { - errln("FAIL: Calendar::getLocale() failed"); + dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec)); } else { - _checklocs("Calendar", req, valid, actual); - } - /* Make sure that it fails correctly */ - ec = U_FILE_ACCESS_ERROR; - if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) { - errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\""); + valid = cal->getLocale(ULOC_VALID_LOCALE, ec); + actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: Calendar::getLocale() failed"); + } else { + _checklocs("Calendar", req, valid, actual); + } + /* Make sure that it fails correctly */ + ec = U_FILE_ACCESS_ERROR; + if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) { + errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\""); + } + ec = U_ZERO_ERROR; } - ec = U_ZERO_ERROR; + delete cal; } - delete cal; #endif // DecimalFormat, DecimalFormatSymbols #if !UCONFIG_NO_FORMATTING - req = "fr_FR_NICE"; - DecimalFormat* dec = (DecimalFormat*) - NumberFormat::createInstance(Locale::createFromName(req), ec); - if (U_FAILURE(ec)) { - errln("FAIL: NumberFormat::createInstance failed"); - } else { - if (dec->getDynamicClassID() != DecimalFormat::getStaticClassID()) { - errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat"); - return; - } - valid = dec->getLocale(ULOC_VALID_LOCALE, ec); - actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec); + { + UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code + req = "fr_FR_NICE"; + NumberFormat* nf = NumberFormat::createInstance(Locale::createFromName(req), ec); if (U_FAILURE(ec)) { - errln("FAIL: DecimalFormat::getLocale() failed"); + dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec)); } else { - _checklocs("DecimalFormat", req, valid, actual); - } + DecimalFormat* dec = dynamic_cast(nf); + if (dec == NULL) { + errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat"); + return; + } + valid = dec->getLocale(ULOC_VALID_LOCALE, ec); + actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: DecimalFormat::getLocale() failed"); + } else { + _checklocs("DecimalFormat", req, valid, actual); + } - const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols(); - if (sym == NULL) { - errln("FAIL: getDecimalFormatSymbols returned NULL"); - return; + const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols(); + if (sym == NULL) { + errln("FAIL: getDecimalFormatSymbols returned NULL"); + return; + } + valid = sym->getLocale(ULOC_VALID_LOCALE, ec); + actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: DecimalFormatSymbols::getLocale() failed"); + } else { + _checklocs("DecimalFormatSymbols", req, valid, actual); + } } - valid = sym->getLocale(ULOC_VALID_LOCALE, ec); - actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: DecimalFormatSymbols::getLocale() failed"); - } else { - _checklocs("DecimalFormatSymbols", req, valid, actual); - } + delete nf; } - delete dec; #endif // DateFormat, DateFormatSymbols #if !UCONFIG_NO_FORMATTING - req = "de_CH_LUCERNE"; - SimpleDateFormat* dat = (SimpleDateFormat*) - DateFormat::createDateInstance(DateFormat::kDefault, - Locale::createFromName(req)); - if (dat == 0){ - dataerrln("Error calling DateFormat::createDateInstance()"); - } else { - if (dat->getDynamicClassID() != SimpleDateFormat::getStaticClassID()) { - errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat"); - return; - } - valid = dat->getLocale(ULOC_VALID_LOCALE, ec); - actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: SimpleDateFormat::getLocale() failed"); + { + UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code + req = "de_CH_LUCERNE"; + DateFormat* df = + DateFormat::createDateInstance(DateFormat::kDefault, + Locale::createFromName(req)); + if (df == 0){ + dataerrln("Error calling DateFormat::createDateInstance()"); } else { - _checklocs("SimpleDateFormat", req, valid, actual); - } + SimpleDateFormat* dat = dynamic_cast(df); + if (dat == NULL) { + errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat"); + return; + } + valid = dat->getLocale(ULOC_VALID_LOCALE, ec); + actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: SimpleDateFormat::getLocale() failed"); + } else { + _checklocs("SimpleDateFormat", req, valid, actual); + } - const DateFormatSymbols* sym = dat->getDateFormatSymbols(); - if (sym == NULL) { - errln("FAIL: getDateFormatSymbols returned NULL"); - return; + const DateFormatSymbols* sym = dat->getDateFormatSymbols(); + if (sym == NULL) { + errln("FAIL: getDateFormatSymbols returned NULL"); + return; + } + valid = sym->getLocale(ULOC_VALID_LOCALE, ec); + actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: DateFormatSymbols::getLocale() failed"); + } else { + _checklocs("DateFormatSymbols", req, valid, actual); + } } - valid = sym->getLocale(ULOC_VALID_LOCALE, ec); - actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: DateFormatSymbols::getLocale() failed"); - } else { - _checklocs("DateFormatSymbols", req, valid, actual); - } + delete df; } - delete dat; #endif // BreakIterator #if !UCONFIG_NO_BREAK_ITERATION - req = "es_ES_BARCELONA"; - reqLoc = Locale::createFromName(req); - BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec); - if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::createWordInstance failed"); - } else { - valid = brk->getLocale(ULOC_VALID_LOCALE, ec); - actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); + { + UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code + req = "es_ES_BARCELONA"; + reqLoc = Locale::createFromName(req); + BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec); if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::getLocale() failed"); + dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec)); } else { - _checklocs("BreakIterator", req, valid, actual); - } + valid = brk->getLocale(ULOC_VALID_LOCALE, ec); + actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: BreakIterator::getLocale() failed"); + } else { + _checklocs("BreakIterator", req, valid, actual); + } - // After registering something, the behavior should be different - URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec); - brk = 0; // registerInstance adopts - if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::registerInstance() failed"); - } else { + // After registering something, the behavior should be different + URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec); + brk = 0; // registerInstance adopts + if (U_FAILURE(ec)) { + errln("FAIL: BreakIterator::registerInstance() failed"); + } else { + brk = BreakIterator::createWordInstance(reqLoc, ec); + if (U_FAILURE(ec)) { + errln("FAIL: BreakIterator::createWordInstance failed"); + } else { + valid = brk->getLocale(ULOC_VALID_LOCALE, ec); + actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: BreakIterator::getLocale() failed"); + } else { + // N.B.: now expect valid==actual==req + _checklocs("BreakIterator(registered)", + req, valid, actual, "eq", "eq"); + } + } + // No matter what, unregister + BreakIterator::unregister(key, ec); + if (U_FAILURE(ec)) { + errln("FAIL: BreakIterator::unregister() failed"); + } + delete brk; + brk = 0; + } + + // After unregistering, should behave normally again brk = BreakIterator::createWordInstance(reqLoc, ec); if (U_FAILURE(ec)) { errln("FAIL: BreakIterator::createWordInstance failed"); @@ -1883,121 +2031,206 @@ void LocaleTest::TestGetLocale(void) { if (U_FAILURE(ec)) { errln("FAIL: BreakIterator::getLocale() failed"); } else { - // N.B.: now expect valid==actual==req - _checklocs("BreakIterator(registered)", - req, valid, actual, "eq", "eq"); + _checklocs("BreakIterator(unregistered)", req, valid, actual); } } - // No matter what, unregister - BreakIterator::unregister(key, ec); - if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::unregister() failed"); - } - delete brk; - brk = 0; - } - - // After unregistering, should behave normally again - brk = BreakIterator::createWordInstance(reqLoc, ec); - if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::createWordInstance failed"); - } else { - valid = brk->getLocale(ULOC_VALID_LOCALE, ec); - actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: BreakIterator::getLocale() failed"); - } else { - _checklocs("BreakIterator(unregistered)", req, valid, actual); - } } + delete brk; } - delete brk; #endif // Collator #if !UCONFIG_NO_COLLATION - req = "hi_IN_BHOPAL"; - reqLoc = Locale::createFromName(req); - Collator* coll = Collator::createInstance(reqLoc, ec); - if (U_FAILURE(ec)) { - errln("FAIL: Collator::createInstance failed"); - } else { - valid = coll->getLocale(ULOC_VALID_LOCALE, ec); - actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: Collator::getLocale() failed"); - } else { - _checklocs("Collator", req, valid, actual); - } + { + UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code + + checkRegisteredCollators(NULL); // Don't expect any extras - // After registering something, the behavior should be different - URegistryKey key = Collator::registerInstance(coll, reqLoc, ec); - coll = 0; // registerInstance adopts + req = "hi_IN_BHOPAL"; + reqLoc = Locale::createFromName(req); + Collator* coll = Collator::createInstance(reqLoc, ec); if (U_FAILURE(ec)) { - errln("FAIL: Collator::registerInstance() failed"); + dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec)); } else { + valid = coll->getLocale(ULOC_VALID_LOCALE, ec); + actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: Collator::getLocale() failed"); + } else { + _checklocs("Collator", req, valid, actual); + } + + // After registering something, the behavior should be different + URegistryKey key = Collator::registerInstance(coll, reqLoc, ec); + coll = 0; // registerInstance adopts + if (U_FAILURE(ec)) { + errln("FAIL: Collator::registerInstance() failed"); + } else { + coll = Collator::createInstance(reqLoc, ec); + if (U_FAILURE(ec)) { + errln("FAIL: Collator::createWordInstance failed"); + } else { + valid = coll->getLocale(ULOC_VALID_LOCALE, ec); + actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); + if (U_FAILURE(ec)) { + errln("FAIL: Collator::getLocale() failed"); + } else { + // N.B.: now expect valid==actual==req + _checklocs("Collator(registered)", + req, valid, actual, "eq", "eq"); + } + } + checkRegisteredCollators(req); // include hi_IN_BHOPAL + + // No matter what, unregister + Collator::unregister(key, ec); + if (U_FAILURE(ec)) { + errln("FAIL: Collator::unregister() failed"); + } + delete coll; + coll = 0; + } + + // After unregistering, should behave normally again coll = Collator::createInstance(reqLoc, ec); if (U_FAILURE(ec)) { - errln("FAIL: Collator::createWordInstance failed"); + errln("FAIL: Collator::createInstance failed"); } else { valid = coll->getLocale(ULOC_VALID_LOCALE, ec); actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); if (U_FAILURE(ec)) { errln("FAIL: Collator::getLocale() failed"); } else { - // N.B.: now expect valid==actual==req - _checklocs("Collator(registered)", - req, valid, actual, "eq", "eq"); + _checklocs("Collator(unregistered)", req, valid, actual); } } - // No matter what, unregister - Collator::unregister(key, ec); - if (U_FAILURE(ec)) { - errln("FAIL: Collator::unregister() failed"); - } - delete coll; - coll = 0; } + delete coll; - // After unregistering, should behave normally again - coll = Collator::createInstance(reqLoc, ec); - if (U_FAILURE(ec)) { - errln("FAIL: Collator::createInstance failed"); - } else { - valid = coll->getLocale(ULOC_VALID_LOCALE, ec); - actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); - if (U_FAILURE(ec)) { - errln("FAIL: Collator::getLocale() failed"); + checkRegisteredCollators(NULL); // extra should be gone again + } +#endif +#endif +} + +#if !UCONFIG_NO_COLLATION +/** + * Compare Collator::getAvailableLocales(int) [ "old", returning an array ] + * with Collator::getAvailableLocales() [ "new", returning a StringEnumeration ] + * These should be identical (check their API docs) EXCEPT that + * if expectExtra is non-NULL, it will be in the "new" array but not "old". + * Does not return any status but calls errln on error. + * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL. + */ +void LocaleTest::checkRegisteredCollators(const char *expectExtra) { + UErrorCode status = U_ZERO_ERROR; + int32_t count1=0,count2=0; + Hashtable oldHash(status); + Hashtable newHash(status); + TEST_ASSERT_STATUS(status); + + UnicodeString expectStr(expectExtra?expectExtra:"n/a", ""); + + // the 'old' list (non enumeration) + const Locale* oldList = Collator::getAvailableLocales(count1); + if(oldList == NULL) { + dataerrln("Error: Collator::getAvailableLocales(count) returned NULL"); + return; + } + + // the 'new' list (enumeration) + LocalPointer newEnum(Collator::getAvailableLocales()); + if(newEnum.isNull()) { + errln("Error: collator::getAvailableLocales() returned NULL"); + return; + } + + // OK. Let's add all of the OLD + // then check for any in the NEW not in OLD + // then check for any in OLD not in NEW. + + // 1. add all of OLD + for(int32_t i=0;isnext(status)) && U_SUCCESS(status)) { + count2++; + + if(expectExtra != NULL && expectStr == *locStr) { + foundExpected = TRUE; + logln(UnicodeString("Found expected registered collator: ","") + expectStr); + } + (void)foundExpected; // Hush unused variable compiler warning. + + if( oldHash.geti(*locStr) == 0 ) { + if(expectExtra != NULL && expectStr==*locStr) { + logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr); } else { - _checklocs("Collator(unregistered)", req, valid, actual); + errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","") + + *locStr); } } + newHash.puti(*locStr, 1, status); } - delete coll; -#endif -#endif + + // 3. check all of OLD again + for(int32_t i=0;i