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