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