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