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