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