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