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