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