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