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