• 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 *
10 * File CLOCTST.C
11 *
12 * Modification History:
13 *        Name                     Description
14 *     Madhu Katragadda            Ported for C API
15 ******************************************************************************
16 */
17 #include "cloctst.h"
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "cintltst.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 #include "uparse.h"
26 #include "uresimp.h"
27 #include "uassert.h"
28 
29 #include "unicode/putil.h"
30 #include "unicode/ubrk.h"
31 #include "unicode/uchar.h"
32 #include "unicode/ucol.h"
33 #include "unicode/udat.h"
34 #include "unicode/uloc.h"
35 #include "unicode/umsg.h"
36 #include "unicode/ures.h"
37 #include "unicode/uset.h"
38 #include "unicode/ustring.h"
39 #include "unicode/utypes.h"
40 #include "unicode/ulocdata.h"
41 #include "unicode/uldnames.h"
42 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
43 #include "udbgutil.h"
44 
45 static void TestNullDefault(void);
46 static void TestNonexistentLanguageExemplars(void);
47 static void TestLocDataErrorCodeChaining(void);
48 static void TestLocDataWithRgTag(void);
49 static void TestLanguageExemplarsFallbacks(void);
50 static void TestDisplayNameBrackets(void);
51 static void TestIllegalArgumentWhenNoDataWithNoSubstitute(void);
52 static void Test21157CorrectTerminating(void);
53 
54 static void TestUnicodeDefines(void);
55 
56 static void TestIsRightToLeft(void);
57 static void TestBadLocaleIDs(void);
58 static void TestBug20370(void);
59 static void TestBug20321UnicodeLocaleKey(void);
60 
61 static void TestUsingDefaultWarning(void);
62 static void TestExcessivelyLongIDs(void);
63 #if !UCONFIG_NO_FORMATTING
64 static void TestUldnNameVariants(void);
65 #endif
66 
67 void PrintDataTable();
68 
69 /*---------------------------------------------------
70   table of valid data
71  --------------------------------------------------- */
72 #define LOCALE_SIZE 9
73 #define LOCALE_INFO_SIZE 28
74 
75 static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
76     /* language code */
77     {   "en",   "fr",   "ca",   "el",   "no",   "zh",   "de",   "es",  "ja"    },
78     /* script code */
79     {   "",     "",     "",     "",     "",     "", "", "", ""  },
80     /* country code */
81     {   "US",   "FR",   "ES",   "GR",   "NO",   "CN", "DE", "", "JP"    },
82     /* variant code */
83     {   "",     "",     "",     "",     "NY",   "", "", "", ""      },
84     /* full name */
85     {   "en_US",    "fr_FR",    "ca_ES",
86         "el_GR",    "no_NO_NY", "zh_Hans_CN",
87         "de_DE@collation=phonebook", "es@collation=traditional",  "ja_JP@calendar=japanese" },
88     /* ISO-3 language */
89     {   "eng",  "fra",  "cat",  "ell",  "nor",  "zho", "deu", "spa", "jpn"   },
90     /* ISO-3 country */
91     {   "USA",  "FRA",  "ESP",  "GRC",  "NOR",  "CHN", "DEU", "", "JPN"   },
92     /* LCID */
93     {   "409", "40c", "403", "408", "814",  "804", "10407", "40a", "411"     },
94 
95     /* display language (English) */
96     {   "English",  "French",   "Catalan", "Greek",    "Norwegian", "Chinese", "German", "Spanish", "Japanese"    },
97     /* display script code (English) */
98     {   "",     "",     "",     "",     "",     "Simplified Han", "", "", ""       },
99     /* display country (English) */
100     {   "United States",    "France",   "Spain",  "Greece",   "Norway", "China", "Germany", "", "Japan"       },
101     /* display variant (English) */
102     {   "",     "",     "",     "",     "NY",  "", "", "", ""       },
103     /* display name (English) */
104     {   "English (United States)", "French (France)", "Catalan (Spain)",
105         "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
106         "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
107 
108     /* display language (French) */
109     {   "anglais",  "fran\\u00E7ais",   "catalan", "grec",    "norv\\u00E9gien",    "chinois", "allemand", "espagnol", "japonais"     },
110     /* display script code (French) */
111     {   "",     "",     "",     "",     "",     "sinogrammes simplifi\\u00e9s", "", "", ""         },
112     /* display country (French) */
113     {   "\\u00C9tats-Unis",    "France",   "Espagne",  "Gr\\u00E8ce",   "Norv\\u00E8ge",    "Chine", "Allemagne", "", "Japon"       },
114     /* display variant (French) */
115     {   "",     "",     "",     "",     "NY",   "", "", "", ""       },
116     /* display name (French) */
117     {   "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
118         "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)",  "chinois (simplifi\\u00e9, Chine)",
119         "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
120 
121     /* display language (Catalan) */
122     {   "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec",  "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s"    },
123     /* display script code (Catalan) */
124     {   "",     "",     "",     "",     "",     "han simplificat", "", "", ""         },
125     /* display country (Catalan) */
126     {   "Estats Units", "Fran\\u00E7a", "Espanya",  "Gr\\u00E8cia", "Noruega",  "Xina", "Alemanya", "", "Jap\\u00F3"    },
127     /* display variant (Catalan) */
128     {   "", "", "",                    "", "NY",    "", "", "", ""    },
129     /* display name (Catalan) */
130     {   "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
131     "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
132     "alemany (Alemanya, ordre=ordre de la guia telef\\u00F2nica)", "espanyol (ordre=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
133 
134     /* display language (Greek) */
135     {
136         "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
137         "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
138         "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
139         "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
140         "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
141         "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
142         "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
143         "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
144         "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
145     },
146     /* display script code (Greek) */
147 
148     {   "",     "",     "",     "",     "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
149     /* display country (Greek) */
150     {
151         "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
152         "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
153         "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
154         "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
155         "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
156         "\\u039A\\u03AF\\u03BD\\u03B1",
157         "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
158         "",
159         "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
160     },
161     /* display variant (Greek) */
162     {   "", "", "", "", "NY", "", "", "", ""    }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
163     /* display name (Greek) */
164     {
165         "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
166         "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
167         "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
168         "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
169         "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
170         "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
171         "\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03af\\u03b1, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2 \\u03c4\\u03b7\\u03bb\\u03b5\\u03c6\\u03c9\\u03bd\\u03b9\\u03ba\\u03bf\\u03cd \\u03ba\\u03b1\\u03c4\\u03b1\\u03bb\\u03cc\\u03b3\\u03bf\\u03c5)",
172         "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)",
173         "\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03af\\u03b1, \\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf)"
174     }
175 };
176 
177 static UChar*** dataTable=0;
178 enum {
179     ENGLISH = 0,
180     FRENCH = 1,
181     CATALAN = 2,
182     GREEK = 3,
183     NORWEGIAN = 4
184 };
185 
186 enum {
187     LANG = 0,
188     SCRIPT = 1,
189     CTRY = 2,
190     VAR = 3,
191     NAME = 4,
192     LANG3 = 5,
193     CTRY3 = 6,
194     LCID = 7,
195     DLANG_EN = 8,
196     DSCRIPT_EN = 9,
197     DCTRY_EN = 10,
198     DVAR_EN = 11,
199     DNAME_EN = 12,
200     DLANG_FR = 13,
201     DSCRIPT_FR = 14,
202     DCTRY_FR = 15,
203     DVAR_FR = 16,
204     DNAME_FR = 17,
205     DLANG_CA = 18,
206     DSCRIPT_CA = 19,
207     DCTRY_CA = 20,
208     DVAR_CA = 21,
209     DNAME_CA = 22,
210     DLANG_EL = 23,
211     DSCRIPT_EL = 24,
212     DCTRY_EL = 25,
213     DVAR_EL = 26,
214     DNAME_EL = 27
215 };
216 
217 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
218 
219 void addLocaleTest(TestNode** root);
220 
addLocaleTest(TestNode ** root)221 void addLocaleTest(TestNode** root)
222 {
223     TESTCASE(TestObsoleteNames); /* srl- move */
224     TESTCASE(TestBasicGetters);
225     TESTCASE(TestNullDefault);
226     TESTCASE(TestPrefixes);
227     TESTCASE(TestSimpleResourceInfo);
228     TESTCASE(TestDisplayNames);
229     TESTCASE(TestGetDisplayScriptPreFlighting21160);
230     TESTCASE(TestGetAvailableLocales);
231     TESTCASE(TestGetAvailableLocalesByType);
232     TESTCASE(TestDataDirectory);
233 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
234     TESTCASE(TestISOFunctions);
235 #endif
236     TESTCASE(TestISO3Fallback);
237     TESTCASE(TestUninstalledISO3Names);
238     TESTCASE(TestSimpleDisplayNames);
239     TESTCASE(TestVariantParsing);
240     TESTCASE(TestKeywordVariants);
241     TESTCASE(TestKeywordVariantParsing);
242     TESTCASE(TestCanonicalization);
243     TESTCASE(TestCanonicalizationBuffer);
244     TESTCASE(TestKeywordSet);
245     TESTCASE(TestKeywordSetError);
246     TESTCASE(TestDisplayKeywords);
247     TESTCASE(TestCanonicalization21749StackUseAfterScope);
248     TESTCASE(TestDisplayKeywordValues);
249     TESTCASE(TestGetBaseName);
250 #if !UCONFIG_NO_FILE_IO
251     TESTCASE(TestGetLocale);
252 #endif
253     TESTCASE(TestDisplayNameWarning);
254     TESTCASE(Test21157CorrectTerminating);
255     TESTCASE(TestNonexistentLanguageExemplars);
256     TESTCASE(TestLocDataErrorCodeChaining);
257     TESTCASE(TestLocDataWithRgTag);
258     TESTCASE(TestLanguageExemplarsFallbacks);
259     TESTCASE(TestCalendar);
260     TESTCASE(TestDateFormat);
261     TESTCASE(TestCollation);
262     TESTCASE(TestULocale);
263     TESTCASE(TestUResourceBundle);
264     TESTCASE(TestDisplayName);
265     TESTCASE(TestAcceptLanguage);
266     TESTCASE(TestGetLocaleForLCID);
267     TESTCASE(TestOrientation);
268     TESTCASE(TestLikelySubtags);
269     TESTCASE(TestToLanguageTag);
270     TESTCASE(TestBug20132);
271     TESTCASE(TestBug20149);
272     TESTCASE(TestCDefaultLocale);
273     TESTCASE(TestForLanguageTag);
274     TESTCASE(TestLangAndRegionCanonicalize);
275     TESTCASE(TestTrailingNull);
276     TESTCASE(TestUnicodeDefines);
277     TESTCASE(TestEnglishExemplarCharacters);
278     TESTCASE(TestDisplayNameBrackets);
279     TESTCASE(TestIllegalArgumentWhenNoDataWithNoSubstitute);
280     TESTCASE(TestIsRightToLeft);
281     TESTCASE(TestToUnicodeLocaleKey);
282     TESTCASE(TestToLegacyKey);
283     TESTCASE(TestToUnicodeLocaleType);
284     TESTCASE(TestToLegacyType);
285     TESTCASE(TestBadLocaleIDs);
286     TESTCASE(TestBug20370);
287     TESTCASE(TestBug20321UnicodeLocaleKey);
288     TESTCASE(TestUsingDefaultWarning);
289     TESTCASE(TestBug21449InfiniteLoop);
290     TESTCASE(TestExcessivelyLongIDs);
291 #if !UCONFIG_NO_FORMATTING
292     TESTCASE(TestUldnNameVariants);
293 #endif
294 }
295 
296 
297 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
TestBasicGetters()298 static void TestBasicGetters() {
299     int32_t i;
300     int32_t cap;
301     UErrorCode status = U_ZERO_ERROR;
302     char *testLocale = 0;
303     char *temp = 0, *name = 0;
304     log_verbose("Testing Basic Getters\n");
305     for (i = 0; i < LOCALE_SIZE; i++) {
306         testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
307         strcpy(testLocale,rawData2[NAME][i]);
308 
309         log_verbose("Testing   %s  .....\n", testLocale);
310         cap=uloc_getLanguage(testLocale, NULL, 0, &status);
311         if(status==U_BUFFER_OVERFLOW_ERROR){
312             status=U_ZERO_ERROR;
313             temp=(char*)malloc(sizeof(char) * (cap+1));
314             uloc_getLanguage(testLocale, temp, cap+1, &status);
315         }
316         if(U_FAILURE(status)){
317             log_err("ERROR: in uloc_getLanguage  %s\n", myErrorName(status));
318         }
319         if (0 !=strcmp(temp,rawData2[LANG][i]))    {
320             log_err("  Language code mismatch: %s versus  %s\n", temp, rawData2[LANG][i]);
321         }
322 
323 
324         cap=uloc_getCountry(testLocale, temp, cap, &status);
325         if(status==U_BUFFER_OVERFLOW_ERROR){
326             status=U_ZERO_ERROR;
327             temp=(char*)realloc(temp, sizeof(char) * (cap+1));
328             uloc_getCountry(testLocale, temp, cap+1, &status);
329         }
330         if(U_FAILURE(status)){
331             log_err("ERROR: in uloc_getCountry  %s\n", myErrorName(status));
332         }
333         if (0 != strcmp(temp, rawData2[CTRY][i])) {
334             log_err(" Country code mismatch:  %s  versus   %s\n", temp, rawData2[CTRY][i]);
335 
336           }
337 
338         cap=uloc_getVariant(testLocale, temp, cap, &status);
339         if(status==U_BUFFER_OVERFLOW_ERROR){
340             status=U_ZERO_ERROR;
341             temp=(char*)realloc(temp, sizeof(char) * (cap+1));
342             uloc_getVariant(testLocale, temp, cap+1, &status);
343         }
344         if(U_FAILURE(status)){
345             log_err("ERROR: in uloc_getVariant  %s\n", myErrorName(status));
346         }
347         if (0 != strcmp(temp, rawData2[VAR][i])) {
348             log_err("Variant code mismatch:  %s  versus   %s\n", temp, rawData2[VAR][i]);
349         }
350 
351         cap=uloc_getName(testLocale, NULL, 0, &status);
352         if(status==U_BUFFER_OVERFLOW_ERROR){
353             status=U_ZERO_ERROR;
354             name=(char*)malloc(sizeof(char) * (cap+1));
355             uloc_getName(testLocale, name, cap+1, &status);
356         } else if(status==U_ZERO_ERROR) {
357           log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale);
358         }
359         if(U_FAILURE(status)){
360             log_err("ERROR: in uloc_getName   %s\n", myErrorName(status));
361         }
362         if (0 != strcmp(name, rawData2[NAME][i])){
363             log_err(" Mismatch in getName:  %s  versus   %s\n", name, rawData2[NAME][i]);
364         }
365 
366         free(temp);
367         free(name);
368 
369         free(testLocale);
370     }
371 }
372 
TestNullDefault()373 static void TestNullDefault() {
374     UErrorCode status = U_ZERO_ERROR;
375     char original[ULOC_FULLNAME_CAPACITY];
376 
377     uprv_strcpy(original, uloc_getDefault());
378     uloc_setDefault("qq_BLA", &status);
379     if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
380         log_err(" Mismatch in uloc_setDefault:  qq_BLA  versus   %s\n", uloc_getDefault());
381     }
382     uloc_setDefault(NULL, &status);
383     if (uprv_strcmp(uloc_getDefault(), original) != 0) {
384         log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
385     }
386 
387     {
388     /* Test that set & get of default locale work, and that
389      * default locales are cached and reused, and not overwritten.
390      */
391         const char *n_en_US;
392         const char *n_fr_FR;
393         const char *n2_en_US;
394 
395         status = U_ZERO_ERROR;
396         uloc_setDefault("en_US", &status);
397         n_en_US = uloc_getDefault();
398         if (strcmp(n_en_US, "en_US") != 0) {
399             log_err("Wrong result from uloc_getDefault().  Expected \"en_US\", got \"%s\"\n", n_en_US);
400         }
401 
402         uloc_setDefault("fr_FR", &status);
403         n_fr_FR = uloc_getDefault();
404         if (strcmp(n_en_US, "en_US") != 0) {
405             log_err("uloc_setDefault altered previously default string."
406                 "Expected \"en_US\", got \"%s\"\n",  n_en_US);
407         }
408         if (strcmp(n_fr_FR, "fr_FR") != 0) {
409             log_err("Wrong result from uloc_getDefault().  Expected \"fr_FR\", got %s\n",  n_fr_FR);
410         }
411 
412         uloc_setDefault("en_US", &status);
413         n2_en_US = uloc_getDefault();
414         if (strcmp(n2_en_US, "en_US") != 0) {
415             log_err("Wrong result from uloc_getDefault().  Expected \"en_US\", got \"%s\"\n", n_en_US);
416         }
417         if (n2_en_US != n_en_US) {
418             log_err("Default locale cache failed to reuse en_US locale.\n");
419         }
420 
421         if (U_FAILURE(status)) {
422             log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status));
423         }
424 
425     }
426     uloc_setDefault(original, &status);
427     if (U_FAILURE(status)) {
428         log_err("Failed to change the default locale back to %s\n", original);
429     }
430 
431 }
432 /* Test the i- and x- and @ and . functionality
433 */
434 
435 #define PREFIXBUFSIZ 128
436 
TestPrefixes()437 static void TestPrefixes() {
438     int row = 0;
439     int n;
440     const char *loc, *expected;
441 
442     static const char * const testData[][7] =
443     {
444         /* NULL canonicalize() column means "expect same as getName()" */
445         {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL},
446         {"en", "", "GB", "", "en-gb", "en_GB", NULL},
447         {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL},
448         {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL},
449         {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL},
450         {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL},
451         {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", "hyw"},
452         {"de", "", "", "1901", "de-1901", "de__1901", NULL},
453         {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
454         {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
455         {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"},  /* Multibyte English */
456         {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
457         {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
458         {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
459         {"no", "", "NO", "",  "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
460         {"no", "", "",   "NY", "no__ny", "no__NY", NULL},
461         {"no", "", "",   "", "no@ny", "no@ny", "no__NY"},
462         {"el", "Latn", "", "", "el-latn", "el_Latn", NULL},
463         {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL},
464         {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL},
465         {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL},
466         {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL}, /* total garbage */
467 
468         // Before ICU 64, ICU locale canonicalization had some additional mappings.
469         // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
470         // The following now use standard canonicalization.
471         {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans__PINYIN"},
472         {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW_STROKE"},
473 
474         {NULL,NULL,NULL,NULL,NULL,NULL,NULL}
475     };
476 
477     static const char * const testTitles[] = {
478         "uloc_getLanguage()",
479         "uloc_getScript()",
480         "uloc_getCountry()",
481         "uloc_getVariant()",
482         "name",
483         "uloc_getName()",
484         "uloc_canonicalize()"
485     };
486 
487     char buf[PREFIXBUFSIZ];
488     int32_t len;
489     UErrorCode err;
490 
491 
492     for(row=0;testData[row][0] != NULL;row++) {
493         loc = testData[row][NAME];
494         log_verbose("Test #%d: %s\n", row, loc);
495 
496         err = U_ZERO_ERROR;
497         len=0;
498         buf[0]=0;
499         for(n=0;n<=(NAME+2);n++) {
500             if(n==NAME) continue;
501 
502             for(len=0;len<PREFIXBUFSIZ;len++) {
503                 buf[len] = '%'; /* Set a tripwire.. */
504             }
505             len = 0;
506 
507             switch(n) {
508             case LANG:
509                 len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err);
510                 break;
511 
512             case SCRIPT:
513                 len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err);
514                 break;
515 
516             case CTRY:
517                 len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err);
518                 break;
519 
520             case VAR:
521                 len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err);
522                 break;
523 
524             case NAME+1:
525                 len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err);
526                 break;
527 
528             case NAME+2:
529                 len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err);
530                 break;
531 
532             default:
533                 strcpy(buf, "**??");
534                 len=4;
535             }
536 
537             if(U_FAILURE(err)) {
538                 log_err("#%d: %s on %s: err %s\n",
539                     row, testTitles[n], loc, u_errorName(err));
540             } else {
541                 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
542                     row, testTitles[n], loc, buf, len);
543 
544                 if(len != (int32_t)strlen(buf)) {
545                     log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
546                         row, testTitles[n], loc, buf, len, strlen(buf)+1);
547 
548                 }
549 
550                 /* see if they smashed something */
551                 if(buf[len+1] != '%') {
552                     log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
553                         row, testTitles[n], loc, buf, buf[len+1]);
554                 }
555 
556                 expected = testData[row][n];
557                 if (expected == NULL && n == (NAME+2)) {
558                     /* NULL expected canonicalize() means "expect same as getName()" */
559                     expected = testData[row][NAME+1];
560                 }
561                 if(strcmp(buf, expected)) {
562                     log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
563                         row, testTitles[n], loc, buf, expected);
564 
565                 }
566             }
567         }
568     }
569 }
570 
571 
572 /* testing uloc_getISO3Language(), uloc_getISO3Country(),  */
TestSimpleResourceInfo()573 static void TestSimpleResourceInfo() {
574     int32_t i;
575     char* testLocale = 0;
576     UChar* expected = 0;
577 
578     const char* temp;
579     char            temp2[20];
580     testLocale=(char*)malloc(sizeof(char) * 1);
581     expected=(UChar*)malloc(sizeof(UChar) * 1);
582 
583     setUpDataTable();
584     log_verbose("Testing getISO3Language and getISO3Country\n");
585     for (i = 0; i < LOCALE_SIZE; i++) {
586 
587         testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
588         u_austrcpy(testLocale, dataTable[NAME][i]);
589 
590         log_verbose("Testing   %s ......\n", testLocale);
591 
592         temp=uloc_getISO3Language(testLocale);
593         expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
594         u_uastrcpy(expected,temp);
595         if (0 != u_strcmp(expected, dataTable[LANG3][i])) {
596             log_err("  ISO-3 language code mismatch:  %s versus  %s\n",  austrdup(expected),
597                 austrdup(dataTable[LANG3][i]));
598         }
599 
600         temp=uloc_getISO3Country(testLocale);
601         expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
602         u_uastrcpy(expected,temp);
603         if (0 != u_strcmp(expected, dataTable[CTRY3][i])) {
604             log_err("  ISO-3 Country code mismatch:  %s versus  %s\n",  austrdup(expected),
605                 austrdup(dataTable[CTRY3][i]));
606         }
607         snprintf(temp2, sizeof(temp2), "%x", (int)uloc_getLCID(testLocale));
608         if (strcmp(temp2, rawData2[LCID][i]) != 0) {
609             log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]);
610         }
611     }
612 
613     free(expected);
614     free(testLocale);
615     cleanUpDataTable();
616 }
617 
618 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
619  * if there's room but won't be included in result.  result < 0 indicates an error.
620  * Returns the number of chars written (not those that would be written if there's enough room.*/
UCharsToEscapedAscii(const UChar * utext,int32_t len,char * resultChars,int32_t buflen)621 static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) {
622     static const struct {
623         char escapedChar;
624         UChar sourceVal;
625     } ESCAPE_MAP[] = {
626         /*a*/ {'a', 0x07},
627         /*b*/ {'b', 0x08},
628         /*e*/ {'e', 0x1b},
629         /*f*/ {'f', 0x0c},
630         /*n*/ {'n', 0x0a},
631         /*r*/ {'r', 0x0d},
632         /*t*/ {'t', 0x09},
633         /*v*/ {'v', 0x0b}
634     };
635     static const int32_t ESCAPE_MAP_LENGTH = UPRV_LENGTHOF(ESCAPE_MAP);
636     static const char HEX_DIGITS[] = {
637         '0', '1', '2', '3', '4', '5', '6', '7',
638         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
639     };
640     int32_t i, j;
641     int32_t resultLen = 0;
642     const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */
643     const int32_t escapeLimit1 = buflen-2;
644     const int32_t escapeLimit2 = buflen-6;
645     UChar uc;
646 
647     if(utext==NULL || resultChars==NULL || buflen<0) {
648         return -1;
649     }
650 
651     for(i=0;i<limit && resultLen<buflen;++i) {
652         uc=utext[i];
653         if(len<0 && uc==0) {
654             break;
655         }
656         if(uc<0x20) {
657             for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) {
658             }
659             if(j<ESCAPE_MAP_LENGTH) {
660                 if(resultLen>escapeLimit1) {
661                     break;
662                 }
663                 resultChars[resultLen++]='\\';
664                 resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar;
665                 continue;
666             }
667         } else if(uc<0x7f) {
668             u_austrncpy(resultChars + resultLen, &uc, 1);
669             resultLen++;
670             continue;
671         }
672 
673         if(resultLen>escapeLimit2) {
674             break;
675         }
676 
677         /* have to escape the uchar */
678         resultChars[resultLen++]='\\';
679         resultChars[resultLen++]='u';
680         resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff];
681         resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff];
682         resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff];
683         resultChars[resultLen++]=HEX_DIGITS[uc&0xff];
684     }
685 
686     if(resultLen<buflen) {
687         resultChars[resultLen] = 0;
688     }
689 
690     return resultLen;
691 }
692 
693 /*
694  * Jitterbug 2439 -- markus 20030425
695  *
696  * The lookup of display names must not fall back through the default
697  * locale because that yields useless results.
698  */
TestDisplayNames()699 static void TestDisplayNames()
700 {
701     UChar buffer[100];
702     UErrorCode errorCode=U_ZERO_ERROR;
703     int32_t length;
704     log_verbose("Testing getDisplayName for different locales\n");
705 
706     log_verbose("  In locale = en_US...\n");
707     doTestDisplayNames("en_US", DLANG_EN);
708     log_verbose("  In locale = fr_FR....\n");
709     doTestDisplayNames("fr_FR", DLANG_FR);
710     log_verbose("  In locale = ca_ES...\n");
711     doTestDisplayNames("ca_ES", DLANG_CA);
712     log_verbose("  In locale = gr_EL..\n");
713     doTestDisplayNames("el_GR", DLANG_EL);
714 
715     /* test that the default locale has a display name for its own language */
716     errorCode=U_ZERO_ERROR;
717     length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode);
718     /* check <=3 to reject getting the language code as a display name */
719     if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) {
720         const char* defaultLocale = uloc_getDefault();
721         for (int32_t i = 0, count = uloc_countAvailable(); i < count; i++) {
722             /* Only report error if the default locale is in the available list */
723             if (uprv_strcmp(defaultLocale, uloc_getAvailable(i)) == 0) {
724                 log_data_err(
725                     "unable to get a display string for the language of the "
726                     "default locale - %s (Are you missing data?)\n",
727                     u_errorName(errorCode));
728                 break;
729             }
730         }
731     }
732 
733     /* test that we get the language code itself for an unknown language, and a default warning */
734     errorCode=U_ZERO_ERROR;
735     length=uloc_getDisplayLanguage("qq", "rr", buffer, UPRV_LENGTHOF(buffer), &errorCode);
736     if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
737         log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
738     }
739 
740     /* test that we get a default warning for a display name where one component is unknown (4255) */
741     errorCode=U_ZERO_ERROR;
742     length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, UPRV_LENGTHOF(buffer), &errorCode);
743     if(errorCode!=U_USING_DEFAULT_WARNING) {
744         log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode));
745     }
746 
747     {
748         int32_t i;
749         static const char *aLocale = "es@collation=traditional;calendar=japanese";
750         static const char *testL[] = { "en_US",
751             "fr_FR",
752             "ca_ES",
753             "el_GR" };
754         static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
755             "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)",
756             "espanyol (calendari=calendari japon\\u00e8s, ordre=ordre tradicional)",
757             "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)" };
758         UChar *expectBuffer;
759 
760         for(i=0;i<UPRV_LENGTHOF(testL);i++) {
761             errorCode = U_ZERO_ERROR;
762             uloc_getDisplayName(aLocale, testL[i], buffer, UPRV_LENGTHOF(buffer), &errorCode);
763             if(U_FAILURE(errorCode)) {
764                 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode));
765             } else {
766                 expectBuffer = CharsToUChars(expect[i]);
767                 if(u_strcmp(buffer,expectBuffer)) {
768                     log_data_err("FAIL in uloc_getDisplayName(%s,%s,..) expected '%s' got '%s' (Are you missing data?)\n", aLocale, testL[i], expect[i], austrdup(buffer));
769                 } else {
770                     log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]);
771                 }
772                 free(expectBuffer);
773             }
774         }
775     }
776 
777     /* test that we properly preflight and return data when there's a non-default pattern,
778        see ticket #8262. */
779     {
780         int32_t i;
781         static const char *locale="az_Cyrl";
782         static const char *displayLocale="ja";
783         static const char *expectedChars =
784                 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e "
785                 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
786         UErrorCode ec=U_ZERO_ERROR;
787         UChar result[256];
788         int32_t len;
789         int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec);
790         /* inconvenient semantics when preflighting, this condition is expected... */
791         if(ec==U_BUFFER_OVERFLOW_ERROR) {
792             ec=U_ZERO_ERROR;
793         }
794         len=uloc_getDisplayName(locale, displayLocale, result, UPRV_LENGTHOF(result), &ec);
795         if(U_FAILURE(ec)) {
796             log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
797                     locale, displayLocale, u_errorName(ec));
798         } else {
799             UChar *expected=CharsToUChars(expectedChars);
800             int32_t expectedLen=u_strlen(expected);
801 
802             if(len!=expectedLen) {
803                 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
804                         locale, displayLocale, len, expectedLen);
805             } else if(preflightLen!=expectedLen) {
806                 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
807                         locale, displayLocale, preflightLen, expectedLen);
808             } else if(u_strncmp(result, expected, len)) {
809                 int32_t cap=len*6+1;  /* worst case + space for trailing null */
810                 char* resultChars=(char*)malloc(cap);
811                 int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap);
812                 if(resultCharsLen<0 || resultCharsLen<cap-1) {
813                     log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale);
814                 } else {
815                     log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
816                             locale, displayLocale, resultChars, expectedChars);
817                 }
818                 free(resultChars);
819                 resultChars=NULL;
820             } else {
821                 /* test all buffer sizes */
822                 for(i=len+1;i>=0;--i) {
823                     len=uloc_getDisplayName(locale, displayLocale, result, i, &ec);
824                     if(ec==U_BUFFER_OVERFLOW_ERROR) {
825                         ec=U_ZERO_ERROR;
826                     }
827                     if(U_FAILURE(ec)) {
828                         log_err("using buffer of length %d returned error %s", i, u_errorName(ec));
829                         break;
830                     }
831                     if(len!=expectedLen) {
832                         log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len);
833                         break;
834                     }
835                     /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
836                      * we don't know that it's been filled, so no point in checking. */
837                 }
838             }
839 
840             free(expected);
841         }
842     }
843 }
844 
845 /**
846  * ICU-21160 test the pre-flighting call to uloc_getDisplayScript returns the actual length needed
847  * for the result buffer.
848  */
TestGetDisplayScriptPreFlighting21160()849 static void TestGetDisplayScriptPreFlighting21160()
850 {
851     const char* locale = "und-Latn";
852     const char* inlocale = "de";
853 
854     UErrorCode ec = U_ZERO_ERROR;
855     UChar* result = NULL;
856     int32_t length = uloc_getDisplayScript(locale, inlocale, NULL, 0, &ec) + 1;
857     ec = U_ZERO_ERROR;
858     result=(UChar*)malloc(sizeof(UChar) * length);
859     length = uloc_getDisplayScript(locale, inlocale, result, length, &ec);
860     if (U_FAILURE(ec)) {
861         log_err("uloc_getDisplayScript length %d returned error %s", length, u_errorName(ec));
862     }
863     free(result);
864 }
865 
866 /* test for uloc_getAvailable()  and uloc_countAvailable()*/
TestGetAvailableLocales()867 static void TestGetAvailableLocales()
868 {
869 
870     const char *locList;
871     int32_t locCount,i;
872 
873     log_verbose("Testing the no of available locales\n");
874     locCount=uloc_countAvailable();
875     if (locCount == 0)
876         log_data_err("countAvailable() returned an empty list!\n");
877 
878     /* use something sensible w/o hardcoding the count */
879     else if(locCount < 0){
880         log_data_err("countAvailable() returned a wrong value!= %d\n", locCount);
881     }
882     else{
883         log_info("Number of locales returned = %d\n", locCount);
884     }
885     for(i=0;i<locCount;i++){
886         locList=uloc_getAvailable(i);
887 
888         log_verbose(" %s\n", locList);
889     }
890 }
891 
TestGetAvailableLocalesByType()892 static void TestGetAvailableLocalesByType() {
893     UErrorCode status = U_ZERO_ERROR;
894 
895     UEnumeration* uenum = uloc_openAvailableByType(ULOC_AVAILABLE_DEFAULT, &status);
896     assertSuccess("Constructing the UEnumeration", &status);
897 
898     assertIntEquals("countAvailable() should be same in old and new methods",
899         uloc_countAvailable(),
900         uenum_count(uenum, &status));
901 
902     for (int32_t i = 0; i < uloc_countAvailable(); i++) {
903         const char* old = uloc_getAvailable(i);
904         int32_t len = 0;
905         const char* new = uenum_next(uenum, &len, &status);
906         assertEquals("Old and new strings should equal", old, new);
907         assertIntEquals("String length should be correct", uprv_strlen(old), len);
908     }
909     assertPtrEquals("Should get nullptr on the last string",
910         NULL, uenum_next(uenum, NULL, &status));
911 
912     uenum_close(uenum);
913 
914     uenum = uloc_openAvailableByType(ULOC_AVAILABLE_ONLY_LEGACY_ALIASES, &status);
915     UBool found_he = false;
916     UBool found_iw = false;
917     const char* loc;
918     while ((loc = uenum_next(uenum, NULL, &status))) {
919         if (uprv_strcmp("he", loc) == 0) {
920             found_he = true;
921         }
922         if (uprv_strcmp("iw", loc) == 0) {
923             found_iw = true;
924         }
925     }
926     assertTrue("Should NOT have found he amongst the legacy/alias locales", !found_he);
927     assertTrue("Should have found iw amongst the legacy/alias locales", found_iw);
928     uenum_close(uenum);
929 
930     uenum = uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES, &status);
931     found_he = false;
932     found_iw = false;
933     const UChar* uloc; // test the UChar conversion
934     int32_t count = 0;
935     while ((uloc = uenum_unext(uenum, NULL, &status))) {
936         if (u_strcmp(u"iw", uloc) == 0) {
937             found_iw = true;
938         }
939         if (u_strcmp(u"he", uloc) == 0) {
940             found_he = true;
941         }
942         count++;
943     }
944     assertTrue("Should have found he amongst all locales", found_he);
945     assertTrue("Should have found iw amongst all locales", found_iw);
946     assertIntEquals("Should return as many strings as claimed",
947         count, uenum_count(uenum, &status));
948 
949     // Reset the enumeration and it should still work
950     uenum_reset(uenum, &status);
951     count = 0;
952     while ((loc = uenum_next(uenum, NULL, &status))) {
953         count++;
954     }
955     assertIntEquals("After reset, should return as many strings as claimed",
956         count, uenum_count(uenum, &status));
957 
958     uenum_close(uenum);
959 
960     assertSuccess("No errors should have occurred", &status);
961 }
962 
963 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
TestDataDirectory()964 static void TestDataDirectory()
965 {
966 
967     char            oldDirectory[512];
968     const char     *temp,*testValue1,*testValue2,*testValue3;
969     const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */
970 
971     log_verbose("Testing getDataDirectory()\n");
972     temp = u_getDataDirectory();
973     strcpy(oldDirectory, temp);
974 
975     testValue1=uloc_getISO3Language("en_US");
976     log_verbose("first fetch of language retrieved  %s\n", testValue1);
977 
978     if (0 != strcmp(testValue1,"eng")){
979         log_err("Initial check of ISO3 language failed: expected \"eng\", got  %s \n", testValue1);
980     }
981 
982     /*defining the path for DataDirectory */
983     log_verbose("Testing setDataDirectory\n");
984     u_setDataDirectory( path );
985     if(strcmp(path, u_getDataDirectory())==0)
986         log_verbose("setDataDirectory working fine\n");
987     else
988         log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path);
989 
990     testValue2=uloc_getISO3Language("en_US");
991     log_verbose("second fetch of language retrieved  %s \n", testValue2);
992 
993     u_setDataDirectory(oldDirectory);
994     testValue3=uloc_getISO3Language("en_US");
995     log_verbose("third fetch of language retrieved  %s \n", testValue3);
996 
997     if (0 != strcmp(testValue3,"eng")) {
998        log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s  \" \n", testValue3);
999     }
1000 }
1001 
1002 
1003 
1004 /*=========================================================== */
1005 
1006 static UChar _NUL=0;
1007 
doTestDisplayNames(const char * displayLocale,int32_t compareIndex)1008 static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
1009 {
1010     UErrorCode status = U_ZERO_ERROR;
1011     int32_t i;
1012     int32_t maxresultsize;
1013 
1014     const char *testLocale;
1015 
1016 
1017     UChar  *testLang  = 0;
1018     UChar  *testScript  = 0;
1019     UChar  *testCtry = 0;
1020     UChar  *testVar = 0;
1021     UChar  *testName = 0;
1022 
1023 
1024     UChar*  expectedLang = 0;
1025     UChar*  expectedScript = 0;
1026     UChar*  expectedCtry = 0;
1027     UChar*  expectedVar = 0;
1028     UChar*  expectedName = 0;
1029 
1030 setUpDataTable();
1031 
1032     for(i=0;i<LOCALE_SIZE; ++i)
1033     {
1034         testLocale=rawData2[NAME][i];
1035 
1036         log_verbose("Testing.....  %s\n", testLocale);
1037 
1038         maxresultsize=0;
1039         maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
1040         if(status==U_BUFFER_OVERFLOW_ERROR)
1041         {
1042             status=U_ZERO_ERROR;
1043             testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
1044             uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
1045         }
1046         else
1047         {
1048             testLang=&_NUL;
1049         }
1050         if(U_FAILURE(status)){
1051             log_err("Error in getDisplayLanguage()  %s\n", myErrorName(status));
1052         }
1053 
1054         maxresultsize=0;
1055         maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status);
1056         if(status==U_BUFFER_OVERFLOW_ERROR)
1057         {
1058             status=U_ZERO_ERROR;
1059             testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
1060             uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status);
1061         }
1062         else
1063         {
1064             testScript=&_NUL;
1065         }
1066         if(U_FAILURE(status)){
1067             log_err("Error in getDisplayScript()  %s\n", myErrorName(status));
1068         }
1069 
1070         maxresultsize=0;
1071         maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
1072         if(status==U_BUFFER_OVERFLOW_ERROR)
1073         {
1074             status=U_ZERO_ERROR;
1075             testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
1076             uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
1077         }
1078         else
1079         {
1080             testCtry=&_NUL;
1081         }
1082         if(U_FAILURE(status)){
1083             log_err("Error in getDisplayCountry()  %s\n", myErrorName(status));
1084         }
1085 
1086         maxresultsize=0;
1087         maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
1088         if(status==U_BUFFER_OVERFLOW_ERROR)
1089         {
1090             status=U_ZERO_ERROR;
1091             testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
1092             uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
1093         }
1094         else
1095         {
1096             testVar=&_NUL;
1097         }
1098         if(U_FAILURE(status)){
1099                 log_err("Error in getDisplayVariant()  %s\n", myErrorName(status));
1100         }
1101 
1102         maxresultsize=0;
1103         maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
1104         if(status==U_BUFFER_OVERFLOW_ERROR)
1105         {
1106             status=U_ZERO_ERROR;
1107             testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
1108             uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
1109         }
1110         else
1111         {
1112             testName=&_NUL;
1113         }
1114         if(U_FAILURE(status)){
1115             log_err("Error in getDisplayName()  %s\n", myErrorName(status));
1116         }
1117 
1118         expectedLang=dataTable[compareIndex][i];
1119         if(u_strlen(expectedLang)== 0)
1120             expectedLang=dataTable[DLANG_EN][i];
1121 
1122         expectedScript=dataTable[compareIndex + 1][i];
1123         if(u_strlen(expectedScript)== 0)
1124             expectedScript=dataTable[DSCRIPT_EN][i];
1125 
1126         expectedCtry=dataTable[compareIndex + 2][i];
1127         if(u_strlen(expectedCtry)== 0)
1128             expectedCtry=dataTable[DCTRY_EN][i];
1129 
1130         expectedVar=dataTable[compareIndex + 3][i];
1131         if(u_strlen(expectedVar)== 0)
1132             expectedVar=dataTable[DVAR_EN][i];
1133 
1134         expectedName=dataTable[compareIndex + 4][i];
1135         if(u_strlen(expectedName) == 0)
1136             expectedName=dataTable[DNAME_EN][i];
1137 
1138         if (0 !=u_strcmp(testLang,expectedLang))  {
1139             log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
1140         }
1141 
1142         if (0 != u_strcmp(testScript,expectedScript))   {
1143             log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale);
1144         }
1145 
1146         if (0 != u_strcmp(testCtry,expectedCtry))   {
1147             log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
1148         }
1149 
1150         if (0 != u_strcmp(testVar,expectedVar))    {
1151             log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
1152         }
1153 
1154         if(0 != u_strcmp(testName, expectedName))    {
1155             log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale);
1156         }
1157 
1158         if(testName!=&_NUL) {
1159             free(testName);
1160         }
1161         if(testLang!=&_NUL) {
1162             free(testLang);
1163         }
1164         if(testScript!=&_NUL) {
1165             free(testScript);
1166         }
1167         if(testCtry!=&_NUL) {
1168             free(testCtry);
1169         }
1170         if(testVar!=&_NUL) {
1171             free(testVar);
1172         }
1173     }
1174 cleanUpDataTable();
1175 }
1176 
1177 /*------------------------------
1178  * TestDisplayNameBrackets
1179  */
1180 
1181 typedef struct {
1182     const char * displayLocale;
1183     const char * namedRegion;
1184     const char * namedLocale;
1185     const char * regionName;
1186     const char * localeName;
1187 } DisplayNameBracketsItem;
1188 
1189 static const DisplayNameBracketsItem displayNameBracketsItems[] = {
1190     { "en", "CC", "en_CC",      "Cocos (Keeling) Islands",  "English (Cocos [Keeling] Islands)"  },
1191     { "en", "MM", "my_MM",      "Myanmar (Burma)",          "Burmese (Myanmar [Burma])"          },
1192     { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)",          "Burmese (Myanmar, Myanmar [Burma])" },
1193     { "zh", "CC", "en_CC",      "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1194     { "zh", "CG", "fr_CG",      "\\u521A\\u679C\\uFF08\\u5E03\\uFF09",                             "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1195     { NULL, NULL, NULL,         NULL,                       NULL                                 }
1196 };
1197 
1198 enum { kDisplayNameBracketsMax = 128 };
1199 
TestDisplayNameBrackets()1200 static void TestDisplayNameBrackets()
1201 {
1202     const DisplayNameBracketsItem * itemPtr = displayNameBracketsItems;
1203     for (; itemPtr->displayLocale != NULL; itemPtr++) {
1204         ULocaleDisplayNames * uldn;
1205         UErrorCode status;
1206         UChar expectRegionName[kDisplayNameBracketsMax];
1207         UChar expectLocaleName[kDisplayNameBracketsMax];
1208         UChar getName[kDisplayNameBracketsMax];
1209         int32_t ulen;
1210 
1211         (void) u_unescape(itemPtr->regionName, expectRegionName, kDisplayNameBracketsMax);
1212         (void) u_unescape(itemPtr->localeName, expectLocaleName, kDisplayNameBracketsMax);
1213 
1214         status = U_ZERO_ERROR;
1215         ulen = uloc_getDisplayCountry(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1216         if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1217             log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1218         }
1219 
1220         status = U_ZERO_ERROR;
1221         ulen = uloc_getDisplayName(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1222         if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1223             log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1224         }
1225 
1226 #if !UCONFIG_NO_FORMATTING
1227         status = U_ZERO_ERROR;
1228         uldn = uldn_open(itemPtr->displayLocale, ULDN_STANDARD_NAMES, &status);
1229         if (U_SUCCESS(status)) {
1230             status = U_ZERO_ERROR;
1231             ulen = uldn_regionDisplayName(uldn, itemPtr->namedRegion, getName, kDisplayNameBracketsMax, &status);
1232             if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1233                 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedRegion, myErrorName(status));
1234             }
1235 
1236             status = U_ZERO_ERROR;
1237             ulen = uldn_localeDisplayName(uldn, itemPtr->namedLocale, getName, kDisplayNameBracketsMax, &status);
1238             if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1239                 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1240             }
1241 
1242             uldn_close(uldn);
1243         } else {
1244             log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr->displayLocale, u_errorName(status));
1245         }
1246 #endif
1247     (void)ulen;   /* Suppress variable not used warning */
1248     }
1249 }
1250 
1251 /*------------------------------
1252  * TestIllegalArgumentWhenNoDataWithNoSubstitute
1253  */
1254 
TestIllegalArgumentWhenNoDataWithNoSubstitute()1255 static void TestIllegalArgumentWhenNoDataWithNoSubstitute()
1256 {
1257 #if !UCONFIG_NO_FORMATTING
1258     UErrorCode status = U_ZERO_ERROR;
1259     UChar getName[kDisplayNameBracketsMax];
1260     UDisplayContext contexts[] = {
1261         UDISPCTX_NO_SUBSTITUTE,
1262     };
1263     ULocaleDisplayNames* ldn = uldn_openForContext("en", contexts, 1, &status);
1264 
1265     uldn_localeDisplayName(ldn, "efg", getName, kDisplayNameBracketsMax, &status);
1266     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1267         log_err("FAIL uldn_localeDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1268                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1269     }
1270 
1271     status = U_ZERO_ERROR;
1272     uldn_languageDisplayName(ldn, "zz", getName, kDisplayNameBracketsMax, &status);
1273     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1274         log_err("FAIL uldn_languageDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1275                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1276     }
1277 
1278     status = U_ZERO_ERROR;
1279     uldn_scriptDisplayName(ldn, "Aaaa", getName, kDisplayNameBracketsMax, &status);
1280     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1281         log_err("FAIL uldn_scriptDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1282                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1283     }
1284 
1285     status = U_ZERO_ERROR;
1286     uldn_regionDisplayName(ldn, "KK", getName, kDisplayNameBracketsMax, &status);
1287     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1288         log_err("FAIL uldn_regionDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1289                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1290     }
1291 
1292     status = U_ZERO_ERROR;
1293     uldn_variantDisplayName(ldn, "ZZ", getName, kDisplayNameBracketsMax, &status);
1294     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1295         log_err("FAIL uldn_variantDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1296                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1297     }
1298 
1299     status = U_ZERO_ERROR;
1300     uldn_keyDisplayName(ldn, "zz", getName, kDisplayNameBracketsMax, &status);
1301     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1302         log_err("FAIL uldn_keyDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1303                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1304     }
1305 
1306     status = U_ZERO_ERROR;
1307     uldn_keyValueDisplayName(ldn, "ca", "zz", getName, kDisplayNameBracketsMax, &status);
1308     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1309         log_err("FAIL uldn_keyValueDisplayName should return U_ILLEGAL_ARGUMENT_ERROR "
1310                 "while no resource under UDISPCTX_NO_SUBSTITUTE");
1311     }
1312 
1313     uldn_close(ldn);
1314 #endif
1315 }
1316 
1317 /*------------------------------
1318  * TestISOFunctions
1319  */
1320 
1321 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1322 /* test for uloc_getISOLanguages, uloc_getISOCountries */
TestISOFunctions()1323 static void TestISOFunctions()
1324 {
1325     const char* const* str=uloc_getISOLanguages();
1326     const char* const* str1=uloc_getISOCountries();
1327     const char* test;
1328     const char *key = NULL;
1329     int32_t count = 0, skipped = 0;
1330     int32_t expect;
1331     UResourceBundle *res;
1332     UResourceBundle *subRes;
1333     UErrorCode status = U_ZERO_ERROR;
1334 
1335     /*  test getISOLanguages*/
1336     /*str=uloc_getISOLanguages(); */
1337     log_verbose("Testing ISO Languages: \n");
1338 
1339     /* use structLocale - this data is no longer in root */
1340     res = ures_openDirect(loadTestData(&status), "structLocale", &status);
1341     subRes = ures_getByKey(res, "Languages", NULL, &status);
1342     if (U_FAILURE(status)) {
1343         log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status));
1344         return;
1345     }
1346 
1347     expect = ures_getSize(subRes);
1348     for(count = 0; *(str+count) != 0; count++)
1349     {
1350         key = NULL;
1351         test = *(str+count);
1352         status = U_ZERO_ERROR;
1353 
1354         do {
1355             /* Skip over language tags. This API only returns language codes. */
1356             skipped += (key != NULL);
1357             ures_getNextString(subRes, NULL, &key, &status);
1358         }
1359         while (key != NULL && strchr(key, '_'));
1360 
1361         if(key == NULL)
1362             break;
1363         /* TODO: Consider removing sh, which is deprecated */
1364         if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) {
1365             ures_getNextString(subRes, NULL, &key, &status);
1366             skipped++;
1367         }
1368 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1369         /* This code only works on ASCII machines where the keys are stored in ASCII order */
1370         if(strcmp(test,key)) {
1371             /* The first difference usually implies the place where things get out of sync */
1372             log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1373         }
1374 #endif
1375 
1376         if(!strcmp(test,"in"))
1377             log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1378         if(!strcmp(test,"iw"))
1379             log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1380         if(!strcmp(test,"ji"))
1381             log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1382         if(!strcmp(test,"jw"))
1383             log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1384         if(!strcmp(test,"sh"))
1385             log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1386     }
1387 
1388     expect -= skipped; /* Ignore the skipped resources from structLocale */
1389 
1390     if(count!=expect) {
1391         log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect);
1392     }
1393 
1394     subRes = ures_getByKey(res, "Countries", subRes, &status);
1395     log_verbose("Testing ISO Countries");
1396     skipped = 0;
1397     expect = ures_getSize(subRes) - 1; /* Skip ZZ */
1398     for(count = 0; *(str1+count) != 0; count++)
1399     {
1400         key = NULL;
1401         test = *(str1+count);
1402         do {
1403             /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1404             skipped += (key != NULL);
1405             ures_getNextString(subRes, NULL, &key, &status);
1406         }
1407         while (key != NULL && strlen(key) != 2);
1408 
1409         if(key == NULL)
1410             break;
1411         /* TODO: Consider removing CS, which is deprecated */
1412         while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) {
1413             ures_getNextString(subRes, NULL, &key, &status);
1414             skipped++;
1415         }
1416 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1417         /* This code only works on ASCII machines where the keys are stored in ASCII order */
1418         if(strcmp(test,key)) {
1419             /* The first difference usually implies the place where things get out of sync */
1420             log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1421         }
1422 #endif
1423         if(!strcmp(test,"FX"))
1424             log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1425         if(!strcmp(test,"YU"))
1426             log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1427         if(!strcmp(test,"ZR"))
1428             log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1429     }
1430 
1431     ures_getNextString(subRes, NULL, &key, &status);
1432     if (strcmp(key, "ZZ") != 0) {
1433         log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key);
1434     }
1435 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1436     /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1437     key = NULL;
1438     do {
1439         /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1440         skipped += (key != NULL);
1441         ures_getNextString(subRes, NULL, &key, &status);
1442     }
1443     while (U_SUCCESS(status) && key != NULL && strlen(key) != 2);
1444 #endif
1445     expect -= skipped; /* Ignore the skipped resources from structLocale */
1446     if(count!=expect)
1447     {
1448         log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect);
1449     }
1450     ures_close(subRes);
1451     ures_close(res);
1452 }
1453 #endif
1454 
setUpDataTable()1455 static void setUpDataTable()
1456 {
1457     int32_t i,j;
1458     dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE));
1459 
1460     for (i = 0; i < LOCALE_INFO_SIZE; i++) {
1461         dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE));
1462         for (j = 0; j < LOCALE_SIZE; j++){
1463             dataTable[i][j] = CharsToUChars(rawData2[i][j]);
1464         }
1465     }
1466 }
1467 
cleanUpDataTable()1468 static void cleanUpDataTable()
1469 {
1470     int32_t i,j;
1471     if(dataTable != NULL) {
1472         for (i=0; i<LOCALE_INFO_SIZE; i++) {
1473             for(j = 0; j < LOCALE_SIZE; j++) {
1474                 free(dataTable[i][j]);
1475             }
1476             free(dataTable[i]);
1477         }
1478         free(dataTable);
1479     }
1480     dataTable = NULL;
1481 }
1482 
1483 /**
1484  * @bug 4011756 4011380
1485  */
TestISO3Fallback()1486 static void TestISO3Fallback()
1487 {
1488     const char* test="xx_YY";
1489 
1490     const char * result;
1491 
1492     result = uloc_getISO3Language(test);
1493 
1494     /* Conform to C API usage  */
1495 
1496     if (!result || (result[0] != 0))
1497        log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1498 
1499     result = uloc_getISO3Country(test);
1500 
1501     if (!result || (result[0] != 0))
1502         log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1503 }
1504 
1505 /**
1506  * @bug 4118587
1507  */
TestSimpleDisplayNames()1508 static void TestSimpleDisplayNames()
1509 {
1510   /*
1511      This test is different from TestDisplayNames because TestDisplayNames checks
1512      fallback behavior, combination of language and country names to form locale
1513      names, and other stuff like that.  This test just checks specific language
1514      and country codes to make sure we have the correct names for them.
1515   */
1516     char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1517     const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1518                                "Zhuang", "419" };
1519     const char* inLocale [] = { "en_US", "zh_Hant"};
1520     UErrorCode status=U_ZERO_ERROR;
1521 
1522     int32_t i;
1523     int32_t localeIndex = 0;
1524     for (i = 0; i < 7; i++) {
1525         UChar *testLang=0;
1526         UChar *expectedLang=0;
1527         int size=0;
1528 
1529         if (i == 6) {
1530             localeIndex = 1; /* Use the second locale for the rest of the test. */
1531         }
1532 
1533         size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status);
1534         if(status==U_BUFFER_OVERFLOW_ERROR) {
1535             status=U_ZERO_ERROR;
1536             testLang=(UChar*)malloc(sizeof(UChar) * (size + 1));
1537             uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status);
1538         }
1539         expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1));
1540         u_uastrcpy(expectedLang, languageNames[i]);
1541         if (u_strcmp(testLang, expectedLang) != 0)
1542             log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1543                     languageCodes[i], languageNames[i], austrdup(testLang));
1544         free(testLang);
1545         free(expectedLang);
1546     }
1547 
1548 }
1549 
1550 /**
1551  * @bug 4118595
1552  */
TestUninstalledISO3Names()1553 static void TestUninstalledISO3Names()
1554 {
1555   /* This test checks to make sure getISO3Language and getISO3Country work right
1556      even for locales that are not installed (and some installed ones). */
1557     static const char iso2Languages [][4] = {     "am", "ba", "fy", "mr", "rn",
1558                                         "ss", "tw", "zu", "sr" };
1559     static const char iso3Languages [][5] = {     "amh", "bak", "fry", "mar", "run",
1560                                         "ssw", "twi", "zul", "srp" };
1561     static const char iso2Countries [][6] = {     "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1562                                         "ss_SB", "tw_TC", "zu_ZW", "sr_XK" };
1563     static const char iso3Countries [][4] = {     "AFG", "BWA", "KAZ", "MAC", "MNG",
1564                                         "SLB", "TCA", "ZWE", "XKK" };
1565     int32_t i;
1566 
1567     for (i = 0; i < 9; i++) {
1568       UErrorCode err = U_ZERO_ERROR;
1569       const char *test;
1570       test = uloc_getISO3Language(iso2Languages[i]);
1571       if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err))
1572          log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1573                      iso2Languages[i], iso3Languages[i], test, myErrorName(err));
1574     }
1575     for (i = 0; i < 9; i++) {
1576       UErrorCode err = U_ZERO_ERROR;
1577       const char *test;
1578       test = uloc_getISO3Country(iso2Countries[i]);
1579       if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err))
1580          log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1581                      iso2Countries[i], iso3Countries[i], test, myErrorName(err));
1582     }
1583 }
1584 
1585 
TestVariantParsing()1586 static void TestVariantParsing()
1587 {
1588     static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth";
1589     static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1590     static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1591     static const char* shortVariant="fr_FR_foo";
1592     static const char* bogusVariant="fr_FR__foo";
1593     static const char* bogusVariant2="fr_FR_foo_";
1594     static const char* bogusVariant3="fr_FR__foo_";
1595 
1596 
1597     UChar displayVar[100];
1598     UChar displayName[100];
1599     UErrorCode status=U_ZERO_ERROR;
1600     UChar* got=0;
1601     int32_t size=0;
1602     size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status);
1603     if(status==U_BUFFER_OVERFLOW_ERROR) {
1604         status=U_ZERO_ERROR;
1605         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1606         uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status);
1607     }
1608     else {
1609         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1610     }
1611     u_uastrcpy(displayVar, dispVar);
1612     if(u_strcmp(got,displayVar)!=0) {
1613         log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got));
1614     }
1615     size=0;
1616     size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status);
1617     if(status==U_BUFFER_OVERFLOW_ERROR) {
1618         status=U_ZERO_ERROR;
1619         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1620         uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status);
1621     }
1622     else {
1623         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1624     }
1625     u_uastrcpy(displayName, dispName);
1626     if(u_strcmp(got,displayName)!=0) {
1627         if (status == U_USING_DEFAULT_WARNING) {
1628             log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status));
1629         } else {
1630             log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got));
1631         }
1632     }
1633 
1634     size=0;
1635     status=U_ZERO_ERROR;
1636     size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status);
1637     if(status==U_BUFFER_OVERFLOW_ERROR) {
1638         status=U_ZERO_ERROR;
1639         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1640         uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status);
1641     }
1642     else {
1643         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1644     }
1645     if(strcmp(austrdup(got),"FOO")!=0) {
1646         log_err("FAIL: getDisplayVariant()  Wanted: foo  Got: %s\n", austrdup(got));
1647     }
1648     size=0;
1649     status=U_ZERO_ERROR;
1650     size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status);
1651     if(status==U_BUFFER_OVERFLOW_ERROR) {
1652         status=U_ZERO_ERROR;
1653         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1654         uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status);
1655     }
1656     else {
1657         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1658     }
1659     if(strcmp(austrdup(got),"_FOO")!=0) {
1660         log_err("FAIL: getDisplayVariant()  Wanted: _FOO  Got: %s\n", austrdup(got));
1661     }
1662     size=0;
1663     status=U_ZERO_ERROR;
1664     size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status);
1665     if(status==U_BUFFER_OVERFLOW_ERROR) {
1666         status=U_ZERO_ERROR;
1667         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1668         uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status);
1669     }
1670     else {
1671         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1672     }
1673     if(strcmp(austrdup(got),"FOO_")!=0) {
1674         log_err("FAIL: getDisplayVariant()  Wanted: FOO_  Got: %s\n", austrdup(got));
1675     }
1676     size=0;
1677     status=U_ZERO_ERROR;
1678     size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status);
1679     if(status==U_BUFFER_OVERFLOW_ERROR) {
1680         status=U_ZERO_ERROR;
1681         got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1682         uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status);
1683     }
1684     else {
1685         log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1686     }
1687     if(strcmp(austrdup(got),"_FOO_")!=0) {
1688         log_err("FAIL: getDisplayVariant()  Wanted: _FOO_  Got: %s\n", austrdup(got));
1689     }
1690     free(got);
1691 }
1692 
1693 
TestObsoleteNames(void)1694 static void TestObsoleteNames(void)
1695 {
1696     int32_t i;
1697     UErrorCode status = U_ZERO_ERROR;
1698     char buff[256];
1699 
1700     static const struct
1701     {
1702         char locale[9];
1703         char lang3[4];
1704         char lang[4];
1705         char ctry3[4];
1706         char ctry[4];
1707     } tests[] =
1708     {
1709         { "eng_USA", "eng", "en", "USA", "US" },
1710         { "kok",  "kok", "kok", "", "" },
1711         { "in",  "ind", "in", "", "" },
1712         { "id",  "ind", "id", "", "" }, /* NO aliasing */
1713         { "sh",  "srp", "sh", "", "" },
1714         { "zz_CS",  "", "zz", "SCG", "CS" },
1715         { "zz_FX",  "", "zz", "FXX", "FX" },
1716         { "zz_RO",  "", "zz", "ROU", "RO" },
1717         { "zz_TP",  "", "zz", "TMP", "TP" },
1718         { "zz_TL",  "", "zz", "TLS", "TL" },
1719         { "zz_ZR",  "", "zz", "ZAR", "ZR" },
1720         { "zz_FXX",  "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1721         { "zz_ROM",  "", "zz", "ROU", "RO" },
1722         { "zz_ROU",  "", "zz", "ROU", "RO" },
1723         { "zz_ZAR",  "", "zz", "ZAR", "ZR" },
1724         { "zz_TMP",  "", "zz", "TMP", "TP" },
1725         { "zz_TLS",  "", "zz", "TLS", "TL" },
1726         { "zz_YUG",  "", "zz", "YUG", "YU" },
1727         { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1728         { "iw", "heb", "iw", "", "" },
1729         { "ji", "yid", "ji", "", "" },
1730         { "jw", "jaw", "jw", "", "" },
1731         { "sh", "srp", "sh", "", "" },
1732         { "", "", "", "", "" }
1733     };
1734 
1735     for(i=0;tests[i].locale[0];i++)
1736     {
1737         const char *locale;
1738 
1739         locale = tests[i].locale;
1740         log_verbose("** %s:\n", locale);
1741 
1742         status = U_ZERO_ERROR;
1743         if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1744         {
1745             log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1746                 locale,  uloc_getISO3Language(locale), tests[i].lang3);
1747         }
1748         else
1749         {
1750             log_verbose("   uloc_getISO3Language()==\t\"%s\"\n",
1751                 uloc_getISO3Language(locale) );
1752         }
1753 
1754         status = U_ZERO_ERROR;
1755         uloc_getLanguage(locale, buff, 256, &status);
1756         if(U_FAILURE(status))
1757         {
1758             log_err("FAIL: error getting language from %s\n", locale);
1759         }
1760         else
1761         {
1762             if(strcmp(buff,tests[i].lang))
1763             {
1764                 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1765                     locale, buff, tests[i].lang);
1766             }
1767             else
1768             {
1769                 log_verbose("  uloc_getLanguage(%s)==\t%s\n", locale, buff);
1770             }
1771         }
1772         if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1773         {
1774             log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1775                 locale,  uloc_getISO3Language(locale), tests[i].lang3);
1776         }
1777         else
1778         {
1779             log_verbose("   uloc_getISO3Language()==\t\"%s\"\n",
1780                 uloc_getISO3Language(locale) );
1781         }
1782 
1783         if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale)))
1784         {
1785             log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1786                 locale,  uloc_getISO3Country(locale), tests[i].ctry3);
1787         }
1788         else
1789         {
1790             log_verbose("   uloc_getISO3Country()==\t\"%s\"\n",
1791                 uloc_getISO3Country(locale) );
1792         }
1793 
1794         status = U_ZERO_ERROR;
1795         uloc_getCountry(locale, buff, 256, &status);
1796         if(U_FAILURE(status))
1797         {
1798             log_err("FAIL: error getting country from %s\n", locale);
1799         }
1800         else
1801         {
1802             if(strcmp(buff,tests[i].ctry))
1803             {
1804                 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1805                     locale, buff, tests[i].ctry);
1806             }
1807             else
1808             {
1809                 log_verbose("  uloc_getCountry(%s)==\t%s\n", locale, buff);
1810             }
1811         }
1812     }
1813 
1814     if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1815         log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1816     }
1817 
1818     if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1819         log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1820     }
1821 
1822 #if 0
1823 
1824     i = uloc_getLanguage("kok",NULL,0,&icu_err);
1825     if(U_FAILURE(icu_err))
1826     {
1827         log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err));
1828     }
1829 
1830     icu_err = U_ZERO_ERROR;
1831     uloc_getLanguage("kok",r1_buff,12,&icu_err);
1832     if(U_FAILURE(icu_err))
1833     {
1834         log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err));
1835     }
1836 
1837     r1_addr = (char *)uloc_getISO3Language("kok");
1838 
1839     icu_err = U_ZERO_ERROR;
1840     if (strcmp(r1_buff,"kok") != 0)
1841     {
1842         log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff);
1843         line--;
1844     }
1845     r1_addr = (char *)uloc_getISO3Language("in");
1846     i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1847     if (strcmp(r1_buff,"id") != 0)
1848     {
1849         printf("uloc_getLanguage error (%s)\n",r1_buff);
1850         line--;
1851     }
1852     r1_addr = (char *)uloc_getISO3Language("sh");
1853     i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1854     if (strcmp(r1_buff,"sr") != 0)
1855     {
1856         printf("uloc_getLanguage error (%s)\n",r1_buff);
1857         line--;
1858     }
1859 
1860     r1_addr = (char *)uloc_getISO3Country("zz_ZR");
1861     strcpy(p1_buff,"zz_");
1862     strcat(p1_buff,r1_addr);
1863     i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1864     if (strcmp(r1_buff,"ZR") != 0)
1865     {
1866         printf("uloc_getCountry error (%s)\n",r1_buff);
1867         line--;
1868     }
1869     r1_addr = (char *)uloc_getISO3Country("zz_FX");
1870     strcpy(p1_buff,"zz_");
1871     strcat(p1_buff,r1_addr);
1872     i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1873     if (strcmp(r1_buff,"FX") != 0)
1874     {
1875         printf("uloc_getCountry error (%s)\n",r1_buff);
1876         line--;
1877     }
1878 
1879 #endif
1880 
1881 }
1882 
TestKeywordVariants(void)1883 static void TestKeywordVariants(void)
1884 {
1885     static const struct {
1886         const char *localeID;
1887         const char *expectedLocaleID;           /* uloc_getName */
1888         const char *expectedLocaleIDNoKeywords; /* uloc_getBaseName */
1889         const char *expectedCanonicalID;        /* uloc_canonicalize */
1890         const char *expectedKeywords[10];
1891         int32_t numKeywords;
1892         UErrorCode expectedStatus; /* from uloc_openKeywords */
1893     } testCases[] = {
1894         {
1895             "de_DE@  currency = euro; C o ll A t i o n   = Phonebook   ; C alen dar = buddhist   ",
1896             "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1897             "de_DE",
1898             "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1899             {"calendar", "collation", "currency"},
1900             3,
1901             U_ZERO_ERROR
1902         },
1903         {
1904             "de_DE@euro",
1905             "de_DE@euro",
1906             "de_DE@euro",   /* we probably should strip off the POSIX style variant @euro see #11690 */
1907             "de_DE_EURO",
1908             {"","","","","","",""},
1909             0,
1910             U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1911         },
1912         {
1913             "de_DE@euro;collation=phonebook",   /* The POSIX style variant @euro cannot be combined with key=value? */
1914             "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1915             "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1916             "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1917             {"","","","","","",""},
1918             0,
1919             U_INVALID_FORMAT_ERROR
1920         },
1921         {
1922             "de_DE@collation=",
1923             0, /* expected getName to fail */
1924             "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1925             0, /* expected canonicalize to fail */
1926             {"","","","","","",""},
1927             0,
1928             U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1929         }
1930     };
1931     UErrorCode status = U_ZERO_ERROR;
1932 
1933     int32_t i = 0, j = 0;
1934     int32_t resultLen = 0;
1935     char buffer[256];
1936     UEnumeration *keywords;
1937     int32_t keyCount = 0;
1938     const char *keyword = NULL;
1939     int32_t keywordLen = 0;
1940 
1941     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1942         status = U_ZERO_ERROR;
1943         *buffer = 0;
1944         keywords = uloc_openKeywords(testCases[i].localeID, &status);
1945 
1946         if(status != testCases[i].expectedStatus) {
1947             log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1948                     testCases[i].localeID,
1949                     u_errorName(testCases[i].expectedStatus), u_errorName(status));
1950         }
1951         status = U_ZERO_ERROR;
1952         if(keywords) {
1953             if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
1954                 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1955             }
1956             if(keyCount) {
1957                 j = 0;
1958                 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1959                     if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1960                         log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1961                     }
1962                     j++;
1963                 }
1964                 j = 0;
1965                 uenum_reset(keywords, &status);
1966                 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1967                     if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1968                         log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1969                     }
1970                     j++;
1971                 }
1972             }
1973             uenum_close(keywords);
1974         }
1975 
1976         status = U_ZERO_ERROR;
1977         resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
1978         (void)resultLen;
1979         U_ASSERT(resultLen < 256);
1980         if (U_SUCCESS(status)) {
1981             if (testCases[i].expectedLocaleID == 0) {
1982                 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1983                         testCases[i].localeID, buffer);
1984             } else if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
1985                 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1986                         testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
1987             }
1988         } else {
1989             if (testCases[i].expectedLocaleID != 0) {
1990                 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1991                         testCases[i].localeID, testCases[i].expectedLocaleID, buffer, u_errorName(status));
1992             }
1993         }
1994 
1995         status = U_ZERO_ERROR;
1996         resultLen = uloc_getBaseName(testCases[i].localeID, buffer, 256, &status);
1997         U_ASSERT(resultLen < 256);
1998         if (U_SUCCESS(status)) {
1999             if (testCases[i].expectedLocaleIDNoKeywords == 0) {
2000                 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
2001                         testCases[i].localeID, buffer);
2002             } else if (uprv_strcmp(testCases[i].expectedLocaleIDNoKeywords, buffer) != 0) {
2003                 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
2004                         testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer);
2005             }
2006         } else {
2007             if (testCases[i].expectedLocaleIDNoKeywords != 0) {
2008                 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
2009                         testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer, u_errorName(status));
2010             }
2011         }
2012 
2013         status = U_ZERO_ERROR;
2014         resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
2015         U_ASSERT(resultLen < 256);
2016         if (U_SUCCESS(status)) {
2017             if (testCases[i].expectedCanonicalID == 0) {
2018                 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
2019                         testCases[i].localeID, buffer);
2020             } else if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
2021                 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
2022                         testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
2023             }
2024         } else {
2025             if (testCases[i].expectedCanonicalID != 0) {
2026                 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
2027                         testCases[i].localeID, testCases[i].expectedCanonicalID, buffer, u_errorName(status));
2028             }
2029         }
2030     }
2031 }
2032 
TestKeywordVariantParsing(void)2033 static void TestKeywordVariantParsing(void)
2034 {
2035     static const struct {
2036         const char *localeID;
2037         const char *keyword;
2038         const char *expectedValue; /* NULL if failure is expected */
2039     } testCases[] = {
2040         { "de_DE@  C o ll A t i o n   = Phonebook   ", "c o ll a t i o n", NULL }, /* malformed key name */
2041         { "de_DE", "collation", ""},
2042         { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
2043         { "de_DE@currency = euro; CoLLaTion   = PHONEBOOk", "collatiON", "PHONEBOOk" },
2044     };
2045 
2046     UErrorCode status;
2047     int32_t i = 0;
2048     int32_t resultLen = 0;
2049     char buffer[256];
2050 
2051     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2052         *buffer = 0;
2053         status = U_ZERO_ERROR;
2054         resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
2055         (void)resultLen;    /* Suppress set but not used warning. */
2056         if (testCases[i].expectedValue) {
2057             /* expect success */
2058             if (U_FAILURE(status)) {
2059                 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got status %s\n",
2060                     testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, u_errorName(status));
2061             } else if (uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
2062                 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got \"%s\"\n",
2063                     testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
2064             }
2065         } else if (U_SUCCESS(status)) {
2066             /* expect failure */
2067             log_err("Expected failure but got success from \"%s\" for keyword \"%s\". Got \"%s\"\n",
2068                 testCases[i].localeID, testCases[i].keyword, buffer);
2069 
2070         }
2071     }
2072 }
2073 
2074 static const struct {
2075   const char *l; /* locale */
2076   const char *k; /* kw */
2077   const char *v; /* value */
2078   const char *x; /* expected */
2079 } kwSetTestCases[] = {
2080 #if 1
2081   { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
2082   { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
2083   { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
2084   { "en_US@calendar=slovakian", "calendar", "gregorian", "en_US@calendar=gregorian" }, /* don't know what this means, but it has the same # of chars as gregorian */
2085   { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
2086   { "de", "Currency", "CHF", "de@currency=CHF" },
2087   { "de", "Currency", "CHF", "de@currency=CHF" },
2088 
2089   { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2090   { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
2091   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2092   { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2093   { "en_US@calendar=slovakian;collation=phonebook", "calendar", "gregorian", "en_US@calendar=gregorian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */
2094   { "en_US@calendar=slovakian;collation=videobook", "collation", "phonebook", "en_US@calendar=slovakian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */
2095   { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2096   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2097 #endif
2098 #if 1
2099   { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
2100   { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
2101   { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
2102   { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
2103   { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
2104   { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
2105   { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
2106   { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
2107   { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
2108 #endif
2109 #if 1
2110   /* removal tests */
2111   /* 1. removal of item at end */
2112   { "de@collation=phonebook;currency=CHF", "currency",   "", "de@collation=phonebook" },
2113   { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
2114   /* 2. removal of item at beginning */
2115   { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
2116   { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
2117   /* 3. removal of an item not there */
2118   { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
2119   /* 4. removal of only item */
2120   { "de@collation=phonebook", "collation", NULL, "de" },
2121 #endif
2122   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2123   /* cases with legal extra spacing */
2124   /*31*/{ "en_US@ calendar = islamic", "calendar", "japanese", "en_US@calendar=japanese" },
2125   /*32*/{ "en_US@ calendar = gregorian ; collation = phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2126   /*33*/{ "en_US@ calendar = islamic", "currency", "CHF", "en_US@calendar=islamic;currency=CHF" },
2127   /*34*/{ "en_US@ currency = CHF", "calendar", "japanese", "en_US@calendar=japanese;currency=CHF" },
2128   /* cases in which setKeywordValue expected to fail (implied by NULL for expected); locale need not be canonical */
2129   /*35*/{ "en_US@calendar=gregorian;", "calendar", "japanese", NULL },
2130   /*36*/{ "en_US@calendar=gregorian;=", "calendar", "japanese", NULL },
2131   /*37*/{ "en_US@calendar=gregorian;currency=", "calendar", "japanese", NULL },
2132   /*38*/{ "en_US@=", "calendar", "japanese", NULL },
2133   /*39*/{ "en_US@=;", "calendar", "japanese", NULL },
2134   /*40*/{ "en_US@= ", "calendar", "japanese", NULL },
2135   /*41*/{ "en_US@ =", "calendar", "japanese", NULL },
2136   /*42*/{ "en_US@ = ", "calendar", "japanese", NULL },
2137   /*43*/{ "en_US@=;calendar=gregorian", "calendar", "japanese", NULL },
2138   /*44*/{ "en_US@= calen dar = gregorian", "calendar", "japanese", NULL },
2139   /*45*/{ "en_US@= calendar = greg orian", "calendar", "japanese", NULL },
2140   /*46*/{ "en_US@=;cal...endar=gregorian", "calendar", "japanese", NULL },
2141   /*47*/{ "en_US@=;calendar=greg...orian", "calendar", "japanese", NULL },
2142   /*48*/{ "en_US@calendar=gregorian", "cale ndar", "japanese", NULL },
2143   /*49*/{ "en_US@calendar=gregorian", "calendar", "japa..nese", NULL },
2144   /* cases in which getKeywordValue and setKeyword expected to fail (implied by NULL for value and expected) */
2145   /*50*/{ "en_US@=", "calendar", NULL, NULL },
2146   /*51*/{ "en_US@=;", "calendar", NULL, NULL },
2147   /*52*/{ "en_US@= ", "calendar", NULL, NULL },
2148   /*53*/{ "en_US@ =", "calendar", NULL, NULL },
2149   /*54*/{ "en_US@ = ", "calendar", NULL, NULL },
2150   /*55*/{ "en_US@=;calendar=gregorian", "calendar", NULL, NULL },
2151   /*56*/{ "en_US@= calen dar = gregorian", "calendar", NULL, NULL },
2152   /*57*/{ "en_US@= calendar = greg orian", "calendar", NULL, NULL },
2153   /*58*/{ "en_US@=;cal...endar=gregorian", "calendar", NULL, NULL },
2154   /*59*/{ "en_US@=;calendar=greg...orian", "calendar", NULL, NULL },
2155   /*60*/{ "en_US@calendar=gregorian", "cale ndar", NULL, NULL },
2156 };
2157 
2158 
TestKeywordSet(void)2159 static void TestKeywordSet(void)
2160 {
2161     int32_t i = 0;
2162     int32_t resultLen = 0;
2163     char buffer[1024];
2164 
2165     char cbuffer[1024];
2166 
2167     for(i = 0; i < UPRV_LENGTHOF(kwSetTestCases); i++) {
2168       UErrorCode status = U_ZERO_ERROR;
2169       memset(buffer,'%',1023);
2170       strcpy(buffer, kwSetTestCases[i].l);
2171 
2172       if (kwSetTestCases[i].x != NULL) {
2173         uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
2174         if(strcmp(buffer,cbuffer)) {
2175           log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
2176         }
2177         /* sanity check test case results for canonicity */
2178         uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
2179         if(strcmp(kwSetTestCases[i].x,cbuffer)) {
2180           log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
2181         }
2182 
2183         status = U_ZERO_ERROR;
2184         resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
2185         if(U_FAILURE(status)) {
2186           log_err("Err on test case %d for setKeywordValue: got error %s\n", i, u_errorName(status));
2187         } else if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
2188           log_err("FAIL: #%d setKeywordValue: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
2189                   kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
2190         } else {
2191           log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
2192         }
2193 
2194         if (kwSetTestCases[i].v != NULL && kwSetTestCases[i].v[0] != 0) {
2195           status = U_ZERO_ERROR;
2196           resultLen = uloc_getKeywordValue(kwSetTestCases[i].x, kwSetTestCases[i].k, buffer, 1023, &status);
2197           if(U_FAILURE(status)) {
2198             log_err("Err on test case %d for getKeywordValue: got error %s\n", i, u_errorName(status));
2199           } else if (resultLen != (int32_t)uprv_strlen(kwSetTestCases[i].v) || uprv_strcmp(buffer, kwSetTestCases[i].v) != 0) {
2200             log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i, buffer, resultLen,
2201                     kwSetTestCases[i].v, uprv_strlen(kwSetTestCases[i].v));
2202           }
2203         }
2204       } else {
2205         /* test cases expected to result in error */
2206         status = U_ZERO_ERROR;
2207         resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
2208         if(U_SUCCESS(status)) {
2209           log_err("Err on test case %d for setKeywordValue: expected to fail but succeeded, got %s (%d)\n", i, buffer, resultLen);
2210         }
2211 
2212         if (kwSetTestCases[i].v == NULL) {
2213           status = U_ZERO_ERROR;
2214           strcpy(cbuffer, kwSetTestCases[i].l);
2215           resultLen = uloc_getKeywordValue(cbuffer, kwSetTestCases[i].k, buffer, 1023, &status);
2216           if(U_SUCCESS(status)) {
2217             log_err("Err on test case %d for getKeywordValue: expected to fail but succeeded\n", i);
2218           }
2219         }
2220       }
2221     }
2222 }
2223 
TestKeywordSetError(void)2224 static void TestKeywordSetError(void)
2225 {
2226     char buffer[1024];
2227     UErrorCode status;
2228     int32_t res;
2229     int32_t i;
2230     int32_t blen;
2231 
2232     /* 0-test whether an error condition modifies the buffer at all */
2233     blen=0;
2234     i=0;
2235     memset(buffer,'%',1023);
2236     status = U_ZERO_ERROR;
2237     res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2238     if(status != U_ILLEGAL_ARGUMENT_ERROR) {
2239         log_err("expected illegal err got %s\n", u_errorName(status));
2240         return;
2241     }
2242     /*  if(res!=strlen(kwSetTestCases[i].x)) {
2243     log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2244     return;
2245     } */
2246     if(buffer[blen]!='%') {
2247         log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
2248         return;
2249     }
2250     log_verbose("0-buffer modify OK\n");
2251 
2252     for(i=0;i<=2;i++) {
2253         /* 1- test a short buffer with growing text */
2254         blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
2255         memset(buffer,'%',1023);
2256         strcpy(buffer,kwSetTestCases[i].l);
2257         status = U_ZERO_ERROR;
2258         res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2259         if(status != U_BUFFER_OVERFLOW_ERROR) {
2260             log_err("expected buffer overflow on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v);
2261             return;
2262         }
2263         if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
2264             log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2265             return;
2266         }
2267         if(buffer[blen]!='%') {
2268             log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
2269             return;
2270         }
2271         log_verbose("1/%d-buffer modify OK\n",i);
2272     }
2273 
2274     for(i=3;i<=4;i++) {
2275         /* 2- test a short buffer - text the same size or shrinking   */
2276         blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
2277         memset(buffer,'%',1023);
2278         strcpy(buffer,kwSetTestCases[i].l);
2279         status = U_ZERO_ERROR;
2280         res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2281         if(status != U_ZERO_ERROR) {
2282             log_err("expected zero error got %s\n", u_errorName(status));
2283             return;
2284         }
2285         if(buffer[blen+1]!='%') {
2286             log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
2287             return;
2288         }
2289         if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
2290             log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2291             return;
2292         }
2293         if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
2294             log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
2295                 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
2296         } else {
2297             log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
2298                 buffer);
2299         }
2300         log_verbose("2/%d-buffer modify OK\n",i);
2301     }
2302 }
2303 
_canonicalize(int32_t selector,const char * localeID,char * result,int32_t resultCapacity,UErrorCode * ec)2304 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
2305                              const char* localeID,
2306                              char* result,
2307                              int32_t resultCapacity,
2308                              UErrorCode* ec) {
2309     /* YOU can change this to use function pointers if you like */
2310     switch (selector) {
2311     case 0:
2312         return uloc_getName(localeID, result, resultCapacity, ec);
2313     case 1:
2314         return uloc_canonicalize(localeID, result, resultCapacity, ec);
2315     default:
2316         return -1;
2317     }
2318 }
2319 
TestCanonicalization(void)2320 static void TestCanonicalization(void)
2321 {
2322     static const struct {
2323         const char *localeID;    /* input */
2324         const char *getNameID;   /* expected getName() result */
2325         const char *canonicalID; /* expected canonicalize() result */
2326     } testCases[] = {
2327         { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2328           "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2329           "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2330         { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2331         { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2332         { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2333         { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2334         { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2335         { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2336         { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2337         { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2338         { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
2339         { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2340         { "de-1901", "de__1901", "de__1901" }, /* registered name */
2341         { "de-1906", "de__1906", "de__1906" }, /* registered name */
2342 
2343         /* posix behavior that used to be performed by getName */
2344         { "mr.utf8", "mr.utf8", "mr" },
2345         { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2346         { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2347         { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2348         { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2349         { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO_NY_B" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */
2350 
2351         /* fleshing out canonicalization */
2352         /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2353         { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
2354         /* already-canonical ids are not changed */
2355         { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
2356         /* norwegian is just too weird, if we handle things in their full generality */
2357         { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2358 
2359         /* test cases reflecting internal resource bundle usage */
2360         { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2361         { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2362         { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2363         { "ja_JP", "ja_JP", "ja_JP" },
2364 
2365         /* test case for "i-default" */
2366         { "i-default", "en@x=i-default", "en@x=i-default" },
2367 
2368         // Before ICU 64, ICU locale canonicalization had some additional mappings.
2369         // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
2370         // The following now use standard canonicalization.
2371         { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
2372         { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
2373         { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
2374         { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
2375         { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
2376         { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
2377         { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
2378         { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
2379         { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
2380         { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
2381         { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
2382         { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
2383         { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
2384         { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
2385         { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
2386         { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
2387         { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
2388         { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
2389         { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
2390         { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
2391         { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
2392         { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
2393         { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
2394         { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
2395         { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
2396         { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
2397         { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
2398         { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
2399         { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN_STROKE" },
2400         { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
2401         { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
2402         { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */
2403         { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
2404         { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
2405         { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
2406         { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
2407         /* PRE_EURO and EURO conversions don't affect other keywords */
2408         { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
2409         { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
2410         /* currency keyword overrides PRE_EURO and EURO currency */
2411         { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
2412         { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
2413     };
2414 
2415     static const char* label[] = { "getName", "canonicalize" };
2416 
2417     UErrorCode status = U_ZERO_ERROR;
2418     int32_t i, j, resultLen = 0, origResultLen;
2419     char buffer[256];
2420 
2421     for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
2422         for (j=0; j<2; ++j) {
2423             const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
2424             *buffer = 0;
2425             status = U_ZERO_ERROR;
2426 
2427             if (expected == NULL) {
2428                 expected = uloc_getDefault();
2429             }
2430 
2431             /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2432             origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
2433             if (status != U_BUFFER_OVERFLOW_ERROR) {
2434                 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2435                         label[j], testCases[i].localeID, u_errorName(status));
2436                 continue;
2437             }
2438             status = U_ZERO_ERROR;
2439             resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
2440             if (U_FAILURE(status)) {
2441                 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2442                         label[j], testCases[i].localeID, u_errorName(status));
2443                 continue;
2444             }
2445             if(uprv_strcmp(expected, buffer) != 0) {
2446                 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2447                         label[j], testCases[i].localeID, buffer, expected);
2448             } else {
2449                 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2450                             label[j], testCases[i].localeID, buffer);
2451             }
2452             if (resultLen != (int32_t)strlen(buffer)) {
2453                 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2454                         label[j], testCases[i].localeID, resultLen, strlen(buffer));
2455             }
2456             if (origResultLen != resultLen) {
2457                 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2458                         label[j], testCases[i].localeID, origResultLen, resultLen);
2459             }
2460         }
2461     }
2462 }
2463 
TestCanonicalizationBuffer(void)2464 static void TestCanonicalizationBuffer(void)
2465 {
2466     UErrorCode status = U_ZERO_ERROR;
2467     char buffer[256];
2468 
2469     // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
2470     static const char name[] =
2471         "zh@x"
2472         "=foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2473         "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2474         "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2475         "-foo-barz"
2476     ;
2477     static const size_t len = sizeof(name) - 1;  // Without NUL terminator.
2478 
2479     int32_t reslen = uloc_canonicalize(name, buffer, (int32_t)len, &status);
2480 
2481     if (U_FAILURE(status)) {
2482         log_err("FAIL: uloc_canonicalize(%s) => %s, expected !U_FAILURE()\n",
2483                 name, u_errorName(status));
2484         return;
2485     }
2486 
2487     if (reslen != len) {
2488         log_err("FAIL: uloc_canonicalize(%s) => \"%i\", expected \"%u\"\n",
2489                 name, reslen, len);
2490         return;
2491     }
2492 
2493     if (uprv_strncmp(name, buffer, len) != 0) {
2494         log_err("FAIL: uloc_canonicalize(%s) => \"%.*s\", expected \"%s\"\n",
2495                 name, reslen, buffer, name);
2496         return;
2497     }
2498 }
2499 
TestCanonicalization21749StackUseAfterScope(void)2500 static void TestCanonicalization21749StackUseAfterScope(void)
2501 {
2502     UErrorCode status = U_ZERO_ERROR;
2503     char buffer[256];
2504     const char* input = "- _";
2505     uloc_canonicalize(input, buffer, -1, &status);
2506     if (U_SUCCESS(status)) {
2507         log_err("FAIL: uloc_canonicalize(%s) => %s, expected U_FAILURE()\n",
2508                 input, u_errorName(status));
2509         return;
2510     }
2511 
2512     // ICU-22475 test that we don't free an internal buffer twice.
2513     status = U_ZERO_ERROR;
2514     uloc_canonicalize("ti-defaultgR-lS-z-UK-0P", buffer, UPRV_LENGTHOF(buffer), &status);
2515 }
2516 
TestDisplayKeywords(void)2517 static void TestDisplayKeywords(void)
2518 {
2519     int32_t i;
2520 
2521     static const struct {
2522         const char *localeID;
2523         const char *displayLocale;
2524         UChar displayKeyword[200];
2525     } testCases[] = {
2526         {   "ca_ES@currency=ESP",         "de_AT",
2527             {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2528         },
2529         {   "ja_JP@calendar=japanese",         "de",
2530             { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2531         },
2532         {   "de_DE@collation=traditional",       "de_DE",
2533             {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2534         },
2535     };
2536     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2537         UErrorCode status = U_ZERO_ERROR;
2538         const char* keyword =NULL;
2539         int32_t keywordLen = 0;
2540         int32_t keywordCount = 0;
2541         UChar *displayKeyword=NULL;
2542         int32_t displayKeywordLen = 0;
2543         UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2544         for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2545               if(U_FAILURE(status)){
2546                   log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
2547                   break;
2548               }
2549               /* the uenum_next returns NUL terminated string */
2550               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2551               /* fetch the displayKeyword */
2552               displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2553               if(status==U_BUFFER_OVERFLOW_ERROR){
2554                   status = U_ZERO_ERROR;
2555                   displayKeywordLen++; /* for null termination */
2556                   displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
2557                   displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2558                   if(U_FAILURE(status)){
2559                       log_err("uloc_getDisplayKeyword filed for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
2560                       free(displayKeyword);
2561                       break;
2562                   }
2563                   if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
2564                       if (status == U_USING_DEFAULT_WARNING) {
2565                           log_data_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s . Got error: %s. Perhaps you are missing data?\n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
2566                       } else {
2567                           log_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale);
2568                       }
2569                       free(displayKeyword);
2570                       break;
2571                   }
2572               }else{
2573                   log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
2574               }
2575 
2576               free(displayKeyword);
2577 
2578         }
2579         uenum_close(keywordEnum);
2580     }
2581 }
2582 
TestDisplayKeywordValues(void)2583 static void TestDisplayKeywordValues(void){
2584     int32_t i;
2585 
2586     static const struct {
2587         const char *localeID;
2588         const char *displayLocale;
2589         UChar displayKeywordValue[500];
2590     } testCases[] = {
2591         {   "ca_ES@currency=ESP",         "de_AT",
2592             {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2593         },
2594         {   "de_AT@currency=ATS",         "fr_FR",
2595             {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2596         },
2597         {   "de_DE@currency=DEM",         "it",
2598             {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2599         },
2600         {   "el_GR@currency=GRD",         "en",
2601             {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2602         },
2603         {   "eu_ES@currency=ESP",         "it_IT",
2604             {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2605         },
2606         {   "de@collation=phonebook",     "es",
2607             {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000}
2608         },
2609 
2610         { "de_DE@collation=phonebook",  "es",
2611           {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000}
2612         },
2613         { "es_ES@collation=traditional","de",
2614           {0x0054, 0x0072, 0x0061, 0x0064, 0x0069, 0x0074, 0x0069, 0x006f, 0x006e, 0x0065, 0x006c, 0x006c, 0x0065, 0x0020, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006E, 0x0067, 0x0000}
2615         },
2616         { "ja_JP@calendar=japanese",    "de",
2617            {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2618         },
2619     };
2620     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2621         UErrorCode status = U_ZERO_ERROR;
2622         const char* keyword =NULL;
2623         int32_t keywordLen = 0;
2624         int32_t keywordCount = 0;
2625         UChar *displayKeywordValue = NULL;
2626         int32_t displayKeywordValueLen = 0;
2627         UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2628         for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2629               if(U_FAILURE(status)){
2630                   log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", testCases[i].localeID, testCases[i].displayLocale, u_errorName(status));
2631                   break;
2632               }
2633               /* the uenum_next returns NUL terminated string */
2634               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2635 
2636               /* fetch the displayKeywordValue */
2637               displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2638               if(status==U_BUFFER_OVERFLOW_ERROR){
2639                   status = U_ZERO_ERROR;
2640                   displayKeywordValueLen++; /* for null termination */
2641                   displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2642                   displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2643                   if(U_FAILURE(status)){
2644                       log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
2645                       free(displayKeywordValue);
2646                       break;
2647                   }
2648                   if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
2649                       if (status == U_USING_DEFAULT_WARNING) {
2650                           log_data_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s Perhaps you are missing data\n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
2651                       } else {
2652                           log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
2653                       }
2654                       free(displayKeywordValue);
2655                       break;
2656                   }
2657               }else{
2658                   log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2659               }
2660               free(displayKeywordValue);
2661         }
2662         uenum_close(keywordEnum);
2663     }
2664     {
2665         /* test a multiple keywords */
2666         UErrorCode status = U_ZERO_ERROR;
2667         const char* keyword =NULL;
2668         int32_t keywordLen = 0;
2669         int32_t keywordCount = 0;
2670         const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
2671         const char* displayLocale = "de";
2672         static const UChar expected[][50] = {
2673             {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2674 
2675             {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2676             {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2677         };
2678 
2679         UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
2680 
2681         for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
2682               UChar *displayKeywordValue = NULL;
2683               int32_t displayKeywordValueLen = 0;
2684               if(U_FAILURE(status)){
2685                   log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
2686                   break;
2687               }
2688               /* the uenum_next returns NUL terminated string */
2689               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2690 
2691               /* fetch the displayKeywordValue */
2692               displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2693               if(status==U_BUFFER_OVERFLOW_ERROR){
2694                   status = U_ZERO_ERROR;
2695                   displayKeywordValueLen++; /* for null termination */
2696                   displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2697                   displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2698                   if(U_FAILURE(status)){
2699                       log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID, keyword, displayLocale, u_errorName(status));
2700                       free(displayKeywordValue);
2701                       break;
2702                   }
2703                   if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
2704                       if (status == U_USING_DEFAULT_WARNING) {
2705                           log_data_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s  got error: %s. Perhaps you are missing data?\n", localeID, keyword, displayLocale, u_errorName(status));
2706                       } else {
2707                           log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
2708                       }
2709                       free(displayKeywordValue);
2710                       break;
2711                   }
2712               }else{
2713                   log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2714               }
2715               free(displayKeywordValue);
2716         }
2717         uenum_close(keywordEnum);
2718 
2719     }
2720     {
2721         /* Test non existent keywords */
2722         UErrorCode status = U_ZERO_ERROR;
2723         const char* localeID = "es";
2724         const char* displayLocale = "de";
2725         UChar *displayKeywordValue = NULL;
2726         int32_t displayKeywordValueLen = 0;
2727 
2728         /* fetch the displayKeywordValue */
2729         displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2730         if(U_FAILURE(status)) {
2731           log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
2732         } else if(displayKeywordValueLen != 0) {
2733           log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
2734         }
2735     }
2736 }
2737 
2738 
TestGetBaseName(void)2739 static void TestGetBaseName(void) {
2740     static const struct {
2741         const char *localeID;
2742         const char *baseName;
2743     } testCases[] = {
2744         { "de_DE@  C o ll A t i o n   = Phonebook   ", "de_DE" },
2745         { "de@currency = euro; CoLLaTion   = PHONEBOOk", "de" },
2746         { "ja@calendar = buddhist", "ja" }
2747     };
2748 
2749     int32_t i = 0, baseNameLen = 0;
2750     char baseName[256];
2751     UErrorCode status = U_ZERO_ERROR;
2752 
2753     for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2754         baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
2755         (void)baseNameLen;    /* Suppress set but not used warning. */
2756         if(strcmp(testCases[i].baseName, baseName)) {
2757             log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2758                 testCases[i].localeID, testCases[i].baseName, baseName);
2759             return;
2760         }
2761     }
2762 }
2763 
TestTrailingNull(void)2764 static void TestTrailingNull(void) {
2765   const char* localeId = "zh_Hans";
2766   UChar buffer[128]; /* sufficient for this test */
2767   int32_t len;
2768   UErrorCode status = U_ZERO_ERROR;
2769   int i;
2770 
2771   len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status);
2772   if (len > 128) {
2773     log_err("buffer too small");
2774     return;
2775   }
2776 
2777   for (i = 0; i < len; ++i) {
2778     if (buffer[i] == 0) {
2779       log_err("name contained null");
2780       return;
2781     }
2782   }
2783 }
2784 
2785 /* Jitterbug 4115 */
TestDisplayNameWarning(void)2786 static void TestDisplayNameWarning(void) {
2787     UChar name[256];
2788     int32_t size;
2789     UErrorCode status = U_ZERO_ERROR;
2790 
2791     size = uloc_getDisplayLanguage("qqq", "kl", name, UPRV_LENGTHOF(name), &status);
2792     (void)size;    /* Suppress set but not used warning. */
2793     if (status != U_USING_DEFAULT_WARNING) {
2794         log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2795             u_errorName(status));
2796     }
2797 }
2798 
2799 
2800 /**
2801  * Compare two locale IDs.  If they are equal, return 0.  If `string'
2802  * starts with `prefix' plus an additional element, that is, string ==
2803  * prefix + '_' + x, then return 1.  Otherwise return a value < 0.
2804  */
_loccmp(const char * string,const char * prefix)2805 static UBool _loccmp(const char* string, const char* prefix) {
2806     int32_t slen = (int32_t)uprv_strlen(string),
2807             plen = (int32_t)uprv_strlen(prefix);
2808     int32_t c = uprv_strncmp(string, prefix, plen);
2809     /* 'root' is less than everything */
2810     if (uprv_strcmp(prefix, "root") == 0) {
2811         return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
2812     }
2813     if (c) return -1; /* mismatch */
2814     if (slen == plen) return 0;
2815     if (string[plen] == '_') return 1;
2816     return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2817 }
2818 
_checklocs(const char * label,const char * req,const char * valid,const char * actual)2819 static void _checklocs(const char* label,
2820                        const char* req,
2821                        const char* valid,
2822                        const char* actual) {
2823     /* We want the valid to be strictly > the bogus requested locale,
2824        and the valid to be >= the actual. */
2825     if (_loccmp(req, valid) > 0 &&
2826         _loccmp(valid, actual) >= 0) {
2827         log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2828                     label, req, valid, actual);
2829     } else {
2830         log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2831                 label, req, valid, actual);
2832     }
2833 }
2834 
TestGetLocale(void)2835 static void TestGetLocale(void) {
2836     UErrorCode ec = U_ZERO_ERROR;
2837     UParseError pe;
2838     UChar EMPTY[1] = {0};
2839 
2840     /* === udat === */
2841 #if !UCONFIG_NO_FORMATTING
2842     {
2843         UDateFormat *obj;
2844         const char *req = "en_US_REDWOODSHORES", *valid, *actual;
2845         obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
2846                         req,
2847                         NULL, 0,
2848                         NULL, 0, &ec);
2849         if (U_FAILURE(ec)) {
2850             log_data_err("udat_open failed.Error %s\n", u_errorName(ec));
2851             return;
2852         }
2853         valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2854         actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2855         if (U_FAILURE(ec)) {
2856             log_err("udat_getLocaleByType() failed\n");
2857             return;
2858         }
2859         _checklocs("udat", req, valid, actual);
2860         udat_close(obj);
2861     }
2862 #endif
2863 
2864     /* === ucal === */
2865 #if !UCONFIG_NO_FORMATTING
2866     {
2867         UCalendar *obj;
2868         const char *req = "fr_FR_PROVENCAL", *valid, *actual;
2869         obj = ucal_open(NULL, 0,
2870                         req,
2871                         UCAL_GREGORIAN,
2872                         &ec);
2873         if (U_FAILURE(ec)) {
2874             log_err("ucal_open failed with error: %s\n", u_errorName(ec));
2875             return;
2876         }
2877         valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2878         actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2879         if (U_FAILURE(ec)) {
2880             log_err("ucal_getLocaleByType() failed\n");
2881             return;
2882         }
2883         _checklocs("ucal", req, valid, actual);
2884         ucal_close(obj);
2885     }
2886 #endif
2887 
2888     /* === unum === */
2889 #if !UCONFIG_NO_FORMATTING
2890     {
2891         UNumberFormat *obj;
2892         const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
2893         obj = unum_open(UNUM_DECIMAL,
2894                         NULL, 0,
2895                         req,
2896                         &pe, &ec);
2897         if (U_FAILURE(ec)) {
2898             log_err("unum_open failed\n");
2899             return;
2900         }
2901         valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2902         actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2903         if (U_FAILURE(ec)) {
2904             log_err("unum_getLocaleByType() failed\n");
2905             return;
2906         }
2907         _checklocs("unum", req, valid, actual);
2908         unum_close(obj);
2909     }
2910 #endif
2911 
2912     /* === umsg === */
2913 #if 0
2914     /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2915 #if !UCONFIG_NO_FORMATTING
2916     {
2917         UMessageFormat *obj;
2918         const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
2919         UBool test;
2920         obj = umsg_open(EMPTY, 0,
2921                         req,
2922                         &pe, &ec);
2923         if (U_FAILURE(ec)) {
2924             log_err("umsg_open failed\n");
2925             return;
2926         }
2927         valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2928         actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2929         if (U_FAILURE(ec)) {
2930             log_err("umsg_getLocaleByType() failed\n");
2931             return;
2932         }
2933         /* We want the valid to be strictly > the bogus requested locale,
2934            and the valid to be >= the actual. */
2935         /* TODO MessageFormat is currently just storing the locale it is given.
2936            As a result, it will return whatever it was given, even if the
2937            locale is invalid. */
2938         test = (_cmpversion("3.2") <= 0) ?
2939             /* Here is the weakened test for 3.0: */
2940             (_loccmp(req, valid) >= 0) :
2941             /* Here is what the test line SHOULD be: */
2942             (_loccmp(req, valid) > 0);
2943 
2944         if (test &&
2945             _loccmp(valid, actual) >= 0) {
2946             log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2947         } else {
2948             log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2949         }
2950         umsg_close(obj);
2951     }
2952 #endif
2953 #endif
2954 
2955     /* === ubrk === */
2956 #if !UCONFIG_NO_BREAK_ITERATION
2957     {
2958         UBreakIterator *obj;
2959         const char *req = "ar_KW_ABDALI", *valid, *actual;
2960         obj = ubrk_open(UBRK_WORD,
2961                         req,
2962                         EMPTY,
2963                         0,
2964                         &ec);
2965         if (U_FAILURE(ec)) {
2966             log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
2967             return;
2968         }
2969         valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2970         actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2971         if (U_FAILURE(ec)) {
2972             log_err("ubrk_getLocaleByType() failed\n");
2973             return;
2974         }
2975         _checklocs("ubrk", req, valid, actual);
2976         ubrk_close(obj);
2977     }
2978 #endif
2979 
2980     /* === ucol === */
2981 #if !UCONFIG_NO_COLLATION
2982     {
2983         UCollator *obj;
2984         const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
2985         obj = ucol_open(req, &ec);
2986         if (U_FAILURE(ec)) {
2987             log_err("ucol_open failed - %s\n", u_errorName(ec));
2988             return;
2989         }
2990         valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2991         actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2992         if (U_FAILURE(ec)) {
2993             log_err("ucol_getLocaleByType() failed\n");
2994             return;
2995         }
2996         _checklocs("ucol", req, valid, actual);
2997         ucol_close(obj);
2998     }
2999 #endif
3000 }
TestEnglishExemplarCharacters(void)3001 static void TestEnglishExemplarCharacters(void) {
3002     UErrorCode status = U_ZERO_ERROR;
3003     int i;
3004     USet *exSet = NULL;
3005     UChar testChars[] = {
3006         0x61,   /* standard */
3007         0xE1,   /* auxiliary */
3008         0x41,   /* index */
3009         0x2D    /* punctuation */
3010     };
3011     ULocaleData *uld = ulocdata_open("en", &status);
3012     if (U_FAILURE(status)) {
3013         log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status));
3014         return;
3015     }
3016 
3017     for (i = 0; i < ULOCDATA_ES_COUNT; i++) {
3018         exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status);
3019         if (U_FAILURE(status)) {
3020             log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i);
3021             status = U_ZERO_ERROR;
3022             continue;
3023         }
3024         if (!uset_contains(exSet, (UChar32)testChars[i])) {
3025             log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i);
3026         }
3027     }
3028 
3029     uset_close(exSet);
3030     ulocdata_close(uld);
3031 }
3032 
TestNonexistentLanguageExemplars(void)3033 static void TestNonexistentLanguageExemplars(void) {
3034     /* JB 4068 - Nonexistent language */
3035     UErrorCode ec = U_ZERO_ERROR;
3036     ULocaleData *uld = ulocdata_open("qqq",&ec);
3037     if (ec != U_USING_DEFAULT_WARNING) {
3038         log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
3039             u_errorName(ec));
3040     }
3041     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
3042     ulocdata_close(uld);
3043 }
3044 
TestLocDataErrorCodeChaining(void)3045 static void TestLocDataErrorCodeChaining(void) {
3046     UErrorCode ec = U_USELESS_COLLATOR_ERROR;
3047     ulocdata_open(NULL, &ec);
3048     ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
3049     ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
3050     ulocdata_getMeasurementSystem(NULL, &ec);
3051     ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
3052     if (ec != U_USELESS_COLLATOR_ERROR) {
3053         log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
3054     }
3055 }
3056 
3057 typedef struct {
3058     const char*        locale;
3059     UMeasurementSystem measureSys;
3060 } LocToMeasureSys;
3061 
3062 static const LocToMeasureSys locToMeasures[] = {
3063     { "fr_FR",            UMS_SI },
3064     { "en",               UMS_US },
3065     { "en_GB",            UMS_UK },
3066     { "fr_FR@rg=GBZZZZ",  UMS_UK },
3067     { "en@rg=frzzzz",     UMS_SI },
3068     { "en_GB@rg=USZZZZ",  UMS_US },
3069     { NULL, (UMeasurementSystem)0 } /* terminator */
3070 };
3071 
TestLocDataWithRgTag(void)3072 static void TestLocDataWithRgTag(void) {
3073     const  LocToMeasureSys* locToMeasurePtr = locToMeasures;
3074     for (; locToMeasurePtr->locale != NULL; locToMeasurePtr++) {
3075         UErrorCode status = U_ZERO_ERROR;
3076         UMeasurementSystem measureSys = ulocdata_getMeasurementSystem(locToMeasurePtr->locale, &status);
3077         if (U_FAILURE(status)) {
3078             log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
3079                         locToMeasurePtr->locale, u_errorName(status));
3080         } else if (measureSys != locToMeasurePtr->measureSys) {
3081             log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
3082                         locToMeasurePtr->locale, (int) locToMeasurePtr->measureSys, (int)measureSys);
3083         }
3084     }
3085 }
3086 
TestLanguageExemplarsFallbacks(void)3087 static void TestLanguageExemplarsFallbacks(void) {
3088     /* Test that en_US fallsback, but en doesn't fallback. */
3089     UErrorCode ec = U_ZERO_ERROR;
3090     ULocaleData *uld = ulocdata_open("en_US",&ec);
3091     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
3092     if (ec != U_USING_FALLBACK_WARNING) {
3093         log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
3094             u_errorName(ec));
3095     }
3096     ulocdata_close(uld);
3097     ec = U_ZERO_ERROR;
3098     uld = ulocdata_open("en",&ec);
3099     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
3100     if (ec != U_ZERO_ERROR) {
3101         log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
3102             u_errorName(ec));
3103     }
3104     ulocdata_close(uld);
3105 }
3106 
acceptResult(UAcceptResult uar)3107 static const char *acceptResult(UAcceptResult uar) {
3108     return  udbg_enumName(UDBG_UAcceptResult, uar);
3109 }
3110 
TestAcceptLanguage(void)3111 static void TestAcceptLanguage(void) {
3112     UErrorCode status = U_ZERO_ERROR;
3113     UAcceptResult outResult;
3114     UEnumeration *available;
3115     char tmp[200];
3116     int i;
3117     int32_t rc = 0;
3118 
3119     struct {
3120         int32_t httpSet;       /**< Which of http[] should be used? */
3121         const char *icuSet;    /**< ? */
3122         const char *expect;    /**< The expected locale result */
3123         UAcceptResult res;     /**< The expected error code */
3124         UErrorCode expectStatus; /**< expected status */
3125     } tests[] = {
3126         /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
3127         /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
3128         /*2*/{ 2, NULL, "en_GB", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},
3129         /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR},
3130         /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
3131         /*5*/{ 5, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},  /* XF */
3132         /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},  /* XF */
3133         /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},  /* XF */
3134         /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR },  /*  */
3135         /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR },  /*  */
3136        /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR },  /*  */
3137        /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR },  /*  */
3138     };
3139     const int32_t numTests = UPRV_LENGTHOF(tests);
3140     static const char *http[] = {
3141         /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, "
3142               "iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, "
3143               "es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, "
3144               "nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=0.01",
3145         /*1*/ "ja;q=0.5, en;q=0.8, tlh",
3146         /*2*/ "en-wf, de-lx;q=0.8",
3147         /*3*/ "mga-ie;q=0.9, sux",
3148         /*4*/ "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3149               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3150               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3151               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3152               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3153               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, "
3154               "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xx-yy;q=0.1, "
3155               "es",
3156         /*5*/ "zh-xx;q=0.9, en;q=0.6",
3157         /*6*/ "ja-JA",
3158         /*7*/ "zh-xx;q=0.9",
3159        /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3160               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3161               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3162               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
3163        /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3164               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3165               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3166               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
3167        /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3168               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3169               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3170               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
3171        /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3172               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3173               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3174               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
3175     };
3176 
3177     for(i=0;i<numTests;i++) {
3178         outResult = -3;
3179         status=U_ZERO_ERROR;
3180         log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3181             i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
3182 
3183         available = ures_openAvailableLocales(tests[i].icuSet, &status);
3184         tmp[0]=0;
3185         rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult,
3186                                          http[tests[i].httpSet], available, &status);
3187         (void)rc;    /* Suppress set but not used warning. */
3188         uenum_close(available);
3189         log_verbose(" got %s, %s [%s]\n",
3190                     tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
3191         if(status != tests[i].expectStatus) {
3192           log_err_status(status,
3193                          "FAIL: expected status %s but got %s\n",
3194                          u_errorName(tests[i].expectStatus),
3195                          u_errorName(status));
3196         } else if(U_SUCCESS(tests[i].expectStatus)) {
3197             /* don't check content if expected failure */
3198             if(outResult != tests[i].res) {
3199             log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
3200                 acceptResult( tests[i].res),
3201                 acceptResult( outResult));
3202             log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3203                      i, http[tests[i].httpSet], tests[i].icuSet,
3204                      tests[i].expect,acceptResult(tests[i].res));
3205             }
3206             if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
3207               log_err_status(status,
3208                              "FAIL: #%d: expected %s but got %s\n",
3209                              i, tests[i].expect, tmp);
3210               log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3211                        i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
3212             }
3213         }
3214     }
3215 
3216     // API coverage
3217     status = U_ZERO_ERROR;
3218     static const char *const supported[] = { "en-US", "en-GB", "de-DE", "ja-JP" };
3219     const char * desired[] = { "de-LI", "en-IN", "zu", "fr" };
3220     available = uenum_openCharStringsEnumeration(supported, UPRV_LENGTHOF(supported), &status);
3221     tmp[0]=0;
3222     rc = uloc_acceptLanguage(tmp, 199, &outResult, desired, UPRV_LENGTHOF(desired), available, &status);
3223     if (U_FAILURE(status) || rc != 5 || uprv_strcmp(tmp, "de_DE") != 0 || outResult == ULOC_ACCEPT_FAILED) {
3224         log_err("uloc_acceptLanguage() failed to do a simple match\n");
3225     }
3226     uenum_close(available);
3227 }
3228 
3229 static const char* LOCALE_ALIAS[][2] = {
3230     {"in", "id"},
3231     {"in_ID", "id_ID"},
3232     {"iw", "he"},
3233     {"iw_IL", "he_IL"},
3234     {"ji", "yi"},
3235     {"en_BU", "en_MM"},
3236     {"en_DY", "en_BJ"},
3237     {"en_HV", "en_BF"},
3238     {"en_NH", "en_VU"},
3239     {"en_RH", "en_ZW"},
3240     {"en_TP", "en_TL"},
3241     {"en_ZR", "en_CD"}
3242 };
isLocaleAvailable(UResourceBundle * resIndex,const char * loc)3243 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
3244     UErrorCode status = U_ZERO_ERROR;
3245     int32_t len = 0;
3246     ures_getStringByKey(resIndex, loc,&len, &status);
3247     if(U_FAILURE(status)){
3248         return false;
3249     }
3250     return true;
3251 }
3252 
TestCalendar()3253 static void TestCalendar() {
3254 #if !UCONFIG_NO_FORMATTING
3255     int i;
3256     UErrorCode status = U_ZERO_ERROR;
3257     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3258     if(U_FAILURE(status)){
3259         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3260         return;
3261     }
3262     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3263         const char* oldLoc = LOCALE_ALIAS[i][0];
3264         const char* newLoc = LOCALE_ALIAS[i][1];
3265         UCalendar* c1 = NULL;
3266         UCalendar* c2 = NULL;
3267 
3268         /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
3269         const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
3270         const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
3271 
3272         if(!isLocaleAvailable(resIndex, newLoc)){
3273             continue;
3274         }
3275         c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
3276         c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
3277 
3278         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
3279             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3280         }
3281         log_verbose("ucal_getLocaleByType old:%s   new:%s\n", l1, l2);
3282         ucal_close(c1);
3283         ucal_close(c2);
3284     }
3285     ures_close(resIndex);
3286 #endif
3287 }
3288 
TestDateFormat()3289 static void TestDateFormat() {
3290 #if !UCONFIG_NO_FORMATTING
3291     int i;
3292     UErrorCode status = U_ZERO_ERROR;
3293     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3294     if(U_FAILURE(status)){
3295         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3296         return;
3297     }
3298     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3299         const char* oldLoc = LOCALE_ALIAS[i][0];
3300         const char* newLoc = LOCALE_ALIAS[i][1];
3301         UDateFormat* df1 = NULL;
3302         UDateFormat* df2 = NULL;
3303         const char* l1 = NULL;
3304         const char* l2 = NULL;
3305 
3306         if(!isLocaleAvailable(resIndex, newLoc)){
3307             continue;
3308         }
3309         df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
3310         df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
3311         if(U_FAILURE(status)){
3312             log_err("Creation of date format failed  %s\n", u_errorName(status));
3313             return;
3314         }
3315         /*Test function "getLocale"*/
3316         l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
3317         l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
3318         if(U_FAILURE(status)){
3319             log_err("Fetching the locale by type failed.  %s\n", u_errorName(status));
3320         }
3321         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
3322             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3323         }
3324         log_verbose("udat_getLocaleByType old:%s   new:%s\n", l1, l2);
3325         udat_close(df1);
3326         udat_close(df2);
3327     }
3328     ures_close(resIndex);
3329 #endif
3330 }
3331 
TestCollation()3332 static void TestCollation() {
3333 #if !UCONFIG_NO_COLLATION
3334     int i;
3335     UErrorCode status = U_ZERO_ERROR;
3336     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3337     if(U_FAILURE(status)){
3338         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3339         return;
3340     }
3341     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3342         const char* oldLoc = LOCALE_ALIAS[i][0];
3343         const char* newLoc = LOCALE_ALIAS[i][1];
3344         UCollator* c1 = NULL;
3345         UCollator* c2 = NULL;
3346         const char* l1 = NULL;
3347         const char* l2 = NULL;
3348 
3349         status = U_ZERO_ERROR;
3350         if(!isLocaleAvailable(resIndex, newLoc)){
3351             continue;
3352         }
3353         if(U_FAILURE(status)){
3354             log_err("Creation of collators failed  %s\n", u_errorName(status));
3355             return;
3356         }
3357         c1 = ucol_open(oldLoc, &status);
3358         c2 = ucol_open(newLoc, &status);
3359         l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
3360         l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
3361         if(U_FAILURE(status)){
3362             log_err("Fetching the locale names failed failed  %s\n", u_errorName(status));
3363         }
3364         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
3365             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3366         }
3367         log_verbose("ucol_getLocaleByType old:%s   new:%s\n", l1, l2);
3368         ucol_close(c1);
3369         ucol_close(c2);
3370     }
3371     ures_close(resIndex);
3372 #endif
3373 }
3374 
3375 typedef struct OrientationStructTag {
3376     const char* localeId;
3377     ULayoutType character;
3378     ULayoutType line;
3379 } OrientationStruct;
3380 
ULayoutTypeToString(ULayoutType type)3381 static const char* ULayoutTypeToString(ULayoutType type)
3382 {
3383     switch(type)
3384     {
3385     case ULOC_LAYOUT_LTR:
3386         return "ULOC_LAYOUT_LTR";
3387         break;
3388     case ULOC_LAYOUT_RTL:
3389         return "ULOC_LAYOUT_RTL";
3390         break;
3391     case ULOC_LAYOUT_TTB:
3392         return "ULOC_LAYOUT_TTB";
3393         break;
3394     case ULOC_LAYOUT_BTT:
3395         return "ULOC_LAYOUT_BTT";
3396         break;
3397     case ULOC_LAYOUT_UNKNOWN:
3398         break;
3399     }
3400 
3401     return "Unknown enum value for ULayoutType!";
3402 }
3403 
TestOrientation()3404 static void  TestOrientation()
3405 {
3406     static const OrientationStruct toTest [] = {
3407         { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3408         { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3409         { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3410         { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3411         { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3412         { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3413         { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3414         { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3415         { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3416         { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB }
3417     };
3418 
3419     size_t i = 0;
3420     for (; i < UPRV_LENGTHOF(toTest); ++i) {
3421         UErrorCode statusCO = U_ZERO_ERROR;
3422         UErrorCode statusLO = U_ZERO_ERROR;
3423         const char* const localeId = toTest[i].localeId;
3424         const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO);
3425         const ULayoutType expectedCO = toTest[i].character;
3426         const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO);
3427         const ULayoutType expectedLO = toTest[i].line;
3428         if (U_FAILURE(statusCO)) {
3429             log_err_status(statusCO,
3430                 "  unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3431                 localeId,
3432                 u_errorName(statusCO));
3433         }
3434         else if (co != expectedCO) {
3435             log_err(
3436                 "  unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3437                 localeId,
3438                 ULayoutTypeToString(expectedCO),
3439                 ULayoutTypeToString(co));
3440         }
3441         if (U_FAILURE(statusLO)) {
3442             log_err_status(statusLO,
3443                 "  unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3444                 localeId,
3445                 u_errorName(statusLO));
3446         }
3447         else if (lo != expectedLO) {
3448             log_err(
3449                 "  unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3450                 localeId,
3451                 ULayoutTypeToString(expectedLO),
3452                 ULayoutTypeToString(lo));
3453         }
3454     }
3455 }
3456 
TestULocale()3457 static void  TestULocale() {
3458     int i;
3459     UErrorCode status = U_ZERO_ERROR;
3460     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3461     if(U_FAILURE(status)){
3462         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3463         return;
3464     }
3465     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3466         const char* oldLoc = LOCALE_ALIAS[i][0];
3467         const char* newLoc = LOCALE_ALIAS[i][1];
3468         UChar name1[256], name2[256];
3469         char names1[256], names2[256];
3470         int32_t capacity = 256;
3471 
3472         status = U_ZERO_ERROR;
3473         if(!isLocaleAvailable(resIndex, newLoc)){
3474             continue;
3475         }
3476         uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
3477         if(U_FAILURE(status)){
3478             log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
3479         }
3480 
3481         uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
3482         if(U_FAILURE(status)){
3483             log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
3484         }
3485 
3486         if (u_strcmp(name1, name2)!=0) {
3487             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3488         }
3489         u_austrcpy(names1, name1);
3490         u_austrcpy(names2, name2);
3491         log_verbose("uloc_getDisplayName old:%s   new:%s\n", names1, names2);
3492     }
3493     ures_close(resIndex);
3494 
3495 }
3496 
TestUResourceBundle()3497 static void TestUResourceBundle() {
3498     const char* us1;
3499     const char* us2;
3500 
3501     UResourceBundle* rb1 = NULL;
3502     UResourceBundle* rb2 = NULL;
3503     UErrorCode status = U_ZERO_ERROR;
3504     int i;
3505     UResourceBundle *resIndex = NULL;
3506     if(U_FAILURE(status)){
3507         log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3508         return;
3509     }
3510     resIndex = ures_open(NULL,"res_index", &status);
3511     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3512 
3513         const char* oldLoc = LOCALE_ALIAS[i][0];
3514         const char* newLoc = LOCALE_ALIAS[i][1];
3515         if(!isLocaleAvailable(resIndex, newLoc)){
3516             continue;
3517         }
3518         rb1 = ures_open(NULL, oldLoc, &status);
3519         if (U_FAILURE(status)) {
3520             log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3521         }
3522 
3523         us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status);
3524 
3525         status = U_ZERO_ERROR;
3526         rb2 = ures_open(NULL, newLoc, &status);
3527         if (U_FAILURE(status)) {
3528             log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3529         }
3530         us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status);
3531 
3532         if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
3533             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3534         }
3535 
3536         log_verbose("ures_getStringByKey old:%s   new:%s\n", us1, us2);
3537         ures_close(rb1);
3538         rb1 = NULL;
3539         ures_close(rb2);
3540         rb2 = NULL;
3541     }
3542     ures_close(resIndex);
3543 }
3544 
TestDisplayName()3545 static void TestDisplayName() {
3546 
3547     UChar oldCountry[256] = {'\0'};
3548     UChar newCountry[256] = {'\0'};
3549     UChar oldLang[256] = {'\0'};
3550     UChar newLang[256] = {'\0'};
3551     char country[256] ={'\0'};
3552     char language[256] ={'\0'};
3553     int32_t capacity = 256;
3554     int i =0;
3555     int j=0;
3556     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3557         const char* oldLoc = LOCALE_ALIAS[i][0];
3558         const char* newLoc = LOCALE_ALIAS[i][1];
3559         UErrorCode status = U_ZERO_ERROR;
3560         int32_t available = uloc_countAvailable();
3561 
3562         for(j=0; j<available; j++){
3563 
3564             const char* dispLoc = uloc_getAvailable(j);
3565             int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
3566             int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
3567             int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
3568             int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
3569 
3570             int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
3571             int32_t langLen  = uloc_getLanguage(newLoc, language, capacity, &status);
3572             /* there is a display name for the current country ID */
3573             if(countryLen != newCountryLen ){
3574                 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
3575                     log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
3576                 }
3577             }
3578             /* there is a display name for the current lang ID */
3579             if(langLen!=newLangLen){
3580                 if(u_strncmp(oldLang,newLang,oldLangLen)){
3581                     log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc);                }
3582             }
3583         }
3584     }
3585 }
3586 
TestGetLocaleForLCID()3587 static void TestGetLocaleForLCID() {
3588     int32_t i, length, lengthPre;
3589     const char* testLocale = 0;
3590     UErrorCode status = U_ZERO_ERROR;
3591     char            temp2[40], temp3[40];
3592     uint32_t lcid;
3593 
3594     lcid = uloc_getLCID("en_US");
3595     if (lcid != 0x0409) {
3596         log_err("  uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
3597     }
3598 
3599     lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
3600     if (status != U_BUFFER_OVERFLOW_ERROR) {
3601         log_err("  unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
3602     }
3603     else {
3604         status = U_ZERO_ERROR;
3605     }
3606 
3607     length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3608     if (U_FAILURE(status)) {
3609         log_err("  unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
3610         status = U_ZERO_ERROR;
3611     }
3612 
3613     if (length != lengthPre) {
3614         log_err("  uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
3615     }
3616 
3617     length = uloc_getLocaleForLCID(0x12345, temp2, UPRV_LENGTHOF(temp2), &status);
3618     if (U_SUCCESS(status)) {
3619         log_err("  unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
3620     }
3621     status = U_ZERO_ERROR;
3622 
3623     log_verbose("Testing getLocaleForLCID vs. locale data\n");
3624     for (i = 0; i < LOCALE_SIZE; i++) {
3625 
3626         testLocale=rawData2[NAME][i];
3627 
3628         log_verbose("Testing   %s ......\n", testLocale);
3629 
3630         sscanf(rawData2[LCID][i], "%x", &lcid);
3631         length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3632         if (U_FAILURE(status)) {
3633             log_err("  unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
3634             status = U_ZERO_ERROR;
3635             continue;
3636         }
3637 
3638         if (length != (int32_t)uprv_strlen(temp2)) {
3639             log_err("  returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
3640         }
3641 
3642         /* Compare language, country, script */
3643         length = uloc_getLanguage(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3644         if (U_FAILURE(status)) {
3645             log_err("  couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3646             status = U_ZERO_ERROR;
3647         }
3648         else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
3649             log_err("  language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
3650         }
3651 
3652         length = uloc_getScript(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3653         if (U_FAILURE(status)) {
3654             log_err("  couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3655             status = U_ZERO_ERROR;
3656         }
3657         else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
3658             log_err("  script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
3659         }
3660 
3661         length = uloc_getCountry(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3662         if (U_FAILURE(status)) {
3663             log_err("  couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3664             status = U_ZERO_ERROR;
3665         }
3666         else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
3667             log_err("  country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
3668         }
3669     }
3670 
3671 }
3672 
3673 const char* const basic_maximize_data[][2] = {
3674   {
3675     "zu_Zzzz_Zz",
3676     "zu_Latn_ZA",
3677   }, {
3678     "ZU_Zz",
3679     "zu_Latn_ZA"
3680   }, {
3681     "zu_LATN",
3682     "zu_Latn_ZA"
3683   }, {
3684     "en_Zz",
3685     "en_Latn_US"
3686   }, {
3687     "en_us",
3688     "en_Latn_US"
3689   }, {
3690     "en_Kore",
3691     "en_Kore_US"
3692   }, {
3693     "en_Kore_Zz",
3694     "en_Kore_US"
3695   }, {
3696     "en_Kore_ZA",
3697     "en_Kore_ZA"
3698   }, {
3699     "en_Kore_ZA_POSIX",
3700     "en_Kore_ZA_POSIX"
3701   }, {
3702     "en_Gujr",
3703     "en_Gujr_US"
3704   }, {
3705     "en_ZA",
3706     "en_Latn_ZA"
3707   }, {
3708     "en_Gujr_Zz",
3709     "en_Gujr_US"
3710   }, {
3711     "en_Gujr_ZA",
3712     "en_Gujr_ZA"
3713   }, {
3714     "en_Gujr_ZA_POSIX",
3715     "en_Gujr_ZA_POSIX"
3716   }, {
3717     "en_US_POSIX_1901",
3718     "en_Latn_US_POSIX_1901"
3719   }, {
3720     "en_Latn__POSIX_1901",
3721     "en_Latn_US_POSIX_1901"
3722   }, {
3723     "en__POSIX_1901",
3724     "en_Latn_US_POSIX_1901"
3725   }, {
3726     "de__POSIX_1901",
3727     "de_Latn_DE_POSIX_1901"
3728   }, {
3729     "en_US_BOSTON",
3730     "en_Latn_US_BOSTON"
3731   }, {
3732     "th@calendar=buddhist",
3733     "th_Thai_TH@calendar=buddhist"
3734   }, {
3735     "ar_ZZ",
3736     "ar_Arab_EG"
3737   }, {
3738     "zh",
3739     "zh_Hans_CN"
3740   }, {
3741     "zh_TW",
3742     "zh_Hant_TW"
3743   }, {
3744     "zh_HK",
3745     "zh_Hant_HK"
3746   }, {
3747     "zh_Hant",
3748     "zh_Hant_TW"
3749   }, {
3750     "zh_Zzzz_CN",
3751     "zh_Hans_CN"
3752   }, {
3753     "und_US",
3754     "en_Latn_US"
3755   }, {
3756     "und_HK",
3757     "zh_Hant_HK"
3758   }, {
3759     "zzz",
3760     ""
3761   }, {
3762      "de_u_co_phonebk",
3763      "de_Latn_DE@collation=phonebook"
3764   }, {
3765      "de_Latn_u_co_phonebk",
3766       "de_Latn_DE@collation=phonebook"
3767   }, {
3768      "de_Latn_DE_u_co_phonebk",
3769       "de_Latn_DE@collation=phonebook"
3770   }, {
3771     "_Arab@em=emoji",
3772     "ar_Arab_EG@em=emoji"
3773   }, {
3774     "_Latn@em=emoji",
3775     "en_Latn_US@em=emoji"
3776   }, {
3777     "_Latn_DE@em=emoji",
3778     "de_Latn_DE@em=emoji"
3779   }, {
3780     "_Zzzz_DE@em=emoji",
3781     "de_Latn_DE@em=emoji"
3782   }, {
3783     "_DE@em=emoji",
3784     "de_Latn_DE@em=emoji"
3785   }
3786 };
3787 
3788 const char* const basic_minimize_data[][2] = {
3789   {
3790     "en_Latn_US",
3791     "en"
3792   }, {
3793     "en_Latn_US_POSIX_1901",
3794     "en__POSIX_1901"
3795   }, {
3796     "EN_Latn_US_POSIX_1901",
3797     "en__POSIX_1901"
3798   }, {
3799     "en_Zzzz_US_POSIX_1901",
3800     "en__POSIX_1901"
3801   }, {
3802     "de_Latn_DE_POSIX_1901",
3803     "de__POSIX_1901"
3804   }, {
3805     "zzz",
3806     ""
3807   }, {
3808     "en_Latn_US@calendar=gregorian",
3809     "en@calendar=gregorian"
3810   }
3811 };
3812 
3813 const char* const full_data[][3] = {
3814   {
3815     /*   "FROM", */
3816     /*   "ADD-LIKELY", */
3817     /*   "REMOVE-LIKELY" */
3818     /* }, { */
3819     "aa",
3820     "aa_Latn_ET",
3821     "aa"
3822   }, {
3823     "af",
3824     "af_Latn_ZA",
3825     "af"
3826   }, {
3827     "ak",
3828     "ak_Latn_GH",
3829     "ak"
3830   }, {
3831     "am",
3832     "am_Ethi_ET",
3833     "am"
3834   }, {
3835     "ar",
3836     "ar_Arab_EG",
3837     "ar"
3838   }, {
3839     "as",
3840     "as_Beng_IN",
3841     "as"
3842   }, {
3843     "az",
3844     "az_Latn_AZ",
3845     "az"
3846   }, {
3847     "be",
3848     "be_Cyrl_BY",
3849     "be"
3850   }, {
3851     "bg",
3852     "bg_Cyrl_BG",
3853     "bg"
3854   }, {
3855     "bn",
3856     "bn_Beng_BD",
3857     "bn"
3858   }, {
3859     "bo",
3860     "bo_Tibt_CN",
3861     "bo"
3862   }, {
3863     "bs",
3864     "bs_Latn_BA",
3865     "bs"
3866   }, {
3867     "ca",
3868     "ca_Latn_ES",
3869     "ca"
3870   }, {
3871     "ch",
3872     "ch_Latn_GU",
3873     "ch"
3874   }, {
3875     "chk",
3876     "chk_Latn_FM",
3877     "chk"
3878   }, {
3879     "cs",
3880     "cs_Latn_CZ",
3881     "cs"
3882   }, {
3883     "cy",
3884     "cy_Latn_GB",
3885     "cy"
3886   }, {
3887     "da",
3888     "da_Latn_DK",
3889     "da"
3890   }, {
3891     "de",
3892     "de_Latn_DE",
3893     "de"
3894   }, {
3895     "dv",
3896     "dv_Thaa_MV",
3897     "dv"
3898   }, {
3899     "dz",
3900     "dz_Tibt_BT",
3901     "dz"
3902   }, {
3903     "ee",
3904     "ee_Latn_GH",
3905     "ee"
3906   }, {
3907     "el",
3908     "el_Grek_GR",
3909     "el"
3910   }, {
3911     "en",
3912     "en_Latn_US",
3913     "en"
3914   }, {
3915     "es",
3916     "es_Latn_ES",
3917     "es"
3918   }, {
3919     "et",
3920     "et_Latn_EE",
3921     "et"
3922   }, {
3923     "eu",
3924     "eu_Latn_ES",
3925     "eu"
3926   }, {
3927     "fa",
3928     "fa_Arab_IR",
3929     "fa"
3930   }, {
3931     "fi",
3932     "fi_Latn_FI",
3933     "fi"
3934   }, {
3935     "fil",
3936     "fil_Latn_PH",
3937     "fil"
3938   }, {
3939     "fo",
3940     "fo_Latn_FO",
3941     "fo"
3942   }, {
3943     "fr",
3944     "fr_Latn_FR",
3945     "fr"
3946   }, {
3947     "fur",
3948     "fur_Latn_IT",
3949     "fur"
3950   }, {
3951     "ga",
3952     "ga_Latn_IE",
3953     "ga"
3954   }, {
3955     "gaa",
3956     "gaa_Latn_GH",
3957     "gaa"
3958   }, {
3959     "gl",
3960     "gl_Latn_ES",
3961     "gl"
3962   }, {
3963     "gn",
3964     "gn_Latn_PY",
3965     "gn"
3966   }, {
3967     "gu",
3968     "gu_Gujr_IN",
3969     "gu"
3970   }, {
3971     "ha",
3972     "ha_Latn_NG",
3973     "ha"
3974   }, {
3975     "haw",
3976     "haw_Latn_US",
3977     "haw"
3978   }, {
3979     "he",
3980     "he_Hebr_IL",
3981     "he"
3982   }, {
3983     "hi",
3984     "hi_Deva_IN",
3985     "hi"
3986   }, {
3987     "hr",
3988     "hr_Latn_HR",
3989     "hr"
3990   }, {
3991     "ht",
3992     "ht_Latn_HT",
3993     "ht"
3994   }, {
3995     "hu",
3996     "hu_Latn_HU",
3997     "hu"
3998   }, {
3999     "hy",
4000     "hy_Armn_AM",
4001     "hy"
4002   }, {
4003     "id",
4004     "id_Latn_ID",
4005     "id"
4006   }, {
4007     "ig",
4008     "ig_Latn_NG",
4009     "ig"
4010   }, {
4011     "ii",
4012     "ii_Yiii_CN",
4013     "ii"
4014   }, {
4015     "is",
4016     "is_Latn_IS",
4017     "is"
4018   }, {
4019     "it",
4020     "it_Latn_IT",
4021     "it"
4022   }, {
4023     "ja",
4024     "ja_Jpan_JP",
4025     "ja"
4026   }, {
4027     "ka",
4028     "ka_Geor_GE",
4029     "ka"
4030   }, {
4031     "kaj",
4032     "kaj_Latn_NG",
4033     "kaj"
4034   }, {
4035     "kam",
4036     "kam_Latn_KE",
4037     "kam"
4038   }, {
4039     "kk",
4040     "kk_Cyrl_KZ",
4041     "kk"
4042   }, {
4043     "kl",
4044     "kl_Latn_GL",
4045     "kl"
4046   }, {
4047     "km",
4048     "km_Khmr_KH",
4049     "km"
4050   }, {
4051     "kn",
4052     "kn_Knda_IN",
4053     "kn"
4054   }, {
4055     "ko",
4056     "ko_Kore_KR",
4057     "ko"
4058   }, {
4059     "kok",
4060     "kok_Deva_IN",
4061     "kok"
4062   }, {
4063     "kpe",
4064     "kpe_Latn_LR",
4065     "kpe"
4066   }, {
4067     "ku",
4068     "ku_Latn_TR",
4069     "ku"
4070   }, {
4071     "ky",
4072     "ky_Cyrl_KG",
4073     "ky"
4074   }, {
4075     "la",
4076     "la_Latn_VA",
4077     "la"
4078   }, {
4079     "ln",
4080     "ln_Latn_CD",
4081     "ln"
4082   }, {
4083     "lo",
4084     "lo_Laoo_LA",
4085     "lo"
4086   }, {
4087     "lt",
4088     "lt_Latn_LT",
4089     "lt"
4090   }, {
4091     "lv",
4092     "lv_Latn_LV",
4093     "lv"
4094   }, {
4095     "mg",
4096     "mg_Latn_MG",
4097     "mg"
4098   }, {
4099     "mh",
4100     "mh_Latn_MH",
4101     "mh"
4102   }, {
4103     "mk",
4104     "mk_Cyrl_MK",
4105     "mk"
4106   }, {
4107     "ml",
4108     "ml_Mlym_IN",
4109     "ml"
4110   }, {
4111     "mn",
4112     "mn_Cyrl_MN",
4113     "mn"
4114   }, {
4115     "mr",
4116     "mr_Deva_IN",
4117     "mr"
4118   }, {
4119     "ms",
4120     "ms_Latn_MY",
4121     "ms"
4122   }, {
4123     "mt",
4124     "mt_Latn_MT",
4125     "mt"
4126   }, {
4127     "my",
4128     "my_Mymr_MM",
4129     "my"
4130   }, {
4131     "na",
4132     "na_Latn_NR",
4133     "na"
4134   }, {
4135     "ne",
4136     "ne_Deva_NP",
4137     "ne"
4138   }, {
4139     "niu",
4140     "niu_Latn_NU",
4141     "niu"
4142   }, {
4143     "nl",
4144     "nl_Latn_NL",
4145     "nl"
4146   }, {
4147     "nn",
4148     "nn_Latn_NO",
4149     "nn"
4150   }, {
4151     "no",
4152     "no_Latn_NO",
4153     "no"
4154   }, {
4155     "nr",
4156     "nr_Latn_ZA",
4157     "nr"
4158   }, {
4159     "nso",
4160     "nso_Latn_ZA",
4161     "nso"
4162   }, {
4163     "ny",
4164     "ny_Latn_MW",
4165     "ny"
4166   }, {
4167     "om",
4168     "om_Latn_ET",
4169     "om"
4170   }, {
4171     "or",
4172     "or_Orya_IN",
4173     "or"
4174   }, {
4175     "pa",
4176     "pa_Guru_IN",
4177     "pa"
4178   }, {
4179     "pa_Arab",
4180     "pa_Arab_PK",
4181     "pa_PK"
4182   }, {
4183     "pa_PK",
4184     "pa_Arab_PK",
4185     "pa_PK"
4186   }, {
4187     "pap",
4188     "pap_Latn_CW",
4189     "pap"
4190   }, {
4191     "pau",
4192     "pau_Latn_PW",
4193     "pau"
4194   }, {
4195     "pl",
4196     "pl_Latn_PL",
4197     "pl"
4198   }, {
4199     "ps",
4200     "ps_Arab_AF",
4201     "ps"
4202   }, {
4203     "pt",
4204     "pt_Latn_BR",
4205     "pt"
4206   }, {
4207     "rn",
4208     "rn_Latn_BI",
4209     "rn"
4210   }, {
4211     "ro",
4212     "ro_Latn_RO",
4213     "ro"
4214   }, {
4215     "ru",
4216     "ru_Cyrl_RU",
4217     "ru"
4218   }, {
4219     "rw",
4220     "rw_Latn_RW",
4221     "rw"
4222   }, {
4223     "sa",
4224     "sa_Deva_IN",
4225     "sa"
4226   }, {
4227     "se",
4228     "se_Latn_NO",
4229     "se"
4230   }, {
4231     "sg",
4232     "sg_Latn_CF",
4233     "sg"
4234   }, {
4235     "si",
4236     "si_Sinh_LK",
4237     "si"
4238   }, {
4239     "sid",
4240     "sid_Latn_ET",
4241     "sid"
4242   }, {
4243     "sk",
4244     "sk_Latn_SK",
4245     "sk"
4246   }, {
4247     "sl",
4248     "sl_Latn_SI",
4249     "sl"
4250   }, {
4251     "sm",
4252     "sm_Latn_WS",
4253     "sm"
4254   }, {
4255     "so",
4256     "so_Latn_SO",
4257     "so"
4258   }, {
4259     "sq",
4260     "sq_Latn_AL",
4261     "sq"
4262   }, {
4263     "sr",
4264     "sr_Cyrl_RS",
4265     "sr"
4266   }, {
4267     "ss",
4268     "ss_Latn_ZA",
4269     "ss"
4270   }, {
4271     "st",
4272     "st_Latn_ZA",
4273     "st"
4274   }, {
4275     "sv",
4276     "sv_Latn_SE",
4277     "sv"
4278   }, {
4279     "sw",
4280     "sw_Latn_TZ",
4281     "sw"
4282   }, {
4283     "ta",
4284     "ta_Taml_IN",
4285     "ta"
4286   }, {
4287     "te",
4288     "te_Telu_IN",
4289     "te"
4290   }, {
4291     "tet",
4292     "tet_Latn_TL",
4293     "tet"
4294   }, {
4295     "tg",
4296     "tg_Cyrl_TJ",
4297     "tg"
4298   }, {
4299     "th",
4300     "th_Thai_TH",
4301     "th"
4302   }, {
4303     "ti",
4304     "ti_Ethi_ET",
4305     "ti"
4306   }, {
4307     "tig",
4308     "tig_Ethi_ER",
4309     "tig"
4310   }, {
4311     "tk",
4312     "tk_Latn_TM",
4313     "tk"
4314   }, {
4315     "tkl",
4316     "tkl_Latn_TK",
4317     "tkl"
4318   }, {
4319     "tn",
4320     "tn_Latn_ZA",
4321     "tn"
4322   }, {
4323     "to",
4324     "to_Latn_TO",
4325     "to"
4326   }, {
4327     "tpi",
4328     "tpi_Latn_PG",
4329     "tpi"
4330   }, {
4331     "tr",
4332     "tr_Latn_TR",
4333     "tr"
4334   }, {
4335     "ts",
4336     "ts_Latn_ZA",
4337     "ts"
4338   }, {
4339     "tt",
4340     "tt_Cyrl_RU",
4341     "tt"
4342   }, {
4343     "tvl",
4344     "tvl_Latn_TV",
4345     "tvl"
4346   }, {
4347     "ty",
4348     "ty_Latn_PF",
4349     "ty"
4350   }, {
4351     "uk",
4352     "uk_Cyrl_UA",
4353     "uk"
4354   }, {
4355     "und",
4356     "en_Latn_US",
4357     "en"
4358   }, {
4359     "und_AD",
4360     "ca_Latn_AD",
4361     "ca_AD"
4362   }, {
4363     "und_AE",
4364     "ar_Arab_AE",
4365     "ar_AE"
4366   }, {
4367     "und_AF",
4368     "fa_Arab_AF",
4369     "fa_AF"
4370   }, {
4371     "und_AL",
4372     "sq_Latn_AL",
4373     "sq"
4374   }, {
4375     "und_AM",
4376     "hy_Armn_AM",
4377     "hy"
4378   }, {
4379     "und_AO",
4380     "pt_Latn_AO",
4381     "pt_AO"
4382   }, {
4383     "und_AR",
4384     "es_Latn_AR",
4385     "es_AR"
4386   }, {
4387     "und_AS",
4388     "sm_Latn_AS",
4389     "sm_AS"
4390   }, {
4391     "und_AT",
4392     "de_Latn_AT",
4393     "de_AT"
4394   }, {
4395     "und_AW",
4396     "nl_Latn_AW",
4397     "nl_AW"
4398   }, {
4399     "und_AX",
4400     "sv_Latn_AX",
4401     "sv_AX"
4402   }, {
4403     "und_AZ",
4404     "az_Latn_AZ",
4405     "az"
4406   }, {
4407     "und_Arab",
4408     "ar_Arab_EG",
4409     "ar"
4410   }, {
4411     "und_Arab_IN",
4412     "ur_Arab_IN",
4413     "ur_IN"
4414   }, {
4415     "und_Arab_PK",
4416     "ur_Arab_PK",
4417     "ur"
4418   }, {
4419     "und_Arab_SN",
4420     "ar_Arab_SN",
4421     "ar_SN"
4422   }, {
4423     "und_Armn",
4424     "hy_Armn_AM",
4425     "hy"
4426   }, {
4427     "und_BA",
4428     "bs_Latn_BA",
4429     "bs"
4430   }, {
4431     "und_BD",
4432     "bn_Beng_BD",
4433     "bn"
4434   }, {
4435     "und_BE",
4436     "nl_Latn_BE",
4437     "nl_BE"
4438   }, {
4439     "und_BF",
4440     "fr_Latn_BF",
4441     "fr_BF"
4442   }, {
4443     "und_BG",
4444     "bg_Cyrl_BG",
4445     "bg"
4446   }, {
4447     "und_BH",
4448     "ar_Arab_BH",
4449     "ar_BH"
4450   }, {
4451     "und_BI",
4452     "rn_Latn_BI",
4453     "rn"
4454   }, {
4455     "und_BJ",
4456     "fr_Latn_BJ",
4457     "fr_BJ"
4458   }, {
4459     "und_BN",
4460     "ms_Latn_BN",
4461     "ms_BN"
4462   }, {
4463     "und_BO",
4464     "es_Latn_BO",
4465     "es_BO"
4466   }, {
4467     "und_BR",
4468     "pt_Latn_BR",
4469     "pt"
4470   }, {
4471     "und_BT",
4472     "dz_Tibt_BT",
4473     "dz"
4474   }, {
4475     "und_BY",
4476     "be_Cyrl_BY",
4477     "be"
4478   }, {
4479     "und_Beng",
4480     "bn_Beng_BD",
4481     "bn"
4482   }, {
4483     "und_Beng_IN",
4484     "bn_Beng_IN",
4485     "bn_IN"
4486   }, {
4487     "und_CD",
4488     "sw_Latn_CD",
4489     "sw_CD"
4490   }, {
4491     "und_CF",
4492     "fr_Latn_CF",
4493     "fr_CF"
4494   }, {
4495     "und_CG",
4496     "fr_Latn_CG",
4497     "fr_CG"
4498   }, {
4499     "und_CH",
4500     "de_Latn_CH",
4501     "de_CH"
4502   }, {
4503     "und_CI",
4504     "fr_Latn_CI",
4505     "fr_CI"
4506   }, {
4507     "und_CL",
4508     "es_Latn_CL",
4509     "es_CL"
4510   }, {
4511     "und_CM",
4512     "fr_Latn_CM",
4513     "fr_CM"
4514   }, {
4515     "und_CN",
4516     "zh_Hans_CN",
4517     "zh"
4518   }, {
4519     "und_CO",
4520     "es_Latn_CO",
4521     "es_CO"
4522   }, {
4523     "und_CR",
4524     "es_Latn_CR",
4525     "es_CR"
4526   }, {
4527     "und_CU",
4528     "es_Latn_CU",
4529     "es_CU"
4530   }, {
4531     "und_CV",
4532     "pt_Latn_CV",
4533     "pt_CV"
4534   }, {
4535     "und_CY",
4536     "el_Grek_CY",
4537     "el_CY"
4538   }, {
4539     "und_CZ",
4540     "cs_Latn_CZ",
4541     "cs"
4542   }, {
4543     "und_Cher",
4544     "chr_Cher_US",
4545     "chr"
4546   }, {
4547     "und_Cyrl",
4548     "ru_Cyrl_RU",
4549     "ru"
4550   }, {
4551     "und_Cyrl_KZ",
4552     "ru_Cyrl_KZ",
4553     "ru_KZ"
4554   }, {
4555     "und_DE",
4556     "de_Latn_DE",
4557     "de"
4558   }, {
4559     "und_DJ",
4560     "aa_Latn_DJ",
4561     "aa_DJ"
4562   }, {
4563     "und_DK",
4564     "da_Latn_DK",
4565     "da"
4566   }, {
4567     "und_DO",
4568     "es_Latn_DO",
4569     "es_DO"
4570   }, {
4571     "und_DZ",
4572     "ar_Arab_DZ",
4573     "ar_DZ"
4574   }, {
4575     "und_Deva",
4576     "hi_Deva_IN",
4577     "hi"
4578   }, {
4579     "und_EC",
4580     "es_Latn_EC",
4581     "es_EC"
4582   }, {
4583     "und_EE",
4584     "et_Latn_EE",
4585     "et"
4586   }, {
4587     "und_EG",
4588     "ar_Arab_EG",
4589     "ar"
4590   }, {
4591     "und_EH",
4592     "ar_Arab_EH",
4593     "ar_EH"
4594   }, {
4595     "und_ER",
4596     "ti_Ethi_ER",
4597     "ti_ER"
4598   }, {
4599     "und_ES",
4600     "es_Latn_ES",
4601     "es"
4602   }, {
4603     "und_ET",
4604     "am_Ethi_ET",
4605     "am"
4606   }, {
4607     "und_Ethi",
4608     "am_Ethi_ET",
4609     "am"
4610   }, {
4611     "und_Ethi_ER",
4612     "am_Ethi_ER",
4613     "am_ER"
4614   }, {
4615     "und_FI",
4616     "fi_Latn_FI",
4617     "fi"
4618   }, {
4619     "und_FM",
4620     "en_Latn_FM",
4621     "en_FM"
4622   }, {
4623     "und_FO",
4624     "fo_Latn_FO",
4625     "fo"
4626   }, {
4627     "und_FR",
4628     "fr_Latn_FR",
4629     "fr"
4630   }, {
4631     "und_GA",
4632     "fr_Latn_GA",
4633     "fr_GA"
4634   }, {
4635     "und_GE",
4636     "ka_Geor_GE",
4637     "ka"
4638   }, {
4639     "und_GF",
4640     "fr_Latn_GF",
4641     "fr_GF"
4642   }, {
4643     "und_GL",
4644     "kl_Latn_GL",
4645     "kl"
4646   }, {
4647     "und_GN",
4648     "fr_Latn_GN",
4649     "fr_GN"
4650   }, {
4651     "und_GP",
4652     "fr_Latn_GP",
4653     "fr_GP"
4654   }, {
4655     "und_GQ",
4656     "es_Latn_GQ",
4657     "es_GQ"
4658   }, {
4659     "und_GR",
4660     "el_Grek_GR",
4661     "el"
4662   }, {
4663     "und_GT",
4664     "es_Latn_GT",
4665     "es_GT"
4666   }, {
4667     "und_GU",
4668     "en_Latn_GU",
4669     "en_GU"
4670   }, {
4671     "und_GW",
4672     "pt_Latn_GW",
4673     "pt_GW"
4674   }, {
4675     "und_Geor",
4676     "ka_Geor_GE",
4677     "ka"
4678   }, {
4679     "und_Grek",
4680     "el_Grek_GR",
4681     "el"
4682   }, {
4683     "und_Gujr",
4684     "gu_Gujr_IN",
4685     "gu"
4686   }, {
4687     "und_Guru",
4688     "pa_Guru_IN",
4689     "pa"
4690   }, {
4691     "und_HK",
4692     "zh_Hant_HK",
4693     "zh_HK"
4694   }, {
4695     "und_HN",
4696     "es_Latn_HN",
4697     "es_HN"
4698   }, {
4699     "und_HR",
4700     "hr_Latn_HR",
4701     "hr"
4702   }, {
4703     "und_HT",
4704     "ht_Latn_HT",
4705     "ht"
4706   }, {
4707     "und_HU",
4708     "hu_Latn_HU",
4709     "hu"
4710   }, {
4711     "und_Hani",
4712     "zh_Hani_CN",
4713     "zh_Hani"
4714   }, {
4715     "und_Hans",
4716     "zh_Hans_CN",
4717     "zh"
4718   }, {
4719     "und_Hant",
4720     "zh_Hant_TW",
4721     "zh_TW"
4722   }, {
4723     "und_Hebr",
4724     "he_Hebr_IL",
4725     "he"
4726   }, {
4727     "und_IL",
4728     "he_Hebr_IL",
4729     "he"
4730   }, {
4731     "und_IN",
4732     "hi_Deva_IN",
4733     "hi"
4734   }, {
4735     "und_IQ",
4736     "ar_Arab_IQ",
4737     "ar_IQ"
4738   }, {
4739     "und_IR",
4740     "fa_Arab_IR",
4741     "fa"
4742   }, {
4743     "und_IS",
4744     "is_Latn_IS",
4745     "is"
4746   }, {
4747     "und_IT",
4748     "it_Latn_IT",
4749     "it"
4750   }, {
4751     "und_JO",
4752     "ar_Arab_JO",
4753     "ar_JO"
4754   }, {
4755     "und_JP",
4756     "ja_Jpan_JP",
4757     "ja"
4758   }, {
4759     "und_Jpan",
4760     "ja_Jpan_JP",
4761     "ja"
4762   }, {
4763     "und_KG",
4764     "ky_Cyrl_KG",
4765     "ky"
4766   }, {
4767     "und_KH",
4768     "km_Khmr_KH",
4769     "km"
4770   }, {
4771     "und_KM",
4772     "ar_Arab_KM",
4773     "ar_KM"
4774   }, {
4775     "und_KP",
4776     "ko_Kore_KP",
4777     "ko_KP"
4778   }, {
4779     "und_KR",
4780     "ko_Kore_KR",
4781     "ko"
4782   }, {
4783     "und_KW",
4784     "ar_Arab_KW",
4785     "ar_KW"
4786   }, {
4787     "und_KZ",
4788     "ru_Cyrl_KZ",
4789     "ru_KZ"
4790   }, {
4791     "und_Khmr",
4792     "km_Khmr_KH",
4793     "km"
4794   }, {
4795     "und_Knda",
4796     "kn_Knda_IN",
4797     "kn"
4798   }, {
4799     "und_Kore",
4800     "ko_Kore_KR",
4801     "ko"
4802   }, {
4803     "und_LA",
4804     "lo_Laoo_LA",
4805     "lo"
4806   }, {
4807     "und_LB",
4808     "ar_Arab_LB",
4809     "ar_LB"
4810   }, {
4811     "und_LI",
4812     "de_Latn_LI",
4813     "de_LI"
4814   }, {
4815     "und_LK",
4816     "si_Sinh_LK",
4817     "si"
4818   }, {
4819     "und_LS",
4820     "st_Latn_LS",
4821     "st_LS"
4822   }, {
4823     "und_LT",
4824     "lt_Latn_LT",
4825     "lt"
4826   }, {
4827     "und_LU",
4828     "fr_Latn_LU",
4829     "fr_LU"
4830   }, {
4831     "und_LV",
4832     "lv_Latn_LV",
4833     "lv"
4834   }, {
4835     "und_LY",
4836     "ar_Arab_LY",
4837     "ar_LY"
4838   }, {
4839     "und_Laoo",
4840     "lo_Laoo_LA",
4841     "lo"
4842   }, {
4843     "und_Latn_ES",
4844     "es_Latn_ES",
4845     "es"
4846   }, {
4847     "und_Latn_ET",
4848     "en_Latn_ET",
4849     "en_ET"
4850   }, {
4851     "und_Latn_GB",
4852     "en_Latn_GB",
4853     "en_GB"
4854   }, {
4855     "und_Latn_GH",
4856     "ak_Latn_GH",
4857     "ak"
4858   }, {
4859     "und_Latn_ID",
4860     "id_Latn_ID",
4861     "id"
4862   }, {
4863     "und_Latn_IT",
4864     "it_Latn_IT",
4865     "it"
4866   }, {
4867     "und_Latn_NG",
4868     "en_Latn_NG",
4869     "en_NG"
4870   }, {
4871     "und_Latn_TR",
4872     "tr_Latn_TR",
4873     "tr"
4874   }, {
4875     "und_Latn_ZA",
4876     "en_Latn_ZA",
4877     "en_ZA"
4878   }, {
4879     "und_MA",
4880     "ar_Arab_MA",
4881     "ar_MA"
4882   }, {
4883     "und_MC",
4884     "fr_Latn_MC",
4885     "fr_MC"
4886   }, {
4887     "und_MD",
4888     "ro_Latn_MD",
4889     "ro_MD"
4890   }, {
4891     "und_ME",
4892     "sr_Latn_ME",
4893     "sr_ME"
4894   }, {
4895     "und_MG",
4896     "mg_Latn_MG",
4897     "mg"
4898   }, {
4899     "und_MH",
4900     "en_Latn_MH",
4901     "en_MH"
4902   }, {
4903     "und_MK",
4904     "mk_Cyrl_MK",
4905     "mk"
4906   }, {
4907     "und_ML",
4908     "bm_Latn_ML",
4909     "bm"
4910   }, {
4911     "und_MM",
4912     "my_Mymr_MM",
4913     "my"
4914   }, {
4915     "und_MN",
4916     "mn_Cyrl_MN",
4917     "mn"
4918   }, {
4919     "und_MO",
4920     "zh_Hant_MO",
4921     "zh_MO"
4922   }, {
4923     "und_MQ",
4924     "fr_Latn_MQ",
4925     "fr_MQ"
4926   }, {
4927     "und_MR",
4928     "ar_Arab_MR",
4929     "ar_MR"
4930   }, {
4931     "und_MT",
4932     "mt_Latn_MT",
4933     "mt"
4934   }, {
4935     "und_MV",
4936     "dv_Thaa_MV",
4937     "dv"
4938   }, {
4939     "und_MW",
4940     "en_Latn_MW",
4941     "en_MW"
4942   }, {
4943     "und_MX",
4944     "es_Latn_MX",
4945     "es_MX"
4946   }, {
4947     "und_MY",
4948     "ms_Latn_MY",
4949     "ms"
4950   }, {
4951     "und_MZ",
4952     "pt_Latn_MZ",
4953     "pt_MZ"
4954   }, {
4955     "und_Mlym",
4956     "ml_Mlym_IN",
4957     "ml"
4958   }, {
4959     "und_Mymr",
4960     "my_Mymr_MM",
4961     "my"
4962   }, {
4963     "und_NC",
4964     "fr_Latn_NC",
4965     "fr_NC"
4966   }, {
4967     "und_NE",
4968     "ha_Latn_NE",
4969     "ha_NE"
4970   }, {
4971     "und_NG",
4972     "en_Latn_NG",
4973     "en_NG"
4974   }, {
4975     "und_NI",
4976     "es_Latn_NI",
4977     "es_NI"
4978   }, {
4979     "und_NL",
4980     "nl_Latn_NL",
4981     "nl"
4982   }, {
4983     "und_NO",
4984     "nb_Latn_NO",
4985     "nb"
4986   }, {
4987     "und_NP",
4988     "ne_Deva_NP",
4989     "ne"
4990   }, {
4991     "und_NR",
4992     "en_Latn_NR",
4993     "en_NR"
4994   }, {
4995     "und_NU",
4996     "en_Latn_NU",
4997     "en_NU"
4998   }, {
4999     "und_OM",
5000     "ar_Arab_OM",
5001     "ar_OM"
5002   }, {
5003     "und_Orya",
5004     "or_Orya_IN",
5005     "or"
5006   }, {
5007     "und_PA",
5008     "es_Latn_PA",
5009     "es_PA"
5010   }, {
5011     "und_PE",
5012     "es_Latn_PE",
5013     "es_PE"
5014   }, {
5015     "und_PF",
5016     "fr_Latn_PF",
5017     "fr_PF"
5018   }, {
5019     "und_PG",
5020     "tpi_Latn_PG",
5021     "tpi"
5022   }, {
5023     "und_PH",
5024     "fil_Latn_PH",
5025     "fil"
5026   }, {
5027     "und_PL",
5028     "pl_Latn_PL",
5029     "pl"
5030   }, {
5031     "und_PM",
5032     "fr_Latn_PM",
5033     "fr_PM"
5034   }, {
5035     "und_PR",
5036     "es_Latn_PR",
5037     "es_PR"
5038   }, {
5039     "und_PS",
5040     "ar_Arab_PS",
5041     "ar_PS"
5042   }, {
5043     "und_PT",
5044     "pt_Latn_PT",
5045     "pt_PT"
5046   }, {
5047     "und_PW",
5048     "pau_Latn_PW",
5049     "pau"
5050   }, {
5051     "und_PY",
5052     "gn_Latn_PY",
5053     "gn"
5054   }, {
5055     "und_QA",
5056     "ar_Arab_QA",
5057     "ar_QA"
5058   }, {
5059     "und_RE",
5060     "fr_Latn_RE",
5061     "fr_RE"
5062   }, {
5063     "und_RO",
5064     "ro_Latn_RO",
5065     "ro"
5066   }, {
5067     "und_RS",
5068     "sr_Cyrl_RS",
5069     "sr"
5070   }, {
5071     "und_RU",
5072     "ru_Cyrl_RU",
5073     "ru"
5074   }, {
5075     "und_RW",
5076     "rw_Latn_RW",
5077     "rw"
5078   }, {
5079     "und_SA",
5080     "ar_Arab_SA",
5081     "ar_SA"
5082   }, {
5083     "und_SD",
5084     "ar_Arab_SD",
5085     "ar_SD"
5086   }, {
5087     "und_SE",
5088     "sv_Latn_SE",
5089     "sv"
5090   }, {
5091     "und_SG",
5092     "en_Latn_SG",
5093     "en_SG"
5094   }, {
5095     "und_SI",
5096     "sl_Latn_SI",
5097     "sl"
5098   }, {
5099     "und_SJ",
5100     "nb_Latn_SJ",
5101     "nb_SJ"
5102   }, {
5103     "und_SK",
5104     "sk_Latn_SK",
5105     "sk"
5106   }, {
5107     "und_SM",
5108     "it_Latn_SM",
5109     "it_SM"
5110   }, {
5111     "und_SN",
5112     "fr_Latn_SN",
5113     "fr_SN"
5114   }, {
5115     "und_SO",
5116     "so_Latn_SO",
5117     "so"
5118   }, {
5119     "und_SR",
5120     "nl_Latn_SR",
5121     "nl_SR"
5122   }, {
5123     "und_ST",
5124     "pt_Latn_ST",
5125     "pt_ST"
5126   }, {
5127     "und_SV",
5128     "es_Latn_SV",
5129     "es_SV"
5130   }, {
5131     "und_SY",
5132     "ar_Arab_SY",
5133     "ar_SY"
5134   }, {
5135     "und_Sinh",
5136     "si_Sinh_LK",
5137     "si"
5138   }, {
5139     "und_TD",
5140     "fr_Latn_TD",
5141     "fr_TD"
5142   }, {
5143     "und_TG",
5144     "fr_Latn_TG",
5145     "fr_TG"
5146   }, {
5147     "und_TH",
5148     "th_Thai_TH",
5149     "th"
5150   }, {
5151     "und_TJ",
5152     "tg_Cyrl_TJ",
5153     "tg"
5154   }, {
5155     "und_TK",
5156     "tkl_Latn_TK",
5157     "tkl"
5158   }, {
5159     "und_TL",
5160     "pt_Latn_TL",
5161     "pt_TL"
5162   }, {
5163     "und_TM",
5164     "tk_Latn_TM",
5165     "tk"
5166   }, {
5167     "und_TN",
5168     "ar_Arab_TN",
5169     "ar_TN"
5170   }, {
5171     "und_TO",
5172     "to_Latn_TO",
5173     "to"
5174   }, {
5175     "und_TR",
5176     "tr_Latn_TR",
5177     "tr"
5178   }, {
5179     "und_TV",
5180     "tvl_Latn_TV",
5181     "tvl"
5182   }, {
5183     "und_TW",
5184     "zh_Hant_TW",
5185     "zh_TW"
5186   }, {
5187     "und_Taml",
5188     "ta_Taml_IN",
5189     "ta"
5190   }, {
5191     "und_Telu",
5192     "te_Telu_IN",
5193     "te"
5194   }, {
5195     "und_Thaa",
5196     "dv_Thaa_MV",
5197     "dv"
5198   }, {
5199     "und_Thai",
5200     "th_Thai_TH",
5201     "th"
5202   }, {
5203     "und_Tibt",
5204     "bo_Tibt_CN",
5205     "bo"
5206   }, {
5207     "und_UA",
5208     "uk_Cyrl_UA",
5209     "uk"
5210   }, {
5211     "und_UY",
5212     "es_Latn_UY",
5213     "es_UY"
5214   }, {
5215     "und_UZ",
5216     "uz_Latn_UZ",
5217     "uz"
5218   }, {
5219     "und_VA",
5220     "it_Latn_VA",
5221     "it_VA"
5222   }, {
5223     "und_VE",
5224     "es_Latn_VE",
5225     "es_VE"
5226   }, {
5227     "und_VN",
5228     "vi_Latn_VN",
5229     "vi"
5230   }, {
5231     "und_VU",
5232     "bi_Latn_VU",
5233     "bi"
5234   }, {
5235     "und_WF",
5236     "fr_Latn_WF",
5237     "fr_WF"
5238   }, {
5239     "und_WS",
5240     "sm_Latn_WS",
5241     "sm"
5242   }, {
5243     "und_YE",
5244     "ar_Arab_YE",
5245     "ar_YE"
5246   }, {
5247     "und_YT",
5248     "fr_Latn_YT",
5249     "fr_YT"
5250   }, {
5251     "und_Yiii",
5252     "ii_Yiii_CN",
5253     "ii"
5254   }, {
5255     "ur",
5256     "ur_Arab_PK",
5257     "ur"
5258   }, {
5259     "uz",
5260     "uz_Latn_UZ",
5261     "uz"
5262   }, {
5263     "uz_AF",
5264     "uz_Arab_AF",
5265     "uz_AF"
5266   }, {
5267     "uz_Arab",
5268     "uz_Arab_AF",
5269     "uz_AF"
5270   }, {
5271     "ve",
5272     "ve_Latn_ZA",
5273     "ve"
5274   }, {
5275     "vi",
5276     "vi_Latn_VN",
5277     "vi"
5278   }, {
5279     "wal",
5280     "wal_Ethi_ET",
5281     "wal"
5282   }, {
5283     "wo",
5284     "wo_Latn_SN",
5285     "wo"
5286   }, {
5287     "xh",
5288     "xh_Latn_ZA",
5289     "xh"
5290   }, {
5291     "yo",
5292     "yo_Latn_NG",
5293     "yo"
5294   }, {
5295     "zh",
5296     "zh_Hans_CN",
5297     "zh"
5298   }, {
5299     "zh_HK",
5300     "zh_Hant_HK",
5301     "zh_HK"
5302   }, {
5303     "zh_Hani",
5304     "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
5305     "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5306   }, {
5307     "zh_Hant",
5308     "zh_Hant_TW",
5309     "zh_TW"
5310   }, {
5311     "zh_MO",
5312     "zh_Hant_MO",
5313     "zh_MO"
5314   }, {
5315     "zh_TW",
5316     "zh_Hant_TW",
5317     "zh_TW"
5318   }, {
5319     "zu",
5320     "zu_Latn_ZA",
5321     "zu"
5322   }, {
5323     "und",
5324     "en_Latn_US",
5325     "en"
5326   }, {
5327     "und_ZZ",
5328     "en_Latn_US",
5329     "en"
5330   }, {
5331     "und_CN",
5332     "zh_Hans_CN",
5333     "zh"
5334   }, {
5335     "und_TW",
5336     "zh_Hant_TW",
5337     "zh_TW"
5338   }, {
5339     "und_HK",
5340     "zh_Hant_HK",
5341     "zh_HK"
5342   }, {
5343     "und_AQ",
5344     "_Latn_AQ",
5345     "_AQ"
5346   }, {
5347     "und_Zzzz",
5348     "en_Latn_US",
5349     "en"
5350   }, {
5351     "und_Zzzz_ZZ",
5352     "en_Latn_US",
5353     "en"
5354   }, {
5355     "und_Zzzz_CN",
5356     "zh_Hans_CN",
5357     "zh"
5358   }, {
5359     "und_Zzzz_TW",
5360     "zh_Hant_TW",
5361     "zh_TW"
5362   }, {
5363     "und_Zzzz_HK",
5364     "zh_Hant_HK",
5365     "zh_HK"
5366   }, {
5367     "und_Zzzz_AQ",
5368     "_Latn_AQ",
5369     "_AQ"
5370   }, {
5371     "und_Latn",
5372     "en_Latn_US",
5373     "en"
5374   }, {
5375     "und_Latn_ZZ",
5376     "en_Latn_US",
5377     "en"
5378   }, {
5379     "und_Latn_CN",
5380     "za_Latn_CN",
5381     "za"
5382   }, {
5383     "und_Latn_TW",
5384     "trv_Latn_TW",
5385     "trv"
5386   }, {
5387     "und_Latn_HK",
5388     "zh_Latn_HK",
5389     "zh_Latn_HK"
5390   }, {
5391     "und_Latn_AQ",
5392     "_Latn_AQ",
5393     "_AQ"
5394   }, {
5395     "und_Hans",
5396     "zh_Hans_CN",
5397     "zh"
5398   }, {
5399     "und_Hans_ZZ",
5400     "zh_Hans_CN",
5401     "zh"
5402   }, {
5403     "und_Hans_CN",
5404     "zh_Hans_CN",
5405     "zh"
5406   }, {
5407     "und_Hans_TW",
5408     "zh_Hans_TW",
5409     "zh_Hans_TW"
5410   }, {
5411     "und_Hans_HK",
5412     "zh_Hans_HK",
5413     "zh_Hans_HK"
5414   }, {
5415     "und_Hans_AQ",
5416     "zh_Hans_AQ",
5417     "zh_AQ"
5418   }, {
5419     "und_Hant",
5420     "zh_Hant_TW",
5421     "zh_TW"
5422   }, {
5423     "und_Hant_ZZ",
5424     "zh_Hant_TW",
5425     "zh_TW"
5426   }, {
5427     "und_Hant_CN",
5428     "zh_Hant_CN",
5429     "zh_Hant_CN"
5430   }, {
5431     "und_Hant_TW",
5432     "zh_Hant_TW",
5433     "zh_TW"
5434   }, {
5435     "und_Hant_HK",
5436     "zh_Hant_HK",
5437     "zh_HK"
5438   }, {
5439     "und_Hant_AQ",
5440     "zh_Hant_AQ",
5441     "zh_Hant_AQ"
5442   }, {
5443     "und_Moon",
5444     "en_Moon_US",
5445     "en_Moon"
5446   }, {
5447     "und_Moon_ZZ",
5448     "en_Moon_US",
5449     "en_Moon"
5450   }, {
5451     "und_Moon_CN",
5452     "zh_Moon_CN",
5453     "zh_Moon"
5454   }, {
5455     "und_Moon_TW",
5456     "zh_Moon_TW",
5457     "zh_Moon_TW"
5458   }, {
5459     "und_Moon_HK",
5460     "zh_Moon_HK",
5461     "zh_Moon_HK"
5462   }, {
5463     "und_Moon_AQ",
5464     "_Moon_AQ",
5465     "_Moon_AQ"
5466   }, {
5467     "es",
5468     "es_Latn_ES",
5469     "es"
5470   }, {
5471     "es_ZZ",
5472     "es_Latn_ES",
5473     "es"
5474   }, {
5475     "es_CN",
5476     "es_Latn_CN",
5477     "es_CN"
5478   }, {
5479     "es_TW",
5480     "es_Latn_TW",
5481     "es_TW"
5482   }, {
5483     "es_HK",
5484     "es_Latn_HK",
5485     "es_HK"
5486   }, {
5487     "es_AQ",
5488     "es_Latn_AQ",
5489     "es_AQ"
5490   }, {
5491     "es_Zzzz",
5492     "es_Latn_ES",
5493     "es"
5494   }, {
5495     "es_Zzzz_ZZ",
5496     "es_Latn_ES",
5497     "es"
5498   }, {
5499     "es_Zzzz_CN",
5500     "es_Latn_CN",
5501     "es_CN"
5502   }, {
5503     "es_Zzzz_TW",
5504     "es_Latn_TW",
5505     "es_TW"
5506   }, {
5507     "es_Zzzz_HK",
5508     "es_Latn_HK",
5509     "es_HK"
5510   }, {
5511     "es_Zzzz_AQ",
5512     "es_Latn_AQ",
5513     "es_AQ"
5514   }, {
5515     "es_Latn",
5516     "es_Latn_ES",
5517     "es"
5518   }, {
5519     "es_Latn_ZZ",
5520     "es_Latn_ES",
5521     "es"
5522   }, {
5523     "es_Latn_CN",
5524     "es_Latn_CN",
5525     "es_CN"
5526   }, {
5527     "es_Latn_TW",
5528     "es_Latn_TW",
5529     "es_TW"
5530   }, {
5531     "es_Latn_HK",
5532     "es_Latn_HK",
5533     "es_HK"
5534   }, {
5535     "es_Latn_AQ",
5536     "es_Latn_AQ",
5537     "es_AQ"
5538   }, {
5539     "es_Hans",
5540     "es_Hans_ES",
5541     "es_Hans"
5542   }, {
5543     "es_Hans_ZZ",
5544     "es_Hans_ES",
5545     "es_Hans"
5546   }, {
5547     "es_Hans_CN",
5548     "es_Hans_CN",
5549     "es_Hans_CN"
5550   }, {
5551     "es_Hans_TW",
5552     "es_Hans_TW",
5553     "es_Hans_TW"
5554   }, {
5555     "es_Hans_HK",
5556     "es_Hans_HK",
5557     "es_Hans_HK"
5558   }, {
5559     "es_Hans_AQ",
5560     "es_Hans_AQ",
5561     "es_Hans_AQ"
5562   }, {
5563     "es_Hant",
5564     "es_Hant_ES",
5565     "es_Hant"
5566   }, {
5567     "es_Hant_ZZ",
5568     "es_Hant_ES",
5569     "es_Hant"
5570   }, {
5571     "es_Hant_CN",
5572     "es_Hant_CN",
5573     "es_Hant_CN"
5574   }, {
5575     "es_Hant_TW",
5576     "es_Hant_TW",
5577     "es_Hant_TW"
5578   }, {
5579     "es_Hant_HK",
5580     "es_Hant_HK",
5581     "es_Hant_HK"
5582   }, {
5583     "es_Hant_AQ",
5584     "es_Hant_AQ",
5585     "es_Hant_AQ"
5586   }, {
5587     "es_Moon",
5588     "es_Moon_ES",
5589     "es_Moon"
5590   }, {
5591     "es_Moon_ZZ",
5592     "es_Moon_ES",
5593     "es_Moon"
5594   }, {
5595     "es_Moon_CN",
5596     "es_Moon_CN",
5597     "es_Moon_CN"
5598   }, {
5599     "es_Moon_TW",
5600     "es_Moon_TW",
5601     "es_Moon_TW"
5602   }, {
5603     "es_Moon_HK",
5604     "es_Moon_HK",
5605     "es_Moon_HK"
5606   }, {
5607     "es_Moon_AQ",
5608     "es_Moon_AQ",
5609     "es_Moon_AQ"
5610   }, {
5611     "zh",
5612     "zh_Hans_CN",
5613     "zh"
5614   }, {
5615     "zh_ZZ",
5616     "zh_Hans_CN",
5617     "zh"
5618   }, {
5619     "zh_CN",
5620     "zh_Hans_CN",
5621     "zh"
5622   }, {
5623     "zh_TW",
5624     "zh_Hant_TW",
5625     "zh_TW"
5626   }, {
5627     "zh_HK",
5628     "zh_Hant_HK",
5629     "zh_HK"
5630   }, {
5631     "zh_AQ",
5632     "zh_Hans_AQ",
5633     "zh_AQ"
5634   }, {
5635     "zh_Zzzz",
5636     "zh_Hans_CN",
5637     "zh"
5638   }, {
5639     "zh_Zzzz_ZZ",
5640     "zh_Hans_CN",
5641     "zh"
5642   }, {
5643     "zh_Zzzz_CN",
5644     "zh_Hans_CN",
5645     "zh"
5646   }, {
5647     "zh_Zzzz_TW",
5648     "zh_Hant_TW",
5649     "zh_TW"
5650   }, {
5651     "zh_Zzzz_HK",
5652     "zh_Hant_HK",
5653     "zh_HK"
5654   }, {
5655     "zh_Zzzz_AQ",
5656     "zh_Hans_AQ",
5657     "zh_AQ"
5658   }, {
5659     "zh_Latn",
5660     "zh_Latn_CN",
5661     "zh_Latn"
5662   }, {
5663     "zh_Latn_ZZ",
5664     "zh_Latn_CN",
5665     "zh_Latn"
5666   }, {
5667     "zh_Latn_CN",
5668     "zh_Latn_CN",
5669     "zh_Latn"
5670   }, {
5671     "zh_Latn_TW",
5672     "zh_Latn_TW",
5673     "zh_Latn_TW"
5674   }, {
5675     "zh_Latn_HK",
5676     "zh_Latn_HK",
5677     "zh_Latn_HK"
5678   }, {
5679     "zh_Latn_AQ",
5680     "zh_Latn_AQ",
5681     "zh_Latn_AQ"
5682   }, {
5683     "zh_Hans",
5684     "zh_Hans_CN",
5685     "zh"
5686   }, {
5687     "zh_Hans_ZZ",
5688     "zh_Hans_CN",
5689     "zh"
5690   }, {
5691     "zh_Hans_TW",
5692     "zh_Hans_TW",
5693     "zh_Hans_TW"
5694   }, {
5695     "zh_Hans_HK",
5696     "zh_Hans_HK",
5697     "zh_Hans_HK"
5698   }, {
5699     "zh_Hans_AQ",
5700     "zh_Hans_AQ",
5701     "zh_AQ"
5702   }, {
5703     "zh_Hant",
5704     "zh_Hant_TW",
5705     "zh_TW"
5706   }, {
5707     "zh_Hant_ZZ",
5708     "zh_Hant_TW",
5709     "zh_TW"
5710   }, {
5711     "zh_Hant_CN",
5712     "zh_Hant_CN",
5713     "zh_Hant_CN"
5714   }, {
5715     "zh_Hant_AQ",
5716     "zh_Hant_AQ",
5717     "zh_Hant_AQ"
5718   }, {
5719     "zh_Moon",
5720     "zh_Moon_CN",
5721     "zh_Moon"
5722   }, {
5723     "zh_Moon_ZZ",
5724     "zh_Moon_CN",
5725     "zh_Moon"
5726   }, {
5727     "zh_Moon_CN",
5728     "zh_Moon_CN",
5729     "zh_Moon"
5730   }, {
5731     "zh_Moon_TW",
5732     "zh_Moon_TW",
5733     "zh_Moon_TW"
5734   }, {
5735     "zh_Moon_HK",
5736     "zh_Moon_HK",
5737     "zh_Moon_HK"
5738   }, {
5739     "zh_Moon_AQ",
5740     "zh_Moon_AQ",
5741     "zh_Moon_AQ"
5742   }, {
5743     "art",
5744     "",
5745     ""
5746   }, {
5747     "art_ZZ",
5748     "",
5749     ""
5750   }, {
5751     "art_CN",
5752     "",
5753     ""
5754   }, {
5755     "art_TW",
5756     "",
5757     ""
5758   }, {
5759     "art_HK",
5760     "",
5761     ""
5762   }, {
5763     "art_AQ",
5764     "",
5765     ""
5766   }, {
5767     "art_Zzzz",
5768     "",
5769     ""
5770   }, {
5771     "art_Zzzz_ZZ",
5772     "",
5773     ""
5774   }, {
5775     "art_Zzzz_CN",
5776     "",
5777     ""
5778   }, {
5779     "art_Zzzz_TW",
5780     "",
5781     ""
5782   }, {
5783     "art_Zzzz_HK",
5784     "",
5785     ""
5786   }, {
5787     "art_Zzzz_AQ",
5788     "",
5789     ""
5790   }, {
5791     "art_Latn",
5792     "",
5793     ""
5794   }, {
5795     "art_Latn_ZZ",
5796     "",
5797     ""
5798   }, {
5799     "art_Latn_CN",
5800     "",
5801     ""
5802   }, {
5803     "art_Latn_TW",
5804     "",
5805     ""
5806   }, {
5807     "art_Latn_HK",
5808     "",
5809     ""
5810   }, {
5811     "art_Latn_AQ",
5812     "",
5813     ""
5814   }, {
5815     "art_Hans",
5816     "",
5817     ""
5818   }, {
5819     "art_Hans_ZZ",
5820     "",
5821     ""
5822   }, {
5823     "art_Hans_CN",
5824     "",
5825     ""
5826   }, {
5827     "art_Hans_TW",
5828     "",
5829     ""
5830   }, {
5831     "art_Hans_HK",
5832     "",
5833     ""
5834   }, {
5835     "art_Hans_AQ",
5836     "",
5837     ""
5838   }, {
5839     "art_Hant",
5840     "",
5841     ""
5842   }, {
5843     "art_Hant_ZZ",
5844     "",
5845     ""
5846   }, {
5847     "art_Hant_CN",
5848     "",
5849     ""
5850   }, {
5851     "art_Hant_TW",
5852     "",
5853     ""
5854   }, {
5855     "art_Hant_HK",
5856     "",
5857     ""
5858   }, {
5859     "art_Hant_AQ",
5860     "",
5861     ""
5862   }, {
5863     "art_Moon",
5864     "",
5865     ""
5866   }, {
5867     "art_Moon_ZZ",
5868     "",
5869     ""
5870   }, {
5871     "art_Moon_CN",
5872     "",
5873     ""
5874   }, {
5875     "art_Moon_TW",
5876     "",
5877     ""
5878   }, {
5879     "art_Moon_HK",
5880     "",
5881     ""
5882   }, {
5883     "art_Moon_AQ",
5884     "",
5885     ""
5886   }, {
5887     "de@collation=phonebook",
5888     "de_Latn_DE@collation=phonebook",
5889     "de@collation=phonebook"
5890   }
5891 };
5892 
5893 typedef struct errorDataTag {
5894     const char* tag;
5895     const char* expected;
5896     UErrorCode uerror;
5897     int32_t  bufferSize;
5898 } errorData;
5899 
5900 const errorData maximizeErrors[] = {
5901     {
5902         "enfueiujhytdf",
5903         NULL,
5904         U_ILLEGAL_ARGUMENT_ERROR,
5905         -1
5906     },
5907     {
5908         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5909         NULL,
5910         U_ILLEGAL_ARGUMENT_ERROR,
5911         -1
5912     },
5913     {
5914         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5915         NULL,
5916         U_ILLEGAL_ARGUMENT_ERROR,
5917         -1
5918     },
5919     {
5920         "en_Latn_US_POSIX@currency=EURO",
5921         "en_Latn_US_POSIX@currency=EURO",
5922         U_BUFFER_OVERFLOW_ERROR,
5923         29
5924     },
5925     {
5926         "en_Latn_US_POSIX@currency=EURO",
5927         "en_Latn_US_POSIX@currency=EURO",
5928         U_STRING_NOT_TERMINATED_WARNING,
5929         30
5930     }
5931 };
5932 
5933 const errorData minimizeErrors[] = {
5934     {
5935         "enfueiujhytdf",
5936         NULL,
5937         U_ILLEGAL_ARGUMENT_ERROR,
5938         -1
5939     },
5940     {
5941         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5942         NULL,
5943         U_ILLEGAL_ARGUMENT_ERROR,
5944         -1
5945     },
5946     {
5947         "en_Latn_US_POSIX@currency=EURO",
5948         "en__POSIX@currency=EURO",
5949         U_BUFFER_OVERFLOW_ERROR,
5950         22
5951     },
5952     {
5953         "en_Latn_US_POSIX@currency=EURO",
5954         "en__POSIX@currency=EURO",
5955         U_STRING_NOT_TERMINATED_WARNING,
5956         23
5957     }
5958 };
5959 
getExpectedReturnValue(const errorData * data)5960 static int32_t getExpectedReturnValue(const errorData* data)
5961 {
5962     if (data->uerror == U_BUFFER_OVERFLOW_ERROR ||
5963         data->uerror == U_STRING_NOT_TERMINATED_WARNING)
5964     {
5965         return (int32_t)strlen(data->expected);
5966     }
5967     else
5968     {
5969         return -1;
5970     }
5971 }
5972 
getBufferSize(const errorData * data,int32_t actualSize)5973 static int32_t getBufferSize(const errorData* data, int32_t actualSize)
5974 {
5975     if (data->expected == NULL)
5976     {
5977         return actualSize;
5978     }
5979     else if (data->bufferSize < 0)
5980     {
5981         return (int32_t)strlen(data->expected) + 1;
5982     }
5983     else
5984     {
5985         return data->bufferSize;
5986     }
5987 }
5988 
TestLikelySubtags()5989 static void TestLikelySubtags()
5990 {
5991     char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1];
5992     int32_t i = 0;
5993 
5994     for (; i < UPRV_LENGTHOF(basic_maximize_data); ++i)
5995     {
5996         UErrorCode status = U_ZERO_ERROR;
5997         const char* const minimal = basic_maximize_data[i][0];
5998         const char* const maximal = basic_maximize_data[i][1];
5999 
6000         /* const int32_t length = */
6001             uloc_addLikelySubtags(
6002                 minimal,
6003                 buffer,
6004                 sizeof(buffer),
6005                 &status);
6006         if (U_FAILURE(status)) {
6007             log_err_status(status, "  unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status));
6008             status = U_ZERO_ERROR;
6009         }
6010         else if (uprv_strlen(maximal) == 0) {
6011             if (uprv_stricmp(minimal, buffer) != 0) {
6012                 log_err("  unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
6013             }
6014         }
6015         else if (uprv_stricmp(maximal, buffer) != 0) {
6016             log_err("  maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer);
6017         }
6018     }
6019 
6020     for (i = 0; i < UPRV_LENGTHOF(basic_minimize_data); ++i) {
6021 
6022         UErrorCode status = U_ZERO_ERROR;
6023         const char* const maximal = basic_minimize_data[i][0];
6024         const char* const minimal = basic_minimize_data[i][1];
6025 
6026         /* const int32_t length = */
6027             uloc_minimizeSubtags(
6028                 maximal,
6029                 buffer,
6030                 sizeof(buffer),
6031                 &status);
6032 
6033         if (U_FAILURE(status)) {
6034             log_err_status(status, "  unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
6035             status = U_ZERO_ERROR;
6036         }
6037         else if (uprv_strlen(minimal) == 0) {
6038             if (uprv_stricmp(maximal, buffer) != 0) {
6039                 log_err("  unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
6040             }
6041         }
6042         else if (uprv_stricmp(minimal, buffer) != 0) {
6043             log_err("  minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
6044         }
6045     }
6046 
6047     for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
6048 
6049         UErrorCode status = U_ZERO_ERROR;
6050         const char* const minimal = full_data[i][0];
6051         const char* const maximal = full_data[i][1];
6052 
6053         /* const int32_t length = */
6054             uloc_addLikelySubtags(
6055                 minimal,
6056                 buffer,
6057                 sizeof(buffer),
6058                 &status);
6059         if (U_FAILURE(status)) {
6060             log_err_status(status, "  unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status));
6061             status = U_ZERO_ERROR;
6062         }
6063         else if (uprv_strlen(maximal) == 0) {
6064             if (uprv_stricmp(minimal, buffer) != 0) {
6065                 log_err("  unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
6066             }
6067         }
6068         else if (uprv_stricmp(maximal, buffer) != 0) {
6069             log_err("  maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
6070         }
6071     }
6072 
6073     for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
6074 
6075         UErrorCode status = U_ZERO_ERROR;
6076         const char* const maximal = full_data[i][1];
6077         const char* const minimal = full_data[i][2];
6078 
6079         if (strlen(maximal) > 0) {
6080 
6081             /* const int32_t length = */
6082                 uloc_minimizeSubtags(
6083                     maximal,
6084                     buffer,
6085                     sizeof(buffer),
6086                     &status);
6087 
6088             if (U_FAILURE(status)) {
6089                 log_err_status(status, "  unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
6090                 status = U_ZERO_ERROR;
6091             }
6092             else if (uprv_strlen(minimal) == 0) {
6093                 if (uprv_stricmp(maximal, buffer) != 0) {
6094                     log_err("  unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
6095                 }
6096             }
6097             else if (uprv_stricmp(minimal, buffer) != 0) {
6098                 log_err("  minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
6099             }
6100         }
6101     }
6102 
6103     for (i = 0; i < UPRV_LENGTHOF(maximizeErrors); ++i) {
6104 
6105         UErrorCode status = U_ZERO_ERROR;
6106         const char* const minimal = maximizeErrors[i].tag;
6107         const char* const maximal = maximizeErrors[i].expected;
6108         const UErrorCode expectedStatus = maximizeErrors[i].uerror;
6109         const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]);
6110         const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer));
6111 
6112         const int32_t length =
6113             uloc_addLikelySubtags(
6114                 minimal,
6115                 buffer,
6116                 bufferSize,
6117                 &status);
6118 
6119         if (status == U_ZERO_ERROR) {
6120             log_err("  unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus));
6121             status = U_ZERO_ERROR;
6122         }
6123         else if (status != expectedStatus) {
6124             log_err_status(status, "  unexpected status for uloc_addLikelySubtags(), minimal \"%s\" expected status %s, but got %s\n", minimal, u_errorName(expectedStatus), u_errorName(status));
6125         }
6126         else if (length != expectedLength) {
6127             log_err("  unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length);
6128         }
6129         else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
6130             if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) {
6131                 log_err("  maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
6132                     maximal, minimal, (int)sizeof(buffer), buffer);
6133             }
6134         }
6135     }
6136 
6137     for (i = 0; i < UPRV_LENGTHOF(minimizeErrors); ++i) {
6138 
6139         UErrorCode status = U_ZERO_ERROR;
6140         const char* const maximal = minimizeErrors[i].tag;
6141         const char* const minimal = minimizeErrors[i].expected;
6142         const UErrorCode expectedStatus = minimizeErrors[i].uerror;
6143         const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]);
6144         const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer));
6145 
6146         const int32_t length =
6147             uloc_minimizeSubtags(
6148                 maximal,
6149                 buffer,
6150                 bufferSize,
6151                 &status);
6152 
6153         if (status == U_ZERO_ERROR) {
6154             log_err("  unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus));
6155             status = U_ZERO_ERROR;
6156         }
6157         else if (status != expectedStatus) {
6158             log_err_status(status, "  unexpected status for uloc_minimizeSubtags(), maximal \"%s\" expected status %s, but got %s\n", maximal, u_errorName(expectedStatus), u_errorName(status));
6159         }
6160         else if (length != expectedLength) {
6161             log_err("  unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length);
6162         }
6163         else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
6164             if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) {
6165                 log_err("  minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
6166                     minimal, maximal, (int)sizeof(buffer), buffer);
6167             }
6168         }
6169     }
6170 }
6171 
6172 const char* const locale_to_langtag[][3] = {
6173     {"",            "und",          "und"},
6174     {"en",          "en",           "en"},
6175     {"en_US",       "en-US",        "en-US"},
6176     {"iw_IL",       "he-IL",        "he-IL"},
6177     {"sr_Latn_SR",  "sr-Latn-SR",   "sr-Latn-SR"},
6178     {"en__POSIX",   "en-u-va-posix", "en-u-va-posix"},
6179     {"en_POSIX",    "en-u-va-posix", "en-u-va-posix"},
6180     {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL},  /* variant POSIX_VAR is processed as regular variant */
6181     {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL},  /* variant VAR_POSIX is processed as regular variant */
6182     {"en_US_POSIX@va=posix2",   "en-US-u-va-posix2",  "en-US-u-va-posix2"},           /* if keyword va=xxx already exists, variant POSIX is simply dropped */
6183     {"en_US_POSIX@ca=japanese",  "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
6184     {"und_555",     "und-555",      "und-555"},
6185     {"123",         "und",          NULL},
6186     {"%$#&",        "und",          NULL},
6187     {"_Latn",       "und-Latn",     "und-Latn"},
6188     {"_DE",         "und-DE",       "und-DE"},
6189     {"und_FR",      "und-FR",       "und-FR"},
6190     {"th_TH_TH",    "th-TH-x-lvariant-th", NULL},
6191     {"bogus",       "bogus",        "bogus"},
6192     {"foooobarrr",  "und",          NULL},
6193     {"aa_BB_CYRL",  "aa-BB-x-lvariant-cyrl", NULL},
6194     {"en_US_1234",  "en-US-1234",   "en-US-1234"},
6195     {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb",  "en-US-varianta-variantb"},
6196     {"en_US_VARIANTB_VARIANTA", "en-US-varianta-variantb",  "en-US-varianta-variantb"}, /* ICU-20478 */
6197     {"ja__9876_5432",   "ja-5432-9876", "ja-5432-9876"}, /* ICU-20478 */
6198     {"sl__ROZAJ_BISKE_1994",   "sl-1994-biske-rozaj", "sl-1994-biske-rozaj"}, /* ICU-20478 */
6199     {"en__SCOUSE_FONIPA",   "en-fonipa-scouse", "en-fonipa-scouse"}, /* ICU-20478 */
6200     {"zh_Hant__VAR",    "zh-Hant-x-lvariant-var", NULL},
6201     {"es__BADVARIANT_GOODVAR",  "es-goodvar",   NULL},
6202     {"en@calendar=gregorian",   "en-u-ca-gregory",  "en-u-ca-gregory"},
6203     {"de@collation=phonebook;calendar=gregorian",   "de-u-ca-gregory-co-phonebk",   "de-u-ca-gregory-co-phonebk"},
6204     {"th@numbers=thai;z=extz;x=priv-use;a=exta",   "th-a-exta-u-nu-thai-z-extz-x-priv-use", "th-a-exta-u-nu-thai-z-extz-x-priv-use"},
6205     {"en@timezone=America/New_York;calendar=japanese",    "en-u-ca-japanese-tz-usnyc",    "en-u-ca-japanese-tz-usnyc"},
6206     {"en@timezone=US/Eastern",  "en-u-tz-usnyc",    "en-u-tz-usnyc"},
6207     {"en@x=x-y-z;a=a-b-c",  "en-x-x-y-z",   NULL},
6208     {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic",  NULL},
6209     {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
6210     {"en_US_POSIX@calendar=japanese;currency=EUR","en-US-u-ca-japanese-cu-eur-va-posix", "en-US-u-ca-japanese-cu-eur-va-posix"},
6211     {"@x=elmer",    "und-x-elmer",      "und-x-elmer"},
6212     {"en@x=elmer",  "en-x-elmer",   "en-x-elmer"},
6213     {"@x=elmer;a=exta", "und-a-exta-x-elmer",   "und-a-exta-x-elmer"},
6214     {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
6215     /* #12671 */
6216     {"en@a=bar;attribute=baz",  "en-a-bar-u-baz",   "en-a-bar-u-baz"},
6217     {"en@a=bar;attribute=baz;x=u-foo",  "en-a-bar-u-baz-x-u-foo",   "en-a-bar-u-baz-x-u-foo"},
6218     {"en@attribute=baz",    "en-u-baz", "en-u-baz"},
6219     {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil",    "en-u-baz-ca-islamic-civil"},
6220     {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo",  "en-a-bar-u-ca-islamic-civil-x-u-foo"},
6221     {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo",   "en-a-bar-u-baz-ca-islamic-civil-x-u-foo",  "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"},
6222     {"en@9=efg;a=baz",    "en-9-efg-a-baz", "en-9-efg-a-baz"},
6223 
6224     // Before ICU 64, ICU locale canonicalization had some additional mappings.
6225     // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
6226     // The following now uses standard canonicalization.
6227     {"az_AZ_CYRL", "az-AZ-x-lvariant-cyrl", NULL},
6228 
6229 
6230     /* ICU-20310 */
6231     {"en-u-kn-true",   "en-u-kn", "en-u-kn"},
6232     {"en-u-kn",   "en-u-kn", "en-u-kn"},
6233     {"de-u-co-yes",   "de-u-co", "de-u-co"},
6234     {"de-u-co",   "de-u-co", "de-u-co"},
6235     {"de@collation=yes",   "de-u-co", "de-u-co"},
6236     {"cmn-hans-cn-u-ca-t-ca-x-t-u",   "cmn-Hans-CN-t-ca-u-ca-x-t-u", "cmn-Hans-CN-t-ca-u-ca-x-t-u"},
6237     {NULL,          NULL,           NULL}
6238 };
6239 
TestToLanguageTag(void)6240 static void TestToLanguageTag(void) {
6241     char langtag[256];
6242     int32_t i;
6243     UErrorCode status;
6244     int32_t len;
6245     const char *inloc;
6246     const char *expected;
6247 
6248     for (i = 0; locale_to_langtag[i][0] != NULL; i++) {
6249         inloc = locale_to_langtag[i][0];
6250 
6251         /* testing non-strict mode */
6252         status = U_ZERO_ERROR;
6253         langtag[0] = 0;
6254         expected = locale_to_langtag[i][1];
6255 
6256         len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), false, &status);
6257         (void)len;    /* Suppress set but not used warning. */
6258         if (U_FAILURE(status)) {
6259             if (expected != NULL) {
6260                 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
6261                     inloc, u_errorName(status));
6262             }
6263         } else {
6264             if (expected == NULL) {
6265                 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
6266                     inloc, langtag);
6267             } else if (uprv_strcmp(langtag, expected) != 0) {
6268                 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6269                     langtag, inloc, expected);
6270             }
6271         }
6272 
6273         /* testing strict mode */
6274         status = U_ZERO_ERROR;
6275         langtag[0] = 0;
6276         expected = locale_to_langtag[i][2];
6277 
6278         len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), true, &status);
6279         if (U_FAILURE(status)) {
6280             if (expected != NULL) {
6281                 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
6282                     inloc, u_errorName(status));
6283             }
6284         } else {
6285             if (expected == NULL) {
6286                 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
6287                     inloc, langtag);
6288             } else if (uprv_strcmp(langtag, expected) != 0) {
6289                 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
6290                     langtag, inloc, expected);
6291             }
6292         }
6293     }
6294 }
6295 
TestBug20132(void)6296 static void TestBug20132(void) {
6297     char langtag[256];
6298     UErrorCode status;
6299     int32_t len;
6300 
6301     static const char inloc[] = "en-C";
6302     static const char expected[] = "en-x-lvariant-c";
6303     const int32_t expected_len = (int32_t)uprv_strlen(expected);
6304 
6305     /* Before ICU-20132 was fixed, calling uloc_toLanguageTag() with a too small
6306      * buffer would not immediately return the buffer size actually needed, but
6307      * instead require several iterations before getting the correct size. */
6308 
6309     status = U_ZERO_ERROR;
6310     len = uloc_toLanguageTag(inloc, langtag, 1, false, &status);
6311 
6312     if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
6313         log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6314             inloc, u_errorName(status));
6315     }
6316 
6317     if (len != expected_len) {
6318         log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc, len, expected_len);
6319     }
6320 
6321     status = U_ZERO_ERROR;
6322     len = uloc_toLanguageTag(inloc, langtag, expected_len, false, &status);
6323 
6324     if (U_FAILURE(status)) {
6325         log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6326             inloc, u_errorName(status));
6327     }
6328 
6329     if (len != expected_len) {
6330         log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc, len, expected_len);
6331     } else if (uprv_strncmp(langtag, expected, expected_len) != 0) {
6332         log_data_err("uloc_toLanguageTag returned language tag [%.*s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6333             len, langtag, inloc, expected);
6334     }
6335 }
6336 
6337 #define FULL_LENGTH -1
6338 static const struct {
6339     const char  *bcpID;
6340     const char  *locID;
6341     int32_t     len;
6342 } langtag_to_locale[] = {
6343     {"en",                  "en",                   FULL_LENGTH},
6344     {"en-us",               "en_US",                FULL_LENGTH},
6345     {"und-US",              "_US",                  FULL_LENGTH},
6346     {"und-latn",            "_Latn",                FULL_LENGTH},
6347     {"en-US-posix",         "en_US_POSIX",          FULL_LENGTH},
6348     {"de-de_euro",          "de",                   2},
6349     {"kok-IN",              "kok_IN",               FULL_LENGTH},
6350     {"123",                 "",                     0},
6351     {"en_us",               "",                     0},
6352     {"en-latn-x",           "en_Latn",              7},
6353     {"art-lojban",          "jbo",                  FULL_LENGTH},
6354     {"zh-hakka",            "hak",                  FULL_LENGTH},
6355     {"zh-cmn-CH",           "cmn_CH",               FULL_LENGTH},
6356     {"zh-cmn-CH-u-co-pinyin", "cmn_CH@collation=pinyin", FULL_LENGTH},
6357     {"xxx-yy",              "xxx_YY",               FULL_LENGTH},
6358     {"fr-234",              "fr_234",               FULL_LENGTH},
6359     {"i-default",           "en@x=i-default",       FULL_LENGTH},
6360     {"i-test",              "",                     0},
6361     {"ja-jp-jp",            "ja_JP",                5},
6362     {"bogus",               "bogus",                FULL_LENGTH},
6363     {"boguslang",           "",                     0},
6364     {"EN-lATN-us",          "en_Latn_US",           FULL_LENGTH},
6365     {"und-variant-1234",    "__1234_VARIANT",       FULL_LENGTH}, /* ICU-20478 */
6366     {"ja-9876-5432",    "ja__5432_9876",       FULL_LENGTH}, /* ICU-20478 */
6367     {"en-US-varianta-variantb",    "en_US_VARIANTA_VARIANTB",       FULL_LENGTH}, /* ICU-20478 */
6368     {"en-US-variantb-varianta",    "en_US_VARIANTA_VARIANTB",       FULL_LENGTH}, /* ICU-20478 */
6369     {"sl-rozaj-1994-biske",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
6370     {"sl-biske-1994-rozaj",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
6371     {"sl-1994-rozaj-biske",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
6372     {"sl-rozaj-biske-1994",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
6373     {"en-fonipa-scouse",    "en__FONIPA_SCOUSE",       FULL_LENGTH}, /* ICU-20478 */
6374     {"en-scouse-fonipa",    "en__FONIPA_SCOUSE",       FULL_LENGTH}, /* ICU-20478 */
6375     {"und-varzero-var1-vartwo", "__VARZERO",        11},
6376     {"en-u-ca-gregory",     "en@calendar=gregorian",    FULL_LENGTH},
6377     {"en-U-cu-USD",         "en@currency=usd",      FULL_LENGTH},
6378     {"en-US-u-va-posix",    "en_US_POSIX",          FULL_LENGTH},
6379     {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian",   FULL_LENGTH},
6380     {"en-us-posix-u-va-posix",   "en_US_POSIX@va=posix",    FULL_LENGTH},
6381     {"en-us-u-va-posix2",        "en_US@va=posix2",         FULL_LENGTH},
6382     {"en-us-vari1-u-va-posix",   "en_US_VARI1@va=posix",    FULL_LENGTH},
6383     {"ar-x-1-2-3",          "ar@x=1-2-3",           FULL_LENGTH},
6384     {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH},
6385     {"de-k-kext-u-co-phonebk-nu-latn",  "de@collation=phonebook;k=kext;numbers=latn",   FULL_LENGTH},
6386     {"ja-u-cu-jpy-ca-jp",   "ja@calendar=yes;currency=jpy;jp=yes",  FULL_LENGTH},
6387     {"en-us-u-tz-usnyc",    "en_US@timezone=America/New_York",  FULL_LENGTH},
6388     {"und-a-abc-def",       "und@a=abc-def",        FULL_LENGTH},
6389     {"zh-u-ca-chinese-x-u-ca-chinese",  "zh@calendar=chinese;x=u-ca-chinese",   FULL_LENGTH},
6390     {"x-elmer",             "@x=elmer",             FULL_LENGTH},
6391     {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian",    FULL_LENGTH},
6392     {"sr-u-kn",             "sr@colnumeric=yes",    FULL_LENGTH},
6393     {"de-u-kn-co-phonebk",  "de@collation=phonebook;colnumeric=yes",    FULL_LENGTH},
6394     {"en-u-attr2-attr1-kn-kb",  "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH},
6395     {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn",   "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz",  FULL_LENGTH},
6396     {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
6397      "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
6398     {"de-1901-1901", "de__1901", 7},
6399     {"de-DE-1901-1901", "de_DE_1901", 10},
6400     {"en-a-bbb-a-ccc", "en@a=bbb", 8},
6401     /* #12761 */
6402     {"en-a-bar-u-baz",      "en@a=bar;attribute=baz",   FULL_LENGTH},
6403     {"en-a-bar-u-baz-x-u-foo",  "en@a=bar;attribute=baz;x=u-foo",   FULL_LENGTH},
6404     {"en-u-baz",            "en@attribute=baz",     FULL_LENGTH},
6405     {"en-u-baz-ca-islamic-civil",   "en@attribute=baz;calendar=islamic-civil",  FULL_LENGTH},
6406     {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo",  FULL_LENGTH},
6407     {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo",    FULL_LENGTH},
6408     {"und-Arab-u-em-emoji", "_Arab@em=emoji", FULL_LENGTH},
6409     {"und-Latn-u-em-emoji", "_Latn@em=emoji", FULL_LENGTH},
6410     {"und-Latn-DE-u-em-emoji", "_Latn_DE@em=emoji", FULL_LENGTH},
6411     {"und-Zzzz-DE-u-em-emoji", "_Zzzz_DE@em=emoji", FULL_LENGTH},
6412     {"und-DE-u-em-emoji", "_DE@em=emoji", FULL_LENGTH},
6413     // #20098
6414     {"hant-cmn-cn", "hant", 4},
6415     {"zh-cmn-TW", "cmn_TW", FULL_LENGTH},
6416     {"zh-x_t-ab", "zh", 2},
6417     {"zh-hans-cn-u-ca-x_t-u", "zh_Hans_CN@calendar=yes", 15},
6418     /* #20140 dupe keys in U-extension */
6419     {"zh-u-ca-chinese-ca-gregory", "zh@calendar=chinese", FULL_LENGTH},
6420     {"zh-u-ca-gregory-co-pinyin-ca-chinese", "zh@calendar=gregorian;collation=pinyin", FULL_LENGTH},
6421     {"de-latn-DE-1901-u-co-phonebk-co-pinyin-ca-gregory", "de_Latn_DE_1901@calendar=gregorian;collation=phonebook", FULL_LENGTH},
6422     {"th-u-kf-nu-thai-kf-false", "th@colcasefirst=yes;numbers=thai", FULL_LENGTH},
6423     /* #9562 IANA language tag data update */
6424     {"en-gb-oed", "en_GB_OXENDICT", FULL_LENGTH},
6425     {"i-navajo", "nv", FULL_LENGTH},
6426     {"i-navajo-a-foo", "nv@a=foo", FULL_LENGTH},
6427     {"i-navajo-latn-us", "nv_Latn_US", FULL_LENGTH},
6428     {"sgn-br", "bzs", FULL_LENGTH},
6429     {"sgn-br-u-co-phonebk", "bzs@collation=phonebook", FULL_LENGTH},
6430     {"ja-latn-hepburn-heploc", "ja_Latn__ALALC97", FULL_LENGTH},
6431     {"ja-latn-hepburn-heploc-u-ca-japanese", "ja_Latn__ALALC97@calendar=japanese", FULL_LENGTH},
6432     {"en-a-bcde-0-fgh", "en@0=fgh;a=bcde", FULL_LENGTH},
6433 };
6434 
TestForLanguageTag(void)6435 static void TestForLanguageTag(void) {
6436     char locale[256];
6437     int32_t i;
6438     UErrorCode status;
6439     int32_t parsedLen;
6440     int32_t expParsedLen;
6441 
6442     for (i = 0; i < UPRV_LENGTHOF(langtag_to_locale); i++) {
6443         status = U_ZERO_ERROR;
6444         locale[0] = 0;
6445         expParsedLen = langtag_to_locale[i].len;
6446         if (expParsedLen == FULL_LENGTH) {
6447             expParsedLen = (int32_t)uprv_strlen(langtag_to_locale[i].bcpID);
6448         }
6449         uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status);
6450         if (U_FAILURE(status)) {
6451             log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
6452                 langtag_to_locale[i].bcpID, u_errorName(status));
6453         } else {
6454             if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) {
6455                 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
6456                     locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID);
6457             }
6458             if (parsedLen != expParsedLen) {
6459                 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
6460                     parsedLen, langtag_to_locale[i].bcpID, expParsedLen);
6461             }
6462         }
6463     }
6464 }
6465 
6466 static const struct {
6467     const char  *input;
6468     const char  *canonical;
6469 } langtag_to_canonical[] = {
6470     {"de-DD", "de-DE"},
6471     {"de-DD-u-co-phonebk", "de-DE-u-co-phonebk"},
6472     {"jw-id", "jv-ID"},
6473     {"jw-id-u-ca-islamic-civil", "jv-ID-u-ca-islamic-civil"},
6474     {"mo-md", "ro-MD"},
6475     {"my-bu-u-nu-mymr", "my-MM-u-nu-mymr"},
6476     {"yuu-ru", "yug-RU"},
6477 };
6478 
6479 
TestLangAndRegionCanonicalize(void)6480 static void TestLangAndRegionCanonicalize(void) {
6481     char locale[256];
6482     char canonical[256];
6483     int32_t i;
6484     UErrorCode status;
6485     for (i = 0; i < UPRV_LENGTHOF(langtag_to_canonical); i++) {
6486         status = U_ZERO_ERROR;
6487         const char* input = langtag_to_canonical[i].input;
6488         uloc_forLanguageTag(input, locale, sizeof(locale), NULL, &status);
6489         uloc_toLanguageTag(locale, canonical, sizeof(canonical), true, &status);
6490         if (U_FAILURE(status)) {
6491             log_err_status(status, "Error returned by uloc_forLanguageTag or uloc_toLanguageTag "
6492                            "for language tag [%s] - error: %s\n", input, u_errorName(status));
6493         } else {
6494             const char* expected_canonical = langtag_to_canonical[i].canonical;
6495             if (uprv_strcmp(expected_canonical, canonical) != 0) {
6496                 log_data_err("input language tag [%s] is canonicalized to [%s] - expected: [%s]\n",
6497                     input, canonical, expected_canonical);
6498             }
6499         }
6500     }
6501 }
6502 
TestToUnicodeLocaleKey(void)6503 static void TestToUnicodeLocaleKey(void)
6504 {
6505     /* $IN specifies the result should be the input pointer itself */
6506     static const char* DATA[][2] = {
6507         {"calendar",    "ca"},
6508         {"CALEndar",    "ca"},  /* difference casing */
6509         {"ca",          "ca"},  /* bcp key itself */
6510         {"kv",          "kv"},  /* no difference between legacy and bcp */
6511         {"foo",         NULL},  /* unknown, bcp ill-formed */
6512         {"ZZ",          "$IN"}, /* unknown, bcp well-formed -  */
6513         {NULL,          NULL}
6514     };
6515 
6516     int32_t i;
6517     for (i = 0; DATA[i][0] != NULL; i++) {
6518         const char* keyword = DATA[i][0];
6519         const char* expected = DATA[i][1];
6520         const char* bcpKey = NULL;
6521 
6522         bcpKey = uloc_toUnicodeLocaleKey(keyword);
6523         if (expected == NULL) {
6524             if (bcpKey != NULL) {
6525                 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey);
6526             }
6527         } else if (bcpKey == NULL) {
6528             log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6529         } else if (uprv_strcmp(expected, "$IN") == 0) {
6530             if (bcpKey != keyword) {
6531                 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword);
6532             }
6533         } else if (uprv_strcmp(bcpKey, expected) != 0) {
6534             log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected);
6535         }
6536     }
6537 }
6538 
TestBug20321UnicodeLocaleKey(void)6539 static void TestBug20321UnicodeLocaleKey(void)
6540 {
6541     // key = alphanum alpha ;
6542     static const char* invalid[] = {
6543         "a0",
6544         "00",
6545         "a@",
6546         "0@",
6547         "@a",
6548         "@a",
6549         "abc",
6550         "0bc",
6551     };
6552     for (int i = 0; i < UPRV_LENGTHOF(invalid); i++) {
6553         const char* bcpKey = NULL;
6554         bcpKey = uloc_toUnicodeLocaleKey(invalid[i]);
6555         if (bcpKey != NULL) {
6556             log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", invalid[i], bcpKey);
6557         }
6558     }
6559     static const char* valid[] = {
6560         "aa",
6561         "0a",
6562     };
6563     for (int i = 0; i < UPRV_LENGTHOF(valid); i++) {
6564         const char* bcpKey = NULL;
6565         bcpKey = uloc_toUnicodeLocaleKey(valid[i]);
6566         if (bcpKey == NULL) {
6567             log_err("toUnicodeLocaleKey: keyword=%s => NULL, expected!=NULL\n", valid[i]);
6568         }
6569     }
6570 }
6571 
TestToLegacyKey(void)6572 static void TestToLegacyKey(void)
6573 {
6574     /* $IN specifies the result should be the input pointer itself */
6575     static const char* DATA[][2] = {
6576         {"kb",          "colbackwards"},
6577         {"kB",          "colbackwards"},    /* different casing */
6578         {"Collation",   "collation"},   /* keyword itself with different casing */
6579         {"kv",          "kv"},  /* no difference between legacy and bcp */
6580         {"foo",         "$IN"}, /* unknown, bcp ill-formed */
6581         {"ZZ",          "$IN"}, /* unknown, bcp well-formed */
6582         {"e=mc2",       NULL},  /* unknown, bcp/legacy ill-formed */
6583         {NULL,          NULL}
6584     };
6585 
6586     int32_t i;
6587     for (i = 0; DATA[i][0] != NULL; i++) {
6588         const char* keyword = DATA[i][0];
6589         const char* expected = DATA[i][1];
6590         const char* legacyKey = NULL;
6591 
6592         legacyKey = uloc_toLegacyKey(keyword);
6593         if (expected == NULL) {
6594             if (legacyKey != NULL) {
6595                 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey);
6596             }
6597         } else if (legacyKey == NULL) {
6598             log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6599         } else if (uprv_strcmp(expected, "$IN") == 0) {
6600             if (legacyKey != keyword) {
6601                 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword);
6602             }
6603         } else if (uprv_strcmp(legacyKey, expected) != 0) {
6604             log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected);
6605         }
6606     }
6607 }
6608 
TestToUnicodeLocaleType(void)6609 static void TestToUnicodeLocaleType(void)
6610 {
6611     /* $IN specifies the result should be the input pointer itself */
6612     static const char* DATA[][3] = {
6613         {"tz",              "Asia/Kolkata",     "inccu"},
6614         {"calendar",        "gregorian",        "gregory"},
6615         {"ca",              "gregorian",        "gregory"},
6616         {"ca",              "Gregorian",        "gregory"},
6617         {"ca",              "buddhist",         "buddhist"},
6618         {"Calendar",        "Japanese",         "japanese"},
6619         {"calendar",        "Islamic-Civil",    "islamic-civil"},
6620         {"calendar",        "islamicc",         "islamic-civil"},   /* bcp type alias */
6621         {"colalternate",    "NON-IGNORABLE",    "noignore"},
6622         {"colcaselevel",    "yes",              "true"},
6623         {"rg",              "GBzzzz",           "$IN"},
6624         {"tz",              "america/new_york", "usnyc"},
6625         {"tz",              "Asia/Kolkata",     "inccu"},
6626         {"timezone",        "navajo",           "usden"},
6627         {"ca",              "aaaa",             "$IN"},     /* unknown type, well-formed type */
6628         {"ca",              "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6629         {"zz",              "gregorian",        NULL},      /* unknown key, ill-formed type */
6630         {"co",              "foo-",             NULL},      /* unknown type, ill-formed type */
6631         {"variableTop",     "00A0",             "$IN"},     /* valid codepoints type */
6632         {"variableTop",     "wxyz",             "$IN"},     /* invalid codepoints type - return as is for now */
6633         {"kr",              "space-punct",      "space-punct"}, /* valid reordercode type */
6634         {"kr",              "digit-spacepunct", NULL},      /* invalid (bcp ill-formed) reordercode type */
6635         {NULL,              NULL,               NULL}
6636     };
6637 
6638     int32_t i;
6639     for (i = 0; DATA[i][0] != NULL; i++) {
6640         const char* keyword = DATA[i][0];
6641         const char* value = DATA[i][1];
6642         const char* expected = DATA[i][2];
6643         const char* bcpType = NULL;
6644 
6645         bcpType = uloc_toUnicodeLocaleType(keyword, value);
6646         if (expected == NULL) {
6647             if (bcpType != NULL) {
6648                 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType);
6649             }
6650         } else if (bcpType == NULL) {
6651             log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6652         } else if (uprv_strcmp(expected, "$IN") == 0) {
6653             if (bcpType != value) {
6654                 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value);
6655             }
6656         } else if (uprv_strcmp(bcpType, expected) != 0) {
6657             log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected);
6658         }
6659     }
6660 }
6661 
TestToLegacyType(void)6662 static void TestToLegacyType(void)
6663 {
6664     /* $IN specifies the result should be the input pointer itself */
6665     static const char* DATA[][3] = {
6666         {"calendar",        "gregory",          "gregorian"},
6667         {"ca",              "gregory",          "gregorian"},
6668         {"ca",              "Gregory",          "gregorian"},
6669         {"ca",              "buddhist",         "buddhist"},
6670         {"Calendar",        "Japanese",         "japanese"},
6671         {"calendar",        "Islamic-Civil",    "islamic-civil"},
6672         {"calendar",        "islamicc",         "islamic-civil"},   /* bcp type alias */
6673         {"colalternate",    "noignore",         "non-ignorable"},
6674         {"colcaselevel",    "true",             "yes"},
6675         {"rg",              "gbzzzz",           "gbzzzz"},
6676         {"tz",              "usnyc",            "America/New_York"},
6677         {"tz",              "inccu",            "Asia/Calcutta"},
6678         {"timezone",        "usden",            "America/Denver"},
6679         {"timezone",        "usnavajo",         "America/Denver"},  /* bcp type alias */
6680         {"colstrength",     "quarternary",      "quaternary"},  /* type alias */
6681         {"ca",              "aaaa",             "$IN"}, /* unknown type */
6682         {"calendar",        "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6683         {"zz",              "gregorian",        "$IN"}, /* unknown key, bcp ill-formed type */
6684         {"ca",              "gregorian-calendar",   "$IN"}, /* known key, bcp ill-formed type */
6685         {"co",              "e=mc2",            NULL},  /* known key, ill-formed bcp/legacy type */
6686         {"variableTop",     "00A0",             "$IN"},     /* valid codepoints type */
6687         {"variableTop",     "wxyz",             "$IN"},    /* invalid codepoints type - return as is for now */
6688         {"kr",              "space-punct",      "space-punct"}, /* valid reordercode type */
6689         {"kr",              "digit-spacepunct", "digit-spacepunct"},    /* invalid reordercode type, but ok for legacy syntax */
6690         {NULL,              NULL,               NULL}
6691     };
6692 
6693     int32_t i;
6694     for (i = 0; DATA[i][0] != NULL; i++) {
6695         const char* keyword = DATA[i][0];
6696         const char* value = DATA[i][1];
6697         const char* expected = DATA[i][2];
6698         const char* legacyType = NULL;
6699 
6700         legacyType = uloc_toLegacyType(keyword, value);
6701         if (expected == NULL) {
6702             if (legacyType != NULL) {
6703                 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType);
6704             }
6705         } else if (legacyType == NULL) {
6706             log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6707         } else if (uprv_strcmp(expected, "$IN") == 0) {
6708             if (legacyType != value) {
6709                 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value);
6710             }
6711         } else if (uprv_strcmp(legacyType, expected) != 0) {
6712             log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected);
6713         } else {
6714             log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword, value, legacyType);
6715         }
6716     }
6717 }
6718 
6719 
6720 
test_unicode_define(const char * namech,char ch,const char * nameu,UChar uch)6721 static void test_unicode_define(const char *namech, char ch,
6722                                 const char *nameu, UChar uch)
6723 {
6724     UChar asUch[1];
6725     asUch[0]=0;
6726     log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n",
6727                 namech, ch,(int)ch, nameu, (int) uch);
6728     u_charsToUChars(&ch, asUch, 1);
6729     if(asUch[0] != uch) {
6730         log_err("FAIL:  %s[\\x%02x,'%c'] maps to U+%04X, but %s = U+%04X\n",
6731                 namech, ch, (int)ch, (int)asUch[0], nameu, (int)uch);
6732     } else {
6733         log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]);
6734     }
6735 }
6736 
checkTerminating(const char * locale,const char * inLocale)6737 static void checkTerminating(const char* locale, const char* inLocale)
6738 {
6739     UErrorCode status = U_ZERO_ERROR;
6740     int32_t preflight_length = uloc_getDisplayName(
6741         locale, inLocale, NULL, 0, &status);
6742     if (status != U_BUFFER_OVERFLOW_ERROR) {
6743         log_err("uloc_getDisplayName(%s, %s) preflight failed",
6744                 locale, inLocale);
6745     }
6746     UChar buff[256];
6747     const UChar sentinel1 = 0x6C38; // 永- a Han unicode as sentinel.
6748     const UChar sentinel2 = 0x92D2; // 鋒- a Han unicode as sentinel.
6749 
6750     // 1. Test when we set the maxResultSize to preflight_length + 1.
6751     // Set sentinel1 in the buff[preflight_length-1] to check it will be
6752     // replaced with display name.
6753     buff[preflight_length-1] = sentinel1;
6754     // Set sentinel2 in the buff[preflight_length] to check it will be
6755     // replaced by null.
6756     buff[preflight_length] = sentinel2;
6757     // It should be properly null terminated at buff[preflight_length].
6758     status = U_ZERO_ERROR;
6759     int32_t length = uloc_getDisplayName(
6760         locale, inLocale, buff, preflight_length + 1, &status);
6761     const char* result = U_SUCCESS(status) ?
6762         aescstrdup(buff, length) : "(undefined when failure)";
6763     if (length != preflight_length) {
6764         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 returns "
6765                 "length %d different from preflight length %d. Returns '%s'\n",
6766                 locale, inLocale, length, preflight_length, result);
6767     }
6768     if (U_ZERO_ERROR != status) {
6769         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 should "
6770                 "set status to U_ZERO_ERROR but got %d %s. Returns %s\n",
6771                 locale, inLocale, status, myErrorName(status), result);
6772     }
6773     if (buff[length-1] == sentinel1) {
6774         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 does "
6775                 "not change memory in the end of buffer while it should. "
6776                 "Returns %s\n",
6777                 locale, inLocale, result);
6778     }
6779     if (buff[length] != 0x0000) {
6780         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 should "
6781                 "null terminate at buff[length] but does not %x. Returns %s\n",
6782                 locale, inLocale, buff[length], result);
6783     }
6784 
6785     // 2. Test when we only set the maxResultSize to preflight_length.
6786 
6787     // Set sentinel1 in the buff[preflight_length-1] to check it will be
6788     // replaced with display name.
6789     buff[preflight_length-1] = sentinel1;
6790     // Set sentinel2 in the buff[preflight_length] to check it won't be replaced
6791     // by null.
6792     buff[preflight_length] = sentinel2;
6793     status = U_ZERO_ERROR;
6794     length = uloc_getDisplayName(
6795         locale, inLocale, buff, preflight_length, &status);
6796     result = U_SUCCESS(status) ?
6797         aescstrdup(buff, length) : "(undefined when failure)";
6798 
6799     if (length != preflight_length) {
6800         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length return "
6801                 "length %d different from preflight length %d. Returns '%s'\n",
6802                 locale, inLocale, length, preflight_length, result);
6803     }
6804     if (U_STRING_NOT_TERMINATED_WARNING != status) {
6805         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length should "
6806                 "set status to U_STRING_NOT_TERMINATED_WARNING but got %d %s. "
6807                 "Returns %s\n",
6808                 locale, inLocale, status, myErrorName(status), result);
6809     }
6810     if (buff[length-1] == sentinel1) {
6811         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length does not "
6812                 "change memory in the end of buffer while it should. Returns "
6813                 "'%s'\n",
6814                 locale, inLocale, result);
6815     }
6816     if (buff[length] != sentinel2) {
6817         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length change "
6818                 "memory beyond maxResultSize to %x. Returns '%s'\n",
6819                 locale, inLocale, buff[length], result);
6820     }
6821     if (buff[preflight_length - 1] == 0x0000) {
6822         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length null "
6823                 "terminated while it should not. Return '%s'\n",
6824                 locale, inLocale, result);
6825     }
6826 
6827     // 3. Test when we only set the maxResultSize to preflight_length-1.
6828     // Set sentinel1 in the buff[preflight_length-1] to check it will not be
6829     // replaced with display name.
6830     buff[preflight_length-1] = sentinel1;
6831     // Set sentinel2 in the buff[preflight_length] to check it won't be replaced
6832     // by null.
6833     buff[preflight_length] = sentinel2;
6834     status = U_ZERO_ERROR;
6835     length = uloc_getDisplayName(
6836         locale, inLocale, buff, preflight_length - 1, &status);
6837     result = U_SUCCESS(status) ?
6838         aescstrdup(buff, length) : "(undefined when failure)";
6839 
6840     if (length != preflight_length) {
6841         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 return "
6842                 "length %d different from preflight length %d. Returns '%s'\n",
6843                 locale, inLocale, length, preflight_length, result);
6844     }
6845     if (U_BUFFER_OVERFLOW_ERROR != status) {
6846         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 should "
6847                 "set status to U_BUFFER_OVERFLOW_ERROR but got %d %s. "
6848                 "Returns %s\n",
6849                 locale, inLocale, status, myErrorName(status), result);
6850     }
6851     if (buff[length-1] != sentinel1) {
6852         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 should "
6853                 "not change memory in beyond the maxResultSize. Returns '%s'\n",
6854                 locale, inLocale, result);
6855     }
6856     if (buff[length] != sentinel2) {
6857         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 change "
6858                 "memory beyond maxResultSize to %x. Returns '%s'\n",
6859                 locale, inLocale, buff[length], result);
6860     }
6861     if (buff[preflight_length - 2] == 0x0000) {
6862         log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 null "
6863                 "terminated while it should not. Return '%s'\n",
6864                 locale, inLocale, result);
6865     }
6866 }
6867 
Test21157CorrectTerminating(void)6868 static void Test21157CorrectTerminating(void) {
6869     checkTerminating("fr", "fr");
6870     checkTerminating("fr_BE", "fr");
6871     checkTerminating("fr_Latn_BE", "fr");
6872     checkTerminating("fr_Latn", "fr");
6873     checkTerminating("fr", "fr");
6874     checkTerminating("fr-CN", "fr");
6875     checkTerminating("fr-Hant-CN", "fr");
6876     checkTerminating("fr-Hant", "fr");
6877     checkTerminating("zh-u-co-pinyin", "fr");
6878 }
6879 
6880 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6881 
TestUnicodeDefines(void)6882 static void TestUnicodeDefines(void) {
6883   TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE);
6884   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
6885   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
6886 }
6887 
TestIsRightToLeft()6888 static void TestIsRightToLeft() {
6889     // API test only. More test cases in intltest/LocaleTest.
6890     if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6891         log_err("uloc_isRightToLeft() failed");
6892     }
6893 }
6894 
6895 typedef struct {
6896     const char * badLocaleID;
6897     const char * displayLocale;
6898     const char * expectedName;
6899     UErrorCode   expectedStatus;
6900 } BadLocaleItem;
6901 
6902 static const BadLocaleItem badLocaleItems[] = {
6903     { "-9223372036854775808", "en", "Unknown language (9223372036854775808)", U_USING_DEFAULT_WARNING },
6904     /* add more in the future */
6905     { NULL, NULL, NULL, U_ZERO_ERROR } /* terminator */
6906 };
6907 
6908 enum { kUBufDispNameMax = 128, kBBufDispNameMax = 256 };
6909 
TestBadLocaleIDs()6910 static void TestBadLocaleIDs() {
6911     const BadLocaleItem* itemPtr;
6912     for (itemPtr = badLocaleItems; itemPtr->badLocaleID != NULL; itemPtr++) {
6913         UChar ubufExpect[kUBufDispNameMax], ubufGet[kUBufDispNameMax];
6914         UErrorCode status = U_ZERO_ERROR;
6915         int32_t ulenExpect = u_unescape(itemPtr->expectedName, ubufExpect, kUBufDispNameMax);
6916         int32_t ulenGet = uloc_getDisplayName(itemPtr->badLocaleID, itemPtr->displayLocale, ubufGet, kUBufDispNameMax, &status);
6917         if (status != itemPtr->expectedStatus ||
6918                 (U_SUCCESS(status) && (ulenGet != ulenExpect || u_strncmp(ubufGet, ubufExpect, ulenExpect) != 0))) {
6919             char bbufExpect[kBBufDispNameMax], bbufGet[kBBufDispNameMax];
6920             u_austrncpy(bbufExpect, ubufExpect, ulenExpect);
6921             u_austrncpy(bbufGet, ubufGet, ulenGet);
6922             log_err("FAIL: For localeID %s, displayLocale %s, calling uloc_getDisplayName:\n"
6923                     "    expected status %-26s, name (len %2d): %s\n"
6924                     "    got      status %-26s, name (len %2d): %s\n",
6925                     itemPtr->badLocaleID, itemPtr->displayLocale,
6926                     u_errorName(itemPtr->expectedStatus), ulenExpect, bbufExpect,
6927                     u_errorName(status), ulenGet, bbufGet );
6928         }
6929     }
6930 }
6931 
6932 // Test case for ICU-20370.
6933 // The issue shows as an Address Sanitizer failure.
TestBug20370()6934 static void TestBug20370() {
6935     const char *localeID = "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar";
6936     uint32_t lcid = uloc_getLCID(localeID);
6937     if (lcid != 0) {
6938         log_err("FAIL: Expected LCID value of 0 for invalid localeID input.");
6939     }
6940 }
6941 
6942 // Test case for ICU-20149
6943 // Handle the duplicate U extension attribute
TestBug20149()6944 static void TestBug20149() {
6945     const char *localeID = "zh-u-foo-foo-co-pinyin";
6946     char locale[256];
6947     UErrorCode status = U_ZERO_ERROR;
6948     int32_t parsedLen;
6949     locale[0] = '\0';
6950     uloc_forLanguageTag(localeID, locale, sizeof(locale), &parsedLen, &status);
6951     if (U_FAILURE(status) ||
6952         0 !=strcmp("zh@attribute=foo;collation=pinyin", locale)) {
6953         log_err("ERROR: in uloc_forLanguageTag %s return %s\n", myErrorName(status), locale);
6954     }
6955 }
6956 
6957 #if !UCONFIG_NO_FORMATTING
6958 typedef enum UldnNameType {
6959     TEST_ULDN_LOCALE,
6960     TEST_ULDN_LANGUAGE,
6961     TEST_ULDN_SCRIPT,
6962     TEST_ULDN_REGION,
6963     TEST_ULOC_LOCALE,   // only valid with optStdMidLong
6964     TEST_ULOC_LANGUAGE, // only valid with optStdMidLong
6965     TEST_ULOC_SCRIPT,   // only valid with optStdMidLong
6966     TEST_ULOC_REGION,   // only valid with optStdMidLong
6967 } UldnNameType;
6968 
6969 typedef struct {
6970     const char * localeToName; // NULL to terminate a list of these
6971     UldnNameType nameType;
6972     const UChar * expectResult;
6973 } UldnItem;
6974 
6975 typedef struct {
6976     const char *            displayLocale;
6977     const UDisplayContext * displayOptions; // set of 3 UDisplayContext items
6978     const UldnItem *        testItems;
6979     int32_t                 countItems;
6980 } UldnLocAndOpts;
6981 
6982 static const UDisplayContext optStdMidLong[3] = {UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UDISPCTX_LENGTH_FULL};
6983 static const UDisplayContext optStdMidShrt[3] = {UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UDISPCTX_LENGTH_SHORT};
6984 static const UDisplayContext optDiaMidLong[3] = {UDISPCTX_DIALECT_NAMES,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UDISPCTX_LENGTH_FULL};
6985 static const UDisplayContext optDiaMidShrt[3] = {UDISPCTX_DIALECT_NAMES,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UDISPCTX_LENGTH_SHORT};
6986 
6987 static const UldnItem en_StdMidLong[] = {
6988 	{ "en_US",                  TEST_ULDN_LOCALE, u"English (United States)" },
6989 	{ "en",                     TEST_ULDN_LANGUAGE, u"English" },
6990 	{ "en_US",                  TEST_ULOC_LOCALE, u"English (United States)" },
6991 	{ "en_US",                  TEST_ULOC_LANGUAGE, u"English" },
6992 	{ "en",                     TEST_ULOC_LANGUAGE, u"English" },
6993 	// https://unicode-org.atlassian.net/browse/ICU-20870
6994 	{ "fa_AF",                  TEST_ULDN_LOCALE, u"Persian (Afghanistan)" },
6995 	{ "prs",                    TEST_ULDN_LOCALE, u"Dari" },
6996 	{ "prs_AF",                 TEST_ULDN_LOCALE, u"Dari (Afghanistan)" },
6997 	{ "prs_TJ",                 TEST_ULDN_LOCALE, u"Dari (Tajikistan)" },
6998 	{ "prs",                    TEST_ULDN_LANGUAGE, u"Dari" },
6999 	{ "prs",                    TEST_ULOC_LANGUAGE, u"Dari" },
7000 	// https://unicode-org.atlassian.net/browse/ICU-21742
7001 	{ "ji",                     TEST_ULDN_LOCALE, u"Yiddish" },
7002 	{ "ji_US",                  TEST_ULDN_LOCALE, u"Yiddish (United States)" },
7003 	{ "ji",                     TEST_ULDN_LANGUAGE, u"Yiddish" },
7004 	{ "ji_US",                  TEST_ULOC_LOCALE, u"Yiddish (United States)" },
7005 	{ "ji",                     TEST_ULOC_LANGUAGE, u"Yiddish" },
7006 	// https://unicode-org.atlassian.net/browse/ICU-11563
7007 	{ "mo",                     TEST_ULDN_LOCALE, u"Romanian" },
7008 	{ "mo_MD",                  TEST_ULDN_LOCALE, u"Romanian (Moldova)" },
7009 	{ "mo",                     TEST_ULDN_LANGUAGE, u"Romanian" },
7010 	{ "mo_MD",                  TEST_ULOC_LOCALE, u"Romanian (Moldova)" },
7011 	{ "mo",                     TEST_ULOC_LANGUAGE, u"Romanian" },
7012 };
7013 
7014 static const UldnItem en_StdMidShrt[] = {
7015 	{ "en_US",                  TEST_ULDN_LOCALE, u"English (US)" },
7016 	{ "en",                     TEST_ULDN_LANGUAGE, u"English" },
7017 };
7018 
7019 static const UldnItem en_DiaMidLong[] = {
7020 	{ "en_US",                  TEST_ULDN_LOCALE, u"American English" },
7021 	{ "fa_AF",                  TEST_ULDN_LOCALE, u"Dari" },
7022 	{ "prs",                    TEST_ULDN_LOCALE, u"Dari" },
7023 	{ "prs_AF",                 TEST_ULDN_LOCALE, u"Dari (Afghanistan)" },
7024 	{ "prs_TJ",                 TEST_ULDN_LOCALE, u"Dari (Tajikistan)" },
7025 	{ "prs",                    TEST_ULDN_LANGUAGE, u"Dari" },
7026 	{ "mo",                     TEST_ULDN_LOCALE, u"Romanian" },
7027 	{ "mo",                     TEST_ULDN_LANGUAGE, u"Romanian" },
7028 };
7029 
7030 static const UldnItem en_DiaMidShrt[] = {
7031 	{ "en_US",                  TEST_ULDN_LOCALE, u"US English" },
7032 };
7033 
7034 static const UldnItem ro_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-11563
7035 	{ "mo",                     TEST_ULDN_LOCALE, u"română" },
7036 	{ "mo_MD",                  TEST_ULDN_LOCALE, u"română (Republica Moldova)" },
7037 	{ "mo",                     TEST_ULDN_LANGUAGE, u"română" },
7038 	{ "mo_MD",                  TEST_ULOC_LOCALE, u"română (Republica Moldova)" },
7039 	{ "mo",                     TEST_ULOC_LANGUAGE, u"română" },
7040 };
7041 
7042 static const UldnItem yi_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-21742
7043 	{ "ji",                     TEST_ULDN_LOCALE, u"ייִדיש" },
7044 	{ "ji_US",                  TEST_ULDN_LOCALE, u"ייִדיש (פֿאַראייניגטע שטאַטן)" },
7045 	{ "ji",                     TEST_ULDN_LANGUAGE, u"ייִדיש" },
7046 	{ "ji_US",                  TEST_ULOC_LOCALE, u"ייִדיש (פֿאַראייניגטע שטאַטן)" },
7047 	{ "ji",                     TEST_ULOC_LANGUAGE, u"ייִדיש" },
7048 };
7049 
7050 static const UldnItem zh_DiaMidLong[] = {
7051     // zh and zh_Hant both have dialect names for the following in ICU 73
7052     { "ar_001",                 TEST_ULDN_LOCALE, u"现代标准阿拉伯语" },
7053     { "nl_BE",                  TEST_ULDN_LOCALE, u"弗拉芒语" },
7054     { "ro_MD",                  TEST_ULDN_LOCALE, u"摩尔多瓦语" },
7055     // zh has dialect names for the following in ICU 73
7056     { "en_AU",                  TEST_ULDN_LOCALE, u"澳大利亚英语" },
7057     { "en_CA",                  TEST_ULDN_LOCALE, u"加拿大英语" },
7058     { "en_GB",                  TEST_ULDN_LOCALE, u"英国英语" },
7059     { "en_US",                  TEST_ULDN_LOCALE, u"美国英语" },
7060     { "es_419",                 TEST_ULDN_LOCALE, u"拉丁美洲西班牙语" },
7061     { "es_ES",                  TEST_ULDN_LOCALE, u"欧洲西班牙语" },
7062     { "es_MX",                  TEST_ULDN_LOCALE, u"墨西哥西班牙语" },
7063     { "fr_CA",                  TEST_ULDN_LOCALE, u"加拿大法语" },
7064     { "fr_CH",                  TEST_ULDN_LOCALE, u"瑞士法语" },
7065 };
7066 
7067 static const UldnItem zh_Hant_DiaMidLong[] = {
7068     // zh and zh_Hant both have dialect names for the following in ICU 73
7069     { "ar_001",                 TEST_ULDN_LOCALE, u"現代標準阿拉伯文" },
7070     { "nl_BE",                  TEST_ULDN_LOCALE, u"佛蘭芒文" },
7071     { "ro_MD",                  TEST_ULDN_LOCALE, u"摩爾多瓦文" },
7072     // zh_Hant no dialect names for the following in ICU-73,
7073     // use standard name
7074     { "en_AU",                  TEST_ULDN_LOCALE, u"英文(澳洲)" },
7075     { "en_CA",                  TEST_ULDN_LOCALE, u"英文(加拿大)" },
7076     { "en_GB",                  TEST_ULDN_LOCALE, u"英文(英國)" },
7077     { "en_US",                  TEST_ULDN_LOCALE, u"英文(美國)" },
7078     { "es_419",                 TEST_ULDN_LOCALE, u"西班牙文(拉丁美洲)" },
7079     { "es_ES",                  TEST_ULDN_LOCALE, u"西班牙文(西班牙)" },
7080     { "es_MX",                  TEST_ULDN_LOCALE, u"西班牙文(墨西哥)" },
7081     { "fr_CA",                  TEST_ULDN_LOCALE, u"法文(加拿大)" },
7082     { "fr_CH",                  TEST_ULDN_LOCALE, u"法文(瑞士)" },
7083 };
7084 
7085 static const UldnLocAndOpts uldnLocAndOpts[] = {
7086     { "en", optStdMidLong,      en_StdMidLong,      UPRV_LENGTHOF(en_StdMidLong) },
7087     { "en", optStdMidShrt,      en_StdMidShrt,      UPRV_LENGTHOF(en_StdMidShrt) },
7088     { "en", optDiaMidLong,      en_DiaMidLong,      UPRV_LENGTHOF(en_DiaMidLong) },
7089     { "en", optDiaMidShrt,      en_DiaMidShrt,      UPRV_LENGTHOF(en_DiaMidShrt) },
7090     { "ro", optStdMidLong,      ro_StdMidLong,      UPRV_LENGTHOF(ro_StdMidLong) },
7091     { "yi", optStdMidLong,      yi_StdMidLong,      UPRV_LENGTHOF(yi_StdMidLong) },
7092     { "zh", optDiaMidLong,      zh_DiaMidLong,      UPRV_LENGTHOF(zh_DiaMidLong) },
7093     { "zh_Hant", optDiaMidLong, zh_Hant_DiaMidLong, UPRV_LENGTHOF(zh_Hant_DiaMidLong) },
7094     { NULL, NULL, NULL, 0 }
7095 };
7096 
7097 enum { kUNameBuf = 128, kBNameBuf = 256 };
7098 
TestUldnNameVariants()7099 static void TestUldnNameVariants() {
7100     const UldnLocAndOpts * uloPtr;
7101     for (uloPtr = uldnLocAndOpts; uloPtr->displayLocale != NULL; uloPtr++) {
7102         UErrorCode status = U_ZERO_ERROR;
7103         ULocaleDisplayNames * uldn = uldn_openForContext(uloPtr->displayLocale, (UDisplayContext*)uloPtr->displayOptions, 3, &status);
7104         if (U_FAILURE(status)) {
7105             log_data_err("uldn_openForContext fails, displayLocale %s, contexts %03X %03X %03X: %s - Are you missing data?\n",
7106                     uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2],
7107                     u_errorName(status) );
7108             continue;
7109         }
7110         // API coverage: Expect to get back the dialect handling which is
7111         // the first item in the displayOptions test data.
7112         UDialectHandling dh = uldn_getDialectHandling(uldn);
7113         UDisplayContext dhContext = (UDisplayContext)dh;  // same numeric values
7114         if (dhContext != uloPtr->displayOptions[0]) {
7115             log_err("uldn_getDialectHandling()=%03X != expected UDisplayContext %03X\n",
7116                     dhContext, uloPtr->displayOptions[0]);
7117         }
7118         const UldnItem * itemPtr = uloPtr->testItems;
7119         int32_t itemCount = uloPtr->countItems;
7120         for (; itemCount-- > 0; itemPtr++) {
7121             UChar uget[kUNameBuf];
7122             int32_t ulenget, ulenexp;
7123             const char* typeString;
7124             status = U_ZERO_ERROR;
7125             switch (itemPtr->nameType) {
7126                 case TEST_ULDN_LOCALE:
7127                     ulenget = uldn_localeDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status);
7128                     typeString = "uldn_localeDisplayName";
7129                     break;
7130                 case TEST_ULDN_LANGUAGE:
7131                     ulenget = uldn_languageDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status);
7132                     typeString = "uldn_languageDisplayName";
7133                   break;
7134                 case TEST_ULDN_SCRIPT:
7135                     ulenget = uldn_scriptDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status);
7136                     typeString = "uldn_scriptDisplayName";
7137                     break;
7138                 case TEST_ULDN_REGION:
7139                     ulenget = uldn_regionDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status);
7140                     typeString = "uldn_regionDisplayName";
7141                     break;
7142                 case TEST_ULOC_LOCALE:
7143                     ulenget = uloc_getDisplayName(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status);
7144                     typeString = "uloc_getDisplayName";
7145                     break;
7146                 case TEST_ULOC_LANGUAGE:
7147                     ulenget = uloc_getDisplayLanguage(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status);
7148                     typeString = "uloc_getDisplayLanguage";
7149                     break;
7150                 case TEST_ULOC_SCRIPT:
7151                     ulenget = uloc_getDisplayScript(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status);
7152                     typeString = "uloc_getDisplayScript";
7153                     break;
7154                 case TEST_ULOC_REGION:
7155                     ulenget = uloc_getDisplayCountry(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status);
7156                     typeString = "uloc_getDisplayCountry";
7157                     break;
7158                 default:
7159                     continue;
7160             }
7161             if (U_FAILURE(status)) {
7162                 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s: %s\n",
7163                         typeString, uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2],
7164                         itemPtr->localeToName, u_errorName(status) );
7165                 continue;
7166             }
7167             ulenexp = u_strlen(itemPtr->expectResult);
7168             if (ulenget != ulenexp || u_strncmp(uget, itemPtr->expectResult, ulenexp) != 0) {
7169                 char bexp[kBNameBuf], bget[kBNameBuf];
7170                 u_strToUTF8(bexp, kBNameBuf, NULL, itemPtr->expectResult, ulenexp, &status);
7171                 u_strToUTF8(bget, kBNameBuf, NULL, uget, ulenget, &status);
7172                 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s:\n    expect %2d: %s\n    get    %2d: %s\n",
7173                         typeString, uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2],
7174                         itemPtr->localeToName, ulenexp, bexp, ulenget, bget );
7175             }
7176         }
7177 
7178         uldn_close(uldn);
7179     }
7180 }
7181 #endif
7182 
TestUsingDefaultWarning()7183 static void TestUsingDefaultWarning() {
7184     UChar buff[256];
7185     char errorOutputBuff[256];
7186     UErrorCode status = U_ZERO_ERROR;
7187     const char* language = "jJj";
7188     int32_t length = uloc_getDisplayLanguage(language, "de", buff, 256, &status);
7189     if (status != U_USING_DEFAULT_WARNING ||
7190         u_strcmp(buff, u"jjj") != 0 ||
7191         length != 3) {
7192         u_UCharsToChars(buff, errorOutputBuff, length+1);
7193         log_err("ERROR: in uloc_getDisplayLanguage %s return len:%d %s with status %d %s\n",
7194                 language, length, errorOutputBuff, status, myErrorName(status));
7195     }
7196 
7197     status = U_ZERO_ERROR;
7198     const char* script = "und-lALA";
7199     length = uloc_getDisplayScript(script, "de", buff, 256, &status);
7200     if (status != U_USING_DEFAULT_WARNING ||
7201         u_strcmp(buff, u"Lala") != 0 ||
7202         length != 4) {
7203         u_UCharsToChars(buff, errorOutputBuff, length+1);
7204         log_err("ERROR: in uloc_getDisplayScript %s return len:%d %s with status %d %s\n",
7205                 script, length, errorOutputBuff, status, myErrorName(status));
7206     }
7207 
7208     status = U_ZERO_ERROR;
7209     const char* region = "und-wt";
7210     length = uloc_getDisplayCountry(region, "de", buff, 256, &status);
7211     if (status != U_USING_DEFAULT_WARNING ||
7212         u_strcmp(buff, u"WT") != 0 ||
7213         length != 2) {
7214         u_UCharsToChars(buff, errorOutputBuff, length+1);
7215         log_err("ERROR: in uloc_getDisplayCountry %s return len:%d %s with status %d %s\n",
7216                 region, length, errorOutputBuff, status, myErrorName(status));
7217     }
7218 
7219     status = U_ZERO_ERROR;
7220     const char* variant = "und-abcde";
7221     length = uloc_getDisplayVariant(variant, "de", buff, 256, &status);
7222     if (status != U_USING_DEFAULT_WARNING ||
7223         u_strcmp(buff, u"ABCDE") != 0 ||
7224         length != 5) {
7225         u_UCharsToChars(buff, errorOutputBuff, length+1);
7226         log_err("ERROR: in uloc_getDisplayVariant %s return len:%d %s with status %d %s\n",
7227                 variant, length, errorOutputBuff, status, myErrorName(status));
7228     }
7229 
7230     status = U_ZERO_ERROR;
7231     const char* keyword = "postCODE";
7232     length = uloc_getDisplayKeyword(keyword, "de", buff, 256, &status);
7233     if (status != U_USING_DEFAULT_WARNING ||
7234         u_strcmp(buff, u"postCODE") != 0 ||
7235         length != 8) {
7236         u_UCharsToChars(buff, errorOutputBuff, length+1);
7237         log_err("ERROR: in uloc_getDisplayKeyword %s return len:%d %s with status %d %s\n",
7238                 keyword, length, errorOutputBuff, status, myErrorName(status));
7239     }
7240 
7241     status = U_ZERO_ERROR;
7242     const char* keyword_value = "de_DE@postCode=fOObAR";
7243     length = uloc_getDisplayKeywordValue(keyword_value, keyword, "de", buff, 256, &status);
7244     if (status != U_USING_DEFAULT_WARNING ||
7245         u_strcmp(buff, u"fOObAR") != 0 ||
7246         length != 6) {
7247         u_UCharsToChars(buff, errorOutputBuff, length+1);
7248         log_err("ERROR: in uloc_getDisplayKeywordValue %s %s return len:%d %s with status %d %s\n",
7249                 keyword_value, keyword, length, errorOutputBuff, status, myErrorName(status));
7250       }
7251 }
7252 
7253 // Test case for ICU-20575
7254 // This test checks if the environment variable LANG is set,
7255 // and if so ensures that both C and C.UTF-8 cause ICU's default locale to be en_US_POSIX.
TestCDefaultLocale()7256 static void TestCDefaultLocale() {
7257     const char *defaultLocale = uloc_getDefault();
7258     char *env_var = getenv("LANG");
7259     if (env_var == NULL) {
7260       log_verbose("Skipping TestCDefaultLocale test, as the LANG variable is not set.");
7261       return;
7262     }
7263     if (getenv("LC_ALL") != NULL) {
7264       log_verbose("Skipping TestCDefaultLocale test, as the LC_ALL variable is set.");
7265       return;
7266     }
7267     if ((strcmp(env_var, "C") == 0 || strcmp(env_var, "C.UTF-8") == 0) && strcmp(defaultLocale, "en_US_POSIX") != 0) {
7268       log_err("The default locale for LANG=%s should be en_US_POSIX, not %s\n", env_var, defaultLocale);
7269     }
7270 }
7271 
7272 // Test case for ICU-21449
TestBug21449InfiniteLoop()7273 static void TestBug21449InfiniteLoop() {
7274     UErrorCode status = U_ZERO_ERROR;
7275     const char* invalidLocaleId = RES_PATH_SEPARATOR_S;
7276 
7277     // The issue causes an infinite loop to occur when looking up a non-existent resource for the invalid locale ID,
7278     // so the test is considered passed if the call to the API below returns anything at all.
7279     uloc_getDisplayLanguage(invalidLocaleId, invalidLocaleId, NULL, 0, &status);
7280 }
7281 
7282 // rdar://79296849 and https://unicode-org.atlassian.net/browse/ICU-21639
TestExcessivelyLongIDs(void)7283 static void TestExcessivelyLongIDs(void) {
7284     const char* reallyLongID =
7285         "de-u-cu-eur-em-default-hc-h23-ks-level1-lb-strict-lw-normal-ms-metric"
7286         "-nu-latn-rg-atzzzz-sd-atat1-ss-none-tz-atvie-va-posix";
7287     char minimizedID[ULOC_FULLNAME_CAPACITY];
7288     char maximizedID[ULOC_FULLNAME_CAPACITY];
7289     int32_t actualMinimizedLength = 0;
7290     int32_t actualMaximizedLength = 0;
7291     UErrorCode err = U_ZERO_ERROR;
7292 
7293     actualMinimizedLength = uloc_minimizeSubtags(reallyLongID, minimizedID, ULOC_FULLNAME_CAPACITY, &err);
7294     assertTrue("uloc_minimizeSubtags() with too-small buffer didn't fail as expected",
7295             U_FAILURE(err) && actualMinimizedLength > ULOC_FULLNAME_CAPACITY);
7296 
7297     err = U_ZERO_ERROR;
7298     actualMaximizedLength = uloc_addLikelySubtags(reallyLongID, maximizedID, ULOC_FULLNAME_CAPACITY, &err);
7299     assertTrue("uloc_addLikelySubtags() with too-small buffer didn't fail as expected",
7300             U_FAILURE(err) && actualMaximizedLength > ULOC_FULLNAME_CAPACITY);
7301 
7302     err = U_ZERO_ERROR;
7303     char* realMinimizedID = (char*)uprv_malloc(actualMinimizedLength + 1);
7304     uloc_minimizeSubtags(reallyLongID, realMinimizedID, actualMinimizedLength + 1, &err);
7305     if (assertSuccess("uloc_minimizeSubtags() failed", &err)) {
7306         assertEquals("Wrong result from uloc_minimizeSubtags()",
7307                      "de__POSIX@colstrength=primary;currency=eur;em=default;hours=h23;lb=strict;"
7308                          "lw=normal;measure=metric;numbers=latn;rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna",
7309                      realMinimizedID);
7310     }
7311     uprv_free(realMinimizedID);
7312 
7313     char* realMaximizedID = (char*)uprv_malloc(actualMaximizedLength + 1);
7314     uloc_addLikelySubtags(reallyLongID, realMaximizedID, actualMaximizedLength + 1, &err);
7315     if (assertSuccess("uloc_addLikelySubtags() failed", &err)) {
7316         assertEquals("Wrong result from uloc_addLikelySubtags()",
7317                      "de_Latn_DE_POSIX@colstrength=primary;currency=eur;em=default;hours=h23;lb=strict;"
7318                          "lw=normal;measure=metric;numbers=latn;rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna",
7319                      realMaximizedID);
7320     }
7321     uprv_free(realMaximizedID);
7322 }
7323