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