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