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