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