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