Home | History | Annotate | Download | only in intltest
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2015, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 
      7 #include "loctest.h"
      8 #include "unicode/decimfmt.h"
      9 #include "unicode/ucurr.h"
     10 #include "unicode/smpdtfmt.h"
     11 #include "unicode/dtfmtsym.h"
     12 #include "unicode/brkiter.h"
     13 #include "unicode/coll.h"
     14 #include "cstring.h"
     15 #include <stdio.h>
     16 #include <string.h>
     17 #include "putilimp.h"
     18 #include "unicode/ustring.h"
     19 #include "hash.h"
     20 
     21 static const char* const rawData[33][8] = {
     22 
     23         // language code
     24         {   "en",   "fr",   "ca",   "el",   "no",   "it",   "xx",   "zh"  },
     25         // script code
     26         {   "",     "",     "",     "",     "",     "",     "",     "Hans" },
     27         // country code
     28         {   "US",   "FR",   "ES",   "GR",   "NO",   "",     "YY",   "CN"  },
     29         // variant code
     30         {   "",     "",     "",     "",     "NY",   "",     "",   ""    },
     31         // full name
     32         {   "en_US",    "fr_FR",    "ca_ES",    "el_GR",    "no_NO_NY", "it",   "xx_YY",   "zh_Hans_CN" },
     33         // ISO-3 language
     34         {   "eng",  "fra",  "cat",  "ell",  "nor",  "ita",  "",   "zho"   },
     35         // ISO-3 country
     36         {   "USA",  "FRA",  "ESP",  "GRC",  "NOR",  "",     "",   "CHN"   },
     37         // LCID
     38         {   "409", "40c", "403", "408", "814", "10",     "0",   "804"  },
     39 
     40         // display langage (English)
     41         {   "English",  "French",   "Catalan", "Greek",    "Norwegian",    "Italian",  "xx",   "Chinese" },
     42         // display script (English)
     43         {   "",     "",     "",     "",     "",   "",     "",   "Simplified Han" },
     44         // display country (English)
     45         {   "United States",    "France",   "Spain",  "Greece",   "Norway",   "",     "YY",   "China" },
     46         // display variant (English)
     47         {   "",     "",     "",     "",     "NY",   "",     "",   ""},
     48         // display name (English)
     49         // Updated no_NO_NY English display name for new pattern-based algorithm
     50         // (part of Euro support).
     51         {   "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China)" },
     52 
     53         // display langage (French)
     54         {   "anglais",  "fran\\u00E7ais",   "catalan", "grec",    "norv\\u00E9gien",    "italien", "xx", "chinois" },
     55         // display script (French)
     56         {   "",     "",     "",     "",     "",     "",     "",   "sinogrammes simplifi\\u00E9s" },
     57         // display country (French)
     58         {   "\\u00C9tats-Unis",    "France",   "Espagne",  "Gr\\u00E8ce",   "Norv\\u00E8ge", "", "YY", "Chine" },
     59         // display variant (French)
     60         {   "",     "",     "",     "",     "NY",     "",     "",   "" },
     61         // display name (French)
     62         //{   "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" },
     63         {   "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine)" },
     64 
     65 
     66         /* display language (Catalan) */
     67         {   "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec",  "noruec", "itali\\u00E0", "", "xin\\u00E8s" },
     68         /* display script (Catalan) */
     69         {   "", "", "",                    "", "", "", "", "han simplificat" },
     70         /* display country (Catalan) */
     71         {   "Estats Units", "Fran\\u00E7a", "Espanya",  "Gr\\u00E8cia", "Noruega", "", "", "Xina" },
     72         /* display variant (Catalan) */
     73         {   "", "", "",                    "", "NY", "", "" },
     74         /* display name (Catalan) */
     75         {   "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina)" },
     76 
     77         // display langage (Greek)[actual values listed below]
     78         {   "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
     79             "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
     80             "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
     81             "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
     82             "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
     83             "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
     84             "",
     85             "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC"
     86         },
     87         // display script (Greek)
     88         {   "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" },
     89         // display country (Greek)[actual values listed below]
     90         {   "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
     91             "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
     92             "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
     93             "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
     94             "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
     95             "",
     96             "",
     97             "\\u039A\\u03AF\\u03BD\\u03B1"
     98         },
     99         // display variant (Greek)
    100         {   "", "", "", "", "NY", "", "" },
    101         // display name (Greek)[actual values listed below]
    102         {   "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
    103             "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
    104             "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
    105             "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
    106             "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
    107             "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
    108             "",
    109             "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)"
    110         },
    111 
    112         // display langage (<root>)
    113         {   "English",  "French",   "Catalan", "Greek",    "Norwegian",    "Italian",  "xx", "" },
    114         // display script (<root>)
    115         {   "",     "",     "",     "",     "",   "",     "", ""},
    116         // display country (<root>)
    117         {   "United States",    "France",   "Spain",  "Greece",   "Norway",   "",     "YY", "" },
    118         // display variant (<root>)
    119         {   "",     "",     "",     "",     "Nynorsk",   "",     "", ""},
    120         // display name (<root>)
    121         //{   "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
    122         {   "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,NY)", "Italian", "xx (YY)", "" }
    123 };
    124 
    125 
    126 /*
    127  Usage:
    128     test_assert(    Test (should be TRUE)  )
    129 
    130    Example:
    131        test_assert(i==3);
    132 
    133    the macro is ugly but makes the tests pretty.
    134 */
    135 
    136 #define test_assert(test) \
    137     { \
    138         if(!(test)) \
    139             errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \
    140         else \
    141             logln("PASS: asserted " #test); \
    142     }
    143 
    144 /*
    145  Usage:
    146     test_assert_print(    Test (should be TRUE),  printable  )
    147 
    148    Example:
    149        test_assert(i==3, toString(i));
    150 
    151    the macro is ugly but makes the tests pretty.
    152 */
    153 
    154 #define test_assert_print(test,print) \
    155     { \
    156         if(!(test)) \
    157             errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \
    158         else \
    159             logln("PASS: asserted " #test "-> " + UnicodeString(print)); \
    160     }
    161 
    162 
    163 #define test_dumpLocale(l) { logln(#l " = " + UnicodeString(l.getName(), "")); }
    164 
    165 LocaleTest::LocaleTest()
    166 : dataTable(NULL)
    167 {
    168     setUpDataTable();
    169 }
    170 
    171 LocaleTest::~LocaleTest()
    172 {
    173     if (dataTable != 0) {
    174         for (int32_t i = 0; i < 33; i++) {
    175             delete []dataTable[i];
    176         }
    177         delete []dataTable;
    178         dataTable = 0;
    179     }
    180 }
    181 
    182 void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
    183 {
    184     TESTCASE_AUTO_BEGIN;
    185     TESTCASE_AUTO(TestBug11421);         // Must run early in list to trigger failure.
    186     TESTCASE_AUTO(TestBasicGetters);
    187     TESTCASE_AUTO(TestSimpleResourceInfo);
    188     TESTCASE_AUTO(TestDisplayNames);
    189     TESTCASE_AUTO(TestSimpleObjectStuff);
    190     TESTCASE_AUTO(TestPOSIXParsing);
    191     TESTCASE_AUTO(TestGetAvailableLocales);
    192     TESTCASE_AUTO(TestDataDirectory);
    193     TESTCASE_AUTO(TestISO3Fallback);
    194     TESTCASE_AUTO(TestGetLangsAndCountries);
    195     TESTCASE_AUTO(TestSimpleDisplayNames);
    196     TESTCASE_AUTO(TestUninstalledISO3Names);
    197     TESTCASE_AUTO(TestAtypicalLocales);
    198 #if !UCONFIG_NO_FORMATTING
    199     TESTCASE_AUTO(TestThaiCurrencyFormat);
    200     TESTCASE_AUTO(TestEuroSupport);
    201 #endif
    202     TESTCASE_AUTO(TestToString);
    203 #if !UCONFIG_NO_FORMATTING
    204     TESTCASE_AUTO(Test4139940);
    205     TESTCASE_AUTO(Test4143951);
    206 #endif
    207     TESTCASE_AUTO(Test4147315);
    208     TESTCASE_AUTO(Test4147317);
    209     TESTCASE_AUTO(Test4147552);
    210     TESTCASE_AUTO(TestVariantParsing);
    211 #if !UCONFIG_NO_FORMATTING
    212     TESTCASE_AUTO(Test4105828);
    213 #endif
    214     TESTCASE_AUTO(TestSetIsBogus);
    215     TESTCASE_AUTO(TestParallelAPIValues);
    216     TESTCASE_AUTO(TestKeywordVariants);
    217     TESTCASE_AUTO(TestKeywordVariantParsing);
    218     TESTCASE_AUTO(TestSetKeywordValue);
    219     TESTCASE_AUTO(TestGetBaseName);
    220 #if !UCONFIG_NO_FILE_IO
    221     TESTCASE_AUTO(TestGetLocale);
    222 #endif
    223     TESTCASE_AUTO(TestVariantWithOutCountry);
    224     TESTCASE_AUTO(TestCanonicalization);
    225     TESTCASE_AUTO(TestCurrencyByDate);
    226     TESTCASE_AUTO(TestGetVariantWithKeywords);
    227     TESTCASE_AUTO(TestIsRightToLeft);
    228     TESTCASE_AUTO_END;
    229 }
    230 
    231 void LocaleTest::TestBasicGetters() {
    232     UnicodeString   temp;
    233 
    234     int32_t i;
    235     for (i = 0; i <= MAX_LOCALES; i++) {
    236         Locale testLocale("");
    237         if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
    238             testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
    239         }
    240         else {
    241             testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
    242         }
    243         logln("Testing " + (UnicodeString)testLocale.getName() + "...");
    244 
    245         if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
    246             errln("  Language code mismatch: " + temp + " versus "
    247                         + dataTable[LANG][i]);
    248         if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
    249             errln("  Script code mismatch: " + temp + " versus "
    250                         + dataTable[SCRIPT][i]);
    251         if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
    252             errln("  Country code mismatch: " + temp + " versus "
    253                         + dataTable[CTRY][i]);
    254         if ( (temp=testLocale.getVariant()) != (dataTable[VAR][i]))
    255             errln("  Variant code mismatch: " + temp + " versus "
    256                         + dataTable[VAR][i]);
    257         if ( (temp=testLocale.getName()) != (dataTable[NAME][i]))
    258             errln("  Locale name mismatch: " + temp + " versus "
    259                         + dataTable[NAME][i]);
    260     }
    261 
    262     logln("Same thing without variant codes...");
    263     for (i = 0; i <= MAX_LOCALES; i++) {
    264         Locale testLocale("");
    265         if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
    266             testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i]);
    267         }
    268         else {
    269             testLocale = Locale(rawData[LANG][i], rawData[CTRY][i]);
    270         }
    271         logln("Testing " + (temp=testLocale.getName()) + "...");
    272 
    273         if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
    274             errln("Language code mismatch: " + temp + " versus "
    275                         + dataTable[LANG][i]);
    276         if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
    277             errln("Script code mismatch: " + temp + " versus "
    278                         + dataTable[SCRIPT][i]);
    279         if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
    280             errln("Country code mismatch: " + temp + " versus "
    281                         + dataTable[CTRY][i]);
    282         if (testLocale.getVariant()[0] != 0)
    283             errln("Variant code mismatch: something versus \"\"");
    284     }
    285 
    286     logln("Testing long language names and getters");
    287     Locale  test8 = Locale::createFromName("x-klingon-latn-zx.utf32be@special");
    288 
    289     temp = test8.getLanguage();
    290     if (temp != UnicodeString("x-klingon") )
    291         errln("Language code mismatch: " + temp + "  versus \"x-klingon\"");
    292 
    293     temp = test8.getScript();
    294     if (temp != UnicodeString("Latn") )
    295         errln("Script code mismatch: " + temp + "  versus \"Latn\"");
    296 
    297     temp = test8.getCountry();
    298     if (temp != UnicodeString("ZX") )
    299         errln("Country code mismatch: " + temp + "  versus \"ZX\"");
    300 
    301     temp = test8.getVariant();
    302     //if (temp != UnicodeString("SPECIAL") )
    303     //    errln("Variant code mismatch: " + temp + "  versus \"SPECIAL\"");
    304     // As of 3.0, the "@special" will *not* be parsed by uloc_getName()
    305     if (temp != UnicodeString("") )
    306         errln("Variant code mismatch: " + temp + "  versus \"\"");
    307 
    308     if (Locale::getDefault() != Locale::createFromName(NULL))
    309         errln("Locale::getDefault() == Locale::createFromName(NULL)");
    310 
    311     /*----------*/
    312     // NOTE: There used to be a special test for locale names that had language or
    313     // country codes that were longer than two letters.  The new version of Locale
    314     // doesn't support anything that isn't an officially recognized language or
    315     // country code, so we no longer support this feature.
    316 
    317     Locale bogusLang("THISISABOGUSLANGUAGE"); // Jitterbug 2864: language code too long
    318     if(!bogusLang.isBogus()) {
    319         errln("Locale(\"THISISABOGUSLANGUAGE\").isBogus()==FALSE");
    320     }
    321 
    322     bogusLang=Locale("eo");
    323     if( bogusLang.isBogus() ||
    324         strcmp(bogusLang.getLanguage(), "eo")!=0 ||
    325         *bogusLang.getCountry()!=0 ||
    326         *bogusLang.getVariant()!=0 ||
    327         strcmp(bogusLang.getName(), "eo")!=0
    328     ) {
    329         errln("assignment to bogus Locale does not unbogus it or sets bad data");
    330     }
    331 
    332     Locale a("eo_DE@currency=DEM");
    333     Locale *pb=a.clone();
    334     if(pb==&a || *pb!=a) {
    335         errln("Locale.clone() failed");
    336     }
    337     delete pb;
    338 }
    339 
    340 void LocaleTest::TestParallelAPIValues() {
    341     logln("Test synchronization between C and C++ API");
    342     if (strcmp(Locale::getChinese().getName(), ULOC_CHINESE) != 0) {
    343         errln("Differences for ULOC_CHINESE Locale");
    344     }
    345     if (strcmp(Locale::getEnglish().getName(), ULOC_ENGLISH) != 0) {
    346         errln("Differences for ULOC_ENGLISH Locale");
    347     }
    348     if (strcmp(Locale::getFrench().getName(), ULOC_FRENCH) != 0) {
    349         errln("Differences for ULOC_FRENCH Locale");
    350     }
    351     if (strcmp(Locale::getGerman().getName(), ULOC_GERMAN) != 0) {
    352         errln("Differences for ULOC_GERMAN Locale");
    353     }
    354     if (strcmp(Locale::getItalian().getName(), ULOC_ITALIAN) != 0) {
    355         errln("Differences for ULOC_ITALIAN Locale");
    356     }
    357     if (strcmp(Locale::getJapanese().getName(), ULOC_JAPANESE) != 0) {
    358         errln("Differences for ULOC_JAPANESE Locale");
    359     }
    360     if (strcmp(Locale::getKorean().getName(), ULOC_KOREAN) != 0) {
    361         errln("Differences for ULOC_KOREAN Locale");
    362     }
    363     if (strcmp(Locale::getSimplifiedChinese().getName(), ULOC_SIMPLIFIED_CHINESE) != 0) {
    364         errln("Differences for ULOC_SIMPLIFIED_CHINESE Locale");
    365     }
    366     if (strcmp(Locale::getTraditionalChinese().getName(), ULOC_TRADITIONAL_CHINESE) != 0) {
    367         errln("Differences for ULOC_TRADITIONAL_CHINESE Locale");
    368     }
    369 
    370 
    371     if (strcmp(Locale::getCanada().getName(), ULOC_CANADA) != 0) {
    372         errln("Differences for ULOC_CANADA Locale");
    373     }
    374     if (strcmp(Locale::getCanadaFrench().getName(), ULOC_CANADA_FRENCH) != 0) {
    375         errln("Differences for ULOC_CANADA_FRENCH Locale");
    376     }
    377     if (strcmp(Locale::getChina().getName(), ULOC_CHINA) != 0) {
    378         errln("Differences for ULOC_CHINA Locale");
    379     }
    380     if (strcmp(Locale::getPRC().getName(), ULOC_PRC) != 0) {
    381         errln("Differences for ULOC_PRC Locale");
    382     }
    383     if (strcmp(Locale::getFrance().getName(), ULOC_FRANCE) != 0) {
    384         errln("Differences for ULOC_FRANCE Locale");
    385     }
    386     if (strcmp(Locale::getGermany().getName(), ULOC_GERMANY) != 0) {
    387         errln("Differences for ULOC_GERMANY Locale");
    388     }
    389     if (strcmp(Locale::getItaly().getName(), ULOC_ITALY) != 0) {
    390         errln("Differences for ULOC_ITALY Locale");
    391     }
    392     if (strcmp(Locale::getJapan().getName(), ULOC_JAPAN) != 0) {
    393         errln("Differences for ULOC_JAPAN Locale");
    394     }
    395     if (strcmp(Locale::getKorea().getName(), ULOC_KOREA) != 0) {
    396         errln("Differences for ULOC_KOREA Locale");
    397     }
    398     if (strcmp(Locale::getTaiwan().getName(), ULOC_TAIWAN) != 0) {
    399         errln("Differences for ULOC_TAIWAN Locale");
    400     }
    401     if (strcmp(Locale::getUK().getName(), ULOC_UK) != 0) {
    402         errln("Differences for ULOC_UK Locale");
    403     }
    404     if (strcmp(Locale::getUS().getName(), ULOC_US) != 0) {
    405         errln("Differences for ULOC_US Locale");
    406     }
    407 }
    408 
    409 
    410 void LocaleTest::TestSimpleResourceInfo() {
    411     UnicodeString   temp;
    412     char            temp2[20];
    413     UErrorCode err = U_ZERO_ERROR;
    414     int32_t i = 0;
    415 
    416     for (i = 0; i <= MAX_LOCALES; i++) {
    417         Locale testLocale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
    418         logln("Testing " + (temp=testLocale.getName()) + "...");
    419 
    420         if ( (temp=testLocale.getISO3Language()) != (dataTable[LANG3][i]))
    421             errln("  ISO-3 language code mismatch: " + temp
    422                 + " versus " + dataTable[LANG3][i]);
    423         if ( (temp=testLocale.getISO3Country()) != (dataTable[CTRY3][i]))
    424             errln("  ISO-3 country code mismatch: " + temp
    425                 + " versus " + dataTable[CTRY3][i]);
    426 
    427         sprintf(temp2, "%x", (int)testLocale.getLCID());
    428         if (UnicodeString(temp2) != dataTable[LCID][i])
    429             errln((UnicodeString)"  LCID mismatch: " + temp2 + " versus "
    430                 + dataTable[LCID][i]);
    431 
    432         if(U_FAILURE(err))
    433         {
    434             errln((UnicodeString)"Some error on number " + i + u_errorName(err));
    435         }
    436         err = U_ZERO_ERROR;
    437     }
    438 
    439     Locale locale("en");
    440     if(strcmp(locale.getName(), "en") != 0||
    441         strcmp(locale.getLanguage(), "en") != 0) {
    442         errln("construction of Locale(en) failed\n");
    443     }
    444     /*-----*/
    445 
    446 }
    447 
    448 /*
    449  * Jitterbug 2439 -- markus 20030425
    450  *
    451  * The lookup of display names must not fall back through the default
    452  * locale because that yields useless results.
    453  */
    454 void
    455 LocaleTest::TestDisplayNames()
    456 {
    457     Locale  english("en", "US");
    458     Locale  french("fr", "FR");
    459     Locale  croatian("ca", "ES");
    460     Locale  greek("el", "GR");
    461 
    462     logln("  In locale = en_US...");
    463     doTestDisplayNames(english, DLANG_EN);
    464     logln("  In locale = fr_FR...");
    465     doTestDisplayNames(french, DLANG_FR);
    466     logln("  In locale = ca_ES...");
    467     doTestDisplayNames(croatian, DLANG_CA);
    468     logln("  In locale = el_GR...");
    469     doTestDisplayNames(greek, DLANG_EL);
    470 
    471     UnicodeString s;
    472     UErrorCode status = U_ZERO_ERROR;
    473 
    474 #if !UCONFIG_NO_FORMATTING
    475     DecimalFormatSymbols symb(status);
    476     /* Check to see if ICU supports this locale */
    477     if (symb.getLocale(ULOC_VALID_LOCALE, status) != Locale("root")) {
    478         /* test that the default locale has a display name for its own language */
    479         /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */
    480         if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) {
    481             Locale().getDisplayLanguage(Locale(), s);
    482             if(s.length()<=3 && s.charAt(0)<=0x7f) {
    483                 /* check <=3 to reject getting the language code as a display name */
    484                 dataerrln("unable to get a display string for the language of the default locale: " + s);
    485             }
    486 
    487             /*
    488              * API coverage improvements: call
    489              * Locale::getDisplayLanguage(UnicodeString &) and
    490              * Locale::getDisplayCountry(UnicodeString &)
    491              */
    492             s.remove();
    493             Locale().getDisplayLanguage(s);
    494             if(s.length()<=3 && s.charAt(0)<=0x7f) {
    495                 dataerrln("unable to get a display string for the language of the default locale [2]: " + s);
    496             }
    497         }
    498     }
    499     else {
    500         logln("Default locale %s is unsupported by ICU\n", Locale().getName());
    501     }
    502     s.remove();
    503 #endif
    504 
    505     french.getDisplayCountry(s);
    506     if(s.isEmpty()) {
    507         errln("unable to get any default-locale display string for the country of fr_FR\n");
    508     }
    509     s.remove();
    510     Locale("zh", "Hant").getDisplayScript(s);
    511     if(s.isEmpty()) {
    512         errln("unable to get any default-locale display string for the country of zh_Hant\n");
    513     }
    514 }
    515 
    516 void LocaleTest::TestSimpleObjectStuff() {
    517     Locale  test1("aa", "AA");
    518     Locale  test2("aa", "AA");
    519     Locale  test3(test1);
    520     Locale  test4("zz", "ZZ");
    521     Locale  test5("aa", "AA", "");
    522     Locale  test6("aa", "AA", "ANTARES");
    523     Locale  test7("aa", "AA", "JUPITER");
    524     Locale  test8 = Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that
    525 
    526     // now list them all for debugging usage.
    527     test_dumpLocale(test1);
    528     test_dumpLocale(test2);
    529     test_dumpLocale(test3);
    530     test_dumpLocale(test4);
    531     test_dumpLocale(test5);
    532     test_dumpLocale(test6);
    533     test_dumpLocale(test7);
    534     test_dumpLocale(test8);
    535 
    536     // Make sure things compare to themselves!
    537     test_assert(test1 == test1);
    538     test_assert(test2 == test2);
    539     test_assert(test3 == test3);
    540     test_assert(test4 == test4);
    541     test_assert(test5 == test5);
    542     test_assert(test6 == test6);
    543     test_assert(test7 == test7);
    544     test_assert(test8 == test8);
    545 
    546     // make sure things are not equal to themselves.
    547     test_assert(!(test1 != test1));
    548     test_assert(!(test2 != test2));
    549     test_assert(!(test3 != test3));
    550     test_assert(!(test4 != test4));
    551     test_assert(!(test5 != test5));
    552     test_assert(!(test6 != test6));
    553     test_assert(!(test7 != test7));
    554     test_assert(!(test8 != test8));
    555 
    556     // make sure things that are equal to each other don't show up as unequal.
    557     test_assert(!(test1 != test2));
    558     test_assert(!(test2 != test1));
    559     test_assert(!(test1 != test3));
    560     test_assert(!(test2 != test3));
    561     test_assert(test5 == test1);
    562     test_assert(test6 != test2);
    563     test_assert(test6 != test5);
    564 
    565     test_assert(test6 != test7);
    566 
    567     // test for things that shouldn't compare equal.
    568     test_assert(!(test1 == test4));
    569     test_assert(!(test2 == test4));
    570     test_assert(!(test3 == test4));
    571 
    572     test_assert(test7 == test8);
    573 
    574     // test for hash codes to be the same.
    575     int32_t hash1 = test1.hashCode();
    576     int32_t hash2 = test2.hashCode();
    577     int32_t hash3 = test3.hashCode();
    578 
    579     test_assert(hash1 == hash2);
    580     test_assert(hash1 == hash3);
    581     test_assert(hash2 == hash3);
    582 
    583     // test that the assignment operator works.
    584     test4 = test1;
    585     logln("test4=test1;");
    586     test_dumpLocale(test4);
    587     test_assert(test4 == test4);
    588 
    589     test_assert(!(test1 != test4));
    590     test_assert(!(test2 != test4));
    591     test_assert(!(test3 != test4));
    592     test_assert(test1 == test4);
    593     test_assert(test4 == test1);
    594 
    595     // test assignments with a variant
    596     logln("test7 = test6");
    597     test7 = test6;
    598     test_dumpLocale(test7);
    599     test_assert(test7 == test7);
    600     test_assert(test7 == test6);
    601     test_assert(test7 != test5);
    602 
    603     logln("test6 = test1");
    604     test6=test1;
    605     test_dumpLocale(test6);
    606     test_assert(test6 != test7);
    607     test_assert(test6 == test1);
    608     test_assert(test6 == test6);
    609 }
    610 
    611 // A class which exposes constructors that are implemented in terms of the POSIX parsing code.
    612 class POSIXLocale : public Locale
    613 {
    614 public:
    615     POSIXLocale(const UnicodeString& l)
    616         :Locale()
    617     {
    618       char *ch;
    619       ch = new char[l.length() + 1];
    620       ch[l.extract(0, 0x7fffffff, ch, "")] = 0;
    621       setFromPOSIXID(ch);
    622       delete [] ch;
    623     }
    624     POSIXLocale(const char *l)
    625         :Locale()
    626     {
    627         setFromPOSIXID(l);
    628     }
    629 };
    630 
    631 void LocaleTest::TestPOSIXParsing()
    632 {
    633     POSIXLocale  test1("ab_AB");
    634     POSIXLocale  test2(UnicodeString("ab_AB"));
    635     Locale  test3("ab","AB");
    636 
    637     POSIXLocale test4("ab_AB_Antares");
    638     POSIXLocale test5(UnicodeString("ab_AB_Antares"));
    639     Locale  test6("ab", "AB", "Antares");
    640 
    641     test_dumpLocale(test1);
    642     test_dumpLocale(test2);
    643     test_dumpLocale(test3);
    644     test_dumpLocale(test4);
    645     test_dumpLocale(test5);
    646     test_dumpLocale(test6);
    647 
    648     test_assert(test1 == test1);
    649 
    650     test_assert(test1 == test2);
    651     test_assert(test2 == test3);
    652     test_assert(test3 == test1);
    653 
    654     test_assert(test4 == test5);
    655     test_assert(test5 == test6);
    656     test_assert(test6 == test4);
    657 
    658     test_assert(test1 != test4);
    659     test_assert(test5 != test3);
    660     test_assert(test5 != test2);
    661 
    662     int32_t hash1 = test1.hashCode();
    663     int32_t hash2 = test2.hashCode();
    664     int32_t hash3 = test3.hashCode();
    665 
    666     test_assert(hash1 == hash2);
    667     test_assert(hash2 == hash3);
    668     test_assert(hash3 == hash1);
    669 }
    670 
    671 void LocaleTest::TestGetAvailableLocales()
    672 {
    673     int32_t locCount = 0;
    674     const Locale* locList = Locale::getAvailableLocales(locCount);
    675 
    676     if (locCount == 0)
    677         dataerrln("getAvailableLocales() returned an empty list!");
    678     else {
    679         logln(UnicodeString("Number of locales returned = ") + locCount);
    680         UnicodeString temp;
    681         for(int32_t i = 0; i < locCount; ++i)
    682             logln(locList[i].getName());
    683     }
    684     // I have no idea how to test this function...
    685 }
    686 
    687 // This test isn't applicable anymore - getISO3Language is
    688 // independent of the data directory
    689 void LocaleTest::TestDataDirectory()
    690 {
    691 /*
    692     char            oldDirectory[80];
    693     const char*     temp;
    694     UErrorCode       err = U_ZERO_ERROR;
    695     UnicodeString   testValue;
    696 
    697     temp = Locale::getDataDirectory();
    698     strcpy(oldDirectory, temp);
    699     logln(UnicodeString("oldDirectory = ") + oldDirectory);
    700 
    701     Locale  test(Locale::US);
    702     test.getISO3Language(testValue);
    703     logln("first fetch of language retrieved " + testValue);
    704     if (testValue != "eng")
    705         errln("Initial check of ISO3 language failed: expected \"eng\", got \"" + testValue + "\"");
    706 
    707     {
    708         char *path;
    709         path=IntlTest::getTestDirectory();
    710         Locale::setDataDirectory( path );
    711     }
    712 
    713     test.getISO3Language(testValue);
    714     logln("second fetch of language retrieved " + testValue);
    715     if (testValue != "xxx")
    716         errln("setDataDirectory() failed: expected \"xxx\", got \"" + testValue + "\"");
    717 
    718     Locale::setDataDirectory(oldDirectory);
    719     test.getISO3Language(testValue);
    720     logln("third fetch of language retrieved " + testValue);
    721     if (testValue != "eng")
    722         errln("get/setDataDirectory() failed: expected \"eng\", got \"" + testValue + "\"");
    723 */
    724 }
    725 
    726 //===========================================================
    727 
    728 void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) {
    729     UnicodeString   temp;
    730 
    731     for (int32_t i = 0; i <= MAX_LOCALES; i++) {
    732         Locale testLocale("");
    733         if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
    734             testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
    735         }
    736         else {
    737             testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
    738         }
    739         logln("  Testing " + (temp=testLocale.getName()) + "...");
    740 
    741         UnicodeString  testLang;
    742         UnicodeString  testScript;
    743         UnicodeString  testCtry;
    744         UnicodeString  testVar;
    745         UnicodeString  testName;
    746 
    747         testLocale.getDisplayLanguage(displayLocale, testLang);
    748         testLocale.getDisplayScript(displayLocale, testScript);
    749         testLocale.getDisplayCountry(displayLocale, testCtry);
    750         testLocale.getDisplayVariant(displayLocale, testVar);
    751         testLocale.getDisplayName(displayLocale, testName);
    752 
    753         UnicodeString  expectedLang;
    754         UnicodeString  expectedScript;
    755         UnicodeString  expectedCtry;
    756         UnicodeString  expectedVar;
    757         UnicodeString  expectedName;
    758 
    759         expectedLang = dataTable[compareIndex][i];
    760         if (expectedLang.length() == 0)
    761             expectedLang = dataTable[DLANG_EN][i];
    762 
    763         expectedScript = dataTable[compareIndex + 1][i];
    764         if (expectedScript.length() == 0)
    765             expectedScript = dataTable[DSCRIPT_EN][i];
    766 
    767         expectedCtry = dataTable[compareIndex + 2][i];
    768         if (expectedCtry.length() == 0)
    769             expectedCtry = dataTable[DCTRY_EN][i];
    770 
    771         expectedVar = dataTable[compareIndex + 3][i];
    772         if (expectedVar.length() == 0)
    773             expectedVar = dataTable[DVAR_EN][i];
    774 
    775         expectedName = dataTable[compareIndex + 4][i];
    776         if (expectedName.length() == 0)
    777             expectedName = dataTable[DNAME_EN][i];
    778 
    779         if (testLang != expectedLang)
    780             dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang);
    781         if (testScript != expectedScript)
    782             dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript);
    783         if (testCtry != expectedCtry)
    784             dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry);
    785         if (testVar != expectedVar)
    786             dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar);
    787         if (testName != expectedName)
    788             dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName);
    789     }
    790 }
    791 
    792 //---------------------------------------------------
    793 // table of valid data
    794 //---------------------------------------------------
    795 
    796 
    797 
    798 void LocaleTest::setUpDataTable()
    799 {
    800     if (dataTable == 0) {
    801         dataTable = new UnicodeString*[33];
    802 
    803         for (int32_t i = 0; i < 33; i++) {
    804             dataTable[i] = new UnicodeString[8];
    805             for (int32_t j = 0; j < 8; j++) {
    806                 dataTable[i][j] = CharsToUnicodeString(rawData[i][j]);
    807             }
    808         }
    809     }
    810 }
    811 
    812 // ====================
    813 
    814 
    815 /**
    816  * @bug 4011756 4011380
    817  */
    818 void
    819 LocaleTest::TestISO3Fallback()
    820 {
    821     Locale test("xx", "YY");
    822 
    823     const char * result;
    824 
    825     result = test.getISO3Language();
    826 
    827     // Conform to C API usage
    828 
    829     if (!result || (result[0] != 0))
    830         errln("getISO3Language() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
    831 
    832     result = test.getISO3Country();
    833 
    834     if (!result || (result[0] != 0))
    835         errln("getISO3Country() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
    836 }
    837 
    838 /**
    839  * @bug 4106155 4118587
    840  */
    841 void
    842 LocaleTest::TestGetLangsAndCountries()
    843 {
    844     // It didn't seem right to just do an exhaustive test of everything here, so I check
    845     // for the following things:
    846     // 1) Does each list have the right total number of entries?
    847     // 2) Does each list contain certain language and country codes we think are important
    848     //     (the G7 countries, plus a couple others)?
    849     // 3) Does each list have every entry formatted correctly? (i.e., two characters,
    850     //     all lower case for the language codes, all upper case for the country codes)
    851     // 4) Is each list in sorted order?
    852     int32_t testCount = 0;
    853     const char * const * test = Locale::getISOLanguages();
    854     const char spotCheck1[ ][4] = { "en", "es", "fr", "de", "it",
    855                                     "ja", "ko", "zh", "th", "he",
    856                                     "id", "iu", "ug", "yi", "za" };
    857 
    858     int32_t i;
    859 
    860     for(testCount = 0;test[testCount];testCount++)
    861       ;
    862 
    863     /* TODO: Change this test to be more like the cloctst version? */
    864     if (testCount != 560)
    865         errln("Expected getISOLanguages() to return 560 languages; it returned %d", testCount);
    866     else {
    867         for (i = 0; i < 15; i++) {
    868             int32_t j;
    869             for (j = 0; j < testCount; j++)
    870               if (uprv_strcmp(test[j],spotCheck1[i])== 0)
    871                     break;
    872             if (j == testCount || (uprv_strcmp(test[j],spotCheck1[i])!=0))
    873                 errln("Couldn't find " + (UnicodeString)spotCheck1[i] + " in language list.");
    874         }
    875     }
    876     for (i = 0; i < testCount; i++) {
    877         UnicodeString testee(test[i],"");
    878         UnicodeString lc(test[i],"");
    879         if (testee != lc.toLower())
    880             errln(lc + " is not all lower case.");
    881         if ( (testee.length() != 2) && (testee.length() != 3))
    882             errln(testee + " is not two or three characters long.");
    883         if (i > 0 && testee.compare(test[i - 1]) <= 0)
    884             errln(testee + " appears in an out-of-order position in the list.");
    885     }
    886 
    887     test = Locale::getISOCountries();
    888     UnicodeString spotCheck2 [] = { "US", "CA", "GB", "FR", "DE",
    889                                     "IT", "JP", "KR", "CN", "TW",
    890                                     "TH" };
    891     int32_t spot2Len = 11;
    892     for(testCount=0;test[testCount];testCount++)
    893       ;
    894 
    895     if (testCount != 249){
    896         errln("Expected getISOCountries to return 249 countries; it returned %d", testCount);
    897     }else {
    898         for (i = 0; i < spot2Len; i++) {
    899             int32_t j;
    900             for (j = 0; j < testCount; j++)
    901               {
    902                 UnicodeString testee(test[j],"");
    903 
    904                 if (testee == spotCheck2[i])
    905                     break;
    906               }
    907                 UnicodeString testee(test[j],"");
    908             if (j == testCount || testee != spotCheck2[i])
    909                 errln("Couldn't find " + spotCheck2[i] + " in country list.");
    910         }
    911     }
    912     for (i = 0; i < testCount; i++) {
    913         UnicodeString testee(test[i],"");
    914         UnicodeString uc(test[i],"");
    915         if (testee != uc.toUpper())
    916             errln(testee + " is not all upper case.");
    917         if (testee.length() != 2)
    918             errln(testee + " is not two characters long.");
    919         if (i > 0 && testee.compare(test[i - 1]) <= 0)
    920             errln(testee + " appears in an out-of-order position in the list.");
    921     }
    922 
    923     // This getAvailableLocales and getISO3Language
    924     {
    925         int32_t numOfLocales;
    926         Locale  enLoc ("en");
    927         const Locale *pLocales = Locale::getAvailableLocales(numOfLocales);
    928 
    929         for (int i = 0; i < numOfLocales; i++) {
    930             const Locale    &loc(pLocales[i]);
    931             UnicodeString   name;
    932             char        szName[200];
    933 
    934             loc.getDisplayName (enLoc, name);
    935             name.extract (0, 200, szName, sizeof(szName));
    936 
    937             if (strlen(loc.getISO3Language()) == 0) {
    938                 errln("getISO3Language() returned an empty string for: " + name);
    939             }
    940         }
    941     }
    942 }
    943 
    944 /**
    945  * @bug 4118587
    946  */
    947 void
    948 LocaleTest::TestSimpleDisplayNames()
    949 {
    950     // This test is different from TestDisplayNames because TestDisplayNames checks
    951     // fallback behavior, combination of language and country names to form locale
    952     // names, and other stuff like that.  This test just checks specific language
    953     // and country codes to make sure we have the correct names for them.
    954     char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" };
    955     UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
    956                                "Zhuang" };
    957 
    958     for (int32_t i = 0; i < 6; i++) {
    959         UnicodeString test;
    960         Locale l(languageCodes[i], "", "");
    961         l.getDisplayLanguage(Locale::getUS(), test);
    962         if (test != languageNames[i])
    963             dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" +
    964                   languageNames[i] + "\", got \"" + test + "\".");
    965     }
    966 }
    967 
    968 /**
    969  * @bug 4118595
    970  */
    971 void
    972 LocaleTest::TestUninstalledISO3Names()
    973 {
    974     // This test checks to make sure getISO3Language and getISO3Country work right
    975     // even for locales that are not installed.
    976     const char iso2Languages [][4] = {     "am", "ba", "fy", "mr", "rn",
    977                                         "ss", "tw", "zu" };
    978     const char iso3Languages [][5] = {     "amh", "bak", "fry", "mar", "run",
    979                                         "ssw", "twi", "zul" };
    980 
    981     int32_t i;
    982 
    983     for (i = 0; i < 8; i++) {
    984       UErrorCode err = U_ZERO_ERROR;
    985 
    986       UnicodeString test;
    987         Locale l(iso2Languages[i], "", "");
    988         test = l.getISO3Language();
    989         if((test != iso3Languages[i]) || U_FAILURE(err))
    990             errln("Got wrong ISO3 code for " + UnicodeString(iso2Languages[i]) + ": Expected \"" +
    991                     iso3Languages[i] + "\", got \"" + test + "\"." + UnicodeString(u_errorName(err)));
    992     }
    993 
    994     char iso2Countries [][4] = {     "AF", "BW", "KZ", "MO", "MN",
    995                                         "SB", "TC", "ZW" };
    996     char iso3Countries [][4] = {     "AFG", "BWA", "KAZ", "MAC", "MNG",
    997                                         "SLB", "TCA", "ZWE" };
    998 
    999     for (i = 0; i < 8; i++) {
   1000       UErrorCode err = U_ZERO_ERROR;
   1001         Locale l("", iso2Countries[i], "");
   1002         UnicodeString test(l.getISO3Country(), "");
   1003         if (test != iso3Countries[i])
   1004             errln("Got wrong ISO3 code for " + UnicodeString(iso2Countries[i]) + ": Expected \"" +
   1005                     UnicodeString(iso3Countries[i]) + "\", got \"" + test + "\"." + u_errorName(err));
   1006     }
   1007 }
   1008 
   1009 /**
   1010  * @bug 4092475
   1011  * I could not reproduce this bug.  I'm pretty convinced it was fixed with the
   1012  * big locale-data reorg of 10/28/97.  The lookup logic for language and country
   1013  * display names was also changed at that time in that check-in.    --rtg 3/20/98
   1014  */
   1015 void
   1016 LocaleTest::TestAtypicalLocales()
   1017 {
   1018     Locale localesToTest [] = { Locale("de", "CA"),
   1019                                   Locale("ja", "ZA"),
   1020                                    Locale("ru", "MX"),
   1021                                    Locale("en", "FR"),
   1022                                    Locale("es", "DE"),
   1023                                    Locale("", "HR"),
   1024                                    Locale("", "SE"),
   1025                                    Locale("", "DO"),
   1026                                    Locale("", "BE") };
   1027 
   1028     UnicodeString englishDisplayNames [] = { "German (Canada)",
   1029                                      "Japanese (South Africa)",
   1030                                      "Russian (Mexico)",
   1031                                      "English (France)",
   1032                                      "Spanish (Germany)",
   1033                                      "Croatia",
   1034                                      "Sweden",
   1035                                      "Dominican Republic",
   1036                                      "Belgium" };
   1037     UnicodeString frenchDisplayNames []= { "allemand (Canada)",
   1038                                     "japonais (Afrique du Sud)",
   1039                                     "russe (Mexique)",
   1040                                      "anglais (France)",
   1041                                      "espagnol (Allemagne)",
   1042                                     "Croatie",
   1043                                     CharsToUnicodeString("Su\\u00E8de"),
   1044                                     CharsToUnicodeString("R\\u00E9publique dominicaine"),
   1045                                     "Belgique" };
   1046     UnicodeString spanishDisplayNames [] = {
   1047                                      CharsToUnicodeString("alem\\u00E1n (Canad\\u00E1)"),
   1048                                      CharsToUnicodeString("japon\\u00E9s (Sud\\u00E1frica)"),
   1049                                      CharsToUnicodeString("ruso (M\\u00E9xico)"),
   1050                                      CharsToUnicodeString("ingl\\u00E9s (Francia)"),
   1051                                      CharsToUnicodeString("espa\\u00F1ol (Alemania)"),
   1052                                      "Croacia",
   1053                                      "Suecia",
   1054                                      CharsToUnicodeString("Rep\\u00FAblica Dominicana"),
   1055                                      CharsToUnicodeString("B\\u00E9lgica") };
   1056     // De-Anglicizing root required the change from
   1057     // English display names to ISO Codes - ram 2003/09/26
   1058     UnicodeString invDisplayNames [] = { "German (Canada)",
   1059                                      "Japanese (South Africa)",
   1060                                      "Russian (Mexico)",
   1061                                      "English (France)",
   1062                                      "Spanish (Germany)",
   1063                                      "Croatia",
   1064                                      "Sweden",
   1065                                      "Dominican Republic",
   1066                                      "Belgium" };
   1067 
   1068     int32_t i;
   1069     UErrorCode status = U_ZERO_ERROR;
   1070     Locale saveLocale;
   1071     Locale::setDefault(Locale::getUS(), status);
   1072     for (i = 0; i < 9; ++i) {
   1073         UnicodeString name;
   1074         localesToTest[i].getDisplayName(Locale::getUS(), name);
   1075         logln(name);
   1076         if (name != englishDisplayNames[i])
   1077         {
   1078             dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i]
   1079                         + "\", got \"" + name + "\"");
   1080             logln("Locale name was-> " + (name=localesToTest[i].getName()));
   1081         }
   1082     }
   1083 
   1084     for (i = 0; i < 9; i++) {
   1085         UnicodeString name;
   1086         localesToTest[i].getDisplayName(Locale("es", "ES"), name);
   1087         logln(name);
   1088         if (name != spanishDisplayNames[i])
   1089             dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
   1090                         + "\", got \"" + name + "\"");
   1091     }
   1092 
   1093     for (i = 0; i < 9; i++) {
   1094         UnicodeString name;
   1095         localesToTest[i].getDisplayName(Locale::getFrance(), name);
   1096         logln(name);
   1097         if (name != frenchDisplayNames[i])
   1098             dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
   1099                         + "\", got \"" + name + "\"");
   1100     }
   1101 
   1102     for (i = 0; i < 9; i++) {
   1103         UnicodeString name;
   1104         localesToTest[i].getDisplayName(Locale("inv", "IN"), name);
   1105         logln(name + " Locale fallback to be, and data fallback to root");
   1106         if (name != invDisplayNames[i])
   1107             dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
   1108                         + "\", got \"" + prettify(name) + "\"");
   1109         localesToTest[i].getDisplayName(Locale("inv", "BD"), name);
   1110         logln(name + " Data fallback to root");
   1111         if (name != invDisplayNames[i])
   1112             dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
   1113                         + "\", got \"" + prettify(name )+ "\"");
   1114     }
   1115     Locale::setDefault(saveLocale, status);
   1116 }
   1117 
   1118 #if !UCONFIG_NO_FORMATTING
   1119 
   1120 /**
   1121  * @bug 4135752
   1122  * This would be better tested by the LocaleDataTest.  Will move it when I
   1123  * get the LocaleDataTest working again.
   1124  */
   1125 void
   1126 LocaleTest::TestThaiCurrencyFormat()
   1127 {
   1128     UErrorCode status = U_ZERO_ERROR;
   1129     DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance(
   1130                     Locale("th", "TH"), status);
   1131     UnicodeString posPrefix("THB", 3, US_INV);  // per cldrbug 7618
   1132     UnicodeString temp;
   1133 
   1134     if(U_FAILURE(status) || !thaiCurrency)
   1135     {
   1136         dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status)));
   1137         return;
   1138     }
   1139     if (thaiCurrency->getPositivePrefix(temp) != posPrefix)
   1140         errln("Thai currency prefix wrong: expected THB, got \"" +
   1141                         thaiCurrency->getPositivePrefix(temp) + "\"");
   1142     if (thaiCurrency->getPositiveSuffix(temp) != "")
   1143         errln("Thai currency suffix wrong: expected \"\", got \"" +
   1144                         thaiCurrency->getPositiveSuffix(temp) + "\"");
   1145 
   1146     delete thaiCurrency;
   1147 }
   1148 
   1149 /**
   1150  * @bug 4122371
   1151  * Confirm that Euro support works.  This test is pretty rudimentary; all it does
   1152  * is check that any locales with the EURO variant format a number using the
   1153  * Euro currency symbol.
   1154  *
   1155  * ASSUME: All locales encode the Euro character "\u20AC".
   1156  * If this is changed to use the single-character Euro symbol, this
   1157  * test must be updated.
   1158  *
   1159  */
   1160 void
   1161 LocaleTest::TestEuroSupport()
   1162 {
   1163     UChar euro = 0x20ac;
   1164     const UnicodeString EURO_CURRENCY(&euro, 1, 1); // Look for this UnicodeString in formatted Euro currency
   1165     const char* localeArr[] = {
   1166                             "ca_ES",
   1167                             "de_AT",
   1168                             "de_DE",
   1169                             "de_LU",
   1170                             "el_GR",
   1171                             "en_BE",
   1172                             "en_IE",
   1173                             "en_GB_EURO",
   1174                             "en_US_EURO",
   1175                             "es_ES",
   1176                             "eu_ES",
   1177                             "fi_FI",
   1178                             "fr_BE",
   1179                             "fr_FR",
   1180                             "fr_LU",
   1181                             "ga_IE",
   1182                             "gl_ES",
   1183                             "it_IT",
   1184                             "nl_BE",
   1185                             "nl_NL",
   1186                             "pt_PT",
   1187                             NULL
   1188                         };
   1189     const char** locales = localeArr;
   1190 
   1191     UErrorCode status = U_ZERO_ERROR;
   1192 
   1193     UnicodeString temp;
   1194 
   1195     for (;*locales!=NULL;locales++) {
   1196         Locale loc (*locales);
   1197         UnicodeString temp;
   1198         NumberFormat *nf = NumberFormat::createCurrencyInstance(loc, status);
   1199         UnicodeString pos;
   1200 
   1201         if (U_FAILURE(status)) {
   1202             dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales);
   1203             continue;
   1204         }
   1205 
   1206         nf->format(271828.182845, pos);
   1207         UnicodeString neg;
   1208         nf->format(-271828.182845, neg);
   1209         if (pos.indexOf(EURO_CURRENCY) >= 0 &&
   1210             neg.indexOf(EURO_CURRENCY) >= 0) {
   1211             logln("Ok: " + (temp=loc.getName()) +
   1212                 ": " + pos + " / " + neg);
   1213         }
   1214         else {
   1215             errln("Fail: " + (temp=loc.getName()) +
   1216                 " formats without " + EURO_CURRENCY +
   1217                 ": " + pos + " / " + neg +
   1218                 "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
   1219         }
   1220 
   1221         delete nf;
   1222     }
   1223 
   1224     UnicodeString dollarStr("USD", ""), euroStr("EUR", ""), genericStr((UChar)0x00a4), resultStr;
   1225     UChar tmp[4];
   1226     status = U_ZERO_ERROR;
   1227 
   1228     ucurr_forLocale("en_US", tmp, 4, &status);
   1229     resultStr.setTo(tmp);
   1230     if (dollarStr != resultStr) {
   1231         errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
   1232     }
   1233     ucurr_forLocale("en_US_EURO", tmp, 4, &status);
   1234     resultStr.setTo(tmp);
   1235     if (euroStr != resultStr) {
   1236         errcheckln(status, "Fail: en_US_EURO didn't return EUR - %s", u_errorName(status));
   1237     }
   1238     ucurr_forLocale("en_GB_EURO", tmp, 4, &status);
   1239     resultStr.setTo(tmp);
   1240     if (euroStr != resultStr) {
   1241         errcheckln(status, "Fail: en_GB_EURO didn't return EUR - %s", u_errorName(status));
   1242     }
   1243     ucurr_forLocale("en_US_PREEURO", tmp, 4, &status);
   1244     resultStr.setTo(tmp);
   1245     if (dollarStr != resultStr) {
   1246         errcheckln(status, "Fail: en_US_PREEURO didn't fallback to en_US - %s", u_errorName(status));
   1247     }
   1248     ucurr_forLocale("en_US_Q", tmp, 4, &status);
   1249     resultStr.setTo(tmp);
   1250     if (dollarStr != resultStr) {
   1251         errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
   1252     }
   1253     int32_t invalidLen = ucurr_forLocale("en_QQ", tmp, 4, &status);
   1254     if (invalidLen || U_SUCCESS(status)) {
   1255         errln("Fail: en_QQ didn't return NULL");
   1256     }
   1257 }
   1258 
   1259 #endif
   1260 
   1261 /**
   1262  * @bug 4139504
   1263  * toString() doesn't work with language_VARIANT.
   1264  */
   1265 void
   1266 LocaleTest::TestToString() {
   1267     Locale DATA [] = {
   1268         Locale("xx", "", ""),
   1269         Locale("", "YY", ""),
   1270         Locale("", "", "ZZ"),
   1271         Locale("xx", "YY", ""),
   1272         Locale("xx", "", "ZZ"),
   1273         Locale("", "YY", "ZZ"),
   1274         Locale("xx", "YY", "ZZ"),
   1275     };
   1276 
   1277     const char DATA_S [][20] = {
   1278         "xx",
   1279         "_YY",
   1280         "__ZZ",
   1281         "xx_YY",
   1282         "xx__ZZ",
   1283         "_YY_ZZ",
   1284         "xx_YY_ZZ",
   1285     };
   1286 
   1287     for (int32_t i=0; i < 7; ++i) {
   1288       const char *name;
   1289       name = DATA[i].getName();
   1290 
   1291       if (strcmp(name, DATA_S[i]) != 0)
   1292         {
   1293             errln("Fail: Locale.getName(), got:" + UnicodeString(name) + ", expected: " + DATA_S[i]);
   1294         }
   1295         else
   1296             logln("Pass: Locale.getName(), got:" + UnicodeString(name) );
   1297     }
   1298 }
   1299 
   1300 #if !UCONFIG_NO_FORMATTING
   1301 
   1302 /**
   1303  * @bug 4139940
   1304  * Couldn't reproduce this bug -- probably was fixed earlier.
   1305  *
   1306  * ORIGINAL BUG REPORT:
   1307  * -- basically, hungarian for monday shouldn't have an \u00f4
   1308  * (o circumflex)in it instead it should be an o with 2 inclined
   1309  * (right) lines over it..
   1310  *
   1311  * You may wonder -- why do all this -- why not just add a line to
   1312  * LocaleData?  Well, I could see by inspection that the locale file had the
   1313  * right character in it, so I wanted to check the rest of the pipeline -- a
   1314  * very remote possibility, but I wanted to be sure.  The other possibility
   1315  * is that something is wrong with the font mapping subsystem, but we can't
   1316  * test that here.
   1317  */
   1318 void
   1319 LocaleTest::Test4139940()
   1320 {
   1321     Locale mylocale("hu", "", "");
   1322     UDate mydate = date(98,3,13); // A Monday
   1323     UErrorCode status = U_ZERO_ERROR;
   1324     SimpleDateFormat df_full("EEEE", mylocale, status);
   1325     if(U_FAILURE(status)){
   1326         dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status)));
   1327         return;
   1328     }
   1329     UnicodeString str;
   1330     FieldPosition pos(FieldPosition::DONT_CARE);
   1331     df_full.format(mydate, str, pos);
   1332     // Make sure that o circumflex (\u00F4) is NOT there, and
   1333     // o double acute (\u0151) IS.
   1334     UChar ocf = 0x00f4;
   1335     UChar oda = 0x0151;
   1336     if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) {
   1337       /* If the default locale is "th" this test will fail because of the buddhist calendar. */
   1338       if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) {
   1339         errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d",
   1340               str.indexOf(oda), str.indexOf(ocf));
   1341       } else {
   1342         logln(UnicodeString("An error is produce in buddhist calendar."));
   1343       }
   1344       logln(UnicodeString("String is: ") + str );
   1345     }
   1346 }
   1347 
   1348 UDate
   1349 LocaleTest::date(int32_t y, int32_t m, int32_t d, int32_t hr, int32_t min, int32_t sec)
   1350 {
   1351     UErrorCode status = U_ZERO_ERROR;
   1352     Calendar *cal = Calendar::createInstance(status);
   1353     if (cal == 0)
   1354         return 0.0;
   1355     cal->clear();
   1356     cal->set(1900 + y, m, d, hr, min, sec); // Add 1900 to follow java.util.Date protocol
   1357     UDate dt = cal->getTime(status);
   1358     if (U_FAILURE(status))
   1359         return 0.0;
   1360 
   1361     delete cal;
   1362     return dt;
   1363 }
   1364 
   1365 /**
   1366  * @bug 4143951
   1367  * Russian first day of week should be Monday. Confirmed.
   1368  */
   1369 void
   1370 LocaleTest::Test4143951()
   1371 {
   1372     UErrorCode status = U_ZERO_ERROR;
   1373     Calendar *cal = Calendar::createInstance(Locale("ru", "", ""), status);
   1374     if(U_SUCCESS(status)) {
   1375       if (cal->getFirstDayOfWeek(status) != UCAL_MONDAY) {
   1376           dataerrln("Fail: First day of week in Russia should be Monday");
   1377       }
   1378     }
   1379     delete cal;
   1380 }
   1381 
   1382 #endif
   1383 
   1384 /**
   1385  * @bug 4147315
   1386  * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
   1387  * Should throw an exception for unknown locales
   1388  */
   1389 void
   1390 LocaleTest::Test4147315()
   1391 {
   1392   UnicodeString temp;
   1393     // Try with codes that are the wrong length but happen to match text
   1394     // at a valid offset in the mapping table
   1395     Locale locale("xxx", "CCC");
   1396 
   1397     const char *result = locale.getISO3Country();
   1398 
   1399     // Change to conform to C api usage
   1400     if((result==NULL)||(result[0] != 0))
   1401       errln("ERROR: getISO3Country() returns: " + UnicodeString(result,"") +
   1402                 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
   1403 }
   1404 
   1405 /**
   1406  * @bug 4147317
   1407  * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes.
   1408  * Should throw an exception for unknown locales
   1409  */
   1410 void
   1411 LocaleTest::Test4147317()
   1412 {
   1413     UnicodeString temp;
   1414     // Try with codes that are the wrong length but happen to match text
   1415     // at a valid offset in the mapping table
   1416     Locale locale("xxx", "CCC");
   1417 
   1418     const char *result = locale.getISO3Language();
   1419 
   1420     // Change to conform to C api usage
   1421     if((result==NULL)||(result[0] != 0))
   1422       errln("ERROR: getISO3Language() returns: " + UnicodeString(result,"") +
   1423                 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
   1424 }
   1425 
   1426 /*
   1427  * @bug 4147552
   1428  */
   1429 void
   1430 LocaleTest::Test4147552()
   1431 {
   1432     Locale locales [] = {     Locale("no", "NO"),
   1433                             Locale("no", "NO", "B"),
   1434                              Locale("no", "NO", "NY")
   1435     };
   1436 
   1437     UnicodeString edn("Norwegian (Norway, B)");
   1438     UnicodeString englishDisplayNames [] = {
   1439                                                 "Norwegian (Norway)",
   1440                                                  edn,
   1441                                                  // "Norwegian (Norway,B)",
   1442                                                  //"Norwegian (Norway,NY)"
   1443                                                  "Norwegian (Norway, NY)"
   1444     };
   1445     UnicodeString ndn("norsk (Norge, B");
   1446     UnicodeString norwegianDisplayNames [] = {
   1447                                                 "norsk (Norge)",
   1448                                                 "norsk (Norge, B)",
   1449                                                 //ndn,
   1450                                                  "norsk (Noreg, NY)"
   1451                                                  //"Norsk (Noreg, Nynorsk)"
   1452     };
   1453     UErrorCode status = U_ZERO_ERROR;
   1454 
   1455     Locale saveLocale;
   1456     Locale::setDefault(Locale::getEnglish(), status);
   1457     for (int32_t i = 0; i < 3; ++i) {
   1458         Locale loc = locales[i];
   1459         UnicodeString temp;
   1460         if (loc.getDisplayName(temp) != englishDisplayNames[i])
   1461            dataerrln("English display-name mismatch: expected " +
   1462                    englishDisplayNames[i] + ", got " + loc.getDisplayName(temp));
   1463         if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i])
   1464             dataerrln("Norwegian display-name mismatch: expected " +
   1465                    norwegianDisplayNames[i] + ", got " +
   1466                    loc.getDisplayName(loc, temp));
   1467     }
   1468     Locale::setDefault(saveLocale, status);
   1469 }
   1470 
   1471 void
   1472 LocaleTest::TestVariantParsing()
   1473 {
   1474     Locale en_US_custom("en", "US", "De Anza_Cupertino_California_United States_Earth");
   1475 
   1476     UnicodeString dispName("English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)");
   1477     UnicodeString dispVar("DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH");
   1478 
   1479     UnicodeString got;
   1480 
   1481     en_US_custom.getDisplayVariant(Locale::getUS(), got);
   1482     if(got != dispVar) {
   1483         errln("FAIL: getDisplayVariant()");
   1484         errln("Wanted: " + dispVar);
   1485         errln("Got   : " + got);
   1486     }
   1487 
   1488     en_US_custom.getDisplayName(Locale::getUS(), got);
   1489     if(got != dispName) {
   1490         dataerrln("FAIL: getDisplayName()");
   1491         dataerrln("Wanted: " + dispName);
   1492         dataerrln("Got   : " + got);
   1493     }
   1494 
   1495     Locale shortVariant("fr", "FR", "foo");
   1496     shortVariant.getDisplayVariant(got);
   1497 
   1498     if(got != "FOO") {
   1499         errln("FAIL: getDisplayVariant()");
   1500         errln("Wanted: foo");
   1501         errln("Got   : " + got);
   1502     }
   1503 
   1504     Locale bogusVariant("fr", "FR", "_foo");
   1505     bogusVariant.getDisplayVariant(got);
   1506 
   1507     if(got != "FOO") {
   1508         errln("FAIL: getDisplayVariant()");
   1509         errln("Wanted: foo");
   1510         errln("Got   : " + got);
   1511     }
   1512 
   1513     Locale bogusVariant2("fr", "FR", "foo_");
   1514     bogusVariant2.getDisplayVariant(got);
   1515 
   1516     if(got != "FOO") {
   1517         errln("FAIL: getDisplayVariant()");
   1518         errln("Wanted: foo");
   1519         errln("Got   : " + got);
   1520     }
   1521 
   1522     Locale bogusVariant3("fr", "FR", "_foo_");
   1523     bogusVariant3.getDisplayVariant(got);
   1524 
   1525     if(got != "FOO") {
   1526         errln("FAIL: getDisplayVariant()");
   1527         errln("Wanted: foo");
   1528         errln("Got   : " + got);
   1529     }
   1530 }
   1531 
   1532 #if !UCONFIG_NO_FORMATTING
   1533 
   1534 /**
   1535  * @bug 4105828
   1536  * Currency symbol in zh is wrong.  We will test this at the NumberFormat
   1537  * end to test the whole pipe.
   1538  */
   1539 void
   1540 LocaleTest::Test4105828()
   1541 {
   1542     Locale LOC [] = { Locale::getChinese(),  Locale("zh", "CN", ""),
   1543                      Locale("zh", "TW", ""), Locale("zh", "HK", "") };
   1544     UErrorCode status = U_ZERO_ERROR;
   1545     for (int32_t i = 0; i < 4; ++i) {
   1546         NumberFormat *fmt = NumberFormat::createPercentInstance(LOC[i], status);
   1547         if(U_FAILURE(status)) {
   1548             dataerrln("Couldn't create NumberFormat - %s", u_errorName(status));
   1549             return;
   1550         }
   1551         UnicodeString result;
   1552         FieldPosition pos(0);
   1553         fmt->format((int32_t)1, result, pos);
   1554         UnicodeString temp;
   1555         if(result != "100%") {
   1556             errln(UnicodeString("Percent for ") + LOC[i].getDisplayName(temp) + " should be 100%, got " + result);
   1557         }
   1558         delete fmt;
   1559     }
   1560 }
   1561 
   1562 #endif
   1563 
   1564 // Tests setBogus and isBogus APIs for Locale
   1565 // Jitterbug 1735
   1566 void
   1567 LocaleTest::TestSetIsBogus() {
   1568     Locale l("en_US");
   1569     l.setToBogus();
   1570     if(l.isBogus() != TRUE) {
   1571         errln("After setting bogus, didn't return TRUE");
   1572     }
   1573     l = "en_US"; // This should reset bogus
   1574     if(l.isBogus() != FALSE) {
   1575         errln("After resetting bogus, didn't return FALSE");
   1576     }
   1577 }
   1578 
   1579 
   1580 void
   1581 LocaleTest::TestKeywordVariants(void) {
   1582     static const struct {
   1583         const char *localeID;
   1584         const char *expectedLocaleID;
   1585         //const char *expectedLocaleIDNoKeywords;
   1586         //const char *expectedCanonicalID;
   1587         const char *expectedKeywords[10];
   1588         int32_t numKeywords;
   1589         UErrorCode expectedStatus;
   1590     } testCases[] = {
   1591         {
   1592             "de_DE@  currency = euro; C o ll A t i o n   = Phonebook   ; C alen dar = buddhist   ",
   1593             "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
   1594             //"de_DE",
   1595             //"de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
   1596             {"calendar", "collation", "currency"},
   1597             3,
   1598             U_ZERO_ERROR
   1599         },
   1600         {
   1601             "de_DE@euro",
   1602             "de_DE@euro",
   1603             //"de_DE",
   1604             //"de_DE@currency=EUR",
   1605             {"","","","","","",""},
   1606             0,
   1607             U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
   1608         }
   1609     };
   1610     UErrorCode status = U_ZERO_ERROR;
   1611 
   1612     int32_t i = 0, j = 0;
   1613     const char *result = NULL;
   1614     StringEnumeration *keywords;
   1615     int32_t keyCount = 0;
   1616     const char *keyword = NULL;
   1617     const UnicodeString *keywordString;
   1618     int32_t keywordLen = 0;
   1619 
   1620     for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) {
   1621         status = U_ZERO_ERROR;
   1622         Locale l(testCases[i].localeID);
   1623         keywords = l.createKeywords(status);
   1624 
   1625         if(status != testCases[i].expectedStatus) {
   1626             err("Expected to get status %s. Got %s instead\n",
   1627                 u_errorName(testCases[i].expectedStatus), u_errorName(status));
   1628         }
   1629         status = U_ZERO_ERROR;
   1630         if(keywords) {
   1631             if((keyCount = keywords->count(status)) != testCases[i].numKeywords) {
   1632                 err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
   1633             }
   1634             if(keyCount) {
   1635                 for(j = 0;;) {
   1636                     if((j&1)==0) {
   1637                         if((keyword = keywords->next(&keywordLen, status)) == NULL) {
   1638                             break;
   1639                         }
   1640                         if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
   1641                             err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
   1642                         }
   1643                     } else {
   1644                         if((keywordString = keywords->snext(status)) == NULL) {
   1645                             break;
   1646                         }
   1647                         if(*keywordString != UnicodeString(testCases[i].expectedKeywords[j], "")) {
   1648                             err("Expected to get keyword UnicodeString %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
   1649                         }
   1650                     }
   1651                     j++;
   1652 
   1653                     if(j == keyCount / 2) {
   1654                         // replace keywords with a clone of itself
   1655                         StringEnumeration *k2 = keywords->clone();
   1656                         if(k2 == NULL || keyCount != k2->count(status)) {
   1657                             errln("KeywordEnumeration.clone() failed");
   1658                         } else {
   1659                             delete keywords;
   1660                             keywords = k2;
   1661                         }
   1662                     }
   1663                 }
   1664                 keywords->reset(status); // Make sure that reset works.
   1665                 for(j = 0;;) {
   1666                     if((keyword = keywords->next(&keywordLen, status)) == NULL) {
   1667                         break;
   1668                     }
   1669                     if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
   1670                         err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
   1671                     }
   1672                     j++;
   1673                 }
   1674             }
   1675             delete keywords;
   1676         }
   1677         result = l.getName();
   1678         if(uprv_strcmp(testCases[i].expectedLocaleID, result) != 0) {
   1679             err("Expected to get \"%s\" from \"%s\". Got \"%s\" instead\n",
   1680                 testCases[i].expectedLocaleID, testCases[i].localeID, result);
   1681         }
   1682 
   1683     }
   1684 
   1685 }
   1686 
   1687 void
   1688 LocaleTest::TestKeywordVariantParsing(void) {
   1689     static const struct {
   1690         const char *localeID;
   1691         const char *keyword;
   1692         const char *expectedValue;
   1693     } testCases[] = {
   1694         { "de_DE@  C o ll A t i o n   = Phonebook   ", "collation", "Phonebook" },
   1695         { "de_DE", "collation", ""},
   1696         { "de_DE@collation= PHONEBOOK", "collation", "PHONEBOOK" },
   1697         { "de_DE@ currency = euro   ; CoLLaTion   = PHONEBOOk   ", "collation", "PHONEBOOk" },
   1698     };
   1699 
   1700     UErrorCode status = U_ZERO_ERROR;
   1701 
   1702     int32_t i = 0;
   1703     int32_t resultLen = 0;
   1704     char buffer[256];
   1705 
   1706     for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) {
   1707         *buffer = 0;
   1708         Locale l(testCases[i].localeID);
   1709         resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
   1710         (void)resultLen;  // Suppress unused variable warning.
   1711         if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
   1712             err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
   1713                 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
   1714         }
   1715     }
   1716 }
   1717 
   1718 void
   1719 LocaleTest::TestSetKeywordValue(void) {
   1720     static const struct {
   1721         const char *keyword;
   1722         const char *value;
   1723     } testCases[] = {
   1724         { "collation", "phonebook" },
   1725         { "currency", "euro" },
   1726         { "calendar", "buddhist" }
   1727     };
   1728 
   1729     UErrorCode status = U_ZERO_ERROR;
   1730 
   1731     int32_t i = 0;
   1732     int32_t resultLen = 0;
   1733     char buffer[256];
   1734 
   1735     Locale l(Locale::getGerman());
   1736 
   1737     for(i = 0; i < (int32_t)(sizeof(testCases)/sizeof(testCases[0])); i++) {
   1738         l.setKeywordValue(testCases[i].keyword, testCases[i].value, status);
   1739         if(U_FAILURE(status)) {
   1740             err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status));
   1741         }
   1742 
   1743         *buffer = 0;
   1744         resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
   1745         (void)resultLen;  // Suppress unused variable warning.
   1746         if(uprv_strcmp(testCases[i].value, buffer) != 0) {
   1747             err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
   1748                 testCases[i].value, testCases[i].keyword, buffer);
   1749         }
   1750     }
   1751 }
   1752 
   1753 void
   1754 LocaleTest::TestGetBaseName(void) {
   1755     static const struct {
   1756         const char *localeID;
   1757         const char *baseName;
   1758     } testCases[] = {
   1759         { "de_DE@  C o ll A t i o n   = Phonebook   ", "de_DE" },
   1760         { "de@currency = euro; CoLLaTion   = PHONEBOOk", "de" },
   1761         { "ja@calendar = buddhist", "ja" },
   1762         { "de-u-co-phonebk", "de"}
   1763     };
   1764 
   1765     int32_t i = 0;
   1766 
   1767     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
   1768         Locale loc(testCases[i].localeID);
   1769         if(strcmp(testCases[i].baseName, loc.getBaseName())) {
   1770             errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"",
   1771                 testCases[i].localeID, testCases[i].baseName, loc.getBaseName());
   1772             return;
   1773         }
   1774     }
   1775 
   1776     // Verify that adding a keyword to an existing Locale doesn't change the base name.
   1777     UErrorCode status = U_ZERO_ERROR;
   1778     Locale loc2("en-US");
   1779     if (strcmp("en_US", loc2.getBaseName())) {
   1780         errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
   1781     }
   1782     loc2.setKeywordValue("key", "value", status);
   1783     if (strcmp("en_US@key=value", loc2.getName())) {
   1784         errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__, __LINE__, loc2.getName());
   1785     }
   1786     if (strcmp("en_US", loc2.getBaseName())) {
   1787         errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
   1788     }
   1789 }
   1790 
   1791 /**
   1792  * Compare two locale IDs.  If they are equal, return 0.  If `string'
   1793  * starts with `prefix' plus an additional element, that is, string ==
   1794  * prefix + '_' + x, then return 1.  Otherwise return a value < 0.
   1795  */
   1796 static UBool _loccmp(const char* string, const char* prefix) {
   1797     int32_t slen = (int32_t)strlen(string),
   1798             plen = (int32_t)strlen(prefix);
   1799     int32_t c = uprv_strncmp(string, prefix, plen);
   1800     /* 'root' is "less than" everything */
   1801     if (uprv_strcmp(prefix, "root") == 0) {
   1802         return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
   1803     }
   1804     if (c) return -1; /* mismatch */
   1805     if (slen == plen) return 0;
   1806     if (string[plen] == '_') return 1;
   1807     return -2; /* false match, e.g. "en_USX" cmp "en_US" */
   1808 }
   1809 
   1810 /**
   1811  * Check the relationship between requested locales, and report problems.
   1812  * The caller specifies the expected relationships between requested
   1813  * and valid (expReqValid) and between valid and actual (expValidActual).
   1814  * Possible values are:
   1815  * "gt" strictly greater than, e.g., en_US > en
   1816  * "ge" greater or equal,      e.g., en >= en
   1817  * "eq" equal,                 e.g., en == en
   1818  */
   1819 void LocaleTest::_checklocs(const char* label,
   1820                             const char* req,
   1821                             const Locale& validLoc,
   1822                             const Locale& actualLoc,
   1823                             const char* expReqValid,
   1824                             const char* expValidActual) {
   1825     const char* valid = validLoc.getName();
   1826     const char* actual = actualLoc.getName();
   1827     int32_t reqValid = _loccmp(req, valid);
   1828     int32_t validActual = _loccmp(valid, actual);
   1829     if (((0 == uprv_strcmp(expReqValid, "gt") && reqValid > 0) ||
   1830          (0 == uprv_strcmp(expReqValid, "ge") && reqValid >= 0) ||
   1831          (0 == uprv_strcmp(expReqValid, "eq") && reqValid == 0)) &&
   1832         ((0 == uprv_strcmp(expValidActual, "gt") && validActual > 0) ||
   1833          (0 == uprv_strcmp(expValidActual, "ge") && validActual >= 0) ||
   1834          (0 == uprv_strcmp(expValidActual, "eq") && validActual == 0))) {
   1835         logln("%s; req=%s, valid=%s, actual=%s",
   1836               label, req, valid, actual);
   1837     } else {
   1838         dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s.  Require (R %s V) and (V %s A)",
   1839               label, req, valid, actual,
   1840               expReqValid, expValidActual);
   1841     }
   1842 }
   1843 
   1844 void LocaleTest::TestGetLocale(void) {
   1845 #if !UCONFIG_NO_SERVICE
   1846     const char *req;
   1847     Locale valid, actual, reqLoc;
   1848 
   1849     // Calendar
   1850 #if !UCONFIG_NO_FORMATTING
   1851     {
   1852         UErrorCode ec = U_ZERO_ERROR;  // give each resource type its own error code
   1853         req = "en_US_BROOKLYN";
   1854         Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec);
   1855         if (U_FAILURE(ec)) {
   1856             dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec));
   1857         } else {
   1858             valid = cal->getLocale(ULOC_VALID_LOCALE, ec);
   1859             actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1860             if (U_FAILURE(ec)) {
   1861                 errln("FAIL: Calendar::getLocale() failed");
   1862             } else {
   1863                 _checklocs("Calendar", req, valid, actual);
   1864             }
   1865             /* Make sure that it fails correctly */
   1866             ec = U_FILE_ACCESS_ERROR;
   1867             if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) {
   1868                 errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\"");
   1869             }
   1870             ec = U_ZERO_ERROR;
   1871         }
   1872         delete cal;
   1873     }
   1874 #endif
   1875 
   1876     // DecimalFormat, DecimalFormatSymbols
   1877 #if !UCONFIG_NO_FORMATTING
   1878     {
   1879         UErrorCode ec = U_ZERO_ERROR;  // give each resource type its own error code
   1880         req = "fr_FR_NICE";
   1881         NumberFormat* nf = NumberFormat::createInstance(Locale::createFromName(req), ec);
   1882         if (U_FAILURE(ec)) {
   1883             dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec));
   1884         } else {
   1885             DecimalFormat* dec = dynamic_cast<DecimalFormat*>(nf);
   1886             if (dec == NULL) {
   1887                 errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat");
   1888                 return;
   1889             }
   1890             valid = dec->getLocale(ULOC_VALID_LOCALE, ec);
   1891             actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1892             if (U_FAILURE(ec)) {
   1893                 errln("FAIL: DecimalFormat::getLocale() failed");
   1894             } else {
   1895                 _checklocs("DecimalFormat", req, valid, actual);
   1896             }
   1897 
   1898             const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols();
   1899             if (sym == NULL) {
   1900                 errln("FAIL: getDecimalFormatSymbols returned NULL");
   1901                 return;
   1902             }
   1903             valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
   1904             actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1905             if (U_FAILURE(ec)) {
   1906                 errln("FAIL: DecimalFormatSymbols::getLocale() failed");
   1907             } else {
   1908                 _checklocs("DecimalFormatSymbols", req, valid, actual);
   1909             }
   1910         }
   1911         delete nf;
   1912     }
   1913 #endif
   1914 
   1915     // DateFormat, DateFormatSymbols
   1916 #if !UCONFIG_NO_FORMATTING
   1917     {
   1918         UErrorCode ec = U_ZERO_ERROR;  // give each resource type its own error code
   1919         req = "de_CH_LUCERNE";
   1920         DateFormat* df =
   1921             DateFormat::createDateInstance(DateFormat::kDefault,
   1922                                            Locale::createFromName(req));
   1923         if (df == 0){
   1924             dataerrln("Error calling DateFormat::createDateInstance()");
   1925         } else {
   1926             SimpleDateFormat* dat = dynamic_cast<SimpleDateFormat*>(df);
   1927             if (dat == NULL) {
   1928                 errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat");
   1929                 return;
   1930             }
   1931             valid = dat->getLocale(ULOC_VALID_LOCALE, ec);
   1932             actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1933             if (U_FAILURE(ec)) {
   1934                 errln("FAIL: SimpleDateFormat::getLocale() failed");
   1935             } else {
   1936                 _checklocs("SimpleDateFormat", req, valid, actual);
   1937             }
   1938 
   1939             const DateFormatSymbols* sym = dat->getDateFormatSymbols();
   1940             if (sym == NULL) {
   1941                 errln("FAIL: getDateFormatSymbols returned NULL");
   1942                 return;
   1943             }
   1944             valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
   1945             actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1946             if (U_FAILURE(ec)) {
   1947                 errln("FAIL: DateFormatSymbols::getLocale() failed");
   1948             } else {
   1949                 _checklocs("DateFormatSymbols", req, valid, actual);
   1950             }
   1951         }
   1952         delete df;
   1953     }
   1954 #endif
   1955 
   1956     // BreakIterator
   1957 #if !UCONFIG_NO_BREAK_ITERATION
   1958     {
   1959         UErrorCode ec = U_ZERO_ERROR;  // give each resource type its own error code
   1960         req = "es_ES_BARCELONA";
   1961         reqLoc = Locale::createFromName(req);
   1962         BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec);
   1963         if (U_FAILURE(ec)) {
   1964             dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec));
   1965         } else {
   1966             valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
   1967             actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1968             if (U_FAILURE(ec)) {
   1969                 errln("FAIL: BreakIterator::getLocale() failed");
   1970             } else {
   1971                 _checklocs("BreakIterator", req, valid, actual);
   1972             }
   1973 
   1974             // After registering something, the behavior should be different
   1975             URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec);
   1976             brk = 0; // registerInstance adopts
   1977             if (U_FAILURE(ec)) {
   1978                 errln("FAIL: BreakIterator::registerInstance() failed");
   1979             } else {
   1980                 brk = BreakIterator::createWordInstance(reqLoc, ec);
   1981                 if (U_FAILURE(ec)) {
   1982                     errln("FAIL: BreakIterator::createWordInstance failed");
   1983                 } else {
   1984                     valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
   1985                     actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
   1986                     if (U_FAILURE(ec)) {
   1987                         errln("FAIL: BreakIterator::getLocale() failed");
   1988                     } else {
   1989                         // N.B.: now expect valid==actual==req
   1990                         _checklocs("BreakIterator(registered)",
   1991                                    req, valid, actual, "eq", "eq");
   1992                     }
   1993                 }
   1994                 // No matter what, unregister
   1995                 BreakIterator::unregister(key, ec);
   1996                 if (U_FAILURE(ec)) {
   1997                     errln("FAIL: BreakIterator::unregister() failed");
   1998                 }
   1999                 delete brk;
   2000                 brk = 0;
   2001             }
   2002 
   2003             // After unregistering, should behave normally again
   2004             brk = BreakIterator::createWordInstance(reqLoc, ec);
   2005             if (U_FAILURE(ec)) {
   2006                 errln("FAIL: BreakIterator::createWordInstance failed");
   2007             } else {
   2008                 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
   2009                 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
   2010                 if (U_FAILURE(ec)) {
   2011                     errln("FAIL: BreakIterator::getLocale() failed");
   2012                 } else {
   2013                     _checklocs("BreakIterator(unregistered)", req, valid, actual);
   2014                 }
   2015             }
   2016         }
   2017         delete brk;
   2018     }
   2019 #endif
   2020 
   2021     // Collator
   2022 #if !UCONFIG_NO_COLLATION
   2023     {
   2024         UErrorCode ec = U_ZERO_ERROR;  // give each resource type its own error code
   2025 
   2026         checkRegisteredCollators(NULL); // Don't expect any extras
   2027 
   2028         req = "hi_IN_BHOPAL";
   2029         reqLoc = Locale::createFromName(req);
   2030         Collator* coll = Collator::createInstance(reqLoc, ec);
   2031         if (U_FAILURE(ec)) {
   2032             dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec));
   2033         } else {
   2034             valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
   2035             actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
   2036             if (U_FAILURE(ec)) {
   2037                 errln("FAIL: Collator::getLocale() failed");
   2038             } else {
   2039                 _checklocs("Collator", req, valid, actual);
   2040             }
   2041 
   2042             // After registering something, the behavior should be different
   2043             URegistryKey key = Collator::registerInstance(coll, reqLoc, ec);
   2044             coll = 0; // registerInstance adopts
   2045             if (U_FAILURE(ec)) {
   2046                 errln("FAIL: Collator::registerInstance() failed");
   2047             } else {
   2048                 coll = Collator::createInstance(reqLoc, ec);
   2049                 if (U_FAILURE(ec)) {
   2050                     errln("FAIL: Collator::createWordInstance failed");
   2051                 } else {
   2052                     valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
   2053                     actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
   2054                     if (U_FAILURE(ec)) {
   2055                         errln("FAIL: Collator::getLocale() failed");
   2056                     } else {
   2057                         // N.B.: now expect valid==actual==req
   2058                         _checklocs("Collator(registered)",
   2059                                    req, valid, actual, "eq", "eq");
   2060                     }
   2061                 }
   2062                 checkRegisteredCollators(req); // include hi_IN_BHOPAL
   2063 
   2064                 // No matter what, unregister
   2065                 Collator::unregister(key, ec);
   2066                 if (U_FAILURE(ec)) {
   2067                     errln("FAIL: Collator::unregister() failed");
   2068                 }
   2069                 delete coll;
   2070                 coll = 0;
   2071             }
   2072 
   2073             // After unregistering, should behave normally again
   2074             coll = Collator::createInstance(reqLoc, ec);
   2075             if (U_FAILURE(ec)) {
   2076                 errln("FAIL: Collator::createInstance failed");
   2077             } else {
   2078                 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
   2079                 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
   2080                 if (U_FAILURE(ec)) {
   2081                     errln("FAIL: Collator::getLocale() failed");
   2082                 } else {
   2083                     _checklocs("Collator(unregistered)", req, valid, actual);
   2084                 }
   2085             }
   2086         }
   2087         delete coll;
   2088 
   2089         checkRegisteredCollators(NULL); // extra should be gone again
   2090     }
   2091 #endif
   2092 #endif
   2093 }
   2094 
   2095 #if !UCONFIG_NO_COLLATION
   2096 /**
   2097  * Compare Collator::getAvailableLocales(int) [ "old", returning an array ]
   2098  *   with  Collator::getAvailableLocales()    [ "new", returning a StringEnumeration ]
   2099  * These should be identical (check their API docs) EXCEPT that
   2100  * if expectExtra is non-NULL, it will be in the "new" array but not "old".
   2101  * Does not return any status but calls errln on error.
   2102  * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL.
   2103  */
   2104 void LocaleTest::checkRegisteredCollators(const char *expectExtra) {
   2105     UErrorCode status = U_ZERO_ERROR;
   2106     int32_t count1=0,count2=0;
   2107     Hashtable oldHash(status);
   2108     Hashtable newHash(status);
   2109     TEST_ASSERT_STATUS(status);
   2110 
   2111     UnicodeString expectStr(expectExtra?expectExtra:"n/a", "");
   2112 
   2113     // the 'old' list (non enumeration)
   2114     const Locale*  oldList = Collator::getAvailableLocales(count1);
   2115     if(oldList == NULL) {
   2116         dataerrln("Error: Collator::getAvailableLocales(count) returned NULL");
   2117         return;
   2118     }
   2119 
   2120     // the 'new' list (enumeration)
   2121     LocalPointer<StringEnumeration> newEnum(Collator::getAvailableLocales());
   2122     if(newEnum.isNull()) {
   2123        errln("Error: collator::getAvailableLocales() returned NULL");
   2124        return;
   2125     }
   2126 
   2127     // OK. Let's add all of the OLD
   2128     // then check for any in the NEW not in OLD
   2129     // then check for any in OLD not in NEW.
   2130 
   2131     // 1. add all of OLD
   2132     for(int32_t i=0;i<count1;i++) {
   2133         const UnicodeString key(oldList[i].getName(), "");
   2134         int32_t oldI = oldHash.puti(key, 1, status);
   2135         if( oldI == 1 ){
   2136             errln("Error: duplicate key %s in Collator::getAvailableLocales(count) list.\n",
   2137                 oldList[i].getName());
   2138             return;
   2139         }
   2140         if(expectExtra != NULL && !strcmp(expectExtra, oldList[i].getName())) {
   2141             errln("Inexplicably, Collator::getAvailableCollators(count) had registered collator %s. This shouldn't happen, so I am going to consider it an error.\n", expectExtra);
   2142         }
   2143     }
   2144 
   2145     // 2. add all of NEW
   2146     const UnicodeString *locStr;
   2147     UBool foundExpected = FALSE;
   2148     while((locStr = newEnum->snext(status)) && U_SUCCESS(status)) {
   2149         count2++;
   2150 
   2151         if(expectExtra != NULL && expectStr == *locStr) {
   2152             foundExpected = TRUE;
   2153             logln(UnicodeString("Found expected registered collator: ","") + expectStr);
   2154         }
   2155         (void)foundExpected;    // Hush unused variable compiler warning.
   2156 
   2157         if( oldHash.geti(*locStr) == 0 ) {
   2158             if(expectExtra != NULL && expectStr==*locStr) {
   2159                 logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr);
   2160             } else {
   2161                 errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","")
   2162                     + *locStr);
   2163             }
   2164         }
   2165         newHash.puti(*locStr, 1, status);
   2166     }
   2167 
   2168     // 3. check all of OLD again
   2169     for(int32_t i=0;i<count1;i++) {
   2170         const UnicodeString key(oldList[i].getName(), "");
   2171         int32_t newI = newHash.geti(key);
   2172         if(newI == 0) {
   2173             errln(UnicodeString("Error: Collator::getAvailableLocales() is missing: ","")
   2174                 + key);
   2175         }
   2176     }
   2177 
   2178     int32_t expectCount2 = count1;
   2179     if(expectExtra != NULL) {
   2180         expectCount2 ++; // if an extra item registered, bump the expect count
   2181     }
   2182 
   2183     assertEquals("Collator::getAvail() count", expectCount2, count2);
   2184 }
   2185 #endif
   2186 
   2187 
   2188 
   2189 void LocaleTest::TestVariantWithOutCountry(void) {
   2190     Locale loc("en","","POSIX");
   2191     if (0 != strcmp(loc.getVariant(), "POSIX")) {
   2192         errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc.getName(), "POSIX", loc.getVariant());
   2193     }
   2194     Locale loc2("en","","FOUR");
   2195     if (0 != strcmp(loc2.getVariant(), "FOUR")) {
   2196         errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2.getName(), "FOUR", loc2.getVariant());
   2197     }
   2198     Locale loc3("en","Latn","","FOUR");
   2199     if (0 != strcmp(loc3.getVariant(), "FOUR")) {
   2200         errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3.getName(), "FOUR", loc3.getVariant());
   2201     }
   2202     Locale loc4("","Latn","","FOUR");
   2203     if (0 != strcmp(loc4.getVariant(), "FOUR")) {
   2204         errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4.getName(), "FOUR", loc4.getVariant());
   2205     }
   2206     Locale loc5("","Latn","US","FOUR");
   2207     if (0 != strcmp(loc5.getVariant(), "FOUR")) {
   2208         errln("FAIL: _Latn_US_FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc5.getName(), "FOUR", loc5.getVariant());
   2209     }
   2210     Locale loc6("de-1901");
   2211     if (0 != strcmp(loc6.getVariant(), "1901")) {
   2212         errln("FAIL: de-1901 didn't get parsed correctly - name is %s - expected %s got %s", loc6.getName(), "1901", loc6.getVariant());
   2213     }
   2214 }
   2215 
   2216 static Locale _canonicalize(int32_t selector, /* 0==createFromName, 1==createCanonical, 2==Locale ct */
   2217                             const char* localeID) {
   2218     switch (selector) {
   2219     case 0:
   2220         return Locale::createFromName(localeID);
   2221     case 1:
   2222         return Locale::createCanonical(localeID);
   2223     case 2:
   2224         return Locale(localeID);
   2225     default:
   2226         return Locale("");
   2227     }
   2228 }
   2229 
   2230 void LocaleTest::TestCanonicalization(void)
   2231 {
   2232     static const struct {
   2233         const char *localeID;    /* input */
   2234         const char *getNameID;   /* expected getName() result */
   2235         const char *canonicalID; /* expected canonicalize() result */
   2236     } testCases[] = {
   2237         { "", "", "en_US_POSIX" },
   2238         { "C", "c", "en_US_POSIX" },
   2239         { "POSIX", "posix", "en_US_POSIX" },
   2240         { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
   2241           "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
   2242           "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
   2243         { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
   2244         { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
   2245         { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
   2246         { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
   2247         { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
   2248         { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
   2249         { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
   2250         { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
   2251         { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
   2252         { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
   2253         { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
   2254         { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
   2255         { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
   2256         { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
   2257         { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
   2258         { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
   2259         { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
   2260         { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
   2261         { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
   2262         { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
   2263         { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
   2264         { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
   2265         { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
   2266         { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
   2267         { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
   2268         { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
   2269         { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
   2270         { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
   2271         { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
   2272         { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
   2273         { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
   2274         { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
   2275         { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
   2276         { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
   2277         { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
   2278         { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
   2279         { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
   2280         // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS
   2281         // TODO: unify this behavior
   2282         { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
   2283         { "de-1901", "de__1901", "de__1901" }, /* registered name */
   2284         { "de-1906", "de__1906", "de__1906" }, /* registered name */
   2285         { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
   2286         { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
   2287         { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
   2288         { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
   2289         { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
   2290         { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
   2291         { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
   2292 
   2293         /* posix behavior that used to be performed by getName */
   2294         { "mr.utf8", "mr.utf8", "mr" },
   2295         { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
   2296         { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
   2297         { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
   2298         { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
   2299         { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO_NY_B" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */
   2300 
   2301         /* fleshing out canonicalization */
   2302         /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
   2303         { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
   2304         /* already-canonical ids are not changed */
   2305         { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
   2306         /* PRE_EURO and EURO conversions don't affect other keywords */
   2307         { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
   2308         { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
   2309         /* currency keyword overrides PRE_EURO and EURO currency */
   2310         { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
   2311         { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
   2312         /* norwegian is just too weird, if we handle things in their full generality */
   2313         { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
   2314 
   2315         /* test cases reflecting internal resource bundle usage */
   2316         { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
   2317         { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
   2318         { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }
   2319     };
   2320 
   2321     static const char* label[] = { "createFromName", "createCanonical", "Locale" };
   2322 
   2323     int32_t i, j;
   2324 
   2325     for (i=0; i < (int)(sizeof(testCases)/sizeof(testCases[0])); i++) {
   2326         for (j=0; j<3; ++j) {
   2327             const char* expected = (j==1) ? testCases[i].canonicalID : testCases[i].getNameID;
   2328             Locale loc = _canonicalize(j, testCases[i].localeID);
   2329             const char* getName = loc.isBogus() ? "BOGUS" : loc.getName();
   2330             if(uprv_strcmp(expected, getName) != 0) {
   2331                 errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"",
   2332                       label[j], testCases[i].localeID, getName, expected);
   2333             } else {
   2334                 logln("Ok: %s(%s) => \"%s\"",
   2335                       label[j], testCases[i].localeID, getName);
   2336             }
   2337         }
   2338     }
   2339 }
   2340 
   2341 void LocaleTest::TestCurrencyByDate(void)
   2342 {
   2343 #if !UCONFIG_NO_FORMATTING
   2344     UErrorCode status = U_ZERO_ERROR;
   2345     UDate date = uprv_getUTCtime();
   2346 	UChar TMP[4];
   2347 	int32_t index = 0;
   2348 	int32_t resLen = 0;
   2349     UnicodeString tempStr, resultStr;
   2350 
   2351 	// Cycle through historical currencies
   2352     date = (UDate)-630720000000.0; // pre 1961 - no currency defined
   2353     index = ucurr_countCurrencies("eo_AM", date, &status);
   2354     if (index != 0)
   2355 	{
   2356 		errcheckln(status, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status));
   2357 	}
   2358     resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
   2359     if (resLen != 0) {
   2360 		errcheckln(status, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status));
   2361     }
   2362     status = U_ZERO_ERROR;
   2363 
   2364     date = (UDate)0.0; // 1970 - one currency defined
   2365     index = ucurr_countCurrencies("eo_AM", date, &status);
   2366     if (index != 1)
   2367 	{
   2368 		errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
   2369 	}
   2370     resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
   2371 	tempStr.setTo(TMP);
   2372     resultStr.setTo("SUR");
   2373     if (resultStr != tempStr) {
   2374         errcheckln(status, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status));
   2375     }
   2376 
   2377     date = (UDate)693792000000.0; // 1992 - one currency defined
   2378 	index = ucurr_countCurrencies("eo_AM", date, &status);
   2379     if (index != 1)
   2380 	{
   2381 		errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
   2382 	}
   2383     resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
   2384 	tempStr.setTo(TMP);
   2385     resultStr.setTo("RUR");
   2386     if (resultStr != tempStr) {
   2387         errcheckln(status, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status));
   2388     }
   2389 
   2390 	date = (UDate)977616000000.0; // post 1993 - one currency defined
   2391 	index = ucurr_countCurrencies("eo_AM", date, &status);
   2392     if (index != 1)
   2393 	{
   2394 		errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
   2395 	}
   2396     resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
   2397 	tempStr.setTo(TMP);
   2398     resultStr.setTo("AMD");
   2399     if (resultStr != tempStr) {
   2400         errcheckln(status, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status));
   2401     }
   2402 
   2403     // Locale AD has multiple currencies at once
   2404 	date = (UDate)977616000000.0; // year 2001
   2405 	index = ucurr_countCurrencies("eo_AD", date, &status);
   2406     if (index != 4)
   2407 	{
   2408 		errcheckln(status, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status));
   2409 	}
   2410     resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
   2411 	tempStr.setTo(TMP);
   2412     resultStr.setTo("EUR");
   2413     if (resultStr != tempStr) {
   2414         errcheckln(status, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status));
   2415     }
   2416     resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
   2417 	tempStr.setTo(TMP);
   2418     resultStr.setTo("ESP");
   2419     if (resultStr != tempStr) {
   2420         errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
   2421     }
   2422     resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
   2423 	tempStr.setTo(TMP);
   2424     resultStr.setTo("FRF");
   2425     if (resultStr != tempStr) {
   2426         errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
   2427     }
   2428     resLen = ucurr_forLocaleAndDate("eo_AD", date, 4, TMP, 4, &status);
   2429 	tempStr.setTo(TMP);
   2430     resultStr.setTo("ADP");
   2431     if (resultStr != tempStr) {
   2432         errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
   2433     }
   2434 
   2435 	date = (UDate)0.0; // year 1970
   2436 	index = ucurr_countCurrencies("eo_AD", date, &status);
   2437     if (index != 3)
   2438 	{
   2439 		errcheckln(status, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status));
   2440 	}
   2441     resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
   2442 	tempStr.setTo(TMP);
   2443     resultStr.setTo("ESP");
   2444     if (resultStr != tempStr) {
   2445         errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
   2446     }
   2447     resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
   2448 	tempStr.setTo(TMP);
   2449     resultStr.setTo("FRF");
   2450     if (resultStr != tempStr) {
   2451         errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
   2452     }
   2453     resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
   2454 	tempStr.setTo(TMP);
   2455     resultStr.setTo("ADP");
   2456     if (resultStr != tempStr) {
   2457         errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
   2458     }
   2459 
   2460 	date = (UDate)-630720000000.0; // year 1950
   2461 	index = ucurr_countCurrencies("eo_AD", date, &status);
   2462     if (index != 2)
   2463 	{
   2464 		errcheckln(status, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status));
   2465 	}
   2466     resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
   2467 	tempStr.setTo(TMP);
   2468     resultStr.setTo("ESP");
   2469     if (resultStr != tempStr) {
   2470         errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
   2471     }
   2472     resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
   2473 	tempStr.setTo(TMP);
   2474     resultStr.setTo("ADP");
   2475     if (resultStr != tempStr) {
   2476         errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
   2477     }
   2478 
   2479 	date = (UDate)-2207520000000.0; // year 1900
   2480 	index = ucurr_countCurrencies("eo_AD", date, &status);
   2481     if (index != 1)
   2482 	{
   2483 		errcheckln(status, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status));
   2484 	}
   2485     resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
   2486 	tempStr.setTo(TMP);
   2487     resultStr.setTo("ESP");
   2488     if (resultStr != tempStr) {
   2489         errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
   2490     }
   2491 
   2492 	// Locale UA has gap between years 1994 - 1996
   2493 	date = (UDate)788400000000.0;
   2494 	index = ucurr_countCurrencies("eo_UA", date, &status);
   2495     if (index != 0)
   2496 	{
   2497 		errcheckln(status, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status));
   2498 	}
   2499     resLen = ucurr_forLocaleAndDate("eo_UA", date, index, TMP, 4, &status);
   2500     if (resLen != 0) {
   2501 		errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
   2502     }
   2503     status = U_ZERO_ERROR;
   2504 
   2505 	// Test index bounds
   2506     resLen = ucurr_forLocaleAndDate("eo_UA", date, 100, TMP, 4, &status);
   2507     if (resLen != 0) {
   2508 		errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
   2509     }
   2510     status = U_ZERO_ERROR;
   2511 
   2512     resLen = ucurr_forLocaleAndDate("eo_UA", date, 0, TMP, 4, &status);
   2513     if (resLen != 0) {
   2514 		errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
   2515     }
   2516     status = U_ZERO_ERROR;
   2517 
   2518 	// Test for bogus locale
   2519 	index = ucurr_countCurrencies("eo_QQ", date, &status);
   2520     if (index != 0)
   2521 	{
   2522 		errcheckln(status, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status));
   2523 	}
   2524     status = U_ZERO_ERROR;
   2525     resLen = ucurr_forLocaleAndDate("eo_QQ", date, 1, TMP, 4, &status);
   2526     if (resLen != 0) {
   2527 		errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
   2528     }
   2529     status = U_ZERO_ERROR;
   2530     resLen = ucurr_forLocaleAndDate("eo_QQ", date, 0, TMP, 4, &status);
   2531     if (resLen != 0) {
   2532 		errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
   2533     }
   2534     status = U_ZERO_ERROR;
   2535 
   2536     // Cycle through histrocial currencies
   2537 	date = (UDate)977616000000.0; // 2001 - one currency
   2538 	index = ucurr_countCurrencies("eo_AO", date, &status);
   2539     if (index != 1)
   2540 	{
   2541 		errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
   2542 	}
   2543     resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
   2544 	tempStr.setTo(TMP);
   2545     resultStr.setTo("AOA");
   2546     if (resultStr != tempStr) {
   2547         errcheckln(status, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status));
   2548     }
   2549 
   2550 	date = (UDate)819936000000.0; // 1996 - 2 currencies
   2551 	index = ucurr_countCurrencies("eo_AO", date, &status);
   2552     if (index != 2)
   2553 	{
   2554 		errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
   2555 	}
   2556     resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
   2557 	tempStr.setTo(TMP);
   2558     resultStr.setTo("AOR");
   2559     if (resultStr != tempStr) {
   2560         errcheckln(status, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status));
   2561     }
   2562     resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
   2563 	tempStr.setTo(TMP);
   2564     resultStr.setTo("AON");
   2565     if (resultStr != tempStr) {
   2566         errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
   2567     }
   2568 
   2569 	date = (UDate)662256000000.0; // 1991 - 2 currencies
   2570 	index = ucurr_countCurrencies("eo_AO", date, &status);
   2571     if (index != 2)
   2572 	{
   2573 		errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
   2574 	}
   2575     resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
   2576 	tempStr.setTo(TMP);
   2577     resultStr.setTo("AON");
   2578     if (resultStr != tempStr) {
   2579         errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
   2580     }
   2581     resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
   2582 	tempStr.setTo(TMP);
   2583     resultStr.setTo("AOK");
   2584     if (resultStr != tempStr) {
   2585         errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
   2586     }
   2587 
   2588 	date = (UDate)315360000000.0; // 1980 - one currency
   2589 	index = ucurr_countCurrencies("eo_AO", date, &status);
   2590     if (index != 1)
   2591 	{
   2592 		errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
   2593 	}
   2594     resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
   2595 	tempStr.setTo(TMP);
   2596     resultStr.setTo("AOK");
   2597     if (resultStr != tempStr) {
   2598         errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
   2599     }
   2600 
   2601 	date = (UDate)0.0; // 1970 - no currencies
   2602 	index = ucurr_countCurrencies("eo_AO", date, &status);
   2603     if (index != 0)
   2604 	{
   2605 		errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
   2606 	}
   2607     resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
   2608     if (resLen != 0) {
   2609 		errcheckln(status, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status));
   2610     }
   2611     status = U_ZERO_ERROR;
   2612 
   2613     // Test with currency keyword override
   2614 	date = (UDate)977616000000.0; // 2001 - two currencies
   2615 	index = ucurr_countCurrencies("eo_DE@currency=DEM", date, &status);
   2616     if (index != 2)
   2617 	{
   2618 		errcheckln(status, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status));
   2619 	}
   2620     resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 1, TMP, 4, &status);
   2621 	tempStr.setTo(TMP);
   2622     resultStr.setTo("EUR");
   2623     if (resultStr != tempStr) {
   2624         errcheckln(status, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status));
   2625     }
   2626     resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 2, TMP, 4, &status);
   2627 	tempStr.setTo(TMP);
   2628     resultStr.setTo("DEM");
   2629     if (resultStr != tempStr) {
   2630         errcheckln(status, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status));
   2631     }
   2632 
   2633     // Test Euro Support
   2634 	status = U_ZERO_ERROR; // reset
   2635     date = uprv_getUTCtime();
   2636 
   2637     UChar USD[4];
   2638     ucurr_forLocaleAndDate("en_US", date, 1, USD, 4, &status);
   2639 
   2640 	UChar YEN[4];
   2641     ucurr_forLocaleAndDate("ja_JP", date, 1, YEN, 4, &status);
   2642 
   2643     ucurr_forLocaleAndDate("en_US", date, 1, TMP, 4, &status);
   2644     if (u_strcmp(USD, TMP) != 0) {
   2645         errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
   2646     }
   2647     ucurr_forLocaleAndDate("en_US_PREEURO", date, 1, TMP, 4, &status);
   2648     if (u_strcmp(USD, TMP) != 0) {
   2649         errcheckln(status, "Fail: en_US_PREEURO didn't fallback to en_US - %s", u_errorName(status));
   2650     }
   2651     ucurr_forLocaleAndDate("en_US_Q", date, 1, TMP, 4, &status);
   2652     if (u_strcmp(USD, TMP) != 0) {
   2653         errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
   2654     }
   2655     status = U_ZERO_ERROR; // reset
   2656 #endif
   2657 }
   2658 
   2659 void LocaleTest::TestGetVariantWithKeywords(void)
   2660 {
   2661   Locale l("en_US_VALLEY@foo=value");
   2662   const char *variant = l.getVariant();
   2663   logln(variant);
   2664   test_assert(strcmp("VALLEY", variant) == 0);
   2665 
   2666   UErrorCode status = U_ZERO_ERROR;
   2667   char buffer[50];
   2668   int32_t len = l.getKeywordValue("foo", buffer, 50, status);
   2669   buffer[len] = '\0';
   2670   test_assert(strcmp("value", buffer) == 0);
   2671 }
   2672 
   2673 void LocaleTest::TestIsRightToLeft() {
   2674     assertFalse("root LTR", Locale::getRoot().isRightToLeft());
   2675     assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
   2676     assertTrue("ar RTL", Locale("ar").isRightToLeft());
   2677     assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), FALSE, TRUE);
   2678     assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
   2679     assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
   2680     assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), FALSE, TRUE);  // Sorani Kurdish
   2681     assertFalse("fil LTR", Locale("fil").isRightToLeft());
   2682     assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
   2683 }
   2684 
   2685 void LocaleTest::TestBug11421() {
   2686     Locale::getDefault().getBaseName();
   2687     int32_t numLocales;
   2688     const Locale *localeList = Locale::getAvailableLocales(numLocales);
   2689     for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) {
   2690         const Locale &loc = localeList[localeIndex];
   2691         if (strncmp(loc.getName(), loc.getBaseName(), strlen(loc.getBaseName()))) {
   2692             errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"",
   2693                 __FILE__, __LINE__, loc.getName(), loc.getBaseName());
   2694             break;
   2695         }
   2696     }
   2697 }
   2698