1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
10 #include "unicode/decimfmt.h"
11 #include "unicode/ucurr.h"
12 #include "unicode/smpdtfmt.h"
13 #include "unicode/strenum.h"
14 #include "unicode/dtfmtsym.h"
15 #include "unicode/brkiter.h"
16 #include "unicode/coll.h"
17 #include "unicode/ustring.h"
27 static const char* const rawData
[33][8] = {
30 { "en", "fr", "ca", "el", "no", "it", "xx", "zh" },
32 { "", "", "", "", "", "", "", "Hans" },
34 { "US", "FR", "ES", "GR", "NO", "", "YY", "CN" },
36 { "", "", "", "", "NY", "", "", "" },
38 { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "it", "xx_YY", "zh_Hans_CN" },
40 { "eng", "fra", "cat", "ell", "nor", "ita", "", "zho" },
42 { "USA", "FRA", "ESP", "GRC", "NOR", "", "", "CHN" },
44 { "409", "40c", "403", "408", "814", "10", "0", "804" },
46 // display langage (English)
47 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "Chinese" },
48 // display script (English)
49 { "", "", "", "", "", "", "", "Simplified Han" },
50 // display country (English)
51 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "China mainland" },
52 // display variant (English)
53 { "", "", "", "", "NY", "", "", ""},
54 // display name (English)
55 // Updated no_NO_NY English display name for new pattern-based algorithm
56 // (part of Euro support).
57 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China mainland)" },
59 // display langage (French)
60 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" },
61 // display script (French)
62 { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" },
63 // display country (French)
64 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine continentale" },
65 // display variant (French)
66 { "", "", "", "", "NY", "", "", "" },
67 // display name (French)
68 //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" },
69 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine continentale)" },
72 /* display language (Catalan) */
73 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" },
74 /* display script (Catalan) */
75 { "", "", "", "", "", "", "", "han simplificat" },
76 /* display country (Catalan) */
77 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina continental" },
78 /* display variant (Catalan) */
79 { "", "", "", "", "NY", "", "" },
80 /* display name (Catalan) */
81 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina continental)" },
83 // display langage (Greek)[actual values listed below]
84 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
85 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
86 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
87 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
88 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
89 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
91 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC"
93 // display script (Greek)
94 { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" },
95 // display country (Greek)[actual values listed below]
96 { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
97 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
98 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
99 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
100 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
103 "\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE"
105 // display variant (Greek)
106 { "", "", "", "", "NY", "", "" },
107 // display name (Greek)[actual values listed below]
108 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
109 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
110 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
111 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
112 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
113 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
115 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03b1, \\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE)"
118 // display langage (<root>)
119 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "" },
120 // display script (<root>)
121 { "", "", "", "", "", "", "", ""},
122 // display country (<root>)
123 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "" },
124 // display variant (<root>)
125 { "", "", "", "", "Nynorsk", "", "", ""},
126 // display name (<root>)
127 //{ "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
128 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,NY)", "Italian", "xx (YY)", "" }
134 test_assert( Test (should be TRUE) )
139 the macro is ugly but makes the tests pretty.
142 #define test_assert(test) \
145 errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \
147 logln("PASS: asserted " #test); \
152 test_assert_print( Test (should be TRUE), printable )
155 test_assert(i==3, toString(i));
157 the macro is ugly but makes the tests pretty.
160 #define test_assert_print(test,print) \
163 errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \
165 logln("PASS: asserted " #test "-> " + UnicodeString(print)); \
169 #define test_dumpLocale(l) { logln(#l " = " + UnicodeString(l.getName(), "")); }
171 LocaleTest::LocaleTest()
177 LocaleTest::~LocaleTest()
179 if (dataTable
!= 0) {
180 for (int32_t i
= 0; i
< 33; i
++) {
181 delete []dataTable
[i
];
188 void LocaleTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
191 TESTCASE_AUTO(TestBug11421
); // Must run early in list to trigger failure.
192 TESTCASE_AUTO(TestBasicGetters
);
193 TESTCASE_AUTO(TestSimpleResourceInfo
);
194 TESTCASE_AUTO(TestDisplayNames
);
195 TESTCASE_AUTO(TestSimpleObjectStuff
);
196 TESTCASE_AUTO(TestPOSIXParsing
);
197 TESTCASE_AUTO(TestGetAvailableLocales
);
198 TESTCASE_AUTO(TestDataDirectory
);
199 TESTCASE_AUTO(TestISO3Fallback
);
200 TESTCASE_AUTO(TestGetLangsAndCountries
);
201 TESTCASE_AUTO(TestSimpleDisplayNames
);
202 TESTCASE_AUTO(TestUninstalledISO3Names
);
203 TESTCASE_AUTO(TestAtypicalLocales
);
204 #if !UCONFIG_NO_FORMATTING
205 TESTCASE_AUTO(TestThaiCurrencyFormat
);
206 TESTCASE_AUTO(TestEuroSupport
);
208 TESTCASE_AUTO(TestToString
);
209 #if !UCONFIG_NO_FORMATTING
210 TESTCASE_AUTO(Test4139940
);
211 TESTCASE_AUTO(Test4143951
);
213 TESTCASE_AUTO(Test4147315
);
214 TESTCASE_AUTO(Test4147317
);
215 TESTCASE_AUTO(Test4147552
);
216 TESTCASE_AUTO(TestVariantParsing
);
217 #if !UCONFIG_NO_FORMATTING
218 TESTCASE_AUTO(Test4105828
);
220 TESTCASE_AUTO(TestSetIsBogus
);
221 TESTCASE_AUTO(TestParallelAPIValues
);
222 TESTCASE_AUTO(TestKeywordVariants
);
223 TESTCASE_AUTO(TestKeywordVariantParsing
);
224 TESTCASE_AUTO(TestSetKeywordValue
);
225 TESTCASE_AUTO(TestGetBaseName
);
226 #if !UCONFIG_NO_FILE_IO
227 TESTCASE_AUTO(TestGetLocale
);
229 TESTCASE_AUTO(TestVariantWithOutCountry
);
230 TESTCASE_AUTO(TestCanonicalization
);
231 TESTCASE_AUTO(TestCurrencyByDate
);
232 TESTCASE_AUTO(TestGetVariantWithKeywords
);
233 TESTCASE_AUTO(TestIsRightToLeft
);
234 TESTCASE_AUTO(TestBug13277
);
235 TESTCASE_AUTO(TestBug13554
);
239 void LocaleTest::TestBasicGetters() {
243 for (i
= 0; i
<= MAX_LOCALES
; i
++) {
244 Locale
testLocale("");
245 if (rawData
[SCRIPT
][i
] && rawData
[SCRIPT
][i
][0] != 0) {
246 testLocale
= Locale(rawData
[LANG
][i
], rawData
[SCRIPT
][i
], rawData
[CTRY
][i
], rawData
[VAR
][i
]);
249 testLocale
= Locale(rawData
[LANG
][i
], rawData
[CTRY
][i
], rawData
[VAR
][i
]);
251 logln("Testing " + (UnicodeString
)testLocale
.getName() + "...");
253 if ( (temp
=testLocale
.getLanguage()) != (dataTable
[LANG
][i
]))
254 errln(" Language code mismatch: " + temp
+ " versus "
255 + dataTable
[LANG
][i
]);
256 if ( (temp
=testLocale
.getScript()) != (dataTable
[SCRIPT
][i
]))
257 errln(" Script code mismatch: " + temp
+ " versus "
258 + dataTable
[SCRIPT
][i
]);
259 if ( (temp
=testLocale
.getCountry()) != (dataTable
[CTRY
][i
]))
260 errln(" Country code mismatch: " + temp
+ " versus "
261 + dataTable
[CTRY
][i
]);
262 if ( (temp
=testLocale
.getVariant()) != (dataTable
[VAR
][i
]))
263 errln(" Variant code mismatch: " + temp
+ " versus "
264 + dataTable
[VAR
][i
]);
265 if ( (temp
=testLocale
.getName()) != (dataTable
[NAME
][i
]))
266 errln(" Locale name mismatch: " + temp
+ " versus "
267 + dataTable
[NAME
][i
]);
270 logln("Same thing without variant codes...");
271 for (i
= 0; i
<= MAX_LOCALES
; i
++) {
272 Locale
testLocale("");
273 if (rawData
[SCRIPT
][i
] && rawData
[SCRIPT
][i
][0] != 0) {
274 testLocale
= Locale(rawData
[LANG
][i
], rawData
[SCRIPT
][i
], rawData
[CTRY
][i
]);
277 testLocale
= Locale(rawData
[LANG
][i
], rawData
[CTRY
][i
]);
279 logln("Testing " + (temp
=testLocale
.getName()) + "...");
281 if ( (temp
=testLocale
.getLanguage()) != (dataTable
[LANG
][i
]))
282 errln("Language code mismatch: " + temp
+ " versus "
283 + dataTable
[LANG
][i
]);
284 if ( (temp
=testLocale
.getScript()) != (dataTable
[SCRIPT
][i
]))
285 errln("Script code mismatch: " + temp
+ " versus "
286 + dataTable
[SCRIPT
][i
]);
287 if ( (temp
=testLocale
.getCountry()) != (dataTable
[CTRY
][i
]))
288 errln("Country code mismatch: " + temp
+ " versus "
289 + dataTable
[CTRY
][i
]);
290 if (testLocale
.getVariant()[0] != 0)
291 errln("Variant code mismatch: something versus \"\"");
294 logln("Testing long language names and getters");
295 Locale test8
= Locale::createFromName("x-klingon-latn-zx.utf32be@special");
297 temp
= test8
.getLanguage();
298 if (temp
!= UnicodeString("x-klingon") )
299 errln("Language code mismatch: " + temp
+ " versus \"x-klingon\"");
301 temp
= test8
.getScript();
302 if (temp
!= UnicodeString("Latn") )
303 errln("Script code mismatch: " + temp
+ " versus \"Latn\"");
305 temp
= test8
.getCountry();
306 if (temp
!= UnicodeString("ZX") )
307 errln("Country code mismatch: " + temp
+ " versus \"ZX\"");
309 temp
= test8
.getVariant();
310 //if (temp != UnicodeString("SPECIAL") )
311 // errln("Variant code mismatch: " + temp + " versus \"SPECIAL\"");
312 // As of 3.0, the "@special" will *not* be parsed by uloc_getName()
313 if (temp
!= UnicodeString("") )
314 errln("Variant code mismatch: " + temp
+ " versus \"\"");
316 if (Locale::getDefault() != Locale::createFromName(NULL
))
317 errln("Locale::getDefault() == Locale::createFromName(NULL)");
320 // NOTE: There used to be a special test for locale names that had language or
321 // country codes that were longer than two letters. The new version of Locale
322 // doesn't support anything that isn't an officially recognized language or
323 // country code, so we no longer support this feature.
325 Locale
bogusLang("THISISABOGUSLANGUAGE"); // Jitterbug 2864: language code too long
326 if(!bogusLang
.isBogus()) {
327 errln("Locale(\"THISISABOGUSLANGUAGE\").isBogus()==FALSE");
330 bogusLang
=Locale("eo");
331 if( bogusLang
.isBogus() ||
332 strcmp(bogusLang
.getLanguage(), "eo")!=0 ||
333 *bogusLang
.getCountry()!=0 ||
334 *bogusLang
.getVariant()!=0 ||
335 strcmp(bogusLang
.getName(), "eo")!=0
337 errln("assignment to bogus Locale does not unbogus it or sets bad data");
340 Locale
a("eo_DE@currency=DEM");
341 Locale
*pb
=a
.clone();
342 if(pb
==&a
|| *pb
!=a
) {
343 errln("Locale.clone() failed");
348 void LocaleTest::TestParallelAPIValues() {
349 logln("Test synchronization between C and C++ API");
350 if (strcmp(Locale::getChinese().getName(), ULOC_CHINESE
) != 0) {
351 errln("Differences for ULOC_CHINESE Locale");
353 if (strcmp(Locale::getEnglish().getName(), ULOC_ENGLISH
) != 0) {
354 errln("Differences for ULOC_ENGLISH Locale");
356 if (strcmp(Locale::getFrench().getName(), ULOC_FRENCH
) != 0) {
357 errln("Differences for ULOC_FRENCH Locale");
359 if (strcmp(Locale::getGerman().getName(), ULOC_GERMAN
) != 0) {
360 errln("Differences for ULOC_GERMAN Locale");
362 if (strcmp(Locale::getItalian().getName(), ULOC_ITALIAN
) != 0) {
363 errln("Differences for ULOC_ITALIAN Locale");
365 if (strcmp(Locale::getJapanese().getName(), ULOC_JAPANESE
) != 0) {
366 errln("Differences for ULOC_JAPANESE Locale");
368 if (strcmp(Locale::getKorean().getName(), ULOC_KOREAN
) != 0) {
369 errln("Differences for ULOC_KOREAN Locale");
371 if (strcmp(Locale::getSimplifiedChinese().getName(), ULOC_SIMPLIFIED_CHINESE
) != 0) {
372 errln("Differences for ULOC_SIMPLIFIED_CHINESE Locale");
374 if (strcmp(Locale::getTraditionalChinese().getName(), ULOC_TRADITIONAL_CHINESE
) != 0) {
375 errln("Differences for ULOC_TRADITIONAL_CHINESE Locale");
379 if (strcmp(Locale::getCanada().getName(), ULOC_CANADA
) != 0) {
380 errln("Differences for ULOC_CANADA Locale");
382 if (strcmp(Locale::getCanadaFrench().getName(), ULOC_CANADA_FRENCH
) != 0) {
383 errln("Differences for ULOC_CANADA_FRENCH Locale");
385 if (strcmp(Locale::getChina().getName(), ULOC_CHINA
) != 0) {
386 errln("Differences for ULOC_CHINA Locale");
388 if (strcmp(Locale::getPRC().getName(), ULOC_PRC
) != 0) {
389 errln("Differences for ULOC_PRC Locale");
391 if (strcmp(Locale::getFrance().getName(), ULOC_FRANCE
) != 0) {
392 errln("Differences for ULOC_FRANCE Locale");
394 if (strcmp(Locale::getGermany().getName(), ULOC_GERMANY
) != 0) {
395 errln("Differences for ULOC_GERMANY Locale");
397 if (strcmp(Locale::getItaly().getName(), ULOC_ITALY
) != 0) {
398 errln("Differences for ULOC_ITALY Locale");
400 if (strcmp(Locale::getJapan().getName(), ULOC_JAPAN
) != 0) {
401 errln("Differences for ULOC_JAPAN Locale");
403 if (strcmp(Locale::getKorea().getName(), ULOC_KOREA
) != 0) {
404 errln("Differences for ULOC_KOREA Locale");
406 if (strcmp(Locale::getTaiwan().getName(), ULOC_TAIWAN
) != 0) {
407 errln("Differences for ULOC_TAIWAN Locale");
409 if (strcmp(Locale::getUK().getName(), ULOC_UK
) != 0) {
410 errln("Differences for ULOC_UK Locale");
412 if (strcmp(Locale::getUS().getName(), ULOC_US
) != 0) {
413 errln("Differences for ULOC_US Locale");
418 void LocaleTest::TestSimpleResourceInfo() {
421 UErrorCode err
= U_ZERO_ERROR
;
424 for (i
= 0; i
<= MAX_LOCALES
; i
++) {
425 Locale
testLocale(rawData
[LANG
][i
], rawData
[CTRY
][i
], rawData
[VAR
][i
]);
426 logln("Testing " + (temp
=testLocale
.getName()) + "...");
428 if ( (temp
=testLocale
.getISO3Language()) != (dataTable
[LANG3
][i
]))
429 errln(" ISO-3 language code mismatch: " + temp
430 + " versus " + dataTable
[LANG3
][i
]);
431 if ( (temp
=testLocale
.getISO3Country()) != (dataTable
[CTRY3
][i
]))
432 errln(" ISO-3 country code mismatch: " + temp
433 + " versus " + dataTable
[CTRY3
][i
]);
435 sprintf(temp2
, "%x", (int)testLocale
.getLCID());
436 if (UnicodeString(temp2
) != dataTable
[LCID
][i
])
437 errln((UnicodeString
)" LCID mismatch: " + temp2
+ " versus "
438 + dataTable
[LCID
][i
]);
442 errln((UnicodeString
)"Some error on number " + i
+ u_errorName(err
));
448 if(strcmp(locale
.getName(), "en") != 0||
449 strcmp(locale
.getLanguage(), "en") != 0) {
450 errln("construction of Locale(en) failed\n");
457 * Jitterbug 2439 -- markus 20030425
459 * The lookup of display names must not fall back through the default
460 * locale because that yields useless results.
463 LocaleTest::TestDisplayNames()
465 Locale
english("en", "US");
466 Locale
french("fr", "FR");
467 Locale
croatian("ca", "ES");
468 Locale
greek("el", "GR");
470 logln(" In locale = en_US...");
471 doTestDisplayNames(english
, DLANG_EN
);
472 logln(" In locale = fr_FR...");
473 doTestDisplayNames(french
, DLANG_FR
);
474 logln(" In locale = ca_ES...");
475 doTestDisplayNames(croatian
, DLANG_CA
);
476 logln(" In locale = el_GR...");
477 doTestDisplayNames(greek
, DLANG_EL
);
480 UErrorCode status
= U_ZERO_ERROR
;
482 #if !UCONFIG_NO_FORMATTING
483 DecimalFormatSymbols
symb(status
);
484 /* Check to see if ICU supports this locale */
485 if (symb
.getLocale(ULOC_VALID_LOCALE
, status
) != Locale("root")) {
486 /* test that the default locale has a display name for its own language */
487 /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */
488 if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) {
489 Locale().getDisplayLanguage(Locale(), s
);
490 if(s
.length()<=3 && s
.charAt(0)<=0x7f) {
491 /* check <=3 to reject getting the language code as a display name */
492 dataerrln("unable to get a display string for the language of the default locale: " + s
);
496 * API coverage improvements: call
497 * Locale::getDisplayLanguage(UnicodeString &) and
498 * Locale::getDisplayCountry(UnicodeString &)
501 Locale().getDisplayLanguage(s
);
502 if(s
.length()<=3 && s
.charAt(0)<=0x7f) {
503 dataerrln("unable to get a display string for the language of the default locale [2]: " + s
);
508 logln("Default locale %s is unsupported by ICU\n", Locale().getName());
513 french
.getDisplayCountry(s
);
515 errln("unable to get any default-locale display string for the country of fr_FR\n");
518 Locale("zh", "Hant").getDisplayScript(s
);
520 errln("unable to get any default-locale display string for the country of zh_Hant\n");
524 void LocaleTest::TestSimpleObjectStuff() {
525 Locale
test1("aa", "AA");
526 Locale
test2("aa", "AA");
528 Locale
test4("zz", "ZZ");
529 Locale
test5("aa", "AA", "");
530 Locale
test6("aa", "AA", "ANTARES");
531 Locale
test7("aa", "AA", "JUPITER");
532 Locale test8
= Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that
534 // now list them all for debugging usage.
535 test_dumpLocale(test1
);
536 test_dumpLocale(test2
);
537 test_dumpLocale(test3
);
538 test_dumpLocale(test4
);
539 test_dumpLocale(test5
);
540 test_dumpLocale(test6
);
541 test_dumpLocale(test7
);
542 test_dumpLocale(test8
);
544 // Make sure things compare to themselves!
545 test_assert(test1
== test1
);
546 test_assert(test2
== test2
);
547 test_assert(test3
== test3
);
548 test_assert(test4
== test4
);
549 test_assert(test5
== test5
);
550 test_assert(test6
== test6
);
551 test_assert(test7
== test7
);
552 test_assert(test8
== test8
);
554 // make sure things are not equal to themselves.
555 test_assert(!(test1
!= test1
));
556 test_assert(!(test2
!= test2
));
557 test_assert(!(test3
!= test3
));
558 test_assert(!(test4
!= test4
));
559 test_assert(!(test5
!= test5
));
560 test_assert(!(test6
!= test6
));
561 test_assert(!(test7
!= test7
));
562 test_assert(!(test8
!= test8
));
564 // make sure things that are equal to each other don't show up as unequal.
565 test_assert(!(test1
!= test2
));
566 test_assert(!(test2
!= test1
));
567 test_assert(!(test1
!= test3
));
568 test_assert(!(test2
!= test3
));
569 test_assert(test5
== test1
);
570 test_assert(test6
!= test2
);
571 test_assert(test6
!= test5
);
573 test_assert(test6
!= test7
);
575 // test for things that shouldn't compare equal.
576 test_assert(!(test1
== test4
));
577 test_assert(!(test2
== test4
));
578 test_assert(!(test3
== test4
));
580 test_assert(test7
== test8
);
582 // test for hash codes to be the same.
583 int32_t hash1
= test1
.hashCode();
584 int32_t hash2
= test2
.hashCode();
585 int32_t hash3
= test3
.hashCode();
587 test_assert(hash1
== hash2
);
588 test_assert(hash1
== hash3
);
589 test_assert(hash2
== hash3
);
591 // test that the assignment operator works.
593 logln("test4=test1;");
594 test_dumpLocale(test4
);
595 test_assert(test4
== test4
);
597 test_assert(!(test1
!= test4
));
598 test_assert(!(test2
!= test4
));
599 test_assert(!(test3
!= test4
));
600 test_assert(test1
== test4
);
601 test_assert(test4
== test1
);
603 // test assignments with a variant
604 logln("test7 = test6");
606 test_dumpLocale(test7
);
607 test_assert(test7
== test7
);
608 test_assert(test7
== test6
);
609 test_assert(test7
!= test5
);
611 logln("test6 = test1");
613 test_dumpLocale(test6
);
614 test_assert(test6
!= test7
);
615 test_assert(test6
== test1
);
616 test_assert(test6
== test6
);
619 // A class which exposes constructors that are implemented in terms of the POSIX parsing code.
620 class POSIXLocale
: public Locale
623 POSIXLocale(const UnicodeString
& l
)
627 ch
= new char[l
.length() + 1];
628 ch
[l
.extract(0, 0x7fffffff, ch
, "")] = 0;
632 POSIXLocale(const char *l
)
639 void LocaleTest::TestPOSIXParsing()
641 POSIXLocale
test1("ab_AB");
642 POSIXLocale
test2(UnicodeString("ab_AB"));
643 Locale
test3("ab","AB");
645 POSIXLocale
test4("ab_AB_Antares");
646 POSIXLocale
test5(UnicodeString("ab_AB_Antares"));
647 Locale
test6("ab", "AB", "Antares");
649 test_dumpLocale(test1
);
650 test_dumpLocale(test2
);
651 test_dumpLocale(test3
);
652 test_dumpLocale(test4
);
653 test_dumpLocale(test5
);
654 test_dumpLocale(test6
);
656 test_assert(test1
== test1
);
658 test_assert(test1
== test2
);
659 test_assert(test2
== test3
);
660 test_assert(test3
== test1
);
662 test_assert(test4
== test5
);
663 test_assert(test5
== test6
);
664 test_assert(test6
== test4
);
666 test_assert(test1
!= test4
);
667 test_assert(test5
!= test3
);
668 test_assert(test5
!= test2
);
670 int32_t hash1
= test1
.hashCode();
671 int32_t hash2
= test2
.hashCode();
672 int32_t hash3
= test3
.hashCode();
674 test_assert(hash1
== hash2
);
675 test_assert(hash2
== hash3
);
676 test_assert(hash3
== hash1
);
679 void LocaleTest::TestGetAvailableLocales()
681 int32_t locCount
= 0;
682 const Locale
* locList
= Locale::getAvailableLocales(locCount
);
685 dataerrln("getAvailableLocales() returned an empty list!");
687 logln(UnicodeString("Number of locales returned = ") + locCount
);
689 for(int32_t i
= 0; i
< locCount
; ++i
)
690 logln(locList
[i
].getName());
692 // I have no idea how to test this function...
695 // This test isn't applicable anymore - getISO3Language is
696 // independent of the data directory
697 void LocaleTest::TestDataDirectory()
700 char oldDirectory[80];
702 UErrorCode err = U_ZERO_ERROR;
703 UnicodeString testValue;
705 temp = Locale::getDataDirectory();
706 strcpy(oldDirectory, temp);
707 logln(UnicodeString("oldDirectory = ") + oldDirectory);
709 Locale test(Locale::US);
710 test.getISO3Language(testValue);
711 logln("first fetch of language retrieved " + testValue);
712 if (testValue != "eng")
713 errln("Initial check of ISO3 language failed: expected \"eng\", got \"" + testValue + "\"");
717 path=IntlTest::getTestDirectory();
718 Locale::setDataDirectory( path );
721 test.getISO3Language(testValue);
722 logln("second fetch of language retrieved " + testValue);
723 if (testValue != "xxx")
724 errln("setDataDirectory() failed: expected \"xxx\", got \"" + testValue + "\"");
726 Locale::setDataDirectory(oldDirectory);
727 test.getISO3Language(testValue);
728 logln("third fetch of language retrieved " + testValue);
729 if (testValue != "eng")
730 errln("get/setDataDirectory() failed: expected \"eng\", got \"" + testValue + "\"");
734 //===========================================================
736 void LocaleTest::doTestDisplayNames(Locale
& displayLocale
, int32_t compareIndex
) {
739 for (int32_t i
= 0; i
<= MAX_LOCALES
; i
++) {
740 Locale
testLocale("");
741 if (rawData
[SCRIPT
][i
] && rawData
[SCRIPT
][i
][0] != 0) {
742 testLocale
= Locale(rawData
[LANG
][i
], rawData
[SCRIPT
][i
], rawData
[CTRY
][i
], rawData
[VAR
][i
]);
745 testLocale
= Locale(rawData
[LANG
][i
], rawData
[CTRY
][i
], rawData
[VAR
][i
]);
747 logln(" Testing " + (temp
=testLocale
.getName()) + "...");
749 UnicodeString testLang
;
750 UnicodeString testScript
;
751 UnicodeString testCtry
;
752 UnicodeString testVar
;
753 UnicodeString testName
;
755 testLocale
.getDisplayLanguage(displayLocale
, testLang
);
756 testLocale
.getDisplayScript(displayLocale
, testScript
);
757 testLocale
.getDisplayCountry(displayLocale
, testCtry
);
758 testLocale
.getDisplayVariant(displayLocale
, testVar
);
759 testLocale
.getDisplayName(displayLocale
, testName
);
761 UnicodeString expectedLang
;
762 UnicodeString expectedScript
;
763 UnicodeString expectedCtry
;
764 UnicodeString expectedVar
;
765 UnicodeString expectedName
;
767 expectedLang
= dataTable
[compareIndex
][i
];
768 if (expectedLang
.length() == 0)
769 expectedLang
= dataTable
[DLANG_EN
][i
];
771 expectedScript
= dataTable
[compareIndex
+ 1][i
];
772 if (expectedScript
.length() == 0)
773 expectedScript
= dataTable
[DSCRIPT_EN
][i
];
775 expectedCtry
= dataTable
[compareIndex
+ 2][i
];
776 if (expectedCtry
.length() == 0)
777 expectedCtry
= dataTable
[DCTRY_EN
][i
];
779 expectedVar
= dataTable
[compareIndex
+ 3][i
];
780 if (expectedVar
.length() == 0)
781 expectedVar
= dataTable
[DVAR_EN
][i
];
783 expectedName
= dataTable
[compareIndex
+ 4][i
];
784 if (expectedName
.length() == 0)
785 expectedName
= dataTable
[DNAME_EN
][i
];
787 if (testLang
!= expectedLang
)
788 dataerrln("Display language (" + UnicodeString(displayLocale
.getName()) + ") of (" + UnicodeString(testLocale
.getName()) + ") got " + testLang
+ " expected " + expectedLang
);
789 if (testScript
!= expectedScript
)
790 dataerrln("Display script (" + UnicodeString(displayLocale
.getName()) + ") of (" + UnicodeString(testLocale
.getName()) + ") got " + testScript
+ " expected " + expectedScript
);
791 if (testCtry
!= expectedCtry
)
792 dataerrln("Display country (" + UnicodeString(displayLocale
.getName()) + ") of (" + UnicodeString(testLocale
.getName()) + ") got " + testCtry
+ " expected " + expectedCtry
);
793 if (testVar
!= expectedVar
)
794 dataerrln("Display variant (" + UnicodeString(displayLocale
.getName()) + ") of (" + UnicodeString(testLocale
.getName()) + ") got " + testVar
+ " expected " + expectedVar
);
795 if (testName
!= expectedName
)
796 dataerrln("Display name (" + UnicodeString(displayLocale
.getName()) + ") of (" + UnicodeString(testLocale
.getName()) + ") got " + testName
+ " expected " + expectedName
);
800 //---------------------------------------------------
801 // table of valid data
802 //---------------------------------------------------
806 void LocaleTest::setUpDataTable()
808 if (dataTable
== 0) {
809 dataTable
= new UnicodeString
*[33];
811 for (int32_t i
= 0; i
< 33; i
++) {
812 dataTable
[i
] = new UnicodeString
[8];
813 for (int32_t j
= 0; j
< 8; j
++) {
814 dataTable
[i
][j
] = CharsToUnicodeString(rawData
[i
][j
]);
820 // ====================
824 * @bug 4011756 4011380
827 LocaleTest::TestISO3Fallback()
829 Locale
test("xx", "YY");
833 result
= test
.getISO3Language();
835 // Conform to C API usage
837 if (!result
|| (result
[0] != 0))
838 errln("getISO3Language() on xx_YY returned " + UnicodeString(result
) + " instead of \"\"");
840 result
= test
.getISO3Country();
842 if (!result
|| (result
[0] != 0))
843 errln("getISO3Country() on xx_YY returned " + UnicodeString(result
) + " instead of \"\"");
847 * @bug 4106155 4118587
850 LocaleTest::TestGetLangsAndCountries()
852 // It didn't seem right to just do an exhaustive test of everything here, so I check
853 // for the following things:
854 // 1) Does each list have the right total number of entries?
855 // 2) Does each list contain certain language and country codes we think are important
856 // (the G7 countries, plus a couple others)?
857 // 3) Does each list have every entry formatted correctly? (i.e., two characters,
858 // all lower case for the language codes, all upper case for the country codes)
859 // 4) Is each list in sorted order?
860 int32_t testCount
= 0;
861 const char * const * test
= Locale::getISOLanguages();
862 const char spotCheck1
[ ][4] = { "en", "es", "fr", "de", "it",
863 "ja", "ko", "zh", "th", "he",
864 "id", "iu", "ug", "yi", "za" };
868 for(testCount
= 0;test
[testCount
];testCount
++)
871 /* TODO: Change this test to be more like the cloctst version? */
872 if (testCount
!= 595)
873 errln("Expected getISOLanguages() to return 595 languages; it returned %d", testCount
);
875 for (i
= 0; i
< 15; i
++) {
877 for (j
= 0; j
< testCount
; j
++)
878 if (uprv_strcmp(test
[j
],spotCheck1
[i
])== 0)
880 if (j
== testCount
|| (uprv_strcmp(test
[j
],spotCheck1
[i
])!=0))
881 errln("Couldn't find " + (UnicodeString
)spotCheck1
[i
] + " in language list.");
884 for (i
= 0; i
< testCount
; i
++) {
885 UnicodeString
testee(test
[i
],"");
886 UnicodeString
lc(test
[i
],"");
887 if (testee
!= lc
.toLower())
888 errln(lc
+ " is not all lower case.");
889 if ( (testee
.length() != 2) && (testee
.length() != 3))
890 errln(testee
+ " is not two or three characters long.");
891 if (i
> 0 && testee
.compare(test
[i
- 1]) <= 0)
892 errln(testee
+ " appears in an out-of-order position in the list.");
895 test
= Locale::getISOCountries();
896 UnicodeString spotCheck2
[] = { "US", "CA", "GB", "FR", "DE",
897 "IT", "JP", "KR", "CN", "TW",
899 int32_t spot2Len
= 11;
900 for(testCount
=0;test
[testCount
];testCount
++)
903 if (testCount
!= 256){
904 errln("Expected getISOCountries to return 256 countries; it returned %d", testCount
);
906 for (i
= 0; i
< spot2Len
; i
++) {
908 for (j
= 0; j
< testCount
; j
++)
910 UnicodeString
testee(test
[j
],"");
912 if (testee
== spotCheck2
[i
])
915 UnicodeString
testee(test
[j
],"");
916 if (j
== testCount
|| testee
!= spotCheck2
[i
])
917 errln("Couldn't find " + spotCheck2
[i
] + " in country list.");
920 for (i
= 0; i
< testCount
; i
++) {
921 UnicodeString
testee(test
[i
],"");
922 UnicodeString
uc(test
[i
],"");
923 if (testee
!= uc
.toUpper())
924 errln(testee
+ " is not all upper case.");
925 if (testee
.length() != 2)
926 errln(testee
+ " is not two characters long.");
927 if (i
> 0 && testee
.compare(test
[i
- 1]) <= 0)
928 errln(testee
+ " appears in an out-of-order position in the list.");
931 // This getAvailableLocales and getISO3Language
933 int32_t numOfLocales
;
935 const Locale
*pLocales
= Locale::getAvailableLocales(numOfLocales
);
937 for (int i
= 0; i
< numOfLocales
; i
++) {
938 const Locale
&loc(pLocales
[i
]);
942 loc
.getDisplayName (enLoc
, name
);
943 name
.extract (0, 200, szName
, sizeof(szName
));
945 if (strlen(loc
.getISO3Language()) == 0) {
946 errln("getISO3Language() returned an empty string for: " + name
);
956 LocaleTest::TestSimpleDisplayNames()
958 // This test is different from TestDisplayNames because TestDisplayNames checks
959 // fallback behavior, combination of language and country names to form locale
960 // names, and other stuff like that. This test just checks specific language
961 // and country codes to make sure we have the correct names for them.
962 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za" };
963 UnicodeString languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
966 for (int32_t i
= 0; i
< 6; i
++) {
968 Locale
l(languageCodes
[i
], "", "");
969 l
.getDisplayLanguage(Locale::getUS(), test
);
970 if (test
!= languageNames
[i
])
971 dataerrln("Got wrong display name for " + UnicodeString(languageCodes
[i
]) + ": Expected \"" +
972 languageNames
[i
] + "\", got \"" + test
+ "\".");
980 LocaleTest::TestUninstalledISO3Names()
982 // This test checks to make sure getISO3Language and getISO3Country work right
983 // even for locales that are not installed.
984 const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
986 const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
987 "ssw", "twi", "zul" };
991 for (i
= 0; i
< 8; i
++) {
992 UErrorCode err
= U_ZERO_ERROR
;
995 Locale
l(iso2Languages
[i
], "", "");
996 test
= l
.getISO3Language();
997 if((test
!= iso3Languages
[i
]) || U_FAILURE(err
))
998 errln("Got wrong ISO3 code for " + UnicodeString(iso2Languages
[i
]) + ": Expected \"" +
999 iso3Languages
[i
] + "\", got \"" + test
+ "\"." + UnicodeString(u_errorName(err
)));
1002 char iso2Countries
[][4] = { "AF", "BW", "KZ", "MO", "MN",
1004 char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1005 "SLB", "TCA", "ZWE" };
1007 for (i
= 0; i
< 8; i
++) {
1008 UErrorCode err
= U_ZERO_ERROR
;
1009 Locale
l("", iso2Countries
[i
], "");
1010 UnicodeString
test(l
.getISO3Country(), "");
1011 if (test
!= iso3Countries
[i
])
1012 errln("Got wrong ISO3 code for " + UnicodeString(iso2Countries
[i
]) + ": Expected \"" +
1013 UnicodeString(iso3Countries
[i
]) + "\", got \"" + test
+ "\"." + u_errorName(err
));
1019 * I could not reproduce this bug. I'm pretty convinced it was fixed with the
1020 * big locale-data reorg of 10/28/97. The lookup logic for language and country
1021 * display names was also changed at that time in that check-in. --rtg 3/20/98
1024 LocaleTest::TestAtypicalLocales()
1026 Locale localesToTest
[] = { Locale("de", "CA"),
1036 UnicodeString englishDisplayNames
[] = { "German (Canada)",
1037 "Japanese (South Africa)",
1040 "Spanish (Germany)",
1043 "Dominican Republic",
1045 UnicodeString frenchDisplayNames
[]= { "allemand (Canada)",
1046 "japonais (Afrique du Sud)",
1049 "espagnol (Allemagne)",
1051 CharsToUnicodeString("Su\\u00E8de"),
1052 CharsToUnicodeString("R\\u00E9publique dominicaine"),
1054 UnicodeString spanishDisplayNames
[] = {
1055 CharsToUnicodeString("alem\\u00E1n (Canad\\u00E1)"),
1056 CharsToUnicodeString("japon\\u00E9s (Sud\\u00E1frica)"),
1057 CharsToUnicodeString("ruso (M\\u00E9xico)"),
1058 CharsToUnicodeString("ingl\\u00E9s (Francia)"),
1059 CharsToUnicodeString("espa\\u00F1ol (Alemania)"),
1062 CharsToUnicodeString("Rep\\u00FAblica Dominicana"),
1063 CharsToUnicodeString("B\\u00E9lgica") };
1064 // De-Anglicizing root required the change from
1065 // English display names to ISO Codes - ram 2003/09/26
1066 UnicodeString invDisplayNames
[] = { "German (Canada)",
1067 "Japanese (South Africa)",
1070 "Spanish (Germany)",
1073 "Dominican Republic",
1077 UErrorCode status
= U_ZERO_ERROR
;
1079 Locale::setDefault(Locale::getUS(), status
);
1080 for (i
= 0; i
< 9; ++i
) {
1082 localesToTest
[i
].getDisplayName(Locale::getUS(), name
);
1084 if (name
!= englishDisplayNames
[i
])
1086 dataerrln("Lookup in English failed: expected \"" + englishDisplayNames
[i
]
1087 + "\", got \"" + name
+ "\"");
1088 logln("Locale name was-> " + (name
=localesToTest
[i
].getName()));
1092 for (i
= 0; i
< 9; i
++) {
1094 localesToTest
[i
].getDisplayName(Locale("es", "ES"), name
);
1096 if (name
!= spanishDisplayNames
[i
])
1097 dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames
[i
]
1098 + "\", got \"" + name
+ "\"");
1101 for (i
= 0; i
< 9; i
++) {
1103 localesToTest
[i
].getDisplayName(Locale::getFrance(), name
);
1105 if (name
!= frenchDisplayNames
[i
])
1106 dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames
[i
]
1107 + "\", got \"" + name
+ "\"");
1110 for (i
= 0; i
< 9; i
++) {
1112 localesToTest
[i
].getDisplayName(Locale("inv", "IN"), name
);
1113 logln(name
+ " Locale fallback to be, and data fallback to root");
1114 if (name
!= invDisplayNames
[i
])
1115 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames
[i
])
1116 + "\", got \"" + prettify(name
) + "\"");
1117 localesToTest
[i
].getDisplayName(Locale("inv", "BD"), name
);
1118 logln(name
+ " Data fallback to root");
1119 if (name
!= invDisplayNames
[i
])
1120 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames
[i
])
1121 + "\", got \"" + prettify(name
)+ "\"");
1123 Locale::setDefault(saveLocale
, status
);
1126 #if !UCONFIG_NO_FORMATTING
1130 * This would be better tested by the LocaleDataTest. Will move it when I
1131 * get the LocaleDataTest working again.
1134 LocaleTest::TestThaiCurrencyFormat()
1136 UErrorCode status
= U_ZERO_ERROR
;
1137 DecimalFormat
*thaiCurrency
= (DecimalFormat
*)NumberFormat::createCurrencyInstance(
1138 Locale("th", "TH"), status
);
1139 UnicodeString
posPrefix("THB", 3, US_INV
); // per cldrbug 7618
1142 if(U_FAILURE(status
) || !thaiCurrency
)
1144 dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status
)));
1147 if (thaiCurrency
->getPositivePrefix(temp
) != posPrefix
)
1148 errln("Thai currency prefix wrong: expected THB, got \"" +
1149 thaiCurrency
->getPositivePrefix(temp
) + "\"");
1150 if (thaiCurrency
->getPositiveSuffix(temp
) != "")
1151 errln("Thai currency suffix wrong: expected \"\", got \"" +
1152 thaiCurrency
->getPositiveSuffix(temp
) + "\"");
1154 delete thaiCurrency
;
1159 * Confirm that Euro support works. This test is pretty rudimentary; all it does
1160 * is check that any locales with the EURO variant format a number using the
1161 * Euro currency symbol.
1163 * ASSUME: All locales encode the Euro character "\u20AC".
1164 * If this is changed to use the single-character Euro symbol, this
1165 * test must be updated.
1169 LocaleTest::TestEuroSupport()
1171 UChar euro
= 0x20ac;
1172 const UnicodeString
EURO_CURRENCY(&euro
, 1, 1); // Look for this UnicodeString in formatted Euro currency
1173 const char* localeArr
[] = {
1197 const char** locales
= localeArr
;
1199 UErrorCode status
= U_ZERO_ERROR
;
1203 for (;*locales
!=NULL
;locales
++) {
1204 Locale
loc (*locales
);
1206 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(loc
, status
);
1209 if (U_FAILURE(status
)) {
1210 dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales
);
1214 nf
->format(271828.182845, pos
);
1216 nf
->format(-271828.182845, neg
);
1217 if (pos
.indexOf(EURO_CURRENCY
) >= 0 &&
1218 neg
.indexOf(EURO_CURRENCY
) >= 0) {
1219 logln("Ok: " + (temp
=loc
.getName()) +
1220 ": " + pos
+ " / " + neg
);
1223 errln("Fail: " + (temp
=loc
.getName()) +
1224 " formats without " + EURO_CURRENCY
+
1225 ": " + pos
+ " / " + neg
+
1226 "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
1232 UnicodeString
dollarStr("USD", ""), euroStr("EUR", ""), genericStr((UChar
)0x00a4), resultStr
;
1234 status
= U_ZERO_ERROR
;
1236 ucurr_forLocale("en_US", tmp
, 4, &status
);
1237 resultStr
.setTo(tmp
);
1238 if (dollarStr
!= resultStr
) {
1239 errcheckln(status
, "Fail: en_US didn't return USD - %s", u_errorName(status
));
1241 ucurr_forLocale("en_US_EURO", tmp
, 4, &status
);
1242 resultStr
.setTo(tmp
);
1243 if (euroStr
!= resultStr
) {
1244 errcheckln(status
, "Fail: en_US_EURO didn't return EUR - %s", u_errorName(status
));
1246 ucurr_forLocale("en_GB_EURO", tmp
, 4, &status
);
1247 resultStr
.setTo(tmp
);
1248 if (euroStr
!= resultStr
) {
1249 errcheckln(status
, "Fail: en_GB_EURO didn't return EUR - %s", u_errorName(status
));
1251 ucurr_forLocale("en_US_PREEURO", tmp
, 4, &status
);
1252 resultStr
.setTo(tmp
);
1253 if (dollarStr
!= resultStr
) {
1254 errcheckln(status
, "Fail: en_US_PREEURO didn't fallback to en_US - %s", u_errorName(status
));
1256 ucurr_forLocale("en_US_Q", tmp
, 4, &status
);
1257 resultStr
.setTo(tmp
);
1258 if (dollarStr
!= resultStr
) {
1259 errcheckln(status
, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status
));
1261 int32_t invalidLen
= ucurr_forLocale("en_QQ", tmp
, 4, &status
);
1262 if (invalidLen
|| U_SUCCESS(status
)) {
1263 errln("Fail: en_QQ didn't return NULL");
1266 // The currency keyword value is as long as the destination buffer.
1267 // It should detect the overflow internally, and default to the locale's currency.
1269 status
= U_ZERO_ERROR
;
1270 int32_t length
= ucurr_forLocale("en_US@currency=euro", tmp
, 4, &status
);
1271 if (U_FAILURE(status
) || dollarStr
!= UnicodeString(tmp
, length
)) {
1272 if (U_SUCCESS(status
) && tmp
[0] == u
'¤') {
1273 errln("Fail: ucurr_forLocale(en_US@currency=euro) succeeded without writing output");
1275 errln("Fail: ucurr_forLocale(en_US@currency=euro) != USD - %s", u_errorName(status
));
1284 * toString() doesn't work with language_VARIANT.
1287 LocaleTest::TestToString() {
1289 Locale("xx", "", ""),
1290 Locale("", "YY", ""),
1291 Locale("", "", "ZZ"),
1292 Locale("xx", "YY", ""),
1293 Locale("xx", "", "ZZ"),
1294 Locale("", "YY", "ZZ"),
1295 Locale("xx", "YY", "ZZ"),
1298 const char DATA_S
[][20] = {
1308 for (int32_t i
=0; i
< 7; ++i
) {
1310 name
= DATA
[i
].getName();
1312 if (strcmp(name
, DATA_S
[i
]) != 0)
1314 errln("Fail: Locale.getName(), got:" + UnicodeString(name
) + ", expected: " + DATA_S
[i
]);
1317 logln("Pass: Locale.getName(), got:" + UnicodeString(name
) );
1321 #if !UCONFIG_NO_FORMATTING
1325 * Couldn't reproduce this bug -- probably was fixed earlier.
1327 * ORIGINAL BUG REPORT:
1328 * -- basically, hungarian for monday shouldn't have an \u00f4
1329 * (o circumflex)in it instead it should be an o with 2 inclined
1330 * (right) lines over it..
1332 * You may wonder -- why do all this -- why not just add a line to
1333 * LocaleData? Well, I could see by inspection that the locale file had the
1334 * right character in it, so I wanted to check the rest of the pipeline -- a
1335 * very remote possibility, but I wanted to be sure. The other possibility
1336 * is that something is wrong with the font mapping subsystem, but we can't
1340 LocaleTest::Test4139940()
1342 Locale
mylocale("hu", "", "");
1343 UDate mydate
= date(98,3,13); // A Monday
1344 UErrorCode status
= U_ZERO_ERROR
;
1345 SimpleDateFormat
df_full("EEEE", mylocale
, status
);
1346 if(U_FAILURE(status
)){
1347 dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status
)));
1351 FieldPosition
pos(FieldPosition::DONT_CARE
);
1352 df_full
.format(mydate
, str
, pos
);
1353 // Make sure that o circumflex (\u00F4) is NOT there, and
1354 // o double acute (\u0151) IS.
1357 if (str
.indexOf(oda
) < 0 || str
.indexOf(ocf
) >= 0) {
1358 /* If the default locale is "th" this test will fail because of the buddhist calendar. */
1359 if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) {
1360 errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d",
1361 str
.indexOf(oda
), str
.indexOf(ocf
));
1363 logln(UnicodeString("An error is produce in buddhist calendar."));
1365 logln(UnicodeString("String is: ") + str
);
1370 LocaleTest::date(int32_t y
, int32_t m
, int32_t d
, int32_t hr
, int32_t min
, int32_t sec
)
1372 UErrorCode status
= U_ZERO_ERROR
;
1373 Calendar
*cal
= Calendar::createInstance(status
);
1377 cal
->set(1900 + y
, m
, d
, hr
, min
, sec
); // Add 1900 to follow java.util.Date protocol
1378 UDate dt
= cal
->getTime(status
);
1379 if (U_FAILURE(status
))
1388 * Russian first day of week should be Monday. Confirmed.
1391 LocaleTest::Test4143951()
1393 UErrorCode status
= U_ZERO_ERROR
;
1394 Calendar
*cal
= Calendar::createInstance(Locale("ru", "", ""), status
);
1395 if(U_SUCCESS(status
)) {
1396 if (cal
->getFirstDayOfWeek(status
) != UCAL_MONDAY
) {
1397 dataerrln("Fail: First day of week in Russia should be Monday");
1407 * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
1408 * Should throw an exception for unknown locales
1411 LocaleTest::Test4147315()
1414 // Try with codes that are the wrong length but happen to match text
1415 // at a valid offset in the mapping table
1416 Locale
locale("xxx", "CCC");
1418 const char *result
= locale
.getISO3Country();
1420 // Change to conform to C api usage
1421 if((result
==NULL
)||(result
[0] != 0))
1422 errln("ERROR: getISO3Country() returns: " + UnicodeString(result
,"") +
1423 " for locale '" + (temp
=locale
.getName()) + "' rather than exception" );
1428 * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes.
1429 * Should throw an exception for unknown locales
1432 LocaleTest::Test4147317()
1435 // Try with codes that are the wrong length but happen to match text
1436 // at a valid offset in the mapping table
1437 Locale
locale("xxx", "CCC");
1439 const char *result
= locale
.getISO3Language();
1441 // Change to conform to C api usage
1442 if((result
==NULL
)||(result
[0] != 0))
1443 errln("ERROR: getISO3Language() returns: " + UnicodeString(result
,"") +
1444 " for locale '" + (temp
=locale
.getName()) + "' rather than exception" );
1451 LocaleTest::Test4147552()
1453 Locale locales
[] = { Locale("no", "NO"),
1454 Locale("no", "NO", "B"),
1455 Locale("no", "NO", "NY")
1458 UnicodeString
edn("Norwegian (Norway, B)");
1459 UnicodeString englishDisplayNames
[] = {
1460 "Norwegian (Norway)",
1462 // "Norwegian (Norway,B)",
1463 //"Norwegian (Norway,NY)"
1464 "Norwegian (Norway, NY)"
1466 UnicodeString
ndn("norsk (Norge, B");
1467 UnicodeString norwegianDisplayNames
[] = {
1472 //"Norsk (Noreg, Nynorsk)"
1474 UErrorCode status
= U_ZERO_ERROR
;
1477 Locale::setDefault(Locale::getEnglish(), status
);
1478 for (int32_t i
= 0; i
< 3; ++i
) {
1479 Locale loc
= locales
[i
];
1481 if (loc
.getDisplayName(temp
) != englishDisplayNames
[i
])
1482 dataerrln("English display-name mismatch: expected " +
1483 englishDisplayNames
[i
] + ", got " + loc
.getDisplayName(temp
));
1484 if (loc
.getDisplayName(loc
, temp
) != norwegianDisplayNames
[i
])
1485 dataerrln("Norwegian display-name mismatch: expected " +
1486 norwegianDisplayNames
[i
] + ", got " +
1487 loc
.getDisplayName(loc
, temp
));
1489 Locale::setDefault(saveLocale
, status
);
1493 LocaleTest::TestVariantParsing()
1495 Locale
en_US_custom("en", "US", "De Anza_Cupertino_California_United States_Earth");
1497 UnicodeString
dispName("English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)");
1498 UnicodeString
dispVar("DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH");
1502 en_US_custom
.getDisplayVariant(Locale::getUS(), got
);
1503 if(got
!= dispVar
) {
1504 errln("FAIL: getDisplayVariant()");
1505 errln("Wanted: " + dispVar
);
1506 errln("Got : " + got
);
1509 en_US_custom
.getDisplayName(Locale::getUS(), got
);
1510 if(got
!= dispName
) {
1511 dataerrln("FAIL: getDisplayName()");
1512 dataerrln("Wanted: " + dispName
);
1513 dataerrln("Got : " + got
);
1516 Locale
shortVariant("fr", "FR", "foo");
1517 shortVariant
.getDisplayVariant(got
);
1520 errln("FAIL: getDisplayVariant()");
1521 errln("Wanted: foo");
1522 errln("Got : " + got
);
1525 Locale
bogusVariant("fr", "FR", "_foo");
1526 bogusVariant
.getDisplayVariant(got
);
1529 errln("FAIL: getDisplayVariant()");
1530 errln("Wanted: foo");
1531 errln("Got : " + got
);
1534 Locale
bogusVariant2("fr", "FR", "foo_");
1535 bogusVariant2
.getDisplayVariant(got
);
1538 errln("FAIL: getDisplayVariant()");
1539 errln("Wanted: foo");
1540 errln("Got : " + got
);
1543 Locale
bogusVariant3("fr", "FR", "_foo_");
1544 bogusVariant3
.getDisplayVariant(got
);
1547 errln("FAIL: getDisplayVariant()");
1548 errln("Wanted: foo");
1549 errln("Got : " + got
);
1553 #if !UCONFIG_NO_FORMATTING
1557 * Currency symbol in zh is wrong. We will test this at the NumberFormat
1558 * end to test the whole pipe.
1561 LocaleTest::Test4105828()
1563 Locale LOC
[] = { Locale::getChinese(), Locale("zh", "CN", ""),
1564 Locale("zh", "TW", ""), Locale("zh", "HK", "") };
1565 UErrorCode status
= U_ZERO_ERROR
;
1566 for (int32_t i
= 0; i
< 4; ++i
) {
1567 NumberFormat
*fmt
= NumberFormat::createPercentInstance(LOC
[i
], status
);
1568 if(U_FAILURE(status
)) {
1569 dataerrln("Couldn't create NumberFormat - %s", u_errorName(status
));
1572 UnicodeString result
;
1573 FieldPosition
pos(FieldPosition::DONT_CARE
);
1574 fmt
->format((int32_t)1, result
, pos
);
1576 if(result
!= "100%") {
1577 errln(UnicodeString("Percent for ") + LOC
[i
].getDisplayName(temp
) + " should be 100%, got " + result
);
1585 // Tests setBogus and isBogus APIs for Locale
1588 LocaleTest::TestSetIsBogus() {
1591 if(l
.isBogus() != TRUE
) {
1592 errln("After setting bogus, didn't return TRUE");
1594 l
= "en_US"; // This should reset bogus
1595 if(l
.isBogus() != FALSE
) {
1596 errln("After resetting bogus, didn't return FALSE");
1602 LocaleTest::TestKeywordVariants(void) {
1603 static const struct {
1604 const char *localeID
;
1605 const char *expectedLocaleID
;
1606 //const char *expectedLocaleIDNoKeywords;
1607 //const char *expectedCanonicalID;
1608 const char *expectedKeywords
[10];
1609 int32_t numKeywords
;
1610 UErrorCode expectedStatus
;
1613 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1614 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1616 //"de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1617 {"calendar", "collation", "currency"},
1625 //"de_DE@currency=EUR",
1626 {"","","","","","",""},
1628 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1631 UErrorCode status
= U_ZERO_ERROR
;
1633 int32_t i
= 0, j
= 0;
1634 const char *result
= NULL
;
1635 StringEnumeration
*keywords
;
1636 int32_t keyCount
= 0;
1637 const char *keyword
= NULL
;
1638 const UnicodeString
*keywordString
;
1639 int32_t keywordLen
= 0;
1641 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1642 status
= U_ZERO_ERROR
;
1643 Locale
l(testCases
[i
].localeID
);
1644 keywords
= l
.createKeywords(status
);
1646 if(status
!= testCases
[i
].expectedStatus
) {
1647 err("Expected to get status %s. Got %s instead\n",
1648 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1650 status
= U_ZERO_ERROR
;
1652 if((keyCount
= keywords
->count(status
)) != testCases
[i
].numKeywords
) {
1653 err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1658 if((keyword
= keywords
->next(&keywordLen
, status
)) == NULL
) {
1661 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1662 err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1665 if((keywordString
= keywords
->snext(status
)) == NULL
) {
1668 if(*keywordString
!= UnicodeString(testCases
[i
].expectedKeywords
[j
], "")) {
1669 err("Expected to get keyword UnicodeString %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1674 if(j
== keyCount
/ 2) {
1675 // replace keywords with a clone of itself
1676 StringEnumeration
*k2
= keywords
->clone();
1677 if(k2
== NULL
|| keyCount
!= k2
->count(status
)) {
1678 errln("KeywordEnumeration.clone() failed");
1685 keywords
->reset(status
); // Make sure that reset works.
1687 if((keyword
= keywords
->next(&keywordLen
, status
)) == NULL
) {
1690 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1691 err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1698 result
= l
.getName();
1699 if(uprv_strcmp(testCases
[i
].expectedLocaleID
, result
) != 0) {
1700 err("Expected to get \"%s\" from \"%s\". Got \"%s\" instead\n",
1701 testCases
[i
].expectedLocaleID
, testCases
[i
].localeID
, result
);
1709 LocaleTest::TestKeywordVariantParsing(void) {
1710 static const struct {
1711 const char *localeID
;
1712 const char *keyword
;
1713 const char *expectedValue
;
1715 { "de_DE@ C o ll A t i o n = Phonebook ", "collation", "Phonebook" },
1716 { "de_DE", "collation", ""},
1717 { "de_DE@collation= PHONEBOOK", "collation", "PHONEBOOK" },
1718 { "de_DE@ currency = euro ; CoLLaTion = PHONEBOOk ", "collation", "PHONEBOOk" },
1721 UErrorCode status
= U_ZERO_ERROR
;
1724 int32_t resultLen
= 0;
1727 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1729 Locale
l(testCases
[i
].localeID
);
1730 resultLen
= l
.getKeywordValue(testCases
[i
].keyword
, buffer
, 256, status
);
1731 (void)resultLen
; // Suppress unused variable warning.
1732 if(uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1733 err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1734 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1740 LocaleTest::TestSetKeywordValue(void) {
1741 static const struct {
1742 const char *keyword
;
1745 { "collation", "phonebook" },
1746 { "currency", "euro" },
1747 { "calendar", "buddhist" }
1750 UErrorCode status
= U_ZERO_ERROR
;
1753 int32_t resultLen
= 0;
1756 Locale
l(Locale::getGerman());
1758 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1759 l
.setKeywordValue(testCases
[i
].keyword
, testCases
[i
].value
, status
);
1760 if(U_FAILURE(status
)) {
1761 err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status
));
1765 resultLen
= l
.getKeywordValue(testCases
[i
].keyword
, buffer
, 256, status
);
1766 (void)resultLen
; // Suppress unused variable warning.
1767 if(uprv_strcmp(testCases
[i
].value
, buffer
) != 0) {
1768 err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1769 testCases
[i
].value
, testCases
[i
].keyword
, buffer
);
1775 LocaleTest::TestGetBaseName(void) {
1776 static const struct {
1777 const char *localeID
;
1778 const char *baseName
;
1780 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
1781 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
1782 { "ja@calendar = buddhist", "ja" },
1783 { "de-u-co-phonebk", "de"}
1788 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1789 Locale
loc(testCases
[i
].localeID
);
1790 if(strcmp(testCases
[i
].baseName
, loc
.getBaseName())) {
1791 errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"",
1792 testCases
[i
].localeID
, testCases
[i
].baseName
, loc
.getBaseName());
1797 // Verify that adding a keyword to an existing Locale doesn't change the base name.
1798 UErrorCode status
= U_ZERO_ERROR
;
1799 Locale
loc2("en-US");
1800 if (strcmp("en_US", loc2
.getBaseName())) {
1801 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__
, __LINE__
, loc2
.getBaseName());
1803 loc2
.setKeywordValue("key", "value", status
);
1804 if (strcmp("en_US@key=value", loc2
.getName())) {
1805 errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__
, __LINE__
, loc2
.getName());
1807 if (strcmp("en_US", loc2
.getBaseName())) {
1808 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__
, __LINE__
, loc2
.getBaseName());
1813 * Compare two locale IDs. If they are equal, return 0. If `string'
1814 * starts with `prefix' plus an additional element, that is, string ==
1815 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
1817 static UBool
_loccmp(const char* string
, const char* prefix
) {
1818 int32_t slen
= (int32_t)strlen(string
),
1819 plen
= (int32_t)strlen(prefix
);
1820 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
1821 /* 'root' is "less than" everything */
1822 if (uprv_strcmp(prefix
, "root") == 0) {
1823 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
1825 if (c
) return -1; /* mismatch */
1826 if (slen
== plen
) return 0;
1827 if (string
[plen
] == '_') return 1;
1828 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
1832 * Check the relationship between requested locales, and report problems.
1833 * The caller specifies the expected relationships between requested
1834 * and valid (expReqValid) and between valid and actual (expValidActual).
1835 * Possible values are:
1836 * "gt" strictly greater than, e.g., en_US > en
1837 * "ge" greater or equal, e.g., en >= en
1838 * "eq" equal, e.g., en == en
1840 void LocaleTest::_checklocs(const char* label
,
1842 const Locale
& validLoc
,
1843 const Locale
& actualLoc
,
1844 const char* expReqValid
,
1845 const char* expValidActual
) {
1846 const char* valid
= validLoc
.getName();
1847 const char* actual
= actualLoc
.getName();
1848 int32_t reqValid
= _loccmp(req
, valid
);
1849 int32_t validActual
= _loccmp(valid
, actual
);
1850 if (((0 == uprv_strcmp(expReqValid
, "gt") && reqValid
> 0) ||
1851 (0 == uprv_strcmp(expReqValid
, "ge") && reqValid
>= 0) ||
1852 (0 == uprv_strcmp(expReqValid
, "eq") && reqValid
== 0)) &&
1853 ((0 == uprv_strcmp(expValidActual
, "gt") && validActual
> 0) ||
1854 (0 == uprv_strcmp(expValidActual
, "ge") && validActual
>= 0) ||
1855 (0 == uprv_strcmp(expValidActual
, "eq") && validActual
== 0))) {
1856 logln("%s; req=%s, valid=%s, actual=%s",
1857 label
, req
, valid
, actual
);
1859 dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)",
1860 label
, req
, valid
, actual
,
1861 expReqValid
, expValidActual
);
1865 void LocaleTest::TestGetLocale(void) {
1866 #if !UCONFIG_NO_SERVICE
1868 Locale valid
, actual
, reqLoc
;
1871 #if !UCONFIG_NO_FORMATTING
1873 UErrorCode ec
= U_ZERO_ERROR
; // give each resource type its own error code
1874 req
= "en_US_BROOKLYN";
1875 Calendar
* cal
= Calendar::createInstance(Locale::createFromName(req
), ec
);
1876 if (U_FAILURE(ec
)) {
1877 dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec
));
1879 valid
= cal
->getLocale(ULOC_VALID_LOCALE
, ec
);
1880 actual
= cal
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1881 if (U_FAILURE(ec
)) {
1882 errln("FAIL: Calendar::getLocale() failed");
1884 _checklocs("Calendar", req
, valid
, actual
);
1886 /* Make sure that it fails correctly */
1887 ec
= U_FILE_ACCESS_ERROR
;
1888 if (cal
->getLocale(ULOC_VALID_LOCALE
, ec
).getName()[0] != 0) {
1889 errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\"");
1897 // DecimalFormat, DecimalFormatSymbols
1898 #if !UCONFIG_NO_FORMATTING
1900 UErrorCode ec
= U_ZERO_ERROR
; // give each resource type its own error code
1902 NumberFormat
* nf
= NumberFormat::createInstance(Locale::createFromName(req
), ec
);
1903 if (U_FAILURE(ec
)) {
1904 dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec
));
1906 DecimalFormat
* dec
= dynamic_cast<DecimalFormat
*>(nf
);
1908 errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat");
1911 valid
= dec
->getLocale(ULOC_VALID_LOCALE
, ec
);
1912 actual
= dec
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1913 if (U_FAILURE(ec
)) {
1914 errln("FAIL: DecimalFormat::getLocale() failed");
1916 _checklocs("DecimalFormat", req
, valid
, actual
);
1919 const DecimalFormatSymbols
* sym
= dec
->getDecimalFormatSymbols();
1921 errln("FAIL: getDecimalFormatSymbols returned NULL");
1924 valid
= sym
->getLocale(ULOC_VALID_LOCALE
, ec
);
1925 actual
= sym
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1926 if (U_FAILURE(ec
)) {
1927 errln("FAIL: DecimalFormatSymbols::getLocale() failed");
1929 _checklocs("DecimalFormatSymbols", req
, valid
, actual
);
1936 // DateFormat, DateFormatSymbols
1937 #if !UCONFIG_NO_FORMATTING
1939 UErrorCode ec
= U_ZERO_ERROR
; // give each resource type its own error code
1940 req
= "de_CH_LUCERNE";
1942 DateFormat::createDateInstance(DateFormat::kDefault
,
1943 Locale::createFromName(req
));
1945 dataerrln("Error calling DateFormat::createDateInstance()");
1947 SimpleDateFormat
* dat
= dynamic_cast<SimpleDateFormat
*>(df
);
1949 errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat");
1952 valid
= dat
->getLocale(ULOC_VALID_LOCALE
, ec
);
1953 actual
= dat
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1954 if (U_FAILURE(ec
)) {
1955 errln("FAIL: SimpleDateFormat::getLocale() failed");
1957 _checklocs("SimpleDateFormat", req
, valid
, actual
);
1960 const DateFormatSymbols
* sym
= dat
->getDateFormatSymbols();
1962 errln("FAIL: getDateFormatSymbols returned NULL");
1965 valid
= sym
->getLocale(ULOC_VALID_LOCALE
, ec
);
1966 actual
= sym
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1967 if (U_FAILURE(ec
)) {
1968 errln("FAIL: DateFormatSymbols::getLocale() failed");
1970 _checklocs("DateFormatSymbols", req
, valid
, actual
);
1978 #if !UCONFIG_NO_BREAK_ITERATION
1980 UErrorCode ec
= U_ZERO_ERROR
; // give each resource type its own error code
1981 req
= "es_ES_BARCELONA";
1982 reqLoc
= Locale::createFromName(req
);
1983 BreakIterator
* brk
= BreakIterator::createWordInstance(reqLoc
, ec
);
1984 if (U_FAILURE(ec
)) {
1985 dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec
));
1987 valid
= brk
->getLocale(ULOC_VALID_LOCALE
, ec
);
1988 actual
= brk
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
1989 if (U_FAILURE(ec
)) {
1990 errln("FAIL: BreakIterator::getLocale() failed");
1992 _checklocs("BreakIterator", req
, valid
, actual
);
1995 // After registering something, the behavior should be different
1996 URegistryKey key
= BreakIterator::registerInstance(brk
, reqLoc
, UBRK_WORD
, ec
);
1997 brk
= 0; // registerInstance adopts
1998 if (U_FAILURE(ec
)) {
1999 errln("FAIL: BreakIterator::registerInstance() failed");
2001 brk
= BreakIterator::createWordInstance(reqLoc
, ec
);
2002 if (U_FAILURE(ec
)) {
2003 errln("FAIL: BreakIterator::createWordInstance failed");
2005 valid
= brk
->getLocale(ULOC_VALID_LOCALE
, ec
);
2006 actual
= brk
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
2007 if (U_FAILURE(ec
)) {
2008 errln("FAIL: BreakIterator::getLocale() failed");
2010 // N.B.: now expect valid==actual==req
2011 _checklocs("BreakIterator(registered)",
2012 req
, valid
, actual
, "eq", "eq");
2015 // No matter what, unregister
2016 BreakIterator::unregister(key
, ec
);
2017 if (U_FAILURE(ec
)) {
2018 errln("FAIL: BreakIterator::unregister() failed");
2024 // After unregistering, should behave normally again
2025 brk
= BreakIterator::createWordInstance(reqLoc
, ec
);
2026 if (U_FAILURE(ec
)) {
2027 errln("FAIL: BreakIterator::createWordInstance failed");
2029 valid
= brk
->getLocale(ULOC_VALID_LOCALE
, ec
);
2030 actual
= brk
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
2031 if (U_FAILURE(ec
)) {
2032 errln("FAIL: BreakIterator::getLocale() failed");
2034 _checklocs("BreakIterator(unregistered)", req
, valid
, actual
);
2043 #if !UCONFIG_NO_COLLATION
2045 UErrorCode ec
= U_ZERO_ERROR
; // give each resource type its own error code
2047 checkRegisteredCollators(NULL
); // Don't expect any extras
2049 req
= "hi_IN_BHOPAL";
2050 reqLoc
= Locale::createFromName(req
);
2051 Collator
* coll
= Collator::createInstance(reqLoc
, ec
);
2052 if (U_FAILURE(ec
)) {
2053 dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec
));
2055 valid
= coll
->getLocale(ULOC_VALID_LOCALE
, ec
);
2056 actual
= coll
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
2057 if (U_FAILURE(ec
)) {
2058 errln("FAIL: Collator::getLocale() failed");
2060 _checklocs("Collator", req
, valid
, actual
);
2063 // After registering something, the behavior should be different
2064 URegistryKey key
= Collator::registerInstance(coll
, reqLoc
, ec
);
2065 coll
= 0; // registerInstance adopts
2066 if (U_FAILURE(ec
)) {
2067 errln("FAIL: Collator::registerInstance() failed");
2069 coll
= Collator::createInstance(reqLoc
, ec
);
2070 if (U_FAILURE(ec
)) {
2071 errln("FAIL: Collator::createWordInstance failed");
2073 valid
= coll
->getLocale(ULOC_VALID_LOCALE
, ec
);
2074 actual
= coll
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
2075 if (U_FAILURE(ec
)) {
2076 errln("FAIL: Collator::getLocale() failed");
2078 // N.B.: now expect valid==actual==req
2079 _checklocs("Collator(registered)",
2080 req
, valid
, actual
, "eq", "eq");
2083 checkRegisteredCollators(req
); // include hi_IN_BHOPAL
2085 // No matter what, unregister
2086 Collator::unregister(key
, ec
);
2087 if (U_FAILURE(ec
)) {
2088 errln("FAIL: Collator::unregister() failed");
2094 // After unregistering, should behave normally again
2095 coll
= Collator::createInstance(reqLoc
, ec
);
2096 if (U_FAILURE(ec
)) {
2097 errln("FAIL: Collator::createInstance failed");
2099 valid
= coll
->getLocale(ULOC_VALID_LOCALE
, ec
);
2100 actual
= coll
->getLocale(ULOC_ACTUAL_LOCALE
, ec
);
2101 if (U_FAILURE(ec
)) {
2102 errln("FAIL: Collator::getLocale() failed");
2104 _checklocs("Collator(unregistered)", req
, valid
, actual
);
2110 checkRegisteredCollators(NULL
); // extra should be gone again
2116 #if !UCONFIG_NO_COLLATION
2118 * Compare Collator::getAvailableLocales(int) [ "old", returning an array ]
2119 * with Collator::getAvailableLocales() [ "new", returning a StringEnumeration ]
2120 * These should be identical (check their API docs) EXCEPT that
2121 * if expectExtra is non-NULL, it will be in the "new" array but not "old".
2122 * Does not return any status but calls errln on error.
2123 * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL.
2125 void LocaleTest::checkRegisteredCollators(const char *expectExtra
) {
2126 UErrorCode status
= U_ZERO_ERROR
;
2127 int32_t count1
=0,count2
=0;
2128 Hashtable
oldHash(status
);
2129 Hashtable
newHash(status
);
2130 TEST_ASSERT_STATUS(status
);
2132 UnicodeString
expectStr(expectExtra
?expectExtra
:"n/a", "");
2134 // the 'old' list (non enumeration)
2135 const Locale
* oldList
= Collator::getAvailableLocales(count1
);
2136 if(oldList
== NULL
) {
2137 dataerrln("Error: Collator::getAvailableLocales(count) returned NULL");
2141 // the 'new' list (enumeration)
2142 LocalPointer
<StringEnumeration
> newEnum(Collator::getAvailableLocales());
2143 if(newEnum
.isNull()) {
2144 errln("Error: collator::getAvailableLocales() returned NULL");
2148 // OK. Let's add all of the OLD
2149 // then check for any in the NEW not in OLD
2150 // then check for any in OLD not in NEW.
2152 // 1. add all of OLD
2153 for(int32_t i
=0;i
<count1
;i
++) {
2154 const UnicodeString
key(oldList
[i
].getName(), "");
2155 int32_t oldI
= oldHash
.puti(key
, 1, status
);
2157 errln("Error: duplicate key %s in Collator::getAvailableLocales(count) list.\n",
2158 oldList
[i
].getName());
2161 if(expectExtra
!= NULL
&& !strcmp(expectExtra
, oldList
[i
].getName())) {
2162 errln("Inexplicably, Collator::getAvailableCollators(count) had registered collator %s. This shouldn't happen, so I am going to consider it an error.\n", expectExtra
);
2166 // 2. add all of NEW
2167 const UnicodeString
*locStr
;
2168 UBool foundExpected
= FALSE
;
2169 while((locStr
= newEnum
->snext(status
)) && U_SUCCESS(status
)) {
2172 if(expectExtra
!= NULL
&& expectStr
== *locStr
) {
2173 foundExpected
= TRUE
;
2174 logln(UnicodeString("Found expected registered collator: ","") + expectStr
);
2176 (void)foundExpected
; // Hush unused variable compiler warning.
2178 if( oldHash
.geti(*locStr
) == 0 ) {
2179 if(expectExtra
!= NULL
&& expectStr
==*locStr
) {
2180 logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr
);
2182 errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","")
2186 newHash
.puti(*locStr
, 1, status
);
2189 // 3. check all of OLD again
2190 for(int32_t i
=0;i
<count1
;i
++) {
2191 const UnicodeString
key(oldList
[i
].getName(), "");
2192 int32_t newI
= newHash
.geti(key
);
2194 errln(UnicodeString("Error: Collator::getAvailableLocales() is missing: ","")
2199 int32_t expectCount2
= count1
;
2200 if(expectExtra
!= NULL
) {
2201 expectCount2
++; // if an extra item registered, bump the expect count
2204 assertEquals("Collator::getAvail() count", expectCount2
, count2
);
2210 void LocaleTest::TestVariantWithOutCountry(void) {
2211 Locale
loc("en","","POSIX");
2212 if (0 != strcmp(loc
.getVariant(), "POSIX")) {
2213 errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc
.getName(), "POSIX", loc
.getVariant());
2215 Locale
loc2("en","","FOUR");
2216 if (0 != strcmp(loc2
.getVariant(), "FOUR")) {
2217 errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2
.getName(), "FOUR", loc2
.getVariant());
2219 Locale
loc3("en","Latn","","FOUR");
2220 if (0 != strcmp(loc3
.getVariant(), "FOUR")) {
2221 errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3
.getName(), "FOUR", loc3
.getVariant());
2223 Locale
loc4("","Latn","","FOUR");
2224 if (0 != strcmp(loc4
.getVariant(), "FOUR")) {
2225 errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4
.getName(), "FOUR", loc4
.getVariant());
2227 Locale
loc5("","Latn","US","FOUR");
2228 if (0 != strcmp(loc5
.getVariant(), "FOUR")) {
2229 errln("FAIL: _Latn_US_FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc5
.getName(), "FOUR", loc5
.getVariant());
2231 Locale
loc6("de-1901");
2232 if (0 != strcmp(loc6
.getVariant(), "1901")) {
2233 errln("FAIL: de-1901 didn't get parsed correctly - name is %s - expected %s got %s", loc6
.getName(), "1901", loc6
.getVariant());
2237 static Locale
_canonicalize(int32_t selector
, /* 0==createFromName, 1==createCanonical, 2==Locale ct */
2238 const char* localeID
) {
2241 return Locale::createFromName(localeID
);
2243 return Locale::createCanonical(localeID
);
2245 return Locale(localeID
);
2251 void LocaleTest::TestCanonicalization(void)
2253 static const struct {
2254 const char *localeID
; /* input */
2255 const char *getNameID
; /* expected getName() result */
2256 const char *canonicalID
; /* expected canonicalize() result */
2258 { "", "", "en_US_POSIX" },
2259 { "C", "c", "en_US_POSIX" },
2260 { "POSIX", "posix", "en_US_POSIX" },
2261 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2262 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2263 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2264 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
2265 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
2266 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
2267 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2268 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2269 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2270 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2271 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2272 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2273 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2274 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2275 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2276 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2277 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2278 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2279 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2280 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2281 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2282 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2283 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2284 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2285 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2286 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2287 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2288 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2289 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2290 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2291 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2292 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2293 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2294 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2295 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2296 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2297 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2298 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2299 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2300 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2301 // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS
2302 // TODO: unify this behavior
2303 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2304 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2305 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2306 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2307 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2308 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2309 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2310 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2311 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2312 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2314 /* posix behavior that used to be performed by getName */
2315 { "mr.utf8", "mr.utf8", "mr" },
2316 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2317 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2318 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2319 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2320 { "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 */
2322 /* fleshing out canonicalization */
2323 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2324 { "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" },
2325 /* already-canonical ids are not changed */
2326 { "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" },
2327 /* PRE_EURO and EURO conversions don't affect other keywords */
2328 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2329 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2330 /* currency keyword overrides PRE_EURO and EURO currency */
2331 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2332 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2333 /* norwegian is just too weird, if we handle things in their full generality */
2334 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2336 /* test cases reflecting internal resource bundle usage */
2337 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2338 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2339 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }
2342 static const char* label
[] = { "createFromName", "createCanonical", "Locale" };
2346 for (i
=0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2347 for (j
=0; j
<3; ++j
) {
2348 const char* expected
= (j
==1) ? testCases
[i
].canonicalID
: testCases
[i
].getNameID
;
2349 Locale loc
= _canonicalize(j
, testCases
[i
].localeID
);
2350 const char* getName
= loc
.isBogus() ? "BOGUS" : loc
.getName();
2351 if(uprv_strcmp(expected
, getName
) != 0) {
2352 errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"",
2353 label
[j
], testCases
[i
].localeID
, getName
, expected
);
2355 logln("Ok: %s(%s) => \"%s\"",
2356 label
[j
], testCases
[i
].localeID
, getName
);
2362 void LocaleTest::TestCurrencyByDate(void)
2364 #if !UCONFIG_NO_FORMATTING
2365 UErrorCode status
= U_ZERO_ERROR
;
2366 UDate date
= uprv_getUTCtime();
2370 UnicodeString tempStr
, resultStr
;
2372 // Cycle through historical currencies
2373 date
= (UDate
)-630720000000.0; // pre 1961 - no currency defined
2374 index
= ucurr_countCurrencies("eo_AM", date
, &status
);
2377 errcheckln(status
, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status
));
2379 resLen
= ucurr_forLocaleAndDate("eo_AM", date
, index
, TMP
, 4, &status
);
2381 errcheckln(status
, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status
));
2383 status
= U_ZERO_ERROR
;
2385 date
= (UDate
)0.0; // 1970 - one currency defined
2386 index
= ucurr_countCurrencies("eo_AM", date
, &status
);
2389 errcheckln(status
, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status
));
2391 resLen
= ucurr_forLocaleAndDate("eo_AM", date
, index
, TMP
, 4, &status
);
2393 resultStr
.setTo("SUR");
2394 if (resultStr
!= tempStr
) {
2395 errcheckln(status
, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status
));
2398 date
= (UDate
)693792000000.0; // 1992 - one currency defined
2399 index
= ucurr_countCurrencies("eo_AM", date
, &status
);
2402 errcheckln(status
, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status
));
2404 resLen
= ucurr_forLocaleAndDate("eo_AM", date
, index
, TMP
, 4, &status
);
2406 resultStr
.setTo("RUR");
2407 if (resultStr
!= tempStr
) {
2408 errcheckln(status
, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status
));
2411 date
= (UDate
)977616000000.0; // post 1993 - one currency defined
2412 index
= ucurr_countCurrencies("eo_AM", date
, &status
);
2415 errcheckln(status
, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status
));
2417 resLen
= ucurr_forLocaleAndDate("eo_AM", date
, index
, TMP
, 4, &status
);
2419 resultStr
.setTo("AMD");
2420 if (resultStr
!= tempStr
) {
2421 errcheckln(status
, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status
));
2424 // Locale AD has multiple currencies at once
2425 date
= (UDate
)977616000000.0; // year 2001
2426 index
= ucurr_countCurrencies("eo_AD", date
, &status
);
2429 errcheckln(status
, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status
));
2431 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 1, TMP
, 4, &status
);
2433 resultStr
.setTo("EUR");
2434 if (resultStr
!= tempStr
) {
2435 errcheckln(status
, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status
));
2437 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 2, TMP
, 4, &status
);
2439 resultStr
.setTo("ESP");
2440 if (resultStr
!= tempStr
) {
2441 errcheckln(status
, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status
));
2443 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 3, TMP
, 4, &status
);
2445 resultStr
.setTo("FRF");
2446 if (resultStr
!= tempStr
) {
2447 errcheckln(status
, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status
));
2449 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 4, TMP
, 4, &status
);
2451 resultStr
.setTo("ADP");
2452 if (resultStr
!= tempStr
) {
2453 errcheckln(status
, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status
));
2456 date
= (UDate
)0.0; // year 1970
2457 index
= ucurr_countCurrencies("eo_AD", date
, &status
);
2460 errcheckln(status
, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status
));
2462 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 1, TMP
, 4, &status
);
2464 resultStr
.setTo("ESP");
2465 if (resultStr
!= tempStr
) {
2466 errcheckln(status
, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status
));
2468 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 2, TMP
, 4, &status
);
2470 resultStr
.setTo("FRF");
2471 if (resultStr
!= tempStr
) {
2472 errcheckln(status
, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status
));
2474 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 3, TMP
, 4, &status
);
2476 resultStr
.setTo("ADP");
2477 if (resultStr
!= tempStr
) {
2478 errcheckln(status
, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status
));
2481 date
= (UDate
)-630720000000.0; // year 1950
2482 index
= ucurr_countCurrencies("eo_AD", date
, &status
);
2485 errcheckln(status
, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status
));
2487 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 1, TMP
, 4, &status
);
2489 resultStr
.setTo("ESP");
2490 if (resultStr
!= tempStr
) {
2491 errcheckln(status
, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status
));
2493 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 2, TMP
, 4, &status
);
2495 resultStr
.setTo("ADP");
2496 if (resultStr
!= tempStr
) {
2497 errcheckln(status
, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status
));
2500 date
= (UDate
)-2207520000000.0; // year 1900
2501 index
= ucurr_countCurrencies("eo_AD", date
, &status
);
2504 errcheckln(status
, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status
));
2506 resLen
= ucurr_forLocaleAndDate("eo_AD", date
, 1, TMP
, 4, &status
);
2508 resultStr
.setTo("ESP");
2509 if (resultStr
!= tempStr
) {
2510 errcheckln(status
, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status
));
2513 // Locale UA has gap between years 1994 - 1996
2514 date
= (UDate
)788400000000.0;
2515 index
= ucurr_countCurrencies("eo_UA", date
, &status
);
2518 errcheckln(status
, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status
));
2520 resLen
= ucurr_forLocaleAndDate("eo_UA", date
, index
, TMP
, 4, &status
);
2522 errcheckln(status
, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status
));
2524 status
= U_ZERO_ERROR
;
2526 // Test index bounds
2527 resLen
= ucurr_forLocaleAndDate("eo_UA", date
, 100, TMP
, 4, &status
);
2529 errcheckln(status
, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status
));
2531 status
= U_ZERO_ERROR
;
2533 resLen
= ucurr_forLocaleAndDate("eo_UA", date
, 0, TMP
, 4, &status
);
2535 errcheckln(status
, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status
));
2537 status
= U_ZERO_ERROR
;
2539 // Test for bogus locale
2540 index
= ucurr_countCurrencies("eo_QQ", date
, &status
);
2543 errcheckln(status
, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status
));
2545 status
= U_ZERO_ERROR
;
2546 resLen
= ucurr_forLocaleAndDate("eo_QQ", date
, 1, TMP
, 4, &status
);
2548 errcheckln(status
, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status
));
2550 status
= U_ZERO_ERROR
;
2551 resLen
= ucurr_forLocaleAndDate("eo_QQ", date
, 0, TMP
, 4, &status
);
2553 errcheckln(status
, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status
));
2555 status
= U_ZERO_ERROR
;
2557 // Cycle through histrocial currencies
2558 date
= (UDate
)977616000000.0; // 2001 - one currency
2559 index
= ucurr_countCurrencies("eo_AO", date
, &status
);
2562 errcheckln(status
, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status
));
2564 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 1, TMP
, 4, &status
);
2566 resultStr
.setTo("AOA");
2567 if (resultStr
!= tempStr
) {
2568 errcheckln(status
, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status
));
2571 date
= (UDate
)819936000000.0; // 1996 - 2 currencies
2572 index
= ucurr_countCurrencies("eo_AO", date
, &status
);
2575 errcheckln(status
, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status
));
2577 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 1, TMP
, 4, &status
);
2579 resultStr
.setTo("AOR");
2580 if (resultStr
!= tempStr
) {
2581 errcheckln(status
, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status
));
2583 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 2, TMP
, 4, &status
);
2585 resultStr
.setTo("AON");
2586 if (resultStr
!= tempStr
) {
2587 errcheckln(status
, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status
));
2590 date
= (UDate
)662256000000.0; // 1991 - 2 currencies
2591 index
= ucurr_countCurrencies("eo_AO", date
, &status
);
2594 errcheckln(status
, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status
));
2596 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 1, TMP
, 4, &status
);
2598 resultStr
.setTo("AON");
2599 if (resultStr
!= tempStr
) {
2600 errcheckln(status
, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status
));
2602 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 2, TMP
, 4, &status
);
2604 resultStr
.setTo("AOK");
2605 if (resultStr
!= tempStr
) {
2606 errcheckln(status
, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status
));
2609 date
= (UDate
)315360000000.0; // 1980 - one currency
2610 index
= ucurr_countCurrencies("eo_AO", date
, &status
);
2613 errcheckln(status
, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status
));
2615 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 1, TMP
, 4, &status
);
2617 resultStr
.setTo("AOK");
2618 if (resultStr
!= tempStr
) {
2619 errcheckln(status
, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status
));
2622 date
= (UDate
)0.0; // 1970 - no currencies
2623 index
= ucurr_countCurrencies("eo_AO", date
, &status
);
2626 errcheckln(status
, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status
));
2628 resLen
= ucurr_forLocaleAndDate("eo_AO", date
, 1, TMP
, 4, &status
);
2630 errcheckln(status
, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status
));
2632 status
= U_ZERO_ERROR
;
2634 // Test with currency keyword override
2635 date
= (UDate
)977616000000.0; // 2001 - two currencies
2636 index
= ucurr_countCurrencies("eo_DE@currency=DEM", date
, &status
);
2639 errcheckln(status
, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status
));
2641 resLen
= ucurr_forLocaleAndDate("eo_DE@currency=DEM", date
, 1, TMP
, 4, &status
);
2643 resultStr
.setTo("EUR");
2644 if (resultStr
!= tempStr
) {
2645 errcheckln(status
, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status
));
2647 resLen
= ucurr_forLocaleAndDate("eo_DE@currency=DEM", date
, 2, TMP
, 4, &status
);
2649 resultStr
.setTo("DEM");
2650 if (resultStr
!= tempStr
) {
2651 errcheckln(status
, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status
));
2654 // Test Euro Support
2655 status
= U_ZERO_ERROR
; // reset
2656 date
= uprv_getUTCtime();
2659 ucurr_forLocaleAndDate("en_US", date
, 1, USD
, 4, &status
);
2662 ucurr_forLocaleAndDate("ja_JP", date
, 1, YEN
, 4, &status
);
2664 ucurr_forLocaleAndDate("en_US", date
, 1, TMP
, 4, &status
);
2665 if (u_strcmp(USD
, TMP
) != 0) {
2666 errcheckln(status
, "Fail: en_US didn't return USD - %s", u_errorName(status
));
2668 ucurr_forLocaleAndDate("en_US_PREEURO", date
, 1, TMP
, 4, &status
);
2669 if (u_strcmp(USD
, TMP
) != 0) {
2670 errcheckln(status
, "Fail: en_US_PREEURO didn't fallback to en_US - %s", u_errorName(status
));
2672 ucurr_forLocaleAndDate("en_US_Q", date
, 1, TMP
, 4, &status
);
2673 if (u_strcmp(USD
, TMP
) != 0) {
2674 errcheckln(status
, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status
));
2676 status
= U_ZERO_ERROR
; // reset
2680 void LocaleTest::TestGetVariantWithKeywords(void)
2682 Locale
l("en_US_VALLEY@foo=value");
2683 const char *variant
= l
.getVariant();
2685 test_assert(strcmp("VALLEY", variant
) == 0);
2687 UErrorCode status
= U_ZERO_ERROR
;
2689 int32_t len
= l
.getKeywordValue("foo", buffer
, 50, status
);
2691 test_assert(strcmp("value", buffer
) == 0);
2694 void LocaleTest::TestIsRightToLeft() {
2695 assertFalse("root LTR", Locale::getRoot().isRightToLeft());
2696 assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
2697 assertTrue("ar RTL", Locale("ar").isRightToLeft());
2698 assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), FALSE
, TRUE
);
2699 assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
2700 assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
2701 assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), FALSE
, TRUE
); // Sorani Kurdish
2702 assertFalse("fil LTR", Locale("fil").isRightToLeft());
2703 assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
2706 void LocaleTest::TestBug11421() {
2707 Locale::getDefault().getBaseName();
2709 const Locale
*localeList
= Locale::getAvailableLocales(numLocales
);
2710 for (int localeIndex
= 0; localeIndex
< numLocales
; localeIndex
++) {
2711 const Locale
&loc
= localeList
[localeIndex
];
2712 if (strncmp(loc
.getName(), loc
.getBaseName(), strlen(loc
.getBaseName()))) {
2713 errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"",
2714 __FILE__
, __LINE__
, loc
.getName(), loc
.getBaseName());
2720 // TestBug13277. The failure manifests as valgrind errors.
2721 // See the trac ticket for details.
2724 void LocaleTest::TestBug13277() {
2725 UErrorCode status
= U_ZERO_ERROR
;
2726 CharString
name("en-us-x-foo", -1, status
);
2727 while (name
.length() < 152) {
2728 name
.append("-x-foo", -1, status
);
2731 while (name
.length() < 160) {
2732 name
.append('z', status
);
2733 Locale
loc(name
.data(), nullptr, nullptr, nullptr);
2737 // TestBug13554 Check for read past end of array in getPosixID().
2738 // The bug shows as an Address Sanitizer failure.
2740 void LocaleTest::TestBug13554() {
2741 UErrorCode status
= U_ZERO_ERROR
;
2742 const int BUFFER_SIZE
= 100;
2743 char posixID
[BUFFER_SIZE
];
2745 for (uint32_t hostid
= 0; hostid
< 0x500; ++hostid
) {
2746 status
= U_ZERO_ERROR
;
2747 uprv_convertToPosix(hostid
, posixID
, BUFFER_SIZE
, &status
);