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