1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9 #include <algorithm>
10 #include <functional>
11 #include <iterator>
12 #include <set>
13 #include <utility>
14
15 #include "loctest.h"
16 #include "unicode/localebuilder.h"
17 #include "unicode/localpointer.h"
18 #include "unicode/decimfmt.h"
19 #include "unicode/ucurr.h"
20 #include "unicode/smpdtfmt.h"
21 #include "unicode/strenum.h"
22 #include "unicode/dtfmtsym.h"
23 #include "unicode/brkiter.h"
24 #include "unicode/coll.h"
25 #include "unicode/ustring.h"
26 #include "unicode/std_string.h"
27 #include "charstr.h"
28 #include "cmemory.h"
29 #include "cstring.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include "putilimp.h"
33 #include "hash.h"
34 #include "locmap.h"
35 #include "uparse.h"
36 #include "ulocimp.h"
37
38 static const char* const rawData[33][8] = {
39
40 // language code
41 { "en", "fr", "ca", "el", "no", "it", "xx", "zh" },
42 // script code
43 { "", "", "", "", "", "", "", "Hans" },
44 // country code
45 { "US", "FR", "ES", "GR", "NO", "", "YY", "CN" },
46 // variant code
47 { "", "", "", "", "NY", "", "", "" },
48 // full name
49 { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "it", "xx_YY", "zh_Hans_CN" },
50 // ISO-3 language
51 { "eng", "fra", "cat", "ell", "nor", "ita", "", "zho" },
52 // ISO-3 country
53 { "USA", "FRA", "ESP", "GRC", "NOR", "", "", "CHN" },
54 // LCID
55 { "409", "40c", "403", "408", "814", "10", "0", "804" },
56
57 // display language (English)
58 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "Chinese" },
59 // display script (English)
60 { "", "", "", "", "", "", "", "Simplified Han" },
61 // display country (English)
62 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "China" },
63 // display variant (English)
64 { "", "", "", "", "NY", "", "", ""},
65 // display name (English)
66 // Updated no_NO_NY English display name for new pattern-based algorithm
67 // (part of Euro support).
68 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China)" },
69
70 // display language (French)
71 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" },
72 // display script (French)
73 { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" },
74 // display country (French)
75 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine" },
76 // display variant (French)
77 { "", "", "", "", "NY", "", "", "" },
78 // display name (French)
79 //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" },
80 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine)" },
81
82
83 /* display language (Catalan) */
84 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" },
85 /* display script (Catalan) */
86 { "", "", "", "", "", "", "", "han simplificat" },
87 /* display country (Catalan) */
88 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina" },
89 /* display variant (Catalan) */
90 { "", "", "", "", "NY", "", "" },
91 /* display name (Catalan) */
92 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina)" },
93
94 // display language (Greek)[actual values listed below]
95 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
96 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
97 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
98 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
99 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
100 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
101 "",
102 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC"
103 },
104 // display script (Greek)
105 { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" },
106 // display country (Greek)[actual values listed below]
107 { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
108 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
109 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
110 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
111 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
112 "",
113 "",
114 "\\u039A\\u03AF\\u03BD\\u03B1"
115 },
116 // display variant (Greek)
117 { "", "", "", "", "NY", "", "" },
118 // display name (Greek)[actual values listed below]
119 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
120 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
121 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
122 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
123 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
124 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
125 "",
126 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)"
127 },
128
129 // display language (<root>)
130 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "" },
131 // display script (<root>)
132 { "", "", "", "", "", "", "", ""},
133 // display country (<root>)
134 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "" },
135 // display variant (<root>)
136 { "", "", "", "", "Nynorsk", "", "", ""},
137 // display name (<root>)
138 //{ "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
139 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,NY)", "Italian", "xx (YY)", "" }
140 };
141
142
143 /*
144 Usage:
145 test_assert( Test (should be true) )
146
147 Example:
148 test_assert(i==3);
149
150 the macro is ugly but makes the tests pretty.
151 */
152
153 #define test_assert(test) UPRV_BLOCK_MACRO_BEGIN { \
154 if(!(test)) \
155 errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \
156 else \
157 logln("PASS: asserted " #test); \
158 } UPRV_BLOCK_MACRO_END
159
160 /*
161 Usage:
162 test_assert_print( Test (should be true), printable )
163
164 Example:
165 test_assert(i==3, toString(i));
166
167 the macro is ugly but makes the tests pretty.
168 */
169
170 #define test_assert_print(test,print) UPRV_BLOCK_MACRO_BEGIN { \
171 if(!(test)) \
172 errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \
173 else \
174 logln("PASS: asserted " #test "-> " + UnicodeString(print)); \
175 } UPRV_BLOCK_MACRO_END
176
177
178 #define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \
179 logln(#l " = " + UnicodeString(l.getName(), "")); \
180 } UPRV_BLOCK_MACRO_END
181
LocaleTest()182 LocaleTest::LocaleTest()
183 : dataTable(NULL)
184 {
185 setUpDataTable();
186 }
187
~LocaleTest()188 LocaleTest::~LocaleTest()
189 {
190 if (dataTable != 0) {
191 for (int32_t i = 0; i < 33; i++) {
192 delete []dataTable[i];
193 }
194 delete []dataTable;
195 dataTable = 0;
196 }
197 }
198
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)199 void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
200 {
201 TESTCASE_AUTO_BEGIN;
202 TESTCASE_AUTO(TestBug11421); // Must run early in list to trigger failure.
203 TESTCASE_AUTO(TestBasicGetters);
204 TESTCASE_AUTO(TestSimpleResourceInfo);
205 TESTCASE_AUTO(TestDisplayNames);
206 TESTCASE_AUTO(TestSimpleObjectStuff);
207 TESTCASE_AUTO(TestPOSIXParsing);
208 TESTCASE_AUTO(TestGetAvailableLocales);
209 TESTCASE_AUTO(TestDataDirectory);
210 TESTCASE_AUTO(TestISO3Fallback);
211 TESTCASE_AUTO(TestGetLangsAndCountries);
212 TESTCASE_AUTO(TestSimpleDisplayNames);
213 TESTCASE_AUTO(TestUninstalledISO3Names);
214 TESTCASE_AUTO(TestAtypicalLocales);
215 #if !UCONFIG_NO_FORMATTING
216 TESTCASE_AUTO(TestThaiCurrencyFormat);
217 TESTCASE_AUTO(TestEuroSupport);
218 #endif
219 TESTCASE_AUTO(TestToString);
220 #if !UCONFIG_NO_FORMATTING
221 TESTCASE_AUTO(Test4139940);
222 TESTCASE_AUTO(Test4143951);
223 #endif
224 TESTCASE_AUTO(Test4147315);
225 TESTCASE_AUTO(Test4147317);
226 TESTCASE_AUTO(Test4147552);
227 TESTCASE_AUTO(TestVariantParsing);
228 TESTCASE_AUTO(Test20639_DeprecatesISO3Language);
229 #if !UCONFIG_NO_FORMATTING
230 TESTCASE_AUTO(Test4105828);
231 #endif
232 TESTCASE_AUTO(TestSetIsBogus);
233 TESTCASE_AUTO(TestParallelAPIValues);
234 TESTCASE_AUTO(TestAddLikelySubtags);
235 TESTCASE_AUTO(TestMinimizeSubtags);
236 TESTCASE_AUTO(TestAddLikelyAndMinimizeSubtags);
237 TESTCASE_AUTO(TestKeywordVariants);
238 TESTCASE_AUTO(TestCreateUnicodeKeywords);
239 TESTCASE_AUTO(TestKeywordVariantParsing);
240 TESTCASE_AUTO(TestCreateKeywordSet);
241 TESTCASE_AUTO(TestCreateKeywordSetEmpty);
242 TESTCASE_AUTO(TestCreateKeywordSetWithPrivateUse);
243 TESTCASE_AUTO(TestCreateUnicodeKeywordSet);
244 TESTCASE_AUTO(TestCreateUnicodeKeywordSetEmpty);
245 TESTCASE_AUTO(TestCreateUnicodeKeywordSetWithPrivateUse);
246 TESTCASE_AUTO(TestGetKeywordValueStdString);
247 TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString);
248 TESTCASE_AUTO(TestSetKeywordValue);
249 TESTCASE_AUTO(TestSetKeywordValueStringPiece);
250 TESTCASE_AUTO(TestSetUnicodeKeywordValueStringPiece);
251 TESTCASE_AUTO(TestGetBaseName);
252 #if !UCONFIG_NO_FILE_IO
253 TESTCASE_AUTO(TestGetLocale);
254 #endif
255 TESTCASE_AUTO(TestVariantWithOutCountry);
256 TESTCASE_AUTO(TestCanonicalization);
257 TESTCASE_AUTO(TestCurrencyByDate);
258 TESTCASE_AUTO(TestGetVariantWithKeywords);
259 TESTCASE_AUTO(TestIsRightToLeft);
260 TESTCASE_AUTO(TestBug13277);
261 TESTCASE_AUTO(TestBug13554);
262 TESTCASE_AUTO(TestBug20410);
263 TESTCASE_AUTO(TestBug20900);
264 TESTCASE_AUTO(TestLocaleCanonicalizationFromFile);
265 TESTCASE_AUTO(TestKnownCanonicalizedListCorrect);
266 TESTCASE_AUTO(TestConstructorAcceptsBCP47);
267 TESTCASE_AUTO(TestForLanguageTag);
268 TESTCASE_AUTO(TestForLanguageTagLegacyTagBug21676);
269 TESTCASE_AUTO(TestToLanguageTag);
270 TESTCASE_AUTO(TestToLanguageTagOmitTrue);
271 TESTCASE_AUTO(TestMoveAssign);
272 TESTCASE_AUTO(TestMoveCtor);
273 TESTCASE_AUTO(TestBug20407iVariantPreferredValue);
274 TESTCASE_AUTO(TestBug13417VeryLongLanguageTag);
275 TESTCASE_AUTO(TestBug11053UnderlineTimeZone);
276 TESTCASE_AUTO(TestUnd);
277 TESTCASE_AUTO(TestUndScript);
278 TESTCASE_AUTO(TestUndRegion);
279 TESTCASE_AUTO(TestUndCAPI);
280 TESTCASE_AUTO(TestRangeIterator);
281 TESTCASE_AUTO(TestPointerConvertingIterator);
282 TESTCASE_AUTO(TestTagConvertingIterator);
283 TESTCASE_AUTO(TestCapturingTagConvertingIterator);
284 TESTCASE_AUTO(TestSetUnicodeKeywordValueInLongLocale);
285 TESTCASE_AUTO(TestSetUnicodeKeywordValueNullInLongLocale);
286 TESTCASE_AUTO(TestCanonicalize);
287 TESTCASE_AUTO(TestLeak21419);
288 TESTCASE_AUTO(TestNullDereferenceWrite21597);
289 TESTCASE_AUTO(TestLongLocaleSetKeywordAssign);
290 TESTCASE_AUTO(TestLongLocaleSetKeywordMoveAssign);
291 #if !UCONFIG_NO_FORMATTING
292 TESTCASE_AUTO(TestSierraLeoneCurrency21997);
293 #endif
294 TESTCASE_AUTO_END;
295 }
296
TestBasicGetters()297 void LocaleTest::TestBasicGetters() {
298 UnicodeString temp;
299
300 int32_t i;
301 for (i = 0; i <= MAX_LOCALES; i++) {
302 Locale testLocale("");
303 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
304 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
305 }
306 else {
307 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
308 }
309 logln("Testing " + (UnicodeString)testLocale.getName() + "...");
310
311 if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
312 errln(" Language code mismatch: " + temp + " versus "
313 + dataTable[LANG][i]);
314 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
315 errln(" Script code mismatch: " + temp + " versus "
316 + dataTable[SCRIPT][i]);
317 if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
318 errln(" Country code mismatch: " + temp + " versus "
319 + dataTable[CTRY][i]);
320 if ( (temp=testLocale.getVariant()) != (dataTable[VAR][i]))
321 errln(" Variant code mismatch: " + temp + " versus "
322 + dataTable[VAR][i]);
323 if ( (temp=testLocale.getName()) != (dataTable[NAME][i]))
324 errln(" Locale name mismatch: " + temp + " versus "
325 + dataTable[NAME][i]);
326 }
327
328 logln("Same thing without variant codes...");
329 for (i = 0; i <= MAX_LOCALES; i++) {
330 Locale testLocale("");
331 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
332 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i]);
333 }
334 else {
335 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i]);
336 }
337 logln("Testing " + (temp=testLocale.getName()) + "...");
338
339 if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
340 errln("Language code mismatch: " + temp + " versus "
341 + dataTable[LANG][i]);
342 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
343 errln("Script code mismatch: " + temp + " versus "
344 + dataTable[SCRIPT][i]);
345 if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
346 errln("Country code mismatch: " + temp + " versus "
347 + dataTable[CTRY][i]);
348 if (testLocale.getVariant()[0] != 0)
349 errln("Variant code mismatch: something versus \"\"");
350 }
351
352 logln("Testing long language names and getters");
353 Locale test8 = Locale::createFromName("x-klingon-latn-zx.utf32be@special");
354
355 temp = test8.getLanguage();
356 if (temp != UnicodeString("x-klingon") )
357 errln("Language code mismatch: " + temp + " versus \"x-klingon\"");
358
359 temp = test8.getScript();
360 if (temp != UnicodeString("Latn") )
361 errln("Script code mismatch: " + temp + " versus \"Latn\"");
362
363 temp = test8.getCountry();
364 if (temp != UnicodeString("ZX") )
365 errln("Country code mismatch: " + temp + " versus \"ZX\"");
366
367 temp = test8.getVariant();
368 //if (temp != UnicodeString("SPECIAL") )
369 // errln("Variant code mismatch: " + temp + " versus \"SPECIAL\"");
370 // As of 3.0, the "@special" will *not* be parsed by uloc_getName()
371 if (temp != UnicodeString("") )
372 errln("Variant code mismatch: " + temp + " versus \"\"");
373
374 if (Locale::getDefault() != Locale::createFromName(NULL))
375 errln("Locale::getDefault() == Locale::createFromName(NULL)");
376
377 /*----------*/
378 // NOTE: There used to be a special test for locale names that had language or
379 // country codes that were longer than two letters. The new version of Locale
380 // doesn't support anything that isn't an officially recognized language or
381 // country code, so we no longer support this feature.
382
383 Locale bogusLang("THISISABOGUSLANGUAGE"); // Jitterbug 2864: language code too long
384 if(!bogusLang.isBogus()) {
385 errln("Locale(\"THISISABOGUSLANGUAGE\").isBogus()==false");
386 }
387
388 bogusLang=Locale("eo");
389 if( bogusLang.isBogus() ||
390 strcmp(bogusLang.getLanguage(), "eo")!=0 ||
391 *bogusLang.getCountry()!=0 ||
392 *bogusLang.getVariant()!=0 ||
393 strcmp(bogusLang.getName(), "eo")!=0
394 ) {
395 errln("assignment to bogus Locale does not unbogus it or sets bad data");
396 }
397
398 Locale a("eo_DE@currency=DEM");
399 Locale *pb=a.clone();
400 if(pb==&a || *pb!=a) {
401 errln("Locale.clone() failed");
402 }
403 delete pb;
404 }
405
TestParallelAPIValues()406 void LocaleTest::TestParallelAPIValues() {
407 logln("Test synchronization between C and C++ API");
408 if (strcmp(Locale::getChinese().getName(), ULOC_CHINESE) != 0) {
409 errln("Differences for ULOC_CHINESE Locale");
410 }
411 if (strcmp(Locale::getEnglish().getName(), ULOC_ENGLISH) != 0) {
412 errln("Differences for ULOC_ENGLISH Locale");
413 }
414 if (strcmp(Locale::getFrench().getName(), ULOC_FRENCH) != 0) {
415 errln("Differences for ULOC_FRENCH Locale");
416 }
417 if (strcmp(Locale::getGerman().getName(), ULOC_GERMAN) != 0) {
418 errln("Differences for ULOC_GERMAN Locale");
419 }
420 if (strcmp(Locale::getItalian().getName(), ULOC_ITALIAN) != 0) {
421 errln("Differences for ULOC_ITALIAN Locale");
422 }
423 if (strcmp(Locale::getJapanese().getName(), ULOC_JAPANESE) != 0) {
424 errln("Differences for ULOC_JAPANESE Locale");
425 }
426 if (strcmp(Locale::getKorean().getName(), ULOC_KOREAN) != 0) {
427 errln("Differences for ULOC_KOREAN Locale");
428 }
429 if (strcmp(Locale::getSimplifiedChinese().getName(), ULOC_SIMPLIFIED_CHINESE) != 0) {
430 errln("Differences for ULOC_SIMPLIFIED_CHINESE Locale");
431 }
432 if (strcmp(Locale::getTraditionalChinese().getName(), ULOC_TRADITIONAL_CHINESE) != 0) {
433 errln("Differences for ULOC_TRADITIONAL_CHINESE Locale");
434 }
435
436
437 if (strcmp(Locale::getCanada().getName(), ULOC_CANADA) != 0) {
438 errln("Differences for ULOC_CANADA Locale");
439 }
440 if (strcmp(Locale::getCanadaFrench().getName(), ULOC_CANADA_FRENCH) != 0) {
441 errln("Differences for ULOC_CANADA_FRENCH Locale");
442 }
443 if (strcmp(Locale::getChina().getName(), ULOC_CHINA) != 0) {
444 errln("Differences for ULOC_CHINA Locale");
445 }
446 if (strcmp(Locale::getPRC().getName(), ULOC_PRC) != 0) {
447 errln("Differences for ULOC_PRC Locale");
448 }
449 if (strcmp(Locale::getFrance().getName(), ULOC_FRANCE) != 0) {
450 errln("Differences for ULOC_FRANCE Locale");
451 }
452 if (strcmp(Locale::getGermany().getName(), ULOC_GERMANY) != 0) {
453 errln("Differences for ULOC_GERMANY Locale");
454 }
455 if (strcmp(Locale::getItaly().getName(), ULOC_ITALY) != 0) {
456 errln("Differences for ULOC_ITALY Locale");
457 }
458 if (strcmp(Locale::getJapan().getName(), ULOC_JAPAN) != 0) {
459 errln("Differences for ULOC_JAPAN Locale");
460 }
461 if (strcmp(Locale::getKorea().getName(), ULOC_KOREA) != 0) {
462 errln("Differences for ULOC_KOREA Locale");
463 }
464 if (strcmp(Locale::getTaiwan().getName(), ULOC_TAIWAN) != 0) {
465 errln("Differences for ULOC_TAIWAN Locale");
466 }
467 if (strcmp(Locale::getUK().getName(), ULOC_UK) != 0) {
468 errln("Differences for ULOC_UK Locale");
469 }
470 if (strcmp(Locale::getUS().getName(), ULOC_US) != 0) {
471 errln("Differences for ULOC_US Locale");
472 }
473 }
474
475
TestSimpleResourceInfo()476 void LocaleTest::TestSimpleResourceInfo() {
477 UnicodeString temp;
478 char temp2[20];
479 UErrorCode err = U_ZERO_ERROR;
480 int32_t i = 0;
481
482 for (i = 0; i <= MAX_LOCALES; i++) {
483 Locale testLocale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
484 logln("Testing " + (temp=testLocale.getName()) + "...");
485
486 if ( (temp=testLocale.getISO3Language()) != (dataTable[LANG3][i]))
487 errln(" ISO-3 language code mismatch: " + temp
488 + " versus " + dataTable[LANG3][i]);
489 if ( (temp=testLocale.getISO3Country()) != (dataTable[CTRY3][i]))
490 errln(" ISO-3 country code mismatch: " + temp
491 + " versus " + dataTable[CTRY3][i]);
492
493 sprintf(temp2, "%x", (int)testLocale.getLCID());
494 if (UnicodeString(temp2) != dataTable[LCID][i])
495 errln((UnicodeString)" LCID mismatch: " + temp2 + " versus "
496 + dataTable[LCID][i]);
497
498 if(U_FAILURE(err))
499 {
500 errln((UnicodeString)"Some error on number " + i + u_errorName(err));
501 }
502 err = U_ZERO_ERROR;
503 }
504
505 Locale locale("en");
506 if(strcmp(locale.getName(), "en") != 0||
507 strcmp(locale.getLanguage(), "en") != 0) {
508 errln("construction of Locale(en) failed\n");
509 }
510 /*-----*/
511
512 }
513
514 /*
515 * Jitterbug 2439 -- markus 20030425
516 *
517 * The lookup of display names must not fall back through the default
518 * locale because that yields useless results.
519 */
520 void
TestDisplayNames()521 LocaleTest::TestDisplayNames()
522 {
523 Locale english("en", "US");
524 Locale french("fr", "FR");
525 Locale croatian("ca", "ES");
526 Locale greek("el", "GR");
527
528 logln(" In locale = en_US...");
529 doTestDisplayNames(english, DLANG_EN);
530 logln(" In locale = fr_FR...");
531 doTestDisplayNames(french, DLANG_FR);
532 logln(" In locale = ca_ES...");
533 doTestDisplayNames(croatian, DLANG_CA);
534 logln(" In locale = el_GR...");
535 doTestDisplayNames(greek, DLANG_EL);
536
537 UnicodeString s;
538 UErrorCode status = U_ZERO_ERROR;
539
540 #if !UCONFIG_NO_FORMATTING
541 DecimalFormatSymbols symb(status);
542 /* Check to see if ICU supports this locale */
543 if (symb.getLocale(ULOC_VALID_LOCALE, status) != Locale("root")) {
544 /* test that the default locale has a display name for its own language */
545 /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */
546 if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) {
547 Locale().getDisplayLanguage(Locale(), s);
548 if(s.length()<=3 && s.charAt(0)<=0x7f) {
549 /* check <=3 to reject getting the language code as a display name */
550 dataerrln("unable to get a display string for the language of the default locale: " + s);
551 }
552
553 /*
554 * API coverage improvements: call
555 * Locale::getDisplayLanguage(UnicodeString &) and
556 * Locale::getDisplayCountry(UnicodeString &)
557 */
558 s.remove();
559 Locale().getDisplayLanguage(s);
560 if(s.length()<=3 && s.charAt(0)<=0x7f) {
561 dataerrln("unable to get a display string for the language of the default locale [2]: " + s);
562 }
563 }
564 }
565 else {
566 logln("Default locale %s is unsupported by ICU\n", Locale().getName());
567 }
568 s.remove();
569 #endif
570
571 french.getDisplayCountry(s);
572 if(s.isEmpty()) {
573 errln("unable to get any default-locale display string for the country of fr_FR\n");
574 }
575 s.remove();
576 Locale("zh", "Hant").getDisplayScript(s);
577 if(s.isEmpty()) {
578 errln("unable to get any default-locale display string for the country of zh_Hant\n");
579 }
580 }
581
TestSimpleObjectStuff()582 void LocaleTest::TestSimpleObjectStuff() {
583 Locale test1("aa", "AA");
584 Locale test2("aa", "AA");
585 Locale test3(test1);
586 Locale test4("zz", "ZZ");
587 Locale test5("aa", "AA", "");
588 Locale test6("aa", "AA", "ANTARES");
589 Locale test7("aa", "AA", "JUPITER");
590 Locale test8 = Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that
591
592 // now list them all for debugging usage.
593 test_dumpLocale(test1);
594 test_dumpLocale(test2);
595 test_dumpLocale(test3);
596 test_dumpLocale(test4);
597 test_dumpLocale(test5);
598 test_dumpLocale(test6);
599 test_dumpLocale(test7);
600 test_dumpLocale(test8);
601
602 // Make sure things compare to themselves!
603 test_assert(test1 == test1);
604 test_assert(test2 == test2);
605 test_assert(test3 == test3);
606 test_assert(test4 == test4);
607 test_assert(test5 == test5);
608 test_assert(test6 == test6);
609 test_assert(test7 == test7);
610 test_assert(test8 == test8);
611
612 // make sure things are not equal to themselves.
613 test_assert(!(test1 != test1));
614 test_assert(!(test2 != test2));
615 test_assert(!(test3 != test3));
616 test_assert(!(test4 != test4));
617 test_assert(!(test5 != test5));
618 test_assert(!(test6 != test6));
619 test_assert(!(test7 != test7));
620 test_assert(!(test8 != test8));
621
622 // make sure things that are equal to each other don't show up as unequal.
623 test_assert(!(test1 != test2));
624 test_assert(!(test2 != test1));
625 test_assert(!(test1 != test3));
626 test_assert(!(test2 != test3));
627 test_assert(test5 == test1);
628 test_assert(test6 != test2);
629 test_assert(test6 != test5);
630
631 test_assert(test6 != test7);
632
633 // test for things that shouldn't compare equal.
634 test_assert(!(test1 == test4));
635 test_assert(!(test2 == test4));
636 test_assert(!(test3 == test4));
637
638 test_assert(test7 == test8);
639
640 // test for hash codes to be the same.
641 int32_t hash1 = test1.hashCode();
642 int32_t hash2 = test2.hashCode();
643 int32_t hash3 = test3.hashCode();
644
645 test_assert(hash1 == hash2);
646 test_assert(hash1 == hash3);
647 test_assert(hash2 == hash3);
648
649 // test that the assignment operator works.
650 test4 = test1;
651 logln("test4=test1;");
652 test_dumpLocale(test4);
653 test_assert(test4 == test4);
654
655 test_assert(!(test1 != test4));
656 test_assert(!(test2 != test4));
657 test_assert(!(test3 != test4));
658 test_assert(test1 == test4);
659 test_assert(test4 == test1);
660
661 // test assignments with a variant
662 logln("test7 = test6");
663 test7 = test6;
664 test_dumpLocale(test7);
665 test_assert(test7 == test7);
666 test_assert(test7 == test6);
667 test_assert(test7 != test5);
668
669 logln("test6 = test1");
670 test6=test1;
671 test_dumpLocale(test6);
672 test_assert(test6 != test7);
673 test_assert(test6 == test1);
674 test_assert(test6 == test6);
675 }
676
677 // A class which exposes constructors that are implemented in terms of the POSIX parsing code.
678 class POSIXLocale : public Locale
679 {
680 public:
POSIXLocale(const UnicodeString & l)681 POSIXLocale(const UnicodeString& l)
682 :Locale()
683 {
684 char *ch;
685 ch = new char[l.length() + 1];
686 ch[l.extract(0, 0x7fffffff, ch, "")] = 0;
687 setFromPOSIXID(ch);
688 delete [] ch;
689 }
POSIXLocale(const char * l)690 POSIXLocale(const char *l)
691 :Locale()
692 {
693 setFromPOSIXID(l);
694 }
695 };
696
TestPOSIXParsing()697 void LocaleTest::TestPOSIXParsing()
698 {
699 POSIXLocale test1("ab_AB");
700 POSIXLocale test2(UnicodeString("ab_AB"));
701 Locale test3("ab","AB");
702
703 POSIXLocale test4("ab_AB_Antares");
704 POSIXLocale test5(UnicodeString("ab_AB_Antares"));
705 Locale test6("ab", "AB", "Antares");
706
707 test_dumpLocale(test1);
708 test_dumpLocale(test2);
709 test_dumpLocale(test3);
710 test_dumpLocale(test4);
711 test_dumpLocale(test5);
712 test_dumpLocale(test6);
713
714 test_assert(test1 == test1);
715
716 test_assert(test1 == test2);
717 test_assert(test2 == test3);
718 test_assert(test3 == test1);
719
720 test_assert(test4 == test5);
721 test_assert(test5 == test6);
722 test_assert(test6 == test4);
723
724 test_assert(test1 != test4);
725 test_assert(test5 != test3);
726 test_assert(test5 != test2);
727
728 int32_t hash1 = test1.hashCode();
729 int32_t hash2 = test2.hashCode();
730 int32_t hash3 = test3.hashCode();
731
732 test_assert(hash1 == hash2);
733 test_assert(hash2 == hash3);
734 test_assert(hash3 == hash1);
735 }
736
TestGetAvailableLocales()737 void LocaleTest::TestGetAvailableLocales()
738 {
739 int32_t locCount = 0;
740 const Locale* locList = Locale::getAvailableLocales(locCount);
741
742 if (locCount == 0)
743 dataerrln("getAvailableLocales() returned an empty list!");
744 else {
745 logln(UnicodeString("Number of locales returned = ") + locCount);
746 UnicodeString temp;
747 for(int32_t i = 0; i < locCount; ++i)
748 logln(locList[i].getName());
749 }
750 // I have no idea how to test this function...
751 }
752
753 // This test isn't applicable anymore - getISO3Language is
754 // independent of the data directory
TestDataDirectory()755 void LocaleTest::TestDataDirectory()
756 {
757 /*
758 char oldDirectory[80];
759 const char* temp;
760 UErrorCode err = U_ZERO_ERROR;
761 UnicodeString testValue;
762
763 temp = Locale::getDataDirectory();
764 strcpy(oldDirectory, temp);
765 logln(UnicodeString("oldDirectory = ") + oldDirectory);
766
767 Locale test(Locale::US);
768 test.getISO3Language(testValue);
769 logln("first fetch of language retrieved " + testValue);
770 if (testValue != "eng")
771 errln("Initial check of ISO3 language failed: expected \"eng\", got \"" + testValue + "\"");
772
773 {
774 char *path;
775 path=IntlTest::getTestDirectory();
776 Locale::setDataDirectory( path );
777 }
778
779 test.getISO3Language(testValue);
780 logln("second fetch of language retrieved " + testValue);
781 if (testValue != "xxx")
782 errln("setDataDirectory() failed: expected \"xxx\", got \"" + testValue + "\"");
783
784 Locale::setDataDirectory(oldDirectory);
785 test.getISO3Language(testValue);
786 logln("third fetch of language retrieved " + testValue);
787 if (testValue != "eng")
788 errln("get/setDataDirectory() failed: expected \"eng\", got \"" + testValue + "\"");
789 */
790 }
791
792 //===========================================================
793
doTestDisplayNames(Locale & displayLocale,int32_t compareIndex)794 void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) {
795 UnicodeString temp;
796
797 for (int32_t i = 0; i <= MAX_LOCALES; i++) {
798 Locale testLocale("");
799 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
800 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
801 }
802 else {
803 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
804 }
805 logln(" Testing " + (temp=testLocale.getName()) + "...");
806
807 UnicodeString testLang;
808 UnicodeString testScript;
809 UnicodeString testCtry;
810 UnicodeString testVar;
811 UnicodeString testName;
812
813 testLocale.getDisplayLanguage(displayLocale, testLang);
814 testLocale.getDisplayScript(displayLocale, testScript);
815 testLocale.getDisplayCountry(displayLocale, testCtry);
816 testLocale.getDisplayVariant(displayLocale, testVar);
817 testLocale.getDisplayName(displayLocale, testName);
818
819 UnicodeString expectedLang;
820 UnicodeString expectedScript;
821 UnicodeString expectedCtry;
822 UnicodeString expectedVar;
823 UnicodeString expectedName;
824
825 expectedLang = dataTable[compareIndex][i];
826 if (expectedLang.length() == 0)
827 expectedLang = dataTable[DLANG_EN][i];
828
829 expectedScript = dataTable[compareIndex + 1][i];
830 if (expectedScript.length() == 0)
831 expectedScript = dataTable[DSCRIPT_EN][i];
832
833 expectedCtry = dataTable[compareIndex + 2][i];
834 if (expectedCtry.length() == 0)
835 expectedCtry = dataTable[DCTRY_EN][i];
836
837 expectedVar = dataTable[compareIndex + 3][i];
838 if (expectedVar.length() == 0)
839 expectedVar = dataTable[DVAR_EN][i];
840
841 expectedName = dataTable[compareIndex + 4][i];
842 if (expectedName.length() == 0)
843 expectedName = dataTable[DNAME_EN][i];
844
845 if (testLang != expectedLang)
846 dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang);
847 if (testScript != expectedScript)
848 dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript);
849 if (testCtry != expectedCtry)
850 dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry);
851 if (testVar != expectedVar)
852 dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar);
853 if (testName != expectedName)
854 dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName);
855 }
856 }
857
858 //---------------------------------------------------
859 // table of valid data
860 //---------------------------------------------------
861
862
863
setUpDataTable()864 void LocaleTest::setUpDataTable()
865 {
866 if (dataTable == 0) {
867 dataTable = new UnicodeString*[33];
868
869 for (int32_t i = 0; i < 33; i++) {
870 dataTable[i] = new UnicodeString[8];
871 for (int32_t j = 0; j < 8; j++) {
872 dataTable[i][j] = CharsToUnicodeString(rawData[i][j]);
873 }
874 }
875 }
876 }
877
878 // ====================
879
880
881 /**
882 * @bug 4011756 4011380
883 */
884 void
TestISO3Fallback()885 LocaleTest::TestISO3Fallback()
886 {
887 Locale test("xx", "YY");
888
889 const char * result;
890
891 result = test.getISO3Language();
892
893 // Conform to C API usage
894
895 if (!result || (result[0] != 0))
896 errln("getISO3Language() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
897
898 result = test.getISO3Country();
899
900 if (!result || (result[0] != 0))
901 errln("getISO3Country() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
902 }
903
904 /**
905 * @bug 4106155 4118587
906 */
907 void
TestGetLangsAndCountries()908 LocaleTest::TestGetLangsAndCountries()
909 {
910 // It didn't seem right to just do an exhaustive test of everything here, so I check
911 // for the following things:
912 // 1) Does each list have the right total number of entries?
913 // 2) Does each list contain certain language and country codes we think are important
914 // (the G7 countries, plus a couple others)?
915 // 3) Does each list have every entry formatted correctly? (i.e., two characters,
916 // all lower case for the language codes, all upper case for the country codes)
917 // 4) Is each list in sorted order?
918 int32_t testCount = 0;
919 const char * const * test = Locale::getISOLanguages();
920 const char spotCheck1[ ][4] = { "en", "es", "fr", "de", "it",
921 "ja", "ko", "zh", "th", "he",
922 "id", "iu", "ug", "yi", "za" };
923
924 int32_t i;
925
926 for(testCount = 0;test[testCount];testCount++)
927 ;
928
929 /* TODO: Change this test to be more like the cloctst version? */
930 if (testCount != 595)
931 errln("Expected getISOLanguages() to return 595 languages; it returned %d", testCount);
932 else {
933 for (i = 0; i < 15; i++) {
934 int32_t j;
935 for (j = 0; j < testCount; j++)
936 if (uprv_strcmp(test[j],spotCheck1[i])== 0)
937 break;
938 if (j == testCount || (uprv_strcmp(test[j],spotCheck1[i])!=0))
939 errln("Couldn't find " + (UnicodeString)spotCheck1[i] + " in language list.");
940 }
941 }
942 for (i = 0; i < testCount; i++) {
943 UnicodeString testee(test[i],"");
944 UnicodeString lc(test[i],"");
945 if (testee != lc.toLower())
946 errln(lc + " is not all lower case.");
947 if ( (testee.length() != 2) && (testee.length() != 3))
948 errln(testee + " is not two or three characters long.");
949 if (i > 0 && testee.compare(test[i - 1]) <= 0)
950 errln(testee + " appears in an out-of-order position in the list.");
951 }
952
953 test = Locale::getISOCountries();
954 UnicodeString spotCheck2 [] = { "US", "CA", "GB", "FR", "DE",
955 "IT", "JP", "KR", "CN", "TW",
956 "TH" };
957 int32_t spot2Len = 11;
958 for(testCount=0;test[testCount];testCount++)
959 ;
960
961 if (testCount != 253){
962 errln("Expected getISOCountries to return 253 countries; it returned %d", testCount);
963 }else {
964 for (i = 0; i < spot2Len; i++) {
965 int32_t j;
966 for (j = 0; j < testCount; j++)
967 {
968 UnicodeString testee(test[j],"");
969
970 if (testee == spotCheck2[i])
971 break;
972 }
973 UnicodeString testee(test[j],"");
974 if (j == testCount || testee != spotCheck2[i])
975 errln("Couldn't find " + spotCheck2[i] + " in country list.");
976 }
977 }
978 for (i = 0; i < testCount; i++) {
979 UnicodeString testee(test[i],"");
980 UnicodeString uc(test[i],"");
981 if (testee != uc.toUpper())
982 errln(testee + " is not all upper case.");
983 if (testee.length() != 2)
984 errln(testee + " is not two characters long.");
985 if (i > 0 && testee.compare(test[i - 1]) <= 0)
986 errln(testee + " appears in an out-of-order position in the list.");
987 }
988
989 // This getAvailableLocales and getISO3Language
990 {
991 int32_t numOfLocales;
992 Locale enLoc ("en");
993 const Locale *pLocales = Locale::getAvailableLocales(numOfLocales);
994
995 for (int i = 0; i < numOfLocales; i++) {
996 const Locale &loc(pLocales[i]);
997 UnicodeString name;
998 char szName[200];
999
1000 loc.getDisplayName (enLoc, name);
1001 name.extract (0, 200, szName, sizeof(szName));
1002
1003 if (strlen(loc.getISO3Language()) == 0) {
1004 errln("getISO3Language() returned an empty string for: " + name);
1005 }
1006 }
1007 }
1008 }
1009
1010 /**
1011 * @bug 4118587
1012 */
1013 void
TestSimpleDisplayNames()1014 LocaleTest::TestSimpleDisplayNames()
1015 {
1016 // This test is different from TestDisplayNames because TestDisplayNames checks
1017 // fallback behavior, combination of language and country names to form locale
1018 // names, and other stuff like that. This test just checks specific language
1019 // and country codes to make sure we have the correct names for them.
1020 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" };
1021 UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1022 "Zhuang" };
1023
1024 for (int32_t i = 0; i < 6; i++) {
1025 UnicodeString test;
1026 Locale l(languageCodes[i], "", "");
1027 l.getDisplayLanguage(Locale::getUS(), test);
1028 if (test != languageNames[i])
1029 dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" +
1030 languageNames[i] + "\", got \"" + test + "\".");
1031 }
1032 }
1033
1034 /**
1035 * @bug 4118595
1036 */
1037 void
TestUninstalledISO3Names()1038 LocaleTest::TestUninstalledISO3Names()
1039 {
1040 // This test checks to make sure getISO3Language and getISO3Country work right
1041 // even for locales that are not installed.
1042 const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
1043 "ss", "tw", "zu" };
1044 const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
1045 "ssw", "twi", "zul" };
1046
1047 int32_t i;
1048
1049 for (i = 0; i < 8; i++) {
1050 UErrorCode err = U_ZERO_ERROR;
1051
1052 UnicodeString test;
1053 Locale l(iso2Languages[i], "", "");
1054 test = l.getISO3Language();
1055 if((test != iso3Languages[i]) || U_FAILURE(err))
1056 errln("Got wrong ISO3 code for " + UnicodeString(iso2Languages[i]) + ": Expected \"" +
1057 iso3Languages[i] + "\", got \"" + test + "\"." + UnicodeString(u_errorName(err)));
1058 }
1059
1060 char iso2Countries [][4] = { "AF", "BW", "KZ", "MO", "MN",
1061 "SB", "TC", "ZW" };
1062 char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1063 "SLB", "TCA", "ZWE" };
1064
1065 for (i = 0; i < 8; i++) {
1066 UErrorCode err = U_ZERO_ERROR;
1067 Locale l("", iso2Countries[i], "");
1068 UnicodeString test(l.getISO3Country(), "");
1069 if (test != iso3Countries[i])
1070 errln("Got wrong ISO3 code for " + UnicodeString(iso2Countries[i]) + ": Expected \"" +
1071 UnicodeString(iso3Countries[i]) + "\", got \"" + test + "\"." + u_errorName(err));
1072 }
1073 }
1074
1075 /**
1076 * @bug 4092475
1077 * I could not reproduce this bug. I'm pretty convinced it was fixed with the
1078 * big locale-data reorg of 10/28/97. The lookup logic for language and country
1079 * display names was also changed at that time in that check-in. --rtg 3/20/98
1080 */
1081 void
TestAtypicalLocales()1082 LocaleTest::TestAtypicalLocales()
1083 {
1084 Locale localesToTest [] = { Locale("de", "CA"),
1085 Locale("ja", "ZA"),
1086 Locale("ru", "MX"),
1087 Locale("en", "FR"),
1088 Locale("es", "DE"),
1089 Locale("", "HR"),
1090 Locale("", "SE"),
1091 Locale("", "DO"),
1092 Locale("", "BE") };
1093
1094 UnicodeString englishDisplayNames [] = { "German (Canada)",
1095 "Japanese (South Africa)",
1096 "Russian (Mexico)",
1097 "English (France)",
1098 "Spanish (Germany)",
1099 "Unknown language (Croatia)",
1100 "Unknown language (Sweden)",
1101 "Unknown language (Dominican Republic)",
1102 "Unknown language (Belgium)" };
1103 UnicodeString frenchDisplayNames []= { "allemand (Canada)",
1104 "japonais (Afrique du Sud)",
1105 "russe (Mexique)",
1106 "anglais (France)",
1107 "espagnol (Allemagne)",
1108 u"langue indéterminée (Croatie)",
1109 u"langue indéterminée (Suède)",
1110 u"langue indéterminée (République dominicaine)",
1111 u"langue indéterminée (Belgique)" };
1112 UnicodeString spanishDisplayNames [] = {
1113 u"alemán (Canadá)",
1114 u"japonés (Sudáfrica)",
1115 u"ruso (México)",
1116 u"inglés (Francia)",
1117 u"español (Alemania)",
1118 "lengua desconocida (Croacia)",
1119 "lengua desconocida (Suecia)",
1120 u"lengua desconocida (República Dominicana)",
1121 u"lengua desconocida (Bélgica)" };
1122 // De-Anglicizing root required the change from
1123 // English display names to ISO Codes - ram 2003/09/26
1124 UnicodeString invDisplayNames [] = { "German (Canada)",
1125 "Japanese (South Africa)",
1126 "Russian (Mexico)",
1127 "English (France)",
1128 "Spanish (Germany)",
1129 "Unknown language (Croatia)",
1130 "Unknown language (Sweden)",
1131 "Unknown language (Dominican Republic)",
1132 "Unknown language (Belgium)" };
1133
1134 int32_t i;
1135 UErrorCode status = U_ZERO_ERROR;
1136 Locale saveLocale;
1137 Locale::setDefault(Locale::getUS(), status);
1138 for (i = 0; i < 9; ++i) {
1139 UnicodeString name;
1140 localesToTest[i].getDisplayName(Locale::getUS(), name);
1141 logln(name);
1142 if (name != englishDisplayNames[i])
1143 {
1144 dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i]
1145 + "\", got \"" + name + "\"");
1146 logln("Locale name was-> " + (name=localesToTest[i].getName()));
1147 }
1148 }
1149
1150 for (i = 0; i < 9; i++) {
1151 UnicodeString name;
1152 localesToTest[i].getDisplayName(Locale("es", "ES"), name);
1153 logln(name);
1154 if (name != spanishDisplayNames[i])
1155 dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
1156 + "\", got \"" + name + "\"");
1157 }
1158
1159 for (i = 0; i < 9; i++) {
1160 UnicodeString name;
1161 localesToTest[i].getDisplayName(Locale::getFrance(), name);
1162 logln(name);
1163 if (name != frenchDisplayNames[i])
1164 dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
1165 + "\", got \"" + name + "\"");
1166 }
1167
1168 for (i = 0; i < 9; i++) {
1169 UnicodeString name;
1170 localesToTest[i].getDisplayName(Locale("inv", "IN"), name);
1171 logln(name + " Locale fallback to be, and data fallback to root");
1172 if (name != invDisplayNames[i])
1173 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
1174 + "\", got \"" + prettify(name) + "\"");
1175 localesToTest[i].getDisplayName(Locale("inv", "BD"), name);
1176 logln(name + " Data fallback to root");
1177 if (name != invDisplayNames[i])
1178 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
1179 + "\", got \"" + prettify(name )+ "\"");
1180 }
1181 Locale::setDefault(saveLocale, status);
1182 }
1183
1184 #if !UCONFIG_NO_FORMATTING
1185
1186 /**
1187 * @bug 4135752
1188 * This would be better tested by the LocaleDataTest. Will move it when I
1189 * get the LocaleDataTest working again.
1190 */
1191 void
TestThaiCurrencyFormat()1192 LocaleTest::TestThaiCurrencyFormat()
1193 {
1194 UErrorCode status = U_ZERO_ERROR;
1195 DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance(
1196 Locale("th", "TH"), status);
1197 UnicodeString posPrefix(u"\u0E3F");
1198 UnicodeString temp;
1199
1200 if(U_FAILURE(status) || !thaiCurrency)
1201 {
1202 dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status)));
1203 return;
1204 }
1205 if (thaiCurrency->getPositivePrefix(temp) != posPrefix)
1206 errln("Thai currency prefix wrong: expected Baht sign, got \"" +
1207 thaiCurrency->getPositivePrefix(temp) + "\"");
1208 if (thaiCurrency->getPositiveSuffix(temp) != "")
1209 errln("Thai currency suffix wrong: expected \"\", got \"" +
1210 thaiCurrency->getPositiveSuffix(temp) + "\"");
1211
1212 delete thaiCurrency;
1213 }
1214
1215 /**
1216 * @bug 4122371
1217 * Confirm that Euro support works. This test is pretty rudimentary; all it does
1218 * is check that any locales with the EURO variant format a number using the
1219 * Euro currency symbol.
1220 *
1221 * ASSUME: All locales encode the Euro character "\u20AC".
1222 * If this is changed to use the single-character Euro symbol, this
1223 * test must be updated.
1224 *
1225 */
1226 void
TestEuroSupport()1227 LocaleTest::TestEuroSupport()
1228 {
1229 UChar euro = 0x20ac;
1230 const UnicodeString EURO_CURRENCY(&euro, 1, 1); // Look for this UnicodeString in formatted Euro currency
1231 const char* localeArr[] = {
1232 "ca_ES",
1233 "de_AT",
1234 "de_DE",
1235 "de_LU",
1236 "el_GR",
1237 "en_BE",
1238 "en_IE",
1239 "en_GB@currency=EUR",
1240 "en_US@currency=EUR",
1241 "es_ES",
1242 "eu_ES",
1243 "fi_FI",
1244 "fr_BE",
1245 "fr_FR",
1246 "fr_LU",
1247 "ga_IE",
1248 "gl_ES",
1249 "it_IT",
1250 "nl_BE",
1251 "nl_NL",
1252 "pt_PT",
1253 NULL
1254 };
1255 const char** locales = localeArr;
1256
1257 UErrorCode status = U_ZERO_ERROR;
1258
1259 UnicodeString temp;
1260
1261 for (;*locales!=NULL;locales++) {
1262 Locale loc (*locales);
1263 UnicodeString temp;
1264 NumberFormat *nf = NumberFormat::createCurrencyInstance(loc, status);
1265 UnicodeString pos;
1266
1267 if (U_FAILURE(status)) {
1268 dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales);
1269 continue;
1270 }
1271
1272 nf->format(271828.182845, pos);
1273 UnicodeString neg;
1274 nf->format(-271828.182845, neg);
1275 if (pos.indexOf(EURO_CURRENCY) >= 0 &&
1276 neg.indexOf(EURO_CURRENCY) >= 0) {
1277 logln("Ok: " + (temp=loc.getName()) +
1278 ": " + pos + " / " + neg);
1279 }
1280 else {
1281 errln("Fail: " + (temp=loc.getName()) +
1282 " formats without " + EURO_CURRENCY +
1283 ": " + pos + " / " + neg +
1284 "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
1285 }
1286
1287 delete nf;
1288 }
1289
1290 UnicodeString dollarStr("USD", ""), euroStr("EUR", ""), genericStr((UChar)0x00a4), resultStr;
1291 UChar tmp[4];
1292 status = U_ZERO_ERROR;
1293
1294 ucurr_forLocale("en_US", tmp, 4, &status);
1295 resultStr.setTo(tmp);
1296 if (dollarStr != resultStr) {
1297 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
1298 }
1299 ucurr_forLocale("en_US@currency=EUR", tmp, 4, &status);
1300 resultStr.setTo(tmp);
1301 if (euroStr != resultStr) {
1302 errcheckln(status, "Fail: en_US@currency=EUR didn't return EUR - %s", u_errorName(status));
1303 }
1304 ucurr_forLocale("en_GB@currency=EUR", tmp, 4, &status);
1305 resultStr.setTo(tmp);
1306 if (euroStr != resultStr) {
1307 errcheckln(status, "Fail: en_GB@currency=EUR didn't return EUR - %s", u_errorName(status));
1308 }
1309 ucurr_forLocale("en_US_Q", tmp, 4, &status);
1310 resultStr.setTo(tmp);
1311 if (dollarStr != resultStr) {
1312 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
1313 }
1314 int32_t invalidLen = ucurr_forLocale("en_QQ", tmp, 4, &status);
1315 if (invalidLen || U_SUCCESS(status)) {
1316 errln("Fail: en_QQ didn't return NULL");
1317 }
1318
1319 // The currency keyword value is as long as the destination buffer.
1320 // It should detect the overflow internally, and default to the locale's currency.
1321 tmp[0] = u'¤';
1322 status = U_ZERO_ERROR;
1323 int32_t length = ucurr_forLocale("en_US@currency=euro", tmp, 4, &status);
1324 if (U_FAILURE(status) || dollarStr != UnicodeString(tmp, length)) {
1325 if (U_SUCCESS(status) && tmp[0] == u'¤') {
1326 errln("Fail: ucurr_forLocale(en_US@currency=euro) succeeded without writing output");
1327 } else {
1328 errln("Fail: ucurr_forLocale(en_US@currency=euro) != USD - %s", u_errorName(status));
1329 }
1330 }
1331 }
1332
1333 #endif
1334
1335 /**
1336 * @bug 4139504
1337 * toString() doesn't work with language_VARIANT.
1338 */
1339 void
TestToString()1340 LocaleTest::TestToString() {
1341 Locale DATA [] = {
1342 Locale("xx", "", ""),
1343 Locale("", "YY", ""),
1344 Locale("", "", "ZZ"),
1345 Locale("xx", "YY", ""),
1346 Locale("xx", "", "ZZ"),
1347 Locale("", "YY", "ZZ"),
1348 Locale("xx", "YY", "ZZ"),
1349 };
1350
1351 const char DATA_S [][20] = {
1352 "xx",
1353 "_YY",
1354 "__ZZ",
1355 "xx_YY",
1356 "xx__ZZ",
1357 "_YY_ZZ",
1358 "xx_YY_ZZ",
1359 };
1360
1361 for (int32_t i=0; i < 7; ++i) {
1362 const char *name;
1363 name = DATA[i].getName();
1364
1365 if (strcmp(name, DATA_S[i]) != 0)
1366 {
1367 errln("Fail: Locale.getName(), got:" + UnicodeString(name) + ", expected: " + DATA_S[i]);
1368 }
1369 else
1370 logln("Pass: Locale.getName(), got:" + UnicodeString(name) );
1371 }
1372 }
1373
1374 #if !UCONFIG_NO_FORMATTING
1375
1376 /**
1377 * @bug 4139940
1378 * Couldn't reproduce this bug -- probably was fixed earlier.
1379 *
1380 * ORIGINAL BUG REPORT:
1381 * -- basically, hungarian for monday shouldn't have an \u00f4
1382 * (o circumflex)in it instead it should be an o with 2 inclined
1383 * (right) lines over it..
1384 *
1385 * You may wonder -- why do all this -- why not just add a line to
1386 * LocaleData? Well, I could see by inspection that the locale file had the
1387 * right character in it, so I wanted to check the rest of the pipeline -- a
1388 * very remote possibility, but I wanted to be sure. The other possibility
1389 * is that something is wrong with the font mapping subsystem, but we can't
1390 * test that here.
1391 */
1392 void
Test4139940()1393 LocaleTest::Test4139940()
1394 {
1395 Locale mylocale("hu", "", "");
1396 UDate mydate = date(98,3,13); // A Monday
1397 UErrorCode status = U_ZERO_ERROR;
1398 SimpleDateFormat df_full("EEEE", mylocale, status);
1399 if(U_FAILURE(status)){
1400 dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status)));
1401 return;
1402 }
1403 UnicodeString str;
1404 FieldPosition pos(FieldPosition::DONT_CARE);
1405 df_full.format(mydate, str, pos);
1406 // Make sure that o circumflex (\u00F4) is NOT there, and
1407 // o double acute (\u0151) IS.
1408 UChar ocf = 0x00f4;
1409 UChar oda = 0x0151;
1410 if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) {
1411 /* If the default locale is "th" this test will fail because of the buddhist calendar. */
1412 if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) {
1413 errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d",
1414 str.indexOf(oda), str.indexOf(ocf));
1415 } else {
1416 logln(UnicodeString("An error is produce in buddhist calendar."));
1417 }
1418 logln(UnicodeString("String is: ") + str );
1419 }
1420 }
1421
1422 UDate
date(int32_t y,int32_t m,int32_t d,int32_t hr,int32_t min,int32_t sec)1423 LocaleTest::date(int32_t y, int32_t m, int32_t d, int32_t hr, int32_t min, int32_t sec)
1424 {
1425 UErrorCode status = U_ZERO_ERROR;
1426 Calendar *cal = Calendar::createInstance(status);
1427 if (cal == 0)
1428 return 0.0;
1429 cal->clear();
1430 cal->set(1900 + y, m, d, hr, min, sec); // Add 1900 to follow java.util.Date protocol
1431 UDate dt = cal->getTime(status);
1432 if (U_FAILURE(status))
1433 return 0.0;
1434
1435 delete cal;
1436 return dt;
1437 }
1438
1439 /**
1440 * @bug 4143951
1441 * Russian first day of week should be Monday. Confirmed.
1442 */
1443 void
Test4143951()1444 LocaleTest::Test4143951()
1445 {
1446 UErrorCode status = U_ZERO_ERROR;
1447 Calendar *cal = Calendar::createInstance(Locale("ru", "", ""), status);
1448 if(U_SUCCESS(status)) {
1449 if (cal->getFirstDayOfWeek(status) != UCAL_MONDAY) {
1450 dataerrln("Fail: First day of week in Russia should be Monday");
1451 }
1452 }
1453 delete cal;
1454 }
1455
1456 #endif
1457
1458 /**
1459 * @bug 4147315
1460 * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
1461 * Should throw an exception for unknown locales
1462 */
1463 void
Test4147315()1464 LocaleTest::Test4147315()
1465 {
1466 UnicodeString temp;
1467 // Try with codes that are the wrong length but happen to match text
1468 // at a valid offset in the mapping table
1469 Locale locale("xxx", "CCC");
1470
1471 const char *result = locale.getISO3Country();
1472
1473 // Change to conform to C api usage
1474 if((result==NULL)||(result[0] != 0))
1475 errln("ERROR: getISO3Country() returns: " + UnicodeString(result,"") +
1476 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
1477 }
1478
1479 /**
1480 * @bug 4147317
1481 * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes.
1482 * Should throw an exception for unknown locales
1483 */
1484 void
Test4147317()1485 LocaleTest::Test4147317()
1486 {
1487 UnicodeString temp;
1488 // Try with codes that are the wrong length but happen to match text
1489 // at a valid offset in the mapping table
1490 Locale locale("xxx", "CCC");
1491
1492 const char *result = locale.getISO3Language();
1493
1494 // Change to conform to C api usage
1495 if((result==NULL)||(result[0] != 0))
1496 errln("ERROR: getISO3Language() returns: " + UnicodeString(result,"") +
1497 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
1498 }
1499
1500 /*
1501 * @bug 4147552
1502 */
1503 void
Test4147552()1504 LocaleTest::Test4147552()
1505 {
1506 Locale locales [] = { Locale("no", "NO"),
1507 Locale("no", "NO", "B"),
1508 Locale("no", "NO", "NY")
1509 };
1510
1511 UnicodeString edn("Norwegian (Norway, B)");
1512 UnicodeString englishDisplayNames [] = {
1513 "Norwegian (Norway)",
1514 edn,
1515 // "Norwegian (Norway,B)",
1516 //"Norwegian (Norway,NY)"
1517 "Norwegian (Norway, NY)"
1518 };
1519 UnicodeString ndn("norsk (Norge, B");
1520 UnicodeString norwegianDisplayNames [] = {
1521 "norsk (Norge)",
1522 "norsk (Norge, B)",
1523 //ndn,
1524 "norsk (Noreg, NY)"
1525 //"Norsk (Noreg, Nynorsk)"
1526 };
1527 UErrorCode status = U_ZERO_ERROR;
1528
1529 Locale saveLocale;
1530 Locale::setDefault(Locale::getEnglish(), status);
1531 for (int32_t i = 0; i < 3; ++i) {
1532 Locale loc = locales[i];
1533 UnicodeString temp;
1534 if (loc.getDisplayName(temp) != englishDisplayNames[i])
1535 dataerrln("English display-name mismatch: expected " +
1536 englishDisplayNames[i] + ", got " + loc.getDisplayName(temp));
1537 if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i])
1538 dataerrln("Norwegian display-name mismatch: expected " +
1539 norwegianDisplayNames[i] + ", got " +
1540 loc.getDisplayName(loc, temp));
1541 }
1542 Locale::setDefault(saveLocale, status);
1543 }
1544
1545 void
TestVariantParsing()1546 LocaleTest::TestVariantParsing()
1547 {
1548 Locale en_US_custom("en", "US", "De Anza_Cupertino_California_United States_Earth");
1549
1550 UnicodeString dispName("English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)");
1551 UnicodeString dispVar("DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH");
1552
1553 UnicodeString got;
1554
1555 en_US_custom.getDisplayVariant(Locale::getUS(), got);
1556 if(got != dispVar) {
1557 errln("FAIL: getDisplayVariant()");
1558 errln("Wanted: " + dispVar);
1559 errln("Got : " + got);
1560 }
1561
1562 en_US_custom.getDisplayName(Locale::getUS(), got);
1563 if(got != dispName) {
1564 dataerrln("FAIL: getDisplayName()");
1565 dataerrln("Wanted: " + dispName);
1566 dataerrln("Got : " + got);
1567 }
1568
1569 Locale shortVariant("fr", "FR", "foo");
1570 shortVariant.getDisplayVariant(got);
1571
1572 if(got != "FOO") {
1573 errln("FAIL: getDisplayVariant()");
1574 errln("Wanted: foo");
1575 errln("Got : " + got);
1576 }
1577
1578 Locale bogusVariant("fr", "FR", "_foo");
1579 bogusVariant.getDisplayVariant(got);
1580
1581 if(got != "FOO") {
1582 errln("FAIL: getDisplayVariant()");
1583 errln("Wanted: foo");
1584 errln("Got : " + got);
1585 }
1586
1587 Locale bogusVariant2("fr", "FR", "foo_");
1588 bogusVariant2.getDisplayVariant(got);
1589
1590 if(got != "FOO") {
1591 errln("FAIL: getDisplayVariant()");
1592 errln("Wanted: foo");
1593 errln("Got : " + got);
1594 }
1595
1596 Locale bogusVariant3("fr", "FR", "_foo_");
1597 bogusVariant3.getDisplayVariant(got);
1598
1599 if(got != "FOO") {
1600 errln("FAIL: getDisplayVariant()");
1601 errln("Wanted: foo");
1602 errln("Got : " + got);
1603 }
1604 }
1605
Test20639_DeprecatesISO3Language()1606 void LocaleTest::Test20639_DeprecatesISO3Language() {
1607 IcuTestErrorCode status(*this, "Test20639_DeprecatesISO3Language");
1608
1609 const struct TestCase {
1610 const char* localeName;
1611 const char* expectedISO3Language;
1612 } cases[] = {
1613 {"nb", "nob"},
1614 {"no", "nor"}, // why not nob?
1615 {"he", "heb"},
1616 {"iw", "heb"},
1617 {"ro", "ron"},
1618 {"mo", "mol"},
1619 };
1620 for (auto& cas : cases) {
1621 Locale loc(cas.localeName);
1622 const char* actual = loc.getISO3Language();
1623 assertEquals(cas.localeName, cas.expectedISO3Language, actual);
1624 }
1625 }
1626
1627 #if !UCONFIG_NO_FORMATTING
1628
1629 /**
1630 * @bug 4105828
1631 * Currency symbol in zh is wrong. We will test this at the NumberFormat
1632 * end to test the whole pipe.
1633 */
1634 void
Test4105828()1635 LocaleTest::Test4105828()
1636 {
1637 Locale LOC [] = { Locale::getChinese(), Locale("zh", "CN", ""),
1638 Locale("zh", "TW", ""), Locale("zh", "HK", "") };
1639 UErrorCode status = U_ZERO_ERROR;
1640 for (int32_t i = 0; i < 4; ++i) {
1641 NumberFormat *fmt = NumberFormat::createPercentInstance(LOC[i], status);
1642 if(U_FAILURE(status)) {
1643 dataerrln("Couldn't create NumberFormat - %s", u_errorName(status));
1644 return;
1645 }
1646 UnicodeString result;
1647 FieldPosition pos(FieldPosition::DONT_CARE);
1648 fmt->format((int32_t)1, result, pos);
1649 UnicodeString temp;
1650 if(result != "100%") {
1651 errln(UnicodeString("Percent for ") + LOC[i].getDisplayName(temp) + " should be 100%, got " + result);
1652 }
1653 delete fmt;
1654 }
1655 }
1656
1657 #endif
1658
1659 // Tests setBogus and isBogus APIs for Locale
1660 // Jitterbug 1735
1661 void
TestSetIsBogus()1662 LocaleTest::TestSetIsBogus() {
1663 Locale l("en_US");
1664 l.setToBogus();
1665 if(l.isBogus() != true) {
1666 errln("After setting bogus, didn't return true");
1667 }
1668 l = "en_US"; // This should reset bogus
1669 if(l.isBogus() != false) {
1670 errln("After resetting bogus, didn't return false");
1671 }
1672 }
1673
1674
1675 void
TestAddLikelySubtags()1676 LocaleTest::TestAddLikelySubtags() {
1677 IcuTestErrorCode status(*this, "TestAddLikelySubtags()");
1678
1679 static const Locale min("sv");
1680 static const Locale max("sv_Latn_SE");
1681
1682 Locale result(min);
1683 result.addLikelySubtags(status);
1684 status.errIfFailureAndReset("\"%s\"", min.getName());
1685 assertEquals("addLikelySubtags", max.getName(), result.getName());
1686 }
1687
1688
1689 void
TestMinimizeSubtags()1690 LocaleTest::TestMinimizeSubtags() {
1691 IcuTestErrorCode status(*this, "TestMinimizeSubtags()");
1692
1693 static const Locale max("zh_Hant_TW");
1694 static const Locale min("zh_TW");
1695
1696 Locale result(max);
1697 result.minimizeSubtags(status);
1698 status.errIfFailureAndReset("\"%s\"", max.getName());
1699 assertEquals("minimizeSubtags", min.getName(), result.getName());
1700 }
1701
1702
1703 void
TestAddLikelyAndMinimizeSubtags()1704 LocaleTest::TestAddLikelyAndMinimizeSubtags() {
1705 IcuTestErrorCode status(*this, "TestAddLikelyAndMinimizeSubtags()");
1706
1707 static const struct {
1708 const char* const from;
1709 const char* const add;
1710 const char* const remove;
1711 } full_data[] = {
1712 {
1713 "und_AQ",
1714 "_Latn_AQ",
1715 "_AQ"
1716 }, {
1717 "und_Zzzz_AQ",
1718 "_Latn_AQ",
1719 "_AQ"
1720 }, {
1721 "und_Latn_AQ",
1722 "_Latn_AQ",
1723 "_AQ"
1724 }, {
1725 "und_Moon_AQ",
1726 "_Moon_AQ",
1727 "_Moon_AQ"
1728 }, {
1729 "aa",
1730 "aa_Latn_ET",
1731 "aa"
1732 }, {
1733 "af",
1734 "af_Latn_ZA",
1735 "af"
1736 }, {
1737 "ak",
1738 "ak_Latn_GH",
1739 "ak"
1740 }, {
1741 "am",
1742 "am_Ethi_ET",
1743 "am"
1744 }, {
1745 "ar",
1746 "ar_Arab_EG",
1747 "ar"
1748 }, {
1749 "as",
1750 "as_Beng_IN",
1751 "as"
1752 }, {
1753 "az",
1754 "az_Latn_AZ",
1755 "az"
1756 }, {
1757 "be",
1758 "be_Cyrl_BY",
1759 "be"
1760 }, {
1761 "bg",
1762 "bg_Cyrl_BG",
1763 "bg"
1764 }, {
1765 "bn",
1766 "bn_Beng_BD",
1767 "bn"
1768 }, {
1769 "bo",
1770 "bo_Tibt_CN",
1771 "bo"
1772 }, {
1773 "bs",
1774 "bs_Latn_BA",
1775 "bs"
1776 }, {
1777 "ca",
1778 "ca_Latn_ES",
1779 "ca"
1780 }, {
1781 "ch",
1782 "ch_Latn_GU",
1783 "ch"
1784 }, {
1785 "chk",
1786 "chk_Latn_FM",
1787 "chk"
1788 }, {
1789 "cs",
1790 "cs_Latn_CZ",
1791 "cs"
1792 }, {
1793 "cy",
1794 "cy_Latn_GB",
1795 "cy"
1796 }, {
1797 "da",
1798 "da_Latn_DK",
1799 "da"
1800 }, {
1801 "de",
1802 "de_Latn_DE",
1803 "de"
1804 }, {
1805 "dv",
1806 "dv_Thaa_MV",
1807 "dv"
1808 }, {
1809 "dz",
1810 "dz_Tibt_BT",
1811 "dz"
1812 }, {
1813 "ee",
1814 "ee_Latn_GH",
1815 "ee"
1816 }, {
1817 "el",
1818 "el_Grek_GR",
1819 "el"
1820 }, {
1821 "en",
1822 "en_Latn_US",
1823 "en"
1824 }, {
1825 "es",
1826 "es_Latn_ES",
1827 "es"
1828 }, {
1829 "et",
1830 "et_Latn_EE",
1831 "et"
1832 }, {
1833 "eu",
1834 "eu_Latn_ES",
1835 "eu"
1836 }, {
1837 "fa",
1838 "fa_Arab_IR",
1839 "fa"
1840 }, {
1841 "fi",
1842 "fi_Latn_FI",
1843 "fi"
1844 }, {
1845 "fil",
1846 "fil_Latn_PH",
1847 "fil"
1848 }, {
1849 "fj",
1850 "fj_Latn_FJ",
1851 "fj"
1852 }, {
1853 "fo",
1854 "fo_Latn_FO",
1855 "fo"
1856 }, {
1857 "fr",
1858 "fr_Latn_FR",
1859 "fr"
1860 }, {
1861 "fur",
1862 "fur_Latn_IT",
1863 "fur"
1864 }, {
1865 "ga",
1866 "ga_Latn_IE",
1867 "ga"
1868 }, {
1869 "gaa",
1870 "gaa_Latn_GH",
1871 "gaa"
1872 }, {
1873 "gl",
1874 "gl_Latn_ES",
1875 "gl"
1876 }, {
1877 "gn",
1878 "gn_Latn_PY",
1879 "gn"
1880 }, {
1881 "gu",
1882 "gu_Gujr_IN",
1883 "gu"
1884 }, {
1885 "ha",
1886 "ha_Latn_NG",
1887 "ha"
1888 }, {
1889 "haw",
1890 "haw_Latn_US",
1891 "haw"
1892 }, {
1893 "he",
1894 "he_Hebr_IL",
1895 "he"
1896 }, {
1897 "hi",
1898 "hi_Deva_IN",
1899 "hi"
1900 }, {
1901 "hr",
1902 "hr_Latn_HR",
1903 "hr"
1904 }, {
1905 "ht",
1906 "ht_Latn_HT",
1907 "ht"
1908 }, {
1909 "hu",
1910 "hu_Latn_HU",
1911 "hu"
1912 }, {
1913 "hy",
1914 "hy_Armn_AM",
1915 "hy"
1916 }, {
1917 "id",
1918 "id_Latn_ID",
1919 "id"
1920 }, {
1921 "ig",
1922 "ig_Latn_NG",
1923 "ig"
1924 }, {
1925 "ii",
1926 "ii_Yiii_CN",
1927 "ii"
1928 }, {
1929 "is",
1930 "is_Latn_IS",
1931 "is"
1932 }, {
1933 "it",
1934 "it_Latn_IT",
1935 "it"
1936 }, {
1937 "ja",
1938 "ja_Jpan_JP",
1939 "ja"
1940 }, {
1941 "ka",
1942 "ka_Geor_GE",
1943 "ka"
1944 }, {
1945 "kaj",
1946 "kaj_Latn_NG",
1947 "kaj"
1948 }, {
1949 "kam",
1950 "kam_Latn_KE",
1951 "kam"
1952 }, {
1953 "kk",
1954 "kk_Cyrl_KZ",
1955 "kk"
1956 }, {
1957 "kl",
1958 "kl_Latn_GL",
1959 "kl"
1960 }, {
1961 "km",
1962 "km_Khmr_KH",
1963 "km"
1964 }, {
1965 "kn",
1966 "kn_Knda_IN",
1967 "kn"
1968 }, {
1969 "ko",
1970 "ko_Kore_KR",
1971 "ko"
1972 }, {
1973 "kok",
1974 "kok_Deva_IN",
1975 "kok"
1976 }, {
1977 "kpe",
1978 "kpe_Latn_LR",
1979 "kpe"
1980 }, {
1981 "ku",
1982 "ku_Latn_TR",
1983 "ku"
1984 }, {
1985 "ky",
1986 "ky_Cyrl_KG",
1987 "ky"
1988 }, {
1989 "la",
1990 "la_Latn_VA",
1991 "la"
1992 }, {
1993 "ln",
1994 "ln_Latn_CD",
1995 "ln"
1996 }, {
1997 "lo",
1998 "lo_Laoo_LA",
1999 "lo"
2000 }, {
2001 "lt",
2002 "lt_Latn_LT",
2003 "lt"
2004 }, {
2005 "lv",
2006 "lv_Latn_LV",
2007 "lv"
2008 }, {
2009 "mg",
2010 "mg_Latn_MG",
2011 "mg"
2012 }, {
2013 "mh",
2014 "mh_Latn_MH",
2015 "mh"
2016 }, {
2017 "mk",
2018 "mk_Cyrl_MK",
2019 "mk"
2020 }, {
2021 "ml",
2022 "ml_Mlym_IN",
2023 "ml"
2024 }, {
2025 "mn",
2026 "mn_Cyrl_MN",
2027 "mn"
2028 }, {
2029 "mr",
2030 "mr_Deva_IN",
2031 "mr"
2032 }, {
2033 "ms",
2034 "ms_Latn_MY",
2035 "ms"
2036 }, {
2037 "mt",
2038 "mt_Latn_MT",
2039 "mt"
2040 }, {
2041 "my",
2042 "my_Mymr_MM",
2043 "my"
2044 }, {
2045 "na",
2046 "na_Latn_NR",
2047 "na"
2048 }, {
2049 "ne",
2050 "ne_Deva_NP",
2051 "ne"
2052 }, {
2053 "niu",
2054 "niu_Latn_NU",
2055 "niu"
2056 }, {
2057 "nl",
2058 "nl_Latn_NL",
2059 "nl"
2060 }, {
2061 "nn",
2062 "nn_Latn_NO",
2063 "nn"
2064 }, {
2065 "no",
2066 "no_Latn_NO",
2067 "no"
2068 }, {
2069 "nr",
2070 "nr_Latn_ZA",
2071 "nr"
2072 }, {
2073 "nso",
2074 "nso_Latn_ZA",
2075 "nso"
2076 }, {
2077 "om",
2078 "om_Latn_ET",
2079 "om"
2080 }, {
2081 "or",
2082 "or_Orya_IN",
2083 "or"
2084 }, {
2085 "pa",
2086 "pa_Guru_IN",
2087 "pa"
2088 }, {
2089 "pa_Arab",
2090 "pa_Arab_PK",
2091 "pa_PK"
2092 }, {
2093 "pa_PK",
2094 "pa_Arab_PK",
2095 "pa_PK"
2096 }, {
2097 "pap",
2098 "pap_Latn_AW",
2099 "pap"
2100 }, {
2101 "pau",
2102 "pau_Latn_PW",
2103 "pau"
2104 }, {
2105 "pl",
2106 "pl_Latn_PL",
2107 "pl"
2108 }, {
2109 "ps",
2110 "ps_Arab_AF",
2111 "ps"
2112 }, {
2113 "pt",
2114 "pt_Latn_BR",
2115 "pt"
2116 }, {
2117 "rn",
2118 "rn_Latn_BI",
2119 "rn"
2120 }, {
2121 "ro",
2122 "ro_Latn_RO",
2123 "ro"
2124 }, {
2125 "ru",
2126 "ru_Cyrl_RU",
2127 "ru"
2128 }, {
2129 "rw",
2130 "rw_Latn_RW",
2131 "rw"
2132 }, {
2133 "sa",
2134 "sa_Deva_IN",
2135 "sa"
2136 }, {
2137 "se",
2138 "se_Latn_NO",
2139 "se"
2140 }, {
2141 "sg",
2142 "sg_Latn_CF",
2143 "sg"
2144 }, {
2145 "si",
2146 "si_Sinh_LK",
2147 "si"
2148 }, {
2149 "sid",
2150 "sid_Latn_ET",
2151 "sid"
2152 }, {
2153 "sk",
2154 "sk_Latn_SK",
2155 "sk"
2156 }, {
2157 "sl",
2158 "sl_Latn_SI",
2159 "sl"
2160 }, {
2161 "sm",
2162 "sm_Latn_WS",
2163 "sm"
2164 }, {
2165 "so",
2166 "so_Latn_SO",
2167 "so"
2168 }, {
2169 "sq",
2170 "sq_Latn_AL",
2171 "sq"
2172 }, {
2173 "sr",
2174 "sr_Cyrl_RS",
2175 "sr"
2176 }, {
2177 "ss",
2178 "ss_Latn_ZA",
2179 "ss"
2180 }, {
2181 "st",
2182 "st_Latn_ZA",
2183 "st"
2184 }, {
2185 "sv",
2186 "sv_Latn_SE",
2187 "sv"
2188 }, {
2189 "sw",
2190 "sw_Latn_TZ",
2191 "sw"
2192 }, {
2193 "ta",
2194 "ta_Taml_IN",
2195 "ta"
2196 }, {
2197 "te",
2198 "te_Telu_IN",
2199 "te"
2200 }, {
2201 "tet",
2202 "tet_Latn_TL",
2203 "tet"
2204 }, {
2205 "tg",
2206 "tg_Cyrl_TJ",
2207 "tg"
2208 }, {
2209 "th",
2210 "th_Thai_TH",
2211 "th"
2212 }, {
2213 "ti",
2214 "ti_Ethi_ET",
2215 "ti"
2216 }, {
2217 "tig",
2218 "tig_Ethi_ER",
2219 "tig"
2220 }, {
2221 "tk",
2222 "tk_Latn_TM",
2223 "tk"
2224 }, {
2225 "tkl",
2226 "tkl_Latn_TK",
2227 "tkl"
2228 }, {
2229 "tn",
2230 "tn_Latn_ZA",
2231 "tn"
2232 }, {
2233 "to",
2234 "to_Latn_TO",
2235 "to"
2236 }, {
2237 "tpi",
2238 "tpi_Latn_PG",
2239 "tpi"
2240 }, {
2241 "tr",
2242 "tr_Latn_TR",
2243 "tr"
2244 }, {
2245 "ts",
2246 "ts_Latn_ZA",
2247 "ts"
2248 }, {
2249 "tt",
2250 "tt_Cyrl_RU",
2251 "tt"
2252 }, {
2253 "tvl",
2254 "tvl_Latn_TV",
2255 "tvl"
2256 }, {
2257 "ty",
2258 "ty_Latn_PF",
2259 "ty"
2260 }, {
2261 "uk",
2262 "uk_Cyrl_UA",
2263 "uk"
2264 }, {
2265 "und",
2266 "en_Latn_US",
2267 "en"
2268 }, {
2269 "und_AD",
2270 "ca_Latn_AD",
2271 "ca_AD"
2272 }, {
2273 "und_AE",
2274 "ar_Arab_AE",
2275 "ar_AE"
2276 }, {
2277 "und_AF",
2278 "fa_Arab_AF",
2279 "fa_AF"
2280 }, {
2281 "und_AL",
2282 "sq_Latn_AL",
2283 "sq"
2284 }, {
2285 "und_AM",
2286 "hy_Armn_AM",
2287 "hy"
2288 }, {
2289 "und_AO",
2290 "pt_Latn_AO",
2291 "pt_AO"
2292 }, {
2293 "und_AR",
2294 "es_Latn_AR",
2295 "es_AR"
2296 }, {
2297 "und_AS",
2298 "sm_Latn_AS",
2299 "sm_AS"
2300 }, {
2301 "und_AT",
2302 "de_Latn_AT",
2303 "de_AT"
2304 }, {
2305 "und_AW",
2306 "nl_Latn_AW",
2307 "nl_AW"
2308 }, {
2309 "und_AX",
2310 "sv_Latn_AX",
2311 "sv_AX"
2312 }, {
2313 "und_AZ",
2314 "az_Latn_AZ",
2315 "az"
2316 }, {
2317 "und_Arab",
2318 "ar_Arab_EG",
2319 "ar"
2320 }, {
2321 "und_Arab_IN",
2322 "ur_Arab_IN",
2323 "ur_IN"
2324 }, {
2325 "und_Arab_PK",
2326 "ur_Arab_PK",
2327 "ur"
2328 }, {
2329 "und_Arab_SN",
2330 "ar_Arab_SN",
2331 "ar_SN"
2332 }, {
2333 "und_Armn",
2334 "hy_Armn_AM",
2335 "hy"
2336 }, {
2337 "und_BA",
2338 "bs_Latn_BA",
2339 "bs"
2340 }, {
2341 "und_BD",
2342 "bn_Beng_BD",
2343 "bn"
2344 }, {
2345 "und_BE",
2346 "nl_Latn_BE",
2347 "nl_BE"
2348 }, {
2349 "und_BF",
2350 "fr_Latn_BF",
2351 "fr_BF"
2352 }, {
2353 "und_BG",
2354 "bg_Cyrl_BG",
2355 "bg"
2356 }, {
2357 "und_BH",
2358 "ar_Arab_BH",
2359 "ar_BH"
2360 }, {
2361 "und_BI",
2362 "rn_Latn_BI",
2363 "rn"
2364 }, {
2365 "und_BJ",
2366 "fr_Latn_BJ",
2367 "fr_BJ"
2368 }, {
2369 "und_BN",
2370 "ms_Latn_BN",
2371 "ms_BN"
2372 }, {
2373 "und_BO",
2374 "es_Latn_BO",
2375 "es_BO"
2376 }, {
2377 "und_BR",
2378 "pt_Latn_BR",
2379 "pt"
2380 }, {
2381 "und_BT",
2382 "dz_Tibt_BT",
2383 "dz"
2384 }, {
2385 "und_BY",
2386 "be_Cyrl_BY",
2387 "be"
2388 }, {
2389 "und_Beng",
2390 "bn_Beng_BD",
2391 "bn"
2392 }, {
2393 "und_Beng_IN",
2394 "bn_Beng_IN",
2395 "bn_IN"
2396 }, {
2397 "und_CD",
2398 "sw_Latn_CD",
2399 "sw_CD"
2400 }, {
2401 "und_CF",
2402 "fr_Latn_CF",
2403 "fr_CF"
2404 }, {
2405 "und_CG",
2406 "fr_Latn_CG",
2407 "fr_CG"
2408 }, {
2409 "und_CH",
2410 "de_Latn_CH",
2411 "de_CH"
2412 }, {
2413 "und_CI",
2414 "fr_Latn_CI",
2415 "fr_CI"
2416 }, {
2417 "und_CL",
2418 "es_Latn_CL",
2419 "es_CL"
2420 }, {
2421 "und_CM",
2422 "fr_Latn_CM",
2423 "fr_CM"
2424 }, {
2425 "und_CN",
2426 "zh_Hans_CN",
2427 "zh"
2428 }, {
2429 "und_CO",
2430 "es_Latn_CO",
2431 "es_CO"
2432 }, {
2433 "und_CR",
2434 "es_Latn_CR",
2435 "es_CR"
2436 }, {
2437 "und_CU",
2438 "es_Latn_CU",
2439 "es_CU"
2440 }, {
2441 "und_CV",
2442 "pt_Latn_CV",
2443 "pt_CV"
2444 }, {
2445 "und_CY",
2446 "el_Grek_CY",
2447 "el_CY"
2448 }, {
2449 "und_CZ",
2450 "cs_Latn_CZ",
2451 "cs"
2452 }, {
2453 "und_Cyrl",
2454 "ru_Cyrl_RU",
2455 "ru"
2456 }, {
2457 "und_Cyrl_KZ",
2458 "ru_Cyrl_KZ",
2459 "ru_KZ"
2460 }, {
2461 "und_DE",
2462 "de_Latn_DE",
2463 "de"
2464 }, {
2465 "und_DJ",
2466 "aa_Latn_DJ",
2467 "aa_DJ"
2468 }, {
2469 "und_DK",
2470 "da_Latn_DK",
2471 "da"
2472 }, {
2473 "und_DO",
2474 "es_Latn_DO",
2475 "es_DO"
2476 }, {
2477 "und_DZ",
2478 "ar_Arab_DZ",
2479 "ar_DZ"
2480 }, {
2481 "und_Deva",
2482 "hi_Deva_IN",
2483 "hi"
2484 }, {
2485 "und_EC",
2486 "es_Latn_EC",
2487 "es_EC"
2488 }, {
2489 "und_EE",
2490 "et_Latn_EE",
2491 "et"
2492 }, {
2493 "und_EG",
2494 "ar_Arab_EG",
2495 "ar"
2496 }, {
2497 "und_EH",
2498 "ar_Arab_EH",
2499 "ar_EH"
2500 }, {
2501 "und_ER",
2502 "ti_Ethi_ER",
2503 "ti_ER"
2504 }, {
2505 "und_ES",
2506 "es_Latn_ES",
2507 "es"
2508 }, {
2509 "und_ET",
2510 "am_Ethi_ET",
2511 "am"
2512 }, {
2513 "und_Ethi",
2514 "am_Ethi_ET",
2515 "am"
2516 }, {
2517 "und_Ethi_ER",
2518 "am_Ethi_ER",
2519 "am_ER"
2520 }, {
2521 "und_FI",
2522 "fi_Latn_FI",
2523 "fi"
2524 }, {
2525 "und_FM",
2526 "en_Latn_FM",
2527 "en_FM"
2528 }, {
2529 "und_FO",
2530 "fo_Latn_FO",
2531 "fo"
2532 }, {
2533 "und_FR",
2534 "fr_Latn_FR",
2535 "fr"
2536 }, {
2537 "und_GA",
2538 "fr_Latn_GA",
2539 "fr_GA"
2540 }, {
2541 "und_GE",
2542 "ka_Geor_GE",
2543 "ka"
2544 }, {
2545 "und_GF",
2546 "fr_Latn_GF",
2547 "fr_GF"
2548 }, {
2549 "und_GL",
2550 "kl_Latn_GL",
2551 "kl"
2552 }, {
2553 "und_GN",
2554 "fr_Latn_GN",
2555 "fr_GN"
2556 }, {
2557 "und_GP",
2558 "fr_Latn_GP",
2559 "fr_GP"
2560 }, {
2561 "und_GQ",
2562 "es_Latn_GQ",
2563 "es_GQ"
2564 }, {
2565 "und_GR",
2566 "el_Grek_GR",
2567 "el"
2568 }, {
2569 "und_GT",
2570 "es_Latn_GT",
2571 "es_GT"
2572 }, {
2573 "und_GU",
2574 "en_Latn_GU",
2575 "en_GU"
2576 }, {
2577 "und_GW",
2578 "pt_Latn_GW",
2579 "pt_GW"
2580 }, {
2581 "und_Geor",
2582 "ka_Geor_GE",
2583 "ka"
2584 }, {
2585 "und_Grek",
2586 "el_Grek_GR",
2587 "el"
2588 }, {
2589 "und_Gujr",
2590 "gu_Gujr_IN",
2591 "gu"
2592 }, {
2593 "und_Guru",
2594 "pa_Guru_IN",
2595 "pa"
2596 }, {
2597 "und_HK",
2598 "zh_Hant_HK",
2599 "zh_HK"
2600 }, {
2601 "und_HN",
2602 "es_Latn_HN",
2603 "es_HN"
2604 }, {
2605 "und_HR",
2606 "hr_Latn_HR",
2607 "hr"
2608 }, {
2609 "und_HT",
2610 "ht_Latn_HT",
2611 "ht"
2612 }, {
2613 "und_HU",
2614 "hu_Latn_HU",
2615 "hu"
2616 }, {
2617 "und_Hani",
2618 "zh_Hani_CN",
2619 "zh_Hani"
2620 }, {
2621 "und_Hans",
2622 "zh_Hans_CN",
2623 "zh"
2624 }, {
2625 "und_Hant",
2626 "zh_Hant_TW",
2627 "zh_TW"
2628 }, {
2629 "und_Hebr",
2630 "he_Hebr_IL",
2631 "he"
2632 }, {
2633 "und_ID",
2634 "id_Latn_ID",
2635 "id"
2636 }, {
2637 "und_IL",
2638 "he_Hebr_IL",
2639 "he"
2640 }, {
2641 "und_IN",
2642 "hi_Deva_IN",
2643 "hi"
2644 }, {
2645 "und_IQ",
2646 "ar_Arab_IQ",
2647 "ar_IQ"
2648 }, {
2649 "und_IR",
2650 "fa_Arab_IR",
2651 "fa"
2652 }, {
2653 "und_IS",
2654 "is_Latn_IS",
2655 "is"
2656 }, {
2657 "und_IT",
2658 "it_Latn_IT",
2659 "it"
2660 }, {
2661 "und_JO",
2662 "ar_Arab_JO",
2663 "ar_JO"
2664 }, {
2665 "und_JP",
2666 "ja_Jpan_JP",
2667 "ja"
2668 }, {
2669 "und_Jpan",
2670 "ja_Jpan_JP",
2671 "ja"
2672 }, {
2673 "und_KG",
2674 "ky_Cyrl_KG",
2675 "ky"
2676 }, {
2677 "und_KH",
2678 "km_Khmr_KH",
2679 "km"
2680 }, {
2681 "und_KM",
2682 "ar_Arab_KM",
2683 "ar_KM"
2684 }, {
2685 "und_KP",
2686 "ko_Kore_KP",
2687 "ko_KP"
2688 }, {
2689 "und_KR",
2690 "ko_Kore_KR",
2691 "ko"
2692 }, {
2693 "und_KW",
2694 "ar_Arab_KW",
2695 "ar_KW"
2696 }, {
2697 "und_KZ",
2698 "ru_Cyrl_KZ",
2699 "ru_KZ"
2700 }, {
2701 "und_Khmr",
2702 "km_Khmr_KH",
2703 "km"
2704 }, {
2705 "und_Knda",
2706 "kn_Knda_IN",
2707 "kn"
2708 }, {
2709 "und_Kore",
2710 "ko_Kore_KR",
2711 "ko"
2712 }, {
2713 "und_LA",
2714 "lo_Laoo_LA",
2715 "lo"
2716 }, {
2717 "und_LB",
2718 "ar_Arab_LB",
2719 "ar_LB"
2720 }, {
2721 "und_LI",
2722 "de_Latn_LI",
2723 "de_LI"
2724 }, {
2725 "und_LK",
2726 "si_Sinh_LK",
2727 "si"
2728 }, {
2729 "und_LS",
2730 "st_Latn_LS",
2731 "st_LS"
2732 }, {
2733 "und_LT",
2734 "lt_Latn_LT",
2735 "lt"
2736 }, {
2737 "und_LU",
2738 "fr_Latn_LU",
2739 "fr_LU"
2740 }, {
2741 "und_LV",
2742 "lv_Latn_LV",
2743 "lv"
2744 }, {
2745 "und_LY",
2746 "ar_Arab_LY",
2747 "ar_LY"
2748 }, {
2749 "und_Laoo",
2750 "lo_Laoo_LA",
2751 "lo"
2752 }, {
2753 "und_Latn_ES",
2754 "es_Latn_ES",
2755 "es"
2756 }, {
2757 "und_Latn_ET",
2758 "en_Latn_ET",
2759 "en_ET"
2760 }, {
2761 "und_Latn_GB",
2762 "en_Latn_GB",
2763 "en_GB"
2764 }, {
2765 "und_Latn_GH",
2766 "ak_Latn_GH",
2767 "ak"
2768 }, {
2769 "und_Latn_ID",
2770 "id_Latn_ID",
2771 "id"
2772 }, {
2773 "und_Latn_IT",
2774 "it_Latn_IT",
2775 "it"
2776 }, {
2777 "und_Latn_NG",
2778 "en_Latn_NG",
2779 "en_NG"
2780 }, {
2781 "und_Latn_TR",
2782 "tr_Latn_TR",
2783 "tr"
2784 }, {
2785 "und_Latn_ZA",
2786 "en_Latn_ZA",
2787 "en_ZA"
2788 }, {
2789 "und_MA",
2790 "ar_Arab_MA",
2791 "ar_MA"
2792 }, {
2793 "und_MC",
2794 "fr_Latn_MC",
2795 "fr_MC"
2796 }, {
2797 "und_MD",
2798 "ro_Latn_MD",
2799 "ro_MD"
2800 }, {
2801 "und_ME",
2802 "sr_Latn_ME",
2803 "sr_ME"
2804 }, {
2805 "und_MG",
2806 "mg_Latn_MG",
2807 "mg"
2808 }, {
2809 "und_MK",
2810 "mk_Cyrl_MK",
2811 "mk"
2812 }, {
2813 "und_ML",
2814 "bm_Latn_ML",
2815 "bm"
2816 }, {
2817 "und_MM",
2818 "my_Mymr_MM",
2819 "my"
2820 }, {
2821 "und_MN",
2822 "mn_Cyrl_MN",
2823 "mn"
2824 }, {
2825 "und_MO",
2826 "zh_Hant_MO",
2827 "zh_MO"
2828 }, {
2829 "und_MQ",
2830 "fr_Latn_MQ",
2831 "fr_MQ"
2832 }, {
2833 "und_MR",
2834 "ar_Arab_MR",
2835 "ar_MR"
2836 }, {
2837 "und_MT",
2838 "mt_Latn_MT",
2839 "mt"
2840 }, {
2841 "und_MV",
2842 "dv_Thaa_MV",
2843 "dv"
2844 }, {
2845 "und_MX",
2846 "es_Latn_MX",
2847 "es_MX"
2848 }, {
2849 "und_MY",
2850 "ms_Latn_MY",
2851 "ms"
2852 }, {
2853 "und_MZ",
2854 "pt_Latn_MZ",
2855 "pt_MZ"
2856 }, {
2857 "und_Mlym",
2858 "ml_Mlym_IN",
2859 "ml"
2860 }, {
2861 "und_Mymr",
2862 "my_Mymr_MM",
2863 "my"
2864 }, {
2865 "und_NC",
2866 "fr_Latn_NC",
2867 "fr_NC"
2868 }, {
2869 "und_NE",
2870 "ha_Latn_NE",
2871 "ha_NE"
2872 }, {
2873 "und_NG",
2874 "en_Latn_NG",
2875 "en_NG"
2876 }, {
2877 "und_NI",
2878 "es_Latn_NI",
2879 "es_NI"
2880 }, {
2881 "und_NL",
2882 "nl_Latn_NL",
2883 "nl"
2884 }, {
2885 "und_NO",
2886 "nb_Latn_NO",
2887 "nb"
2888 }, {
2889 "und_NP",
2890 "ne_Deva_NP",
2891 "ne"
2892 }, {
2893 "und_NR",
2894 "en_Latn_NR",
2895 "en_NR"
2896 }, {
2897 "und_OM",
2898 "ar_Arab_OM",
2899 "ar_OM"
2900 }, {
2901 "und_Orya",
2902 "or_Orya_IN",
2903 "or"
2904 }, {
2905 "und_PA",
2906 "es_Latn_PA",
2907 "es_PA"
2908 }, {
2909 "und_PE",
2910 "es_Latn_PE",
2911 "es_PE"
2912 }, {
2913 "und_PF",
2914 "fr_Latn_PF",
2915 "fr_PF"
2916 }, {
2917 "und_PG",
2918 "tpi_Latn_PG",
2919 "tpi"
2920 }, {
2921 "und_PH",
2922 "fil_Latn_PH",
2923 "fil"
2924 }, {
2925 "und_PL",
2926 "pl_Latn_PL",
2927 "pl"
2928 }, {
2929 "und_PM",
2930 "fr_Latn_PM",
2931 "fr_PM"
2932 }, {
2933 "und_PR",
2934 "es_Latn_PR",
2935 "es_PR"
2936 }, {
2937 "und_PS",
2938 "ar_Arab_PS",
2939 "ar_PS"
2940 }, {
2941 "und_PT",
2942 "pt_Latn_PT",
2943 "pt_PT"
2944 }, {
2945 "und_PW",
2946 "pau_Latn_PW",
2947 "pau"
2948 }, {
2949 "und_PY",
2950 "gn_Latn_PY",
2951 "gn"
2952 }, {
2953 "und_QA",
2954 "ar_Arab_QA",
2955 "ar_QA"
2956 }, {
2957 "und_RE",
2958 "fr_Latn_RE",
2959 "fr_RE"
2960 }, {
2961 "und_RO",
2962 "ro_Latn_RO",
2963 "ro"
2964 }, {
2965 "und_RS",
2966 "sr_Cyrl_RS",
2967 "sr"
2968 }, {
2969 "und_RU",
2970 "ru_Cyrl_RU",
2971 "ru"
2972 }, {
2973 "und_RW",
2974 "rw_Latn_RW",
2975 "rw"
2976 }, {
2977 "und_SA",
2978 "ar_Arab_SA",
2979 "ar_SA"
2980 }, {
2981 "und_SD",
2982 "ar_Arab_SD",
2983 "ar_SD"
2984 }, {
2985 "und_SE",
2986 "sv_Latn_SE",
2987 "sv"
2988 }, {
2989 "und_SG",
2990 "en_Latn_SG",
2991 "en_SG"
2992 }, {
2993 "und_SI",
2994 "sl_Latn_SI",
2995 "sl"
2996 }, {
2997 "und_SJ",
2998 "nb_Latn_SJ",
2999 "nb_SJ"
3000 }, {
3001 "und_SK",
3002 "sk_Latn_SK",
3003 "sk"
3004 }, {
3005 "und_SM",
3006 "it_Latn_SM",
3007 "it_SM"
3008 }, {
3009 "und_SN",
3010 "fr_Latn_SN",
3011 "fr_SN"
3012 }, {
3013 "und_SO",
3014 "so_Latn_SO",
3015 "so"
3016 }, {
3017 "und_SR",
3018 "nl_Latn_SR",
3019 "nl_SR"
3020 }, {
3021 "und_ST",
3022 "pt_Latn_ST",
3023 "pt_ST"
3024 }, {
3025 "und_SV",
3026 "es_Latn_SV",
3027 "es_SV"
3028 }, {
3029 "und_SY",
3030 "ar_Arab_SY",
3031 "ar_SY"
3032 }, {
3033 "und_Sinh",
3034 "si_Sinh_LK",
3035 "si"
3036 }, {
3037 "und_Syrc",
3038 "syr_Syrc_IQ",
3039 "syr"
3040 }, {
3041 "und_TD",
3042 "fr_Latn_TD",
3043 "fr_TD"
3044 }, {
3045 "und_TG",
3046 "fr_Latn_TG",
3047 "fr_TG"
3048 }, {
3049 "und_TH",
3050 "th_Thai_TH",
3051 "th"
3052 }, {
3053 "und_TJ",
3054 "tg_Cyrl_TJ",
3055 "tg"
3056 }, {
3057 "und_TK",
3058 "tkl_Latn_TK",
3059 "tkl"
3060 }, {
3061 "und_TL",
3062 "pt_Latn_TL",
3063 "pt_TL"
3064 }, {
3065 "und_TM",
3066 "tk_Latn_TM",
3067 "tk"
3068 }, {
3069 "und_TN",
3070 "ar_Arab_TN",
3071 "ar_TN"
3072 }, {
3073 "und_TO",
3074 "to_Latn_TO",
3075 "to"
3076 }, {
3077 "und_TR",
3078 "tr_Latn_TR",
3079 "tr"
3080 }, {
3081 "und_TV",
3082 "tvl_Latn_TV",
3083 "tvl"
3084 }, {
3085 "und_TW",
3086 "zh_Hant_TW",
3087 "zh_TW"
3088 }, {
3089 "und_Taml",
3090 "ta_Taml_IN",
3091 "ta"
3092 }, {
3093 "und_Telu",
3094 "te_Telu_IN",
3095 "te"
3096 }, {
3097 "und_Thaa",
3098 "dv_Thaa_MV",
3099 "dv"
3100 }, {
3101 "und_Thai",
3102 "th_Thai_TH",
3103 "th"
3104 }, {
3105 "und_Tibt",
3106 "bo_Tibt_CN",
3107 "bo"
3108 }, {
3109 "und_UA",
3110 "uk_Cyrl_UA",
3111 "uk"
3112 }, {
3113 "und_UY",
3114 "es_Latn_UY",
3115 "es_UY"
3116 }, {
3117 "und_UZ",
3118 "uz_Latn_UZ",
3119 "uz"
3120 }, {
3121 "und_VA",
3122 "it_Latn_VA",
3123 "it_VA"
3124 }, {
3125 "und_VE",
3126 "es_Latn_VE",
3127 "es_VE"
3128 }, {
3129 "und_VN",
3130 "vi_Latn_VN",
3131 "vi"
3132 }, {
3133 "und_VU",
3134 "bi_Latn_VU",
3135 "bi"
3136 }, {
3137 "und_WF",
3138 "fr_Latn_WF",
3139 "fr_WF"
3140 }, {
3141 "und_WS",
3142 "sm_Latn_WS",
3143 "sm"
3144 }, {
3145 "und_YE",
3146 "ar_Arab_YE",
3147 "ar_YE"
3148 }, {
3149 "und_YT",
3150 "fr_Latn_YT",
3151 "fr_YT"
3152 }, {
3153 "und_Yiii",
3154 "ii_Yiii_CN",
3155 "ii"
3156 }, {
3157 "ur",
3158 "ur_Arab_PK",
3159 "ur"
3160 }, {
3161 "uz",
3162 "uz_Latn_UZ",
3163 "uz"
3164 }, {
3165 "uz_AF",
3166 "uz_Arab_AF",
3167 "uz_AF"
3168 }, {
3169 "uz_Arab",
3170 "uz_Arab_AF",
3171 "uz_AF"
3172 }, {
3173 "ve",
3174 "ve_Latn_ZA",
3175 "ve"
3176 }, {
3177 "vi",
3178 "vi_Latn_VN",
3179 "vi"
3180 }, {
3181 "wal",
3182 "wal_Ethi_ET",
3183 "wal"
3184 }, {
3185 "wo",
3186 "wo_Latn_SN",
3187 "wo"
3188 }, {
3189 "wo_SN",
3190 "wo_Latn_SN",
3191 "wo"
3192 }, {
3193 "xh",
3194 "xh_Latn_ZA",
3195 "xh"
3196 }, {
3197 "yo",
3198 "yo_Latn_NG",
3199 "yo"
3200 }, {
3201 "zh",
3202 "zh_Hans_CN",
3203 "zh"
3204 }, {
3205 "zh_HK",
3206 "zh_Hant_HK",
3207 "zh_HK"
3208 }, {
3209 "zh_Hani",
3210 "zh_Hani_CN",
3211 "zh_Hani"
3212 }, {
3213 "zh_Hant",
3214 "zh_Hant_TW",
3215 "zh_TW"
3216 }, {
3217 "zh_MO",
3218 "zh_Hant_MO",
3219 "zh_MO"
3220 }, {
3221 "zh_TW",
3222 "zh_Hant_TW",
3223 "zh_TW"
3224 }, {
3225 "zu",
3226 "zu_Latn_ZA",
3227 "zu"
3228 }, {
3229 "und",
3230 "en_Latn_US",
3231 "en"
3232 }, {
3233 "und_ZZ",
3234 "en_Latn_US",
3235 "en"
3236 }, {
3237 "und_CN",
3238 "zh_Hans_CN",
3239 "zh"
3240 }, {
3241 "und_TW",
3242 "zh_Hant_TW",
3243 "zh_TW"
3244 }, {
3245 "und_HK",
3246 "zh_Hant_HK",
3247 "zh_HK"
3248 }, {
3249 "und_AQ",
3250 "_Latn_AQ",
3251 "_AQ"
3252 }, {
3253 "und_Zzzz",
3254 "en_Latn_US",
3255 "en"
3256 }, {
3257 "und_Zzzz_ZZ",
3258 "en_Latn_US",
3259 "en"
3260 }, {
3261 "und_Zzzz_CN",
3262 "zh_Hans_CN",
3263 "zh"
3264 }, {
3265 "und_Zzzz_TW",
3266 "zh_Hant_TW",
3267 "zh_TW"
3268 }, {
3269 "und_Zzzz_HK",
3270 "zh_Hant_HK",
3271 "zh_HK"
3272 }, {
3273 "und_Zzzz_AQ",
3274 "_Latn_AQ",
3275 "_AQ"
3276 }, {
3277 "und_Latn",
3278 "en_Latn_US",
3279 "en"
3280 }, {
3281 "und_Latn_ZZ",
3282 "en_Latn_US",
3283 "en"
3284 }, {
3285 "und_Latn_CN",
3286 "za_Latn_CN",
3287 "za"
3288 }, {
3289 "und_Latn_TW",
3290 "trv_Latn_TW",
3291 "trv"
3292 }, {
3293 "und_Latn_HK",
3294 "zh_Latn_HK",
3295 "zh_Latn_HK"
3296 }, {
3297 "und_Latn_AQ",
3298 "_Latn_AQ",
3299 "_AQ"
3300 }, {
3301 "und_Hans",
3302 "zh_Hans_CN",
3303 "zh"
3304 }, {
3305 "und_Hans_ZZ",
3306 "zh_Hans_CN",
3307 "zh"
3308 }, {
3309 "und_Hans_CN",
3310 "zh_Hans_CN",
3311 "zh"
3312 }, {
3313 "und_Hans_TW",
3314 "zh_Hans_TW",
3315 "zh_Hans_TW"
3316 }, {
3317 "und_Hans_HK",
3318 "zh_Hans_HK",
3319 "zh_Hans_HK"
3320 }, {
3321 "und_Hans_AQ",
3322 "zh_Hans_AQ",
3323 "zh_AQ"
3324 }, {
3325 "und_Hant",
3326 "zh_Hant_TW",
3327 "zh_TW"
3328 }, {
3329 "und_Hant_ZZ",
3330 "zh_Hant_TW",
3331 "zh_TW"
3332 }, {
3333 "und_Hant_CN",
3334 "zh_Hant_CN",
3335 "zh_Hant_CN"
3336 }, {
3337 "und_Hant_TW",
3338 "zh_Hant_TW",
3339 "zh_TW"
3340 }, {
3341 "und_Hant_HK",
3342 "zh_Hant_HK",
3343 "zh_HK"
3344 }, {
3345 "und_Hant_AQ",
3346 "zh_Hant_AQ",
3347 "zh_Hant_AQ"
3348 }, {
3349 "und_Moon",
3350 "en_Moon_US",
3351 "en_Moon"
3352 }, {
3353 "und_Moon_ZZ",
3354 "en_Moon_US",
3355 "en_Moon"
3356 }, {
3357 "und_Moon_CN",
3358 "zh_Moon_CN",
3359 "zh_Moon"
3360 }, {
3361 "und_Moon_TW",
3362 "zh_Moon_TW",
3363 "zh_Moon_TW"
3364 }, {
3365 "und_Moon_HK",
3366 "zh_Moon_HK",
3367 "zh_Moon_HK"
3368 }, {
3369 "und_Moon_AQ",
3370 "_Moon_AQ",
3371 "_Moon_AQ"
3372 }, {
3373 "es",
3374 "es_Latn_ES",
3375 "es"
3376 }, {
3377 "es_ZZ",
3378 "es_Latn_ES",
3379 "es"
3380 }, {
3381 "es_CN",
3382 "es_Latn_CN",
3383 "es_CN"
3384 }, {
3385 "es_TW",
3386 "es_Latn_TW",
3387 "es_TW"
3388 }, {
3389 "es_HK",
3390 "es_Latn_HK",
3391 "es_HK"
3392 }, {
3393 "es_AQ",
3394 "es_Latn_AQ",
3395 "es_AQ"
3396 }, {
3397 "es_Zzzz",
3398 "es_Latn_ES",
3399 "es"
3400 }, {
3401 "es_Zzzz_ZZ",
3402 "es_Latn_ES",
3403 "es"
3404 }, {
3405 "es_Zzzz_CN",
3406 "es_Latn_CN",
3407 "es_CN"
3408 }, {
3409 "es_Zzzz_TW",
3410 "es_Latn_TW",
3411 "es_TW"
3412 }, {
3413 "es_Zzzz_HK",
3414 "es_Latn_HK",
3415 "es_HK"
3416 }, {
3417 "es_Zzzz_AQ",
3418 "es_Latn_AQ",
3419 "es_AQ"
3420 }, {
3421 "es_Latn",
3422 "es_Latn_ES",
3423 "es"
3424 }, {
3425 "es_Latn_ZZ",
3426 "es_Latn_ES",
3427 "es"
3428 }, {
3429 "es_Latn_CN",
3430 "es_Latn_CN",
3431 "es_CN"
3432 }, {
3433 "es_Latn_TW",
3434 "es_Latn_TW",
3435 "es_TW"
3436 }, {
3437 "es_Latn_HK",
3438 "es_Latn_HK",
3439 "es_HK"
3440 }, {
3441 "es_Latn_AQ",
3442 "es_Latn_AQ",
3443 "es_AQ"
3444 }, {
3445 "es_Hans",
3446 "es_Hans_ES",
3447 "es_Hans"
3448 }, {
3449 "es_Hans_ZZ",
3450 "es_Hans_ES",
3451 "es_Hans"
3452 }, {
3453 "es_Hans_CN",
3454 "es_Hans_CN",
3455 "es_Hans_CN"
3456 }, {
3457 "es_Hans_TW",
3458 "es_Hans_TW",
3459 "es_Hans_TW"
3460 }, {
3461 "es_Hans_HK",
3462 "es_Hans_HK",
3463 "es_Hans_HK"
3464 }, {
3465 "es_Hans_AQ",
3466 "es_Hans_AQ",
3467 "es_Hans_AQ"
3468 }, {
3469 "es_Hant",
3470 "es_Hant_ES",
3471 "es_Hant"
3472 }, {
3473 "es_Hant_ZZ",
3474 "es_Hant_ES",
3475 "es_Hant"
3476 }, {
3477 "es_Hant_CN",
3478 "es_Hant_CN",
3479 "es_Hant_CN"
3480 }, {
3481 "es_Hant_TW",
3482 "es_Hant_TW",
3483 "es_Hant_TW"
3484 }, {
3485 "es_Hant_HK",
3486 "es_Hant_HK",
3487 "es_Hant_HK"
3488 }, {
3489 "es_Hant_AQ",
3490 "es_Hant_AQ",
3491 "es_Hant_AQ"
3492 }, {
3493 "es_Moon",
3494 "es_Moon_ES",
3495 "es_Moon"
3496 }, {
3497 "es_Moon_ZZ",
3498 "es_Moon_ES",
3499 "es_Moon"
3500 }, {
3501 "es_Moon_CN",
3502 "es_Moon_CN",
3503 "es_Moon_CN"
3504 }, {
3505 "es_Moon_TW",
3506 "es_Moon_TW",
3507 "es_Moon_TW"
3508 }, {
3509 "es_Moon_HK",
3510 "es_Moon_HK",
3511 "es_Moon_HK"
3512 }, {
3513 "es_Moon_AQ",
3514 "es_Moon_AQ",
3515 "es_Moon_AQ"
3516 }, {
3517 "zh",
3518 "zh_Hans_CN",
3519 "zh"
3520 }, {
3521 "zh_ZZ",
3522 "zh_Hans_CN",
3523 "zh"
3524 }, {
3525 "zh_CN",
3526 "zh_Hans_CN",
3527 "zh"
3528 }, {
3529 "zh_TW",
3530 "zh_Hant_TW",
3531 "zh_TW"
3532 }, {
3533 "zh_HK",
3534 "zh_Hant_HK",
3535 "zh_HK"
3536 }, {
3537 "zh_AQ",
3538 "zh_Hans_AQ",
3539 "zh_AQ"
3540 }, {
3541 "zh_Zzzz",
3542 "zh_Hans_CN",
3543 "zh"
3544 }, {
3545 "zh_Zzzz_ZZ",
3546 "zh_Hans_CN",
3547 "zh"
3548 }, {
3549 "zh_Zzzz_CN",
3550 "zh_Hans_CN",
3551 "zh"
3552 }, {
3553 "zh_Zzzz_TW",
3554 "zh_Hant_TW",
3555 "zh_TW"
3556 }, {
3557 "zh_Zzzz_HK",
3558 "zh_Hant_HK",
3559 "zh_HK"
3560 }, {
3561 "zh_Zzzz_AQ",
3562 "zh_Hans_AQ",
3563 "zh_AQ"
3564 }, {
3565 "zh_Latn",
3566 "zh_Latn_CN",
3567 "zh_Latn"
3568 }, {
3569 "zh_Latn_ZZ",
3570 "zh_Latn_CN",
3571 "zh_Latn"
3572 }, {
3573 "zh_Latn_CN",
3574 "zh_Latn_CN",
3575 "zh_Latn"
3576 }, {
3577 "zh_Latn_TW",
3578 "zh_Latn_TW",
3579 "zh_Latn_TW"
3580 }, {
3581 "zh_Latn_HK",
3582 "zh_Latn_HK",
3583 "zh_Latn_HK"
3584 }, {
3585 "zh_Latn_AQ",
3586 "zh_Latn_AQ",
3587 "zh_Latn_AQ"
3588 }, {
3589 "zh_Hans",
3590 "zh_Hans_CN",
3591 "zh"
3592 }, {
3593 "zh_Hans_ZZ",
3594 "zh_Hans_CN",
3595 "zh"
3596 }, {
3597 "zh_Hans_TW",
3598 "zh_Hans_TW",
3599 "zh_Hans_TW"
3600 }, {
3601 "zh_Hans_HK",
3602 "zh_Hans_HK",
3603 "zh_Hans_HK"
3604 }, {
3605 "zh_Hans_AQ",
3606 "zh_Hans_AQ",
3607 "zh_AQ"
3608 }, {
3609 "zh_Hant",
3610 "zh_Hant_TW",
3611 "zh_TW"
3612 }, {
3613 "zh_Hant_ZZ",
3614 "zh_Hant_TW",
3615 "zh_TW"
3616 }, {
3617 "zh_Hant_CN",
3618 "zh_Hant_CN",
3619 "zh_Hant_CN"
3620 }, {
3621 "zh_Hant_AQ",
3622 "zh_Hant_AQ",
3623 "zh_Hant_AQ"
3624 }, {
3625 "zh_Moon",
3626 "zh_Moon_CN",
3627 "zh_Moon"
3628 }, {
3629 "zh_Moon_ZZ",
3630 "zh_Moon_CN",
3631 "zh_Moon"
3632 }, {
3633 "zh_Moon_CN",
3634 "zh_Moon_CN",
3635 "zh_Moon"
3636 }, {
3637 "zh_Moon_TW",
3638 "zh_Moon_TW",
3639 "zh_Moon_TW"
3640 }, {
3641 "zh_Moon_HK",
3642 "zh_Moon_HK",
3643 "zh_Moon_HK"
3644 }, {
3645 "zh_Moon_AQ",
3646 "zh_Moon_AQ",
3647 "zh_Moon_AQ"
3648 }, {
3649 "art",
3650 "",
3651 ""
3652 }, {
3653 "art_ZZ",
3654 "",
3655 ""
3656 }, {
3657 "art_CN",
3658 "",
3659 ""
3660 }, {
3661 "art_TW",
3662 "",
3663 ""
3664 }, {
3665 "art_HK",
3666 "",
3667 ""
3668 }, {
3669 "art_AQ",
3670 "",
3671 ""
3672 }, {
3673 "art_Zzzz",
3674 "",
3675 ""
3676 }, {
3677 "art_Zzzz_ZZ",
3678 "",
3679 ""
3680 }, {
3681 "art_Zzzz_CN",
3682 "",
3683 ""
3684 }, {
3685 "art_Zzzz_TW",
3686 "",
3687 ""
3688 }, {
3689 "art_Zzzz_HK",
3690 "",
3691 ""
3692 }, {
3693 "art_Zzzz_AQ",
3694 "",
3695 ""
3696 }, {
3697 "art_Latn",
3698 "",
3699 ""
3700 }, {
3701 "art_Latn_ZZ",
3702 "",
3703 ""
3704 }, {
3705 "art_Latn_CN",
3706 "",
3707 ""
3708 }, {
3709 "art_Latn_TW",
3710 "",
3711 ""
3712 }, {
3713 "art_Latn_HK",
3714 "",
3715 ""
3716 }, {
3717 "art_Latn_AQ",
3718 "",
3719 ""
3720 }, {
3721 "art_Hans",
3722 "",
3723 ""
3724 }, {
3725 "art_Hans_ZZ",
3726 "",
3727 ""
3728 }, {
3729 "art_Hans_CN",
3730 "",
3731 ""
3732 }, {
3733 "art_Hans_TW",
3734 "",
3735 ""
3736 }, {
3737 "art_Hans_HK",
3738 "",
3739 ""
3740 }, {
3741 "art_Hans_AQ",
3742 "",
3743 ""
3744 }, {
3745 "art_Hant",
3746 "",
3747 ""
3748 }, {
3749 "art_Hant_ZZ",
3750 "",
3751 ""
3752 }, {
3753 "art_Hant_CN",
3754 "",
3755 ""
3756 }, {
3757 "art_Hant_TW",
3758 "",
3759 ""
3760 }, {
3761 "art_Hant_HK",
3762 "",
3763 ""
3764 }, {
3765 "art_Hant_AQ",
3766 "",
3767 ""
3768 }, {
3769 "art_Moon",
3770 "",
3771 ""
3772 }, {
3773 "art_Moon_ZZ",
3774 "",
3775 ""
3776 }, {
3777 "art_Moon_CN",
3778 "",
3779 ""
3780 }, {
3781 "art_Moon_TW",
3782 "",
3783 ""
3784 }, {
3785 "art_Moon_HK",
3786 "",
3787 ""
3788 }, {
3789 "art_Moon_AQ",
3790 "",
3791 ""
3792 }, {
3793 "aae_Latn_IT",
3794 "aae_Latn_IT",
3795 "aae_Latn_IT"
3796 }, {
3797 "aae_Thai_CO",
3798 "aae_Thai_CO",
3799 "aae_Thai_CO"
3800 }, {
3801 "und_CW",
3802 "pap_Latn_CW",
3803 "pap_CW"
3804 }, {
3805 "zh_Hant",
3806 "zh_Hant_TW",
3807 "zh_TW"
3808 }, {
3809 "zh_Hani",
3810 "zh_Hani_CN",
3811 "zh_Hani"
3812 }, {
3813 "und",
3814 "en_Latn_US",
3815 "en"
3816 }, {
3817 "und_Thai",
3818 "th_Thai_TH",
3819 "th"
3820 }, {
3821 "und_419",
3822 "es_Latn_419",
3823 "es_419"
3824 }, {
3825 "und_150",
3826 "ru_Cyrl_RU",
3827 "ru"
3828 }, {
3829 "und_AT",
3830 "de_Latn_AT",
3831 "de_AT"
3832 }, {
3833 "und_US",
3834 "en_Latn_US",
3835 "en"
3836 }
3837 };
3838
3839 for (const auto& item : full_data) {
3840 const char* const org = item.from;
3841 const char* const exp = item.add;
3842 Locale res(org);
3843 res.addLikelySubtags(status);
3844 status.errIfFailureAndReset("\"%s\"", org);
3845 if (exp[0]) {
3846 assertEquals("addLikelySubtags", exp, res.getName());
3847 } else {
3848 assertEquals("addLikelySubtags", org, res.getName());
3849 }
3850 }
3851
3852 for (const auto& item : full_data) {
3853 const char* const org = item.from;
3854 const char* const exp = item.remove;
3855 Locale res(org);
3856 res.minimizeSubtags(status);
3857 status.errIfFailureAndReset("\"%s\"", org);
3858 if (exp[0]) {
3859 assertEquals("minimizeSubtags", exp, res.getName());
3860 } else {
3861 assertEquals("minimizeSubtags", org, res.getName());
3862 }
3863 }
3864 }
3865
3866
3867 void
TestKeywordVariants(void)3868 LocaleTest::TestKeywordVariants(void) {
3869 static const struct {
3870 const char *localeID;
3871 const char *expectedLocaleID;
3872 //const char *expectedLocaleIDNoKeywords;
3873 //const char *expectedCanonicalID;
3874 const char *expectedKeywords[10];
3875 int32_t numKeywords;
3876 UErrorCode expectedStatus;
3877 } testCases[] = {
3878 {
3879 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
3880 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
3881 //"de_DE",
3882 //"de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
3883 {"calendar", "collation", "currency"},
3884 3,
3885 U_ZERO_ERROR
3886 },
3887 {
3888 "de_DE@euro",
3889 "de_DE@euro",
3890 //"de_DE",
3891 //"de_DE@currency=EUR",
3892 {"","","","","","",""},
3893 0,
3894 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
3895 }
3896 };
3897 UErrorCode status = U_ZERO_ERROR;
3898
3899 int32_t i = 0, j = 0;
3900 const char *result = NULL;
3901 StringEnumeration *keywords;
3902 int32_t keyCount = 0;
3903 const char *keyword = NULL;
3904 const UnicodeString *keywordString;
3905 int32_t keywordLen = 0;
3906
3907 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
3908 status = U_ZERO_ERROR;
3909 Locale l(testCases[i].localeID);
3910 keywords = l.createKeywords(status);
3911
3912 if(status != testCases[i].expectedStatus) {
3913 err("Expected to get status %s. Got %s instead\n",
3914 u_errorName(testCases[i].expectedStatus), u_errorName(status));
3915 }
3916 status = U_ZERO_ERROR;
3917 if(keywords) {
3918 if((keyCount = keywords->count(status)) != testCases[i].numKeywords) {
3919 err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
3920 }
3921 if(keyCount) {
3922 for(j = 0;;) {
3923 if((j&1)==0) {
3924 if((keyword = keywords->next(&keywordLen, status)) == NULL) {
3925 break;
3926 }
3927 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
3928 err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
3929 }
3930 } else {
3931 if((keywordString = keywords->snext(status)) == NULL) {
3932 break;
3933 }
3934 if(*keywordString != UnicodeString(testCases[i].expectedKeywords[j], "")) {
3935 err("Expected to get keyword UnicodeString %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
3936 }
3937 }
3938 j++;
3939
3940 if(j == keyCount / 2) {
3941 // replace keywords with a clone of itself
3942 StringEnumeration *k2 = keywords->clone();
3943 if(k2 == NULL || keyCount != k2->count(status)) {
3944 errln("KeywordEnumeration.clone() failed");
3945 } else {
3946 delete keywords;
3947 keywords = k2;
3948 }
3949 }
3950 }
3951 keywords->reset(status); // Make sure that reset works.
3952 for(j = 0;;) {
3953 if((keyword = keywords->next(&keywordLen, status)) == NULL) {
3954 break;
3955 }
3956 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
3957 err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
3958 }
3959 j++;
3960 }
3961 }
3962 delete keywords;
3963 }
3964 result = l.getName();
3965 if(uprv_strcmp(testCases[i].expectedLocaleID, result) != 0) {
3966 err("Expected to get \"%s\" from \"%s\". Got \"%s\" instead\n",
3967 testCases[i].expectedLocaleID, testCases[i].localeID, result);
3968 }
3969
3970 }
3971
3972 }
3973
3974
3975 void
TestCreateUnicodeKeywords(void)3976 LocaleTest::TestCreateUnicodeKeywords(void) {
3977 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywords()");
3978
3979 static const Locale l("de@calendar=buddhist;collation=phonebook");
3980
3981 LocalPointer<StringEnumeration> keys(l.createUnicodeKeywords(status));
3982 status.errIfFailureAndReset("\"%s\"", l.getName());
3983
3984 const char* key;
3985 int32_t resultLength;
3986
3987 key = keys->next(&resultLength, status);
3988 status.errIfFailureAndReset("key #1");
3989 assertEquals("resultLength", 2, resultLength);
3990 assertTrue("key != nullptr", key != nullptr);
3991 if (key != nullptr) {
3992 assertEquals("calendar", "ca", key);
3993 }
3994
3995 key = keys->next(&resultLength, status);
3996 status.errIfFailureAndReset("key #2");
3997 assertEquals("resultLength", 2, resultLength);
3998 assertTrue("key != nullptr", key != nullptr);
3999 if (key != nullptr) {
4000 assertEquals("collation", "co", key);
4001 }
4002
4003 key = keys->next(&resultLength, status);
4004 status.errIfFailureAndReset("end of keys");
4005 assertEquals("resultLength", 0, resultLength);
4006 assertTrue("key == nullptr", key == nullptr);
4007
4008 const UnicodeString* skey;
4009 keys->reset(status); // KeywordEnumeration::reset() never touches status.
4010
4011 skey = keys->snext(status);
4012 status.errIfFailureAndReset("skey #1");
4013 assertTrue("skey != nullptr", skey != nullptr);
4014 if (skey != nullptr) {
4015 assertEquals("calendar", "ca", *skey);
4016 }
4017
4018 skey = keys->snext(status);
4019 status.errIfFailureAndReset("skey #2");
4020 assertTrue("skey != nullptr", skey != nullptr);
4021 if (skey != nullptr) {
4022 assertEquals("collation", "co", *skey);
4023 }
4024
4025 skey = keys->snext(status);
4026 status.errIfFailureAndReset("end of keys");
4027 assertTrue("skey == nullptr", skey == nullptr);
4028 }
4029
4030
4031 void
TestKeywordVariantParsing(void)4032 LocaleTest::TestKeywordVariantParsing(void) {
4033 static const struct {
4034 const char *localeID;
4035 const char *keyword;
4036 const char *expectedValue;
4037 } testCases[] = {
4038 { "de_DE@ C o ll A t i o n = Phonebook ", "collation", "Phonebook" },
4039 { "de_DE", "collation", ""},
4040 { "de_DE@collation= PHONEBOOK", "collation", "PHONEBOOK" },
4041 { "de_DE@ currency = euro ; CoLLaTion = PHONEBOOk ", "collation", "PHONEBOOk" },
4042 };
4043
4044 UErrorCode status = U_ZERO_ERROR;
4045
4046 int32_t i = 0;
4047 int32_t resultLen = 0;
4048 char buffer[256];
4049
4050 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
4051 *buffer = 0;
4052 Locale l(testCases[i].localeID);
4053 resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
4054 (void)resultLen; // Suppress unused variable warning.
4055 if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
4056 err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
4057 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
4058 }
4059 }
4060 }
4061
4062 void
TestCreateKeywordSet(void)4063 LocaleTest::TestCreateKeywordSet(void) {
4064 IcuTestErrorCode status(*this, "TestCreateKeywordSet()");
4065
4066 static const Locale l("de@calendar=buddhist;collation=phonebook");
4067
4068 std::set<std::string> result;
4069 l.getKeywords<std::string>(
4070 std::insert_iterator<decltype(result)>(result, result.begin()),
4071 status);
4072 status.errIfFailureAndReset("\"%s\"", l.getName());
4073
4074 assertEquals("set::size()", 2, static_cast<int32_t>(result.size()));
4075 assertTrue("set::find(\"calendar\")",
4076 result.find("calendar") != result.end());
4077 assertTrue("set::find(\"collation\")",
4078 result.find("collation") != result.end());
4079 }
4080
4081 void
TestCreateKeywordSetEmpty(void)4082 LocaleTest::TestCreateKeywordSetEmpty(void) {
4083 IcuTestErrorCode status(*this, "TestCreateKeywordSetEmpty()");
4084
4085 static const Locale l("de");
4086
4087 std::set<std::string> result;
4088 l.getKeywords<std::string>(
4089 std::insert_iterator<decltype(result)>(result, result.begin()),
4090 status);
4091 status.errIfFailureAndReset("\"%s\"", l.getName());
4092
4093 assertEquals("set::size()", 0, static_cast<int32_t>(result.size()));
4094 }
4095
4096 void
TestCreateKeywordSetWithPrivateUse(void)4097 LocaleTest::TestCreateKeywordSetWithPrivateUse(void) {
4098 IcuTestErrorCode status(*this, "TestCreateKeywordSetWithPrivateUse()");
4099
4100 static const char tag[] = "en-US-u-ca-gregory-x-foo";
4101 static const Locale l = Locale::forLanguageTag(tag, status);
4102 std::set<std::string> result;
4103 l.getKeywords<std::string>(
4104 std::insert_iterator<decltype(result)>(result, result.begin()),
4105 status);
4106 status.errIfFailureAndReset("getKeywords \"%s\"", l.getName());
4107 assertTrue("getKeywords set::find(\"calendar\")",
4108 result.find("calendar") != result.end());
4109 assertTrue("getKeywords set::find(\"ca\")",
4110 result.find("ca") == result.end());
4111 assertTrue("getKeywords set::find(\"x\")",
4112 result.find("x") != result.end());
4113 assertTrue("getKeywords set::find(\"foo\")",
4114 result.find("foo") == result.end());
4115 }
4116
4117 void
TestCreateUnicodeKeywordSet(void)4118 LocaleTest::TestCreateUnicodeKeywordSet(void) {
4119 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSet()");
4120
4121 static const Locale l("de@calendar=buddhist;collation=phonebook");
4122
4123 std::set<std::string> result;
4124 l.getUnicodeKeywords<std::string>(
4125 std::insert_iterator<decltype(result)>(result, result.begin()),
4126 status);
4127 status.errIfFailureAndReset("\"%s\"", l.getName());
4128
4129 assertEquals("set::size()", 2, static_cast<int32_t>(result.size()));
4130 assertTrue("set::find(\"ca\")",
4131 result.find("ca") != result.end());
4132 assertTrue("set::find(\"co\")",
4133 result.find("co") != result.end());
4134 }
4135
4136 void
TestCreateUnicodeKeywordSetEmpty(void)4137 LocaleTest::TestCreateUnicodeKeywordSetEmpty(void) {
4138 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetEmpty()");
4139
4140 static const Locale l("de");
4141
4142 std::set<std::string> result;
4143 l.getUnicodeKeywords<std::string>(
4144 std::insert_iterator<decltype(result)>(result, result.begin()),
4145 status);
4146 status.errIfFailureAndReset("\"%s\"", l.getName());
4147
4148 assertEquals("set::size()", 0, static_cast<int32_t>(result.size()));
4149 }
4150
4151 void
TestCreateUnicodeKeywordSetWithPrivateUse(void)4152 LocaleTest::TestCreateUnicodeKeywordSetWithPrivateUse(void) {
4153 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetWithPrivateUse()");
4154
4155 static const char tag[] = "en-US-u-ca-gregory-x-foo";
4156 static const Locale l = Locale::forLanguageTag(tag, status);
4157
4158 std::set<std::string> result;
4159 l.getUnicodeKeywords<std::string>(
4160 std::insert_iterator<decltype(result)>(result, result.begin()),
4161 status);
4162 status.errIfFailureAndReset("getUnicodeKeywords \"%s\"", l.getName());
4163 assertTrue("getUnicodeKeywords set::find(\"ca\")",
4164 result.find("ca") != result.end());
4165 assertTrue("getUnicodeKeywords set::find(\"x\")",
4166 result.find("x") == result.end());
4167 assertTrue("getUnicodeKeywords set::find(\"foo\")",
4168 result.find("foo") == result.end());
4169 }
4170
4171 void
TestGetKeywordValueStdString(void)4172 LocaleTest::TestGetKeywordValueStdString(void) {
4173 IcuTestErrorCode status(*this, "TestGetKeywordValueStdString()");
4174
4175 static const char tag[] = "fa-u-nu-latn";
4176 static const char keyword[] = "numbers";
4177 static const char expected[] = "latn";
4178
4179 Locale l = Locale::forLanguageTag(tag, status);
4180 status.errIfFailureAndReset("\"%s\"", tag);
4181
4182 std::string result = l.getKeywordValue<std::string>(keyword, status);
4183 status.errIfFailureAndReset("\"%s\"", keyword);
4184 assertEquals(keyword, expected, result.c_str());
4185 }
4186
4187 void
TestGetUnicodeKeywordValueStdString(void)4188 LocaleTest::TestGetUnicodeKeywordValueStdString(void) {
4189 IcuTestErrorCode status(*this, "TestGetUnicodeKeywordValueStdString()");
4190
4191 static const char keyword[] = "co";
4192 static const char expected[] = "phonebk";
4193
4194 static const Locale l("de@calendar=buddhist;collation=phonebook");
4195
4196 std::string result = l.getUnicodeKeywordValue<std::string>(keyword, status);
4197 status.errIfFailureAndReset("\"%s\"", keyword);
4198 assertEquals(keyword, expected, result.c_str());
4199 }
4200
4201 void
TestSetKeywordValue(void)4202 LocaleTest::TestSetKeywordValue(void) {
4203 static const struct {
4204 const char *keyword;
4205 const char *value;
4206 } testCases[] = {
4207 { "collation", "phonebook" },
4208 { "currency", "euro" },
4209 { "calendar", "buddhist" }
4210 };
4211
4212 IcuTestErrorCode status(*this, "TestSetKeywordValue()");
4213
4214 int32_t i = 0;
4215 int32_t resultLen = 0;
4216 char buffer[256];
4217
4218 Locale l(Locale::getGerman());
4219
4220 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
4221 l.setKeywordValue(testCases[i].keyword, testCases[i].value, status);
4222 if(U_FAILURE(status)) {
4223 err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status));
4224 }
4225
4226 *buffer = 0;
4227 resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
4228 (void)resultLen; // Suppress unused variable warning.
4229 if(uprv_strcmp(testCases[i].value, buffer) != 0) {
4230 err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
4231 testCases[i].value, testCases[i].keyword, buffer);
4232 }
4233 }
4234
4235 // Test long locale
4236 {
4237 status.errIfFailureAndReset();
4238 const char* input =
4239 "de__POSIX@colnormalization=no;colstrength=primary;currency=eur;"
4240 "em=default;kv=space;lb=strict;lw=normal;measure=metric;"
4241 "numbers=latn;rg=atzzzz;sd=atat1";
4242 const char* expected =
4243 "de__POSIX@colnormalization=no;colstrength=primary;currency=eur;"
4244 "em=default;kv=space;lb=strict;lw=normal;measure=metric;"
4245 "numbers=latn;rg=atzzzz;sd=atat1;ss=none";
4246 // Bug ICU-21385
4247 Locale l2(input);
4248 l2.setKeywordValue("ss", "none", status);
4249 assertEquals("", expected, l2.getName());
4250 status.errIfFailureAndReset();
4251 }
4252 }
4253
4254 void
TestSetKeywordValueStringPiece(void)4255 LocaleTest::TestSetKeywordValueStringPiece(void) {
4256 IcuTestErrorCode status(*this, "TestSetKeywordValueStringPiece()");
4257 Locale l(Locale::getGerman());
4258
4259 l.setKeywordValue(StringPiece("collation"), StringPiece("phonebook"), status);
4260 l.setKeywordValue(StringPiece("calendarxxx", 8), StringPiece("buddhistxxx", 8), status);
4261
4262 static const char expected[] = "de@calendar=buddhist;collation=phonebook";
4263 assertEquals("", expected, l.getName());
4264 }
4265
4266 void
TestSetUnicodeKeywordValueStringPiece(void)4267 LocaleTest::TestSetUnicodeKeywordValueStringPiece(void) {
4268 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueStringPiece()");
4269 Locale l(Locale::getGerman());
4270
4271 l.setUnicodeKeywordValue(StringPiece("co"), StringPiece("phonebk"), status);
4272 status.errIfFailureAndReset();
4273
4274 l.setUnicodeKeywordValue(StringPiece("caxxx", 2), StringPiece("buddhistxxx", 8), status);
4275 status.errIfFailureAndReset();
4276
4277 static const char expected[] = "de@calendar=buddhist;collation=phonebook";
4278 assertEquals("", expected, l.getName());
4279
4280 l.setUnicodeKeywordValue("cu", nullptr, status);
4281 status.errIfFailureAndReset();
4282 assertEquals("", expected, l.getName());
4283
4284 l.setUnicodeKeywordValue("!!", nullptr, status);
4285 assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
4286 assertEquals("", expected, l.getName());
4287
4288 l.setUnicodeKeywordValue("co", "!!", status);
4289 assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
4290 assertEquals("", expected, l.getName());
4291
4292 l.setUnicodeKeywordValue("co", nullptr, status);
4293 status.errIfFailureAndReset();
4294
4295 l.setUnicodeKeywordValue("ca", "", status);
4296 status.errIfFailureAndReset();
4297
4298 assertEquals("", Locale::getGerman().getName(), l.getName());
4299 }
4300
4301 void
TestGetBaseName(void)4302 LocaleTest::TestGetBaseName(void) {
4303 static const struct {
4304 const char *localeID;
4305 const char *baseName;
4306 } testCases[] = {
4307 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
4308 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
4309 { "ja@calendar = buddhist", "ja" },
4310 { "de-u-co-phonebk", "de"}
4311 };
4312
4313 int32_t i = 0;
4314
4315 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
4316 Locale loc(testCases[i].localeID);
4317 if(strcmp(testCases[i].baseName, loc.getBaseName())) {
4318 errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"",
4319 testCases[i].localeID, testCases[i].baseName, loc.getBaseName());
4320 return;
4321 }
4322 }
4323
4324 // Verify that adding a keyword to an existing Locale doesn't change the base name.
4325 UErrorCode status = U_ZERO_ERROR;
4326 Locale loc2("en-US");
4327 if (strcmp("en_US", loc2.getBaseName())) {
4328 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
4329 }
4330 loc2.setKeywordValue("key", "value", status);
4331 if (strcmp("en_US@key=value", loc2.getName())) {
4332 errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__, __LINE__, loc2.getName());
4333 }
4334 if (strcmp("en_US", loc2.getBaseName())) {
4335 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
4336 }
4337 }
4338
4339 /**
4340 * Compare two locale IDs. If they are equal, return 0. If `string'
4341 * starts with `prefix' plus an additional element, that is, string ==
4342 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
4343 */
_loccmp(const char * string,const char * prefix)4344 static UBool _loccmp(const char* string, const char* prefix) {
4345 int32_t slen = (int32_t)strlen(string),
4346 plen = (int32_t)strlen(prefix);
4347 int32_t c = uprv_strncmp(string, prefix, plen);
4348 /* 'root' is "less than" everything */
4349 if (prefix[0] == '\0') {
4350 return string[0] != '\0';
4351 }
4352 if (c) return -1; /* mismatch */
4353 if (slen == plen) return 0;
4354 if (string[plen] == '_') return 1;
4355 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
4356 }
4357
4358 /**
4359 * Check the relationship between requested locales, and report problems.
4360 * The caller specifies the expected relationships between requested
4361 * and valid (expReqValid) and between valid and actual (expValidActual).
4362 * Possible values are:
4363 * "gt" strictly greater than, e.g., en_US > en
4364 * "ge" greater or equal, e.g., en >= en
4365 * "eq" equal, e.g., en == en
4366 */
_checklocs(const char * label,const char * req,const Locale & validLoc,const Locale & actualLoc,const char * expReqValid,const char * expValidActual)4367 void LocaleTest::_checklocs(const char* label,
4368 const char* req,
4369 const Locale& validLoc,
4370 const Locale& actualLoc,
4371 const char* expReqValid,
4372 const char* expValidActual) {
4373 const char* valid = validLoc.getName();
4374 const char* actual = actualLoc.getName();
4375 int32_t reqValid = _loccmp(req, valid);
4376 int32_t validActual = _loccmp(valid, actual);
4377 if (((0 == uprv_strcmp(expReqValid, "gt") && reqValid > 0) ||
4378 (0 == uprv_strcmp(expReqValid, "ge") && reqValid >= 0) ||
4379 (0 == uprv_strcmp(expReqValid, "eq") && reqValid == 0)) &&
4380 ((0 == uprv_strcmp(expValidActual, "gt") && validActual > 0) ||
4381 (0 == uprv_strcmp(expValidActual, "ge") && validActual >= 0) ||
4382 (0 == uprv_strcmp(expValidActual, "eq") && validActual == 0))) {
4383 logln("%s; req=%s, valid=%s, actual=%s",
4384 label, req, valid, actual);
4385 } else {
4386 dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)",
4387 label, req, valid, actual,
4388 expReqValid, expValidActual);
4389 }
4390 }
4391
TestGetLocale(void)4392 void LocaleTest::TestGetLocale(void) {
4393 #if !UCONFIG_NO_SERVICE
4394 const char *req;
4395 Locale valid, actual, reqLoc;
4396
4397 // Calendar
4398 #if !UCONFIG_NO_FORMATTING
4399 {
4400 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
4401 req = "en_US_BROOKLYN";
4402 Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec);
4403 if (U_FAILURE(ec)) {
4404 dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec));
4405 } else {
4406 valid = cal->getLocale(ULOC_VALID_LOCALE, ec);
4407 actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec);
4408 if (U_FAILURE(ec)) {
4409 errln("FAIL: Calendar::getLocale() failed");
4410 } else {
4411 _checklocs("Calendar", req, valid, actual);
4412 }
4413 /* Make sure that it fails correctly */
4414 ec = U_FILE_ACCESS_ERROR;
4415 if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) {
4416 errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\"");
4417 }
4418 ec = U_ZERO_ERROR;
4419 }
4420 delete cal;
4421 }
4422 #endif
4423
4424 // DecimalFormat, DecimalFormatSymbols
4425 #if !UCONFIG_NO_FORMATTING
4426 {
4427 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
4428 req = "fr_FR_NICE";
4429 NumberFormat* nf = NumberFormat::createInstance(Locale::createFromName(req), ec);
4430 if (U_FAILURE(ec)) {
4431 dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec));
4432 } else {
4433 DecimalFormat* dec = dynamic_cast<DecimalFormat*>(nf);
4434 if (dec == NULL) {
4435 errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat");
4436 return;
4437 }
4438 valid = dec->getLocale(ULOC_VALID_LOCALE, ec);
4439 actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec);
4440 if (U_FAILURE(ec)) {
4441 errln("FAIL: DecimalFormat::getLocale() failed");
4442 } else {
4443 _checklocs("DecimalFormat", req, valid, actual);
4444 }
4445
4446 const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols();
4447 if (sym == NULL) {
4448 errln("FAIL: getDecimalFormatSymbols returned NULL");
4449 return;
4450 }
4451 valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
4452 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
4453 if (U_FAILURE(ec)) {
4454 errln("FAIL: DecimalFormatSymbols::getLocale() failed");
4455 } else {
4456 _checklocs("DecimalFormatSymbols", req, valid, actual);
4457 }
4458 }
4459 delete nf;
4460 }
4461 #endif
4462
4463 // DateFormat, DateFormatSymbols
4464 #if !UCONFIG_NO_FORMATTING
4465 {
4466 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
4467 req = "de_CH_LUCERNE";
4468 DateFormat* df =
4469 DateFormat::createDateInstance(DateFormat::kDefault,
4470 Locale::createFromName(req));
4471 if (df == 0){
4472 dataerrln("Error calling DateFormat::createDateInstance()");
4473 } else {
4474 SimpleDateFormat* dat = dynamic_cast<SimpleDateFormat*>(df);
4475 if (dat == NULL) {
4476 errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat");
4477 return;
4478 }
4479 valid = dat->getLocale(ULOC_VALID_LOCALE, ec);
4480 actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec);
4481 if (U_FAILURE(ec)) {
4482 errln("FAIL: SimpleDateFormat::getLocale() failed");
4483 } else {
4484 _checklocs("SimpleDateFormat", req, valid, actual);
4485 }
4486
4487 const DateFormatSymbols* sym = dat->getDateFormatSymbols();
4488 if (sym == NULL) {
4489 errln("FAIL: getDateFormatSymbols returned NULL");
4490 return;
4491 }
4492 valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
4493 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
4494 if (U_FAILURE(ec)) {
4495 errln("FAIL: DateFormatSymbols::getLocale() failed");
4496 } else {
4497 _checklocs("DateFormatSymbols", req, valid, actual);
4498 }
4499 }
4500 delete df;
4501 }
4502 #endif
4503
4504 // BreakIterator
4505 #if !UCONFIG_NO_BREAK_ITERATION
4506 {
4507 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
4508 req = "es_ES_BARCELONA";
4509 reqLoc = Locale::createFromName(req);
4510 BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec);
4511 if (U_FAILURE(ec)) {
4512 dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec));
4513 } else {
4514 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
4515 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
4516 if (U_FAILURE(ec)) {
4517 errln("FAIL: BreakIterator::getLocale() failed");
4518 } else {
4519 _checklocs("BreakIterator", req, valid, actual);
4520 }
4521
4522 // After registering something, the behavior should be different
4523 URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec);
4524 brk = 0; // registerInstance adopts
4525 if (U_FAILURE(ec)) {
4526 errln("FAIL: BreakIterator::registerInstance() failed");
4527 } else {
4528 brk = BreakIterator::createWordInstance(reqLoc, ec);
4529 if (U_FAILURE(ec)) {
4530 errln("FAIL: BreakIterator::createWordInstance failed");
4531 } else {
4532 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
4533 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
4534 if (U_FAILURE(ec)) {
4535 errln("FAIL: BreakIterator::getLocale() failed");
4536 } else {
4537 // N.B.: now expect valid==actual==req
4538 _checklocs("BreakIterator(registered)",
4539 req, valid, actual, "eq", "eq");
4540 }
4541 }
4542 // No matter what, unregister
4543 BreakIterator::unregister(key, ec);
4544 if (U_FAILURE(ec)) {
4545 errln("FAIL: BreakIterator::unregister() failed");
4546 }
4547 delete brk;
4548 brk = 0;
4549 }
4550
4551 // After unregistering, should behave normally again
4552 brk = BreakIterator::createWordInstance(reqLoc, ec);
4553 if (U_FAILURE(ec)) {
4554 errln("FAIL: BreakIterator::createWordInstance failed");
4555 } else {
4556 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
4557 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
4558 if (U_FAILURE(ec)) {
4559 errln("FAIL: BreakIterator::getLocale() failed");
4560 } else {
4561 _checklocs("BreakIterator(unregistered)", req, valid, actual);
4562 }
4563 }
4564 }
4565 delete brk;
4566 }
4567 #endif
4568
4569 // Collator
4570 #if !UCONFIG_NO_COLLATION
4571 {
4572 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
4573
4574 checkRegisteredCollators(NULL); // Don't expect any extras
4575
4576 req = "hi_IN_BHOPAL";
4577 reqLoc = Locale::createFromName(req);
4578 Collator* coll = Collator::createInstance(reqLoc, ec);
4579 if (U_FAILURE(ec)) {
4580 dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec));
4581 } else {
4582 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
4583 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
4584 if (U_FAILURE(ec)) {
4585 errln("FAIL: Collator::getLocale() failed");
4586 } else {
4587 _checklocs("Collator", req, valid, actual);
4588 }
4589
4590 // After registering something, the behavior should be different
4591 URegistryKey key = Collator::registerInstance(coll, reqLoc, ec);
4592 coll = 0; // registerInstance adopts
4593 if (U_FAILURE(ec)) {
4594 errln("FAIL: Collator::registerInstance() failed");
4595 } else {
4596 coll = Collator::createInstance(reqLoc, ec);
4597 if (U_FAILURE(ec)) {
4598 errln("FAIL: Collator::createWordInstance failed");
4599 } else {
4600 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
4601 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
4602 if (U_FAILURE(ec)) {
4603 errln("FAIL: Collator::getLocale() failed");
4604 } else {
4605 // N.B.: now expect valid==actual==req
4606 _checklocs("Collator(registered)",
4607 req, valid, actual, "eq", "eq");
4608 }
4609 }
4610 checkRegisteredCollators(req); // include hi_IN_BHOPAL
4611
4612 // No matter what, unregister
4613 Collator::unregister(key, ec);
4614 if (U_FAILURE(ec)) {
4615 errln("FAIL: Collator::unregister() failed");
4616 }
4617 delete coll;
4618 coll = 0;
4619 }
4620
4621 // After unregistering, should behave normally again
4622 coll = Collator::createInstance(reqLoc, ec);
4623 if (U_FAILURE(ec)) {
4624 errln("FAIL: Collator::createInstance failed");
4625 } else {
4626 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
4627 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
4628 if (U_FAILURE(ec)) {
4629 errln("FAIL: Collator::getLocale() failed");
4630 } else {
4631 _checklocs("Collator(unregistered)", req, valid, actual);
4632 }
4633 }
4634 }
4635 delete coll;
4636
4637 checkRegisteredCollators(NULL); // extra should be gone again
4638 }
4639 #endif
4640 #endif
4641 }
4642
4643 #if !UCONFIG_NO_COLLATION
4644 /**
4645 * Compare Collator::getAvailableLocales(int) [ "old", returning an array ]
4646 * with Collator::getAvailableLocales() [ "new", returning a StringEnumeration ]
4647 * These should be identical (check their API docs) EXCEPT that
4648 * if expectExtra is non-NULL, it will be in the "new" array but not "old".
4649 * Does not return any status but calls errln on error.
4650 * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL.
4651 */
checkRegisteredCollators(const char * expectExtra)4652 void LocaleTest::checkRegisteredCollators(const char *expectExtra) {
4653 UErrorCode status = U_ZERO_ERROR;
4654 int32_t count1=0,count2=0;
4655 Hashtable oldHash(status);
4656 Hashtable newHash(status);
4657 assertSuccess(WHERE, status);
4658
4659 UnicodeString expectStr(expectExtra?expectExtra:"n/a", "");
4660
4661 // the 'old' list (non enumeration)
4662 const Locale* oldList = Collator::getAvailableLocales(count1);
4663 if(oldList == NULL) {
4664 dataerrln("Error: Collator::getAvailableLocales(count) returned NULL");
4665 return;
4666 }
4667
4668 // the 'new' list (enumeration)
4669 LocalPointer<StringEnumeration> newEnum(Collator::getAvailableLocales());
4670 if(newEnum.isNull()) {
4671 errln("Error: collator::getAvailableLocales() returned NULL");
4672 return;
4673 }
4674
4675 // OK. Let's add all of the OLD
4676 // then check for any in the NEW not in OLD
4677 // then check for any in OLD not in NEW.
4678
4679 // 1. add all of OLD
4680 for(int32_t i=0;i<count1;i++) {
4681 const UnicodeString key(oldList[i].getName(), "");
4682 int32_t oldI = oldHash.puti(key, 1, status);
4683 if( oldI == 1 ){
4684 errln("Error: duplicate key %s in Collator::getAvailableLocales(count) list.\n",
4685 oldList[i].getName());
4686 return;
4687 }
4688 if(expectExtra != NULL && !strcmp(expectExtra, oldList[i].getName())) {
4689 errln("Inexplicably, Collator::getAvailableCollators(count) had registered collator %s. This shouldn't happen, so I am going to consider it an error.\n", expectExtra);
4690 }
4691 }
4692
4693 // 2. add all of NEW
4694 const UnicodeString *locStr;
4695 UBool foundExpected = false;
4696 while((locStr = newEnum->snext(status)) && U_SUCCESS(status)) {
4697 count2++;
4698
4699 if(expectExtra != NULL && expectStr == *locStr) {
4700 foundExpected = true;
4701 logln(UnicodeString("Found expected registered collator: ","") + expectStr);
4702 }
4703 (void)foundExpected; // Hush unused variable compiler warning.
4704
4705 if( oldHash.geti(*locStr) == 0 ) {
4706 if(expectExtra != NULL && expectStr==*locStr) {
4707 logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr);
4708 } else {
4709 errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","")
4710 + *locStr);
4711 }
4712 }
4713 newHash.puti(*locStr, 1, status);
4714 }
4715
4716 // 3. check all of OLD again
4717 for(int32_t i=0;i<count1;i++) {
4718 const UnicodeString key(oldList[i].getName(), "");
4719 int32_t newI = newHash.geti(key);
4720 if(newI == 0) {
4721 errln(UnicodeString("Error: Collator::getAvailableLocales() is missing: ","")
4722 + key);
4723 }
4724 }
4725
4726 int32_t expectCount2 = count1;
4727 if(expectExtra != NULL) {
4728 expectCount2 ++; // if an extra item registered, bump the expect count
4729 }
4730
4731 assertEquals("Collator::getAvail() count", expectCount2, count2);
4732 }
4733 #endif
4734
4735
4736
TestVariantWithOutCountry(void)4737 void LocaleTest::TestVariantWithOutCountry(void) {
4738 Locale loc("en","","POSIX");
4739 if (0 != strcmp(loc.getVariant(), "POSIX")) {
4740 errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc.getName(), "POSIX", loc.getVariant());
4741 }
4742 Locale loc2("en","","FOUR");
4743 if (0 != strcmp(loc2.getVariant(), "FOUR")) {
4744 errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2.getName(), "FOUR", loc2.getVariant());
4745 }
4746 Locale loc3("en","Latn","","FOUR");
4747 if (0 != strcmp(loc3.getVariant(), "FOUR")) {
4748 errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3.getName(), "FOUR", loc3.getVariant());
4749 }
4750 Locale loc4("","Latn","","FOUR");
4751 if (0 != strcmp(loc4.getVariant(), "FOUR")) {
4752 errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4.getName(), "FOUR", loc4.getVariant());
4753 }
4754 Locale loc5("","Latn","US","FOUR");
4755 if (0 != strcmp(loc5.getVariant(), "FOUR")) {
4756 errln("FAIL: _Latn_US_FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc5.getName(), "FOUR", loc5.getVariant());
4757 }
4758 Locale loc6("de-1901");
4759 if (0 != strcmp(loc6.getVariant(), "1901")) {
4760 errln("FAIL: de-1901 didn't get parsed correctly - name is %s - expected %s got %s", loc6.getName(), "1901", loc6.getVariant());
4761 }
4762 }
4763
_canonicalize(int32_t selector,const char * localeID)4764 static Locale _canonicalize(int32_t selector, /* 0==createFromName, 1==createCanonical, 2==Locale ct */
4765 const char* localeID) {
4766 switch (selector) {
4767 case 0:
4768 return Locale::createFromName(localeID);
4769 case 1:
4770 return Locale::createCanonical(localeID);
4771 case 2:
4772 return Locale(localeID);
4773 default:
4774 return Locale("");
4775 }
4776 }
4777
TestCanonicalization(void)4778 void LocaleTest::TestCanonicalization(void)
4779 {
4780 static const struct {
4781 const char *localeID; /* input */
4782 const char *getNameID; /* expected getName() result */
4783 const char *canonicalID; /* expected canonicalize() result */
4784 } testCases[] = {
4785 { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
4786 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
4787 "ca_ES_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_WITH_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
4788 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
4789 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
4790 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
4791 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
4792 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
4793 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
4794 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
4795 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" }, /* POSIX ID */
4796 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
4797 // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS
4798 // TODO: unify this behavior
4799 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
4800 { "de-1901", "de__1901", "de__1901" }, /* registered name */
4801 { "de-1906", "de__1906", "de__1906" }, /* registered name */
4802 // New in CLDR 39 / ICU 69
4803 { "nb", "nb", "nb" },
4804
4805 /* posix behavior that used to be performed by getName */
4806 { "mr.utf8", "mr.utf8", "mr" },
4807 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
4808 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
4809 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
4810 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
4811 { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO@b=ny" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */
4812
4813 /* fleshing out canonicalization */
4814 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
4815 { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;",
4816 "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR",
4817 "en_Hant_IL_GIRL_VALLEY@calendar=Japanese;currency=EUR" },
4818 /* already-canonical ids are not changed */
4819 { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR",
4820 "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR",
4821 "en_Hant_IL_GIRL_VALLEY@calendar=Japanese;currency=EUR" },
4822 /* norwegian is just too weird, if we handle things in their full generality */
4823 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
4824
4825 /* test cases reflecting internal resource bundle usage */
4826 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
4827 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
4828 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
4829
4830 // Before ICU 64, ICU locale canonicalization had some additional mappings.
4831 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
4832 // The following now use standard canonicalization.
4833 { "", "", "" },
4834 { "C", "c", "c" },
4835 { "POSIX", "posix", "posix" },
4836 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
4837 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
4838 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
4839 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
4840 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
4841 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
4842 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
4843 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
4844 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
4845 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
4846 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
4847 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
4848 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
4849 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
4850 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
4851 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
4852 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
4853 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
4854 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
4855 { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
4856 { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
4857 { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
4858 { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
4859 { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
4860 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
4861 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
4862 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
4863 { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
4864 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
4865 { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
4866 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_RS_CYRILLIC" }, /* Linux name */
4867 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
4868 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
4869 { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
4870 { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
4871 /* PRE_EURO and EURO conversions don't affect other keywords */
4872 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
4873 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
4874 /* currency keyword overrides PRE_EURO and EURO currency */
4875 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
4876 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
4877 };
4878
4879 static const char* label[] = { "createFromName", "createCanonical", "Locale" };
4880
4881 int32_t i, j;
4882
4883 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
4884 for (j=0; j<3; ++j) {
4885 const char* expected = (j==1) ? testCases[i].canonicalID : testCases[i].getNameID;
4886 Locale loc = _canonicalize(j, testCases[i].localeID);
4887 const char* getName = loc.isBogus() ? "BOGUS" : loc.getName();
4888 if(uprv_strcmp(expected, getName) != 0) {
4889 errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"",
4890 label[j], testCases[i].localeID, getName, expected);
4891 } else {
4892 logln("Ok: %s(%s) => \"%s\"",
4893 label[j], testCases[i].localeID, getName);
4894 }
4895 }
4896 }
4897 }
4898
TestCanonicalize(void)4899 void LocaleTest::TestCanonicalize(void)
4900 {
4901 static const struct {
4902 const char *localeID; /* input */
4903 const char *canonicalID; /* expected canonicalize() result */
4904 } testCases[] = {
4905 // language _ variant -> language
4906 { "no-BOKMAL", "nb" },
4907 // also test with script, country and extensions
4908 { "no-Cyrl-ID-BOKMAL-u-ca-japanese", "nb-Cyrl-ID-u-ca-japanese" },
4909 { "no-Cyrl-ID-1901-BOKMAL-xsistemo-u-ca-japanese", "nb-Cyrl-ID-1901-xsistemo-u-ca-japanese" },
4910 { "no-Cyrl-ID-1901-BOKMAL-u-ca-japanese", "nb-Cyrl-ID-1901-u-ca-japanese" },
4911 { "no-Cyrl-ID-BOKMAL-xsistemo-u-ca-japanese", "nb-Cyrl-ID-xsistemo-u-ca-japanese" },
4912 { "no-NYNORSK", "nn" },
4913 { "no-Cyrl-ID-NYNORSK-u-ca-japanese", "nn-Cyrl-ID-u-ca-japanese" },
4914 { "aa-SAAHO", "ssy" },
4915 // also test with script, country and extensions
4916 { "aa-Deva-IN-SAAHO-u-ca-japanese", "ssy-Deva-IN-u-ca-japanese" },
4917
4918 // language -> language
4919 { "aam", "aas" },
4920 // also test with script, country, variants and extensions
4921 { "aam-Cyrl-ID-3456-u-ca-japanese", "aas-Cyrl-ID-3456-u-ca-japanese" },
4922
4923 // language -> language _ Script
4924 { "sh", "sr-Latn" },
4925 // also test with script
4926 { "sh-Cyrl", "sr-Cyrl" },
4927 // also test with country, variants and extensions
4928 { "sh-ID-3456-u-ca-roc", "sr-Latn-ID-3456-u-ca-roc" },
4929
4930 // language -> language _ country
4931 { "prs", "fa-AF" },
4932 // also test with country
4933 { "prs-RU", "fa-RU" },
4934 // also test with script, variants and extensions
4935 { "prs-Cyrl-1009-u-ca-roc", "fa-Cyrl-AF-1009-u-ca-roc" },
4936
4937 { "pa-IN", "pa-IN" },
4938 // also test with script
4939 { "pa-Latn-IN", "pa-Latn-IN" },
4940 // also test with variants and extensions
4941 { "pa-IN-5678-u-ca-hindi", "pa-IN-5678-u-ca-hindi" },
4942
4943 { "ky-Cyrl-KG", "ky-Cyrl-KG" },
4944 // also test with variants and extensions
4945 { "ky-Cyrl-KG-3456-u-ca-roc", "ky-Cyrl-KG-3456-u-ca-roc" },
4946
4947 // Test replacement of scriptAlias
4948 { "en-Qaai", "en-Zinh" },
4949
4950 // Test replacement of territoryAlias
4951 // 554 has one replacement
4952 { "en-554", "en-NZ" },
4953 { "en-554-u-nu-arab", "en-NZ-u-nu-arab" },
4954 // 172 has multiple replacements
4955 // also test with variants
4956 { "ru-172-1234", "ru-RU-1234" },
4957 // also test with extensions
4958 { "ru-172-1234-u-nu-latn", "ru-RU-1234-u-nu-latn" },
4959 // also test with scripts
4960 { "uz-172", "uz-UZ" },
4961 { "uz-Cyrl-172", "uz-Cyrl-UZ" },
4962 { "uz-Bopo-172", "uz-Bopo-UZ" },
4963 // also test with variants and scripts
4964 { "uz-Cyrl-172-5678-u-nu-latn", "uz-Cyrl-UZ-5678-u-nu-latn" },
4965 // a language not used in this region
4966 { "fr-172", "fr-RU" },
4967
4968 // variant
4969 { "ja-Latn-hepburn-heploc", "ja-Latn-alalc97"},
4970
4971 { "aaa-Fooo-SU", "aaa-Fooo-RU"},
4972
4973 // ICU-21344
4974 { "ku-Arab-NT", "ku-Arab-IQ"},
4975
4976 // ICU-21402
4977 { "und-u-rg-no23", "und-u-rg-no50"},
4978 { "und-u-rg-cn11", "und-u-rg-cnbj"},
4979 { "und-u-rg-cz10a", "und-u-rg-cz110"},
4980 { "und-u-rg-fra", "und-u-rg-frges"},
4981 { "und-u-rg-frg", "und-u-rg-frges"},
4982 { "und-u-rg-lud", "und-u-rg-lucl"},
4983
4984 { "und-NO-u-sd-no23", "und-NO-u-sd-no50"},
4985 { "und-CN-u-sd-cn11", "und-CN-u-sd-cnbj"},
4986 { "und-CZ-u-sd-cz10a", "und-CZ-u-sd-cz110"},
4987 { "und-FR-u-sd-fra", "und-FR-u-sd-frges"},
4988 { "und-FR-u-sd-frg", "und-FR-u-sd-frges"},
4989 { "und-LU-u-sd-lud", "und-LU-u-sd-lucl"},
4990
4991 // ICU-21550
4992 { "und-u-rg-fi01", "und-u-rg-axzzzz"},
4993 { "und-u-rg-frcp", "und-u-rg-cpzzzz"},
4994 { "und-u-rg-frpm", "und-u-rg-pmzzzz"},
4995 { "und-u-rg-usvi", "und-u-rg-vizzzz"},
4996 { "und-u-rg-cn91", "und-u-rg-hkzzzz"},
4997 { "und-u-rg-nlaw", "und-u-rg-awzzzz"},
4998
4999 { "und-NO-u-sd-frre", "und-NO-u-sd-rezzzz"},
5000 { "und-CN-u-sd-nlcw", "und-CN-u-sd-cwzzzz"},
5001 { "und-CZ-u-sd-usgu", "und-CZ-u-sd-guzzzz"},
5002 { "und-FR-u-sd-shta", "und-FR-u-sd-tazzzz"},
5003 { "und-FR-u-sd-cn71", "und-FR-u-sd-twzzzz"},
5004
5005
5006 // ICU-21401
5007 { "cel-gaulish", "xtg"},
5008
5009 // ICU-21406
5010 // Inside T extension
5011 // Case of Script and Region
5012 { "ja-kana-jp-t-it-latn-it", "ja-Kana-JP-t-it-latn-it"},
5013 { "und-t-zh-hani-tw", "und-t-zh-hani-tw"},
5014 { "und-cyrl-t-und-Latn", "und-Cyrl-t-und-latn"},
5015 // Order of singleton
5016 { "und-u-ca-roc-t-zh", "und-t-zh-u-ca-roc"},
5017 // Variant subtags are alphabetically ordered.
5018 { "sl-t-sl-rozaj-biske-1994", "sl-t-sl-1994-biske-rozaj"},
5019 // tfield subtags are alphabetically ordered.
5020 // (Also tests subtag case normalisation.)
5021 { "DE-T-lv-M0-DIN", "de-t-lv-m0-din"},
5022 { "DE-T-M0-DIN-K0-QWERTZ", "de-t-k0-qwertz-m0-din"},
5023 { "DE-T-lv-M0-DIN-K0-QWERTZ", "de-t-lv-k0-qwertz-m0-din"},
5024 // "true" tvalue subtags aren't removed.
5025 // (UTS 35 version 36, §3.2.1 claims otherwise, but tkey must be followed by
5026 // tvalue, so that's likely a spec bug in UTS 35.)
5027 { "en-t-m0-true", "en-t-m0-true"},
5028 // tlang subtags are canonicalised.
5029 { "en-t-iw", "en-t-he"},
5030 { "en-t-hy-latn-SU", "en-t-hy-latn-am"},
5031 { "ru-t-ru-cyrl-SU", "ru-t-ru-cyrl-ru"},
5032 { "fr-t-fr-172", "fr-t-fr-ru"},
5033 { "und-t-no-latn-BOKMAL", "und-t-nb-latn" },
5034 { "und-t-sgn-qAAi-NL", "und-t-dse-zinh" },
5035 // alias of tvalue should be replaced
5036 { "en-t-m0-NaMeS", "en-t-m0-prprname" },
5037 { "en-t-s0-ascii-d0-NaMe", "en-t-d0-charname-s0-ascii" },
5038 };
5039 int32_t i;
5040 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
5041 UErrorCode status = U_ZERO_ERROR;
5042 std::string otag = testCases[i].localeID;
5043 Locale loc = Locale::forLanguageTag(otag.c_str(), status);
5044 loc.canonicalize(status);
5045 std::string tag = loc.toLanguageTag<std::string>(status);
5046 if (tag != testCases[i].canonicalID) {
5047 errcheckln(status, "FAIL: %s should be canonicalized to %s but got %s - %s",
5048 otag.c_str(),
5049 testCases[i].canonicalID,
5050 tag.c_str(),
5051 u_errorName(status));
5052 }
5053 }
5054 }
5055
TestCurrencyByDate(void)5056 void LocaleTest::TestCurrencyByDate(void)
5057 {
5058 #if !UCONFIG_NO_FORMATTING
5059 UErrorCode status = U_ZERO_ERROR;
5060 UDate date = uprv_getUTCtime();
5061 UChar TMP[4] = {0, 0, 0, 0};
5062 int32_t index = 0;
5063 int32_t resLen = 0;
5064 UnicodeString tempStr, resultStr;
5065
5066 // Cycle through historical currencies
5067 date = (UDate)-630720000000.0; // pre 1961 - no currency defined
5068 index = ucurr_countCurrencies("eo_AM", date, &status);
5069 if (index != 0)
5070 {
5071 errcheckln(status, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status));
5072 }
5073 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
5074 if (resLen != 0) {
5075 errcheckln(status, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status));
5076 }
5077 status = U_ZERO_ERROR;
5078
5079 date = (UDate)0.0; // 1970 - one currency defined
5080 index = ucurr_countCurrencies("eo_AM", date, &status);
5081 if (index != 1)
5082 {
5083 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
5084 }
5085 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
5086 tempStr.setTo(TMP);
5087 resultStr.setTo("SUR");
5088 if (resultStr != tempStr) {
5089 errcheckln(status, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status));
5090 }
5091
5092 date = (UDate)693792000000.0; // 1992 - one currency defined
5093 index = ucurr_countCurrencies("eo_AM", date, &status);
5094 if (index != 1)
5095 {
5096 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
5097 }
5098 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
5099 tempStr.setTo(TMP);
5100 resultStr.setTo("RUR");
5101 if (resultStr != tempStr) {
5102 errcheckln(status, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status));
5103 }
5104
5105 date = (UDate)977616000000.0; // post 1993 - one currency defined
5106 index = ucurr_countCurrencies("eo_AM", date, &status);
5107 if (index != 1)
5108 {
5109 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
5110 }
5111 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
5112 tempStr.setTo(TMP);
5113 resultStr.setTo("AMD");
5114 if (resultStr != tempStr) {
5115 errcheckln(status, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status));
5116 }
5117
5118 // Locale AD has multiple currencies at once
5119 date = (UDate)977616000000.0; // year 2001
5120 index = ucurr_countCurrencies("eo_AD", date, &status);
5121 if (index != 4)
5122 {
5123 errcheckln(status, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status));
5124 }
5125 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
5126 tempStr.setTo(TMP);
5127 resultStr.setTo("EUR");
5128 if (resultStr != tempStr) {
5129 errcheckln(status, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status));
5130 }
5131 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
5132 tempStr.setTo(TMP);
5133 resultStr.setTo("ESP");
5134 if (resultStr != tempStr) {
5135 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
5136 }
5137 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
5138 tempStr.setTo(TMP);
5139 resultStr.setTo("FRF");
5140 if (resultStr != tempStr) {
5141 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
5142 }
5143 resLen = ucurr_forLocaleAndDate("eo_AD", date, 4, TMP, 4, &status);
5144 tempStr.setTo(TMP);
5145 resultStr.setTo("ADP");
5146 if (resultStr != tempStr) {
5147 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
5148 }
5149
5150 date = (UDate)0.0; // year 1970
5151 index = ucurr_countCurrencies("eo_AD", date, &status);
5152 if (index != 3)
5153 {
5154 errcheckln(status, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status));
5155 }
5156 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
5157 tempStr.setTo(TMP);
5158 resultStr.setTo("ESP");
5159 if (resultStr != tempStr) {
5160 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
5161 }
5162 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
5163 tempStr.setTo(TMP);
5164 resultStr.setTo("FRF");
5165 if (resultStr != tempStr) {
5166 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
5167 }
5168 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
5169 tempStr.setTo(TMP);
5170 resultStr.setTo("ADP");
5171 if (resultStr != tempStr) {
5172 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
5173 }
5174
5175 date = (UDate)-630720000000.0; // year 1950
5176 index = ucurr_countCurrencies("eo_AD", date, &status);
5177 if (index != 2)
5178 {
5179 errcheckln(status, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status));
5180 }
5181 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
5182 tempStr.setTo(TMP);
5183 resultStr.setTo("ESP");
5184 if (resultStr != tempStr) {
5185 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
5186 }
5187 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
5188 tempStr.setTo(TMP);
5189 resultStr.setTo("ADP");
5190 if (resultStr != tempStr) {
5191 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
5192 }
5193
5194 date = (UDate)-2207520000000.0; // year 1900
5195 index = ucurr_countCurrencies("eo_AD", date, &status);
5196 if (index != 1)
5197 {
5198 errcheckln(status, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status));
5199 }
5200 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
5201 tempStr.setTo(TMP);
5202 resultStr.setTo("ESP");
5203 if (resultStr != tempStr) {
5204 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
5205 }
5206
5207 // Locale UA has gap between years 1994 - 1996
5208 date = (UDate)788400000000.0;
5209 index = ucurr_countCurrencies("eo_UA", date, &status);
5210 if (index != 0)
5211 {
5212 errcheckln(status, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status));
5213 }
5214 resLen = ucurr_forLocaleAndDate("eo_UA", date, index, TMP, 4, &status);
5215 if (resLen != 0) {
5216 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
5217 }
5218 status = U_ZERO_ERROR;
5219
5220 // Test index bounds
5221 resLen = ucurr_forLocaleAndDate("eo_UA", date, 100, TMP, 4, &status);
5222 if (resLen != 0) {
5223 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
5224 }
5225 status = U_ZERO_ERROR;
5226
5227 resLen = ucurr_forLocaleAndDate("eo_UA", date, 0, TMP, 4, &status);
5228 if (resLen != 0) {
5229 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
5230 }
5231 status = U_ZERO_ERROR;
5232
5233 // Test for bogus locale
5234 index = ucurr_countCurrencies("eo_QQ", date, &status);
5235 if (index != 0)
5236 {
5237 errcheckln(status, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status));
5238 }
5239 status = U_ZERO_ERROR;
5240 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 1, TMP, 4, &status);
5241 if (resLen != 0) {
5242 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
5243 }
5244 status = U_ZERO_ERROR;
5245 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 0, TMP, 4, &status);
5246 if (resLen != 0) {
5247 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
5248 }
5249 status = U_ZERO_ERROR;
5250
5251 // Cycle through histrocial currencies
5252 date = (UDate)977616000000.0; // 2001 - one currency
5253 index = ucurr_countCurrencies("eo_AO", date, &status);
5254 if (index != 1)
5255 {
5256 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
5257 }
5258 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
5259 tempStr.setTo(TMP);
5260 resultStr.setTo("AOA");
5261 if (resultStr != tempStr) {
5262 errcheckln(status, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status));
5263 }
5264
5265 date = (UDate)819936000000.0; // 1996 - 2 currencies
5266 index = ucurr_countCurrencies("eo_AO", date, &status);
5267 if (index != 2)
5268 {
5269 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
5270 }
5271 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
5272 tempStr.setTo(TMP);
5273 resultStr.setTo("AOR");
5274 if (resultStr != tempStr) {
5275 errcheckln(status, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status));
5276 }
5277 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
5278 tempStr.setTo(TMP);
5279 resultStr.setTo("AON");
5280 if (resultStr != tempStr) {
5281 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
5282 }
5283
5284 date = (UDate)662256000000.0; // 1991 - 2 currencies
5285 index = ucurr_countCurrencies("eo_AO", date, &status);
5286 if (index != 2)
5287 {
5288 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
5289 }
5290 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
5291 tempStr.setTo(TMP);
5292 resultStr.setTo("AON");
5293 if (resultStr != tempStr) {
5294 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
5295 }
5296 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
5297 tempStr.setTo(TMP);
5298 resultStr.setTo("AOK");
5299 if (resultStr != tempStr) {
5300 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
5301 }
5302
5303 date = (UDate)315360000000.0; // 1980 - one currency
5304 index = ucurr_countCurrencies("eo_AO", date, &status);
5305 if (index != 1)
5306 {
5307 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
5308 }
5309 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
5310 tempStr.setTo(TMP);
5311 resultStr.setTo("AOK");
5312 if (resultStr != tempStr) {
5313 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
5314 }
5315
5316 date = (UDate)0.0; // 1970 - no currencies
5317 index = ucurr_countCurrencies("eo_AO", date, &status);
5318 if (index != 0)
5319 {
5320 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
5321 }
5322 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
5323 if (resLen != 0) {
5324 errcheckln(status, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status));
5325 }
5326 status = U_ZERO_ERROR;
5327
5328 // Test with currency keyword override
5329 date = (UDate)977616000000.0; // 2001 - two currencies
5330 index = ucurr_countCurrencies("eo_DE@currency=DEM", date, &status);
5331 if (index != 2)
5332 {
5333 errcheckln(status, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status));
5334 }
5335 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 1, TMP, 4, &status);
5336 tempStr.setTo(TMP);
5337 resultStr.setTo("EUR");
5338 if (resultStr != tempStr) {
5339 errcheckln(status, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status));
5340 }
5341 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 2, TMP, 4, &status);
5342 tempStr.setTo(TMP);
5343 resultStr.setTo("DEM");
5344 if (resultStr != tempStr) {
5345 errcheckln(status, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status));
5346 }
5347
5348 // Test Euro Support
5349 status = U_ZERO_ERROR; // reset
5350 date = uprv_getUTCtime();
5351
5352 UChar USD[4];
5353 ucurr_forLocaleAndDate("en_US", date, 1, USD, 4, &status);
5354
5355 UChar YEN[4];
5356 ucurr_forLocaleAndDate("ja_JP", date, 1, YEN, 4, &status);
5357
5358 ucurr_forLocaleAndDate("en_US", date, 1, TMP, 4, &status);
5359 if (u_strcmp(USD, TMP) != 0) {
5360 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
5361 }
5362 ucurr_forLocaleAndDate("en_US_Q", date, 1, TMP, 4, &status);
5363 if (u_strcmp(USD, TMP) != 0) {
5364 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
5365 }
5366 status = U_ZERO_ERROR; // reset
5367 #endif
5368 }
5369
TestGetVariantWithKeywords(void)5370 void LocaleTest::TestGetVariantWithKeywords(void)
5371 {
5372 Locale l("en_US_VALLEY@foo=value");
5373 const char *variant = l.getVariant();
5374 logln(variant);
5375 test_assert(strcmp("VALLEY", variant) == 0);
5376
5377 UErrorCode status = U_ZERO_ERROR;
5378 char buffer[50];
5379 int32_t len = l.getKeywordValue("foo", buffer, 50, status);
5380 buffer[len] = '\0';
5381 test_assert(strcmp("value", buffer) == 0);
5382 }
5383
TestIsRightToLeft()5384 void LocaleTest::TestIsRightToLeft() {
5385 assertFalse("root LTR", Locale::getRoot().isRightToLeft());
5386 assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
5387 assertTrue("ar RTL", Locale("ar").isRightToLeft());
5388 assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), false, true);
5389 assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
5390 assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
5391 assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), false, true); // Sorani Kurdish
5392 assertFalse("fil LTR", Locale("fil").isRightToLeft());
5393 assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
5394 }
5395
TestBug11421()5396 void LocaleTest::TestBug11421() {
5397 Locale::getDefault().getBaseName();
5398 int32_t numLocales;
5399 const Locale *localeList = Locale::getAvailableLocales(numLocales);
5400 for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) {
5401 const Locale &loc = localeList[localeIndex];
5402 if (strncmp(loc.getName(), loc.getBaseName(), strlen(loc.getBaseName()))) {
5403 errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"",
5404 __FILE__, __LINE__, loc.getName(), loc.getBaseName());
5405 break;
5406 }
5407 }
5408 }
5409
5410 // TestBug13277. The failure manifests as valgrind errors.
5411 // See the trac ticket for details.
5412 //
5413
TestBug13277()5414 void LocaleTest::TestBug13277() {
5415 UErrorCode status = U_ZERO_ERROR;
5416 CharString name("en-us-x-foo", -1, status);
5417 while (name.length() < 152) {
5418 name.append("-x-foo", -1, status);
5419 }
5420
5421 while (name.length() < 160) {
5422 name.append('z', status);
5423 Locale loc(name.data(), nullptr, nullptr, nullptr);
5424 }
5425 }
5426
5427 // TestBug13554 Check for read past end of array in getPosixID().
5428 // The bug shows as an Address Sanitizer failure.
5429
TestBug13554()5430 void LocaleTest::TestBug13554() {
5431 UErrorCode status = U_ZERO_ERROR;
5432 const int BUFFER_SIZE = 100;
5433 char posixID[BUFFER_SIZE];
5434
5435 for (uint32_t hostid = 0; hostid < 0x500; ++hostid) {
5436 status = U_ZERO_ERROR;
5437 uprv_convertToPosix(hostid, posixID, BUFFER_SIZE, &status);
5438 }
5439 }
5440
TestBug20410()5441 void LocaleTest::TestBug20410() {
5442 IcuTestErrorCode status(*this, "TestBug20410()");
5443
5444 static const char tag1[] = "art-lojban-x-0";
5445 static const Locale expected1("jbo@x=0");
5446 Locale result1 = Locale::forLanguageTag(tag1, status);
5447 status.errIfFailureAndReset("\"%s\"", tag1);
5448 assertEquals(tag1, expected1.getName(), result1.getName());
5449
5450 static const char tag2[] = "zh-xiang-u-nu-thai-x-0";
5451 static const Locale expected2("hsn@numbers=thai;x=0");
5452 Locale result2 = Locale::forLanguageTag(tag2, status);
5453 status.errIfFailureAndReset("\"%s\"", tag2);
5454 assertEquals(tag2, expected2.getName(), result2.getName());
5455
5456 static const char locid3[] = "art__lojban@x=0";
5457 Locale result3 = Locale::createCanonical(locid3);
5458 static const Locale expected3("jbo@x=0");
5459 assertEquals(locid3, expected3.getName(), result3.getName());
5460
5461 static const char locid4[] = "art-lojban-x-0";
5462 Locale result4 = Locale::createCanonical(locid4);
5463 static const Locale expected4("jbo@x=0");
5464 assertEquals(locid4, expected4.getName(), result4.getName());
5465 }
5466
TestBug20900()5467 void LocaleTest::TestBug20900() {
5468 static const struct {
5469 const char *localeID; /* input */
5470 const char *canonicalID; /* expected canonicalize() result */
5471 } testCases[] = {
5472 { "art-lojban", "jbo" },
5473 { "zh-guoyu", "zh" },
5474 { "zh-hakka", "hak" },
5475 { "zh-xiang", "hsn" },
5476 { "zh-min-nan", "nan" },
5477 { "zh-gan", "gan" },
5478 { "zh-wuu", "wuu" },
5479 { "zh-yue", "yue" },
5480 };
5481
5482 IcuTestErrorCode status(*this, "TestBug20900");
5483 for (int32_t i=0; i < UPRV_LENGTHOF(testCases); i++) {
5484 Locale loc = Locale::createCanonical(testCases[i].localeID);
5485 std::string result = loc.toLanguageTag<std::string>(status);
5486 const char* tag = loc.isBogus() ? "BOGUS" : result.c_str();
5487 status.errIfFailureAndReset("FAIL: createCanonical(%s).toLanguageTag() expected \"%s\"",
5488 testCases[i].localeID, tag);
5489 assertEquals("createCanonical", testCases[i].canonicalID, tag);
5490 }
5491 }
5492
5493 U_DEFINE_LOCAL_OPEN_POINTER(LocalStdioFilePointer, FILE, fclose);
TestLocaleCanonicalizationFromFile()5494 void LocaleTest::TestLocaleCanonicalizationFromFile()
5495 {
5496 IcuTestErrorCode status(*this, "TestLocaleCanonicalizationFromFile");
5497 const char *sourceTestDataPath=getSourceTestData(status);
5498 if(status.errIfFailureAndReset("unable to find the source/test/testdata "
5499 "folder (getSourceTestData())")) {
5500 return;
5501 }
5502 char testPath[400];
5503 char line[256];
5504 strcpy(testPath, sourceTestDataPath);
5505 strcat(testPath, "localeCanonicalization.txt");
5506 LocalStdioFilePointer testFile(fopen(testPath, "r"));
5507 if(testFile.isNull()) {
5508 errln("unable to open %s", testPath);
5509 return;
5510 }
5511 // Format:
5512 // <source locale identifier> ; <expected canonicalized locale identifier>
5513 while (fgets(line, (int)sizeof(line), testFile.getAlias())!=NULL) {
5514 if (line[0] == '#') {
5515 // ignore any lines start with #
5516 continue;
5517 }
5518 char *semi = strchr(line, ';');
5519 if (semi == nullptr) {
5520 // ignore any lines without ;
5521 continue;
5522 }
5523 *semi = '\0'; // null terminiate on the spot of semi
5524 const char* from = u_skipWhitespace((const char*)line);
5525 u_rtrim((char*)from);
5526 const char* to = u_skipWhitespace((const char*)semi + 1);
5527 u_rtrim((char*)to);
5528 std::string expect(to);
5529 // Change the _ to -
5530 std::transform(expect.begin(), expect.end(), expect.begin(),
5531 [](unsigned char c){ return c == '_' ? '-' : c; });
5532
5533 Locale loc = Locale::createCanonical(from);
5534 std::string result = loc.toLanguageTag<std::string>(status);
5535 const char* tag = loc.isBogus() ? "BOGUS" : result.c_str();
5536 status.errIfFailureAndReset(
5537 "FAIL: createCanonical(%s).toLanguageTag() expected \"%s\" locale is %s",
5538 from, tag, loc.getName());
5539 std::string msg("createCanonical(");
5540 msg += from;
5541 msg += ") locale = ";
5542 msg += loc.getName();
5543 assertEquals(msg.c_str(), expect.c_str(), tag);
5544 }
5545 }
5546
TestKnownCanonicalizedListCorrect()5547 void LocaleTest::TestKnownCanonicalizedListCorrect()
5548 {
5549 IcuTestErrorCode status(*this, "TestKnownCanonicalizedListCorrect");
5550 int32_t numOfKnownCanonicalized;
5551 const char* const* knownCanonicalized =
5552 ulocimp_getKnownCanonicalizedLocaleForTest(&numOfKnownCanonicalized);
5553 for (int32_t i = 0; i < numOfKnownCanonicalized; i++) {
5554 std::string msg("Known Canonicalized Locale is not canonicalized: ");
5555 assertTrue((msg + knownCanonicalized[i]).c_str(),
5556 ulocimp_isCanonicalizedLocaleForTest(knownCanonicalized[i]));
5557 }
5558 }
5559
TestConstructorAcceptsBCP47()5560 void LocaleTest::TestConstructorAcceptsBCP47() {
5561 IcuTestErrorCode status(*this, "TestConstructorAcceptsBCP47");
5562
5563 Locale loc1("ar-EG-u-nu-latn");
5564 Locale loc2("ar-EG@numbers=latn");
5565 Locale loc3("ar-EG");
5566 std::string val;
5567
5568 // Check getKeywordValue "numbers"
5569 val = loc1.getKeywordValue<std::string>("numbers", status);
5570 assertEquals("BCP47 syntax has ICU keyword value", "latn", val.c_str());
5571
5572 val = loc2.getKeywordValue<std::string>("numbers", status);
5573 assertEquals("ICU syntax has ICU keyword value", "latn", val.c_str());
5574
5575 val = loc3.getKeywordValue<std::string>("numbers", status);
5576 assertEquals("Default, ICU keyword", "", val.c_str());
5577
5578 // Check getUnicodeKeywordValue "nu"
5579 val = loc1.getUnicodeKeywordValue<std::string>("nu", status);
5580 assertEquals("BCP47 syntax has short unicode keyword value", "latn", val.c_str());
5581
5582 val = loc2.getUnicodeKeywordValue<std::string>("nu", status);
5583 assertEquals("ICU syntax has short unicode keyword value", "latn", val.c_str());
5584
5585 val = loc3.getUnicodeKeywordValue<std::string>("nu", status);
5586 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, short unicode keyword");
5587
5588 // Check getUnicodeKeywordValue "numbers"
5589 val = loc1.getUnicodeKeywordValue<std::string>("numbers", status);
5590 assertEquals("BCP47 syntax has long unicode keyword value", "latn", val.c_str());
5591
5592 val = loc2.getUnicodeKeywordValue<std::string>("numbers", status);
5593 assertEquals("ICU syntax has long unicode keyword value", "latn", val.c_str());
5594
5595 val = loc3.getUnicodeKeywordValue<std::string>("numbers", status);
5596 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, long unicode keyword");
5597 }
5598
TestForLanguageTag()5599 void LocaleTest::TestForLanguageTag() {
5600 IcuTestErrorCode status(*this, "TestForLanguageTag()");
5601
5602 static const char tag_en[] = "en-US";
5603 static const char tag_oed[] = "en-GB-oed";
5604 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
5605 static const char tag_ill[] = "!";
5606 static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' };
5607 static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz";
5608 static const char tag_var[] = "sl-rozaj-biske-1994";
5609
5610 static const Locale loc_en("en_US");
5611 static const Locale loc_oed("en_GB_OXENDICT");
5612 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
5613 static const Locale loc_null("");
5614 static const Locale loc_gb("en_GB");
5615 static const Locale loc_ext("en_GB@1=abc-efg;a=xyz");
5616 static const Locale loc_var("sl__1994_BISKE_ROZAJ");
5617
5618 Locale result_en = Locale::forLanguageTag(tag_en, status);
5619 status.errIfFailureAndReset("\"%s\"", tag_en);
5620 assertEquals(tag_en, loc_en.getName(), result_en.getName());
5621
5622 Locale result_oed = Locale::forLanguageTag(tag_oed, status);
5623 status.errIfFailureAndReset("\"%s\"", tag_oed);
5624 assertEquals(tag_oed, loc_oed.getName(), result_oed.getName());
5625
5626 Locale result_af = Locale::forLanguageTag(tag_af, status);
5627 status.errIfFailureAndReset("\"%s\"", tag_af);
5628 assertEquals(tag_af, loc_af.getName(), result_af.getName());
5629
5630 Locale result_var = Locale::forLanguageTag(tag_var, status);
5631 status.errIfFailureAndReset("\"%s\"", tag_var);
5632 assertEquals(tag_var, loc_var.getName(), result_var.getName());
5633
5634 Locale result_ill = Locale::forLanguageTag(tag_ill, status);
5635 assertEquals(tag_ill, U_ILLEGAL_ARGUMENT_ERROR, status.reset());
5636 assertTrue(result_ill.getName(), result_ill.isBogus());
5637
5638 Locale result_null = Locale::forLanguageTag(nullptr, status);
5639 status.errIfFailureAndReset("nullptr");
5640 assertEquals("nullptr", loc_null.getName(), result_null.getName());
5641
5642 StringPiece sp_substr(tag_oed, 5); // "en-GB", no NUL.
5643 Locale result_substr = Locale::forLanguageTag(sp_substr, status);
5644 status.errIfFailureAndReset("\"%.*s\"", sp_substr.size(), sp_substr.data());
5645 assertEquals(CharString(sp_substr, status).data(),
5646 loc_gb.getName(), result_substr.getName());
5647
5648 StringPiece sp_no_nul(tag_no_nul, sizeof tag_no_nul); // "en-GB", no NUL.
5649 Locale result_no_nul = Locale::forLanguageTag(sp_no_nul, status);
5650 status.errIfFailureAndReset("\"%.*s\"", sp_no_nul.size(), sp_no_nul.data());
5651 assertEquals(CharString(sp_no_nul, status).data(),
5652 loc_gb.getName(), result_no_nul.getName());
5653
5654 Locale result_ext = Locale::forLanguageTag(tag_ext, status);
5655 status.errIfFailureAndReset("\"%s\"", tag_ext);
5656 assertEquals(tag_ext, loc_ext.getName(), result_ext.getName());
5657
5658 static const struct {
5659 const char *inputTag; /* input */
5660 const char *expectedID; /* expected forLanguageTag().getName() result */
5661 } testCases[] = {
5662 // ICU-21433
5663 {"und-1994-biske-rozaj", "__1994_BISKE_ROZAJ"},
5664 {"de-1994-biske-rozaj", "de__1994_BISKE_ROZAJ"},
5665 {"und-x-private", "@x=private"},
5666 {"de-1994-biske-rozaj-x-private", "de__1994_BISKE_ROZAJ@x=private"},
5667 {"und-1994-biske-rozaj-x-private", "__1994_BISKE_ROZAJ@x=private"},
5668 };
5669 int32_t i;
5670 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
5671 UErrorCode status = U_ZERO_ERROR;
5672 std::string otag = testCases[i].inputTag;
5673 std::string tag = Locale::forLanguageTag(otag.c_str(), status).getName();
5674 if (tag != testCases[i].expectedID) {
5675 errcheckln(status, "FAIL: %s should be toLanguageTag to %s but got %s - %s",
5676 otag.c_str(),
5677 testCases[i].expectedID,
5678 tag.c_str(),
5679 u_errorName(status));
5680 }
5681 }
5682 }
5683
TestForLanguageTagLegacyTagBug21676()5684 void LocaleTest::TestForLanguageTagLegacyTagBug21676() {
5685 IcuTestErrorCode status(*this, "TestForLanguageTagLegacyTagBug21676()");
5686 std::string tag(
5687 "i-enochian-1nochian-129-515VNTR-64863775-X3il6-110Y101-29-515VNTR-"
5688 "64863775-153zu-u-Y4-H0-t6-X3-u6-110Y101-X");
5689 std::string input(tag);
5690 input += "EXTRA MEMORY AFTER NON-NULL TERMINATED STRING";
5691 StringPiece stringp(input.c_str(), tag.length());
5692 std::string name = Locale::forLanguageTag(stringp, status).getName();
5693 std::string expected(
5694 "@x=i-enochian-1nochian-129-515vntr-64863775-x3il6-110y101-29-515vntr-"
5695 "64863775-153zu-u-y4-h0-t6-x3-u6-110y101-x");
5696 if (name != expected) {
5697 errcheckln(
5698 status,
5699 "FAIL: forLanguageTag('%s', \n%d).getName() should be \n'%s' but got %s",
5700 tag.c_str(), tag.length(), expected.c_str(), name.c_str());
5701 }
5702 }
5703
TestToLanguageTag()5704 void LocaleTest::TestToLanguageTag() {
5705 IcuTestErrorCode status(*this, "TestToLanguageTag()");
5706
5707 static const Locale loc_c("en_US_POSIX");
5708 static const Locale loc_en("en_US");
5709 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
5710 static const Locale loc_ext("en@0=abc;a=xyz");
5711 static const Locale loc_empty("");
5712 static const Locale loc_ill("!");
5713 static const Locale loc_variant("sl__ROZAJ_BISKE_1994");
5714
5715 static const char tag_c[] = "en-US-u-va-posix";
5716 static const char tag_en[] = "en-US";
5717 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
5718 static const char tag_ext[] = "en-0-abc-a-xyz";
5719 static const char tag_und[] = "und";
5720 static const char tag_variant[] = "sl-1994-biske-rozaj";
5721
5722 std::string result;
5723 StringByteSink<std::string> sink(&result);
5724 loc_c.toLanguageTag(sink, status);
5725 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
5726 assertEquals(loc_c.getName(), tag_c, result.c_str());
5727
5728 std::string result_c = loc_c.toLanguageTag<std::string>(status);
5729 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
5730 assertEquals(loc_c.getName(), tag_c, result_c.c_str());
5731
5732 std::string result_en = loc_en.toLanguageTag<std::string>(status);
5733 status.errIfFailureAndReset("\"%s\"", loc_en.getName());
5734 assertEquals(loc_en.getName(), tag_en, result_en.c_str());
5735
5736 std::string result_af = loc_af.toLanguageTag<std::string>(status);
5737 status.errIfFailureAndReset("\"%s\"", loc_af.getName());
5738 assertEquals(loc_af.getName(), tag_af, result_af.c_str());
5739
5740 std::string result_ext = loc_ext.toLanguageTag<std::string>(status);
5741 status.errIfFailureAndReset("\"%s\"", loc_ext.getName());
5742 assertEquals(loc_ext.getName(), tag_ext, result_ext.c_str());
5743
5744 std::string result_empty = loc_empty.toLanguageTag<std::string>(status);
5745 status.errIfFailureAndReset("\"%s\"", loc_empty.getName());
5746 assertEquals(loc_empty.getName(), tag_und, result_empty.c_str());
5747
5748 std::string result_ill = loc_ill.toLanguageTag<std::string>(status);
5749 status.errIfFailureAndReset("\"%s\"", loc_ill.getName());
5750 assertEquals(loc_ill.getName(), tag_und, result_ill.c_str());
5751
5752 std::string result_variant = loc_variant.toLanguageTag<std::string>(status);
5753 status.errIfFailureAndReset("\"%s\"", loc_variant.getName());
5754 assertEquals(loc_variant.getName(), tag_variant, result_variant.c_str());
5755
5756 Locale loc_bogus;
5757 loc_bogus.setToBogus();
5758 std::string result_bogus = loc_bogus.toLanguageTag<std::string>(status);
5759 assertEquals("bogus", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
5760 assertTrue(result_bogus.c_str(), result_bogus.empty());
5761
5762 static const struct {
5763 const char *localeID; /* input */
5764 const char *expectedID; /* expected toLanguageTag() result */
5765 } testCases[] = {
5766 /* ICU-21414 */
5767 {"und-x-abc-private", "und-x-abc-private"},
5768 {"und-x-private", "und-x-private"},
5769 {"und-u-ca-roc-x-private", "und-u-ca-roc-x-private"},
5770 {"und-US-x-private", "und-US-x-private"},
5771 {"und-Latn-x-private", "und-Latn-x-private"},
5772 {"und-1994-biske-rozaj", "und-1994-biske-rozaj"},
5773 {"und-1994-biske-rozaj-x-private", "und-1994-biske-rozaj-x-private"},
5774 };
5775 int32_t i;
5776 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
5777 UErrorCode status = U_ZERO_ERROR;
5778 std::string otag = testCases[i].localeID;
5779 std::string tag = Locale::forLanguageTag(otag.c_str(), status).toLanguageTag<std::string>(status);
5780 if (tag != testCases[i].expectedID) {
5781 errcheckln(status, "FAIL: %s should be toLanguageTag to %s but got %s - %s",
5782 otag.c_str(),
5783 testCases[i].expectedID,
5784 tag.c_str(),
5785 u_errorName(status));
5786 }
5787 }
5788 }
5789
5790 /* ICU-20310 */
TestToLanguageTagOmitTrue()5791 void LocaleTest::TestToLanguageTagOmitTrue() {
5792 IcuTestErrorCode status(*this, "TestToLanguageTagOmitTrue()");
5793 assertEquals("en-u-kn should drop true",
5794 "en-u-kn", Locale("en-u-kn-true").toLanguageTag<std::string>(status).c_str());
5795 status.errIfFailureAndReset();
5796 assertEquals("en-u-kn should drop true",
5797 "en-u-kn", Locale("en-u-kn").toLanguageTag<std::string>(status).c_str());
5798 status.errIfFailureAndReset();
5799
5800 assertEquals("de-u-co should drop true",
5801 "de-u-co", Locale("de-u-co").toLanguageTag<std::string>(status).c_str());
5802 status.errIfFailureAndReset();
5803 assertEquals("de-u-co should drop true",
5804 "de-u-co", Locale("de-u-co-yes").toLanguageTag<std::string>(status).c_str());
5805 status.errIfFailureAndReset();
5806 assertEquals("de@collation=yes should drop true",
5807 "de-u-co", Locale("de@collation=yes").toLanguageTag<std::string>(status).c_str());
5808 status.errIfFailureAndReset();
5809
5810 assertEquals("cmn-Hans-CN-t-ca-u-ca-x-t-u should drop true",
5811 "cmn-Hans-CN-t-ca-u-ca-x-t-u",
5812 Locale("cmn-hans-cn-u-ca-t-ca-x-t-u").toLanguageTag<std::string>(status).c_str());
5813 status.errIfFailureAndReset();
5814 }
5815
TestMoveAssign()5816 void LocaleTest::TestMoveAssign() {
5817 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
5818 Locale l1("de@collation=phonebook;x="
5819 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5820 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5821 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5822 "aaaaabbbbbzz");
5823
5824 Locale l2;
5825 {
5826 Locale l3(l1);
5827 assertTrue("l1 == l3", l1 == l3);
5828 l2 = std::move(l3);
5829 assertTrue("l1 == l2", l1 == l2);
5830 assertTrue("l2 != l3", l2.getName() != l3.getName());
5831 }
5832
5833 // This should remain true also after l3 has been destructed.
5834 assertTrue("l1 == l2, again", l1 == l2);
5835
5836 Locale l4("de@collation=phonebook");
5837
5838 Locale l5;
5839 {
5840 Locale l6(l4);
5841 assertTrue("l4 == l6", l4 == l6);
5842 l5 = std::move(l6);
5843 assertTrue("l4 == l5", l4 == l5);
5844 assertTrue("l5 != l6", l5.getName() != l6.getName());
5845 }
5846
5847 // This should remain true also after l6 has been destructed.
5848 assertTrue("l4 == l5, again", l4 == l5);
5849
5850 Locale l7("vo_Cyrl_AQ_EURO");
5851
5852 Locale l8;
5853 {
5854 Locale l9(l7);
5855 assertTrue("l7 == l9", l7 == l9);
5856 l8 = std::move(l9);
5857 assertTrue("l7 == l8", l7 == l8);
5858 assertTrue("l8 != l9", l8.getName() != l9.getName());
5859 }
5860
5861 // This should remain true also after l9 has been destructed.
5862 assertTrue("l7 == l8, again", l7 == l8);
5863
5864 assertEquals("language", l7.getLanguage(), l8.getLanguage());
5865 assertEquals("script", l7.getScript(), l8.getScript());
5866 assertEquals("country", l7.getCountry(), l8.getCountry());
5867 assertEquals("variant", l7.getVariant(), l8.getVariant());
5868 assertEquals("bogus", l7.isBogus(), l8.isBogus());
5869 }
5870
TestMoveCtor()5871 void LocaleTest::TestMoveCtor() {
5872 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
5873 Locale l1("de@collation=phonebook;x="
5874 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5875 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5876 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
5877 "aaaaabbbbbzz");
5878
5879 Locale l3(l1);
5880 assertTrue("l1 == l3", l1 == l3);
5881 Locale l2(std::move(l3));
5882 assertTrue("l1 == l2", l1 == l2);
5883 assertTrue("l2 != l3", l2.getName() != l3.getName());
5884
5885 Locale l4("de@collation=phonebook");
5886
5887 Locale l6(l4);
5888 assertTrue("l4 == l6", l4 == l6);
5889 Locale l5(std::move(l6));
5890 assertTrue("l4 == l5", l4 == l5);
5891 assertTrue("l5 != l6", l5.getName() != l6.getName());
5892
5893 Locale l7("vo_Cyrl_AQ_EURO");
5894
5895 Locale l9(l7);
5896 assertTrue("l7 == l9", l7 == l9);
5897 Locale l8(std::move(l9));
5898 assertTrue("l7 == l8", l7 == l8);
5899 assertTrue("l8 != l9", l8.getName() != l9.getName());
5900
5901 assertEquals("language", l7.getLanguage(), l8.getLanguage());
5902 assertEquals("script", l7.getScript(), l8.getScript());
5903 assertEquals("country", l7.getCountry(), l8.getCountry());
5904 assertEquals("variant", l7.getVariant(), l8.getVariant());
5905 assertEquals("bogus", l7.isBogus(), l8.isBogus());
5906 }
5907
TestBug20407iVariantPreferredValue()5908 void LocaleTest::TestBug20407iVariantPreferredValue() {
5909 IcuTestErrorCode status(*this, "TestBug20407iVariantPreferredValue()");
5910
5911 Locale l = Locale::forLanguageTag("hy-arevela", status);
5912 status.errIfFailureAndReset("hy-arevela fail");
5913 assertTrue("!l.isBogus()", !l.isBogus());
5914
5915 std::string result = l.toLanguageTag<std::string>(status);
5916 assertEquals(l.getName(), "hy", result.c_str());
5917
5918 l = Locale::forLanguageTag("hy-arevmda", status);
5919 status.errIfFailureAndReset("hy-arevmda");
5920 assertTrue("!l.isBogus()", !l.isBogus());
5921
5922 result = l.toLanguageTag<std::string>(status);
5923 assertEquals(l.getName(), "hyw", result.c_str());
5924 }
5925
TestBug13417VeryLongLanguageTag()5926 void LocaleTest::TestBug13417VeryLongLanguageTag() {
5927 IcuTestErrorCode status(*this, "TestBug13417VeryLongLanguageTag()");
5928
5929 static const char tag[] =
5930 "zh-x"
5931 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
5932 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
5933 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
5934 "-foo-bar-baz-fxx"
5935 ;
5936
5937 Locale l = Locale::forLanguageTag(tag, status);
5938 status.errIfFailureAndReset("\"%s\"", tag);
5939 assertTrue("!l.isBogus()", !l.isBogus());
5940
5941 std::string result = l.toLanguageTag<std::string>(status);
5942 status.errIfFailureAndReset("\"%s\"", l.getName());
5943 assertEquals("equals", tag, result.c_str());
5944 }
5945
TestBug11053UnderlineTimeZone()5946 void LocaleTest::TestBug11053UnderlineTimeZone() {
5947 static const char* const tz_in_ext[] = {
5948 "etadd",
5949 "tzdar",
5950 "eheai",
5951 "sttms",
5952 "arirj",
5953 "arrgl",
5954 "aruaq",
5955 "arluq",
5956 "mxpvr",
5957 "brbvb",
5958 "arbue",
5959 "caycb",
5960 "brcgr",
5961 "cayzs",
5962 "crsjo",
5963 "caydq",
5964 "svsal",
5965 "cafne",
5966 "caglb",
5967 "cagoo",
5968 "tcgdt",
5969 "ustel",
5970 "bolpb",
5971 "uslax",
5972 "sxphi",
5973 "mxmex",
5974 "usnyc",
5975 "usxul",
5976 "usndcnt",
5977 "usndnsl",
5978 "ttpos",
5979 "brpvh",
5980 "prsju",
5981 "clpuq",
5982 "caffs",
5983 "cayek",
5984 "brrbr",
5985 "mxstis",
5986 "dosdq",
5987 "brsao",
5988 "gpsbh",
5989 "casjf",
5990 "knbas",
5991 "lccas",
5992 "vistt",
5993 "vcsvd",
5994 "cayyn",
5995 "cathu",
5996 "hkhkg",
5997 "mykul",
5998 "khpnh",
5999 "cvrai",
6000 "gsgrv",
6001 "shshn",
6002 "aubhq",
6003 "auldh",
6004 "imdgs",
6005 "smsai",
6006 "asppg",
6007 "pgpom",
6008 };
6009 static const char* const tzname_with_underline[] = {
6010 "America/Buenos_Aires",
6011 "America/Coral_Harbour",
6012 "America/Los_Angeles",
6013 "America/Mexico_City",
6014 "America/New_York",
6015 "America/Rio_Branco",
6016 "America/Sao_Paulo",
6017 "America/St_Johns",
6018 "America/St_Thomas",
6019 "Australia/Broken_Hill",
6020 "Australia/Lord_Howe",
6021 "Pacific/Pago_Pago",
6022 };
6023 std::string locale_str;
6024 for (int32_t i = 0; i < UPRV_LENGTHOF(tz_in_ext); i++) {
6025 locale_str = "en-u-tz-";
6026 locale_str += tz_in_ext[i];
6027 Locale l(locale_str.c_str());
6028 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
6029 }
6030 for (int32_t i = 0; i < UPRV_LENGTHOF(tzname_with_underline); i++) {
6031 locale_str = "en@timezone=";
6032 locale_str += tzname_with_underline[i];
6033 Locale l(locale_str.c_str());
6034 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
6035 }
6036 locale_str = "en_US@timezone=America/Coral_Harbour";
6037 Locale l2(locale_str.c_str());
6038 assertTrue((locale_str + " !l2.isBogus()").c_str(), !l2.isBogus());
6039 locale_str = "en_Latn@timezone=America/New_York";
6040 Locale l3(locale_str.c_str());
6041 assertTrue((locale_str + " !l3.isBogus()").c_str(), !l3.isBogus());
6042 locale_str = "en_Latn_US@timezone=Australia/Broken_Hill";
6043 Locale l4(locale_str.c_str());
6044 assertTrue((locale_str + " !l4.isBogus()").c_str(), !l4.isBogus());
6045 locale_str = "en-u-tz-ciabj";
6046 Locale l5(locale_str.c_str());
6047 assertTrue((locale_str + " !l5.isBogus()").c_str(), !l5.isBogus());
6048 locale_str = "en-US-u-tz-asppg";
6049 Locale l6(locale_str.c_str());
6050 assertTrue((locale_str + " !l6.isBogus()").c_str(), !l6.isBogus());
6051 locale_str = "fil-Latn-u-tz-cvrai";
6052 Locale l7(locale_str.c_str());
6053 assertTrue((locale_str + " !l7.isBogus()").c_str(), !l7.isBogus());
6054 locale_str = "fil-Latn-PH-u-tz-gsgrv";
6055 Locale l8(locale_str.c_str());
6056 assertTrue((locale_str + " !l8.isBogus()").c_str(), !l8.isBogus());
6057 }
6058
TestUnd()6059 void LocaleTest::TestUnd() {
6060 IcuTestErrorCode status(*this, "TestUnd()");
6061
6062 static const char empty[] = "";
6063 static const char root[] = "root";
6064 static const char und[] = "und";
6065
6066 Locale empty_ctor(empty);
6067 Locale empty_tag = Locale::forLanguageTag(empty, status);
6068 status.errIfFailureAndReset("\"%s\"", empty);
6069
6070 Locale root_ctor(root);
6071 Locale root_tag = Locale::forLanguageTag(root, status);
6072 Locale root_build = LocaleBuilder().setLanguageTag(root).build(status);
6073 status.errIfFailureAndReset("\"%s\"", root);
6074
6075 Locale und_ctor(und);
6076 Locale und_tag = Locale::forLanguageTag(und, status);
6077 Locale und_build = LocaleBuilder().setLanguageTag(und).build(status);
6078 status.errIfFailureAndReset("\"%s\"", und);
6079
6080 assertEquals("getName()", empty, empty_ctor.getName());
6081 assertEquals("getName()", empty, root_ctor.getName());
6082 assertEquals("getName()", empty, und_ctor.getName());
6083
6084 assertEquals("getName()", empty, empty_tag.getName());
6085 assertEquals("getName()", empty, root_tag.getName());
6086 assertEquals("getName()", empty, und_tag.getName());
6087
6088 assertEquals("getName()", empty, root_build.getName());
6089 assertEquals("getName()", empty, und_build.getName());
6090
6091 assertEquals("toLanguageTag()", und, empty_ctor.toLanguageTag<std::string>(status).c_str());
6092 assertEquals("toLanguageTag()", und, root_ctor.toLanguageTag<std::string>(status).c_str());
6093 assertEquals("toLanguageTag()", und, und_ctor.toLanguageTag<std::string>(status).c_str());
6094 status.errIfFailureAndReset();
6095
6096 assertEquals("toLanguageTag()", und, empty_tag.toLanguageTag<std::string>(status).c_str());
6097 assertEquals("toLanguageTag()", und, root_tag.toLanguageTag<std::string>(status).c_str());
6098 assertEquals("toLanguageTag()", und, und_tag.toLanguageTag<std::string>(status).c_str());
6099 status.errIfFailureAndReset();
6100
6101 assertEquals("toLanguageTag()", und, root_build.toLanguageTag<std::string>(status).c_str());
6102 assertEquals("toLanguageTag()", und, und_build.toLanguageTag<std::string>(status).c_str());
6103 status.errIfFailureAndReset();
6104
6105 assertTrue("empty_ctor == empty_tag", empty_ctor == empty_tag);
6106
6107 assertTrue("root_ctor == root_tag", root_ctor == root_tag);
6108 assertTrue("root_ctor == root_build", root_ctor == root_build);
6109 assertTrue("root_tag == root_build", root_tag == root_build);
6110
6111 assertTrue("und_ctor == und_tag", und_ctor == und_tag);
6112 assertTrue("und_ctor == und_build", und_ctor == und_build);
6113 assertTrue("und_tag == und_build", und_tag == und_build);
6114
6115 assertTrue("empty_ctor == root_ctor", empty_ctor == root_ctor);
6116 assertTrue("empty_ctor == und_ctor", empty_ctor == und_ctor);
6117 assertTrue("root_ctor == und_ctor", root_ctor == und_ctor);
6118
6119 assertTrue("empty_tag == root_tag", empty_tag == root_tag);
6120 assertTrue("empty_tag == und_tag", empty_tag == und_tag);
6121 assertTrue("root_tag == und_tag", root_tag == und_tag);
6122
6123 assertTrue("root_build == und_build", root_build == und_build);
6124
6125 static const Locale& displayLocale = Locale::getEnglish();
6126 static const UnicodeString displayName("Unknown language");
6127 UnicodeString tmp;
6128
6129 assertEquals("getDisplayName()", displayName, empty_ctor.getDisplayName(displayLocale, tmp));
6130 assertEquals("getDisplayName()", displayName, root_ctor.getDisplayName(displayLocale, tmp));
6131 assertEquals("getDisplayName()", displayName, und_ctor.getDisplayName(displayLocale, tmp));
6132
6133 assertEquals("getDisplayName()", displayName, empty_tag.getDisplayName(displayLocale, tmp));
6134 assertEquals("getDisplayName()", displayName, root_tag.getDisplayName(displayLocale, tmp));
6135 assertEquals("getDisplayName()", displayName, und_tag.getDisplayName(displayLocale, tmp));
6136
6137 assertEquals("getDisplayName()", displayName, root_build.getDisplayName(displayLocale, tmp));
6138 assertEquals("getDisplayName()", displayName, und_build.getDisplayName(displayLocale, tmp));
6139 }
6140
TestUndScript()6141 void LocaleTest::TestUndScript() {
6142 IcuTestErrorCode status(*this, "TestUndScript()");
6143
6144 static const char id[] = "_Cyrl";
6145 static const char tag[] = "und-Cyrl";
6146 static const char script[] = "Cyrl";
6147
6148 Locale locale_ctor(id);
6149 Locale locale_legacy(tag);
6150 Locale locale_tag = Locale::forLanguageTag(tag, status);
6151 Locale locale_build = LocaleBuilder().setScript(script).build(status);
6152 status.errIfFailureAndReset("\"%s\"", tag);
6153
6154 assertEquals("getName()", id, locale_ctor.getName());
6155 assertEquals("getName()", id, locale_legacy.getName());
6156 assertEquals("getName()", id, locale_tag.getName());
6157 assertEquals("getName()", id, locale_build.getName());
6158
6159 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
6160 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
6161 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
6162 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
6163 status.errIfFailureAndReset();
6164
6165 static const Locale& displayLocale = Locale::getEnglish();
6166 static const UnicodeString displayName("Unknown language (Cyrillic)");
6167 UnicodeString tmp;
6168
6169 assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp));
6170 assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
6171 assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp));
6172 assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp));
6173 }
6174
TestUndRegion()6175 void LocaleTest::TestUndRegion() {
6176 IcuTestErrorCode status(*this, "TestUndRegion()");
6177
6178 static const char id[] = "_AQ";
6179 static const char tag[] = "und-AQ";
6180 static const char region[] = "AQ";
6181
6182 Locale locale_ctor(id);
6183 Locale locale_legacy(tag);
6184 Locale locale_tag = Locale::forLanguageTag(tag, status);
6185 Locale locale_build = LocaleBuilder().setRegion(region).build(status);
6186 status.errIfFailureAndReset("\"%s\"", tag);
6187
6188 assertEquals("getName()", id, locale_ctor.getName());
6189 assertEquals("getName()", id, locale_legacy.getName());
6190 assertEquals("getName()", id, locale_tag.getName());
6191 assertEquals("getName()", id, locale_build.getName());
6192
6193 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
6194 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
6195 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
6196 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
6197 status.errIfFailureAndReset();
6198
6199 static const Locale& displayLocale = Locale::getEnglish();
6200 static const UnicodeString displayName("Unknown language (Antarctica)");
6201 UnicodeString tmp;
6202
6203 assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp));
6204 assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
6205 assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp));
6206 assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp));
6207 }
6208
TestUndCAPI()6209 void LocaleTest::TestUndCAPI() {
6210 IcuTestErrorCode status(*this, "TestUndCAPI()");
6211
6212 static const char empty[] = "";
6213 static const char root[] = "root";
6214 static const char und[] = "und";
6215
6216 static const char empty_script[] = "_Cyrl";
6217 static const char empty_region[] = "_AQ";
6218
6219 static const char und_script[] = "und_Cyrl";
6220 static const char und_region[] = "und_AQ";
6221
6222 char tmp[ULOC_FULLNAME_CAPACITY];
6223 int32_t reslen;
6224
6225 // uloc_getName()
6226
6227 uprv_memset(tmp, '!', sizeof tmp);
6228 reslen = uloc_getName(empty, tmp, sizeof tmp, status);
6229 status.errIfFailureAndReset("\"%s\"", empty);
6230 assertTrue("reslen >= 0", reslen >= 0);
6231 assertEquals("uloc_getName()", empty, tmp);
6232
6233 uprv_memset(tmp, '!', sizeof tmp);
6234 reslen = uloc_getName(root, tmp, sizeof tmp, status);
6235 status.errIfFailureAndReset("\"%s\"", root);
6236 assertTrue("reslen >= 0", reslen >= 0);
6237 assertEquals("uloc_getName()", empty, tmp);
6238
6239 uprv_memset(tmp, '!', sizeof tmp);
6240 reslen = uloc_getName(und, tmp, sizeof tmp, status);
6241 status.errIfFailureAndReset("\"%s\"", und);
6242 assertTrue("reslen >= 0", reslen >= 0);
6243 assertEquals("uloc_getName()", empty, tmp);
6244
6245 uprv_memset(tmp, '!', sizeof tmp);
6246 reslen = uloc_getName(empty_script, tmp, sizeof tmp, status);
6247 status.errIfFailureAndReset("\"%s\"", empty_script);
6248 assertTrue("reslen >= 0", reslen >= 0);
6249 assertEquals("uloc_getName()", empty_script, tmp);
6250
6251 uprv_memset(tmp, '!', sizeof tmp);
6252 reslen = uloc_getName(empty_region, tmp, sizeof tmp, status);
6253 status.errIfFailureAndReset("\"%s\"", empty_region);
6254 assertTrue("reslen >= 0", reslen >= 0);
6255 assertEquals("uloc_getName()", empty_region, tmp);
6256
6257 uprv_memset(tmp, '!', sizeof tmp);
6258 reslen = uloc_getName(und_script, tmp, sizeof tmp, status);
6259 status.errIfFailureAndReset("\"%s\"", und_script);
6260 assertTrue("reslen >= 0", reslen >= 0);
6261 assertEquals("uloc_getName()", empty_script, tmp);
6262
6263 uprv_memset(tmp, '!', sizeof tmp);
6264 reslen = uloc_getName(und_region, tmp, sizeof tmp, status);
6265 status.errIfFailureAndReset("\"%s\"", und_region);
6266 assertTrue("reslen >= 0", reslen >= 0);
6267 assertEquals("uloc_getName()", empty_region, tmp);
6268
6269 // uloc_getBaseName()
6270
6271 uprv_memset(tmp, '!', sizeof tmp);
6272 reslen = uloc_getBaseName(empty, tmp, sizeof tmp, status);
6273 status.errIfFailureAndReset("\"%s\"", empty);
6274 assertTrue("reslen >= 0", reslen >= 0);
6275 assertEquals("uloc_getBaseName()", empty, tmp);
6276
6277 uprv_memset(tmp, '!', sizeof tmp);
6278 reslen = uloc_getBaseName(root, tmp, sizeof tmp, status);
6279 status.errIfFailureAndReset("\"%s\"", root);
6280 assertTrue("reslen >= 0", reslen >= 0);
6281 assertEquals("uloc_getBaseName()", empty, tmp);
6282
6283 uprv_memset(tmp, '!', sizeof tmp);
6284 reslen = uloc_getBaseName(und, tmp, sizeof tmp, status);
6285 status.errIfFailureAndReset("\"%s\"", und);
6286 assertTrue("reslen >= 0", reslen >= 0);
6287 assertEquals("uloc_getBaseName()", empty, tmp);
6288
6289 uprv_memset(tmp, '!', sizeof tmp);
6290 reslen = uloc_getBaseName(empty_script, tmp, sizeof tmp, status);
6291 status.errIfFailureAndReset("\"%s\"", empty_script);
6292 assertTrue("reslen >= 0", reslen >= 0);
6293 assertEquals("uloc_getBaseName()", empty_script, tmp);
6294
6295 uprv_memset(tmp, '!', sizeof tmp);
6296 reslen = uloc_getBaseName(empty_region, tmp, sizeof tmp, status);
6297 status.errIfFailureAndReset("\"%s\"", empty_region);
6298 assertTrue("reslen >= 0", reslen >= 0);
6299 assertEquals("uloc_getBaseName()", empty_region, tmp);
6300
6301 uprv_memset(tmp, '!', sizeof tmp);
6302 reslen = uloc_getBaseName(und_script, tmp, sizeof tmp, status);
6303 status.errIfFailureAndReset("\"%s\"", und_script);
6304 assertTrue("reslen >= 0", reslen >= 0);
6305 assertEquals("uloc_getBaseName()", empty_script, tmp);
6306
6307 uprv_memset(tmp, '!', sizeof tmp);
6308 reslen = uloc_getBaseName(und_region, tmp, sizeof tmp, status);
6309 status.errIfFailureAndReset("\"%s\"", und_region);
6310 assertTrue("reslen >= 0", reslen >= 0);
6311 assertEquals("uloc_getBaseName()", empty_region, tmp);
6312
6313 // uloc_getParent()
6314
6315 uprv_memset(tmp, '!', sizeof tmp);
6316 reslen = uloc_getParent(empty, tmp, sizeof tmp, status);
6317 status.errIfFailureAndReset("\"%s\"", empty);
6318 assertTrue("reslen >= 0", reslen >= 0);
6319 assertEquals("uloc_getParent()", empty, tmp);
6320
6321 uprv_memset(tmp, '!', sizeof tmp);
6322 reslen = uloc_getParent(root, tmp, sizeof tmp, status);
6323 status.errIfFailureAndReset("\"%s\"", root);
6324 assertTrue("reslen >= 0", reslen >= 0);
6325 assertEquals("uloc_getParent()", empty, tmp);
6326
6327 uprv_memset(tmp, '!', sizeof tmp);
6328 reslen = uloc_getParent(und, tmp, sizeof tmp, status);
6329 status.errIfFailureAndReset("\"%s\"", und);
6330 assertTrue("reslen >= 0", reslen >= 0);
6331 assertEquals("uloc_getParent()", empty, tmp);
6332
6333 uprv_memset(tmp, '!', sizeof tmp);
6334 reslen = uloc_getParent(empty_script, tmp, sizeof tmp, status);
6335 status.errIfFailureAndReset("\"%s\"", empty_script);
6336 assertTrue("reslen >= 0", reslen >= 0);
6337 assertEquals("uloc_getParent()", empty, tmp);
6338
6339 uprv_memset(tmp, '!', sizeof tmp);
6340 reslen = uloc_getParent(empty_region, tmp, sizeof tmp, status);
6341 status.errIfFailureAndReset("\"%s\"", empty_region);
6342 assertTrue("reslen >= 0", reslen >= 0);
6343 assertEquals("uloc_getParent()", empty, tmp);
6344
6345 uprv_memset(tmp, '!', sizeof tmp);
6346 reslen = uloc_getParent(und_script, tmp, sizeof tmp, status);
6347 status.errIfFailureAndReset("\"%s\"", und_script);
6348 assertTrue("reslen >= 0", reslen >= 0);
6349 assertEquals("uloc_getParent()", empty, tmp);
6350
6351 uprv_memset(tmp, '!', sizeof tmp);
6352 reslen = uloc_getParent(und_region, tmp, sizeof tmp, status);
6353 status.errIfFailureAndReset("\"%s\"", und_region);
6354 assertTrue("reslen >= 0", reslen >= 0);
6355 assertEquals("uloc_getParent()", empty, tmp);
6356
6357 // uloc_getLanguage()
6358
6359 uprv_memset(tmp, '!', sizeof tmp);
6360 reslen = uloc_getLanguage(empty, tmp, sizeof tmp, status);
6361 status.errIfFailureAndReset("\"%s\"", empty);
6362 assertTrue("reslen >= 0", reslen >= 0);
6363 assertEquals("uloc_getLanguage()", empty, tmp);
6364
6365 uprv_memset(tmp, '!', sizeof tmp);
6366 reslen = uloc_getLanguage(root, tmp, sizeof tmp, status);
6367 status.errIfFailureAndReset("\"%s\"", root);
6368 assertTrue("reslen >= 0", reslen >= 0);
6369 assertEquals("uloc_getLanguage()", empty, tmp);
6370
6371 uprv_memset(tmp, '!', sizeof tmp);
6372 reslen = uloc_getLanguage(und, tmp, sizeof tmp, status);
6373 status.errIfFailureAndReset("\"%s\"", und);
6374 assertTrue("reslen >= 0", reslen >= 0);
6375 assertEquals("uloc_getLanguage()", empty, tmp);
6376
6377 uprv_memset(tmp, '!', sizeof tmp);
6378 reslen = uloc_getLanguage(empty_script, tmp, sizeof tmp, status);
6379 status.errIfFailureAndReset("\"%s\"", empty_script);
6380 assertTrue("reslen >= 0", reslen >= 0);
6381 assertEquals("uloc_getLanguage()", empty, tmp);
6382
6383 uprv_memset(tmp, '!', sizeof tmp);
6384 reslen = uloc_getLanguage(empty_region, tmp, sizeof tmp, status);
6385 status.errIfFailureAndReset("\"%s\"", empty_region);
6386 assertTrue("reslen >= 0", reslen >= 0);
6387 assertEquals("uloc_getLanguage()", empty, tmp);
6388
6389 uprv_memset(tmp, '!', sizeof tmp);
6390 reslen = uloc_getLanguage(und_script, tmp, sizeof tmp, status);
6391 status.errIfFailureAndReset("\"%s\"", und_script);
6392 assertTrue("reslen >= 0", reslen >= 0);
6393 assertEquals("uloc_getLanguage()", empty, tmp);
6394
6395 uprv_memset(tmp, '!', sizeof tmp);
6396 reslen = uloc_getLanguage(und_region, tmp, sizeof tmp, status);
6397 status.errIfFailureAndReset("\"%s\"", und_region);
6398 assertTrue("reslen >= 0", reslen >= 0);
6399 assertEquals("uloc_getLanguage()", empty, tmp);
6400 }
6401
6402 #define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array))
6403
TestRangeIterator()6404 void LocaleTest::TestRangeIterator() {
6405 IcuTestErrorCode status(*this, "TestRangeIterator");
6406 Locale locales[] = { "fr", "en_GB", "en" };
6407 Locale::RangeIterator<Locale *> iter(ARRAY_RANGE(locales));
6408
6409 assertTrue("0.hasNext()", iter.hasNext());
6410 const Locale &l0 = iter.next();
6411 assertEquals("0.next()", "fr", l0.getName());
6412 assertTrue("&0.next()", &l0 == &locales[0]);
6413
6414 assertTrue("1.hasNext()", iter.hasNext());
6415 const Locale &l1 = iter.next();
6416 assertEquals("1.next()", "en_GB", l1.getName());
6417 assertTrue("&1.next()", &l1 == &locales[1]);
6418
6419 assertTrue("2.hasNext()", iter.hasNext());
6420 const Locale &l2 = iter.next();
6421 assertEquals("2.next()", "en", l2.getName());
6422 assertTrue("&2.next()", &l2 == &locales[2]);
6423
6424 assertFalse("3.hasNext()", iter.hasNext());
6425 }
6426
TestPointerConvertingIterator()6427 void LocaleTest::TestPointerConvertingIterator() {
6428 IcuTestErrorCode status(*this, "TestPointerConvertingIterator");
6429 Locale locales[] = { "fr", "en_GB", "en" };
6430 Locale *pointers[] = { locales, locales + 1, locales + 2 };
6431 // Lambda with explicit reference return type to prevent copy-constructing a temporary
6432 // which would be destructed right away.
6433 Locale::ConvertingIterator<Locale **, std::function<const Locale &(const Locale *)>> iter(
6434 ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; });
6435
6436 assertTrue("0.hasNext()", iter.hasNext());
6437 const Locale &l0 = iter.next();
6438 assertEquals("0.next()", "fr", l0.getName());
6439 assertTrue("&0.next()", &l0 == pointers[0]);
6440
6441 assertTrue("1.hasNext()", iter.hasNext());
6442 const Locale &l1 = iter.next();
6443 assertEquals("1.next()", "en_GB", l1.getName());
6444 assertTrue("&1.next()", &l1 == pointers[1]);
6445
6446 assertTrue("2.hasNext()", iter.hasNext());
6447 const Locale &l2 = iter.next();
6448 assertEquals("2.next()", "en", l2.getName());
6449 assertTrue("&2.next()", &l2 == pointers[2]);
6450
6451 assertFalse("3.hasNext()", iter.hasNext());
6452 }
6453
6454 namespace {
6455
6456 class LocaleFromTag {
6457 public:
LocaleFromTag()6458 LocaleFromTag() : locale(Locale::getRoot()) {}
operator ()(const char * tag)6459 const Locale &operator()(const char *tag) { return locale = Locale(tag); }
6460
6461 private:
6462 // Store the locale in the converter, rather than return a reference to a temporary,
6463 // or a value which could go out of scope with the caller's reference to it.
6464 Locale locale;
6465 };
6466
6467 } // namespace
6468
TestTagConvertingIterator()6469 void LocaleTest::TestTagConvertingIterator() {
6470 IcuTestErrorCode status(*this, "TestTagConvertingIterator");
6471 const char *tags[] = { "fr", "en_GB", "en" };
6472 LocaleFromTag converter;
6473 Locale::ConvertingIterator<const char **, LocaleFromTag> iter(ARRAY_RANGE(tags), converter);
6474
6475 assertTrue("0.hasNext()", iter.hasNext());
6476 const Locale &l0 = iter.next();
6477 assertEquals("0.next()", "fr", l0.getName());
6478
6479 assertTrue("1.hasNext()", iter.hasNext());
6480 const Locale &l1 = iter.next();
6481 assertEquals("1.next()", "en_GB", l1.getName());
6482
6483 assertTrue("2.hasNext()", iter.hasNext());
6484 const Locale &l2 = iter.next();
6485 assertEquals("2.next()", "en", l2.getName());
6486
6487 assertFalse("3.hasNext()", iter.hasNext());
6488 }
6489
TestCapturingTagConvertingIterator()6490 void LocaleTest::TestCapturingTagConvertingIterator() {
6491 IcuTestErrorCode status(*this, "TestCapturingTagConvertingIterator");
6492 const char *tags[] = { "fr", "en_GB", "en" };
6493 // Store the converted locale in a locale variable,
6494 // rather than return a reference to a temporary,
6495 // or a value which could go out of scope with the caller's reference to it.
6496 Locale locale;
6497 // Lambda with explicit reference return type to prevent copy-constructing a temporary
6498 // which would be destructed right away.
6499 Locale::ConvertingIterator<const char **, std::function<const Locale &(const char *)>> iter(
6500 ARRAY_RANGE(tags), [&](const char *tag) -> const Locale & { return locale = Locale(tag); });
6501
6502 assertTrue("0.hasNext()", iter.hasNext());
6503 const Locale &l0 = iter.next();
6504 assertEquals("0.next()", "fr", l0.getName());
6505
6506 assertTrue("1.hasNext()", iter.hasNext());
6507 const Locale &l1 = iter.next();
6508 assertEquals("1.next()", "en_GB", l1.getName());
6509
6510 assertTrue("2.hasNext()", iter.hasNext());
6511 const Locale &l2 = iter.next();
6512 assertEquals("2.next()", "en", l2.getName());
6513
6514 assertFalse("3.hasNext()", iter.hasNext());
6515 }
6516
TestSetUnicodeKeywordValueInLongLocale()6517 void LocaleTest::TestSetUnicodeKeywordValueInLongLocale() {
6518 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueInLongLocale");
6519 const char* value = "efghijkl";
6520 icu::Locale l("de");
6521 char keyword[3];
6522 CharString expected("de-u", status);
6523 keyword[2] = '\0';
6524 for (char i = 'a'; i < 's'; i++) {
6525 keyword[0] = keyword[1] = i;
6526 expected.append("-", status);
6527 expected.append(keyword, status);
6528 expected.append("-", status);
6529 expected.append(value, status);
6530 l.setUnicodeKeywordValue(keyword, value, status);
6531 if (status.errIfFailureAndReset(
6532 "setUnicodeKeywordValue(\"%s\", \"%s\") fail while locale is \"%s\"",
6533 keyword, value, l.getName())) {
6534 return;
6535 }
6536 std::string tag = l.toLanguageTag<std::string>(status);
6537 if (status.errIfFailureAndReset(
6538 "toLanguageTag fail on \"%s\"", l.getName())) {
6539 return;
6540 }
6541 if (tag != expected.data()) {
6542 errln("Expected to get \"%s\" bug got \"%s\"", tag.c_str(),
6543 expected.data());
6544 return;
6545 }
6546 }
6547 }
6548
TestLongLocaleSetKeywordAssign()6549 void LocaleTest::TestLongLocaleSetKeywordAssign() {
6550 IcuTestErrorCode status(*this, "TestLongLocaleSetKeywordAssign");
6551 // A long base name, with an illegal keyword and copy constructor
6552 icu::Locale l("de_AAAAAAA1_AAAAAAA2_AAAAAAA3_AAAAAAA4_AAAAAAA5_AAAAAAA6_"
6553 "AAAAAAA7_AAAAAAA8_AAAAAAA9_AAAAAA10_AAAAAA11_AAAAAA12_"
6554 "AAAAAA13_AAAAAA14_AAAAAA15_AAAAAA16_AAAAAA17_AAAAAA18");
6555 Locale l2;
6556 l.setUnicodeKeywordValue("co", "12", status); // Cause an error
6557 status.reset();
6558 l2 = l; // copy operator on such bogus locale.
6559 }
6560
TestLongLocaleSetKeywordMoveAssign()6561 void LocaleTest::TestLongLocaleSetKeywordMoveAssign() {
6562 IcuTestErrorCode status(*this, "TestLongLocaleSetKeywordMoveAssign");
6563 // A long base name, with an illegal keyword and copy constructor
6564 icu::Locale l("de_AAAAAAA1_AAAAAAA2_AAAAAAA3_AAAAAAA4_AAAAAAA5_AAAAAAA6_"
6565 "AAAAAAA7_AAAAAAA8_AAAAAAA9_AAAAAA10_AAAAAA11_AAAAAA12_"
6566 "AAAAAA13_AAAAAA14_AAAAAA15_AAAAAA16_AAAAAA17");
6567 Locale l2;
6568 l.setUnicodeKeywordValue("co", "12", status); // Cause an error
6569 status.reset();
6570 Locale l3 = std::move(l); // move assign
6571 }
6572
TestSetUnicodeKeywordValueNullInLongLocale()6573 void LocaleTest::TestSetUnicodeKeywordValueNullInLongLocale() {
6574 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueNullInLongLocale");
6575 const char *exts[] = {"cf", "cu", "em", "kk", "kr", "ks", "kv", "lb", "lw",
6576 "ms", "nu", "rg", "sd", "ss", "tz"};
6577 for (int32_t i = 0; i < UPRV_LENGTHOF(exts); i++) {
6578 CharString tag("de-u", status);
6579 for (int32_t j = 0; j <= i; j++) {
6580 tag.append("-", status).append(exts[j], status);
6581 }
6582 if (status.errIfFailureAndReset(
6583 "Cannot create tag \"%s\"", tag.data())) {
6584 continue;
6585 }
6586 Locale l = Locale::forLanguageTag(tag.data(), status);
6587 if (status.errIfFailureAndReset(
6588 "Locale::forLanguageTag(\"%s\") failed", tag.data())) {
6589 continue;
6590 }
6591 for (int32_t j = 0; j <= i; j++) {
6592 l.setUnicodeKeywordValue(exts[j], nullptr, status);
6593 if (status.errIfFailureAndReset(
6594 "Locale(\"%s\").setUnicodeKeywordValue(\"%s\", nullptr) failed",
6595 tag.data(), exts[j])) {
6596 continue;
6597 }
6598 }
6599 if (strcmp("de", l.getName()) != 0) {
6600 errln("setUnicodeKeywordValue should remove all extensions from "
6601 "\"%s\" and only have \"de\", but is \"%s\" instead.",
6602 tag.data(), l.getName());
6603 }
6604 }
6605 }
6606
TestLeak21419()6607 void LocaleTest::TestLeak21419() {
6608 IcuTestErrorCode status(*this, "TestLeak21419");
6609 Locale l = Locale("s-yU");
6610 l.canonicalize(status);
6611 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
6612 }
6613
TestNullDereferenceWrite21597()6614 void LocaleTest::TestNullDereferenceWrite21597() {
6615 IcuTestErrorCode status(*this, "TestNullDereferenceWrite21597");
6616 Locale l = Locale("zu-t-q5-X1-vKf-KK-Ks-cO--Kc");
6617 l.canonicalize(status);
6618 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
6619 }
6620 #if !UCONFIG_NO_FORMATTING
TestSierraLeoneCurrency21997()6621 void LocaleTest::TestSierraLeoneCurrency21997() {
6622 // CLDR 41: Check that currency of Sierra Leone is SLL (which is legal tender)
6623 // and not the newer currency SLE (which is not legal tender), as of CLDR 41.
6624 // Test will fail once SLE is declared legal.
6625 // CLDR 42: Now check that currency of Sierra Leone is SLE (which is legal tender)
6626 UnicodeString sllStr("SLE", ""), resultStr;
6627 UChar tmp[4];
6628 UErrorCode status = U_ZERO_ERROR;
6629
6630 ucurr_forLocale("en_SL", tmp, 4, &status);
6631 resultStr.setTo(tmp);
6632 if (sllStr != resultStr) {
6633 errcheckln(status, "Fail: en_SL didn't return SLE - %s", u_errorName(status));
6634 }
6635 }
6636 #endif
6637