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