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