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