• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
1678         const char *expectedLocaleIDNoKeywords;
1679         const char *expectedCanonicalID;
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",
1697             "de_DE@currency=EUR",
1698             {"","","","","","",""},
1699             0,
1700             U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1701         },
1702         {
1703             "de_DE@euro;collation=phonebook",
1704             "de_DE", /* error result; bad format */
1705             "de_DE", /* error result; bad format */
1706             "de_DE", /* error result; bad format */
1707             {"","","","","","",""},
1708             0,
1709             U_INVALID_FORMAT_ERROR
1710         }
1711     };
1712     UErrorCode status = U_ZERO_ERROR;
1713 
1714     int32_t i = 0, j = 0;
1715     int32_t resultLen = 0;
1716     char buffer[256];
1717     UEnumeration *keywords;
1718     int32_t keyCount = 0;
1719     const char *keyword = NULL;
1720     int32_t keywordLen = 0;
1721 
1722     for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
1723         status = U_ZERO_ERROR;
1724         *buffer = 0;
1725         keywords = uloc_openKeywords(testCases[i].localeID, &status);
1726 
1727         if(status != testCases[i].expectedStatus) {
1728             log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1729                     testCases[i].localeID,
1730                     u_errorName(testCases[i].expectedStatus), u_errorName(status));
1731         }
1732         status = U_ZERO_ERROR;
1733         if(keywords) {
1734             if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
1735                 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1736             }
1737             if(keyCount) {
1738                 j = 0;
1739                 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1740                     if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1741                         log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1742                     }
1743                     j++;
1744                 }
1745                 j = 0;
1746                 uenum_reset(keywords, &status);
1747                 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1748                     if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1749                         log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1750                     }
1751                     j++;
1752                 }
1753             }
1754             uenum_close(keywords);
1755         }
1756         resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
1757         (void)resultLen;    /* Suppress set but not used warning. */
1758         if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
1759             log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1760                     testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
1761         }
1762         resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
1763         if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
1764             log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1765                     testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
1766         }
1767     }
1768 
1769 }
1770 
TestKeywordVariantParsing(void)1771 static void TestKeywordVariantParsing(void)
1772 {
1773     static const struct {
1774         const char *localeID;
1775         const char *keyword;
1776         const char *expectedValue;
1777     } testCases[] = {
1778         { "de_DE@  C o ll A t i o n   = Phonebook   ", "c o ll a t i o n", "Phonebook" },
1779         { "de_DE", "collation", ""},
1780         { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1781         { "de_DE@currency = euro; CoLLaTion   = PHONEBOOk", "collatiON", "PHONEBOOk" },
1782     };
1783 
1784     UErrorCode status = U_ZERO_ERROR;
1785 
1786     int32_t i = 0;
1787     int32_t resultLen = 0;
1788     char buffer[256];
1789 
1790     for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
1791         *buffer = 0;
1792         resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
1793         (void)resultLen;    /* Suppress set but not used warning. */
1794         if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
1795             log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1796                 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
1797         }
1798     }
1799 }
1800 
1801 static const struct {
1802   const char *l; /* locale */
1803   const char *k; /* kw */
1804   const char *v; /* value */
1805   const char *x; /* expected */
1806 } kwSetTestCases[] = {
1807 #if 1
1808   { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1809   { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1810   { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1811   { "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 */
1812   { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1813   { "de", "Currency", "CHF", "de@currency=CHF" },
1814   { "de", "Currency", "CHF", "de@currency=CHF" },
1815 
1816   { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1817   { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1818   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1819   { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1820   { "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 */
1821   { "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 */
1822   { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1823   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1824 #endif
1825 #if 1
1826   { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1827   { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1828   { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1829   { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1830   { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1831   { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1832   { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1833   { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1834   { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1835 #endif
1836 #if 1
1837   /* removal tests */
1838   /* 1. removal of item at end */
1839   { "de@collation=phonebook;currency=CHF", "currency",   "", "de@collation=phonebook" },
1840   { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
1841   /* 2. removal of item at beginning */
1842   { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1843   { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
1844   /* 3. removal of an item not there */
1845   { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
1846   /* 4. removal of only item */
1847   { "de@collation=phonebook", "collation", NULL, "de" },
1848 #endif
1849   { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1850 };
1851 
1852 
TestKeywordSet(void)1853 static void TestKeywordSet(void)
1854 {
1855     int32_t i = 0;
1856     int32_t resultLen = 0;
1857     char buffer[1024];
1858 
1859     char cbuffer[1024];
1860 
1861     for(i = 0; i < sizeof(kwSetTestCases)/sizeof(kwSetTestCases[0]); i++) {
1862         UErrorCode status = U_ZERO_ERROR;
1863         memset(buffer,'%',1023);
1864         strcpy(buffer, kwSetTestCases[i].l);
1865 
1866         uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
1867         if(strcmp(buffer,cbuffer)) {
1868           log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
1869         }
1870           /* sanity check test case results for canonicity */
1871         uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
1872         if(strcmp(kwSetTestCases[i].x,cbuffer)) {
1873           log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
1874         }
1875 
1876         resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
1877         if(U_FAILURE(status)) {
1878           log_err("Err on test case %d: got error %s\n", i, u_errorName(status));
1879           continue;
1880         }
1881         if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
1882           log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1883                   kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
1884         } else {
1885           log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
1886         }
1887     }
1888 }
1889 
TestKeywordSetError(void)1890 static void TestKeywordSetError(void)
1891 {
1892     char buffer[1024];
1893     UErrorCode status;
1894     int32_t res;
1895     int32_t i;
1896     int32_t blen;
1897 
1898     /* 0-test whether an error condition modifies the buffer at all */
1899     blen=0;
1900     i=0;
1901     memset(buffer,'%',1023);
1902     status = U_ZERO_ERROR;
1903     res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1904     if(status != U_ILLEGAL_ARGUMENT_ERROR) {
1905         log_err("expected illegal err got %s\n", u_errorName(status));
1906         return;
1907     }
1908     /*  if(res!=strlen(kwSetTestCases[i].x)) {
1909     log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1910     return;
1911     } */
1912     if(buffer[blen]!='%') {
1913         log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1914         return;
1915     }
1916     log_verbose("0-buffer modify OK\n");
1917 
1918     for(i=0;i<=2;i++) {
1919         /* 1- test a short buffer with growing text */
1920         blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1921         memset(buffer,'%',1023);
1922         strcpy(buffer,kwSetTestCases[i].l);
1923         status = U_ZERO_ERROR;
1924         res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1925         if(status != U_BUFFER_OVERFLOW_ERROR) {
1926             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);
1927             return;
1928         }
1929         if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
1930             log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1931             return;
1932         }
1933         if(buffer[blen]!='%') {
1934             log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1935             return;
1936         }
1937         log_verbose("1/%d-buffer modify OK\n",i);
1938     }
1939 
1940     for(i=3;i<=4;i++) {
1941         /* 2- test a short buffer - text the same size or shrinking   */
1942         blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1943         memset(buffer,'%',1023);
1944         strcpy(buffer,kwSetTestCases[i].l);
1945         status = U_ZERO_ERROR;
1946         res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1947         if(status != U_ZERO_ERROR) {
1948             log_err("expected zero error got %s\n", u_errorName(status));
1949             return;
1950         }
1951         if(buffer[blen+1]!='%') {
1952             log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
1953             return;
1954         }
1955         if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
1956             log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1957             return;
1958         }
1959         if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
1960             log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1961                 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
1962         } else {
1963             log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
1964                 buffer);
1965         }
1966         log_verbose("2/%d-buffer modify OK\n",i);
1967     }
1968 }
1969 
_canonicalize(int32_t selector,const char * localeID,char * result,int32_t resultCapacity,UErrorCode * ec)1970 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
1971                              const char* localeID,
1972                              char* result,
1973                              int32_t resultCapacity,
1974                              UErrorCode* ec) {
1975     /* YOU can change this to use function pointers if you like */
1976     switch (selector) {
1977     case 0:
1978         return uloc_getName(localeID, result, resultCapacity, ec);
1979     case 1:
1980         return uloc_canonicalize(localeID, result, resultCapacity, ec);
1981     default:
1982         return -1;
1983     }
1984 }
1985 
TestCanonicalization(void)1986 static void TestCanonicalization(void)
1987 {
1988     static const struct {
1989         const char *localeID;    /* input */
1990         const char *getNameID;   /* expected getName() result */
1991         const char *canonicalID; /* expected canonicalize() result */
1992     } testCases[] = {
1993         { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
1994           "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
1995           "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
1996         { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
1997         { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
1998         { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
1999         { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2000         { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2001         { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2002         { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2003         { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2004         { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2005         { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2006         { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2007         { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2008         { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2009         { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2010         { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2011         { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2012         { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2013         { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2014         { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2015         { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2016         { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2017         { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2018         { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2019         { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2020         { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2021         { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2022         { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2023         { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2024         { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2025         { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2026         { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
2027         { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2028         { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2029         { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2030         { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2031         { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2032         { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2033         { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2034         { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2035         { "de-1901", "de__1901", "de__1901" }, /* registered name */
2036         { "de-1906", "de__1906", "de__1906" }, /* registered name */
2037         { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2038         { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2039         { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2040         { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2041         { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2042         { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2043         { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2044 
2045         /* posix behavior that used to be performed by getName */
2046         { "mr.utf8", "mr.utf8", "mr" },
2047         { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2048         { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2049         { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2050         { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2051         { "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 */
2052 
2053         /* fleshing out canonicalization */
2054         /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2055         { "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" },
2056         /* already-canonical ids are not changed */
2057         { "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" },
2058         /* PRE_EURO and EURO conversions don't affect other keywords */
2059         { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2060         { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2061         /* currency keyword overrides PRE_EURO and EURO currency */
2062         { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2063         { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2064         /* norwegian is just too weird, if we handle things in their full generality */
2065         { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2066 
2067         /* test cases reflecting internal resource bundle usage */
2068         { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2069         { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2070         { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2071         { "ja_JP", "ja_JP", "ja_JP" },
2072 
2073         /* test case for "i-default" */
2074         { "i-default", "en@x=i-default", "en@x=i-default" }
2075     };
2076 
2077     static const char* label[] = { "getName", "canonicalize" };
2078 
2079     UErrorCode status = U_ZERO_ERROR;
2080     int32_t i, j, resultLen = 0, origResultLen;
2081     char buffer[256];
2082 
2083     for (i=0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2084         for (j=0; j<2; ++j) {
2085             const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
2086             *buffer = 0;
2087             status = U_ZERO_ERROR;
2088 
2089             if (expected == NULL) {
2090                 expected = uloc_getDefault();
2091             }
2092 
2093             /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2094             origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
2095             if (status != U_BUFFER_OVERFLOW_ERROR) {
2096                 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2097                         label[j], testCases[i].localeID, u_errorName(status));
2098                 continue;
2099             }
2100             status = U_ZERO_ERROR;
2101             resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
2102             if (U_FAILURE(status)) {
2103                 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2104                         label[j], testCases[i].localeID, u_errorName(status));
2105                 continue;
2106             }
2107             if(uprv_strcmp(expected, buffer) != 0) {
2108                 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2109                         label[j], testCases[i].localeID, buffer, expected);
2110             } else {
2111                 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2112                             label[j], testCases[i].localeID, buffer);
2113             }
2114             if (resultLen != (int32_t)strlen(buffer)) {
2115                 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2116                         label[j], testCases[i].localeID, resultLen, strlen(buffer));
2117             }
2118             if (origResultLen != resultLen) {
2119                 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2120                         label[j], testCases[i].localeID, origResultLen, resultLen);
2121             }
2122         }
2123     }
2124 }
2125 
TestDisplayKeywords(void)2126 static void TestDisplayKeywords(void)
2127 {
2128     int32_t i;
2129 
2130     static const struct {
2131         const char *localeID;
2132         const char *displayLocale;
2133         UChar displayKeyword[200];
2134     } testCases[] = {
2135         {   "ca_ES@currency=ESP",         "de_AT",
2136             {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2137         },
2138         {   "ja_JP@calendar=japanese",         "de",
2139             { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2140         },
2141         {   "de_DE@collation=traditional",       "de_DE",
2142             {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2143         },
2144     };
2145     for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2146         UErrorCode status = U_ZERO_ERROR;
2147         const char* keyword =NULL;
2148         int32_t keywordLen = 0;
2149         int32_t keywordCount = 0;
2150         UChar *displayKeyword=NULL;
2151         int32_t displayKeywordLen = 0;
2152         UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2153         for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2154               if(U_FAILURE(status)){
2155                   log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
2156                   break;
2157               }
2158               /* the uenum_next returns NUL terminated string */
2159               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2160               /* fetch the displayKeyword */
2161               displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2162               if(status==U_BUFFER_OVERFLOW_ERROR){
2163                   status = U_ZERO_ERROR;
2164                   displayKeywordLen++; /* for null termination */
2165                   displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
2166                   displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2167                   if(U_FAILURE(status)){
2168                       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));
2169                       break;
2170                   }
2171                   if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
2172                       if (status == U_USING_DEFAULT_WARNING) {
2173                           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));
2174                       } else {
2175                           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);
2176                       }
2177                       break;
2178                   }
2179               }else{
2180                   log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
2181               }
2182 
2183               free(displayKeyword);
2184 
2185         }
2186         uenum_close(keywordEnum);
2187     }
2188 }
2189 
TestDisplayKeywordValues(void)2190 static void TestDisplayKeywordValues(void){
2191     int32_t i;
2192 
2193     static const struct {
2194         const char *localeID;
2195         const char *displayLocale;
2196         UChar displayKeywordValue[500];
2197     } testCases[] = {
2198         {   "ca_ES@currency=ESP",         "de_AT",
2199             {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2200         },
2201         {   "de_AT@currency=ATS",         "fr_FR",
2202             {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2203         },
2204         {   "de_DE@currency=DEM",         "it",
2205             {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2206         },
2207         {   "el_GR@currency=GRD",         "en",
2208             {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2209         },
2210         {   "eu_ES@currency=ESP",         "it_IT",
2211             {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2212         },
2213         {   "de@collation=phonebook",     "es",
2214             {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}
2215         },
2216 
2217         { "de_DE@collation=phonebook",  "es",
2218           {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}
2219         },
2220         { "es_ES@collation=traditional","de",
2221           {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}
2222         },
2223         { "ja_JP@calendar=japanese",    "de",
2224            {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2225         },
2226     };
2227     for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2228         UErrorCode status = U_ZERO_ERROR;
2229         const char* keyword =NULL;
2230         int32_t keywordLen = 0;
2231         int32_t keywordCount = 0;
2232         UChar *displayKeywordValue = NULL;
2233         int32_t displayKeywordValueLen = 0;
2234         UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2235         for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2236               if(U_FAILURE(status)){
2237                   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));
2238                   break;
2239               }
2240               /* the uenum_next returns NUL terminated string */
2241               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2242 
2243               /* fetch the displayKeywordValue */
2244               displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2245               if(status==U_BUFFER_OVERFLOW_ERROR){
2246                   status = U_ZERO_ERROR;
2247                   displayKeywordValueLen++; /* for null termination */
2248                   displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2249                   displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2250                   if(U_FAILURE(status)){
2251                       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));
2252                       break;
2253                   }
2254                   if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
2255                       if (status == U_USING_DEFAULT_WARNING) {
2256                           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));
2257                       } else {
2258                           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));
2259                       }
2260                       break;
2261                   }
2262               }else{
2263                   log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2264               }
2265               free(displayKeywordValue);
2266         }
2267         uenum_close(keywordEnum);
2268     }
2269     {
2270         /* test a multiple keywords */
2271         UErrorCode status = U_ZERO_ERROR;
2272         const char* keyword =NULL;
2273         int32_t keywordLen = 0;
2274         int32_t keywordCount = 0;
2275         const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
2276         const char* displayLocale = "de";
2277         static const UChar expected[][50] = {
2278             {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2279 
2280             {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2281             {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2282         };
2283 
2284         UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
2285 
2286         for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
2287               UChar *displayKeywordValue = NULL;
2288               int32_t displayKeywordValueLen = 0;
2289               if(U_FAILURE(status)){
2290                   log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
2291                   break;
2292               }
2293               /* the uenum_next returns NUL terminated string */
2294               keyword = uenum_next(keywordEnum, &keywordLen, &status);
2295 
2296               /* fetch the displayKeywordValue */
2297               displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2298               if(status==U_BUFFER_OVERFLOW_ERROR){
2299                   status = U_ZERO_ERROR;
2300                   displayKeywordValueLen++; /* for null termination */
2301                   displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2302                   displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2303                   if(U_FAILURE(status)){
2304                       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));
2305                       break;
2306                   }
2307                   if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
2308                       if (status == U_USING_DEFAULT_WARNING) {
2309                           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));
2310                       } else {
2311                           log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
2312                       }
2313                       break;
2314                   }
2315               }else{
2316                   log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2317               }
2318               free(displayKeywordValue);
2319         }
2320         uenum_close(keywordEnum);
2321 
2322     }
2323     {
2324         /* Test non existent keywords */
2325         UErrorCode status = U_ZERO_ERROR;
2326         const char* localeID = "es";
2327         const char* displayLocale = "de";
2328         UChar *displayKeywordValue = NULL;
2329         int32_t displayKeywordValueLen = 0;
2330 
2331         /* fetch the displayKeywordValue */
2332         displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2333         if(U_FAILURE(status)) {
2334           log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
2335         } else if(displayKeywordValueLen != 0) {
2336           log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
2337         }
2338     }
2339 }
2340 
2341 
TestGetBaseName(void)2342 static void TestGetBaseName(void) {
2343     static const struct {
2344         const char *localeID;
2345         const char *baseName;
2346     } testCases[] = {
2347         { "de_DE@  C o ll A t i o n   = Phonebook   ", "de_DE" },
2348         { "de@currency = euro; CoLLaTion   = PHONEBOOk", "de" },
2349         { "ja@calendar = buddhist", "ja" }
2350     };
2351 
2352     int32_t i = 0, baseNameLen = 0;
2353     char baseName[256];
2354     UErrorCode status = U_ZERO_ERROR;
2355 
2356     for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2357         baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
2358         (void)baseNameLen;    /* Suppress set but not used warning. */
2359         if(strcmp(testCases[i].baseName, baseName)) {
2360             log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2361                 testCases[i].localeID, testCases[i].baseName, baseName);
2362             return;
2363         }
2364     }
2365 }
2366 
TestTrailingNull(void)2367 static void TestTrailingNull(void) {
2368   const char* localeId = "zh_Hans";
2369   UChar buffer[128]; /* sufficient for this test */
2370   int32_t len;
2371   UErrorCode status = U_ZERO_ERROR;
2372   int i;
2373 
2374   len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status);
2375   if (len > 128) {
2376     log_err("buffer too small");
2377     return;
2378   }
2379 
2380   for (i = 0; i < len; ++i) {
2381     if (buffer[i] == 0) {
2382       log_err("name contained null");
2383       return;
2384     }
2385   }
2386 }
2387 
2388 /* Jitterbug 4115 */
TestDisplayNameWarning(void)2389 static void TestDisplayNameWarning(void) {
2390     UChar name[256];
2391     int32_t size;
2392     UErrorCode status = U_ZERO_ERROR;
2393 
2394     size = uloc_getDisplayLanguage("qqq", "kl", name, sizeof(name)/sizeof(name[0]), &status);
2395     (void)size;    /* Suppress set but not used warning. */
2396     if (status != U_USING_DEFAULT_WARNING) {
2397         log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2398             u_errorName(status));
2399     }
2400 }
2401 
2402 
2403 /**
2404  * Compare two locale IDs.  If they are equal, return 0.  If `string'
2405  * starts with `prefix' plus an additional element, that is, string ==
2406  * prefix + '_' + x, then return 1.  Otherwise return a value < 0.
2407  */
_loccmp(const char * string,const char * prefix)2408 static UBool _loccmp(const char* string, const char* prefix) {
2409     int32_t slen = (int32_t)uprv_strlen(string),
2410             plen = (int32_t)uprv_strlen(prefix);
2411     int32_t c = uprv_strncmp(string, prefix, plen);
2412     /* 'root' is less than everything */
2413     if (uprv_strcmp(prefix, "root") == 0) {
2414         return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
2415     }
2416     if (c) return -1; /* mismatch */
2417     if (slen == plen) return 0;
2418     if (string[plen] == '_') return 1;
2419     return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2420 }
2421 
_checklocs(const char * label,const char * req,const char * valid,const char * actual)2422 static void _checklocs(const char* label,
2423                        const char* req,
2424                        const char* valid,
2425                        const char* actual) {
2426     /* We want the valid to be strictly > the bogus requested locale,
2427        and the valid to be >= the actual. */
2428     if (_loccmp(req, valid) > 0 &&
2429         _loccmp(valid, actual) >= 0) {
2430         log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2431                     label, req, valid, actual);
2432     } else {
2433         log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2434                 label, req, valid, actual);
2435     }
2436 }
2437 
TestGetLocale(void)2438 static void TestGetLocale(void) {
2439     UErrorCode ec = U_ZERO_ERROR;
2440     UParseError pe;
2441     UChar EMPTY[1] = {0};
2442 
2443     /* === udat === */
2444 #if !UCONFIG_NO_FORMATTING
2445     {
2446         UDateFormat *obj;
2447         const char *req = "en_US_REDWOODSHORES", *valid, *actual;
2448         obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
2449                         req,
2450                         NULL, 0,
2451                         NULL, 0, &ec);
2452         if (U_FAILURE(ec)) {
2453             log_data_err("udat_open failed.Error %s\n", u_errorName(ec));
2454             return;
2455         }
2456         valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2457         actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2458         if (U_FAILURE(ec)) {
2459             log_err("udat_getLocaleByType() failed\n");
2460             return;
2461         }
2462         _checklocs("udat", req, valid, actual);
2463         udat_close(obj);
2464     }
2465 #endif
2466 
2467     /* === ucal === */
2468 #if !UCONFIG_NO_FORMATTING
2469     {
2470         UCalendar *obj;
2471         const char *req = "fr_FR_PROVENCAL", *valid, *actual;
2472         obj = ucal_open(NULL, 0,
2473                         req,
2474                         UCAL_GREGORIAN,
2475                         &ec);
2476         if (U_FAILURE(ec)) {
2477             log_err("ucal_open failed with error: %s\n", u_errorName(ec));
2478             return;
2479         }
2480         valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2481         actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2482         if (U_FAILURE(ec)) {
2483             log_err("ucal_getLocaleByType() failed\n");
2484             return;
2485         }
2486         _checklocs("ucal", req, valid, actual);
2487         ucal_close(obj);
2488     }
2489 #endif
2490 
2491     /* === unum === */
2492 #if !UCONFIG_NO_FORMATTING
2493     {
2494         UNumberFormat *obj;
2495         const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
2496         obj = unum_open(UNUM_DECIMAL,
2497                         NULL, 0,
2498                         req,
2499                         &pe, &ec);
2500         if (U_FAILURE(ec)) {
2501             log_err("unum_open failed\n");
2502             return;
2503         }
2504         valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2505         actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2506         if (U_FAILURE(ec)) {
2507             log_err("unum_getLocaleByType() failed\n");
2508             return;
2509         }
2510         _checklocs("unum", req, valid, actual);
2511         unum_close(obj);
2512     }
2513 #endif
2514 
2515     /* === umsg === */
2516 #if 0
2517     /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2518 #if !UCONFIG_NO_FORMATTING
2519     {
2520         UMessageFormat *obj;
2521         const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
2522         UBool test;
2523         obj = umsg_open(EMPTY, 0,
2524                         req,
2525                         &pe, &ec);
2526         if (U_FAILURE(ec)) {
2527             log_err("umsg_open failed\n");
2528             return;
2529         }
2530         valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2531         actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2532         if (U_FAILURE(ec)) {
2533             log_err("umsg_getLocaleByType() failed\n");
2534             return;
2535         }
2536         /* We want the valid to be strictly > the bogus requested locale,
2537            and the valid to be >= the actual. */
2538         /* TODO MessageFormat is currently just storing the locale it is given.
2539            As a result, it will return whatever it was given, even if the
2540            locale is invalid. */
2541         test = (_cmpversion("3.2") <= 0) ?
2542             /* Here is the weakened test for 3.0: */
2543             (_loccmp(req, valid) >= 0) :
2544             /* Here is what the test line SHOULD be: */
2545             (_loccmp(req, valid) > 0);
2546 
2547         if (test &&
2548             _loccmp(valid, actual) >= 0) {
2549             log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2550         } else {
2551             log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2552         }
2553         umsg_close(obj);
2554     }
2555 #endif
2556 #endif
2557 
2558     /* === ubrk === */
2559 #if !UCONFIG_NO_BREAK_ITERATION
2560     {
2561         UBreakIterator *obj;
2562         const char *req = "ar_KW_ABDALI", *valid, *actual;
2563         obj = ubrk_open(UBRK_WORD,
2564                         req,
2565                         EMPTY,
2566                         0,
2567                         &ec);
2568         if (U_FAILURE(ec)) {
2569             log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
2570             return;
2571         }
2572         valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2573         actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2574         if (U_FAILURE(ec)) {
2575             log_err("ubrk_getLocaleByType() failed\n");
2576             return;
2577         }
2578         _checklocs("ubrk", req, valid, actual);
2579         ubrk_close(obj);
2580     }
2581 #endif
2582 
2583     /* === ucol === */
2584 #if !UCONFIG_NO_COLLATION
2585     {
2586         UCollator *obj;
2587         const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
2588         obj = ucol_open(req, &ec);
2589         if (U_FAILURE(ec)) {
2590             log_err("ucol_open failed - %s\n", u_errorName(ec));
2591             return;
2592         }
2593         valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2594         actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2595         if (U_FAILURE(ec)) {
2596             log_err("ucol_getLocaleByType() failed\n");
2597             return;
2598         }
2599         _checklocs("ucol", req, valid, actual);
2600         ucol_close(obj);
2601     }
2602 #endif
2603 }
TestEnglishExemplarCharacters(void)2604 static void TestEnglishExemplarCharacters(void) {
2605     UErrorCode status = U_ZERO_ERROR;
2606     int i;
2607     USet *exSet = NULL;
2608     UChar testChars[] = {
2609         0x61,   /* standard */
2610         0xE1,   /* auxiliary */
2611         0x41,   /* index */
2612         0x2D    /* punctuation */
2613     };
2614     ULocaleData *uld = ulocdata_open("en", &status);
2615     if (U_FAILURE(status)) {
2616         log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status));
2617         return;
2618     }
2619 
2620     for (i = 0; i < ULOCDATA_ES_COUNT; i++) {
2621         exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status);
2622         if (U_FAILURE(status)) {
2623             log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i);
2624             status = U_ZERO_ERROR;
2625             continue;
2626         }
2627         if (!uset_contains(exSet, (UChar32)testChars[i])) {
2628             log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i);
2629         }
2630     }
2631 
2632     uset_close(exSet);
2633     ulocdata_close(uld);
2634 }
2635 
TestNonexistentLanguageExemplars(void)2636 static void TestNonexistentLanguageExemplars(void) {
2637     /* JB 4068 - Nonexistent language */
2638     UErrorCode ec = U_ZERO_ERROR;
2639     ULocaleData *uld = ulocdata_open("qqq",&ec);
2640     if (ec != U_USING_DEFAULT_WARNING) {
2641         log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2642             u_errorName(ec));
2643     }
2644     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2645     ulocdata_close(uld);
2646 }
2647 
TestLocDataErrorCodeChaining(void)2648 static void TestLocDataErrorCodeChaining(void) {
2649     UErrorCode ec = U_USELESS_COLLATOR_ERROR;
2650     ulocdata_open(NULL, &ec);
2651     ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
2652     ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
2653     ulocdata_getMeasurementSystem(NULL, &ec);
2654     ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
2655     if (ec != U_USELESS_COLLATOR_ERROR) {
2656         log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
2657     }
2658 }
2659 
TestLanguageExemplarsFallbacks(void)2660 static void TestLanguageExemplarsFallbacks(void) {
2661     /* Test that en_US fallsback, but en doesn't fallback. */
2662     UErrorCode ec = U_ZERO_ERROR;
2663     ULocaleData *uld = ulocdata_open("en_US",&ec);
2664     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2665     if (ec != U_USING_FALLBACK_WARNING) {
2666         log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2667             u_errorName(ec));
2668     }
2669     ulocdata_close(uld);
2670     ec = U_ZERO_ERROR;
2671     uld = ulocdata_open("en",&ec);
2672     uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2673     if (ec != U_ZERO_ERROR) {
2674         log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2675             u_errorName(ec));
2676     }
2677     ulocdata_close(uld);
2678 }
2679 
acceptResult(UAcceptResult uar)2680 static const char *acceptResult(UAcceptResult uar) {
2681     return  udbg_enumName(UDBG_UAcceptResult, uar);
2682 }
2683 
TestAcceptLanguage(void)2684 static void TestAcceptLanguage(void) {
2685     UErrorCode status = U_ZERO_ERROR;
2686     UAcceptResult outResult;
2687     UEnumeration *available;
2688     char tmp[200];
2689     int i;
2690     int32_t rc = 0;
2691 
2692     struct {
2693         int32_t httpSet;       /**< Which of http[] should be used? */
2694         const char *icuSet;    /**< ? */
2695         const char *expect;    /**< The expected locale result */
2696         UAcceptResult res;     /**< The expected error code */
2697     } tests[] = {
2698         /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID },
2699         /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID },
2700         /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK },
2701         /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED },
2702         /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID },
2703 
2704         /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID },  /* XF */
2705         /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK },  /* XF */
2706         /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK },  /* XF */
2707     };
2708     const int32_t numTests = sizeof(tests)/sizeof(tests[0]);
2709     static const char *http[] = {
2710         /*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",
2711         /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2712         /*2*/ "en-wf, de-lx;q=0.8",
2713         /*3*/ "mga-ie;q=0.9, tlh",
2714         /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2715               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2716               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2717               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2718               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2719               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2720               "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2721               "es",
2722 
2723         /*5*/ "zh-xx;q=0.9, en;q=0.6",
2724         /*6*/ "ja-JA",
2725         /*7*/ "zh-xx;q=0.9",
2726     };
2727 
2728     for(i=0;i<numTests;i++) {
2729         outResult = -3;
2730         status=U_ZERO_ERROR;
2731         log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2732             i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2733 
2734         available = ures_openAvailableLocales(tests[i].icuSet, &status);
2735         tmp[0]=0;
2736         rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status);
2737         (void)rc;    /* Suppress set but not used warning. */
2738         uenum_close(available);
2739         log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
2740         if(outResult != tests[i].res) {
2741             log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
2742                 acceptResult( tests[i].res),
2743                 acceptResult( outResult));
2744             log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2745                 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res));
2746         }
2747         if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
2748             log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
2749             log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2750                 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2751         }
2752     }
2753 }
2754 
2755 static const char* LOCALE_ALIAS[][2] = {
2756     {"in", "id"},
2757     {"in_ID", "id_ID"},
2758     {"iw", "he"},
2759     {"iw_IL", "he_IL"},
2760     {"ji", "yi"},
2761     {"en_BU", "en_MM"},
2762     {"en_DY", "en_BJ"},
2763     {"en_HV", "en_BF"},
2764     {"en_NH", "en_VU"},
2765     {"en_RH", "en_ZW"},
2766     {"en_TP", "en_TL"},
2767     {"en_ZR", "en_CD"}
2768 };
isLocaleAvailable(UResourceBundle * resIndex,const char * loc)2769 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
2770     UErrorCode status = U_ZERO_ERROR;
2771     int32_t len = 0;
2772     ures_getStringByKey(resIndex, loc,&len, &status);
2773     if(U_FAILURE(status)){
2774         return FALSE;
2775     }
2776     return TRUE;
2777 }
2778 
TestCalendar()2779 static void TestCalendar() {
2780 #if !UCONFIG_NO_FORMATTING
2781     int i;
2782     UErrorCode status = U_ZERO_ERROR;
2783     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2784     if(U_FAILURE(status)){
2785         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2786         return;
2787     }
2788     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2789         const char* oldLoc = LOCALE_ALIAS[i][0];
2790         const char* newLoc = LOCALE_ALIAS[i][1];
2791         UCalendar* c1 = NULL;
2792         UCalendar* c2 = NULL;
2793 
2794         /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2795         const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2796         const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2797 
2798         if(!isLocaleAvailable(resIndex, newLoc)){
2799             continue;
2800         }
2801         c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
2802         c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
2803 
2804         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
2805             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2806         }
2807         log_verbose("ucal_getLocaleByType old:%s   new:%s\n", l1, l2);
2808         ucal_close(c1);
2809         ucal_close(c2);
2810     }
2811     ures_close(resIndex);
2812 #endif
2813 }
2814 
TestDateFormat()2815 static void TestDateFormat() {
2816 #if !UCONFIG_NO_FORMATTING
2817     int i;
2818     UErrorCode status = U_ZERO_ERROR;
2819     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2820     if(U_FAILURE(status)){
2821         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2822         return;
2823     }
2824     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2825         const char* oldLoc = LOCALE_ALIAS[i][0];
2826         const char* newLoc = LOCALE_ALIAS[i][1];
2827         UDateFormat* df1 = NULL;
2828         UDateFormat* df2 = NULL;
2829         const char* l1 = NULL;
2830         const char* l2 = NULL;
2831 
2832         if(!isLocaleAvailable(resIndex, newLoc)){
2833             continue;
2834         }
2835         df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
2836         df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
2837         if(U_FAILURE(status)){
2838             log_err("Creation of date format failed  %s\n", u_errorName(status));
2839             return;
2840         }
2841         /*Test function "getLocale"*/
2842         l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
2843         l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
2844         if(U_FAILURE(status)){
2845             log_err("Fetching the locale by type failed.  %s\n", u_errorName(status));
2846         }
2847         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2848             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2849         }
2850         log_verbose("udat_getLocaleByType old:%s   new:%s\n", l1, l2);
2851         udat_close(df1);
2852         udat_close(df2);
2853     }
2854     ures_close(resIndex);
2855 #endif
2856 }
2857 
TestCollation()2858 static void TestCollation() {
2859 #if !UCONFIG_NO_COLLATION
2860     int i;
2861     UErrorCode status = U_ZERO_ERROR;
2862     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2863     if(U_FAILURE(status)){
2864         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2865         return;
2866     }
2867     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2868         const char* oldLoc = LOCALE_ALIAS[i][0];
2869         const char* newLoc = LOCALE_ALIAS[i][1];
2870         UCollator* c1 = NULL;
2871         UCollator* c2 = NULL;
2872         const char* l1 = NULL;
2873         const char* l2 = NULL;
2874 
2875         status = U_ZERO_ERROR;
2876         if(!isLocaleAvailable(resIndex, newLoc)){
2877             continue;
2878         }
2879         if(U_FAILURE(status)){
2880             log_err("Creation of collators failed  %s\n", u_errorName(status));
2881             return;
2882         }
2883         c1 = ucol_open(oldLoc, &status);
2884         c2 = ucol_open(newLoc, &status);
2885         l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2886         l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2887         if(U_FAILURE(status)){
2888             log_err("Fetching the locale names failed failed  %s\n", u_errorName(status));
2889         }
2890         if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2891             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2892         }
2893         log_verbose("ucol_getLocaleByType old:%s   new:%s\n", l1, l2);
2894         ucol_close(c1);
2895         ucol_close(c2);
2896     }
2897     ures_close(resIndex);
2898 #endif
2899 }
2900 
2901 typedef struct OrientationStructTag {
2902     const char* localeId;
2903     ULayoutType character;
2904     ULayoutType line;
2905 } OrientationStruct;
2906 
ULayoutTypeToString(ULayoutType type)2907 static const char* ULayoutTypeToString(ULayoutType type)
2908 {
2909     switch(type)
2910     {
2911     case ULOC_LAYOUT_LTR:
2912         return "ULOC_LAYOUT_LTR";
2913         break;
2914     case ULOC_LAYOUT_RTL:
2915         return "ULOC_LAYOUT_RTL";
2916         break;
2917     case ULOC_LAYOUT_TTB:
2918         return "ULOC_LAYOUT_TTB";
2919         break;
2920     case ULOC_LAYOUT_BTT:
2921         return "ULOC_LAYOUT_BTT";
2922         break;
2923     case ULOC_LAYOUT_UNKNOWN:
2924         break;
2925     }
2926 
2927     return "Unknown enum value for ULayoutType!";
2928 }
2929 
TestOrientation()2930 static void  TestOrientation()
2931 {
2932     static const OrientationStruct toTest [] = {
2933         { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2934         { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2935         { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2936         { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2937         { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2938         { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2939         { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2940         { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2941         { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2942         { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB }
2943     };
2944 
2945     size_t i = 0;
2946     for (; i < sizeof(toTest) / sizeof(toTest[0]); ++i) {
2947         UErrorCode statusCO = U_ZERO_ERROR;
2948         UErrorCode statusLO = U_ZERO_ERROR;
2949         const char* const localeId = toTest[i].localeId;
2950         const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO);
2951         const ULayoutType expectedCO = toTest[i].character;
2952         const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO);
2953         const ULayoutType expectedLO = toTest[i].line;
2954         if (U_FAILURE(statusCO)) {
2955             log_err_status(statusCO,
2956                 "  unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
2957                 localeId,
2958                 u_errorName(statusCO));
2959         }
2960         else if (co != expectedCO) {
2961             log_err(
2962                 "  unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2963                 localeId,
2964                 ULayoutTypeToString(expectedCO),
2965                 ULayoutTypeToString(co));
2966         }
2967         if (U_FAILURE(statusLO)) {
2968             log_err_status(statusLO,
2969                 "  unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
2970                 localeId,
2971                 u_errorName(statusLO));
2972         }
2973         else if (lo != expectedLO) {
2974             log_err(
2975                 "  unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2976                 localeId,
2977                 ULayoutTypeToString(expectedLO),
2978                 ULayoutTypeToString(lo));
2979         }
2980     }
2981 }
2982 
TestULocale()2983 static void  TestULocale() {
2984     int i;
2985     UErrorCode status = U_ZERO_ERROR;
2986     UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2987     if(U_FAILURE(status)){
2988         log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2989         return;
2990     }
2991     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2992         const char* oldLoc = LOCALE_ALIAS[i][0];
2993         const char* newLoc = LOCALE_ALIAS[i][1];
2994         UChar name1[256], name2[256];
2995         char names1[256], names2[256];
2996         int32_t capacity = 256;
2997 
2998         status = U_ZERO_ERROR;
2999         if(!isLocaleAvailable(resIndex, newLoc)){
3000             continue;
3001         }
3002         uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
3003         if(U_FAILURE(status)){
3004             log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
3005         }
3006 
3007         uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
3008         if(U_FAILURE(status)){
3009             log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
3010         }
3011 
3012         if (u_strcmp(name1, name2)!=0) {
3013             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3014         }
3015         u_austrcpy(names1, name1);
3016         u_austrcpy(names2, name2);
3017         log_verbose("uloc_getDisplayName old:%s   new:%s\n", names1, names2);
3018     }
3019     ures_close(resIndex);
3020 
3021 }
3022 
TestUResourceBundle()3023 static void TestUResourceBundle() {
3024     const char* us1;
3025     const char* us2;
3026 
3027     UResourceBundle* rb1 = NULL;
3028     UResourceBundle* rb2 = NULL;
3029     UErrorCode status = U_ZERO_ERROR;
3030     int i;
3031     UResourceBundle *resIndex = NULL;
3032     if(U_FAILURE(status)){
3033         log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3034         return;
3035     }
3036     resIndex = ures_open(NULL,"res_index", &status);
3037     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3038 
3039         const char* oldLoc = LOCALE_ALIAS[i][0];
3040         const char* newLoc = LOCALE_ALIAS[i][1];
3041         if(!isLocaleAvailable(resIndex, newLoc)){
3042             continue;
3043         }
3044         rb1 = ures_open(NULL, oldLoc, &status);
3045         if (U_FAILURE(status)) {
3046             log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3047         }
3048 
3049         us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status);
3050 
3051         status = U_ZERO_ERROR;
3052         rb2 = ures_open(NULL, newLoc, &status);
3053         if (U_FAILURE(status)) {
3054             log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3055         }
3056         us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status);
3057 
3058         if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
3059             log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3060         }
3061 
3062         log_verbose("ures_getStringByKey old:%s   new:%s\n", us1, us2);
3063         ures_close(rb1);
3064         rb1 = NULL;
3065         ures_close(rb2);
3066         rb2 = NULL;
3067     }
3068     ures_close(resIndex);
3069 }
3070 
TestDisplayName()3071 static void TestDisplayName() {
3072 
3073     UChar oldCountry[256] = {'\0'};
3074     UChar newCountry[256] = {'\0'};
3075     UChar oldLang[256] = {'\0'};
3076     UChar newLang[256] = {'\0'};
3077     char country[256] ={'\0'};
3078     char language[256] ={'\0'};
3079     int32_t capacity = 256;
3080     int i =0;
3081     int j=0;
3082     for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3083         const char* oldLoc = LOCALE_ALIAS[i][0];
3084         const char* newLoc = LOCALE_ALIAS[i][1];
3085         UErrorCode status = U_ZERO_ERROR;
3086         int32_t available = uloc_countAvailable();
3087 
3088         for(j=0; j<available; j++){
3089 
3090             const char* dispLoc = uloc_getAvailable(j);
3091             int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
3092             int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
3093             int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
3094             int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
3095 
3096             int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
3097             int32_t langLen  = uloc_getLanguage(newLoc, language, capacity, &status);
3098             /* there is a display name for the current country ID */
3099             if(countryLen != newCountryLen ){
3100                 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
3101                     log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
3102                 }
3103             }
3104             /* there is a display name for the current lang ID */
3105             if(langLen!=newLangLen){
3106                 if(u_strncmp(oldLang,newLang,oldLangLen)){
3107                     log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc);                }
3108             }
3109         }
3110     }
3111 }
3112 
TestGetLocaleForLCID()3113 static void TestGetLocaleForLCID() {
3114     int32_t i, length, lengthPre;
3115     const char* testLocale = 0;
3116     UErrorCode status = U_ZERO_ERROR;
3117     char            temp2[40], temp3[40];
3118     uint32_t lcid;
3119 
3120     lcid = uloc_getLCID("en_US");
3121     if (lcid != 0x0409) {
3122         log_err("  uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
3123     }
3124 
3125     lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
3126     if (status != U_BUFFER_OVERFLOW_ERROR) {
3127         log_err("  unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
3128     }
3129     else {
3130         status = U_ZERO_ERROR;
3131     }
3132 
3133     length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
3134     if (U_FAILURE(status)) {
3135         log_err("  unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
3136         status = U_ZERO_ERROR;
3137     }
3138 
3139     if (length != lengthPre) {
3140         log_err("  uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
3141     }
3142 
3143     length = uloc_getLocaleForLCID(0x12345, temp2, sizeof(temp2)/sizeof(char), &status);
3144     if (U_SUCCESS(status)) {
3145         log_err("  unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
3146     }
3147     status = U_ZERO_ERROR;
3148 
3149     log_verbose("Testing getLocaleForLCID vs. locale data\n");
3150     for (i = 0; i < LOCALE_SIZE; i++) {
3151 
3152         testLocale=rawData2[NAME][i];
3153 
3154         log_verbose("Testing   %s ......\n", testLocale);
3155 
3156         sscanf(rawData2[LCID][i], "%x", &lcid);
3157         length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
3158         if (U_FAILURE(status)) {
3159             log_err("  unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
3160             status = U_ZERO_ERROR;
3161             continue;
3162         }
3163 
3164         if (length != uprv_strlen(temp2)) {
3165             log_err("  returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
3166         }
3167 
3168         /* Compare language, country, script */
3169         length = uloc_getLanguage(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3170         if (U_FAILURE(status)) {
3171             log_err("  couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3172             status = U_ZERO_ERROR;
3173         }
3174         else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
3175             log_err("  language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
3176         }
3177 
3178         length = uloc_getScript(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3179         if (U_FAILURE(status)) {
3180             log_err("  couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3181             status = U_ZERO_ERROR;
3182         }
3183         else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
3184             log_err("  script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
3185         }
3186 
3187         length = uloc_getCountry(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3188         if (U_FAILURE(status)) {
3189             log_err("  couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3190             status = U_ZERO_ERROR;
3191         }
3192         else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
3193             log_err("  country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
3194         }
3195     }
3196 
3197 }
3198 
3199 const char* const basic_maximize_data[][2] = {
3200   {
3201     "zu_Zzzz_Zz",
3202     "zu_Latn_ZA",
3203   }, {
3204     "ZU_Zz",
3205     "zu_Latn_ZA"
3206   }, {
3207     "zu_LATN",
3208     "zu_Latn_ZA"
3209   }, {
3210     "en_Zz",
3211     "en_Latn_US"
3212   }, {
3213     "en_us",
3214     "en_Latn_US"
3215   }, {
3216     "en_Kore",
3217     "en_Kore_US"
3218   }, {
3219     "en_Kore_Zz",
3220     "en_Kore_US"
3221   }, {
3222     "en_Kore_ZA",
3223     "en_Kore_ZA"
3224   }, {
3225     "en_Kore_ZA_POSIX",
3226     "en_Kore_ZA_POSIX"
3227   }, {
3228     "en_Gujr",
3229     "en_Gujr_US"
3230   }, {
3231     "en_ZA",
3232     "en_Latn_ZA"
3233   }, {
3234     "en_Gujr_Zz",
3235     "en_Gujr_US"
3236   }, {
3237     "en_Gujr_ZA",
3238     "en_Gujr_ZA"
3239   }, {
3240     "en_Gujr_ZA_POSIX",
3241     "en_Gujr_ZA_POSIX"
3242   }, {
3243     "en_US_POSIX_1901",
3244     "en_Latn_US_POSIX_1901"
3245   }, {
3246     "en_Latn__POSIX_1901",
3247     "en_Latn_US_POSIX_1901"
3248   }, {
3249     "en__POSIX_1901",
3250     "en_Latn_US_POSIX_1901"
3251   }, {
3252     "de__POSIX_1901",
3253     "de_Latn_DE_POSIX_1901"
3254   }, {
3255     "en_US_BOSTON",
3256     "en_Latn_US_BOSTON"
3257   }, {
3258     "th@calendar=buddhist",
3259     "th_Thai_TH@calendar=buddhist"
3260   }, {
3261     "ar_ZZ",
3262     "ar_Arab_EG"
3263   }, {
3264     "zh",
3265     "zh_Hans_CN"
3266   }, {
3267     "zh_TW",
3268     "zh_Hant_TW"
3269   }, {
3270     "zh_HK",
3271     "zh_Hant_HK"
3272   }, {
3273     "zh_Hant",
3274     "zh_Hant_TW"
3275   }, {
3276     "zh_Zzzz_CN",
3277     "zh_Hans_CN"
3278   }, {
3279     "und_US",
3280     "en_Latn_US"
3281   }, {
3282     "und_HK",
3283     "zh_Hant_HK"
3284   }, {
3285     "zzz",
3286     ""
3287   }, {
3288      "de_u_co_phonebk",
3289      "de_Latn_DE_U_CO_PHONEBK"
3290   }, {
3291      "de_Latn_u_co_phonebk",
3292      "de_Latn_DE_U_CO_PHONEBK"
3293   }, {
3294      "de_Latn_DE_u_co_phonebk",
3295      "de_Latn_DE_U_CO_PHONEBK"
3296   }
3297 };
3298 
3299 const char* const basic_minimize_data[][2] = {
3300   {
3301     "en_Latn_US",
3302     "en"
3303   }, {
3304     "en_Latn_US_POSIX_1901",
3305     "en__POSIX_1901"
3306   }, {
3307     "EN_Latn_US_POSIX_1901",
3308     "en__POSIX_1901"
3309   }, {
3310     "en_Zzzz_US_POSIX_1901",
3311     "en__POSIX_1901"
3312   }, {
3313     "de_Latn_DE_POSIX_1901",
3314     "de__POSIX_1901"
3315   }, {
3316     "und",
3317     ""
3318   }, {
3319     "en_Latn_US@calendar=gregorian",
3320     "en@calendar=gregorian"
3321   }
3322 };
3323 
3324 const char* const full_data[][3] = {
3325   {
3326     /*   "FROM", */
3327     /*   "ADD-LIKELY", */
3328     /*   "REMOVE-LIKELY" */
3329     /* }, { */
3330     "aa",
3331     "aa_Latn_ET",
3332     "aa"
3333   }, {
3334     "af",
3335     "af_Latn_ZA",
3336     "af"
3337   }, {
3338     "ak",
3339     "ak_Latn_GH",
3340     "ak"
3341   }, {
3342     "am",
3343     "am_Ethi_ET",
3344     "am"
3345   }, {
3346     "ar",
3347     "ar_Arab_EG",
3348     "ar"
3349   }, {
3350     "as",
3351     "as_Beng_IN",
3352     "as"
3353   }, {
3354     "az",
3355     "az_Latn_AZ",
3356     "az"
3357   }, {
3358     "be",
3359     "be_Cyrl_BY",
3360     "be"
3361   }, {
3362     "bg",
3363     "bg_Cyrl_BG",
3364     "bg"
3365   }, {
3366     "bn",
3367     "bn_Beng_BD",
3368     "bn"
3369   }, {
3370     "bo",
3371     "bo_Tibt_CN",
3372     "bo"
3373   }, {
3374     "bs",
3375     "bs_Latn_BA",
3376     "bs"
3377   }, {
3378     "ca",
3379     "ca_Latn_ES",
3380     "ca"
3381   }, {
3382     "ch",
3383     "ch_Latn_GU",
3384     "ch"
3385   }, {
3386     "chk",
3387     "chk_Latn_FM",
3388     "chk"
3389   }, {
3390     "cs",
3391     "cs_Latn_CZ",
3392     "cs"
3393   }, {
3394     "cy",
3395     "cy_Latn_GB",
3396     "cy"
3397   }, {
3398     "da",
3399     "da_Latn_DK",
3400     "da"
3401   }, {
3402     "de",
3403     "de_Latn_DE",
3404     "de"
3405   }, {
3406     "dv",
3407     "dv_Thaa_MV",
3408     "dv"
3409   }, {
3410     "dz",
3411     "dz_Tibt_BT",
3412     "dz"
3413   }, {
3414     "ee",
3415     "ee_Latn_GH",
3416     "ee"
3417   }, {
3418     "el",
3419     "el_Grek_GR",
3420     "el"
3421   }, {
3422     "en",
3423     "en_Latn_US",
3424     "en"
3425   }, {
3426     "es",
3427     "es_Latn_ES",
3428     "es"
3429   }, {
3430     "et",
3431     "et_Latn_EE",
3432     "et"
3433   }, {
3434     "eu",
3435     "eu_Latn_ES",
3436     "eu"
3437   }, {
3438     "fa",
3439     "fa_Arab_IR",
3440     "fa"
3441   }, {
3442     "fi",
3443     "fi_Latn_FI",
3444     "fi"
3445   }, {
3446     "fil",
3447     "fil_Latn_PH",
3448     "fil"
3449   }, {
3450     "fo",
3451     "fo_Latn_FO",
3452     "fo"
3453   }, {
3454     "fr",
3455     "fr_Latn_FR",
3456     "fr"
3457   }, {
3458     "fur",
3459     "fur_Latn_IT",
3460     "fur"
3461   }, {
3462     "ga",
3463     "ga_Latn_IE",
3464     "ga"
3465   }, {
3466     "gaa",
3467     "gaa_Latn_GH",
3468     "gaa"
3469   }, {
3470     "gl",
3471     "gl_Latn_ES",
3472     "gl"
3473   }, {
3474     "gn",
3475     "gn_Latn_PY",
3476     "gn"
3477   }, {
3478     "gu",
3479     "gu_Gujr_IN",
3480     "gu"
3481   }, {
3482     "ha",
3483     "ha_Latn_NG",
3484     "ha"
3485   }, {
3486     "haw",
3487     "haw_Latn_US",
3488     "haw"
3489   }, {
3490     "he",
3491     "he_Hebr_IL",
3492     "he"
3493   }, {
3494     "hi",
3495     "hi_Deva_IN",
3496     "hi"
3497   }, {
3498     "hr",
3499     "hr_Latn_HR",
3500     "hr"
3501   }, {
3502     "ht",
3503     "ht_Latn_HT",
3504     "ht"
3505   }, {
3506     "hu",
3507     "hu_Latn_HU",
3508     "hu"
3509   }, {
3510     "hy",
3511     "hy_Armn_AM",
3512     "hy"
3513   }, {
3514     "id",
3515     "id_Latn_ID",
3516     "id"
3517   }, {
3518     "ig",
3519     "ig_Latn_NG",
3520     "ig"
3521   }, {
3522     "ii",
3523     "ii_Yiii_CN",
3524     "ii"
3525   }, {
3526     "is",
3527     "is_Latn_IS",
3528     "is"
3529   }, {
3530     "it",
3531     "it_Latn_IT",
3532     "it"
3533   }, {
3534     "ja",
3535     "ja_Jpan_JP",
3536     "ja"
3537   }, {
3538     "ka",
3539     "ka_Geor_GE",
3540     "ka"
3541   }, {
3542     "kaj",
3543     "kaj_Latn_NG",
3544     "kaj"
3545   }, {
3546     "kam",
3547     "kam_Latn_KE",
3548     "kam"
3549   }, {
3550     "kk",
3551     "kk_Cyrl_KZ",
3552     "kk"
3553   }, {
3554     "kl",
3555     "kl_Latn_GL",
3556     "kl"
3557   }, {
3558     "km",
3559     "km_Khmr_KH",
3560     "km"
3561   }, {
3562     "kn",
3563     "kn_Knda_IN",
3564     "kn"
3565   }, {
3566     "ko",
3567     "ko_Kore_KR",
3568     "ko"
3569   }, {
3570     "kok",
3571     "kok_Deva_IN",
3572     "kok"
3573   }, {
3574     "kpe",
3575     "kpe_Latn_LR",
3576     "kpe"
3577   }, {
3578     "ku",
3579     "ku_Latn_TR",
3580     "ku"
3581   }, {
3582     "ky",
3583     "ky_Cyrl_KG",
3584     "ky"
3585   }, {
3586     "la",
3587     "la_Latn_VA",
3588     "la"
3589   }, {
3590     "ln",
3591     "ln_Latn_CD",
3592     "ln"
3593   }, {
3594     "lo",
3595     "lo_Laoo_LA",
3596     "lo"
3597   }, {
3598     "lt",
3599     "lt_Latn_LT",
3600     "lt"
3601   }, {
3602     "lv",
3603     "lv_Latn_LV",
3604     "lv"
3605   }, {
3606     "mg",
3607     "mg_Latn_MG",
3608     "mg"
3609   }, {
3610     "mh",
3611     "mh_Latn_MH",
3612     "mh"
3613   }, {
3614     "mk",
3615     "mk_Cyrl_MK",
3616     "mk"
3617   }, {
3618     "ml",
3619     "ml_Mlym_IN",
3620     "ml"
3621   }, {
3622     "mn",
3623     "mn_Cyrl_MN",
3624     "mn"
3625   }, {
3626     "mr",
3627     "mr_Deva_IN",
3628     "mr"
3629   }, {
3630     "ms",
3631     "ms_Latn_MY",
3632     "ms"
3633   }, {
3634     "mt",
3635     "mt_Latn_MT",
3636     "mt"
3637   }, {
3638     "my",
3639     "my_Mymr_MM",
3640     "my"
3641   }, {
3642     "na",
3643     "na_Latn_NR",
3644     "na"
3645   }, {
3646     "ne",
3647     "ne_Deva_NP",
3648     "ne"
3649   }, {
3650     "niu",
3651     "niu_Latn_NU",
3652     "niu"
3653   }, {
3654     "nl",
3655     "nl_Latn_NL",
3656     "nl"
3657   }, {
3658     "nn",
3659     "nn_Latn_NO",
3660     "nn"
3661   }, {
3662     "nr",
3663     "nr_Latn_ZA",
3664     "nr"
3665   }, {
3666     "nso",
3667     "nso_Latn_ZA",
3668     "nso"
3669   }, {
3670     "ny",
3671     "ny_Latn_MW",
3672     "ny"
3673   }, {
3674     "om",
3675     "om_Latn_ET",
3676     "om"
3677   }, {
3678     "or",
3679     "or_Orya_IN",
3680     "or"
3681   }, {
3682     "pa",
3683     "pa_Guru_IN",
3684     "pa"
3685   }, {
3686     "pa_Arab",
3687     "pa_Arab_PK",
3688     "pa_PK"
3689   }, {
3690     "pa_PK",
3691     "pa_Arab_PK",
3692     "pa_PK"
3693   }, {
3694     "pap",
3695     "pap_Latn_AW",
3696     "pap"
3697   }, {
3698     "pau",
3699     "pau_Latn_PW",
3700     "pau"
3701   }, {
3702     "pl",
3703     "pl_Latn_PL",
3704     "pl"
3705   }, {
3706     "ps",
3707     "ps_Arab_AF",
3708     "ps"
3709   }, {
3710     "pt",
3711     "pt_Latn_BR",
3712     "pt"
3713   }, {
3714     "rn",
3715     "rn_Latn_BI",
3716     "rn"
3717   }, {
3718     "ro",
3719     "ro_Latn_RO",
3720     "ro"
3721   }, {
3722     "ru",
3723     "ru_Cyrl_RU",
3724     "ru"
3725   }, {
3726     "rw",
3727     "rw_Latn_RW",
3728     "rw"
3729   }, {
3730     "sa",
3731     "sa_Deva_IN",
3732     "sa"
3733   }, {
3734     "se",
3735     "se_Latn_NO",
3736     "se"
3737   }, {
3738     "sg",
3739     "sg_Latn_CF",
3740     "sg"
3741   }, {
3742     "si",
3743     "si_Sinh_LK",
3744     "si"
3745   }, {
3746     "sid",
3747     "sid_Latn_ET",
3748     "sid"
3749   }, {
3750     "sk",
3751     "sk_Latn_SK",
3752     "sk"
3753   }, {
3754     "sl",
3755     "sl_Latn_SI",
3756     "sl"
3757   }, {
3758     "sm",
3759     "sm_Latn_WS",
3760     "sm"
3761   }, {
3762     "so",
3763     "so_Latn_SO",
3764     "so"
3765   }, {
3766     "sq",
3767     "sq_Latn_AL",
3768     "sq"
3769   }, {
3770     "sr",
3771     "sr_Cyrl_RS",
3772     "sr"
3773   }, {
3774     "ss",
3775     "ss_Latn_ZA",
3776     "ss"
3777   }, {
3778     "st",
3779     "st_Latn_ZA",
3780     "st"
3781   }, {
3782     "sv",
3783     "sv_Latn_SE",
3784     "sv"
3785   }, {
3786     "sw",
3787     "sw_Latn_TZ",
3788     "sw"
3789   }, {
3790     "ta",
3791     "ta_Taml_IN",
3792     "ta"
3793   }, {
3794     "te",
3795     "te_Telu_IN",
3796     "te"
3797   }, {
3798     "tet",
3799     "tet_Latn_TL",
3800     "tet"
3801   }, {
3802     "tg",
3803     "tg_Cyrl_TJ",
3804     "tg"
3805   }, {
3806     "th",
3807     "th_Thai_TH",
3808     "th"
3809   }, {
3810     "ti",
3811     "ti_Ethi_ET",
3812     "ti"
3813   }, {
3814     "tig",
3815     "tig_Ethi_ER",
3816     "tig"
3817   }, {
3818     "tk",
3819     "tk_Latn_TM",
3820     "tk"
3821   }, {
3822     "tkl",
3823     "tkl_Latn_TK",
3824     "tkl"
3825   }, {
3826     "tn",
3827     "tn_Latn_ZA",
3828     "tn"
3829   }, {
3830     "to",
3831     "to_Latn_TO",
3832     "to"
3833   }, {
3834     "tpi",
3835     "tpi_Latn_PG",
3836     "tpi"
3837   }, {
3838     "tr",
3839     "tr_Latn_TR",
3840     "tr"
3841   }, {
3842     "ts",
3843     "ts_Latn_ZA",
3844     "ts"
3845   }, {
3846     "tt",
3847     "tt_Cyrl_RU",
3848     "tt"
3849   }, {
3850     "tvl",
3851     "tvl_Latn_TV",
3852     "tvl"
3853   }, {
3854     "ty",
3855     "ty_Latn_PF",
3856     "ty"
3857   }, {
3858     "uk",
3859     "uk_Cyrl_UA",
3860     "uk"
3861   }, {
3862     "und",
3863     "en_Latn_US",
3864     "en"
3865   }, {
3866     "und_AD",
3867     "ca_Latn_AD",
3868     "ca_AD"
3869   }, {
3870     "und_AE",
3871     "ar_Arab_AE",
3872     "ar_AE"
3873   }, {
3874     "und_AF",
3875     "fa_Arab_AF",
3876     "fa_AF"
3877   }, {
3878     "und_AL",
3879     "sq_Latn_AL",
3880     "sq"
3881   }, {
3882     "und_AM",
3883     "hy_Armn_AM",
3884     "hy"
3885   }, {
3886     "und_AO",
3887     "pt_Latn_AO",
3888     "pt_AO"
3889   }, {
3890     "und_AR",
3891     "es_Latn_AR",
3892     "es_AR"
3893   }, {
3894     "und_AS",
3895     "sm_Latn_AS",
3896     "sm_AS"
3897   }, {
3898     "und_AT",
3899     "de_Latn_AT",
3900     "de_AT"
3901   }, {
3902     "und_AW",
3903     "nl_Latn_AW",
3904     "nl_AW"
3905   }, {
3906     "und_AX",
3907     "sv_Latn_AX",
3908     "sv_AX"
3909   }, {
3910     "und_AZ",
3911     "az_Latn_AZ",
3912     "az"
3913   }, {
3914     "und_Arab",
3915     "ar_Arab_EG",
3916     "ar"
3917   }, {
3918     "und_Arab_IN",
3919     "ur_Arab_IN",
3920     "ur_IN"
3921   }, {
3922     "und_Arab_PK",
3923     "ur_Arab_PK",
3924     "ur"
3925   }, {
3926     "und_Arab_SN",
3927     "ar_Arab_SN",
3928     "ar_SN"
3929   }, {
3930     "und_Armn",
3931     "hy_Armn_AM",
3932     "hy"
3933   }, {
3934     "und_BA",
3935     "bs_Latn_BA",
3936     "bs"
3937   }, {
3938     "und_BD",
3939     "bn_Beng_BD",
3940     "bn"
3941   }, {
3942     "und_BE",
3943     "nl_Latn_BE",
3944     "nl_BE"
3945   }, {
3946     "und_BF",
3947     "fr_Latn_BF",
3948     "fr_BF"
3949   }, {
3950     "und_BG",
3951     "bg_Cyrl_BG",
3952     "bg"
3953   }, {
3954     "und_BH",
3955     "ar_Arab_BH",
3956     "ar_BH"
3957   }, {
3958     "und_BI",
3959     "rn_Latn_BI",
3960     "rn"
3961   }, {
3962     "und_BJ",
3963     "fr_Latn_BJ",
3964     "fr_BJ"
3965   }, {
3966     "und_BN",
3967     "ms_Latn_BN",
3968     "ms_BN"
3969   }, {
3970     "und_BO",
3971     "es_Latn_BO",
3972     "es_BO"
3973   }, {
3974     "und_BR",
3975     "pt_Latn_BR",
3976     "pt"
3977   }, {
3978     "und_BT",
3979     "dz_Tibt_BT",
3980     "dz"
3981   }, {
3982     "und_BY",
3983     "be_Cyrl_BY",
3984     "be"
3985   }, {
3986     "und_Beng",
3987     "bn_Beng_BD",
3988     "bn"
3989   }, {
3990     "und_Beng_IN",
3991     "bn_Beng_IN",
3992     "bn_IN"
3993   }, {
3994     "und_CD",
3995     "sw_Latn_CD",
3996     "sw_CD"
3997   }, {
3998     "und_CF",
3999     "fr_Latn_CF",
4000     "fr_CF"
4001   }, {
4002     "und_CG",
4003     "fr_Latn_CG",
4004     "fr_CG"
4005   }, {
4006     "und_CH",
4007     "de_Latn_CH",
4008     "de_CH"
4009   }, {
4010     "und_CI",
4011     "fr_Latn_CI",
4012     "fr_CI"
4013   }, {
4014     "und_CL",
4015     "es_Latn_CL",
4016     "es_CL"
4017   }, {
4018     "und_CM",
4019     "fr_Latn_CM",
4020     "fr_CM"
4021   }, {
4022     "und_CN",
4023     "zh_Hans_CN",
4024     "zh"
4025   }, {
4026     "und_CO",
4027     "es_Latn_CO",
4028     "es_CO"
4029   }, {
4030     "und_CR",
4031     "es_Latn_CR",
4032     "es_CR"
4033   }, {
4034     "und_CU",
4035     "es_Latn_CU",
4036     "es_CU"
4037   }, {
4038     "und_CV",
4039     "pt_Latn_CV",
4040     "pt_CV"
4041   }, {
4042     "und_CY",
4043     "el_Grek_CY",
4044     "el_CY"
4045   }, {
4046     "und_CZ",
4047     "cs_Latn_CZ",
4048     "cs"
4049   }, {
4050     "und_Cher",
4051     "chr_Cher_US",
4052     "chr"
4053   }, {
4054     "und_Cyrl",
4055     "ru_Cyrl_RU",
4056     "ru"
4057   }, {
4058     "und_Cyrl_KZ",
4059     "ru_Cyrl_KZ",
4060     "ru_KZ"
4061   }, {
4062     "und_DE",
4063     "de_Latn_DE",
4064     "de"
4065   }, {
4066     "und_DJ",
4067     "aa_Latn_DJ",
4068     "aa_DJ"
4069   }, {
4070     "und_DK",
4071     "da_Latn_DK",
4072     "da"
4073   }, {
4074     "und_DO",
4075     "es_Latn_DO",
4076     "es_DO"
4077   }, {
4078     "und_DZ",
4079     "ar_Arab_DZ",
4080     "ar_DZ"
4081   }, {
4082     "und_Deva",
4083     "hi_Deva_IN",
4084     "hi"
4085   }, {
4086     "und_EC",
4087     "es_Latn_EC",
4088     "es_EC"
4089   }, {
4090     "und_EE",
4091     "et_Latn_EE",
4092     "et"
4093   }, {
4094     "und_EG",
4095     "ar_Arab_EG",
4096     "ar"
4097   }, {
4098     "und_EH",
4099     "ar_Arab_EH",
4100     "ar_EH"
4101   }, {
4102     "und_ER",
4103     "ti_Ethi_ER",
4104     "ti_ER"
4105   }, {
4106     "und_ES",
4107     "es_Latn_ES",
4108     "es"
4109   }, {
4110     "und_ET",
4111     "am_Ethi_ET",
4112     "am"
4113   }, {
4114     "und_Ethi",
4115     "am_Ethi_ET",
4116     "am"
4117   }, {
4118     "und_Ethi_ER",
4119     "am_Ethi_ER",
4120     "am_ER"
4121   }, {
4122     "und_FI",
4123     "fi_Latn_FI",
4124     "fi"
4125   }, {
4126     "und_FM",
4127     "en_Latn_FM",
4128     "en_FM"
4129   }, {
4130     "und_FO",
4131     "fo_Latn_FO",
4132     "fo"
4133   }, {
4134     "und_FR",
4135     "fr_Latn_FR",
4136     "fr"
4137   }, {
4138     "und_GA",
4139     "fr_Latn_GA",
4140     "fr_GA"
4141   }, {
4142     "und_GE",
4143     "ka_Geor_GE",
4144     "ka"
4145   }, {
4146     "und_GF",
4147     "fr_Latn_GF",
4148     "fr_GF"
4149   }, {
4150     "und_GL",
4151     "kl_Latn_GL",
4152     "kl"
4153   }, {
4154     "und_GN",
4155     "fr_Latn_GN",
4156     "fr_GN"
4157   }, {
4158     "und_GP",
4159     "fr_Latn_GP",
4160     "fr_GP"
4161   }, {
4162     "und_GQ",
4163     "es_Latn_GQ",
4164     "es_GQ"
4165   }, {
4166     "und_GR",
4167     "el_Grek_GR",
4168     "el"
4169   }, {
4170     "und_GT",
4171     "es_Latn_GT",
4172     "es_GT"
4173   }, {
4174     "und_GU",
4175     "en_Latn_GU",
4176     "en_GU"
4177   }, {
4178     "und_GW",
4179     "pt_Latn_GW",
4180     "pt_GW"
4181   }, {
4182     "und_Geor",
4183     "ka_Geor_GE",
4184     "ka"
4185   }, {
4186     "und_Grek",
4187     "el_Grek_GR",
4188     "el"
4189   }, {
4190     "und_Gujr",
4191     "gu_Gujr_IN",
4192     "gu"
4193   }, {
4194     "und_Guru",
4195     "pa_Guru_IN",
4196     "pa"
4197   }, {
4198     "und_HK",
4199     "zh_Hant_HK",
4200     "zh_HK"
4201   }, {
4202     "und_HN",
4203     "es_Latn_HN",
4204     "es_HN"
4205   }, {
4206     "und_HR",
4207     "hr_Latn_HR",
4208     "hr"
4209   }, {
4210     "und_HT",
4211     "ht_Latn_HT",
4212     "ht"
4213   }, {
4214     "und_HU",
4215     "hu_Latn_HU",
4216     "hu"
4217   }, {
4218     "und_Hani",
4219     "zh_Hani_CN",
4220     "zh_Hani"
4221   }, {
4222     "und_Hans",
4223     "zh_Hans_CN",
4224     "zh"
4225   }, {
4226     "und_Hant",
4227     "zh_Hant_TW",
4228     "zh_TW"
4229   }, {
4230     "und_Hebr",
4231     "he_Hebr_IL",
4232     "he"
4233   }, {
4234     "und_IL",
4235     "he_Hebr_IL",
4236     "he"
4237   }, {
4238     "und_IN",
4239     "hi_Deva_IN",
4240     "hi"
4241   }, {
4242     "und_IQ",
4243     "ar_Arab_IQ",
4244     "ar_IQ"
4245   }, {
4246     "und_IR",
4247     "fa_Arab_IR",
4248     "fa"
4249   }, {
4250     "und_IS",
4251     "is_Latn_IS",
4252     "is"
4253   }, {
4254     "und_IT",
4255     "it_Latn_IT",
4256     "it"
4257   }, {
4258     "und_JO",
4259     "ar_Arab_JO",
4260     "ar_JO"
4261   }, {
4262     "und_JP",
4263     "ja_Jpan_JP",
4264     "ja"
4265   }, {
4266     "und_Jpan",
4267     "ja_Jpan_JP",
4268     "ja"
4269   }, {
4270     "und_KG",
4271     "ky_Cyrl_KG",
4272     "ky"
4273   }, {
4274     "und_KH",
4275     "km_Khmr_KH",
4276     "km"
4277   }, {
4278     "und_KM",
4279     "ar_Arab_KM",
4280     "ar_KM"
4281   }, {
4282     "und_KP",
4283     "ko_Kore_KP",
4284     "ko_KP"
4285   }, {
4286     "und_KR",
4287     "ko_Kore_KR",
4288     "ko"
4289   }, {
4290     "und_KW",
4291     "ar_Arab_KW",
4292     "ar_KW"
4293   }, {
4294     "und_KZ",
4295     "ru_Cyrl_KZ",
4296     "ru_KZ"
4297   }, {
4298     "und_Khmr",
4299     "km_Khmr_KH",
4300     "km"
4301   }, {
4302     "und_Knda",
4303     "kn_Knda_IN",
4304     "kn"
4305   }, {
4306     "und_Kore",
4307     "ko_Kore_KR",
4308     "ko"
4309   }, {
4310     "und_LA",
4311     "lo_Laoo_LA",
4312     "lo"
4313   }, {
4314     "und_LB",
4315     "ar_Arab_LB",
4316     "ar_LB"
4317   }, {
4318     "und_LI",
4319     "de_Latn_LI",
4320     "de_LI"
4321   }, {
4322     "und_LK",
4323     "si_Sinh_LK",
4324     "si"
4325   }, {
4326     "und_LS",
4327     "st_Latn_LS",
4328     "st_LS"
4329   }, {
4330     "und_LT",
4331     "lt_Latn_LT",
4332     "lt"
4333   }, {
4334     "und_LU",
4335     "fr_Latn_LU",
4336     "fr_LU"
4337   }, {
4338     "und_LV",
4339     "lv_Latn_LV",
4340     "lv"
4341   }, {
4342     "und_LY",
4343     "ar_Arab_LY",
4344     "ar_LY"
4345   }, {
4346     "und_Laoo",
4347     "lo_Laoo_LA",
4348     "lo"
4349   }, {
4350     "und_Latn_ES",
4351     "es_Latn_ES",
4352     "es"
4353   }, {
4354     "und_Latn_ET",
4355     "en_Latn_ET",
4356     "en_ET"
4357   }, {
4358     "und_Latn_GB",
4359     "en_Latn_GB",
4360     "en_GB"
4361   }, {
4362     "und_Latn_GH",
4363     "ak_Latn_GH",
4364     "ak"
4365   }, {
4366     "und_Latn_ID",
4367     "id_Latn_ID",
4368     "id"
4369   }, {
4370     "und_Latn_IT",
4371     "it_Latn_IT",
4372     "it"
4373   }, {
4374     "und_Latn_NG",
4375     "en_Latn_NG",
4376     "en_NG"
4377   }, {
4378     "und_Latn_TR",
4379     "tr_Latn_TR",
4380     "tr"
4381   }, {
4382     "und_Latn_ZA",
4383     "en_Latn_ZA",
4384     "en_ZA"
4385   }, {
4386     "und_MA",
4387     "ar_Arab_MA",
4388     "ar_MA"
4389   }, {
4390     "und_MC",
4391     "fr_Latn_MC",
4392     "fr_MC"
4393   }, {
4394     "und_MD",
4395     "ro_Latn_MD",
4396     "ro_MD"
4397   }, {
4398     "und_ME",
4399     "sr_Latn_ME",
4400     "sr_ME"
4401   }, {
4402     "und_MG",
4403     "mg_Latn_MG",
4404     "mg"
4405   }, {
4406     "und_MH",
4407     "en_Latn_MH",
4408     "en_MH"
4409   }, {
4410     "und_MK",
4411     "mk_Cyrl_MK",
4412     "mk"
4413   }, {
4414     "und_ML",
4415     "bm_Latn_ML",
4416     "bm"
4417   }, {
4418     "und_MM",
4419     "my_Mymr_MM",
4420     "my"
4421   }, {
4422     "und_MN",
4423     "mn_Cyrl_MN",
4424     "mn"
4425   }, {
4426     "und_MO",
4427     "zh_Hant_MO",
4428     "zh_MO"
4429   }, {
4430     "und_MQ",
4431     "fr_Latn_MQ",
4432     "fr_MQ"
4433   }, {
4434     "und_MR",
4435     "ar_Arab_MR",
4436     "ar_MR"
4437   }, {
4438     "und_MT",
4439     "mt_Latn_MT",
4440     "mt"
4441   }, {
4442     "und_MV",
4443     "dv_Thaa_MV",
4444     "dv"
4445   }, {
4446     "und_MW",
4447     "en_Latn_MW",
4448     "en_MW"
4449   }, {
4450     "und_MX",
4451     "es_Latn_MX",
4452     "es_MX"
4453   }, {
4454     "und_MY",
4455     "ms_Latn_MY",
4456     "ms"
4457   }, {
4458     "und_MZ",
4459     "pt_Latn_MZ",
4460     "pt_MZ"
4461   }, {
4462     "und_Mlym",
4463     "ml_Mlym_IN",
4464     "ml"
4465   }, {
4466     "und_Mymr",
4467     "my_Mymr_MM",
4468     "my"
4469   }, {
4470     "und_NC",
4471     "fr_Latn_NC",
4472     "fr_NC"
4473   }, {
4474     "und_NE",
4475     "ha_Latn_NE",
4476     "ha_NE"
4477   }, {
4478     "und_NG",
4479     "en_Latn_NG",
4480     "en_NG"
4481   }, {
4482     "und_NI",
4483     "es_Latn_NI",
4484     "es_NI"
4485   }, {
4486     "und_NL",
4487     "nl_Latn_NL",
4488     "nl"
4489   }, {
4490     "und_NO",
4491     "no_Latn_NO",  /* Google patch */
4492     "no"  /* Google patch */
4493   }, {
4494     "und_NP",
4495     "ne_Deva_NP",
4496     "ne"
4497   }, {
4498     "und_NR",
4499     "en_Latn_NR",
4500     "en_NR"
4501   }, {
4502     "und_NU",
4503     "en_Latn_NU",
4504     "en_NU"
4505   }, {
4506     "und_OM",
4507     "ar_Arab_OM",
4508     "ar_OM"
4509   }, {
4510     "und_Orya",
4511     "or_Orya_IN",
4512     "or"
4513   }, {
4514     "und_PA",
4515     "es_Latn_PA",
4516     "es_PA"
4517   }, {
4518     "und_PE",
4519     "es_Latn_PE",
4520     "es_PE"
4521   }, {
4522     "und_PF",
4523     "fr_Latn_PF",
4524     "fr_PF"
4525   }, {
4526     "und_PG",
4527     "tpi_Latn_PG",
4528     "tpi"
4529   }, {
4530     "und_PH",
4531     "fil_Latn_PH",
4532     "fil"
4533   }, {
4534     "und_PL",
4535     "pl_Latn_PL",
4536     "pl"
4537   }, {
4538     "und_PM",
4539     "fr_Latn_PM",
4540     "fr_PM"
4541   }, {
4542     "und_PR",
4543     "es_Latn_PR",
4544     "es_PR"
4545   }, {
4546     "und_PS",
4547     "ar_Arab_PS",
4548     "ar_PS"
4549   }, {
4550     "und_PT",
4551     "pt_Latn_PT",
4552     "pt_PT"
4553   }, {
4554     "und_PW",
4555     "pau_Latn_PW",
4556     "pau"
4557   }, {
4558     "und_PY",
4559     "gn_Latn_PY",
4560     "gn"
4561   }, {
4562     "und_QA",
4563     "ar_Arab_QA",
4564     "ar_QA"
4565   }, {
4566     "und_RE",
4567     "fr_Latn_RE",
4568     "fr_RE"
4569   }, {
4570     "und_RO",
4571     "ro_Latn_RO",
4572     "ro"
4573   }, {
4574     "und_RS",
4575     "sr_Cyrl_RS",
4576     "sr"
4577   }, {
4578     "und_RU",
4579     "ru_Cyrl_RU",
4580     "ru"
4581   }, {
4582     "und_RW",
4583     "rw_Latn_RW",
4584     "rw"
4585   }, {
4586     "und_SA",
4587     "ar_Arab_SA",
4588     "ar_SA"
4589   }, {
4590     "und_SD",
4591     "ar_Arab_SD",
4592     "ar_SD"
4593   }, {
4594     "und_SE",
4595     "sv_Latn_SE",
4596     "sv"
4597   }, {
4598     "und_SG",
4599     "en_Latn_SG",
4600     "en_SG"
4601   }, {
4602     "und_SI",
4603     "sl_Latn_SI",
4604     "sl"
4605   }, {
4606     "und_SJ",
4607     "no_Latn_SJ",  /* Google patch */
4608     "no_SJ"  /* Google patch */
4609   }, {
4610     "und_SK",
4611     "sk_Latn_SK",
4612     "sk"
4613   }, {
4614     "und_SM",
4615     "it_Latn_SM",
4616     "it_SM"
4617   }, {
4618     "und_SN",
4619     "fr_Latn_SN",
4620     "fr_SN"
4621   }, {
4622     "und_SO",
4623     "so_Latn_SO",
4624     "so"
4625   }, {
4626     "und_SR",
4627     "nl_Latn_SR",
4628     "nl_SR"
4629   }, {
4630     "und_ST",
4631     "pt_Latn_ST",
4632     "pt_ST"
4633   }, {
4634     "und_SV",
4635     "es_Latn_SV",
4636     "es_SV"
4637   }, {
4638     "und_SY",
4639     "ar_Arab_SY",
4640     "ar_SY"
4641   }, {
4642     "und_Sinh",
4643     "si_Sinh_LK",
4644     "si"
4645   }, {
4646     "und_TD",
4647     "fr_Latn_TD",
4648     "fr_TD"
4649   }, {
4650     "und_TG",
4651     "fr_Latn_TG",
4652     "fr_TG"
4653   }, {
4654     "und_TH",
4655     "th_Thai_TH",
4656     "th"
4657   }, {
4658     "und_TJ",
4659     "tg_Cyrl_TJ",
4660     "tg"
4661   }, {
4662     "und_TK",
4663     "tkl_Latn_TK",
4664     "tkl"
4665   }, {
4666     "und_TL",
4667     "pt_Latn_TL",
4668     "pt_TL"
4669   }, {
4670     "und_TM",
4671     "tk_Latn_TM",
4672     "tk"
4673   }, {
4674     "und_TN",
4675     "ar_Arab_TN",
4676     "ar_TN"
4677   }, {
4678     "und_TO",
4679     "to_Latn_TO",
4680     "to"
4681   }, {
4682     "und_TR",
4683     "tr_Latn_TR",
4684     "tr"
4685   }, {
4686     "und_TV",
4687     "tvl_Latn_TV",
4688     "tvl"
4689   }, {
4690     "und_TW",
4691     "zh_Hant_TW",
4692     "zh_TW"
4693   }, {
4694     "und_Taml",
4695     "ta_Taml_IN",
4696     "ta"
4697   }, {
4698     "und_Telu",
4699     "te_Telu_IN",
4700     "te"
4701   }, {
4702     "und_Thaa",
4703     "dv_Thaa_MV",
4704     "dv"
4705   }, {
4706     "und_Thai",
4707     "th_Thai_TH",
4708     "th"
4709   }, {
4710     "und_Tibt",
4711     "bo_Tibt_CN",
4712     "bo"
4713   }, {
4714     "und_UA",
4715     "uk_Cyrl_UA",
4716     "uk"
4717   }, {
4718     "und_UY",
4719     "es_Latn_UY",
4720     "es_UY"
4721   }, {
4722     "und_UZ",
4723     "uz_Latn_UZ",
4724     "uz"
4725   }, {
4726     "und_VA",
4727     "it_Latn_VA",
4728     "it_VA"
4729   }, {
4730     "und_VE",
4731     "es_Latn_VE",
4732     "es_VE"
4733   }, {
4734     "und_VN",
4735     "vi_Latn_VN",
4736     "vi"
4737   }, {
4738     "und_VU",
4739     "bi_Latn_VU",
4740     "bi"
4741   }, {
4742     "und_WF",
4743     "fr_Latn_WF",
4744     "fr_WF"
4745   }, {
4746     "und_WS",
4747     "sm_Latn_WS",
4748     "sm"
4749   }, {
4750     "und_YE",
4751     "ar_Arab_YE",
4752     "ar_YE"
4753   }, {
4754     "und_YT",
4755     "fr_Latn_YT",
4756     "fr_YT"
4757   }, {
4758     "und_Yiii",
4759     "ii_Yiii_CN",
4760     "ii"
4761   }, {
4762     "ur",
4763     "ur_Arab_PK",
4764     "ur"
4765   }, {
4766     "uz",
4767     "uz_Latn_UZ",
4768     "uz"
4769   }, {
4770     "uz_AF",
4771     "uz_Arab_AF",
4772     "uz_AF"
4773   }, {
4774     "uz_Arab",
4775     "uz_Arab_AF",
4776     "uz_AF"
4777   }, {
4778     "ve",
4779     "ve_Latn_ZA",
4780     "ve"
4781   }, {
4782     "vi",
4783     "vi_Latn_VN",
4784     "vi"
4785   }, {
4786     "wal",
4787     "wal_Ethi_ET",
4788     "wal"
4789   }, {
4790     "wo",
4791     "wo_Latn_SN",
4792     "wo"
4793   }, {
4794     "xh",
4795     "xh_Latn_ZA",
4796     "xh"
4797   }, {
4798     "yo",
4799     "yo_Latn_NG",
4800     "yo"
4801   }, {
4802     "zh",
4803     "zh_Hans_CN",
4804     "zh"
4805   }, {
4806     "zh_HK",
4807     "zh_Hant_HK",
4808     "zh_HK"
4809   }, {
4810     "zh_Hani",
4811     "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
4812     "zh_Hani", /* changed due to cldrbug 6204, may be an error */
4813   }, {
4814     "zh_Hant",
4815     "zh_Hant_TW",
4816     "zh_TW"
4817   }, {
4818     "zh_MO",
4819     "zh_Hant_MO",
4820     "zh_MO"
4821   }, {
4822     "zh_TW",
4823     "zh_Hant_TW",
4824     "zh_TW"
4825   }, {
4826     "zu",
4827     "zu_Latn_ZA",
4828     "zu"
4829   }, {
4830     "und",
4831     "en_Latn_US",
4832     "en"
4833   }, {
4834     "und_ZZ",
4835     "en_Latn_US",
4836     "en"
4837   }, {
4838     "und_CN",
4839     "zh_Hans_CN",
4840     "zh"
4841   }, {
4842     "und_TW",
4843     "zh_Hant_TW",
4844     "zh_TW"
4845   }, {
4846     "und_HK",
4847     "zh_Hant_HK",
4848     "zh_HK"
4849   }, {
4850     "und_AQ",
4851     "und_Latn_AQ",
4852     "und_AQ"
4853   }, {
4854     "und_Zzzz",
4855     "en_Latn_US",
4856     "en"
4857   }, {
4858     "und_Zzzz_ZZ",
4859     "en_Latn_US",
4860     "en"
4861   }, {
4862     "und_Zzzz_CN",
4863     "zh_Hans_CN",
4864     "zh"
4865   }, {
4866     "und_Zzzz_TW",
4867     "zh_Hant_TW",
4868     "zh_TW"
4869   }, {
4870     "und_Zzzz_HK",
4871     "zh_Hant_HK",
4872     "zh_HK"
4873   }, {
4874     "und_Zzzz_AQ",
4875     "und_Latn_AQ",
4876     "und_AQ"
4877   }, {
4878     "und_Latn",
4879     "en_Latn_US",
4880     "en"
4881   }, {
4882     "und_Latn_ZZ",
4883     "en_Latn_US",
4884     "en"
4885   }, {
4886     "und_Latn_CN",
4887     "za_Latn_CN",
4888     "za"
4889   }, {
4890     "und_Latn_TW",
4891     "trv_Latn_TW",
4892     "trv"
4893   }, {
4894     "und_Latn_HK",
4895     "zh_Latn_HK",
4896     "zh_Latn_HK"
4897   }, {
4898     "und_Latn_AQ",
4899     "und_Latn_AQ",
4900     "und_AQ"
4901   }, {
4902     "und_Hans",
4903     "zh_Hans_CN",
4904     "zh"
4905   }, {
4906     "und_Hans_ZZ",
4907     "zh_Hans_CN",
4908     "zh"
4909   }, {
4910     "und_Hans_CN",
4911     "zh_Hans_CN",
4912     "zh"
4913   }, {
4914     "und_Hans_TW",
4915     "zh_Hans_TW",
4916     "zh_Hans_TW"
4917   }, {
4918     "und_Hans_HK",
4919     "zh_Hans_HK",
4920     "zh_Hans_HK"
4921   }, {
4922     "und_Hans_AQ",
4923     "zh_Hans_AQ",
4924     "zh_AQ"
4925   }, {
4926     "und_Hant",
4927     "zh_Hant_TW",
4928     "zh_TW"
4929   }, {
4930     "und_Hant_ZZ",
4931     "zh_Hant_TW",
4932     "zh_TW"
4933   }, {
4934     "und_Hant_CN",
4935     "zh_Hant_CN",
4936     "zh_Hant_CN"
4937   }, {
4938     "und_Hant_TW",
4939     "zh_Hant_TW",
4940     "zh_TW"
4941   }, {
4942     "und_Hant_HK",
4943     "zh_Hant_HK",
4944     "zh_HK"
4945   }, {
4946     "und_Hant_AQ",
4947     "zh_Hant_AQ",
4948     "zh_Hant_AQ"
4949   }, {
4950     "und_Moon",
4951     "en_Moon_US",
4952     "en_Moon"
4953   }, {
4954     "und_Moon_ZZ",
4955     "en_Moon_US",
4956     "en_Moon"
4957   }, {
4958     "und_Moon_CN",
4959     "zh_Moon_CN",
4960     "zh_Moon"
4961   }, {
4962     "und_Moon_TW",
4963     "zh_Moon_TW",
4964     "zh_Moon_TW"
4965   }, {
4966     "und_Moon_HK",
4967     "zh_Moon_HK",
4968     "zh_Moon_HK"
4969   }, {
4970     "und_Moon_AQ",
4971     "und_Moon_AQ",
4972     "und_Moon_AQ"
4973   }, {
4974     "es",
4975     "es_Latn_ES",
4976     "es"
4977   }, {
4978     "es_ZZ",
4979     "es_Latn_ES",
4980     "es"
4981   }, {
4982     "es_CN",
4983     "es_Latn_CN",
4984     "es_CN"
4985   }, {
4986     "es_TW",
4987     "es_Latn_TW",
4988     "es_TW"
4989   }, {
4990     "es_HK",
4991     "es_Latn_HK",
4992     "es_HK"
4993   }, {
4994     "es_AQ",
4995     "es_Latn_AQ",
4996     "es_AQ"
4997   }, {
4998     "es_Zzzz",
4999     "es_Latn_ES",
5000     "es"
5001   }, {
5002     "es_Zzzz_ZZ",
5003     "es_Latn_ES",
5004     "es"
5005   }, {
5006     "es_Zzzz_CN",
5007     "es_Latn_CN",
5008     "es_CN"
5009   }, {
5010     "es_Zzzz_TW",
5011     "es_Latn_TW",
5012     "es_TW"
5013   }, {
5014     "es_Zzzz_HK",
5015     "es_Latn_HK",
5016     "es_HK"
5017   }, {
5018     "es_Zzzz_AQ",
5019     "es_Latn_AQ",
5020     "es_AQ"
5021   }, {
5022     "es_Latn",
5023     "es_Latn_ES",
5024     "es"
5025   }, {
5026     "es_Latn_ZZ",
5027     "es_Latn_ES",
5028     "es"
5029   }, {
5030     "es_Latn_CN",
5031     "es_Latn_CN",
5032     "es_CN"
5033   }, {
5034     "es_Latn_TW",
5035     "es_Latn_TW",
5036     "es_TW"
5037   }, {
5038     "es_Latn_HK",
5039     "es_Latn_HK",
5040     "es_HK"
5041   }, {
5042     "es_Latn_AQ",
5043     "es_Latn_AQ",
5044     "es_AQ"
5045   }, {
5046     "es_Hans",
5047     "es_Hans_ES",
5048     "es_Hans"
5049   }, {
5050     "es_Hans_ZZ",
5051     "es_Hans_ES",
5052     "es_Hans"
5053   }, {
5054     "es_Hans_CN",
5055     "es_Hans_CN",
5056     "es_Hans_CN"
5057   }, {
5058     "es_Hans_TW",
5059     "es_Hans_TW",
5060     "es_Hans_TW"
5061   }, {
5062     "es_Hans_HK",
5063     "es_Hans_HK",
5064     "es_Hans_HK"
5065   }, {
5066     "es_Hans_AQ",
5067     "es_Hans_AQ",
5068     "es_Hans_AQ"
5069   }, {
5070     "es_Hant",
5071     "es_Hant_ES",
5072     "es_Hant"
5073   }, {
5074     "es_Hant_ZZ",
5075     "es_Hant_ES",
5076     "es_Hant"
5077   }, {
5078     "es_Hant_CN",
5079     "es_Hant_CN",
5080     "es_Hant_CN"
5081   }, {
5082     "es_Hant_TW",
5083     "es_Hant_TW",
5084     "es_Hant_TW"
5085   }, {
5086     "es_Hant_HK",
5087     "es_Hant_HK",
5088     "es_Hant_HK"
5089   }, {
5090     "es_Hant_AQ",
5091     "es_Hant_AQ",
5092     "es_Hant_AQ"
5093   }, {
5094     "es_Moon",
5095     "es_Moon_ES",
5096     "es_Moon"
5097   }, {
5098     "es_Moon_ZZ",
5099     "es_Moon_ES",
5100     "es_Moon"
5101   }, {
5102     "es_Moon_CN",
5103     "es_Moon_CN",
5104     "es_Moon_CN"
5105   }, {
5106     "es_Moon_TW",
5107     "es_Moon_TW",
5108     "es_Moon_TW"
5109   }, {
5110     "es_Moon_HK",
5111     "es_Moon_HK",
5112     "es_Moon_HK"
5113   }, {
5114     "es_Moon_AQ",
5115     "es_Moon_AQ",
5116     "es_Moon_AQ"
5117   }, {
5118     "zh",
5119     "zh_Hans_CN",
5120     "zh"
5121   }, {
5122     "zh_ZZ",
5123     "zh_Hans_CN",
5124     "zh"
5125   }, {
5126     "zh_CN",
5127     "zh_Hans_CN",
5128     "zh"
5129   }, {
5130     "zh_TW",
5131     "zh_Hant_TW",
5132     "zh_TW"
5133   }, {
5134     "zh_HK",
5135     "zh_Hant_HK",
5136     "zh_HK"
5137   }, {
5138     "zh_AQ",
5139     "zh_Hans_AQ",
5140     "zh_AQ"
5141   }, {
5142     "zh_Zzzz",
5143     "zh_Hans_CN",
5144     "zh"
5145   }, {
5146     "zh_Zzzz_ZZ",
5147     "zh_Hans_CN",
5148     "zh"
5149   }, {
5150     "zh_Zzzz_CN",
5151     "zh_Hans_CN",
5152     "zh"
5153   }, {
5154     "zh_Zzzz_TW",
5155     "zh_Hant_TW",
5156     "zh_TW"
5157   }, {
5158     "zh_Zzzz_HK",
5159     "zh_Hant_HK",
5160     "zh_HK"
5161   }, {
5162     "zh_Zzzz_AQ",
5163     "zh_Hans_AQ",
5164     "zh_AQ"
5165   }, {
5166     "zh_Latn",
5167     "zh_Latn_CN",
5168     "zh_Latn"
5169   }, {
5170     "zh_Latn_ZZ",
5171     "zh_Latn_CN",
5172     "zh_Latn"
5173   }, {
5174     "zh_Latn_CN",
5175     "zh_Latn_CN",
5176     "zh_Latn"
5177   }, {
5178     "zh_Latn_TW",
5179     "zh_Latn_TW",
5180     "zh_Latn_TW"
5181   }, {
5182     "zh_Latn_HK",
5183     "zh_Latn_HK",
5184     "zh_Latn_HK"
5185   }, {
5186     "zh_Latn_AQ",
5187     "zh_Latn_AQ",
5188     "zh_Latn_AQ"
5189   }, {
5190     "zh_Hans",
5191     "zh_Hans_CN",
5192     "zh"
5193   }, {
5194     "zh_Hans_ZZ",
5195     "zh_Hans_CN",
5196     "zh"
5197   }, {
5198     "zh_Hans_TW",
5199     "zh_Hans_TW",
5200     "zh_Hans_TW"
5201   }, {
5202     "zh_Hans_HK",
5203     "zh_Hans_HK",
5204     "zh_Hans_HK"
5205   }, {
5206     "zh_Hans_AQ",
5207     "zh_Hans_AQ",
5208     "zh_AQ"
5209   }, {
5210     "zh_Hant",
5211     "zh_Hant_TW",
5212     "zh_TW"
5213   }, {
5214     "zh_Hant_ZZ",
5215     "zh_Hant_TW",
5216     "zh_TW"
5217   }, {
5218     "zh_Hant_CN",
5219     "zh_Hant_CN",
5220     "zh_Hant_CN"
5221   }, {
5222     "zh_Hant_AQ",
5223     "zh_Hant_AQ",
5224     "zh_Hant_AQ"
5225   }, {
5226     "zh_Moon",
5227     "zh_Moon_CN",
5228     "zh_Moon"
5229   }, {
5230     "zh_Moon_ZZ",
5231     "zh_Moon_CN",
5232     "zh_Moon"
5233   }, {
5234     "zh_Moon_CN",
5235     "zh_Moon_CN",
5236     "zh_Moon"
5237   }, {
5238     "zh_Moon_TW",
5239     "zh_Moon_TW",
5240     "zh_Moon_TW"
5241   }, {
5242     "zh_Moon_HK",
5243     "zh_Moon_HK",
5244     "zh_Moon_HK"
5245   }, {
5246     "zh_Moon_AQ",
5247     "zh_Moon_AQ",
5248     "zh_Moon_AQ"
5249   }, {
5250     "art",
5251     "",
5252     ""
5253   }, {
5254     "art_ZZ",
5255     "",
5256     ""
5257   }, {
5258     "art_CN",
5259     "",
5260     ""
5261   }, {
5262     "art_TW",
5263     "",
5264     ""
5265   }, {
5266     "art_HK",
5267     "",
5268     ""
5269   }, {
5270     "art_AQ",
5271     "",
5272     ""
5273   }, {
5274     "art_Zzzz",
5275     "",
5276     ""
5277   }, {
5278     "art_Zzzz_ZZ",
5279     "",
5280     ""
5281   }, {
5282     "art_Zzzz_CN",
5283     "",
5284     ""
5285   }, {
5286     "art_Zzzz_TW",
5287     "",
5288     ""
5289   }, {
5290     "art_Zzzz_HK",
5291     "",
5292     ""
5293   }, {
5294     "art_Zzzz_AQ",
5295     "",
5296     ""
5297   }, {
5298     "art_Latn",
5299     "",
5300     ""
5301   }, {
5302     "art_Latn_ZZ",
5303     "",
5304     ""
5305   }, {
5306     "art_Latn_CN",
5307     "",
5308     ""
5309   }, {
5310     "art_Latn_TW",
5311     "",
5312     ""
5313   }, {
5314     "art_Latn_HK",
5315     "",
5316     ""
5317   }, {
5318     "art_Latn_AQ",
5319     "",
5320     ""
5321   }, {
5322     "art_Hans",
5323     "",
5324     ""
5325   }, {
5326     "art_Hans_ZZ",
5327     "",
5328     ""
5329   }, {
5330     "art_Hans_CN",
5331     "",
5332     ""
5333   }, {
5334     "art_Hans_TW",
5335     "",
5336     ""
5337   }, {
5338     "art_Hans_HK",
5339     "",
5340     ""
5341   }, {
5342     "art_Hans_AQ",
5343     "",
5344     ""
5345   }, {
5346     "art_Hant",
5347     "",
5348     ""
5349   }, {
5350     "art_Hant_ZZ",
5351     "",
5352     ""
5353   }, {
5354     "art_Hant_CN",
5355     "",
5356     ""
5357   }, {
5358     "art_Hant_TW",
5359     "",
5360     ""
5361   }, {
5362     "art_Hant_HK",
5363     "",
5364     ""
5365   }, {
5366     "art_Hant_AQ",
5367     "",
5368     ""
5369   }, {
5370     "art_Moon",
5371     "",
5372     ""
5373   }, {
5374     "art_Moon_ZZ",
5375     "",
5376     ""
5377   }, {
5378     "art_Moon_CN",
5379     "",
5380     ""
5381   }, {
5382     "art_Moon_TW",
5383     "",
5384     ""
5385   }, {
5386     "art_Moon_HK",
5387     "",
5388     ""
5389   }, {
5390     "art_Moon_AQ",
5391     "",
5392     ""
5393   }, {
5394     "de@collation=phonebook",
5395     "de_Latn_DE@collation=phonebook",
5396     "de@collation=phonebook"
5397   }
5398 };
5399 
5400 typedef struct errorDataTag {
5401     const char* tag;
5402     const char* expected;
5403     UErrorCode uerror;
5404     int32_t  bufferSize;
5405 } errorData;
5406 
5407 const errorData maximizeErrors[] = {
5408     {
5409         "enfueiujhytdf",
5410         NULL,
5411         U_ILLEGAL_ARGUMENT_ERROR,
5412         -1
5413     },
5414     {
5415         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5416         NULL,
5417         U_ILLEGAL_ARGUMENT_ERROR,
5418         -1
5419     },
5420     {
5421         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5422         NULL,
5423         U_ILLEGAL_ARGUMENT_ERROR,
5424         -1
5425     },
5426     {
5427         "en_Latn_US_POSIX@currency=EURO",
5428         "en_Latn_US_POSIX@currency=EURO",
5429         U_BUFFER_OVERFLOW_ERROR,
5430         29
5431     },
5432     {
5433         "en_Latn_US_POSIX@currency=EURO",
5434         "en_Latn_US_POSIX@currency=EURO",
5435         U_STRING_NOT_TERMINATED_WARNING,
5436         30
5437     }
5438 };
5439 
5440 const errorData minimizeErrors[] = {
5441     {
5442         "enfueiujhytdf",
5443         NULL,
5444         U_ILLEGAL_ARGUMENT_ERROR,
5445         -1
5446     },
5447     {
5448         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5449         NULL,
5450         U_ILLEGAL_ARGUMENT_ERROR,
5451         -1
5452     },
5453     {
5454         "en_Latn_US_POSIX@currency=EURO",
5455         "en__POSIX@currency=EURO",
5456         U_BUFFER_OVERFLOW_ERROR,
5457         22
5458     },
5459     {
5460         "en_Latn_US_POSIX@currency=EURO",
5461         "en__POSIX@currency=EURO",
5462         U_STRING_NOT_TERMINATED_WARNING,
5463         23
5464     }
5465 };
5466 
getExpectedReturnValue(const errorData * data)5467 static int32_t getExpectedReturnValue(const errorData* data)
5468 {
5469     if (data->uerror == U_BUFFER_OVERFLOW_ERROR ||
5470         data->uerror == U_STRING_NOT_TERMINATED_WARNING)
5471     {
5472         return strlen(data->expected);
5473     }
5474     else
5475     {
5476         return -1;
5477     }
5478 }
5479 
getBufferSize(const errorData * data,int32_t actualSize)5480 static int32_t getBufferSize(const errorData* data, int32_t actualSize)
5481 {
5482     if (data->expected == NULL)
5483     {
5484         return actualSize;
5485     }
5486     else if (data->bufferSize < 0)
5487     {
5488         return strlen(data->expected) + 1;
5489     }
5490     else
5491     {
5492         return data->bufferSize;
5493     }
5494 }
5495 
TestLikelySubtags()5496 static void TestLikelySubtags()
5497 {
5498     char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1];
5499     int32_t i = 0;
5500 
5501     for (; i < sizeof(basic_maximize_data) / sizeof(basic_maximize_data[0]); ++i)
5502     {
5503         UErrorCode status = U_ZERO_ERROR;
5504         const char* const minimal = basic_maximize_data[i][0];
5505         const char* const maximal = basic_maximize_data[i][1];
5506 
5507         /* const int32_t length = */
5508             uloc_addLikelySubtags(
5509                 minimal,
5510                 buffer,
5511                 sizeof(buffer),
5512                 &status);
5513         if (U_FAILURE(status)) {
5514             log_err_status(status, "  unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status));
5515             status = U_ZERO_ERROR;
5516         }
5517         else if (uprv_strlen(maximal) == 0) {
5518             if (uprv_stricmp(minimal, buffer) != 0) {
5519                 log_err("  unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5520             }
5521         }
5522         else if (uprv_stricmp(maximal, buffer) != 0) {
5523             log_err("  maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer);
5524         }
5525     }
5526 
5527     for (i = 0; i < sizeof(basic_minimize_data) / sizeof(basic_minimize_data[0]); ++i) {
5528 
5529         UErrorCode status = U_ZERO_ERROR;
5530         const char* const maximal = basic_minimize_data[i][0];
5531         const char* const minimal = basic_minimize_data[i][1];
5532 
5533         /* const int32_t length = */
5534             uloc_minimizeSubtags(
5535                 maximal,
5536                 buffer,
5537                 sizeof(buffer),
5538                 &status);
5539 
5540         if (U_FAILURE(status)) {
5541             log_err_status(status, "  unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5542             status = U_ZERO_ERROR;
5543         }
5544         else if (uprv_strlen(minimal) == 0) {
5545             if (uprv_stricmp(maximal, buffer) != 0) {
5546                 log_err("  unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5547             }
5548         }
5549         else if (uprv_stricmp(minimal, buffer) != 0) {
5550             log_err("  minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5551         }
5552     }
5553 
5554     for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) {
5555 
5556         UErrorCode status = U_ZERO_ERROR;
5557         const char* const minimal = full_data[i][0];
5558         const char* const maximal = full_data[i][1];
5559 
5560         /* const int32_t length = */
5561             uloc_addLikelySubtags(
5562                 minimal,
5563                 buffer,
5564                 sizeof(buffer),
5565                 &status);
5566         if (U_FAILURE(status)) {
5567             log_err_status(status, "  unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status));
5568             status = U_ZERO_ERROR;
5569         }
5570         else if (uprv_strlen(maximal) == 0) {
5571             if (uprv_stricmp(minimal, buffer) != 0) {
5572                 log_err("  unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5573             }
5574         }
5575         else if (uprv_stricmp(maximal, buffer) != 0) {
5576             log_err("  maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5577         }
5578     }
5579 
5580     for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) {
5581 
5582         UErrorCode status = U_ZERO_ERROR;
5583         const char* const maximal = full_data[i][1];
5584         const char* const minimal = full_data[i][2];
5585 
5586         if (strlen(maximal) > 0) {
5587 
5588             /* const int32_t length = */
5589                 uloc_minimizeSubtags(
5590                     maximal,
5591                     buffer,
5592                     sizeof(buffer),
5593                     &status);
5594 
5595             if (U_FAILURE(status)) {
5596                 log_err_status(status, "  unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5597                 status = U_ZERO_ERROR;
5598             }
5599             else if (uprv_strlen(minimal) == 0) {
5600                 if (uprv_stricmp(maximal, buffer) != 0) {
5601                     log_err("  unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5602                 }
5603             }
5604             else if (uprv_stricmp(minimal, buffer) != 0) {
5605                 log_err("  minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5606             }
5607         }
5608     }
5609 
5610     for (i = 0; i < sizeof(maximizeErrors) / sizeof(maximizeErrors[0]); ++i) {
5611 
5612         UErrorCode status = U_ZERO_ERROR;
5613         const char* const minimal = maximizeErrors[i].tag;
5614         const char* const maximal = maximizeErrors[i].expected;
5615         const UErrorCode expectedStatus = maximizeErrors[i].uerror;
5616         const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]);
5617         const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer));
5618 
5619         const int32_t length =
5620             uloc_addLikelySubtags(
5621                 minimal,
5622                 buffer,
5623                 bufferSize,
5624                 &status);
5625 
5626         if (status == U_ZERO_ERROR) {
5627             log_err("  unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus));
5628             status = U_ZERO_ERROR;
5629         }
5630         else if (status != expectedStatus) {
5631             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));
5632         }
5633         else if (length != expectedLength) {
5634             log_err("  unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length);
5635         }
5636         else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5637             if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) {
5638                 log_err("  maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5639                     maximal, minimal, (int)sizeof(buffer), buffer);
5640             }
5641         }
5642     }
5643 
5644     for (i = 0; i < sizeof(minimizeErrors) / sizeof(minimizeErrors[0]); ++i) {
5645 
5646         UErrorCode status = U_ZERO_ERROR;
5647         const char* const maximal = minimizeErrors[i].tag;
5648         const char* const minimal = minimizeErrors[i].expected;
5649         const UErrorCode expectedStatus = minimizeErrors[i].uerror;
5650         const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]);
5651         const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer));
5652 
5653         const int32_t length =
5654             uloc_minimizeSubtags(
5655                 maximal,
5656                 buffer,
5657                 bufferSize,
5658                 &status);
5659 
5660         if (status == U_ZERO_ERROR) {
5661             log_err("  unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus));
5662             status = U_ZERO_ERROR;
5663         }
5664         else if (status != expectedStatus) {
5665             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));
5666         }
5667         else if (length != expectedLength) {
5668             log_err("  unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length);
5669         }
5670         else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5671             if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) {
5672                 log_err("  minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5673                     minimal, maximal, (int)sizeof(buffer), buffer);
5674             }
5675         }
5676     }
5677 }
5678 
5679 const char* const locale_to_langtag[][3] = {
5680     {"",            "und",          "und"},
5681     {"en",          "en",           "en"},
5682     {"en_US",       "en-US",        "en-US"},
5683     {"iw_IL",       "he-IL",        "he-IL"},
5684     {"sr_Latn_SR",  "sr-Latn-SR",   "sr-Latn-SR"},
5685     {"en__POSIX",   "en-u-va-posix", "en-u-va-posix"},
5686     {"en_POSIX",    "en-u-va-posix", "en-u-va-posix"},
5687     {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL},  /* variant POSIX_VAR is processed as regular variant */
5688     {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL},  /* variant VAR_POSIX is processed as regular variant */
5689     {"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 */
5690     {"en_US_POSIX@ca=japanese",  "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5691     {"und_555",     "und-555",      "und-555"},
5692     {"123",         "und",          NULL},
5693     {"%$#&",        "und",          NULL},
5694     {"_Latn",       "und-Latn",     "und-Latn"},
5695     {"_DE",         "und-DE",       "und-DE"},
5696     {"und_FR",      "und-FR",       "und-FR"},
5697     {"th_TH_TH",    "th-TH-x-lvariant-th", NULL},
5698     {"bogus",       "bogus",        "bogus"},
5699     {"foooobarrr",  "und",          NULL},
5700     {"az_AZ_CYRL",  "az-Cyrl-AZ",   "az-Cyrl-AZ"},
5701     {"aa_BB_CYRL",  "aa-BB-x-lvariant-cyrl", NULL},
5702     {"en_US_1234",  "en-US-1234",   "en-US-1234"},
5703     {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb",  "en-US-varianta-variantb"},
5704     {"ja__9876_5432",   "ja-9876-5432", "ja-9876-5432"},
5705     {"zh_Hant__VAR",    "zh-Hant-x-lvariant-var", NULL},
5706     {"es__BADVARIANT_GOODVAR",  "es-goodvar",   NULL},
5707     {"en@calendar=gregorian",   "en-u-ca-gregory",  "en-u-ca-gregory"},
5708     {"de@collation=phonebook;calendar=gregorian",   "de-u-ca-gregory-co-phonebk",   "de-u-ca-gregory-co-phonebk"},
5709     {"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"},
5710     {"en@timezone=America/New_York;calendar=japanese",    "en-u-ca-japanese-tz-usnyc",    "en-u-ca-japanese-tz-usnyc"},
5711     {"en@timezone=US/Eastern",  "en-u-tz-usnyc",    "en-u-tz-usnyc"},
5712     {"en@x=x-y-z;a=a-b-c",  "en-x-x-y-z",   NULL},
5713     {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic",  NULL},
5714     {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5715     {"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"},
5716     {"@x=elmer",    "x-elmer",      "x-elmer"},
5717     {"en@x=elmer",  "en-x-elmer",   "en-x-elmer"},
5718     {"@x=elmer;a=exta", "und-a-exta-x-elmer",   "und-a-exta-x-elmer"},
5719     {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5720     {NULL,          NULL,           NULL}
5721 };
5722 
TestToLanguageTag(void)5723 static void TestToLanguageTag(void) {
5724     char langtag[256];
5725     int32_t i;
5726     UErrorCode status;
5727     int32_t len;
5728     const char *inloc;
5729     const char *expected;
5730 
5731     for (i = 0; locale_to_langtag[i][0] != NULL; i++) {
5732         inloc = locale_to_langtag[i][0];
5733 
5734         /* testing non-strict mode */
5735         status = U_ZERO_ERROR;
5736         langtag[0] = 0;
5737         expected = locale_to_langtag[i][1];
5738 
5739         len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status);
5740         (void)len;    /* Suppress set but not used warning. */
5741         if (U_FAILURE(status)) {
5742             if (expected != NULL) {
5743                 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5744                     inloc, u_errorName(status));
5745             }
5746         } else {
5747             if (expected == NULL) {
5748                 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5749                     inloc, langtag);
5750             } else if (uprv_strcmp(langtag, expected) != 0) {
5751                 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5752                     langtag, inloc, expected);
5753             }
5754         }
5755 
5756         /* testing strict mode */
5757         status = U_ZERO_ERROR;
5758         langtag[0] = 0;
5759         expected = locale_to_langtag[i][2];
5760 
5761         len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status);
5762         if (U_FAILURE(status)) {
5763             if (expected != NULL) {
5764                 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5765                     inloc, u_errorName(status));
5766             }
5767         } else {
5768             if (expected == NULL) {
5769                 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5770                     inloc, langtag);
5771             } else if (uprv_strcmp(langtag, expected) != 0) {
5772                 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5773                     langtag, inloc, expected);
5774             }
5775         }
5776     }
5777 }
5778 
5779 #define FULL_LENGTH -1
5780 static const struct {
5781     const char  *bcpID;
5782     const char  *locID;
5783     int32_t     len;
5784 } langtag_to_locale[] = {
5785     {"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},
5786     {"en",                  "en",                   FULL_LENGTH},
5787     {"en-us",               "en_US",                FULL_LENGTH},
5788     {"und-US",              "_US",                  FULL_LENGTH},
5789     {"und-latn",            "_Latn",                FULL_LENGTH},
5790     {"en-US-posix",         "en_US_POSIX",          FULL_LENGTH},
5791     {"de-de_euro",          "de",                   2},
5792     {"kok-IN",              "kok_IN",               FULL_LENGTH},
5793     {"123",                 "",                     0},
5794     {"en_us",               "",                     0},
5795     {"en-latn-x",           "en_Latn",              7},
5796     {"art-lojban",          "jbo",                  FULL_LENGTH},
5797     {"zh-hakka",            "hak",                  FULL_LENGTH},
5798     {"zh-cmn-CH",           "cmn_CH",               FULL_LENGTH},
5799     {"xxx-yy",              "xxx_YY",               FULL_LENGTH},
5800     {"fr-234",              "fr_234",               FULL_LENGTH},
5801     {"i-default",           "en@x=i-default",       FULL_LENGTH},
5802     {"i-test",              "",                     0},
5803     {"ja-jp-jp",            "ja_JP",                5},
5804     {"bogus",               "bogus",                FULL_LENGTH},
5805     {"boguslang",           "",                     0},
5806     {"EN-lATN-us",          "en_Latn_US",           FULL_LENGTH},
5807     {"und-variant-1234",    "__VARIANT_1234",       FULL_LENGTH},
5808     {"und-varzero-var1-vartwo", "__VARZERO",        11},
5809     {"en-u-ca-gregory",     "en@calendar=gregorian",    FULL_LENGTH},
5810     {"en-U-cu-USD",         "en@currency=usd",      FULL_LENGTH},
5811     {"en-US-u-va-posix",    "en_US_POSIX",          FULL_LENGTH},
5812     {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian",   FULL_LENGTH},
5813     {"en-us-posix-u-va-posix",   "en_US_POSIX@va=posix",    FULL_LENGTH},
5814     {"en-us-u-va-posix2",        "en_US@va=posix2",         FULL_LENGTH},
5815     {"en-us-vari1-u-va-posix",   "en_US_VARI1@va=posix",    FULL_LENGTH},
5816     {"ar-x-1-2-3",          "ar@x=1-2-3",           FULL_LENGTH},
5817     {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH},
5818     {"de-k-kext-u-co-phonebk-nu-latn",  "de@collation=phonebook;k=kext;numbers=latn",   FULL_LENGTH},
5819     {"ja-u-cu-jpy-ca-jp",   "ja@calendar=yes;currency=jpy;jp=yes",  FULL_LENGTH},
5820     {"en-us-u-tz-usnyc",    "en_US@timezone=America/New_York",  FULL_LENGTH},
5821     {"und-a-abc-def",       "und@a=abc-def",        FULL_LENGTH},
5822     {"zh-u-ca-chinese-x-u-ca-chinese",  "zh@calendar=chinese;x=u-ca-chinese",   FULL_LENGTH},
5823     {"x-elmer",             "@x=elmer",             FULL_LENGTH},
5824     {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian",    FULL_LENGTH},
5825     {"sr-u-kn",             "sr@colnumeric=yes",    FULL_LENGTH},
5826     {"de-u-kn-co-phonebk",  "de@collation=phonebook;colnumeric=yes",    FULL_LENGTH},
5827     {"en-u-attr2-attr1-kn-kb",  "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH},
5828     {"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},
5829 
5830     {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5831      "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
5832     {NULL,          NULL,           0}
5833 };
5834 
TestForLanguageTag(void)5835 static void TestForLanguageTag(void) {
5836     char locale[256];
5837     int32_t i;
5838     UErrorCode status;
5839     int32_t parsedLen;
5840     int32_t expParsedLen;
5841 
5842     for (i = 0; langtag_to_locale[i].bcpID != NULL; i++) {
5843         status = U_ZERO_ERROR;
5844         locale[0] = 0;
5845         expParsedLen = langtag_to_locale[i].len;
5846         if (expParsedLen == FULL_LENGTH) {
5847             expParsedLen = uprv_strlen(langtag_to_locale[i].bcpID);
5848         }
5849         uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status);
5850         if (U_FAILURE(status)) {
5851             log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5852                 langtag_to_locale[i].bcpID, u_errorName(status));
5853         } else {
5854             if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) {
5855                 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5856                     locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID);
5857             }
5858             if (parsedLen != expParsedLen) {
5859                 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5860                     parsedLen, langtag_to_locale[i].bcpID, expParsedLen);
5861             }
5862         }
5863     }
5864 }
5865 
TestToUnicodeLocaleKey(void)5866 static void TestToUnicodeLocaleKey(void)
5867 {
5868     /* $IN specifies the result should be the input pointer itself */
5869     static const char* DATA[][2] = {
5870         {"calendar",    "ca"},
5871         {"CALEndar",    "ca"},  /* difference casing */
5872         {"ca",          "ca"},  /* bcp key itself */
5873         {"kv",          "kv"},  /* no difference between legacy and bcp */
5874         {"foo",         NULL},  /* unknown, bcp ill-formed */
5875         {"ZZ",          "$IN"}, /* unknown, bcp well-formed -  */
5876         {NULL,          NULL}
5877     };
5878 
5879     int32_t i;
5880     for (i = 0; DATA[i][0] != NULL; i++) {
5881         const char* keyword = DATA[i][0];
5882         const char* expected = DATA[i][1];
5883         const char* bcpKey = NULL;
5884 
5885         bcpKey = uloc_toUnicodeLocaleKey(keyword);
5886         if (expected == NULL) {
5887             if (bcpKey != NULL) {
5888                 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey);
5889             }
5890         } else if (bcpKey == NULL) {
5891             log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
5892         } else if (uprv_strcmp(expected, "$IN") == 0) {
5893             if (bcpKey != keyword) {
5894                 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword);
5895             }
5896         } else if (uprv_strcmp(bcpKey, expected) != 0) {
5897             log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected);
5898         }
5899     }
5900 }
5901 
TestToLegacyKey(void)5902 static void TestToLegacyKey(void)
5903 {
5904     /* $IN specifies the result should be the input pointer itself */
5905     static const char* DATA[][2] = {
5906         {"kb",          "colbackwards"},
5907         {"kB",          "colbackwards"},    /* different casing */
5908         {"Collation",   "collation"},   /* keyword itself with different casing */
5909         {"kv",          "kv"},  /* no difference between legacy and bcp */
5910         {"foo",         "$IN"}, /* unknown, bcp ill-formed */
5911         {"ZZ",          "$IN"}, /* unknown, bcp well-formed */
5912         {"e=mc2",       NULL},  /* unknown, bcp/legacy ill-formed */
5913         {NULL,          NULL}
5914     };
5915 
5916     int32_t i;
5917     for (i = 0; DATA[i][0] != NULL; i++) {
5918         const char* keyword = DATA[i][0];
5919         const char* expected = DATA[i][1];
5920         const char* legacyKey = NULL;
5921 
5922         legacyKey = uloc_toLegacyKey(keyword);
5923         if (expected == NULL) {
5924             if (legacyKey != NULL) {
5925                 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey);
5926             }
5927         } else if (legacyKey == NULL) {
5928             log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
5929         } else if (uprv_strcmp(expected, "$IN") == 0) {
5930             if (legacyKey != keyword) {
5931                 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword);
5932             }
5933         } else if (uprv_strcmp(legacyKey, expected) != 0) {
5934             log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected);
5935         }
5936     }
5937 }
5938 
TestToUnicodeLocaleType(void)5939 static void TestToUnicodeLocaleType(void)
5940 {
5941     /* $IN specifies the result should be the input pointer itself */
5942     static const char* DATA[][3] = {
5943         {"tz",              "Asia/Kolkata",     "inccu"},
5944         {"calendar",        "gregorian",        "gregory"},
5945         {"ca",              "gregorian",        "gregory"},
5946         {"ca",              "Gregorian",        "gregory"},
5947         {"ca",              "buddhist",         "buddhist"},
5948         {"Calendar",        "Japanese",         "japanese"},
5949         {"calendar",        "Islamic-Civil",    "islamic-civil"},
5950         {"calendar",        "islamicc",         "islamic-civil"},   /* bcp type alias */
5951         {"colalternate",    "NON-IGNORABLE",    "noignore"},
5952         {"colcaselevel",    "yes",              "true"},
5953         {"tz",              "america/new_york", "usnyc"},
5954         {"tz",              "Asia/Kolkata",     "inccu"},
5955         {"timezone",        "navajo",           "usden"},
5956         {"ca",              "aaaa",             "$IN"},     /* unknown type, well-formed type */
5957         {"ca",              "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
5958         {"zz",              "gregorian",        NULL},      /* unknown key, ill-formed type */
5959         {"co",              "foo-",             NULL},      /* unknown type, ill-formed type */
5960         {"variableTop",     "00A0",             "$IN"},     /* valid codepoints type */
5961         {"variableTop",     "wxyz",             "$IN"},     /* invalid codepoints type - return as is for now */
5962         {"kr",              "space-punct",      "space-punct"}, /* valid reordercode type */
5963         {"kr",              "digit-spacepunct", NULL},      /* invalid (bcp ill-formed) reordercode type */
5964         {NULL,              NULL,               NULL}
5965     };
5966 
5967     int32_t i;
5968     for (i = 0; DATA[i][0] != NULL; i++) {
5969         const char* keyword = DATA[i][0];
5970         const char* value = DATA[i][1];
5971         const char* expected = DATA[i][2];
5972         const char* bcpType = NULL;
5973 
5974         bcpType = uloc_toUnicodeLocaleType(keyword, value);
5975         if (expected == NULL) {
5976             if (bcpType != NULL) {
5977                 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType);
5978             }
5979         } else if (bcpType == NULL) {
5980             log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
5981         } else if (uprv_strcmp(expected, "$IN") == 0) {
5982             if (bcpType != value) {
5983                 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value);
5984             }
5985         } else if (uprv_strcmp(bcpType, expected) != 0) {
5986             log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected);
5987         }
5988     }
5989 }
5990 
TestToLegacyType(void)5991 static void TestToLegacyType(void)
5992 {
5993     /* $IN specifies the result should be the input pointer itself */
5994     static const char* DATA[][3] = {
5995         {"calendar",        "gregory",          "gregorian"},
5996         {"ca",              "gregory",          "gregorian"},
5997         {"ca",              "Gregory",          "gregorian"},
5998         {"ca",              "buddhist",         "buddhist"},
5999         {"Calendar",        "Japanese",         "japanese"},
6000         {"calendar",        "Islamic-Civil",    "islamic-civil"},
6001         {"calendar",        "islamicc",         "islamic-civil"},   /* bcp type alias */
6002         {"colalternate",    "noignore",         "non-ignorable"},
6003         {"colcaselevel",    "true",             "yes"},
6004         {"tz",              "usnyc",            "America/New_York"},
6005         {"tz",              "inccu",            "Asia/Calcutta"},
6006         {"timezone",        "usden",            "America/Denver"},
6007         {"timezone",        "usnavajo",         "America/Denver"},  /* bcp type alias */
6008         {"colstrength",     "quarternary",      "quaternary"},  /* type alias */
6009         {"ca",              "aaaa",             "$IN"}, /* unknown type */
6010         {"calendar",        "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6011         {"zz",              "gregorian",        "$IN"}, /* unknown key, bcp ill-formed type */
6012         {"ca",              "gregorian-calendar",   "$IN"}, /* known key, bcp ill-formed type */
6013         {"co",              "e=mc2",            NULL},  /* known key, ill-formed bcp/legacy type */
6014         {"variableTop",     "00A0",             "$IN"},     /* valid codepoints type */
6015         {"variableTop",     "wxyz",             "$IN"},    /* invalid codepoints type - return as is for now */
6016         {"kr",              "space-punct",      "space-punct"}, /* valid reordercode type */
6017         {"kr",              "digit-spacepunct", "digit-spacepunct"},    /* invalid reordercode type, but ok for legacy syntax */
6018         {NULL,              NULL,               NULL}
6019     };
6020 
6021     int32_t i;
6022     for (i = 0; DATA[i][0] != NULL; i++) {
6023         const char* keyword = DATA[i][0];
6024         const char* value = DATA[i][1];
6025         const char* expected = DATA[i][2];
6026         const char* legacyType = NULL;
6027 
6028         legacyType = uloc_toLegacyType(keyword, value);
6029         if (expected == NULL) {
6030             if (legacyType != NULL) {
6031                 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType);
6032             }
6033         } else if (legacyType == NULL) {
6034             log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6035         } else if (uprv_strcmp(expected, "$IN") == 0) {
6036             if (legacyType != value) {
6037                 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value);
6038             }
6039         } else if (uprv_strcmp(legacyType, expected) != 0) {
6040             log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected);
6041         }
6042     }
6043 }
6044 
6045 
6046 
test_unicode_define(const char * namech,char ch,const char * nameu,UChar uch)6047 static void test_unicode_define(const char *namech, char ch, const char *nameu, UChar uch)
6048 {
6049   UChar asUch[1];
6050   asUch[0]=0;
6051   log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech, ch,(int)ch, nameu, (int) uch);
6052   u_charsToUChars(&ch, asUch, 1);
6053   if(asUch[0] != uch) {
6054     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);
6055   } else {
6056     log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]);
6057   }
6058 }
6059 
6060 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6061 
TestUnicodeDefines(void)6062 static void TestUnicodeDefines(void) {
6063   TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE);
6064   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
6065   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
6066 }
6067 
TestIsRightToLeft()6068 static void TestIsRightToLeft() {
6069     // API test only. More test cases in intltest/LocaleTest.
6070     if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6071         log_err("uloc_isRightToLeft() failed");
6072     }
6073 }
6074