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