| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /******************************************************************** |
| * COPYRIGHT: |
| * Copyright (c) 1997-2016, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ********************************************************************/ |
| /***************************************************************************** |
| * |
| * File CLOCTST.C |
| * |
| * Modification History: |
| * Name Description |
| * Madhu Katragadda Ported for C API |
| ****************************************************************************** |
| */ |
| #include "cloctst.h" |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include "cintltst.h" |
| #include "cmemory.h" |
| #include "cstring.h" |
| #include "uparse.h" |
| #include "uresimp.h" |
| #include "uassert.h" |
| |
| #include "unicode/putil.h" |
| #include "unicode/ubrk.h" |
| #include "unicode/uchar.h" |
| #include "unicode/ucol.h" |
| #include "unicode/udat.h" |
| #include "unicode/uloc.h" |
| #include "unicode/umsg.h" |
| #include "unicode/ures.h" |
| #include "unicode/uset.h" |
| #include "unicode/ustring.h" |
| #include "unicode/utypes.h" |
| #include "unicode/ulocdata.h" |
| #include "unicode/uldnames.h" |
| #include "unicode/parseerr.h" /* may not be included with some uconfig switches */ |
| #include "udbgutil.h" |
| |
| static void TestNullDefault(void); |
| static void TestNonexistentLanguageExemplars(void); |
| static void TestLocDataErrorCodeChaining(void); |
| static void TestLocDataWithRgTag(void); |
| static void TestLanguageExemplarsFallbacks(void); |
| static void TestDisplayNameBrackets(void); |
| static void TestIllegalArgumentWhenNoDataWithNoSubstitute(void); |
| static void Test21157CorrectTerminating(void); |
| |
| static void TestUnicodeDefines(void); |
| |
| static void TestIsRightToLeft(void); |
| static void TestBadLocaleIDs(void); |
| static void TestBug20370(void); |
| static void TestBug20321UnicodeLocaleKey(void); |
| |
| static void TestUsingDefaultWarning(void); |
| static void TestExcessivelyLongIDs(void); |
| #if !UCONFIG_NO_FORMATTING |
| static void TestUldnNameVariants(void); |
| #endif |
| |
| void PrintDataTable(); |
| |
| /*--------------------------------------------------- |
| table of valid data |
| --------------------------------------------------- */ |
| #define LOCALE_SIZE 9 |
| #define LOCALE_INFO_SIZE 28 |
| |
| static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = { |
| /* language code */ |
| { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" }, |
| /* script code */ |
| { "", "", "", "", "", "", "", "", "" }, |
| /* country code */ |
| { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" }, |
| /* variant code */ |
| { "", "", "", "", "NY", "", "", "", "" }, |
| /* full name */ |
| { "en_US", "fr_FR", "ca_ES", |
| "el_GR", "no_NO_NY", "zh_Hans_CN", |
| "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" }, |
| /* ISO-3 language */ |
| { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" }, |
| /* ISO-3 country */ |
| { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" }, |
| /* LCID */ |
| { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" }, |
| |
| /* display language (English) */ |
| { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" }, |
| /* display script code (English) */ |
| { "", "", "", "", "", "Simplified Han", "", "", "" }, |
| /* display country (English) */ |
| { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" }, |
| /* display variant (English) */ |
| { "", "", "", "", "NY", "", "", "", "" }, |
| /* display name (English) */ |
| { "English (United States)", "French (France)", "Catalan (Spain)", |
| "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)", |
| "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" }, |
| |
| /* display language (French) */ |
| { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" }, |
| /* display script code (French) */ |
| { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" }, |
| /* display country (French) */ |
| { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" }, |
| /* display variant (French) */ |
| { "", "", "", "", "NY", "", "", "", "" }, |
| /* display name (French) */ |
| { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", |
| "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)", |
| "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" }, |
| |
| /* display language (Catalan) */ |
| { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" }, |
| /* display script code (Catalan) */ |
| { "", "", "", "", "", "han simplificat", "", "", "" }, |
| /* display country (Catalan) */ |
| { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" }, |
| /* display variant (Catalan) */ |
| { "", "", "", "", "NY", "", "", "", "" }, |
| /* display name (Catalan) */ |
| { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", |
| "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)", |
| "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" }, |
| |
| /* display language (Greek) */ |
| { |
| "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", |
| "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", |
| "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac", |
| "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", |
| "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac", |
| "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC", |
| "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", |
| "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", |
| "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC" |
| }, |
| /* display script code (Greek) */ |
| |
| { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" }, |
| /* display country (Greek) */ |
| { |
| "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2", |
| "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", |
| "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1", |
| "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", |
| "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1", |
| "\\u039A\\u03AF\\u03BD\\u03B1", |
| "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1", |
| "", |
| "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1" |
| }, |
| /* display variant (Greek) */ |
| { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */ |
| /* display name (Greek) */ |
| { |
| "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)", |
| "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", |
| "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)", |
| "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", |
| "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", |
| "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)", |
| "\\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)", |
| "\\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)", |
| "\\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)" |
| } |
| }; |
| |
| static UChar*** dataTable=0; |
| enum { |
| ENGLISH = 0, |
| FRENCH = 1, |
| CATALAN = 2, |
| GREEK = 3, |
| NORWEGIAN = 4 |
| }; |
| |
| enum { |
| LANG = 0, |
| SCRIPT = 1, |
| CTRY = 2, |
| VAR = 3, |
| NAME = 4, |
| LANG3 = 5, |
| CTRY3 = 6, |
| LCID = 7, |
| DLANG_EN = 8, |
| DSCRIPT_EN = 9, |
| DCTRY_EN = 10, |
| DVAR_EN = 11, |
| DNAME_EN = 12, |
| DLANG_FR = 13, |
| DSCRIPT_FR = 14, |
| DCTRY_FR = 15, |
| DVAR_FR = 16, |
| DNAME_FR = 17, |
| DLANG_CA = 18, |
| DSCRIPT_CA = 19, |
| DCTRY_CA = 20, |
| DVAR_CA = 21, |
| DNAME_CA = 22, |
| DLANG_EL = 23, |
| DSCRIPT_EL = 24, |
| DCTRY_EL = 25, |
| DVAR_EL = 26, |
| DNAME_EL = 27 |
| }; |
| |
| #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name) |
| |
| void addLocaleTest(TestNode** root); |
| |
| void addLocaleTest(TestNode** root) |
| { |
| TESTCASE(TestObsoleteNames); /* srl- move */ |
| TESTCASE(TestBasicGetters); |
| TESTCASE(TestNullDefault); |
| TESTCASE(TestPrefixes); |
| TESTCASE(TestSimpleResourceInfo); |
| TESTCASE(TestDisplayNames); |
| TESTCASE(TestGetDisplayScriptPreFlighting21160); |
| TESTCASE(TestGetAvailableLocales); |
| TESTCASE(TestGetAvailableLocalesByType); |
| TESTCASE(TestDataDirectory); |
| #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
| TESTCASE(TestISOFunctions); |
| #endif |
| TESTCASE(TestISO3Fallback); |
| TESTCASE(TestUninstalledISO3Names); |
| TESTCASE(TestSimpleDisplayNames); |
| TESTCASE(TestVariantParsing); |
| TESTCASE(TestKeywordVariants); |
| TESTCASE(TestKeywordVariantParsing); |
| TESTCASE(TestCanonicalization); |
| TESTCASE(TestCanonicalizationBuffer); |
| TESTCASE(TestKeywordSet); |
| TESTCASE(TestKeywordSetError); |
| TESTCASE(TestDisplayKeywords); |
| TESTCASE(TestCanonicalization21749StackUseAfterScope); |
| TESTCASE(TestDisplayKeywordValues); |
| TESTCASE(TestGetBaseName); |
| #if !UCONFIG_NO_FILE_IO |
| TESTCASE(TestGetLocale); |
| #endif |
| TESTCASE(TestDisplayNameWarning); |
| TESTCASE(Test21157CorrectTerminating); |
| TESTCASE(TestNonexistentLanguageExemplars); |
| TESTCASE(TestLocDataErrorCodeChaining); |
| TESTCASE(TestLocDataWithRgTag); |
| TESTCASE(TestLanguageExemplarsFallbacks); |
| TESTCASE(TestCalendar); |
| TESTCASE(TestDateFormat); |
| TESTCASE(TestCollation); |
| TESTCASE(TestULocale); |
| TESTCASE(TestUResourceBundle); |
| TESTCASE(TestDisplayName); |
| TESTCASE(TestAcceptLanguage); |
| TESTCASE(TestGetLocaleForLCID); |
| TESTCASE(TestOrientation); |
| TESTCASE(TestLikelySubtags); |
| TESTCASE(TestToLanguageTag); |
| TESTCASE(TestBug20132); |
| TESTCASE(TestBug20149); |
| TESTCASE(TestCDefaultLocale); |
| TESTCASE(TestForLanguageTag); |
| TESTCASE(TestLangAndRegionCanonicalize); |
| TESTCASE(TestTrailingNull); |
| TESTCASE(TestUnicodeDefines); |
| TESTCASE(TestEnglishExemplarCharacters); |
| TESTCASE(TestDisplayNameBrackets); |
| TESTCASE(TestIllegalArgumentWhenNoDataWithNoSubstitute); |
| TESTCASE(TestIsRightToLeft); |
| TESTCASE(TestToUnicodeLocaleKey); |
| TESTCASE(TestToLegacyKey); |
| TESTCASE(TestToUnicodeLocaleType); |
| TESTCASE(TestToLegacyType); |
| TESTCASE(TestBadLocaleIDs); |
| TESTCASE(TestBug20370); |
| TESTCASE(TestBug20321UnicodeLocaleKey); |
| TESTCASE(TestUsingDefaultWarning); |
| TESTCASE(TestBug21449InfiniteLoop); |
| TESTCASE(TestExcessivelyLongIDs); |
| #if !UCONFIG_NO_FORMATTING |
| TESTCASE(TestUldnNameVariants); |
| #endif |
| } |
| |
| |
| /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */ |
| static void TestBasicGetters() { |
| int32_t i; |
| int32_t cap; |
| UErrorCode status = U_ZERO_ERROR; |
| char *testLocale = 0; |
| char *temp = 0, *name = 0; |
| log_verbose("Testing Basic Getters\n"); |
| for (i = 0; i < LOCALE_SIZE; i++) { |
| testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1)); |
| strcpy(testLocale,rawData2[NAME][i]); |
| |
| log_verbose("Testing %s .....\n", testLocale); |
| cap=uloc_getLanguage(testLocale, NULL, 0, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status=U_ZERO_ERROR; |
| temp=(char*)malloc(sizeof(char) * (cap+1)); |
| uloc_getLanguage(testLocale, temp, cap+1, &status); |
| } |
| if(U_FAILURE(status)){ |
| log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status)); |
| } |
| if (0 !=strcmp(temp,rawData2[LANG][i])) { |
| log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]); |
| } |
| |
| |
| cap=uloc_getCountry(testLocale, temp, cap, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status=U_ZERO_ERROR; |
| temp=(char*)realloc(temp, sizeof(char) * (cap+1)); |
| uloc_getCountry(testLocale, temp, cap+1, &status); |
| } |
| if(U_FAILURE(status)){ |
| log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status)); |
| } |
| if (0 != strcmp(temp, rawData2[CTRY][i])) { |
| log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]); |
| |
| } |
| |
| cap=uloc_getVariant(testLocale, temp, cap, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status=U_ZERO_ERROR; |
| temp=(char*)realloc(temp, sizeof(char) * (cap+1)); |
| uloc_getVariant(testLocale, temp, cap+1, &status); |
| } |
| if(U_FAILURE(status)){ |
| log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status)); |
| } |
| if (0 != strcmp(temp, rawData2[VAR][i])) { |
| log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]); |
| } |
| |
| cap=uloc_getName(testLocale, NULL, 0, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status=U_ZERO_ERROR; |
| name=(char*)malloc(sizeof(char) * (cap+1)); |
| uloc_getName(testLocale, name, cap+1, &status); |
| } else if(status==U_ZERO_ERROR) { |
| log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale); |
| } |
| if(U_FAILURE(status)){ |
| log_err("ERROR: in uloc_getName %s\n", myErrorName(status)); |
| } |
| if (0 != strcmp(name, rawData2[NAME][i])){ |
| log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]); |
| } |
| |
| free(temp); |
| free(name); |
| |
| free(testLocale); |
| } |
| } |
| |
| static void TestNullDefault() { |
| UErrorCode status = U_ZERO_ERROR; |
| char original[ULOC_FULLNAME_CAPACITY]; |
| |
| uprv_strcpy(original, uloc_getDefault()); |
| uloc_setDefault("qq_BLA", &status); |
| if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) { |
| log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault()); |
| } |
| uloc_setDefault(NULL, &status); |
| if (uprv_strcmp(uloc_getDefault(), original) != 0) { |
| log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n"); |
| } |
| |
| { |
| /* Test that set & get of default locale work, and that |
| * default locales are cached and reused, and not overwritten. |
| */ |
| const char *n_en_US; |
| const char *n_fr_FR; |
| const char *n2_en_US; |
| |
| status = U_ZERO_ERROR; |
| uloc_setDefault("en_US", &status); |
| n_en_US = uloc_getDefault(); |
| if (strcmp(n_en_US, "en_US") != 0) { |
| log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); |
| } |
| |
| uloc_setDefault("fr_FR", &status); |
| n_fr_FR = uloc_getDefault(); |
| if (strcmp(n_en_US, "en_US") != 0) { |
| log_err("uloc_setDefault altered previously default string." |
| "Expected \"en_US\", got \"%s\"\n", n_en_US); |
| } |
| if (strcmp(n_fr_FR, "fr_FR") != 0) { |
| log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR); |
| } |
| |
| uloc_setDefault("en_US", &status); |
| n2_en_US = uloc_getDefault(); |
| if (strcmp(n2_en_US, "en_US") != 0) { |
| log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); |
| } |
| if (n2_en_US != n_en_US) { |
| log_err("Default locale cache failed to reuse en_US locale.\n"); |
| } |
| |
| if (U_FAILURE(status)) { |
| log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status)); |
| } |
| |
| } |
| uloc_setDefault(original, &status); |
| if (U_FAILURE(status)) { |
| log_err("Failed to change the default locale back to %s\n", original); |
| } |
| |
| } |
| /* Test the i- and x- and @ and . functionality |
| */ |
| |
| #define PREFIXBUFSIZ 128 |
| |
| static void TestPrefixes() { |
| int row = 0; |
| int n; |
| const char *loc, *expected; |
| |
| static const char * const testData[][7] = |
| { |
| /* NULL canonicalize() column means "expect same as getName()" */ |
| {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL}, |
| {"en", "", "GB", "", "en-gb", "en_GB", NULL}, |
| {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL}, |
| {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL}, |
| {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL}, |
| {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL}, |
| {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", "hyw"}, |
| {"de", "", "", "1901", "de-1901", "de__1901", NULL}, |
| {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"}, |
| {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"}, |
| {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */ |
| {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"}, |
| {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"}, |
| {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"}, |
| {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"}, |
| {"no", "", "", "NY", "no__ny", "no__NY", NULL}, |
| {"no", "", "", "", "no@ny", "no@ny", "no__NY"}, |
| {"el", "Latn", "", "", "el-latn", "el_Latn", NULL}, |
| {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL}, |
| {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL}, |
| {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL}, |
| {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL}, /* total garbage */ |
| |
| // Before ICU 64, ICU locale canonicalization had some additional mappings. |
| // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants". |
| // The following now use standard canonicalization. |
| {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans__PINYIN"}, |
| {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW_STROKE"}, |
| |
| {NULL,NULL,NULL,NULL,NULL,NULL,NULL} |
| }; |
| |
| static const char * const testTitles[] = { |
| "uloc_getLanguage()", |
| "uloc_getScript()", |
| "uloc_getCountry()", |
| "uloc_getVariant()", |
| "name", |
| "uloc_getName()", |
| "uloc_canonicalize()" |
| }; |
| |
| char buf[PREFIXBUFSIZ]; |
| int32_t len; |
| UErrorCode err; |
| |
| |
| for(row=0;testData[row][0] != NULL;row++) { |
| loc = testData[row][NAME]; |
| log_verbose("Test #%d: %s\n", row, loc); |
| |
| err = U_ZERO_ERROR; |
| len=0; |
| buf[0]=0; |
| for(n=0;n<=(NAME+2);n++) { |
| if(n==NAME) continue; |
| |
| for(len=0;len<PREFIXBUFSIZ;len++) { |
| buf[len] = '%'; /* Set a tripwire.. */ |
| } |
| len = 0; |
| |
| switch(n) { |
| case LANG: |
| len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| case SCRIPT: |
| len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| case CTRY: |
| len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| case VAR: |
| len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| case NAME+1: |
| len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| case NAME+2: |
| len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err); |
| break; |
| |
| default: |
| strcpy(buf, "**??"); |
| len=4; |
| } |
| |
| if(U_FAILURE(err)) { |
| log_err("#%d: %s on %s: err %s\n", |
| row, testTitles[n], loc, u_errorName(err)); |
| } else { |
| log_verbose("#%d: %s on %s: -> [%s] (length %d)\n", |
| row, testTitles[n], loc, buf, len); |
| |
| if(len != (int32_t)strlen(buf)) { |
| log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n", |
| row, testTitles[n], loc, buf, len, strlen(buf)+1); |
| |
| } |
| |
| /* see if they smashed something */ |
| if(buf[len+1] != '%') { |
| log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n", |
| row, testTitles[n], loc, buf, buf[len+1]); |
| } |
| |
| expected = testData[row][n]; |
| if (expected == NULL && n == (NAME+2)) { |
| /* NULL expected canonicalize() means "expect same as getName()" */ |
| expected = testData[row][NAME+1]; |
| } |
| if(strcmp(buf, expected)) { |
| log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n", |
| row, testTitles[n], loc, buf, expected); |
| |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* testing uloc_getISO3Language(), uloc_getISO3Country(), */ |
| static void TestSimpleResourceInfo() { |
| int32_t i; |
| char* testLocale = 0; |
| UChar* expected = 0; |
| |
| const char* temp; |
| char temp2[20]; |
| testLocale=(char*)malloc(sizeof(char) * 1); |
| expected=(UChar*)malloc(sizeof(UChar) * 1); |
| |
| setUpDataTable(); |
| log_verbose("Testing getISO3Language and getISO3Country\n"); |
| for (i = 0; i < LOCALE_SIZE; i++) { |
| |
| testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1)); |
| u_austrcpy(testLocale, dataTable[NAME][i]); |
| |
| log_verbose("Testing %s ......\n", testLocale); |
| |
| temp=uloc_getISO3Language(testLocale); |
| expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); |
| u_uastrcpy(expected,temp); |
| if (0 != u_strcmp(expected, dataTable[LANG3][i])) { |
| log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected), |
| austrdup(dataTable[LANG3][i])); |
| } |
| |
| temp=uloc_getISO3Country(testLocale); |
| expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); |
| u_uastrcpy(expected,temp); |
| if (0 != u_strcmp(expected, dataTable[CTRY3][i])) { |
| log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected), |
| austrdup(dataTable[CTRY3][i])); |
| } |
| sprintf(temp2, "%x", (int)uloc_getLCID(testLocale)); |
| if (strcmp(temp2, rawData2[LCID][i]) != 0) { |
| log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]); |
| } |
| } |
| |
| free(expected); |
| free(testLocale); |
| cleanUpDataTable(); |
| } |
| |
| /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null |
| * if there's room but won't be included in result. result < 0 indicates an error. |
| * Returns the number of chars written (not those that would be written if there's enough room.*/ |
| static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) { |
| static const struct { |
| char escapedChar; |
| UChar sourceVal; |
| } ESCAPE_MAP[] = { |
| /*a*/ {'a', 0x07}, |
| /*b*/ {'b', 0x08}, |
| /*e*/ {'e', 0x1b}, |
| /*f*/ {'f', 0x0c}, |
| /*n*/ {'n', 0x0a}, |
| /*r*/ {'r', 0x0d}, |
| /*t*/ {'t', 0x09}, |
| /*v*/ {'v', 0x0b} |
| }; |
| static const int32_t ESCAPE_MAP_LENGTH = UPRV_LENGTHOF(ESCAPE_MAP); |
| static const char HEX_DIGITS[] = { |
| '0', '1', '2', '3', '4', '5', '6', '7', |
| '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' |
| }; |
| int32_t i, j; |
| int32_t resultLen = 0; |
| const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */ |
| const int32_t escapeLimit1 = buflen-2; |
| const int32_t escapeLimit2 = buflen-6; |
| UChar uc; |
| |
| if(utext==NULL || resultChars==NULL || buflen<0) { |
| return -1; |
| } |
| |
| for(i=0;i<limit && resultLen<buflen;++i) { |
| uc=utext[i]; |
| if(len<0 && uc==0) { |
| break; |
| } |
| if(uc<0x20) { |
| for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) { |
| } |
| if(j<ESCAPE_MAP_LENGTH) { |
| if(resultLen>escapeLimit1) { |
| break; |
| } |
| resultChars[resultLen++]='\\'; |
| resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar; |
| continue; |
| } |
| } else if(uc<0x7f) { |
| u_austrncpy(resultChars + resultLen, &uc, 1); |
| resultLen++; |
| continue; |
| } |
| |
| if(resultLen>escapeLimit2) { |
| break; |
| } |
| |
| /* have to escape the uchar */ |
| resultChars[resultLen++]='\\'; |
| resultChars[resultLen++]='u'; |
| resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff]; |
| resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff]; |
| resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff]; |
| resultChars[resultLen++]=HEX_DIGITS[uc&0xff]; |
| } |
| |
| if(resultLen<buflen) { |
| resultChars[resultLen] = 0; |
| } |
| |
| return resultLen; |
| } |
| |
| /* |
| * Jitterbug 2439 -- markus 20030425 |
| * |
| * The lookup of display names must not fall back through the default |
| * locale because that yields useless results. |
| */ |
| static void TestDisplayNames() |
| { |
| UChar buffer[100]; |
| UErrorCode errorCode=U_ZERO_ERROR; |
| int32_t length; |
| log_verbose("Testing getDisplayName for different locales\n"); |
| |
| log_verbose(" In locale = en_US...\n"); |
| doTestDisplayNames("en_US", DLANG_EN); |
| log_verbose(" In locale = fr_FR....\n"); |
| doTestDisplayNames("fr_FR", DLANG_FR); |
| log_verbose(" In locale = ca_ES...\n"); |
| doTestDisplayNames("ca_ES", DLANG_CA); |
| log_verbose(" In locale = gr_EL..\n"); |
| doTestDisplayNames("el_GR", DLANG_EL); |
| |
| /* test that the default locale has a display name for its own language */ |
| errorCode=U_ZERO_ERROR; |
| length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode); |
| /* check <=3 to reject getting the language code as a display name */ |
| if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) { |
| const char* defaultLocale = uloc_getDefault(); |
| for (int32_t i = 0, count = uloc_countAvailable(); i < count; i++) { |
| /* Only report error if the default locale is in the available list */ |
| if (uprv_strcmp(defaultLocale, uloc_getAvailable(i)) == 0) { |
| 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)); |
| break; |
| } |
| } |
| } |
| |
| /* test that we get the language code itself for an unknown language, and a default warning */ |
| errorCode=U_ZERO_ERROR; |
| length=uloc_getDisplayLanguage("qq", "rr", buffer, UPRV_LENGTHOF(buffer), &errorCode); |
| if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) { |
| log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode)); |
| } |
| |
| /* test that we get a default warning for a display name where one component is unknown (4255) */ |
| errorCode=U_ZERO_ERROR; |
| length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, UPRV_LENGTHOF(buffer), &errorCode); |
| if(errorCode!=U_USING_DEFAULT_WARNING) { |
| log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode)); |
| } |
| |
| { |
| int32_t i; |
| static const char *aLocale = "es@collation=traditional;calendar=japanese"; |
| static const char *testL[] = { "en_US", |
| "fr_FR", |
| "ca_ES", |
| "el_GR" }; |
| static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */ |
| "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)", |
| "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)", |
| "\\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)" }; |
| UChar *expectBuffer; |
| |
| for(i=0;i<UPRV_LENGTHOF(testL);i++) { |
| errorCode = U_ZERO_ERROR; |
| uloc_getDisplayName(aLocale, testL[i], buffer, UPRV_LENGTHOF(buffer), &errorCode); |
| if(U_FAILURE(errorCode)) { |
| log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode)); |
| } else { |
| expectBuffer = CharsToUChars(expect[i]); |
| if(u_strcmp(buffer,expectBuffer)) { |
| 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)); |
| } else { |
| log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]); |
| } |
| free(expectBuffer); |
| } |
| } |
| } |
| |
| /* test that we properly preflight and return data when there's a non-default pattern, |
| see ticket #8262. */ |
| { |
| int32_t i; |
| static const char *locale="az_Cyrl"; |
| static const char *displayLocale="ja"; |
| static const char *expectedChars = |
| "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e " |
| "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)"; |
| UErrorCode ec=U_ZERO_ERROR; |
| UChar result[256]; |
| int32_t len; |
| int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec); |
| /* inconvenient semantics when preflighting, this condition is expected... */ |
| if(ec==U_BUFFER_OVERFLOW_ERROR) { |
| ec=U_ZERO_ERROR; |
| } |
| len=uloc_getDisplayName(locale, displayLocale, result, UPRV_LENGTHOF(result), &ec); |
| if(U_FAILURE(ec)) { |
| log_err("uloc_getDisplayName(%s, %s...) returned error: %s", |
| locale, displayLocale, u_errorName(ec)); |
| } else { |
| UChar *expected=CharsToUChars(expectedChars); |
| int32_t expectedLen=u_strlen(expected); |
| |
| if(len!=expectedLen) { |
| log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d", |
| locale, displayLocale, len, expectedLen); |
| } else if(preflightLen!=expectedLen) { |
| log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d", |
| locale, displayLocale, preflightLen, expectedLen); |
| } else if(u_strncmp(result, expected, len)) { |
| int32_t cap=len*6+1; /* worst case + space for trailing null */ |
| char* resultChars=(char*)malloc(cap); |
| int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap); |
| if(resultCharsLen<0 || resultCharsLen<cap-1) { |
| log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale); |
| } else { |
| log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'", |
| locale, displayLocale, resultChars, expectedChars); |
| } |
| free(resultChars); |
| resultChars=NULL; |
| } else { |
| /* test all buffer sizes */ |
| for(i=len+1;i>=0;--i) { |
| len=uloc_getDisplayName(locale, displayLocale, result, i, &ec); |
| if(ec==U_BUFFER_OVERFLOW_ERROR) { |
| ec=U_ZERO_ERROR; |
| } |
| if(U_FAILURE(ec)) { |
| log_err("using buffer of length %d returned error %s", i, u_errorName(ec)); |
| break; |
| } |
| if(len!=expectedLen) { |
| log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len); |
| break; |
| } |
| /* There's no guarantee about what's in the buffer if we've overflowed, in particular, |
| * we don't know that it's been filled, so no point in checking. */ |
| } |
| } |
| |
| free(expected); |
| } |
| } |
| } |
| |
| /** |
| * ICU-21160 test the pre-flighting call to uloc_getDisplayScript returns the actual length needed |
| * for the result buffer. |
| */ |
| static void TestGetDisplayScriptPreFlighting21160() |
| { |
| const char* locale = "und-Latn"; |
| const char* inlocale = "de"; |
| |
| UErrorCode ec = U_ZERO_ERROR; |
| UChar* result = NULL; |
| int32_t length = uloc_getDisplayScript(locale, inlocale, NULL, 0, &ec) + 1; |
| ec = U_ZERO_ERROR; |
| result=(UChar*)malloc(sizeof(UChar) * length); |
| length = uloc_getDisplayScript(locale, inlocale, result, length, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("uloc_getDisplayScript length %d returned error %s", length, u_errorName(ec)); |
| } |
| free(result); |
| } |
| |
| /* test for uloc_getAvailable() and uloc_countAvailable()*/ |
| static void TestGetAvailableLocales() |
| { |
| |
| const char *locList; |
| int32_t locCount,i; |
| |
| log_verbose("Testing the no of available locales\n"); |
| locCount=uloc_countAvailable(); |
| if (locCount == 0) |
| log_data_err("countAvailable() returned an empty list!\n"); |
| |
| /* use something sensible w/o hardcoding the count */ |
| else if(locCount < 0){ |
| log_data_err("countAvailable() returned a wrong value!= %d\n", locCount); |
| } |
| else{ |
| log_info("Number of locales returned = %d\n", locCount); |
| } |
| for(i=0;i<locCount;i++){ |
| locList=uloc_getAvailable(i); |
| |
| log_verbose(" %s\n", locList); |
| } |
| } |
| |
| static void TestGetAvailableLocalesByType() { |
| UErrorCode status = U_ZERO_ERROR; |
| |
| UEnumeration* uenum = uloc_openAvailableByType(ULOC_AVAILABLE_DEFAULT, &status); |
| assertSuccess("Constructing the UEnumeration", &status); |
| |
| assertIntEquals("countAvailable() should be same in old and new methods", |
| uloc_countAvailable(), |
| uenum_count(uenum, &status)); |
| |
| for (int32_t i = 0; i < uloc_countAvailable(); i++) { |
| const char* old = uloc_getAvailable(i); |
| int32_t len = 0; |
| const char* new = uenum_next(uenum, &len, &status); |
| assertEquals("Old and new strings should equal", old, new); |
| assertIntEquals("String length should be correct", uprv_strlen(old), len); |
| } |
| assertPtrEquals("Should get nullptr on the last string", |
| NULL, uenum_next(uenum, NULL, &status)); |
| |
| uenum_close(uenum); |
| |
| uenum = uloc_openAvailableByType(ULOC_AVAILABLE_ONLY_LEGACY_ALIASES, &status); |
| UBool found_he = FALSE; |
| UBool found_iw = FALSE; |
| const char* loc; |
| while ((loc = uenum_next(uenum, NULL, &status))) { |
| if (uprv_strcmp("he", loc) == 0) { |
| found_he = TRUE; |
| } |
| if (uprv_strcmp("iw", loc) == 0) { |
| found_iw = TRUE; |
| } |
| } |
| assertTrue("Should NOT have found he amongst the legacy/alias locales", !found_he); |
| assertTrue("Should have found iw amongst the legacy/alias locales", found_iw); |
| uenum_close(uenum); |
| |
| uenum = uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES, &status); |
| found_he = FALSE; |
| found_iw = FALSE; |
| const UChar* uloc; // test the UChar conversion |
| int32_t count = 0; |
| while ((uloc = uenum_unext(uenum, NULL, &status))) { |
| if (u_strcmp(u"iw", uloc) == 0) { |
| found_iw = TRUE; |
| } |
| if (u_strcmp(u"he", uloc) == 0) { |
| found_he = TRUE; |
| } |
| count++; |
| } |
| assertTrue("Should have found he amongst all locales", found_he); |
| assertTrue("Should have found iw amongst all locales", found_iw); |
| assertIntEquals("Should return as many strings as claimed", |
| count, uenum_count(uenum, &status)); |
| |
| // Reset the enumeration and it should still work |
| uenum_reset(uenum, &status); |
| count = 0; |
| while ((loc = uenum_next(uenum, NULL, &status))) { |
| count++; |
| } |
| assertIntEquals("After reset, should return as many strings as claimed", |
| count, uenum_count(uenum, &status)); |
| |
| uenum_close(uenum); |
| |
| assertSuccess("No errors should have occurred", &status); |
| } |
| |
| /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */ |
| static void TestDataDirectory() |
| { |
| |
| char oldDirectory[512]; |
| const char *temp,*testValue1,*testValue2,*testValue3; |
| const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */ |
| |
| log_verbose("Testing getDataDirectory()\n"); |
| temp = u_getDataDirectory(); |
| strcpy(oldDirectory, temp); |
| |
| testValue1=uloc_getISO3Language("en_US"); |
| log_verbose("first fetch of language retrieved %s\n", testValue1); |
| |
| if (0 != strcmp(testValue1,"eng")){ |
| log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1); |
| } |
| |
| /*defining the path for DataDirectory */ |
| log_verbose("Testing setDataDirectory\n"); |
| u_setDataDirectory( path ); |
| if(strcmp(path, u_getDataDirectory())==0) |
| log_verbose("setDataDirectory working fine\n"); |
| else |
| log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path); |
| |
| testValue2=uloc_getISO3Language("en_US"); |
| log_verbose("second fetch of language retrieved %s \n", testValue2); |
| |
| u_setDataDirectory(oldDirectory); |
| testValue3=uloc_getISO3Language("en_US"); |
| log_verbose("third fetch of language retrieved %s \n", testValue3); |
| |
| if (0 != strcmp(testValue3,"eng")) { |
| log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3); |
| } |
| } |
| |
| |
| |
| /*=========================================================== */ |
| |
| static UChar _NUL=0; |
| |
| static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t i; |
| int32_t maxresultsize; |
| |
| const char *testLocale; |
| |
| |
| UChar *testLang = 0; |
| UChar *testScript = 0; |
| UChar *testCtry = 0; |
| UChar *testVar = 0; |
| UChar *testName = 0; |
| |
| |
| UChar* expectedLang = 0; |
| UChar* expectedScript = 0; |
| UChar* expectedCtry = 0; |
| UChar* expectedVar = 0; |
| UChar* expectedName = 0; |
| |
| setUpDataTable(); |
| |
| for(i=0;i<LOCALE_SIZE; ++i) |
| { |
| testLocale=rawData2[NAME][i]; |
| |
| log_verbose("Testing..... %s\n", testLocale); |
| |
| maxresultsize=0; |
| maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) |
| { |
| status=U_ZERO_ERROR; |
| testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); |
| uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status); |
| } |
| else |
| { |
| testLang=&_NUL; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Error in getDisplayLanguage() %s\n", myErrorName(status)); |
| } |
| |
| maxresultsize=0; |
| maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) |
| { |
| status=U_ZERO_ERROR; |
| testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); |
| uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status); |
| } |
| else |
| { |
| testScript=&_NUL; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Error in getDisplayScript() %s\n", myErrorName(status)); |
| } |
| |
| maxresultsize=0; |
| maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) |
| { |
| status=U_ZERO_ERROR; |
| testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); |
| uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status); |
| } |
| else |
| { |
| testCtry=&_NUL; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Error in getDisplayCountry() %s\n", myErrorName(status)); |
| } |
| |
| maxresultsize=0; |
| maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) |
| { |
| status=U_ZERO_ERROR; |
| testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); |
| uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status); |
| } |
| else |
| { |
| testVar=&_NUL; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Error in getDisplayVariant() %s\n", myErrorName(status)); |
| } |
| |
| maxresultsize=0; |
| maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) |
| { |
| status=U_ZERO_ERROR; |
| testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); |
| uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status); |
| } |
| else |
| { |
| testName=&_NUL; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Error in getDisplayName() %s\n", myErrorName(status)); |
| } |
| |
| expectedLang=dataTable[compareIndex][i]; |
| if(u_strlen(expectedLang)== 0) |
| expectedLang=dataTable[DLANG_EN][i]; |
| |
| expectedScript=dataTable[compareIndex + 1][i]; |
| if(u_strlen(expectedScript)== 0) |
| expectedScript=dataTable[DSCRIPT_EN][i]; |
| |
| expectedCtry=dataTable[compareIndex + 2][i]; |
| if(u_strlen(expectedCtry)== 0) |
| expectedCtry=dataTable[DCTRY_EN][i]; |
| |
| expectedVar=dataTable[compareIndex + 3][i]; |
| if(u_strlen(expectedVar)== 0) |
| expectedVar=dataTable[DVAR_EN][i]; |
| |
| expectedName=dataTable[compareIndex + 4][i]; |
| if(u_strlen(expectedName) == 0) |
| expectedName=dataTable[DNAME_EN][i]; |
| |
| if (0 !=u_strcmp(testLang,expectedLang)) { |
| log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale); |
| } |
| |
| if (0 != u_strcmp(testScript,expectedScript)) { |
| log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale); |
| } |
| |
| if (0 != u_strcmp(testCtry,expectedCtry)) { |
| log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale); |
| } |
| |
| if (0 != u_strcmp(testVar,expectedVar)) { |
| log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale); |
| } |
| |
| if(0 != u_strcmp(testName, expectedName)) { |
| log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale); |
| } |
| |
| if(testName!=&_NUL) { |
| free(testName); |
| } |
| if(testLang!=&_NUL) { |
| free(testLang); |
| } |
| if(testScript!=&_NUL) { |
| free(testScript); |
| } |
| if(testCtry!=&_NUL) { |
| free(testCtry); |
| } |
| if(testVar!=&_NUL) { |
| free(testVar); |
| } |
| } |
| cleanUpDataTable(); |
| } |
| |
| /*------------------------------ |
| * TestDisplayNameBrackets |
| */ |
| |
| typedef struct { |
| const char * displayLocale; |
| const char * namedRegion; |
| const char * namedLocale; |
| const char * regionName; |
| const char * localeName; |
| } DisplayNameBracketsItem; |
| |
| static const DisplayNameBracketsItem displayNameBracketsItems[] = { |
| { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" }, |
| { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" }, |
| { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" }, |
| { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" }, |
| { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" }, |
| { NULL, NULL, NULL, NULL, NULL } |
| }; |
| |
| enum { kDisplayNameBracketsMax = 128 }; |
| |
| static void TestDisplayNameBrackets() |
| { |
| const DisplayNameBracketsItem * itemPtr = displayNameBracketsItems; |
| for (; itemPtr->displayLocale != NULL; itemPtr++) { |
| ULocaleDisplayNames * uldn; |
| UErrorCode status; |
| UChar expectRegionName[kDisplayNameBracketsMax]; |
| UChar expectLocaleName[kDisplayNameBracketsMax]; |
| UChar getName[kDisplayNameBracketsMax]; |
| int32_t ulen; |
| |
| (void) u_unescape(itemPtr->regionName, expectRegionName, kDisplayNameBracketsMax); |
| (void) u_unescape(itemPtr->localeName, expectLocaleName, kDisplayNameBracketsMax); |
| |
| status = U_ZERO_ERROR; |
| ulen = uloc_getDisplayCountry(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status); |
| if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) { |
| log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| ulen = uloc_getDisplayName(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status); |
| if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) { |
| log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); |
| } |
| |
| #if !UCONFIG_NO_FORMATTING |
| status = U_ZERO_ERROR; |
| uldn = uldn_open(itemPtr->displayLocale, ULDN_STANDARD_NAMES, &status); |
| if (U_SUCCESS(status)) { |
| status = U_ZERO_ERROR; |
| ulen = uldn_regionDisplayName(uldn, itemPtr->namedRegion, getName, kDisplayNameBracketsMax, &status); |
| if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) { |
| log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedRegion, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| ulen = uldn_localeDisplayName(uldn, itemPtr->namedLocale, getName, kDisplayNameBracketsMax, &status); |
| if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) { |
| log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); |
| } |
| |
| uldn_close(uldn); |
| } else { |
| log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr->displayLocale, u_errorName(status)); |
| } |
| #endif |
| (void)ulen; /* Suppress variable not used warning */ |
| } |
| } |
| |
| /*------------------------------ |
| * TestIllegalArgumentWhenNoDataWithNoSubstitute |
| */ |
| |
| static void TestIllegalArgumentWhenNoDataWithNoSubstitute() |
| { |
| #if !UCONFIG_NO_FORMATTING |
| UErrorCode status = U_ZERO_ERROR; |
| UChar getName[kDisplayNameBracketsMax]; |
| UDisplayContext contexts[] = { |
| UDISPCTX_NO_SUBSTITUTE, |
| }; |
| ULocaleDisplayNames* ldn = uldn_openForContext("en", contexts, 1, &status); |
| |
| uldn_localeDisplayName(ldn, "efg", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_localeDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_languageDisplayName(ldn, "zz", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_languageDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_scriptDisplayName(ldn, "Aaaa", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_scriptDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_regionDisplayName(ldn, "KK", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_regionDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_variantDisplayName(ldn, "ZZ", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_variantDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_keyDisplayName(ldn, "zz", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_keyDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| status = U_ZERO_ERROR; |
| uldn_keyValueDisplayName(ldn, "ca", "zz", getName, kDisplayNameBracketsMax, &status); |
| if (status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("FAIL uldn_keyValueDisplayName should return U_ILLEGAL_ARGUMENT_ERROR " |
| "while no resource under UDISPCTX_NO_SUBSTITUTE"); |
| } |
| |
| uldn_close(ldn); |
| #endif |
| } |
| |
| /*------------------------------ |
| * TestISOFunctions |
| */ |
| |
| #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
| /* test for uloc_getISOLanguages, uloc_getISOCountries */ |
| static void TestISOFunctions() |
| { |
| const char* const* str=uloc_getISOLanguages(); |
| const char* const* str1=uloc_getISOCountries(); |
| const char* test; |
| const char *key = NULL; |
| int32_t count = 0, skipped = 0; |
| int32_t expect; |
| UResourceBundle *res; |
| UResourceBundle *subRes; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| /* test getISOLanguages*/ |
| /*str=uloc_getISOLanguages(); */ |
| log_verbose("Testing ISO Languages: \n"); |
| |
| /* use structLocale - this data is no longer in root */ |
| res = ures_openDirect(loadTestData(&status), "structLocale", &status); |
| subRes = ures_getByKey(res, "Languages", NULL, &status); |
| if (U_FAILURE(status)) { |
| log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status)); |
| return; |
| } |
| |
| expect = ures_getSize(subRes); |
| for(count = 0; *(str+count) != 0; count++) |
| { |
| key = NULL; |
| test = *(str+count); |
| status = U_ZERO_ERROR; |
| |
| do { |
| /* Skip over language tags. This API only returns language codes. */ |
| skipped += (key != NULL); |
| ures_getNextString(subRes, NULL, &key, &status); |
| } |
| while (key != NULL && strchr(key, '_')); |
| |
| if(key == NULL) |
| break; |
| /* TODO: Consider removing sh, which is deprecated */ |
| if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) { |
| ures_getNextString(subRes, NULL, &key, &status); |
| skipped++; |
| } |
| #if U_CHARSET_FAMILY==U_ASCII_FAMILY |
| /* This code only works on ASCII machines where the keys are stored in ASCII order */ |
| if(strcmp(test,key)) { |
| /* The first difference usually implies the place where things get out of sync */ |
| log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); |
| } |
| #endif |
| |
| if(!strcmp(test,"in")) |
| log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); |
| if(!strcmp(test,"iw")) |
| log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); |
| if(!strcmp(test,"ji")) |
| log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); |
| if(!strcmp(test,"jw")) |
| log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); |
| if(!strcmp(test,"sh")) |
| log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); |
| } |
| |
| expect -= skipped; /* Ignore the skipped resources from structLocale */ |
| |
| if(count!=expect) { |
| log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect); |
| } |
| |
| subRes = ures_getByKey(res, "Countries", subRes, &status); |
| log_verbose("Testing ISO Countries"); |
| skipped = 0; |
| expect = ures_getSize(subRes) - 1; /* Skip ZZ */ |
| for(count = 0; *(str1+count) != 0; count++) |
| { |
| key = NULL; |
| test = *(str1+count); |
| do { |
| /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */ |
| skipped += (key != NULL); |
| ures_getNextString(subRes, NULL, &key, &status); |
| } |
| while (key != NULL && strlen(key) != 2); |
| |
| if(key == NULL) |
| break; |
| /* TODO: Consider removing CS, which is deprecated */ |
| while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) { |
| ures_getNextString(subRes, NULL, &key, &status); |
| skipped++; |
| } |
| #if U_CHARSET_FAMILY==U_ASCII_FAMILY |
| /* This code only works on ASCII machines where the keys are stored in ASCII order */ |
| if(strcmp(test,key)) { |
| /* The first difference usually implies the place where things get out of sync */ |
| log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); |
| } |
| #endif |
| if(!strcmp(test,"FX")) |
| log_err("FAIL getISOCountries() has obsolete country code %s\n", test); |
| if(!strcmp(test,"YU")) |
| log_err("FAIL getISOCountries() has obsolete country code %s\n", test); |
| if(!strcmp(test,"ZR")) |
| log_err("FAIL getISOCountries() has obsolete country code %s\n", test); |
| } |
| |
| ures_getNextString(subRes, NULL, &key, &status); |
| if (strcmp(key, "ZZ") != 0) { |
| log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key); |
| } |
| #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY |
| /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */ |
| key = NULL; |
| do { |
| /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */ |
| skipped += (key != NULL); |
| ures_getNextString(subRes, NULL, &key, &status); |
| } |
| while (U_SUCCESS(status) && key != NULL && strlen(key) != 2); |
| #endif |
| expect -= skipped; /* Ignore the skipped resources from structLocale */ |
| if(count!=expect) |
| { |
| log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect); |
| } |
| ures_close(subRes); |
| ures_close(res); |
| } |
| #endif |
| |
| static void setUpDataTable() |
| { |
| int32_t i,j; |
| dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE)); |
| |
| for (i = 0; i < LOCALE_INFO_SIZE; i++) { |
| dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE)); |
| for (j = 0; j < LOCALE_SIZE; j++){ |
| dataTable[i][j] = CharsToUChars(rawData2[i][j]); |
| } |
| } |
| } |
| |
| static void cleanUpDataTable() |
| { |
| int32_t i,j; |
| if(dataTable != NULL) { |
| for (i=0; i<LOCALE_INFO_SIZE; i++) { |
| for(j = 0; j < LOCALE_SIZE; j++) { |
| free(dataTable[i][j]); |
| } |
| free(dataTable[i]); |
| } |
| free(dataTable); |
| } |
| dataTable = NULL; |
| } |
| |
| /** |
| * @bug 4011756 4011380 |
| */ |
| static void TestISO3Fallback() |
| { |
| const char* test="xx_YY"; |
| |
| const char * result; |
| |
| result = uloc_getISO3Language(test); |
| |
| /* Conform to C API usage */ |
| |
| if (!result || (result[0] != 0)) |
| log_err("getISO3Language() on xx_YY returned %s instead of \"\""); |
| |
| result = uloc_getISO3Country(test); |
| |
| if (!result || (result[0] != 0)) |
| log_err("getISO3Country() on xx_YY returned %s instead of \"\""); |
| } |
| |
| /** |
| * @bug 4118587 |
| */ |
| static void TestSimpleDisplayNames() |
| { |
| /* |
| This test is different from TestDisplayNames because TestDisplayNames checks |
| fallback behavior, combination of language and country names to form locale |
| names, and other stuff like that. This test just checks specific language |
| and country codes to make sure we have the correct names for them. |
| */ |
| char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" }; |
| const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish", |
| "Zhuang", "419" }; |
| const char* inLocale [] = { "en_US", "zh_Hant"}; |
| UErrorCode status=U_ZERO_ERROR; |
| |
| int32_t i; |
| int32_t localeIndex = 0; |
| for (i = 0; i < 7; i++) { |
| UChar *testLang=0; |
| UChar *expectedLang=0; |
| int size=0; |
| |
| if (i == 6) { |
| localeIndex = 1; /* Use the second locale for the rest of the test. */ |
| } |
| |
| size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| testLang=(UChar*)malloc(sizeof(UChar) * (size + 1)); |
| uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status); |
| } |
| expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1)); |
| u_uastrcpy(expectedLang, languageNames[i]); |
| if (u_strcmp(testLang, expectedLang) != 0) |
| log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n", |
| languageCodes[i], languageNames[i], austrdup(testLang)); |
| free(testLang); |
| free(expectedLang); |
| } |
| |
| } |
| |
| /** |
| * @bug 4118595 |
| */ |
| static void TestUninstalledISO3Names() |
| { |
| /* This test checks to make sure getISO3Language and getISO3Country work right |
| even for locales that are not installed. */ |
| static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn", |
| "ss", "tw", "zu" }; |
| static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run", |
| "ssw", "twi", "zul" }; |
| static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN", |
| "ss_SB", "tw_TC", "zu_ZW" }; |
| static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG", |
| "SLB", "TCA", "ZWE" }; |
| int32_t i; |
| |
| for (i = 0; i < 8; i++) { |
| UErrorCode err = U_ZERO_ERROR; |
| const char *test; |
| test = uloc_getISO3Language(iso2Languages[i]); |
| if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err)) |
| log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", |
| iso2Languages[i], iso3Languages[i], test, myErrorName(err)); |
| } |
| for (i = 0; i < 8; i++) { |
| UErrorCode err = U_ZERO_ERROR; |
| const char *test; |
| test = uloc_getISO3Country(iso2Countries[i]); |
| if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err)) |
| log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", |
| iso2Countries[i], iso3Countries[i], test, myErrorName(err)); |
| } |
| } |
| |
| |
| static void TestVariantParsing() |
| { |
| static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth"; |
| static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)"; |
| static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH"; |
| static const char* shortVariant="fr_FR_foo"; |
| static const char* bogusVariant="fr_FR__foo"; |
| static const char* bogusVariant2="fr_FR_foo_"; |
| static const char* bogusVariant3="fr_FR__foo_"; |
| |
| |
| UChar displayVar[100]; |
| UChar displayName[100]; |
| UErrorCode status=U_ZERO_ERROR; |
| UChar* got=0; |
| int32_t size=0; |
| size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| u_uastrcpy(displayVar, dispVar); |
| if(u_strcmp(got,displayVar)!=0) { |
| log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got)); |
| } |
| size=0; |
| size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| u_uastrcpy(displayName, dispName); |
| if(u_strcmp(got,displayName)!=0) { |
| if (status == U_USING_DEFAULT_WARNING) { |
| log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status)); |
| } else { |
| log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got)); |
| } |
| } |
| |
| size=0; |
| status=U_ZERO_ERROR; |
| size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| if(strcmp(austrdup(got),"FOO")!=0) { |
| log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got)); |
| } |
| size=0; |
| status=U_ZERO_ERROR; |
| size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| if(strcmp(austrdup(got),"_FOO")!=0) { |
| log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got)); |
| } |
| size=0; |
| status=U_ZERO_ERROR; |
| size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| if(strcmp(austrdup(got),"FOO_")!=0) { |
| log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got)); |
| } |
| size=0; |
| status=U_ZERO_ERROR; |
| size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR) { |
| status=U_ZERO_ERROR; |
| got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); |
| uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status); |
| } |
| else { |
| log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); |
| } |
| if(strcmp(austrdup(got),"_FOO_")!=0) { |
| log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got)); |
| } |
| free(got); |
| } |
| |
| |
| static void TestObsoleteNames(void) |
| { |
| int32_t i; |
| UErrorCode status = U_ZERO_ERROR; |
| char buff[256]; |
| |
| static const struct |
| { |
| char locale[9]; |
| char lang3[4]; |
| char lang[4]; |
| char ctry3[4]; |
| char ctry[4]; |
| } tests[] = |
| { |
| { "eng_USA", "eng", "en", "USA", "US" }, |
| { "kok", "kok", "kok", "", "" }, |
| { "in", "ind", "in", "", "" }, |
| { "id", "ind", "id", "", "" }, /* NO aliasing */ |
| { "sh", "srp", "sh", "", "" }, |
| { "zz_CS", "", "zz", "SCG", "CS" }, |
| { "zz_FX", "", "zz", "FXX", "FX" }, |
| { "zz_RO", "", "zz", "ROU", "RO" }, |
| { "zz_TP", "", "zz", "TMP", "TP" }, |
| { "zz_TL", "", "zz", "TLS", "TL" }, |
| { "zz_ZR", "", "zz", "ZAR", "ZR" }, |
| { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */ |
| { "zz_ROM", "", "zz", "ROU", "RO" }, |
| { "zz_ROU", "", "zz", "ROU", "RO" }, |
| { "zz_ZAR", "", "zz", "ZAR", "ZR" }, |
| { "zz_TMP", "", "zz", "TMP", "TP" }, |
| { "zz_TLS", "", "zz", "TLS", "TL" }, |
| { "zz_YUG", "", "zz", "YUG", "YU" }, |
| { "mlt_PSE", "mlt", "mt", "PSE", "PS" }, |
| { "iw", "heb", "iw", "", "" }, |
| { "ji", "yid", "ji", "", "" }, |
| { "jw", "jaw", "jw", "", "" }, |
| { "sh", "srp", "sh", "", "" }, |
| { "", "", "", "", "" } |
| }; |
| |
| for(i=0;tests[i].locale[0];i++) |
| { |
| const char *locale; |
| |
| locale = tests[i].locale; |
| log_verbose("** %s:\n", locale); |
| |
| status = U_ZERO_ERROR; |
| if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) |
| { |
| log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", |
| locale, uloc_getISO3Language(locale), tests[i].lang3); |
| } |
| else |
| { |
| log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", |
| uloc_getISO3Language(locale) ); |
| } |
| |
| status = U_ZERO_ERROR; |
| uloc_getLanguage(locale, buff, 256, &status); |
| if(U_FAILURE(status)) |
| { |
| log_err("FAIL: error getting language from %s\n", locale); |
| } |
| else |
| { |
| if(strcmp(buff,tests[i].lang)) |
| { |
| log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n", |
| locale, buff, tests[i].lang); |
| } |
| else |
| { |
| log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff); |
| } |
| } |
| if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) |
| { |
| log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", |
| locale, uloc_getISO3Language(locale), tests[i].lang3); |
| } |
| else |
| { |
| log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", |
| uloc_getISO3Language(locale) ); |
| } |
| |
| if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale))) |
| { |
| log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n", |
| locale, uloc_getISO3Country(locale), tests[i].ctry3); |
| } |
| else |
| { |
| log_verbose(" uloc_getISO3Country()==\t\"%s\"\n", |
| uloc_getISO3Country(locale) ); |
| } |
| |
| status = U_ZERO_ERROR; |
| uloc_getCountry(locale, buff, 256, &status); |
| if(U_FAILURE(status)) |
| { |
| log_err("FAIL: error getting country from %s\n", locale); |
| } |
| else |
| { |
| if(strcmp(buff,tests[i].ctry)) |
| { |
| log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n", |
| locale, buff, tests[i].ctry); |
| } |
| else |
| { |
| log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff); |
| } |
| } |
| } |
| |
| if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) { |
| log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL")); |
| } |
| |
| if (uloc_getLCID("iw") != uloc_getLCID("he")) { |
| log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he")); |
| } |
| |
| #if 0 |
| |
| i = uloc_getLanguage("kok",NULL,0,&icu_err); |
| if(U_FAILURE(icu_err)) |
| { |
| log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err)); |
| } |
| |
| icu_err = U_ZERO_ERROR; |
| uloc_getLanguage("kok",r1_buff,12,&icu_err); |
| if(U_FAILURE(icu_err)) |
| { |
| log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err)); |
| } |
| |
| r1_addr = (char *)uloc_getISO3Language("kok"); |
| |
| icu_err = U_ZERO_ERROR; |
| if (strcmp(r1_buff,"kok") != 0) |
| { |
| log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff); |
| line--; |
| } |
| r1_addr = (char *)uloc_getISO3Language("in"); |
| i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); |
| if (strcmp(r1_buff,"id") != 0) |
| { |
| printf("uloc_getLanguage error (%s)\n",r1_buff); |
| line--; |
| } |
| r1_addr = (char *)uloc_getISO3Language("sh"); |
| i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); |
| if (strcmp(r1_buff,"sr") != 0) |
| { |
| printf("uloc_getLanguage error (%s)\n",r1_buff); |
| line--; |
| } |
| |
| r1_addr = (char *)uloc_getISO3Country("zz_ZR"); |
| strcpy(p1_buff,"zz_"); |
| strcat(p1_buff,r1_addr); |
| i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); |
| if (strcmp(r1_buff,"ZR") != 0) |
| { |
| printf("uloc_getCountry error (%s)\n",r1_buff); |
| line--; |
| } |
| r1_addr = (char *)uloc_getISO3Country("zz_FX"); |
| strcpy(p1_buff,"zz_"); |
| strcat(p1_buff,r1_addr); |
| i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); |
| if (strcmp(r1_buff,"FX") != 0) |
| { |
| printf("uloc_getCountry error (%s)\n",r1_buff); |
| line--; |
| } |
| |
| #endif |
| |
| } |
| |
| static void TestKeywordVariants(void) |
| { |
| static const struct { |
| const char *localeID; |
| const char *expectedLocaleID; /* uloc_getName */ |
| const char *expectedLocaleIDNoKeywords; /* uloc_getBaseName */ |
| const char *expectedCanonicalID; /* uloc_canonicalize */ |
| const char *expectedKeywords[10]; |
| int32_t numKeywords; |
| UErrorCode expectedStatus; /* from uloc_openKeywords */ |
| } testCases[] = { |
| { |
| "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ", |
| "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", |
| "de_DE", |
| "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", |
| {"calendar", "collation", "currency"}, |
| 3, |
| U_ZERO_ERROR |
| }, |
| { |
| "de_DE@euro", |
| "de_DE@euro", |
| "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */ |
| "de_DE_EURO", |
| {"","","","","","",""}, |
| 0, |
| U_INVALID_FORMAT_ERROR /* must have '=' after '@' */ |
| }, |
| { |
| "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */ |
| "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */ |
| "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */ |
| "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */ |
| {"","","","","","",""}, |
| 0, |
| U_INVALID_FORMAT_ERROR |
| }, |
| { |
| "de_DE@collation=", |
| 0, /* expected getName to fail */ |
| "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */ |
| 0, /* expected canonicalize to fail */ |
| {"","","","","","",""}, |
| 0, |
| U_INVALID_FORMAT_ERROR /* must have '=' after '@' */ |
| } |
| }; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| int32_t i = 0, j = 0; |
| int32_t resultLen = 0; |
| char buffer[256]; |
| UEnumeration *keywords; |
| int32_t keyCount = 0; |
| const char *keyword = NULL; |
| int32_t keywordLen = 0; |
| |
| for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| status = U_ZERO_ERROR; |
| *buffer = 0; |
| keywords = uloc_openKeywords(testCases[i].localeID, &status); |
| |
| if(status != testCases[i].expectedStatus) { |
| log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n", |
| testCases[i].localeID, |
| u_errorName(testCases[i].expectedStatus), u_errorName(status)); |
| } |
| status = U_ZERO_ERROR; |
| if(keywords) { |
| if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) { |
| log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount); |
| } |
| if(keyCount) { |
| j = 0; |
| while((keyword = uenum_next(keywords, &keywordLen, &status))) { |
| if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { |
| log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); |
| } |
| j++; |
| } |
| j = 0; |
| uenum_reset(keywords, &status); |
| while((keyword = uenum_next(keywords, &keywordLen, &status))) { |
| if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { |
| log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); |
| } |
| j++; |
| } |
| } |
| uenum_close(keywords); |
| } |
| |
| status = U_ZERO_ERROR; |
| resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status); |
| (void)resultLen; |
| U_ASSERT(resultLen < 256); |
| if (U_SUCCESS(status)) { |
| if (testCases[i].expectedLocaleID == 0) { |
| log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n", |
| testCases[i].localeID, buffer); |
| } else if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) { |
| log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n", |
| testCases[i].localeID, testCases[i].expectedLocaleID, buffer); |
| } |
| } else { |
| if (testCases[i].expectedLocaleID != 0) { |
| log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n", |
| testCases[i].localeID, testCases[i].expectedLocaleID, buffer, u_errorName(status)); |
| } |
| } |
| |
| status = U_ZERO_ERROR; |
| resultLen = uloc_getBaseName(testCases[i].localeID, buffer, 256, &status); |
| U_ASSERT(resultLen < 256); |
| if (U_SUCCESS(status)) { |
| if (testCases[i].expectedLocaleIDNoKeywords == 0) { |
| log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n", |
| testCases[i].localeID, buffer); |
| } else if (uprv_strcmp(testCases[i].expectedLocaleIDNoKeywords, buffer) != 0) { |
| log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n", |
| testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer); |
| } |
| } else { |
| if (testCases[i].expectedLocaleIDNoKeywords != 0) { |
| log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n", |
| testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer, u_errorName(status)); |
| } |
| } |
| |
| status = U_ZERO_ERROR; |
| resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status); |
| U_ASSERT(resultLen < 256); |
| if (U_SUCCESS(status)) { |
| if (testCases[i].expectedCanonicalID == 0) { |
| log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n", |
| testCases[i].localeID, buffer); |
| } else if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) { |
| log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n", |
| testCases[i].localeID, testCases[i].expectedCanonicalID, buffer); |
| } |
| } else { |
| if (testCases[i].expectedCanonicalID != 0) { |
| log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n", |
| testCases[i].localeID, testCases[i].expectedCanonicalID, buffer, u_errorName(status)); |
| } |
| } |
| } |
| } |
| |
| static void TestKeywordVariantParsing(void) |
| { |
| static const struct { |
| const char *localeID; |
| const char *keyword; |
| const char *expectedValue; /* NULL if failure is expected */ |
| } testCases[] = { |
| { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", NULL }, /* malformed key name */ |
| { "de_DE", "collation", ""}, |
| { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" }, |
| { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" }, |
| }; |
| |
| UErrorCode status; |
| int32_t i = 0; |
| int32_t resultLen = 0; |
| char buffer[256]; |
| |
| for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| *buffer = 0; |
| status = U_ZERO_ERROR; |
| resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status); |
| (void)resultLen; /* Suppress set but not used warning. */ |
| if (testCases[i].expectedValue) { |
| /* expect success */ |
| if (U_FAILURE(status)) { |
| log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got status %s\n", |
| testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, u_errorName(status)); |
| } else if (uprv_strcmp(testCases[i].expectedValue, buffer) != 0) { |
| log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got \"%s\"\n", |
| testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer); |
| } |
| } else if (U_SUCCESS(status)) { |
| /* expect failure */ |
| log_err("Expected failure but got success from \"%s\" for keyword \"%s\". Got \"%s\"\n", |
| testCases[i].localeID, testCases[i].keyword, buffer); |
| |
| } |
| } |
| } |
| |
| static const struct { |
| const char *l; /* locale */ |
| const char *k; /* kw */ |
| const char *v; /* value */ |
| const char *x; /* expected */ |
| } kwSetTestCases[] = { |
| #if 1 |
| { "en_US", "calendar", "japanese", "en_US@calendar=japanese" }, |
| { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" }, |
| { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" }, |
| { "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 */ |
| { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" }, |
| { "de", "Currency", "CHF", "de@currency=CHF" }, |
| { "de", "Currency", "CHF", "de@currency=CHF" }, |
| |
| { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, |
| { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" }, |
| { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, |
| { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, |
| { "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 */ |
| { "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 */ |
| { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, |
| { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, |
| #endif |
| #if 1 |
| { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" }, |
| { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" }, |
| { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" }, |
| { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" }, |
| { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" }, |
| { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" }, |
| { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" }, |
| { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" }, |
| { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" }, |
| #endif |
| #if 1 |
| /* removal tests */ |
| /* 1. removal of item at end */ |
| { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" }, |
| { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" }, |
| /* 2. removal of item at beginning */ |
| { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" }, |
| { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" }, |
| /* 3. removal of an item not there */ |
| { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" }, |
| /* 4. removal of only item */ |
| { "de@collation=phonebook", "collation", NULL, "de" }, |
| #endif |
| { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, |
| /* cases with legal extra spacing */ |
| /*31*/{ "en_US@ calendar = islamic", "calendar", "japanese", "en_US@calendar=japanese" }, |
| /*32*/{ "en_US@ calendar = gregorian ; collation = phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, |
| /*33*/{ "en_US@ calendar = islamic", "currency", "CHF", "en_US@calendar=islamic;currency=CHF" }, |
| /*34*/{ "en_US@ currency = CHF", "calendar", "japanese", "en_US@calendar=japanese;currency=CHF" }, |
| /* cases in which setKeywordValue expected to fail (implied by NULL for expected); locale need not be canonical */ |
| /*35*/{ "en_US@calendar=gregorian;", "calendar", "japanese", NULL }, |
| /*36*/{ "en_US@calendar=gregorian;=", "calendar", "japanese", NULL }, |
| /*37*/{ "en_US@calendar=gregorian;currency=", "calendar", "japanese", NULL }, |
| /*38*/{ "en_US@=", "calendar", "japanese", NULL }, |
| /*39*/{ "en_US@=;", "calendar", "japanese", NULL }, |
| /*40*/{ "en_US@= ", "calendar", "japanese", NULL }, |
| /*41*/{ "en_US@ =", "calendar", "japanese", NULL }, |
| /*42*/{ "en_US@ = ", "calendar", "japanese", NULL }, |
| /*43*/{ "en_US@=;calendar=gregorian", "calendar", "japanese", NULL }, |
| /*44*/{ "en_US@= calen dar = gregorian", "calendar", "japanese", NULL }, |
| /*45*/{ "en_US@= calendar = greg orian", "calendar", "japanese", NULL }, |
| /*46*/{ "en_US@=;cal...endar=gregorian", "calendar", "japanese", NULL }, |
| /*47*/{ "en_US@=;calendar=greg...orian", "calendar", "japanese", NULL }, |
| /*48*/{ "en_US@calendar=gregorian", "cale ndar", "japanese", NULL }, |
| /*49*/{ "en_US@calendar=gregorian", "calendar", "japa..nese", NULL }, |
| /* cases in which getKeywordValue and setKeyword expected to fail (implied by NULL for value and expected) */ |
| /*50*/{ "en_US@=", "calendar", NULL, NULL }, |
| /*51*/{ "en_US@=;", "calendar", NULL, NULL }, |
| /*52*/{ "en_US@= ", "calendar", NULL, NULL }, |
| /*53*/{ "en_US@ =", "calendar", NULL, NULL }, |
| /*54*/{ "en_US@ = ", "calendar", NULL, NULL }, |
| /*55*/{ "en_US@=;calendar=gregorian", "calendar", NULL, NULL }, |
| /*56*/{ "en_US@= calen dar = gregorian", "calendar", NULL, NULL }, |
| /*57*/{ "en_US@= calendar = greg orian", "calendar", NULL, NULL }, |
| /*58*/{ "en_US@=;cal...endar=gregorian", "calendar", NULL, NULL }, |
| /*59*/{ "en_US@=;calendar=greg...orian", "calendar", NULL, NULL }, |
| /*60*/{ "en_US@calendar=gregorian", "cale ndar", NULL, NULL }, |
| }; |
| |
| |
| static void TestKeywordSet(void) |
| { |
| int32_t i = 0; |
| int32_t resultLen = 0; |
| char buffer[1024]; |
| |
| char cbuffer[1024]; |
| |
| for(i = 0; i < UPRV_LENGTHOF(kwSetTestCases); i++) { |
| UErrorCode status = U_ZERO_ERROR; |
| memset(buffer,'%',1023); |
| strcpy(buffer, kwSetTestCases[i].l); |
| |
| if (kwSetTestCases[i].x != NULL) { |
| uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status); |
| if(strcmp(buffer,cbuffer)) { |
| log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer); |
| } |
| /* sanity check test case results for canonicity */ |
| uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status); |
| if(strcmp(kwSetTestCases[i].x,cbuffer)) { |
| log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer); |
| } |
| |
| status = U_ZERO_ERROR; |
| resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status); |
| if(U_FAILURE(status)) { |
| log_err("Err on test case %d for setKeywordValue: got error %s\n", i, u_errorName(status)); |
| } else if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) { |
| log_err("FAIL: #%d setKeywordValue: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, |
| kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer)); |
| } else { |
| log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer); |
| } |
| |
| if (kwSetTestCases[i].v != NULL && kwSetTestCases[i].v[0] != 0) { |
| status = U_ZERO_ERROR; |
| resultLen = uloc_getKeywordValue(kwSetTestCases[i].x, kwSetTestCases[i].k, buffer, 1023, &status); |
| if(U_FAILURE(status)) { |
| log_err("Err on test case %d for getKeywordValue: got error %s\n", i, u_errorName(status)); |
| } else if (resultLen != (int32_t)uprv_strlen(kwSetTestCases[i].v) || uprv_strcmp(buffer, kwSetTestCases[i].v) != 0) { |
| log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i, buffer, resultLen, |
| kwSetTestCases[i].v, uprv_strlen(kwSetTestCases[i].v)); |
| } |
| } |
| } else { |
| /* test cases expected to result in error */ |
| status = U_ZERO_ERROR; |
| resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status); |
| if(U_SUCCESS(status)) { |
| log_err("Err on test case %d for setKeywordValue: expected to fail but succeeded, got %s (%d)\n", i, buffer, resultLen); |
| } |
| |
| if (kwSetTestCases[i].v == NULL) { |
| status = U_ZERO_ERROR; |
| strcpy(cbuffer, kwSetTestCases[i].l); |
| resultLen = uloc_getKeywordValue(cbuffer, kwSetTestCases[i].k, buffer, 1023, &status); |
| if(U_SUCCESS(status)) { |
| log_err("Err on test case %d for getKeywordValue: expected to fail but succeeded\n", i); |
| } |
| } |
| } |
| } |
| } |
| |
| static void TestKeywordSetError(void) |
| { |
| char buffer[1024]; |
| UErrorCode status; |
| int32_t res; |
| int32_t i; |
| int32_t blen; |
| |
| /* 0-test whether an error condition modifies the buffer at all */ |
| blen=0; |
| i=0; |
| memset(buffer,'%',1023); |
| status = U_ZERO_ERROR; |
| res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); |
| if(status != U_ILLEGAL_ARGUMENT_ERROR) { |
| log_err("expected illegal err got %s\n", u_errorName(status)); |
| return; |
| } |
| /* if(res!=strlen(kwSetTestCases[i].x)) { |
| log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); |
| return; |
| } */ |
| if(buffer[blen]!='%') { |
| log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); |
| return; |
| } |
| log_verbose("0-buffer modify OK\n"); |
| |
| for(i=0;i<=2;i++) { |
| /* 1- test a short buffer with growing text */ |
| blen=(int32_t)strlen(kwSetTestCases[i].l)+1; |
| memset(buffer,'%',1023); |
| strcpy(buffer,kwSetTestCases[i].l); |
| status = U_ZERO_ERROR; |
| res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); |
| if(status != U_BUFFER_OVERFLOW_ERROR) { |
| 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); |
| return; |
| } |
| if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { |
| log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); |
| return; |
| } |
| if(buffer[blen]!='%') { |
| log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); |
| return; |
| } |
| log_verbose("1/%d-buffer modify OK\n",i); |
| } |
| |
| for(i=3;i<=4;i++) { |
| /* 2- test a short buffer - text the same size or shrinking */ |
| blen=(int32_t)strlen(kwSetTestCases[i].l)+1; |
| memset(buffer,'%',1023); |
| strcpy(buffer,kwSetTestCases[i].l); |
| status = U_ZERO_ERROR; |
| res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); |
| if(status != U_ZERO_ERROR) { |
| log_err("expected zero error got %s\n", u_errorName(status)); |
| return; |
| } |
| if(buffer[blen+1]!='%') { |
| log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]); |
| return; |
| } |
| if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { |
| log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); |
| return; |
| } |
| if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) { |
| log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, |
| kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer)); |
| } else { |
| log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v, |
| buffer); |
| } |
| log_verbose("2/%d-buffer modify OK\n",i); |
| } |
| } |
| |
| static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */ |
| const char* localeID, |
| char* result, |
| int32_t resultCapacity, |
| UErrorCode* ec) { |
| /* YOU can change this to use function pointers if you like */ |
| switch (selector) { |
| case 0: |
| return uloc_getName(localeID, result, resultCapacity, ec); |
| case 1: |
| return uloc_canonicalize(localeID, result, resultCapacity, ec); |
| default: |
| return -1; |
| } |
| } |
| |
| static void TestCanonicalization(void) |
| { |
| static const struct { |
| const char *localeID; /* input */ |
| const char *getNameID; /* expected getName() result */ |
| const char *canonicalID; /* expected canonicalize() result */ |
| } testCases[] = { |
| { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage", |
| "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE", |
| "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"}, |
| { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" }, |
| { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" }, |
| { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" }, |
| { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" }, |
| { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" }, |
| { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ }, |
| { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */ |
| { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */ |
| { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */ |
| { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */ |
| { "de-1901", "de__1901", "de__1901" }, /* registered name */ |
| { "de-1906", "de__1906", "de__1906" }, /* registered name */ |
| |
| /* posix behavior that used to be performed by getName */ |
| { "mr.utf8", "mr.utf8", "mr" }, |
| { "de-tv.koi8r", "de_TV.koi8r", "de_TV" }, |
| { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" }, |
| { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" }, |
| { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" }, |
| { "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 */ |
| |
| /* fleshing out canonicalization */ |
| /* trim space and sort keywords, ';' is separator so not present at end in canonical form */ |
| { "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" }, |
| /* already-canonical ids are not changed */ |
| { "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" }, |
| /* norwegian is just too weird, if we handle things in their full generality */ |
| { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ }, |
| |
| /* test cases reflecting internal resource bundle usage */ |
| { "root@kw=foo", "root@kw=foo", "root@kw=foo" }, |
| { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" }, |
| { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }, |
| { "ja_JP", "ja_JP", "ja_JP" }, |
| |
| /* test case for "i-default" */ |
| { "i-default", "en@x=i-default", "en@x=i-default" }, |
| |
| // Before ICU 64, ICU locale canonicalization had some additional mappings. |
| // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants". |
| // The following now use standard canonicalization. |
| { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" }, |
| { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" }, |
| { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" }, |
| { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" }, |
| { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" }, |
| { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" }, |
| { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" }, |
| { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" }, |
| { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" }, |
| { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" }, |
| { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" }, |
| { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" }, |
| { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" }, |
| { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" }, |
| { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" }, |
| { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" }, |
| { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" }, |
| { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" }, |
| { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" }, |
| { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" }, |
| { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" }, |
| { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */ |
| { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" }, |
| { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" }, |
| { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" }, |
| { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" }, |
| { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" }, |
| { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" }, |
| { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN_STROKE" }, |
| { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */ |
| { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */ |
| { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */ |
| { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */ |
| { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */ |
| { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */ |
| { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */ |
| /* PRE_EURO and EURO conversions don't affect other keywords */ |
| { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" }, |
| { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" }, |
| /* currency keyword overrides PRE_EURO and EURO currency */ |
| { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" }, |
| { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" }, |
| }; |
| |
| static const char* label[] = { "getName", "canonicalize" }; |
| |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t i, j, resultLen = 0, origResultLen; |
| char buffer[256]; |
| |
| for (i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| for (j=0; j<2; ++j) { |
| const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID; |
| *buffer = 0; |
| status = U_ZERO_ERROR; |
| |
| if (expected == NULL) { |
| expected = uloc_getDefault(); |
| } |
| |
| /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */ |
| origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status); |
| if (status != U_BUFFER_OVERFLOW_ERROR) { |
| log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n", |
| label[j], testCases[i].localeID, u_errorName(status)); |
| continue; |
| } |
| status = U_ZERO_ERROR; |
| resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status); |
| if (U_FAILURE(status)) { |
| log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n", |
| label[j], testCases[i].localeID, u_errorName(status)); |
| continue; |
| } |
| if(uprv_strcmp(expected, buffer) != 0) { |
| log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n", |
| label[j], testCases[i].localeID, buffer, expected); |
| } else { |
| log_verbose("Ok: uloc_%s(%s) => \"%s\"\n", |
| label[j], testCases[i].localeID, buffer); |
| } |
| if (resultLen != (int32_t)strlen(buffer)) { |
| log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n", |
| label[j], testCases[i].localeID, resultLen, strlen(buffer)); |
| } |
| if (origResultLen != resultLen) { |
| log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n", |
| label[j], testCases[i].localeID, origResultLen, resultLen); |
| } |
| } |
| } |
| } |
| |
| static void TestCanonicalizationBuffer(void) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| char buffer[256]; |
| |
| // ULOC_FULLNAME_CAPACITY == 157 (uloc.h) |
| static const char name[] = |
| "zh@x" |
| "=foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| "-foo-barz" |
| ; |
| static const size_t len = sizeof(name) - 1; // Without NUL terminator. |
| |
| int32_t reslen = uloc_canonicalize(name, buffer, (int32_t)len, &status); |
| |
| if (U_FAILURE(status)) { |
| log_err("FAIL: uloc_canonicalize(%s) => %s, expected !U_FAILURE()\n", |
| name, u_errorName(status)); |
| return; |
| } |
| |
| if (reslen != len) { |
| log_err("FAIL: uloc_canonicalize(%s) => \"%i\", expected \"%u\"\n", |
| name, reslen, len); |
| return; |
| } |
| |
| if (uprv_strncmp(name, buffer, len) != 0) { |
| log_err("FAIL: uloc_canonicalize(%s) => \"%.*s\", expected \"%s\"\n", |
| name, reslen, buffer, name); |
| return; |
| } |
| } |
| |
| static void TestCanonicalization21749StackUseAfterScope(void) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| char buffer[256]; |
| const char* input = "- _"; |
| uloc_canonicalize(input, buffer, -1, &status); |
| if (U_SUCCESS(status)) { |
| log_err("FAIL: uloc_canonicalize(%s) => %s, expected U_FAILURE()\n", |
| input, u_errorName(status)); |
| return; |
| } |
| } |
| |
| static void TestDisplayKeywords(void) |
| { |
| int32_t i; |
| |
| static const struct { |
| const char *localeID; |
| const char *displayLocale; |
| UChar displayKeyword[200]; |
| } testCases[] = { |
| { "ca_ES@currency=ESP", "de_AT", |
| {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}, |
| }, |
| { "ja_JP@calendar=japanese", "de", |
| { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} |
| }, |
| { "de_DE@collation=traditional", "de_DE", |
| {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000} |
| }, |
| }; |
| for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| UErrorCode status = U_ZERO_ERROR; |
| const char* keyword =NULL; |
| int32_t keywordLen = 0; |
| int32_t keywordCount = 0; |
| UChar *displayKeyword=NULL; |
| int32_t displayKeywordLen = 0; |
| UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); |
| for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ |
| if(U_FAILURE(status)){ |
| log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status)); |
| break; |
| } |
| /* the uenum_next returns NUL terminated string */ |
| keyword = uenum_next(keywordEnum, &keywordLen, &status); |
| /* fetch the displayKeyword */ |
| displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status = U_ZERO_ERROR; |
| displayKeywordLen++; /* for null termination */ |
| displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR); |
| displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); |
| if(U_FAILURE(status)){ |
| 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)); |
| free(displayKeyword); |
| break; |
| } |
| if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){ |
| if (status == U_USING_DEFAULT_WARNING) { |
| 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)); |
| } else { |
| 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); |
| } |
| free(displayKeyword); |
| break; |
| } |
| }else{ |
| log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status)); |
| } |
| |
| free(displayKeyword); |
| |
| } |
| uenum_close(keywordEnum); |
| } |
| } |
| |
| static void TestDisplayKeywordValues(void){ |
| int32_t i; |
| |
| static const struct { |
| const char *localeID; |
| const char *displayLocale; |
| UChar displayKeywordValue[500]; |
| } testCases[] = { |
| { "ca_ES@currency=ESP", "de_AT", |
| {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000} |
| }, |
| { "de_AT@currency=ATS", "fr_FR", |
| {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000} |
| }, |
| { "de_DE@currency=DEM", "it", |
| {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000} |
| }, |
| { "el_GR@currency=GRD", "en", |
| {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000} |
| }, |
| { "eu_ES@currency=ESP", "it_IT", |
| {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000} |
| }, |
| { "de@collation=phonebook", "es", |
| {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} |
| }, |
| |
| { "de_DE@collation=phonebook", "es", |
| {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} |
| }, |
| { "es_ES@collation=traditional","de", |
| {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} |
| }, |
| { "ja_JP@calendar=japanese", "de", |
| {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} |
| }, |
| }; |
| for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| UErrorCode status = U_ZERO_ERROR; |
| const char* keyword =NULL; |
| int32_t keywordLen = 0; |
| int32_t keywordCount = 0; |
| UChar *displayKeywordValue = NULL; |
| int32_t displayKeywordValueLen = 0; |
| UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); |
| for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ |
| if(U_FAILURE(status)){ |
| 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)); |
| break; |
| } |
| /* the uenum_next returns NUL terminated string */ |
| keyword = uenum_next(keywordEnum, &keywordLen, &status); |
| |
| /* fetch the displayKeywordValue */ |
| displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status = U_ZERO_ERROR; |
| displayKeywordValueLen++; /* for null termination */ |
| displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); |
| displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); |
| if(U_FAILURE(status)){ |
| 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)); |
| free(displayKeywordValue); |
| break; |
| } |
| if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){ |
| if (status == U_USING_DEFAULT_WARNING) { |
| 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)); |
| } else { |
| 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)); |
| } |
| free(displayKeywordValue); |
| break; |
| } |
| }else{ |
| log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); |
| } |
| free(displayKeywordValue); |
| } |
| uenum_close(keywordEnum); |
| } |
| { |
| /* test a multiple keywords */ |
| UErrorCode status = U_ZERO_ERROR; |
| const char* keyword =NULL; |
| int32_t keywordLen = 0; |
| int32_t keywordCount = 0; |
| const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM"; |
| const char* displayLocale = "de"; |
| static const UChar expected[][50] = { |
| {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}, |
| |
| {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}, |
| {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000}, |
| }; |
| |
| UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status); |
| |
| for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){ |
| UChar *displayKeywordValue = NULL; |
| int32_t displayKeywordValueLen = 0; |
| if(U_FAILURE(status)){ |
| log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status)); |
| break; |
| } |
| /* the uenum_next returns NUL terminated string */ |
| keyword = uenum_next(keywordEnum, &keywordLen, &status); |
| |
| /* fetch the displayKeywordValue */ |
| displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); |
| if(status==U_BUFFER_OVERFLOW_ERROR){ |
| status = U_ZERO_ERROR; |
| displayKeywordValueLen++; /* for null termination */ |
| displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); |
| displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); |
| if(U_FAILURE(status)){ |
| 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)); |
| free(displayKeywordValue); |
| break; |
| } |
| if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){ |
| if (status == U_USING_DEFAULT_WARNING) { |
| 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)); |
| } else { |
| log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale); |
| } |
| free(displayKeywordValue); |
| break; |
| } |
| }else{ |
| log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); |
| } |
| free(displayKeywordValue); |
| } |
| uenum_close(keywordEnum); |
| |
| } |
| { |
| /* Test non existent keywords */ |
| UErrorCode status = U_ZERO_ERROR; |
| const char* localeID = "es"; |
| const char* displayLocale = "de"; |
| UChar *displayKeywordValue = NULL; |
| int32_t displayKeywordValueLen = 0; |
| |
| /* fetch the displayKeywordValue */ |
| displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status); |
| if(U_FAILURE(status)) { |
| log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status)); |
| } else if(displayKeywordValueLen != 0) { |
| log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen); |
| } |
| } |
| } |
| |
| |
| static void TestGetBaseName(void) { |
| static const struct { |
| const char *localeID; |
| const char *baseName; |
| } testCases[] = { |
| { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" }, |
| { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" }, |
| { "ja@calendar = buddhist", "ja" } |
| }; |
| |
| int32_t i = 0, baseNameLen = 0; |
| char baseName[256]; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status); |
| (void)baseNameLen; /* Suppress set but not used warning. */ |
| if(strcmp(testCases[i].baseName, baseName)) { |
| log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n", |
| testCases[i].localeID, testCases[i].baseName, baseName); |
| return; |
| } |
| } |
| } |
| |
| static void TestTrailingNull(void) { |
| const char* localeId = "zh_Hans"; |
| UChar buffer[128]; /* sufficient for this test */ |
| int32_t len; |
| UErrorCode status = U_ZERO_ERROR; |
| int i; |
| |
| len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status); |
| if (len > 128) { |
| log_err("buffer too small"); |
| return; |
| } |
| |
| for (i = 0; i < len; ++i) { |
| if (buffer[i] == 0) { |
| log_err("name contained null"); |
| return; |
| } |
| } |
| } |
| |
| /* Jitterbug 4115 */ |
| static void TestDisplayNameWarning(void) { |
| UChar name[256]; |
| int32_t size; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| size = uloc_getDisplayLanguage("qqq", "kl", name, UPRV_LENGTHOF(name), &status); |
| (void)size; /* Suppress set but not used warning. */ |
| if (status != U_USING_DEFAULT_WARNING) { |
| log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n", |
| u_errorName(status)); |
| } |
| } |
| |
| |
| /** |
| * Compare two locale IDs. If they are equal, return 0. If `string' |
| * starts with `prefix' plus an additional element, that is, string == |
| * prefix + '_' + x, then return 1. Otherwise return a value < 0. |
| */ |
| static UBool _loccmp(const char* string, const char* prefix) { |
| int32_t slen = (int32_t)uprv_strlen(string), |
| plen = (int32_t)uprv_strlen(prefix); |
| int32_t c = uprv_strncmp(string, prefix, plen); |
| /* 'root' is less than everything */ |
| if (uprv_strcmp(prefix, "root") == 0) { |
| return (uprv_strcmp(string, "root") == 0) ? 0 : 1; |
| } |
| if (c) return -1; /* mismatch */ |
| if (slen == plen) return 0; |
| if (string[plen] == '_') return 1; |
| return -2; /* false match, e.g. "en_USX" cmp "en_US" */ |
| } |
| |
| static void _checklocs(const char* label, |
| const char* req, |
| const char* valid, |
| const char* actual) { |
| /* We want the valid to be strictly > the bogus requested locale, |
| and the valid to be >= the actual. */ |
| if (_loccmp(req, valid) > 0 && |
| _loccmp(valid, actual) >= 0) { |
| log_verbose("%s; req=%s, valid=%s, actual=%s\n", |
| label, req, valid, actual); |
| } else { |
| log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n", |
| label, req, valid, actual); |
| } |
| } |
| |
| static void TestGetLocale(void) { |
| UErrorCode ec = U_ZERO_ERROR; |
| UParseError pe; |
| UChar EMPTY[1] = {0}; |
| |
| /* === udat === */ |
| #if !UCONFIG_NO_FORMATTING |
| { |
| UDateFormat *obj; |
| const char *req = "en_US_REDWOODSHORES", *valid, *actual; |
| obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, |
| req, |
| NULL, 0, |
| NULL, 0, &ec); |
| if (U_FAILURE(ec)) { |
| log_data_err("udat_open failed.Error %s\n", u_errorName(ec)); |
| return; |
| } |
| valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("udat_getLocaleByType() failed\n"); |
| return; |
| } |
| _checklocs("udat", req, valid, actual); |
| udat_close(obj); |
| } |
| #endif |
| |
| /* === ucal === */ |
| #if !UCONFIG_NO_FORMATTING |
| { |
| UCalendar *obj; |
| const char *req = "fr_FR_PROVENCAL", *valid, *actual; |
| obj = ucal_open(NULL, 0, |
| req, |
| UCAL_GREGORIAN, |
| &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ucal_open failed with error: %s\n", u_errorName(ec)); |
| return; |
| } |
| valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ucal_getLocaleByType() failed\n"); |
| return; |
| } |
| _checklocs("ucal", req, valid, actual); |
| ucal_close(obj); |
| } |
| #endif |
| |
| /* === unum === */ |
| #if !UCONFIG_NO_FORMATTING |
| { |
| UNumberFormat *obj; |
| const char *req = "zh_Hant_TW_TAINAN", *valid, *actual; |
| obj = unum_open(UNUM_DECIMAL, |
| NULL, 0, |
| req, |
| &pe, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("unum_open failed\n"); |
| return; |
| } |
| valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("unum_getLocaleByType() failed\n"); |
| return; |
| } |
| _checklocs("unum", req, valid, actual); |
| unum_close(obj); |
| } |
| #endif |
| |
| /* === umsg === */ |
| #if 0 |
| /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */ |
| #if !UCONFIG_NO_FORMATTING |
| { |
| UMessageFormat *obj; |
| const char *req = "ja_JP_TAKAYAMA", *valid, *actual; |
| UBool test; |
| obj = umsg_open(EMPTY, 0, |
| req, |
| &pe, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("umsg_open failed\n"); |
| return; |
| } |
| valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("umsg_getLocaleByType() failed\n"); |
| return; |
| } |
| /* We want the valid to be strictly > the bogus requested locale, |
| and the valid to be >= the actual. */ |
| /* TODO MessageFormat is currently just storing the locale it is given. |
| As a result, it will return whatever it was given, even if the |
| locale is invalid. */ |
| test = (_cmpversion("3.2") <= 0) ? |
| /* Here is the weakened test for 3.0: */ |
| (_loccmp(req, valid) >= 0) : |
| /* Here is what the test line SHOULD be: */ |
| (_loccmp(req, valid) > 0); |
| |
| if (test && |
| _loccmp(valid, actual) >= 0) { |
| log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); |
| } else { |
| log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); |
| } |
| umsg_close(obj); |
| } |
| #endif |
| #endif |
| |
| /* === ubrk === */ |
| #if !UCONFIG_NO_BREAK_ITERATION |
| { |
| UBreakIterator *obj; |
| const char *req = "ar_KW_ABDALI", *valid, *actual; |
| obj = ubrk_open(UBRK_WORD, |
| req, |
| EMPTY, |
| 0, |
| &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ubrk_open failed. Error: %s \n", u_errorName(ec)); |
| return; |
| } |
| valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ubrk_getLocaleByType() failed\n"); |
| return; |
| } |
| _checklocs("ubrk", req, valid, actual); |
| ubrk_close(obj); |
| } |
| #endif |
| |
| /* === ucol === */ |
| #if !UCONFIG_NO_COLLATION |
| { |
| UCollator *obj; |
| const char *req = "es_AR_BUENOSAIRES", *valid, *actual; |
| obj = ucol_open(req, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ucol_open failed - %s\n", u_errorName(ec)); |
| return; |
| } |
| valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); |
| actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); |
| if (U_FAILURE(ec)) { |
| log_err("ucol_getLocaleByType() failed\n"); |
| return; |
| } |
| _checklocs("ucol", req, valid, actual); |
| ucol_close(obj); |
| } |
| #endif |
| } |
| static void TestEnglishExemplarCharacters(void) { |
| UErrorCode status = U_ZERO_ERROR; |
| int i; |
| USet *exSet = NULL; |
| UChar testChars[] = { |
| 0x61, /* standard */ |
| 0xE1, /* auxiliary */ |
| 0x41, /* index */ |
| 0x2D /* punctuation */ |
| }; |
| ULocaleData *uld = ulocdata_open("en", &status); |
| if (U_FAILURE(status)) { |
| log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status)); |
| return; |
| } |
| |
| for (i = 0; i < ULOCDATA_ES_COUNT; i++) { |
| exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status); |
| if (U_FAILURE(status)) { |
| log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i); |
| status = U_ZERO_ERROR; |
| continue; |
| } |
| if (!uset_contains(exSet, (UChar32)testChars[i])) { |
| log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i); |
| } |
| } |
| |
| uset_close(exSet); |
| ulocdata_close(uld); |
| } |
| |
| static void TestNonexistentLanguageExemplars(void) { |
| /* JB 4068 - Nonexistent language */ |
| UErrorCode ec = U_ZERO_ERROR; |
| ULocaleData *uld = ulocdata_open("qqq",&ec); |
| if (ec != U_USING_DEFAULT_WARNING) { |
| log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n", |
| u_errorName(ec)); |
| } |
| uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); |
| ulocdata_close(uld); |
| } |
| |
| static void TestLocDataErrorCodeChaining(void) { |
| UErrorCode ec = U_USELESS_COLLATOR_ERROR; |
| ulocdata_open(NULL, &ec); |
| ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec); |
| ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec); |
| ulocdata_getMeasurementSystem(NULL, &ec); |
| ulocdata_getPaperSize(NULL, NULL, NULL, &ec); |
| if (ec != U_USELESS_COLLATOR_ERROR) { |
| log_err("ulocdata API changed the error code to %s\n", u_errorName(ec)); |
| } |
| } |
| |
| typedef struct { |
| const char* locale; |
| UMeasurementSystem measureSys; |
| } LocToMeasureSys; |
| |
| static const LocToMeasureSys locToMeasures[] = { |
| { "fr_FR", UMS_SI }, |
| { "en", UMS_US }, |
| { "en_GB", UMS_UK }, |
| { "fr_FR@rg=GBZZZZ", UMS_UK }, |
| { "en@rg=frzzzz", UMS_SI }, |
| { "en_GB@rg=USZZZZ", UMS_US }, |
| { NULL, (UMeasurementSystem)0 } /* terminator */ |
| }; |
| |
| static void TestLocDataWithRgTag(void) { |
| const LocToMeasureSys* locToMeasurePtr = locToMeasures; |
| for (; locToMeasurePtr->locale != NULL; locToMeasurePtr++) { |
| UErrorCode status = U_ZERO_ERROR; |
| UMeasurementSystem measureSys = ulocdata_getMeasurementSystem(locToMeasurePtr->locale, &status); |
| if (U_FAILURE(status)) { |
| log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n", |
| locToMeasurePtr->locale, u_errorName(status)); |
| } else if (measureSys != locToMeasurePtr->measureSys) { |
| log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n", |
| locToMeasurePtr->locale, (int) locToMeasurePtr->measureSys, (int)measureSys); |
| } |
| } |
| } |
| |
| static void TestLanguageExemplarsFallbacks(void) { |
| /* Test that en_US fallsback, but en doesn't fallback. */ |
| UErrorCode ec = U_ZERO_ERROR; |
| ULocaleData *uld = ulocdata_open("en_US",&ec); |
| uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); |
| if (ec != U_USING_FALLBACK_WARNING) { |
| log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n", |
| u_errorName(ec)); |
| } |
| ulocdata_close(uld); |
| ec = U_ZERO_ERROR; |
| uld = ulocdata_open("en",&ec); |
| uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); |
| if (ec != U_ZERO_ERROR) { |
| log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n", |
| u_errorName(ec)); |
| } |
| ulocdata_close(uld); |
| } |
| |
| static const char *acceptResult(UAcceptResult uar) { |
| return udbg_enumName(UDBG_UAcceptResult, uar); |
| } |
| |
| static void TestAcceptLanguage(void) { |
| UErrorCode status = U_ZERO_ERROR; |
| UAcceptResult outResult; |
| UEnumeration *available; |
| char tmp[200]; |
| int i; |
| int32_t rc = 0; |
| |
| struct { |
| int32_t httpSet; /**< Which of http[] should be used? */ |
| const char *icuSet; /**< ? */ |
| const char *expect; /**< The expected locale result */ |
| UAcceptResult res; /**< The expected error code */ |
| UErrorCode expectStatus; /**< expected status */ |
| } tests[] = { |
| /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, |
| /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, |
| /*2*/{ 2, NULL, "en_GB", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, |
| /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR}, |
| /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, |
| /*5*/{ 5, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */ |
| /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */ |
| /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */ |
| /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR }, /* */ |
| /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR }, /* */ |
| /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR }, /* */ |
| /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_ILLEGAL_ARGUMENT_ERROR }, /* */ |
| }; |
| const int32_t numTests = UPRV_LENGTHOF(tests); |
| static const char *http[] = { |
| /*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=0.01", |
| /*1*/ "ja;q=0.5, en;q=0.8, tlh", |
| /*2*/ "en-wf, de-lx;q=0.8", |
| /*3*/ "mga-ie;q=0.9, sux", |
| /*4*/ "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, " |
| "xxx-yyy;q=0.01, xxx-yyy;q=0.01, xxx-yyy;q=0.01, xx-yy;q=0.1, " |
| "es", |
| /*5*/ "zh-xx;q=0.9, en;q=0.6", |
| /*6*/ "ja-JA", |
| /*7*/ "zh-xx;q=0.9", |
| /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156 |
| /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING ) |
| /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158 |
| /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
| "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes |
| }; |
| |
| for(i=0;i<numTests;i++) { |
| outResult = -3; |
| status=U_ZERO_ERROR; |
| log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n", |
| i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); |
| |
| available = ures_openAvailableLocales(tests[i].icuSet, &status); |
| tmp[0]=0; |
| rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, |
| http[tests[i].httpSet], available, &status); |
| (void)rc; /* Suppress set but not used warning. */ |
| uenum_close(available); |
| log_verbose(" got %s, %s [%s]\n", |
| tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status)); |
| if(status != tests[i].expectStatus) { |
| log_err_status(status, |
| "FAIL: expected status %s but got %s\n", |
| u_errorName(tests[i].expectStatus), |
| u_errorName(status)); |
| } else if(U_SUCCESS(tests[i].expectStatus)) { |
| /* don't check content if expected failure */ |
| if(outResult != tests[i].res) { |
| log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i, |
| acceptResult( tests[i].res), |
| acceptResult( outResult)); |
| log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", |
| i, http[tests[i].httpSet], tests[i].icuSet, |
| tests[i].expect,acceptResult(tests[i].res)); |
| } |
| if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { |
| log_err_status(status, |
| "FAIL: #%d: expected %s but got %s\n", |
| i, tests[i].expect, tmp); |
| log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", |
| i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); |
| } |
| } |
| } |
| |
| // API coverage |
| status = U_ZERO_ERROR; |
| static const char *const supported[] = { "en-US", "en-GB", "de-DE", "ja-JP" }; |
| const char * desired[] = { "de-LI", "en-IN", "zu", "fr" }; |
| available = uenum_openCharStringsEnumeration(supported, UPRV_LENGTHOF(supported), &status); |
| tmp[0]=0; |
| rc = uloc_acceptLanguage(tmp, 199, &outResult, desired, UPRV_LENGTHOF(desired), available, &status); |
| if (U_FAILURE(status) || rc != 5 || uprv_strcmp(tmp, "de_DE") != 0 || outResult == ULOC_ACCEPT_FAILED) { |
| log_err("uloc_acceptLanguage() failed to do a simple match\n"); |
| } |
| uenum_close(available); |
| } |
| |
| static const char* LOCALE_ALIAS[][2] = { |
| {"in", "id"}, |
| {"in_ID", "id_ID"}, |
| {"iw", "he"}, |
| {"iw_IL", "he_IL"}, |
| {"ji", "yi"}, |
| {"en_BU", "en_MM"}, |
| {"en_DY", "en_BJ"}, |
| {"en_HV", "en_BF"}, |
| {"en_NH", "en_VU"}, |
| {"en_RH", "en_ZW"}, |
| {"en_TP", "en_TL"}, |
| {"en_ZR", "en_CD"} |
| }; |
| static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){ |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t len = 0; |
| ures_getStringByKey(resIndex, loc,&len, &status); |
| if(U_FAILURE(status)){ |
| return FALSE; |
| } |
| return TRUE; |
| } |
| |
| static void TestCalendar() { |
| #if !UCONFIG_NO_FORMATTING |
| int i; |
| UErrorCode status = U_ZERO_ERROR; |
| UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); |
| if(U_FAILURE(status)){ |
| log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); |
| return; |
| } |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| UCalendar* c1 = NULL; |
| UCalendar* c2 = NULL; |
| |
| /*Test function "getLocale(ULocale.VALID_LOCALE)"*/ |
| const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); |
| const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); |
| |
| if(!isLocaleAvailable(resIndex, newLoc)){ |
| continue; |
| } |
| c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status); |
| c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status); |
| |
| if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) { |
| log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); |
| } |
| log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2); |
| ucal_close(c1); |
| ucal_close(c2); |
| } |
| ures_close(resIndex); |
| #endif |
| } |
| |
| static void TestDateFormat() { |
| #if !UCONFIG_NO_FORMATTING |
| int i; |
| UErrorCode status = U_ZERO_ERROR; |
| UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); |
| if(U_FAILURE(status)){ |
| log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); |
| return; |
| } |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| UDateFormat* df1 = NULL; |
| UDateFormat* df2 = NULL; |
| const char* l1 = NULL; |
| const char* l2 = NULL; |
| |
| if(!isLocaleAvailable(resIndex, newLoc)){ |
| continue; |
| } |
| df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status); |
| df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status); |
| if(U_FAILURE(status)){ |
| log_err("Creation of date format failed %s\n", u_errorName(status)); |
| return; |
| } |
| /*Test function "getLocale"*/ |
| l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status); |
| l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status); |
| if(U_FAILURE(status)){ |
| log_err("Fetching the locale by type failed. %s\n", u_errorName(status)); |
| } |
| if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { |
| log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); |
| } |
| log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2); |
| udat_close(df1); |
| udat_close(df2); |
| } |
| ures_close(resIndex); |
| #endif |
| } |
| |
| static void TestCollation() { |
| #if !UCONFIG_NO_COLLATION |
| int i; |
| UErrorCode status = U_ZERO_ERROR; |
| UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); |
| if(U_FAILURE(status)){ |
| log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); |
| return; |
| } |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| UCollator* c1 = NULL; |
| UCollator* c2 = NULL; |
| const char* l1 = NULL; |
| const char* l2 = NULL; |
| |
| status = U_ZERO_ERROR; |
| if(!isLocaleAvailable(resIndex, newLoc)){ |
| continue; |
| } |
| if(U_FAILURE(status)){ |
| log_err("Creation of collators failed %s\n", u_errorName(status)); |
| return; |
| } |
| c1 = ucol_open(oldLoc, &status); |
| c2 = ucol_open(newLoc, &status); |
| l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); |
| l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); |
| if(U_FAILURE(status)){ |
| log_err("Fetching the locale names failed failed %s\n", u_errorName(status)); |
| } |
| if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { |
| log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); |
| } |
| log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2); |
| ucol_close(c1); |
| ucol_close(c2); |
| } |
| ures_close(resIndex); |
| #endif |
| } |
| |
| typedef struct OrientationStructTag { |
| const char* localeId; |
| ULayoutType character; |
| ULayoutType line; |
| } OrientationStruct; |
| |
| static const char* ULayoutTypeToString(ULayoutType type) |
| { |
| switch(type) |
| { |
| case ULOC_LAYOUT_LTR: |
| return "ULOC_LAYOUT_LTR"; |
| break; |
| case ULOC_LAYOUT_RTL: |
| return "ULOC_LAYOUT_RTL"; |
| break; |
| case ULOC_LAYOUT_TTB: |
| return "ULOC_LAYOUT_TTB"; |
| break; |
| case ULOC_LAYOUT_BTT: |
| return "ULOC_LAYOUT_BTT"; |
| break; |
| case ULOC_LAYOUT_UNKNOWN: |
| break; |
| } |
| |
| return "Unknown enum value for ULayoutType!"; |
| } |
| |
| static void TestOrientation() |
| { |
| static const OrientationStruct toTest [] = { |
| { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, |
| { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB } |
| }; |
| |
| size_t i = 0; |
| for (; i < UPRV_LENGTHOF(toTest); ++i) { |
| UErrorCode statusCO = U_ZERO_ERROR; |
| UErrorCode statusLO = U_ZERO_ERROR; |
| const char* const localeId = toTest[i].localeId; |
| const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO); |
| const ULayoutType expectedCO = toTest[i].character; |
| const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO); |
| const ULayoutType expectedLO = toTest[i].line; |
| if (U_FAILURE(statusCO)) { |
| log_err_status(statusCO, |
| " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n", |
| localeId, |
| u_errorName(statusCO)); |
| } |
| else if (co != expectedCO) { |
| log_err( |
| " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n", |
| localeId, |
| ULayoutTypeToString(expectedCO), |
| ULayoutTypeToString(co)); |
| } |
| if (U_FAILURE(statusLO)) { |
| log_err_status(statusLO, |
| " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n", |
| localeId, |
| u_errorName(statusLO)); |
| } |
| else if (lo != expectedLO) { |
| log_err( |
| " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n", |
| localeId, |
| ULayoutTypeToString(expectedLO), |
| ULayoutTypeToString(lo)); |
| } |
| } |
| } |
| |
| static void TestULocale() { |
| int i; |
| UErrorCode status = U_ZERO_ERROR; |
| UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); |
| if(U_FAILURE(status)){ |
| log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); |
| return; |
| } |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| UChar name1[256], name2[256]; |
| char names1[256], names2[256]; |
| int32_t capacity = 256; |
| |
| status = U_ZERO_ERROR; |
| if(!isLocaleAvailable(resIndex, newLoc)){ |
| continue; |
| } |
| uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status); |
| if(U_FAILURE(status)){ |
| log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status)); |
| } |
| |
| uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status); |
| if(U_FAILURE(status)){ |
| log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status)); |
| } |
| |
| if (u_strcmp(name1, name2)!=0) { |
| log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); |
| } |
| u_austrcpy(names1, name1); |
| u_austrcpy(names2, name2); |
| log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2); |
| } |
| ures_close(resIndex); |
| |
| } |
| |
| static void TestUResourceBundle() { |
| const char* us1; |
| const char* us2; |
| |
| UResourceBundle* rb1 = NULL; |
| UResourceBundle* rb2 = NULL; |
| UErrorCode status = U_ZERO_ERROR; |
| int i; |
| UResourceBundle *resIndex = NULL; |
| if(U_FAILURE(status)){ |
| log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); |
| return; |
| } |
| resIndex = ures_open(NULL,"res_index", &status); |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| if(!isLocaleAvailable(resIndex, newLoc)){ |
| continue; |
| } |
| rb1 = ures_open(NULL, oldLoc, &status); |
| if (U_FAILURE(status)) { |
| log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); |
| } |
| |
| us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status); |
| |
| status = U_ZERO_ERROR; |
| rb2 = ures_open(NULL, newLoc, &status); |
| if (U_FAILURE(status)) { |
| log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); |
| } |
| us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status); |
| |
| if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) { |
| log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); |
| } |
| |
| log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2); |
| ures_close(rb1); |
| rb1 = NULL; |
| ures_close(rb2); |
| rb2 = NULL; |
| } |
| ures_close(resIndex); |
| } |
| |
| static void TestDisplayName() { |
| |
| UChar oldCountry[256] = {'\0'}; |
| UChar newCountry[256] = {'\0'}; |
| UChar oldLang[256] = {'\0'}; |
| UChar newLang[256] = {'\0'}; |
| char country[256] ={'\0'}; |
| char language[256] ={'\0'}; |
| int32_t capacity = 256; |
| int i =0; |
| int j=0; |
| for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { |
| const char* oldLoc = LOCALE_ALIAS[i][0]; |
| const char* newLoc = LOCALE_ALIAS[i][1]; |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t available = uloc_countAvailable(); |
| |
| for(j=0; j<available; j++){ |
| |
| const char* dispLoc = uloc_getAvailable(j); |
| int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status); |
| int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status); |
| int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status); |
| int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status ); |
| |
| int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status); |
| int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status); |
| /* there is a display name for the current country ID */ |
| if(countryLen != newCountryLen ){ |
| if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){ |
| log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc); |
| } |
| } |
| /* there is a display name for the current lang ID */ |
| if(langLen!=newLangLen){ |
| if(u_strncmp(oldLang,newLang,oldLangLen)){ |
| log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); } |
| } |
| } |
| } |
| } |
| |
| static void TestGetLocaleForLCID() { |
| int32_t i, length, lengthPre; |
| const char* testLocale = 0; |
| UErrorCode status = U_ZERO_ERROR; |
| char temp2[40], temp3[40]; |
| uint32_t lcid; |
| |
| lcid = uloc_getLCID("en_US"); |
| if (lcid != 0x0409) { |
| log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid); |
| } |
| |
| lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status); |
| if (status != U_BUFFER_OVERFLOW_ERROR) { |
| log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status)); |
| } |
| else { |
| status = U_ZERO_ERROR; |
| } |
| |
| length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status); |
| if (U_FAILURE(status)) { |
| log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| |
| if (length != lengthPre) { |
| log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre); |
| } |
| |
| length = uloc_getLocaleForLCID(0x12345, temp2, UPRV_LENGTHOF(temp2), &status); |
| if (U_SUCCESS(status)) { |
| log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status)); |
| } |
| status = U_ZERO_ERROR; |
| |
| log_verbose("Testing getLocaleForLCID vs. locale data\n"); |
| for (i = 0; i < LOCALE_SIZE; i++) { |
| |
| testLocale=rawData2[NAME][i]; |
| |
| log_verbose("Testing %s ......\n", testLocale); |
| |
| sscanf(rawData2[LCID][i], "%x", &lcid); |
| length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status); |
| if (U_FAILURE(status)) { |
| log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| continue; |
| } |
| |
| if (length != (int32_t)uprv_strlen(temp2)) { |
| log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2)); |
| } |
| |
| /* Compare language, country, script */ |
| length = uloc_getLanguage(temp2, temp3, UPRV_LENGTHOF(temp3), &status); |
| if (U_FAILURE(status)) { |
| log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) { |
| log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2); |
| } |
| |
| length = uloc_getScript(temp2, temp3, UPRV_LENGTHOF(temp3), &status); |
| if (U_FAILURE(status)) { |
| log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) { |
| log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2); |
| } |
| |
| length = uloc_getCountry(temp2, temp3, UPRV_LENGTHOF(temp3), &status); |
| if (U_FAILURE(status)) { |
| log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) { |
| log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2); |
| } |
| } |
| |
| } |
| |
| const char* const basic_maximize_data[][2] = { |
| { |
| "zu_Zzzz_Zz", |
| "zu_Latn_ZA", |
| }, { |
| "ZU_Zz", |
| "zu_Latn_ZA" |
| }, { |
| "zu_LATN", |
| "zu_Latn_ZA" |
| }, { |
| "en_Zz", |
| "en_Latn_US" |
| }, { |
| "en_us", |
| "en_Latn_US" |
| }, { |
| "en_Kore", |
| "en_Kore_US" |
| }, { |
| "en_Kore_Zz", |
| "en_Kore_US" |
| }, { |
| "en_Kore_ZA", |
| "en_Kore_ZA" |
| }, { |
| "en_Kore_ZA_POSIX", |
| "en_Kore_ZA_POSIX" |
| }, { |
| "en_Gujr", |
| "en_Gujr_US" |
| }, { |
| "en_ZA", |
| "en_Latn_ZA" |
| }, { |
| "en_Gujr_Zz", |
| "en_Gujr_US" |
| }, { |
| "en_Gujr_ZA", |
| "en_Gujr_ZA" |
| }, { |
| "en_Gujr_ZA_POSIX", |
| "en_Gujr_ZA_POSIX" |
| }, { |
| "en_US_POSIX_1901", |
| "en_Latn_US_POSIX_1901" |
| }, { |
| "en_Latn__POSIX_1901", |
| "en_Latn_US_POSIX_1901" |
| }, { |
| "en__POSIX_1901", |
| "en_Latn_US_POSIX_1901" |
| }, { |
| "de__POSIX_1901", |
| "de_Latn_DE_POSIX_1901" |
| }, { |
| "en_US_BOSTON", |
| "en_Latn_US_BOSTON" |
| }, { |
| "th@calendar=buddhist", |
| "th_Thai_TH@calendar=buddhist" |
| }, { |
| "ar_ZZ", |
| "ar_Arab_EG" |
| }, { |
| "zh", |
| "zh_Hans_CN" |
| }, { |
| "zh_TW", |
| "zh_Hant_TW" |
| }, { |
| "zh_HK", |
| "zh_Hant_HK" |
| }, { |
| "zh_Hant", |
| "zh_Hant_TW" |
| }, { |
| "zh_Zzzz_CN", |
| "zh_Hans_CN" |
| }, { |
| "und_US", |
| "en_Latn_US" |
| }, { |
| "und_HK", |
| "zh_Hant_HK" |
| }, { |
| "zzz", |
| "" |
| }, { |
| "de_u_co_phonebk", |
| "de_Latn_DE@collation=phonebook" |
| }, { |
| "de_Latn_u_co_phonebk", |
| "de_Latn_DE@collation=phonebook" |
| }, { |
| "de_Latn_DE_u_co_phonebk", |
| "de_Latn_DE@collation=phonebook" |
| }, { |
| "_Arab@em=emoji", |
| "ar_Arab_EG@em=emoji" |
| }, { |
| "_Latn@em=emoji", |
| "en_Latn_US@em=emoji" |
| }, { |
| "_Latn_DE@em=emoji", |
| "de_Latn_DE@em=emoji" |
| }, { |
| "_Zzzz_DE@em=emoji", |
| "de_Latn_DE@em=emoji" |
| }, { |
| "_DE@em=emoji", |
| "de_Latn_DE@em=emoji" |
| } |
| }; |
| |
| const char* const basic_minimize_data[][2] = { |
| { |
| "en_Latn_US", |
| "en" |
| }, { |
| "en_Latn_US_POSIX_1901", |
| "en__POSIX_1901" |
| }, { |
| "EN_Latn_US_POSIX_1901", |
| "en__POSIX_1901" |
| }, { |
| "en_Zzzz_US_POSIX_1901", |
| "en__POSIX_1901" |
| }, { |
| "de_Latn_DE_POSIX_1901", |
| "de__POSIX_1901" |
| }, { |
| "zzz", |
| "" |
| }, { |
| "en_Latn_US@calendar=gregorian", |
| "en@calendar=gregorian" |
| } |
| }; |
| |
| const char* const full_data[][3] = { |
| { |
| /* "FROM", */ |
| /* "ADD-LIKELY", */ |
| /* "REMOVE-LIKELY" */ |
| /* }, { */ |
| "aa", |
| "aa_Latn_ET", |
| "aa" |
| }, { |
| "af", |
| "af_Latn_ZA", |
| "af" |
| }, { |
| "ak", |
| "ak_Latn_GH", |
| "ak" |
| }, { |
| "am", |
| "am_Ethi_ET", |
| "am" |
| }, { |
| "ar", |
| "ar_Arab_EG", |
| "ar" |
| }, { |
| "as", |
| "as_Beng_IN", |
| "as" |
| }, { |
| "az", |
| "az_Latn_AZ", |
| "az" |
| }, { |
| "be", |
| "be_Cyrl_BY", |
| "be" |
| }, { |
| "bg", |
| "bg_Cyrl_BG", |
| "bg" |
| }, { |
| "bn", |
| "bn_Beng_BD", |
| "bn" |
| }, { |
| "bo", |
| "bo_Tibt_CN", |
| "bo" |
| }, { |
| "bs", |
| "bs_Latn_BA", |
| "bs" |
| }, { |
| "ca", |
| "ca_Latn_ES", |
| "ca" |
| }, { |
| "ch", |
| "ch_Latn_GU", |
| "ch" |
| }, { |
| "chk", |
| "chk_Latn_FM", |
| "chk" |
| }, { |
| "cs", |
| "cs_Latn_CZ", |
| "cs" |
| }, { |
| "cy", |
| "cy_Latn_GB", |
| "cy" |
| }, { |
| "da", |
| "da_Latn_DK", |
| "da" |
| }, { |
| "de", |
| "de_Latn_DE", |
| "de" |
| }, { |
| "dv", |
| "dv_Thaa_MV", |
| "dv" |
| }, { |
| "dz", |
| "dz_Tibt_BT", |
| "dz" |
| }, { |
| "ee", |
| "ee_Latn_GH", |
| "ee" |
| }, { |
| "el", |
| "el_Grek_GR", |
| "el" |
| }, { |
| "en", |
| "en_Latn_US", |
| "en" |
| }, { |
| "es", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "et", |
| "et_Latn_EE", |
| "et" |
| }, { |
| "eu", |
| "eu_Latn_ES", |
| "eu" |
| }, { |
| "fa", |
| "fa_Arab_IR", |
| "fa" |
| }, { |
| "fi", |
| "fi_Latn_FI", |
| "fi" |
| }, { |
| "fil", |
| "fil_Latn_PH", |
| "fil" |
| }, { |
| "fo", |
| "fo_Latn_FO", |
| "fo" |
| }, { |
| "fr", |
| "fr_Latn_FR", |
| "fr" |
| }, { |
| "fur", |
| "fur_Latn_IT", |
| "fur" |
| }, { |
| "ga", |
| "ga_Latn_IE", |
| "ga" |
| }, { |
| "gaa", |
| "gaa_Latn_GH", |
| "gaa" |
| }, { |
| "gl", |
| "gl_Latn_ES", |
| "gl" |
| }, { |
| "gn", |
| "gn_Latn_PY", |
| "gn" |
| }, { |
| "gu", |
| "gu_Gujr_IN", |
| "gu" |
| }, { |
| "ha", |
| "ha_Latn_NG", |
| "ha" |
| }, { |
| "haw", |
| "haw_Latn_US", |
| "haw" |
| }, { |
| "he", |
| "he_Hebr_IL", |
| "he" |
| }, { |
| "hi", |
| "hi_Deva_IN", |
| "hi" |
| }, { |
| "hr", |
| "hr_Latn_HR", |
| "hr" |
| }, { |
| "ht", |
| "ht_Latn_HT", |
| "ht" |
| }, { |
| "hu", |
| "hu_Latn_HU", |
| "hu" |
| }, { |
| "hy", |
| "hy_Armn_AM", |
| "hy" |
| }, { |
| "id", |
| "id_Latn_ID", |
| "id" |
| }, { |
| "ig", |
| "ig_Latn_NG", |
| "ig" |
| }, { |
| "ii", |
| "ii_Yiii_CN", |
| "ii" |
| }, { |
| "is", |
| "is_Latn_IS", |
| "is" |
| }, { |
| "it", |
| "it_Latn_IT", |
| "it" |
| }, { |
| "ja", |
| "ja_Jpan_JP", |
| "ja" |
| }, { |
| "ka", |
| "ka_Geor_GE", |
| "ka" |
| }, { |
| "kaj", |
| "kaj_Latn_NG", |
| "kaj" |
| }, { |
| "kam", |
| "kam_Latn_KE", |
| "kam" |
| }, { |
| "kk", |
| "kk_Cyrl_KZ", |
| "kk" |
| }, { |
| "kl", |
| "kl_Latn_GL", |
| "kl" |
| }, { |
| "km", |
| "km_Khmr_KH", |
| "km" |
| }, { |
| "kn", |
| "kn_Knda_IN", |
| "kn" |
| }, { |
| "ko", |
| "ko_Kore_KR", |
| "ko" |
| }, { |
| "kok", |
| "kok_Deva_IN", |
| "kok" |
| }, { |
| "kpe", |
| "kpe_Latn_LR", |
| "kpe" |
| }, { |
| "ku", |
| "ku_Latn_TR", |
| "ku" |
| }, { |
| "ky", |
| "ky_Cyrl_KG", |
| "ky" |
| }, { |
| "la", |
| "la_Latn_VA", |
| "la" |
| }, { |
| "ln", |
| "ln_Latn_CD", |
| "ln" |
| }, { |
| "lo", |
| "lo_Laoo_LA", |
| "lo" |
| }, { |
| "lt", |
| "lt_Latn_LT", |
| "lt" |
| }, { |
| "lv", |
| "lv_Latn_LV", |
| "lv" |
| }, { |
| "mg", |
| "mg_Latn_MG", |
| "mg" |
| }, { |
| "mh", |
| "mh_Latn_MH", |
| "mh" |
| }, { |
| "mk", |
| "mk_Cyrl_MK", |
| "mk" |
| }, { |
| "ml", |
| "ml_Mlym_IN", |
| "ml" |
| }, { |
| "mn", |
| "mn_Cyrl_MN", |
| "mn" |
| }, { |
| "mr", |
| "mr_Deva_IN", |
| "mr" |
| }, { |
| "ms", |
| "ms_Latn_MY", |
| "ms" |
| }, { |
| "mt", |
| "mt_Latn_MT", |
| "mt" |
| }, { |
| "my", |
| "my_Mymr_MM", |
| "my" |
| }, { |
| "na", |
| "na_Latn_NR", |
| "na" |
| }, { |
| "ne", |
| "ne_Deva_NP", |
| "ne" |
| }, { |
| "niu", |
| "niu_Latn_NU", |
| "niu" |
| }, { |
| "nl", |
| "nl_Latn_NL", |
| "nl" |
| }, { |
| "nn", |
| "nn_Latn_NO", |
| "nn" |
| }, { |
| "no", |
| "no_Latn_NO", |
| "no" |
| }, { |
| "nr", |
| "nr_Latn_ZA", |
| "nr" |
| }, { |
| "nso", |
| "nso_Latn_ZA", |
| "nso" |
| }, { |
| "ny", |
| "ny_Latn_MW", |
| "ny" |
| }, { |
| "om", |
| "om_Latn_ET", |
| "om" |
| }, { |
| "or", |
| "or_Orya_IN", |
| "or" |
| }, { |
| "pa", |
| "pa_Guru_IN", |
| "pa" |
| }, { |
| "pa_Arab", |
| "pa_Arab_PK", |
| "pa_PK" |
| }, { |
| "pa_PK", |
| "pa_Arab_PK", |
| "pa_PK" |
| }, { |
| "pap", |
| "pap_Latn_AW", |
| "pap" |
| }, { |
| "pau", |
| "pau_Latn_PW", |
| "pau" |
| }, { |
| "pl", |
| "pl_Latn_PL", |
| "pl" |
| }, { |
| "ps", |
| "ps_Arab_AF", |
| "ps" |
| }, { |
| "pt", |
| "pt_Latn_BR", |
| "pt" |
| }, { |
| "rn", |
| "rn_Latn_BI", |
| "rn" |
| }, { |
| "ro", |
| "ro_Latn_RO", |
| "ro" |
| }, { |
| "ru", |
| "ru_Cyrl_RU", |
| "ru" |
| }, { |
| "rw", |
| "rw_Latn_RW", |
| "rw" |
| }, { |
| "sa", |
| "sa_Deva_IN", |
| "sa" |
| }, { |
| "se", |
| "se_Latn_NO", |
| "se" |
| }, { |
| "sg", |
| "sg_Latn_CF", |
| "sg" |
| }, { |
| "si", |
| "si_Sinh_LK", |
| "si" |
| }, { |
| "sid", |
| "sid_Latn_ET", |
| "sid" |
| }, { |
| "sk", |
| "sk_Latn_SK", |
| "sk" |
| }, { |
| "sl", |
| "sl_Latn_SI", |
| "sl" |
| }, { |
| "sm", |
| "sm_Latn_WS", |
| "sm" |
| }, { |
| "so", |
| "so_Latn_SO", |
| "so" |
| }, { |
| "sq", |
| "sq_Latn_AL", |
| "sq" |
| }, { |
| "sr", |
| "sr_Cyrl_RS", |
| "sr" |
| }, { |
| "ss", |
| "ss_Latn_ZA", |
| "ss" |
| }, { |
| "st", |
| "st_Latn_ZA", |
| "st" |
| }, { |
| "sv", |
| "sv_Latn_SE", |
| "sv" |
| }, { |
| "sw", |
| "sw_Latn_TZ", |
| "sw" |
| }, { |
| "ta", |
| "ta_Taml_IN", |
| "ta" |
| }, { |
| "te", |
| "te_Telu_IN", |
| "te" |
| }, { |
| "tet", |
| "tet_Latn_TL", |
| "tet" |
| }, { |
| "tg", |
| "tg_Cyrl_TJ", |
| "tg" |
| }, { |
| "th", |
| "th_Thai_TH", |
| "th" |
| }, { |
| "ti", |
| "ti_Ethi_ET", |
| "ti" |
| }, { |
| "tig", |
| "tig_Ethi_ER", |
| "tig" |
| }, { |
| "tk", |
| "tk_Latn_TM", |
| "tk" |
| }, { |
| "tkl", |
| "tkl_Latn_TK", |
| "tkl" |
| }, { |
| "tn", |
| "tn_Latn_ZA", |
| "tn" |
| }, { |
| "to", |
| "to_Latn_TO", |
| "to" |
| }, { |
| "tpi", |
| "tpi_Latn_PG", |
| "tpi" |
| }, { |
| "tr", |
| "tr_Latn_TR", |
| "tr" |
| }, { |
| "ts", |
| "ts_Latn_ZA", |
| "ts" |
| }, { |
| "tt", |
| "tt_Cyrl_RU", |
| "tt" |
| }, { |
| "tvl", |
| "tvl_Latn_TV", |
| "tvl" |
| }, { |
| "ty", |
| "ty_Latn_PF", |
| "ty" |
| }, { |
| "uk", |
| "uk_Cyrl_UA", |
| "uk" |
| }, { |
| "und", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_AD", |
| "ca_Latn_AD", |
| "ca_AD" |
| }, { |
| "und_AE", |
| "ar_Arab_AE", |
| "ar_AE" |
| }, { |
| "und_AF", |
| "fa_Arab_AF", |
| "fa_AF" |
| }, { |
| "und_AL", |
| "sq_Latn_AL", |
| "sq" |
| }, { |
| "und_AM", |
| "hy_Armn_AM", |
| "hy" |
| }, { |
| "und_AO", |
| "pt_Latn_AO", |
| "pt_AO" |
| }, { |
| "und_AR", |
| "es_Latn_AR", |
| "es_AR" |
| }, { |
| "und_AS", |
| "sm_Latn_AS", |
| "sm_AS" |
| }, { |
| "und_AT", |
| "de_Latn_AT", |
| "de_AT" |
| }, { |
| "und_AW", |
| "nl_Latn_AW", |
| "nl_AW" |
| }, { |
| "und_AX", |
| "sv_Latn_AX", |
| "sv_AX" |
| }, { |
| "und_AZ", |
| "az_Latn_AZ", |
| "az" |
| }, { |
| "und_Arab", |
| "ar_Arab_EG", |
| "ar" |
| }, { |
| "und_Arab_IN", |
| "ur_Arab_IN", |
| "ur_IN" |
| }, { |
| "und_Arab_PK", |
| "ur_Arab_PK", |
| "ur" |
| }, { |
| "und_Arab_SN", |
| "ar_Arab_SN", |
| "ar_SN" |
| }, { |
| "und_Armn", |
| "hy_Armn_AM", |
| "hy" |
| }, { |
| "und_BA", |
| "bs_Latn_BA", |
| "bs" |
| }, { |
| "und_BD", |
| "bn_Beng_BD", |
| "bn" |
| }, { |
| "und_BE", |
| "nl_Latn_BE", |
| "nl_BE" |
| }, { |
| "und_BF", |
| "fr_Latn_BF", |
| "fr_BF" |
| }, { |
| "und_BG", |
| "bg_Cyrl_BG", |
| "bg" |
| }, { |
| "und_BH", |
| "ar_Arab_BH", |
| "ar_BH" |
| }, { |
| "und_BI", |
| "rn_Latn_BI", |
| "rn" |
| }, { |
| "und_BJ", |
| "fr_Latn_BJ", |
| "fr_BJ" |
| }, { |
| "und_BN", |
| "ms_Latn_BN", |
| "ms_BN" |
| }, { |
| "und_BO", |
| "es_Latn_BO", |
| "es_BO" |
| }, { |
| "und_BR", |
| "pt_Latn_BR", |
| "pt" |
| }, { |
| "und_BT", |
| "dz_Tibt_BT", |
| "dz" |
| }, { |
| "und_BY", |
| "be_Cyrl_BY", |
| "be" |
| }, { |
| "und_Beng", |
| "bn_Beng_BD", |
| "bn" |
| }, { |
| "und_Beng_IN", |
| "bn_Beng_IN", |
| "bn_IN" |
| }, { |
| "und_CD", |
| "sw_Latn_CD", |
| "sw_CD" |
| }, { |
| "und_CF", |
| "fr_Latn_CF", |
| "fr_CF" |
| }, { |
| "und_CG", |
| "fr_Latn_CG", |
| "fr_CG" |
| }, { |
| "und_CH", |
| "de_Latn_CH", |
| "de_CH" |
| }, { |
| "und_CI", |
| "fr_Latn_CI", |
| "fr_CI" |
| }, { |
| "und_CL", |
| "es_Latn_CL", |
| "es_CL" |
| }, { |
| "und_CM", |
| "fr_Latn_CM", |
| "fr_CM" |
| }, { |
| "und_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_CO", |
| "es_Latn_CO", |
| "es_CO" |
| }, { |
| "und_CR", |
| "es_Latn_CR", |
| "es_CR" |
| }, { |
| "und_CU", |
| "es_Latn_CU", |
| "es_CU" |
| }, { |
| "und_CV", |
| "pt_Latn_CV", |
| "pt_CV" |
| }, { |
| "und_CY", |
| "el_Grek_CY", |
| "el_CY" |
| }, { |
| "und_CZ", |
| "cs_Latn_CZ", |
| "cs" |
| }, { |
| "und_Cher", |
| "chr_Cher_US", |
| "chr" |
| }, { |
| "und_Cyrl", |
| "ru_Cyrl_RU", |
| "ru" |
| }, { |
| "und_Cyrl_KZ", |
| "ru_Cyrl_KZ", |
| "ru_KZ" |
| }, { |
| "und_DE", |
| "de_Latn_DE", |
| "de" |
| }, { |
| "und_DJ", |
| "aa_Latn_DJ", |
| "aa_DJ" |
| }, { |
| "und_DK", |
| "da_Latn_DK", |
| "da" |
| }, { |
| "und_DO", |
| "es_Latn_DO", |
| "es_DO" |
| }, { |
| "und_DZ", |
| "ar_Arab_DZ", |
| "ar_DZ" |
| }, { |
| "und_Deva", |
| "hi_Deva_IN", |
| "hi" |
| }, { |
| "und_EC", |
| "es_Latn_EC", |
| "es_EC" |
| }, { |
| "und_EE", |
| "et_Latn_EE", |
| "et" |
| }, { |
| "und_EG", |
| "ar_Arab_EG", |
| "ar" |
| }, { |
| "und_EH", |
| "ar_Arab_EH", |
| "ar_EH" |
| }, { |
| "und_ER", |
| "ti_Ethi_ER", |
| "ti_ER" |
| }, { |
| "und_ES", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "und_ET", |
| "am_Ethi_ET", |
| "am" |
| }, { |
| "und_Ethi", |
| "am_Ethi_ET", |
| "am" |
| }, { |
| "und_Ethi_ER", |
| "am_Ethi_ER", |
| "am_ER" |
| }, { |
| "und_FI", |
| "fi_Latn_FI", |
| "fi" |
| }, { |
| "und_FM", |
| "en_Latn_FM", |
| "en_FM" |
| }, { |
| "und_FO", |
| "fo_Latn_FO", |
| "fo" |
| }, { |
| "und_FR", |
| "fr_Latn_FR", |
| "fr" |
| }, { |
| "und_GA", |
| "fr_Latn_GA", |
| "fr_GA" |
| }, { |
| "und_GE", |
| "ka_Geor_GE", |
| "ka" |
| }, { |
| "und_GF", |
| "fr_Latn_GF", |
| "fr_GF" |
| }, { |
| "und_GL", |
| "kl_Latn_GL", |
| "kl" |
| }, { |
| "und_GN", |
| "fr_Latn_GN", |
| "fr_GN" |
| }, { |
| "und_GP", |
| "fr_Latn_GP", |
| "fr_GP" |
| }, { |
| "und_GQ", |
| "es_Latn_GQ", |
| "es_GQ" |
| }, { |
| "und_GR", |
| "el_Grek_GR", |
| "el" |
| }, { |
| "und_GT", |
| "es_Latn_GT", |
| "es_GT" |
| }, { |
| "und_GU", |
| "en_Latn_GU", |
| "en_GU" |
| }, { |
| "und_GW", |
| "pt_Latn_GW", |
| "pt_GW" |
| }, { |
| "und_Geor", |
| "ka_Geor_GE", |
| "ka" |
| }, { |
| "und_Grek", |
| "el_Grek_GR", |
| "el" |
| }, { |
| "und_Gujr", |
| "gu_Gujr_IN", |
| "gu" |
| }, { |
| "und_Guru", |
| "pa_Guru_IN", |
| "pa" |
| }, { |
| "und_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "und_HN", |
| "es_Latn_HN", |
| "es_HN" |
| }, { |
| "und_HR", |
| "hr_Latn_HR", |
| "hr" |
| }, { |
| "und_HT", |
| "ht_Latn_HT", |
| "ht" |
| }, { |
| "und_HU", |
| "hu_Latn_HU", |
| "hu" |
| }, { |
| "und_Hani", |
| "zh_Hani_CN", |
| "zh_Hani" |
| }, { |
| "und_Hans", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_Hant", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Hebr", |
| "he_Hebr_IL", |
| "he" |
| }, { |
| "und_IL", |
| "he_Hebr_IL", |
| "he" |
| }, { |
| "und_IN", |
| "hi_Deva_IN", |
| "hi" |
| }, { |
| "und_IQ", |
| "ar_Arab_IQ", |
| "ar_IQ" |
| }, { |
| "und_IR", |
| "fa_Arab_IR", |
| "fa" |
| }, { |
| "und_IS", |
| "is_Latn_IS", |
| "is" |
| }, { |
| "und_IT", |
| "it_Latn_IT", |
| "it" |
| }, { |
| "und_JO", |
| "ar_Arab_JO", |
| "ar_JO" |
| }, { |
| "und_JP", |
| "ja_Jpan_JP", |
| "ja" |
| }, { |
| "und_Jpan", |
| "ja_Jpan_JP", |
| "ja" |
| }, { |
| "und_KG", |
| "ky_Cyrl_KG", |
| "ky" |
| }, { |
| "und_KH", |
| "km_Khmr_KH", |
| "km" |
| }, { |
| "und_KM", |
| "ar_Arab_KM", |
| "ar_KM" |
| }, { |
| "und_KP", |
| "ko_Kore_KP", |
| "ko_KP" |
| }, { |
| "und_KR", |
| "ko_Kore_KR", |
| "ko" |
| }, { |
| "und_KW", |
| "ar_Arab_KW", |
| "ar_KW" |
| }, { |
| "und_KZ", |
| "ru_Cyrl_KZ", |
| "ru_KZ" |
| }, { |
| "und_Khmr", |
| "km_Khmr_KH", |
| "km" |
| }, { |
| "und_Knda", |
| "kn_Knda_IN", |
| "kn" |
| }, { |
| "und_Kore", |
| "ko_Kore_KR", |
| "ko" |
| }, { |
| "und_LA", |
| "lo_Laoo_LA", |
| "lo" |
| }, { |
| "und_LB", |
| "ar_Arab_LB", |
| "ar_LB" |
| }, { |
| "und_LI", |
| "de_Latn_LI", |
| "de_LI" |
| }, { |
| "und_LK", |
| "si_Sinh_LK", |
| "si" |
| }, { |
| "und_LS", |
| "st_Latn_LS", |
| "st_LS" |
| }, { |
| "und_LT", |
| "lt_Latn_LT", |
| "lt" |
| }, { |
| "und_LU", |
| "fr_Latn_LU", |
| "fr_LU" |
| }, { |
| "und_LV", |
| "lv_Latn_LV", |
| "lv" |
| }, { |
| "und_LY", |
| "ar_Arab_LY", |
| "ar_LY" |
| }, { |
| "und_Laoo", |
| "lo_Laoo_LA", |
| "lo" |
| }, { |
| "und_Latn_ES", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "und_Latn_ET", |
| "en_Latn_ET", |
| "en_ET" |
| }, { |
| "und_Latn_GB", |
| "en_Latn_GB", |
| "en_GB" |
| }, { |
| "und_Latn_GH", |
| "ak_Latn_GH", |
| "ak" |
| }, { |
| "und_Latn_ID", |
| "id_Latn_ID", |
| "id" |
| }, { |
| "und_Latn_IT", |
| "it_Latn_IT", |
| "it" |
| }, { |
| "und_Latn_NG", |
| "en_Latn_NG", |
| "en_NG" |
| }, { |
| "und_Latn_TR", |
| "tr_Latn_TR", |
| "tr" |
| }, { |
| "und_Latn_ZA", |
| "en_Latn_ZA", |
| "en_ZA" |
| }, { |
| "und_MA", |
| "ar_Arab_MA", |
| "ar_MA" |
| }, { |
| "und_MC", |
| "fr_Latn_MC", |
| "fr_MC" |
| }, { |
| "und_MD", |
| "ro_Latn_MD", |
| "ro_MD" |
| }, { |
| "und_ME", |
| "sr_Latn_ME", |
| "sr_ME" |
| }, { |
| "und_MG", |
| "mg_Latn_MG", |
| "mg" |
| }, { |
| "und_MH", |
| "en_Latn_MH", |
| "en_MH" |
| }, { |
| "und_MK", |
| "mk_Cyrl_MK", |
| "mk" |
| }, { |
| "und_ML", |
| "bm_Latn_ML", |
| "bm" |
| }, { |
| "und_MM", |
| "my_Mymr_MM", |
| "my" |
| }, { |
| "und_MN", |
| "mn_Cyrl_MN", |
| "mn" |
| }, { |
| "und_MO", |
| "zh_Hant_MO", |
| "zh_MO" |
| }, { |
| "und_MQ", |
| "fr_Latn_MQ", |
| "fr_MQ" |
| }, { |
| "und_MR", |
| "ar_Arab_MR", |
| "ar_MR" |
| }, { |
| "und_MT", |
| "mt_Latn_MT", |
| "mt" |
| }, { |
| "und_MV", |
| "dv_Thaa_MV", |
| "dv" |
| }, { |
| "und_MW", |
| "en_Latn_MW", |
| "en_MW" |
| }, { |
| "und_MX", |
| "es_Latn_MX", |
| "es_MX" |
| }, { |
| "und_MY", |
| "ms_Latn_MY", |
| "ms" |
| }, { |
| "und_MZ", |
| "pt_Latn_MZ", |
| "pt_MZ" |
| }, { |
| "und_Mlym", |
| "ml_Mlym_IN", |
| "ml" |
| }, { |
| "und_Mymr", |
| "my_Mymr_MM", |
| "my" |
| }, { |
| "und_NC", |
| "fr_Latn_NC", |
| "fr_NC" |
| }, { |
| "und_NE", |
| "ha_Latn_NE", |
| "ha_NE" |
| }, { |
| "und_NG", |
| "en_Latn_NG", |
| "en_NG" |
| }, { |
| "und_NI", |
| "es_Latn_NI", |
| "es_NI" |
| }, { |
| "und_NL", |
| "nl_Latn_NL", |
| "nl" |
| }, { |
| "und_NO", |
| "no_Latn_NO", /* Google patch */ |
| "no" /* Google patch */ |
| }, { |
| "und_NP", |
| "ne_Deva_NP", |
| "ne" |
| }, { |
| "und_NR", |
| "en_Latn_NR", |
| "en_NR" |
| }, { |
| "und_NU", |
| "en_Latn_NU", |
| "en_NU" |
| }, { |
| "und_OM", |
| "ar_Arab_OM", |
| "ar_OM" |
| }, { |
| "und_Orya", |
| "or_Orya_IN", |
| "or" |
| }, { |
| "und_PA", |
| "es_Latn_PA", |
| "es_PA" |
| }, { |
| "und_PE", |
| "es_Latn_PE", |
| "es_PE" |
| }, { |
| "und_PF", |
| "fr_Latn_PF", |
| "fr_PF" |
| }, { |
| "und_PG", |
| "tpi_Latn_PG", |
| "tpi" |
| }, { |
| "und_PH", |
| "fil_Latn_PH", |
| "fil" |
| }, { |
| "und_PL", |
| "pl_Latn_PL", |
| "pl" |
| }, { |
| "und_PM", |
| "fr_Latn_PM", |
| "fr_PM" |
| }, { |
| "und_PR", |
| "es_Latn_PR", |
| "es_PR" |
| }, { |
| "und_PS", |
| "ar_Arab_PS", |
| "ar_PS" |
| }, { |
| "und_PT", |
| "pt_Latn_PT", |
| "pt_PT" |
| }, { |
| "und_PW", |
| "pau_Latn_PW", |
| "pau" |
| }, { |
| "und_PY", |
| "gn_Latn_PY", |
| "gn" |
| }, { |
| "und_QA", |
| "ar_Arab_QA", |
| "ar_QA" |
| }, { |
| "und_RE", |
| "fr_Latn_RE", |
| "fr_RE" |
| }, { |
| "und_RO", |
| "ro_Latn_RO", |
| "ro" |
| }, { |
| "und_RS", |
| "sr_Cyrl_RS", |
| "sr" |
| }, { |
| "und_RU", |
| "ru_Cyrl_RU", |
| "ru" |
| }, { |
| "und_RW", |
| "rw_Latn_RW", |
| "rw" |
| }, { |
| "und_SA", |
| "ar_Arab_SA", |
| "ar_SA" |
| }, { |
| "und_SD", |
| "ar_Arab_SD", |
| "ar_SD" |
| }, { |
| "und_SE", |
| "sv_Latn_SE", |
| "sv" |
| }, { |
| "und_SG", |
| "en_Latn_SG", |
| "en_SG" |
| }, { |
| "und_SI", |
| "sl_Latn_SI", |
| "sl" |
| }, { |
| "und_SJ", |
| "no_Latn_SJ", /* Google patch */ |
| "no_SJ" /* Google patch */ |
| }, { |
| "und_SK", |
| "sk_Latn_SK", |
| "sk" |
| }, { |
| "und_SM", |
| "it_Latn_SM", |
| "it_SM" |
| }, { |
| "und_SN", |
| "fr_Latn_SN", |
| "fr_SN" |
| }, { |
| "und_SO", |
| "so_Latn_SO", |
| "so" |
| }, { |
| "und_SR", |
| "nl_Latn_SR", |
| "nl_SR" |
| }, { |
| "und_ST", |
| "pt_Latn_ST", |
| "pt_ST" |
| }, { |
| "und_SV", |
| "es_Latn_SV", |
| "es_SV" |
| }, { |
| "und_SY", |
| "ar_Arab_SY", |
| "ar_SY" |
| }, { |
| "und_Sinh", |
| "si_Sinh_LK", |
| "si" |
| }, { |
| "und_TD", |
| "fr_Latn_TD", |
| "fr_TD" |
| }, { |
| "und_TG", |
| "fr_Latn_TG", |
| "fr_TG" |
| }, { |
| "und_TH", |
| "th_Thai_TH", |
| "th" |
| }, { |
| "und_TJ", |
| "tg_Cyrl_TJ", |
| "tg" |
| }, { |
| "und_TK", |
| "tkl_Latn_TK", |
| "tkl" |
| }, { |
| "und_TL", |
| "pt_Latn_TL", |
| "pt_TL" |
| }, { |
| "und_TM", |
| "tk_Latn_TM", |
| "tk" |
| }, { |
| "und_TN", |
| "ar_Arab_TN", |
| "ar_TN" |
| }, { |
| "und_TO", |
| "to_Latn_TO", |
| "to" |
| }, { |
| "und_TR", |
| "tr_Latn_TR", |
| "tr" |
| }, { |
| "und_TV", |
| "tvl_Latn_TV", |
| "tvl" |
| }, { |
| "und_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Taml", |
| "ta_Taml_IN", |
| "ta" |
| }, { |
| "und_Telu", |
| "te_Telu_IN", |
| "te" |
| }, { |
| "und_Thaa", |
| "dv_Thaa_MV", |
| "dv" |
| }, { |
| "und_Thai", |
| "th_Thai_TH", |
| "th" |
| }, { |
| "und_Tibt", |
| "bo_Tibt_CN", |
| "bo" |
| }, { |
| "und_UA", |
| "uk_Cyrl_UA", |
| "uk" |
| }, { |
| "und_UY", |
| "es_Latn_UY", |
| "es_UY" |
| }, { |
| "und_UZ", |
| "uz_Latn_UZ", |
| "uz" |
| }, { |
| "und_VA", |
| "it_Latn_VA", |
| "it_VA" |
| }, { |
| "und_VE", |
| "es_Latn_VE", |
| "es_VE" |
| }, { |
| "und_VN", |
| "vi_Latn_VN", |
| "vi" |
| }, { |
| "und_VU", |
| "bi_Latn_VU", |
| "bi" |
| }, { |
| "und_WF", |
| "fr_Latn_WF", |
| "fr_WF" |
| }, { |
| "und_WS", |
| "sm_Latn_WS", |
| "sm" |
| }, { |
| "und_YE", |
| "ar_Arab_YE", |
| "ar_YE" |
| }, { |
| "und_YT", |
| "fr_Latn_YT", |
| "fr_YT" |
| }, { |
| "und_Yiii", |
| "ii_Yiii_CN", |
| "ii" |
| }, { |
| "ur", |
| "ur_Arab_PK", |
| "ur" |
| }, { |
| "uz", |
| "uz_Latn_UZ", |
| "uz" |
| }, { |
| "uz_AF", |
| "uz_Arab_AF", |
| "uz_AF" |
| }, { |
| "uz_Arab", |
| "uz_Arab_AF", |
| "uz_AF" |
| }, { |
| "ve", |
| "ve_Latn_ZA", |
| "ve" |
| }, { |
| "vi", |
| "vi_Latn_VN", |
| "vi" |
| }, { |
| "wal", |
| "wal_Ethi_ET", |
| "wal" |
| }, { |
| "wo", |
| "wo_Latn_SN", |
| "wo" |
| }, { |
| "xh", |
| "xh_Latn_ZA", |
| "xh" |
| }, { |
| "yo", |
| "yo_Latn_NG", |
| "yo" |
| }, { |
| "zh", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "zh_Hani", |
| "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */ |
| "zh_Hani", /* changed due to cldrbug 6204, may be an error */ |
| }, { |
| "zh_Hant", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zh_MO", |
| "zh_Hant_MO", |
| "zh_MO" |
| }, { |
| "zh_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zu", |
| "zu_Latn_ZA", |
| "zu" |
| }, { |
| "und", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_ZZ", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "und_AQ", |
| "_Latn_AQ", |
| "_AQ" |
| }, { |
| "und_Zzzz", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_Zzzz_ZZ", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_Zzzz_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_Zzzz_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Zzzz_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "und_Zzzz_AQ", |
| "_Latn_AQ", |
| "_AQ" |
| }, { |
| "und_Latn", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_Latn_ZZ", |
| "en_Latn_US", |
| "en" |
| }, { |
| "und_Latn_CN", |
| "za_Latn_CN", |
| "za" |
| }, { |
| "und_Latn_TW", |
| "trv_Latn_TW", |
| "trv" |
| }, { |
| "und_Latn_HK", |
| "zh_Latn_HK", |
| "zh_Latn_HK" |
| }, { |
| "und_Latn_AQ", |
| "_Latn_AQ", |
| "_AQ" |
| }, { |
| "und_Hans", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_Hans_ZZ", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_Hans_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "und_Hans_TW", |
| "zh_Hans_TW", |
| "zh_Hans_TW" |
| }, { |
| "und_Hans_HK", |
| "zh_Hans_HK", |
| "zh_Hans_HK" |
| }, { |
| "und_Hans_AQ", |
| "zh_Hans_AQ", |
| "zh_AQ" |
| }, { |
| "und_Hant", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Hant_ZZ", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Hant_CN", |
| "zh_Hant_CN", |
| "zh_Hant_CN" |
| }, { |
| "und_Hant_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "und_Hant_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "und_Hant_AQ", |
| "zh_Hant_AQ", |
| "zh_Hant_AQ" |
| }, { |
| "und_Moon", |
| "en_Moon_US", |
| "en_Moon" |
| }, { |
| "und_Moon_ZZ", |
| "en_Moon_US", |
| "en_Moon" |
| }, { |
| "und_Moon_CN", |
| "zh_Moon_CN", |
| "zh_Moon" |
| }, { |
| "und_Moon_TW", |
| "zh_Moon_TW", |
| "zh_Moon_TW" |
| }, { |
| "und_Moon_HK", |
| "zh_Moon_HK", |
| "zh_Moon_HK" |
| }, { |
| "und_Moon_AQ", |
| "_Moon_AQ", |
| "_Moon_AQ" |
| }, { |
| "es", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_ZZ", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_CN", |
| "es_Latn_CN", |
| "es_CN" |
| }, { |
| "es_TW", |
| "es_Latn_TW", |
| "es_TW" |
| }, { |
| "es_HK", |
| "es_Latn_HK", |
| "es_HK" |
| }, { |
| "es_AQ", |
| "es_Latn_AQ", |
| "es_AQ" |
| }, { |
| "es_Zzzz", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_Zzzz_ZZ", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_Zzzz_CN", |
| "es_Latn_CN", |
| "es_CN" |
| }, { |
| "es_Zzzz_TW", |
| "es_Latn_TW", |
| "es_TW" |
| }, { |
| "es_Zzzz_HK", |
| "es_Latn_HK", |
| "es_HK" |
| }, { |
| "es_Zzzz_AQ", |
| "es_Latn_AQ", |
| "es_AQ" |
| }, { |
| "es_Latn", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_Latn_ZZ", |
| "es_Latn_ES", |
| "es" |
| }, { |
| "es_Latn_CN", |
| "es_Latn_CN", |
| "es_CN" |
| }, { |
| "es_Latn_TW", |
| "es_Latn_TW", |
| "es_TW" |
| }, { |
| "es_Latn_HK", |
| "es_Latn_HK", |
| "es_HK" |
| }, { |
| "es_Latn_AQ", |
| "es_Latn_AQ", |
| "es_AQ" |
| }, { |
| "es_Hans", |
| "es_Hans_ES", |
| "es_Hans" |
| }, { |
| "es_Hans_ZZ", |
| "es_Hans_ES", |
| "es_Hans" |
| }, { |
| "es_Hans_CN", |
| "es_Hans_CN", |
| "es_Hans_CN" |
| }, { |
| "es_Hans_TW", |
| "es_Hans_TW", |
| "es_Hans_TW" |
| }, { |
| "es_Hans_HK", |
| "es_Hans_HK", |
| "es_Hans_HK" |
| }, { |
| "es_Hans_AQ", |
| "es_Hans_AQ", |
| "es_Hans_AQ" |
| }, { |
| "es_Hant", |
| "es_Hant_ES", |
| "es_Hant" |
| }, { |
| "es_Hant_ZZ", |
| "es_Hant_ES", |
| "es_Hant" |
| }, { |
| "es_Hant_CN", |
| "es_Hant_CN", |
| "es_Hant_CN" |
| }, { |
| "es_Hant_TW", |
| "es_Hant_TW", |
| "es_Hant_TW" |
| }, { |
| "es_Hant_HK", |
| "es_Hant_HK", |
| "es_Hant_HK" |
| }, { |
| "es_Hant_AQ", |
| "es_Hant_AQ", |
| "es_Hant_AQ" |
| }, { |
| "es_Moon", |
| "es_Moon_ES", |
| "es_Moon" |
| }, { |
| "es_Moon_ZZ", |
| "es_Moon_ES", |
| "es_Moon" |
| }, { |
| "es_Moon_CN", |
| "es_Moon_CN", |
| "es_Moon_CN" |
| }, { |
| "es_Moon_TW", |
| "es_Moon_TW", |
| "es_Moon_TW" |
| }, { |
| "es_Moon_HK", |
| "es_Moon_HK", |
| "es_Moon_HK" |
| }, { |
| "es_Moon_AQ", |
| "es_Moon_AQ", |
| "es_Moon_AQ" |
| }, { |
| "zh", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_ZZ", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zh_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "zh_AQ", |
| "zh_Hans_AQ", |
| "zh_AQ" |
| }, { |
| "zh_Zzzz", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_Zzzz_ZZ", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_Zzzz_CN", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_Zzzz_TW", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zh_Zzzz_HK", |
| "zh_Hant_HK", |
| "zh_HK" |
| }, { |
| "zh_Zzzz_AQ", |
| "zh_Hans_AQ", |
| "zh_AQ" |
| }, { |
| "zh_Latn", |
| "zh_Latn_CN", |
| "zh_Latn" |
| }, { |
| "zh_Latn_ZZ", |
| "zh_Latn_CN", |
| "zh_Latn" |
| }, { |
| "zh_Latn_CN", |
| "zh_Latn_CN", |
| "zh_Latn" |
| }, { |
| "zh_Latn_TW", |
| "zh_Latn_TW", |
| "zh_Latn_TW" |
| }, { |
| "zh_Latn_HK", |
| "zh_Latn_HK", |
| "zh_Latn_HK" |
| }, { |
| "zh_Latn_AQ", |
| "zh_Latn_AQ", |
| "zh_Latn_AQ" |
| }, { |
| "zh_Hans", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_Hans_ZZ", |
| "zh_Hans_CN", |
| "zh" |
| }, { |
| "zh_Hans_TW", |
| "zh_Hans_TW", |
| "zh_Hans_TW" |
| }, { |
| "zh_Hans_HK", |
| "zh_Hans_HK", |
| "zh_Hans_HK" |
| }, { |
| "zh_Hans_AQ", |
| "zh_Hans_AQ", |
| "zh_AQ" |
| }, { |
| "zh_Hant", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zh_Hant_ZZ", |
| "zh_Hant_TW", |
| "zh_TW" |
| }, { |
| "zh_Hant_CN", |
| "zh_Hant_CN", |
| "zh_Hant_CN" |
| }, { |
| "zh_Hant_AQ", |
| "zh_Hant_AQ", |
| "zh_Hant_AQ" |
| }, { |
| "zh_Moon", |
| "zh_Moon_CN", |
| "zh_Moon" |
| }, { |
| "zh_Moon_ZZ", |
| "zh_Moon_CN", |
| "zh_Moon" |
| }, { |
| "zh_Moon_CN", |
| "zh_Moon_CN", |
| "zh_Moon" |
| }, { |
| "zh_Moon_TW", |
| "zh_Moon_TW", |
| "zh_Moon_TW" |
| }, { |
| "zh_Moon_HK", |
| "zh_Moon_HK", |
| "zh_Moon_HK" |
| }, { |
| "zh_Moon_AQ", |
| "zh_Moon_AQ", |
| "zh_Moon_AQ" |
| }, { |
| "art", |
| "", |
| "" |
| }, { |
| "art_ZZ", |
| "", |
| "" |
| }, { |
| "art_CN", |
| "", |
| "" |
| }, { |
| "art_TW", |
| "", |
| "" |
| }, { |
| "art_HK", |
| "", |
| "" |
| }, { |
| "art_AQ", |
| "", |
| "" |
| }, { |
| "art_Zzzz", |
| "", |
| "" |
| }, { |
| "art_Zzzz_ZZ", |
| "", |
| "" |
| }, { |
| "art_Zzzz_CN", |
| "", |
| "" |
| }, { |
| "art_Zzzz_TW", |
| "", |
| "" |
| }, { |
| "art_Zzzz_HK", |
| "", |
| "" |
| }, { |
| "art_Zzzz_AQ", |
| "", |
| "" |
| }, { |
| "art_Latn", |
| "", |
| "" |
| }, { |
| "art_Latn_ZZ", |
| "", |
| "" |
| }, { |
| "art_Latn_CN", |
| "", |
| "" |
| }, { |
| "art_Latn_TW", |
| "", |
| "" |
| }, { |
| "art_Latn_HK", |
| "", |
| "" |
| }, { |
| "art_Latn_AQ", |
| "", |
| "" |
| }, { |
| "art_Hans", |
| "", |
| "" |
| }, { |
| "art_Hans_ZZ", |
| "", |
| "" |
| }, { |
| "art_Hans_CN", |
| "", |
| "" |
| }, { |
| "art_Hans_TW", |
| "", |
| "" |
| }, { |
| "art_Hans_HK", |
| "", |
| "" |
| }, { |
| "art_Hans_AQ", |
| "", |
| "" |
| }, { |
| "art_Hant", |
| "", |
| "" |
| }, { |
| "art_Hant_ZZ", |
| "", |
| "" |
| }, { |
| "art_Hant_CN", |
| "", |
| "" |
| }, { |
| "art_Hant_TW", |
| "", |
| "" |
| }, { |
| "art_Hant_HK", |
| "", |
| "" |
| }, { |
| "art_Hant_AQ", |
| "", |
| "" |
| }, { |
| "art_Moon", |
| "", |
| "" |
| }, { |
| "art_Moon_ZZ", |
| "", |
| "" |
| }, { |
| "art_Moon_CN", |
| "", |
| "" |
| }, { |
| "art_Moon_TW", |
| "", |
| "" |
| }, { |
| "art_Moon_HK", |
| "", |
| "" |
| }, { |
| "art_Moon_AQ", |
| "", |
| "" |
| }, { |
| "de@collation=phonebook", |
| "de_Latn_DE@collation=phonebook", |
| "de@collation=phonebook" |
| } |
| }; |
| |
| typedef struct errorDataTag { |
| const char* tag; |
| const char* expected; |
| UErrorCode uerror; |
| int32_t bufferSize; |
| } errorData; |
| |
| const errorData maximizeErrors[] = { |
| { |
| "enfueiujhytdf", |
| NULL, |
| U_ILLEGAL_ARGUMENT_ERROR, |
| -1 |
| }, |
| { |
| "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", |
| NULL, |
| U_ILLEGAL_ARGUMENT_ERROR, |
| -1 |
| }, |
| { |
| "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", |
| NULL, |
| U_ILLEGAL_ARGUMENT_ERROR, |
| -1 |
| }, |
| { |
| "en_Latn_US_POSIX@currency=EURO", |
| "en_Latn_US_POSIX@currency=EURO", |
| U_BUFFER_OVERFLOW_ERROR, |
| 29 |
| }, |
| { |
| "en_Latn_US_POSIX@currency=EURO", |
| "en_Latn_US_POSIX@currency=EURO", |
| U_STRING_NOT_TERMINATED_WARNING, |
| 30 |
| } |
| }; |
| |
| const errorData minimizeErrors[] = { |
| { |
| "enfueiujhytdf", |
| NULL, |
| U_ILLEGAL_ARGUMENT_ERROR, |
| -1 |
| }, |
| { |
| "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", |
| NULL, |
| U_ILLEGAL_ARGUMENT_ERROR, |
| -1 |
| }, |
| { |
| "en_Latn_US_POSIX@currency=EURO", |
| "en__POSIX@currency=EURO", |
| U_BUFFER_OVERFLOW_ERROR, |
| 22 |
| }, |
| { |
| "en_Latn_US_POSIX@currency=EURO", |
| "en__POSIX@currency=EURO", |
| U_STRING_NOT_TERMINATED_WARNING, |
| 23 |
| } |
| }; |
| |
| static int32_t getExpectedReturnValue(const errorData* data) |
| { |
| if (data->uerror == U_BUFFER_OVERFLOW_ERROR || |
| data->uerror == U_STRING_NOT_TERMINATED_WARNING) |
| { |
| return (int32_t)strlen(data->expected); |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| |
| static int32_t getBufferSize(const errorData* data, int32_t actualSize) |
| { |
| if (data->expected == NULL) |
| { |
| return actualSize; |
| } |
| else if (data->bufferSize < 0) |
| { |
| return (int32_t)strlen(data->expected) + 1; |
| } |
| else |
| { |
| return data->bufferSize; |
| } |
| } |
| |
| static void TestLikelySubtags() |
| { |
| char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1]; |
| int32_t i = 0; |
| |
| for (; i < UPRV_LENGTHOF(basic_maximize_data); ++i) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const minimal = basic_maximize_data[i][0]; |
| const char* const maximal = basic_maximize_data[i][1]; |
| |
| /* const int32_t length = */ |
| uloc_addLikelySubtags( |
| minimal, |
| buffer, |
| sizeof(buffer), |
| &status); |
| if (U_FAILURE(status)) { |
| log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strlen(maximal) == 0) { |
| if (uprv_stricmp(minimal, buffer) != 0) { |
| log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); |
| } |
| } |
| else if (uprv_stricmp(maximal, buffer) != 0) { |
| log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer); |
| } |
| } |
| |
| for (i = 0; i < UPRV_LENGTHOF(basic_minimize_data); ++i) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const maximal = basic_minimize_data[i][0]; |
| const char* const minimal = basic_minimize_data[i][1]; |
| |
| /* const int32_t length = */ |
| uloc_minimizeSubtags( |
| maximal, |
| buffer, |
| sizeof(buffer), |
| &status); |
| |
| if (U_FAILURE(status)) { |
| log_err_status(status, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strlen(minimal) == 0) { |
| if (uprv_stricmp(maximal, buffer) != 0) { |
| log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer); |
| } |
| } |
| else if (uprv_stricmp(minimal, buffer) != 0) { |
| log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer); |
| } |
| } |
| |
| for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const minimal = full_data[i][0]; |
| const char* const maximal = full_data[i][1]; |
| |
| /* const int32_t length = */ |
| uloc_addLikelySubtags( |
| minimal, |
| buffer, |
| sizeof(buffer), |
| &status); |
| if (U_FAILURE(status)) { |
| log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strlen(maximal) == 0) { |
| if (uprv_stricmp(minimal, buffer) != 0) { |
| log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); |
| } |
| } |
| else if (uprv_stricmp(maximal, buffer) != 0) { |
| log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); |
| } |
| } |
| |
| for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const maximal = full_data[i][1]; |
| const char* const minimal = full_data[i][2]; |
| |
| if (strlen(maximal) > 0) { |
| |
| /* const int32_t length = */ |
| uloc_minimizeSubtags( |
| maximal, |
| buffer, |
| sizeof(buffer), |
| &status); |
| |
| if (U_FAILURE(status)) { |
| log_err_status(status, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status)); |
| status = U_ZERO_ERROR; |
| } |
| else if (uprv_strlen(minimal) == 0) { |
| if (uprv_stricmp(maximal, buffer) != 0) { |
| log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer); |
| } |
| } |
| else if (uprv_stricmp(minimal, buffer) != 0) { |
| log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer); |
| } |
| } |
| } |
| |
| for (i = 0; i < UPRV_LENGTHOF(maximizeErrors); ++i) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const minimal = maximizeErrors[i].tag; |
| const char* const maximal = maximizeErrors[i].expected; |
| const UErrorCode expectedStatus = maximizeErrors[i].uerror; |
| const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]); |
| const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer)); |
| |
| const int32_t length = |
| uloc_addLikelySubtags( |
| minimal, |
| buffer, |
| bufferSize, |
| &status); |
| |
| if (status == U_ZERO_ERROR) { |
| log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus)); |
| status = U_ZERO_ERROR; |
| } |
| else if (status != expectedStatus) { |
| 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)); |
| } |
| else if (length != expectedLength) { |
| log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length); |
| } |
| else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { |
| if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) { |
| log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n", |
| maximal, minimal, (int)sizeof(buffer), buffer); |
| } |
| } |
| } |
| |
| for (i = 0; i < UPRV_LENGTHOF(minimizeErrors); ++i) { |
| |
| UErrorCode status = U_ZERO_ERROR; |
| const char* const maximal = minimizeErrors[i].tag; |
| const char* const minimal = minimizeErrors[i].expected; |
| const UErrorCode expectedStatus = minimizeErrors[i].uerror; |
| const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]); |
| const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer)); |
| |
| const int32_t length = |
| uloc_minimizeSubtags( |
| maximal, |
| buffer, |
| bufferSize, |
| &status); |
| |
| if (status == U_ZERO_ERROR) { |
| log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus)); |
| status = U_ZERO_ERROR; |
| } |
| else if (status != expectedStatus) { |
| 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)); |
| } |
| else if (length != expectedLength) { |
| log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length); |
| } |
| else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { |
| if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) { |
| log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n", |
| minimal, maximal, (int)sizeof(buffer), buffer); |
| } |
| } |
| } |
| } |
| |
| const char* const locale_to_langtag[][3] = { |
| {"", "und", "und"}, |
| {"en", "en", "en"}, |
| {"en_US", "en-US", "en-US"}, |
| {"iw_IL", "he-IL", "he-IL"}, |
| {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"}, |
| {"en__POSIX", "en-u-va-posix", "en-u-va-posix"}, |
| {"en_POSIX", "en-u-va-posix", "en-u-va-posix"}, |
| {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL}, /* variant POSIX_VAR is processed as regular variant */ |
| {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL}, /* variant VAR_POSIX is processed as regular variant */ |
| {"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 */ |
| {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"}, |
| {"und_555", "und-555", "und-555"}, |
| {"123", "und", NULL}, |
| {"%$#&", "und", NULL}, |
| {"_Latn", "und-Latn", "und-Latn"}, |
| {"_DE", "und-DE", "und-DE"}, |
| {"und_FR", "und-FR", "und-FR"}, |
| {"th_TH_TH", "th-TH-x-lvariant-th", NULL}, |
| {"bogus", "bogus", "bogus"}, |
| {"foooobarrr", "und", NULL}, |
| {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL}, |
| {"en_US_1234", "en-US-1234", "en-US-1234"}, |
| {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"}, |
| {"en_US_VARIANTB_VARIANTA", "en-US-varianta-variantb", "en-US-varianta-variantb"}, /* ICU-20478 */ |
| {"ja__9876_5432", "ja-5432-9876", "ja-5432-9876"}, /* ICU-20478 */ |
| {"sl__ROZAJ_BISKE_1994", "sl-1994-biske-rozaj", "sl-1994-biske-rozaj"}, /* ICU-20478 */ |
| {"en__SCOUSE_FONIPA", "en-fonipa-scouse", "en-fonipa-scouse"}, /* ICU-20478 */ |
| {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL}, |
| {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL}, |
| {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"}, |
| {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"}, |
| {"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"}, |
| {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"}, |
| {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"}, |
| {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL}, |
| {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL}, |
| {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"}, |
| {"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"}, |
| {"@x=elmer", "und-x-elmer", "und-x-elmer"}, |
| {"en@x=elmer", "en-x-elmer", "en-x-elmer"}, |
| {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"}, |
| {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"}, |
| /* #12671 */ |
| {"en@a=bar;attribute=baz", "en-a-bar-u-baz", "en-a-bar-u-baz"}, |
| {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo", "en-a-bar-u-baz-x-u-foo"}, |
| {"en@attribute=baz", "en-u-baz", "en-u-baz"}, |
| {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"}, |
| {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo"}, |
| {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"}, |
| {"en@9=efg;a=baz", "en-9-efg-a-baz", "en-9-efg-a-baz"}, |
| |
| // Before ICU 64, ICU locale canonicalization had some additional mappings. |
| // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants". |
| // The following now uses standard canonicalization. |
| {"az_AZ_CYRL", "az-AZ-x-lvariant-cyrl", NULL}, |
| |
| |
| /* ICU-20310 */ |
| {"en-u-kn-true", "en-u-kn", "en-u-kn"}, |
| {"en-u-kn", "en-u-kn", "en-u-kn"}, |
| {"de-u-co-yes", "de-u-co", "de-u-co"}, |
| {"de-u-co", "de-u-co", "de-u-co"}, |
| {"de@collation=yes", "de-u-co", "de-u-co"}, |
| {"cmn-hans-cn-u-ca-t-ca-x-t-u", "cmn-Hans-CN-t-ca-u-ca-x-t-u", "cmn-Hans-CN-t-ca-u-ca-x-t-u"}, |
| {NULL, NULL, NULL} |
| }; |
| |
| static void TestToLanguageTag(void) { |
| char langtag[256]; |
| int32_t i; |
| UErrorCode status; |
| int32_t len; |
| const char *inloc; |
| const char *expected; |
| |
| for (i = 0; locale_to_langtag[i][0] != NULL; i++) { |
| inloc = locale_to_langtag[i][0]; |
| |
| /* testing non-strict mode */ |
| status = U_ZERO_ERROR; |
| langtag[0] = 0; |
| expected = locale_to_langtag[i][1]; |
| |
| len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status); |
| (void)len; /* Suppress set but not used warning. */ |
| if (U_FAILURE(status)) { |
| if (expected != NULL) { |
| log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n", |
| inloc, u_errorName(status)); |
| } |
| } else { |
| if (expected == NULL) { |
| log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n", |
| inloc, langtag); |
| } else if (uprv_strcmp(langtag, expected) != 0) { |
| log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n", |
| langtag, inloc, expected); |
| } |
| } |
| |
| /* testing strict mode */ |
| status = U_ZERO_ERROR; |
| langtag[0] = 0; |
| expected = locale_to_langtag[i][2]; |
| |
| len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status); |
| if (U_FAILURE(status)) { |
| if (expected != NULL) { |
| log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n", |
| inloc, u_errorName(status)); |
| } |
| } else { |
| if (expected == NULL) { |
| log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n", |
| inloc, langtag); |
| } else if (uprv_strcmp(langtag, expected) != 0) { |
| log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n", |
| langtag, inloc, expected); |
| } |
| } |
| } |
| } |
| |
| static void TestBug20132(void) { |
| char langtag[256]; |
| UErrorCode status; |
| int32_t len; |
| |
| static const char inloc[] = "en-C"; |
| static const char expected[] = "en-x-lvariant-c"; |
| const int32_t expected_len = (int32_t)uprv_strlen(expected); |
| |
| /* Before ICU-20132 was fixed, calling uloc_toLanguageTag() with a too small |
| * buffer would not immediately return the buffer size actually needed, but |
| * instead require several iterations before getting the correct size. */ |
| |
| status = U_ZERO_ERROR; |
| len = uloc_toLanguageTag(inloc, langtag, 1, FALSE, &status); |
| |
| if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) { |
| log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n", |
| inloc, u_errorName(status)); |
| } |
| |
| if (len != expected_len) { |
| log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc, len, expected_len); |
| } |
| |
| status = U_ZERO_ERROR; |
| len = uloc_toLanguageTag(inloc, langtag, expected_len, FALSE, &status); |
| |
| if (U_FAILURE(status)) { |
| log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n", |
| inloc, u_errorName(status)); |
| } |
| |
| if (len != expected_len) { |
| log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc, len, expected_len); |
| } else if (uprv_strncmp(langtag, expected, expected_len) != 0) { |
| log_data_err("uloc_toLanguageTag returned language tag [%.*s] for input locale [%s] - expected: [%s]. Are you missing data?\n", |
| len, langtag, inloc, expected); |
| } |
| } |
| |
| #define FULL_LENGTH -1 |
| static const struct { |
| const char *bcpID; |
| const char *locID; |
| int32_t len; |
| } langtag_to_locale[] = { |
| {"en", "en", FULL_LENGTH}, |
| {"en-us", "en_US", FULL_LENGTH}, |
| {"und-US", "_US", FULL_LENGTH}, |
| {"und-latn", "_Latn", FULL_LENGTH}, |
| {"en-US-posix", "en_US_POSIX", FULL_LENGTH}, |
| {"de-de_euro", "de", 2}, |
| {"kok-IN", "kok_IN", FULL_LENGTH}, |
| {"123", "", 0}, |
| {"en_us", "", 0}, |
| {"en-latn-x", "en_Latn", 7}, |
| {"art-lojban", "jbo", FULL_LENGTH}, |
| {"zh-hakka", "hak", FULL_LENGTH}, |
| {"zh-cmn-CH", "cmn_CH", FULL_LENGTH}, |
| {"zh-cmn-CH-u-co-pinyin", "cmn_CH@collation=pinyin", FULL_LENGTH}, |
| {"xxx-yy", "xxx_YY", FULL_LENGTH}, |
| {"fr-234", "fr_234", FULL_LENGTH}, |
| {"i-default", "en@x=i-default", FULL_LENGTH}, |
| {"i-test", "", 0}, |
| {"ja-jp-jp", "ja_JP", 5}, |
| {"bogus", "bogus", FULL_LENGTH}, |
| {"boguslang", "", 0}, |
| {"EN-lATN-us", "en_Latn_US", FULL_LENGTH}, |
| {"und-variant-1234", "__1234_VARIANT", FULL_LENGTH}, /* ICU-20478 */ |
| {"ja-9876-5432", "ja__5432_9876", FULL_LENGTH}, /* ICU-20478 */ |
| {"en-US-varianta-variantb", "en_US_VARIANTA_VARIANTB", FULL_LENGTH}, /* ICU-20478 */ |
| {"en-US-variantb-varianta", "en_US_VARIANTA_VARIANTB", FULL_LENGTH}, /* ICU-20478 */ |
| {"sl-rozaj-1994-biske", "sl__1994_BISKE_ROZAJ", FULL_LENGTH}, /* ICU-20478 */ |
| {"sl-biske-1994-rozaj", "sl__1994_BISKE_ROZAJ", FULL_LENGTH}, /* ICU-20478 */ |
| {"sl-1994-rozaj-biske", "sl__1994_BISKE_ROZAJ", FULL_LENGTH}, /* ICU-20478 */ |
| {"sl-rozaj-biske-1994", "sl__1994_BISKE_ROZAJ", FULL_LENGTH}, /* ICU-20478 */ |
| {"en-fonipa-scouse", "en__FONIPA_SCOUSE", FULL_LENGTH}, /* ICU-20478 */ |
| {"en-scouse-fonipa", "en__FONIPA_SCOUSE", FULL_LENGTH}, /* ICU-20478 */ |
| {"und-varzero-var1-vartwo", "__VARZERO", 11}, |
| {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH}, |
| {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH}, |
| {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH}, |
| {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH}, |
| {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH}, |
| {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH}, |
| {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH}, |
| {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH}, |
| {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH}, |
| {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH}, |
| {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH}, |
| {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH}, |
| {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH}, |
| {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH}, |
| {"x-elmer", "@x=elmer", FULL_LENGTH}, |
| {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH}, |
| {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH}, |
| {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH}, |
| {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH}, |
| {"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}, |
| {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer", |
| "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91}, |
| {"de-1901-1901", "de__1901", 7}, |
| {"de-DE-1901-1901", "de_DE_1901", 10}, |
| {"en-a-bbb-a-ccc", "en@a=bbb", 8}, |
| /* #12761 */ |
| {"en-a-bar-u-baz", "en@a=bar;attribute=baz", FULL_LENGTH}, |
| {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", FULL_LENGTH}, |
| {"en-u-baz", "en@attribute=baz", FULL_LENGTH}, |
| {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", FULL_LENGTH}, |
| {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", FULL_LENGTH}, |
| {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", FULL_LENGTH}, |
| {"und-Arab-u-em-emoji", "_Arab@em=emoji", FULL_LENGTH}, |
| {"und-Latn-u-em-emoji", "_Latn@em=emoji", FULL_LENGTH}, |
| {"und-Latn-DE-u-em-emoji", "_Latn_DE@em=emoji", FULL_LENGTH}, |
| {"und-Zzzz-DE-u-em-emoji", "_Zzzz_DE@em=emoji", FULL_LENGTH}, |
| {"und-DE-u-em-emoji", "_DE@em=emoji", FULL_LENGTH}, |
| // #20098 |
| {"hant-cmn-cn", "hant", 4}, |
| {"zh-cmn-TW", "cmn_TW", FULL_LENGTH}, |
| {"zh-x_t-ab", "zh", 2}, |
| {"zh-hans-cn-u-ca-x_t-u", "zh_Hans_CN@calendar=yes", 15}, |
| /* #20140 dupe keys in U-extension */ |
| {"zh-u-ca-chinese-ca-gregory", "zh@calendar=chinese", FULL_LENGTH}, |
| {"zh-u-ca-gregory-co-pinyin-ca-chinese", "zh@calendar=gregorian;collation=pinyin", FULL_LENGTH}, |
| {"de-latn-DE-1901-u-co-phonebk-co-pinyin-ca-gregory", "de_Latn_DE_1901@calendar=gregorian;collation=phonebook", FULL_LENGTH}, |
| {"th-u-kf-nu-thai-kf-false", "th@colcasefirst=yes;numbers=thai", FULL_LENGTH}, |
| /* #9562 IANA language tag data update */ |
| {"en-gb-oed", "en_GB_OXENDICT", FULL_LENGTH}, |
| {"i-navajo", "nv", FULL_LENGTH}, |
| {"i-navajo-a-foo", "nv@a=foo", FULL_LENGTH}, |
| {"i-navajo-latn-us", "nv_Latn_US", FULL_LENGTH}, |
| {"sgn-br", "bzs", FULL_LENGTH}, |
| {"sgn-br-u-co-phonebk", "bzs@collation=phonebook", FULL_LENGTH}, |
| {"ja-latn-hepburn-heploc", "ja_Latn__ALALC97", FULL_LENGTH}, |
| {"ja-latn-hepburn-heploc-u-ca-japanese", "ja_Latn__ALALC97@calendar=japanese", FULL_LENGTH}, |
| {"en-a-bcde-0-fgh", "en@0=fgh;a=bcde", FULL_LENGTH}, |
| }; |
| |
| static void TestForLanguageTag(void) { |
| char locale[256]; |
| int32_t i; |
| UErrorCode status; |
| int32_t parsedLen; |
| int32_t expParsedLen; |
| |
| for (i = 0; i < UPRV_LENGTHOF(langtag_to_locale); i++) { |
| status = U_ZERO_ERROR; |
| locale[0] = 0; |
| expParsedLen = langtag_to_locale[i].len; |
| if (expParsedLen == FULL_LENGTH) { |
| expParsedLen = (int32_t)uprv_strlen(langtag_to_locale[i].bcpID); |
| } |
| uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status); |
| if (U_FAILURE(status)) { |
| log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n", |
| langtag_to_locale[i].bcpID, u_errorName(status)); |
| } else { |
| if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) { |
| log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n", |
| locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID); |
| } |
| if (parsedLen != expParsedLen) { |
| log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n", |
| parsedLen, langtag_to_locale[i].bcpID, expParsedLen); |
| } |
| } |
| } |
| } |
| |
| static const struct { |
| const char *input; |
| const char *canonical; |
| } langtag_to_canonical[] = { |
| {"de-DD", "de-DE"}, |
| {"de-DD-u-co-phonebk", "de-DE-u-co-phonebk"}, |
| {"jw-id", "jv-ID"}, |
| {"jw-id-u-ca-islamic-civil", "jv-ID-u-ca-islamic-civil"}, |
| {"mo-md", "ro-MD"}, |
| {"my-bu-u-nu-mymr", "my-MM-u-nu-mymr"}, |
| {"yuu-ru", "yug-RU"}, |
| }; |
| |
| |
| static void TestLangAndRegionCanonicalize(void) { |
| char locale[256]; |
| char canonical[256]; |
| int32_t i; |
| UErrorCode status; |
| for (i = 0; i < UPRV_LENGTHOF(langtag_to_canonical); i++) { |
| status = U_ZERO_ERROR; |
| const char* input = langtag_to_canonical[i].input; |
| uloc_forLanguageTag(input, locale, sizeof(locale), NULL, &status); |
| uloc_toLanguageTag(locale, canonical, sizeof(canonical), TRUE, &status); |
| if (U_FAILURE(status)) { |
| log_err_status(status, "Error returned by uloc_forLanguageTag or uloc_toLanguageTag " |
| "for language tag [%s] - error: %s\n", input, u_errorName(status)); |
| } else { |
| const char* expected_canonical = langtag_to_canonical[i].canonical; |
| if (uprv_strcmp(expected_canonical, canonical) != 0) { |
| log_data_err("input language tag [%s] is canonicalized to [%s] - expected: [%s]\n", |
| input, canonical, expected_canonical); |
| } |
| } |
| } |
| } |
| |
| static void TestToUnicodeLocaleKey(void) |
| { |
| /* $IN specifies the result should be the input pointer itself */ |
| static const char* DATA[][2] = { |
| {"calendar", "ca"}, |
| {"CALEndar", "ca"}, /* difference casing */ |
| {"ca", "ca"}, /* bcp key itself */ |
| {"kv", "kv"}, /* no difference between legacy and bcp */ |
| {"foo", NULL}, /* unknown, bcp ill-formed */ |
| {"ZZ", "$IN"}, /* unknown, bcp well-formed - */ |
| {NULL, NULL} |
| }; |
| |
| int32_t i; |
| for (i = 0; DATA[i][0] != NULL; i++) { |
| const char* keyword = DATA[i][0]; |
| const char* expected = DATA[i][1]; |
| const char* bcpKey = NULL; |
| |
| bcpKey = uloc_toUnicodeLocaleKey(keyword); |
| if (expected == NULL) { |
| if (bcpKey != NULL) { |
| log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey); |
| } |
| } else if (bcpKey == NULL) { |
| log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected); |
| } else if (uprv_strcmp(expected, "$IN") == 0) { |
| if (bcpKey != keyword) { |
| log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword); |
| } |
| } else if (uprv_strcmp(bcpKey, expected) != 0) { |
| log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected); |
| } |
| } |
| } |
| |
| static void TestBug20321UnicodeLocaleKey(void) |
| { |
| // key = alphanum alpha ; |
| static const char* invalid[] = { |
| "a0", |
| "00", |
| "a@", |
| "0@", |
| "@a", |
| "@a", |
| "abc", |
| "0bc", |
| }; |
| for (int i = 0; i < UPRV_LENGTHOF(invalid); i++) { |
| const char* bcpKey = NULL; |
| bcpKey = uloc_toUnicodeLocaleKey(invalid[i]); |
| if (bcpKey != NULL) { |
| log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", invalid[i], bcpKey); |
| } |
| } |
| static const char* valid[] = { |
| "aa", |
| "0a", |
| }; |
| for (int i = 0; i < UPRV_LENGTHOF(valid); i++) { |
| const char* bcpKey = NULL; |
| bcpKey = uloc_toUnicodeLocaleKey(valid[i]); |
| if (bcpKey == NULL) { |
| log_err("toUnicodeLocaleKey: keyword=%s => NULL, expected!=NULL\n", valid[i]); |
| } |
| } |
| } |
| |
| static void TestToLegacyKey(void) |
| { |
| /* $IN specifies the result should be the input pointer itself */ |
| static const char* DATA[][2] = { |
| {"kb", "colbackwards"}, |
| {"kB", "colbackwards"}, /* different casing */ |
| {"Collation", "collation"}, /* keyword itself with different casing */ |
| {"kv", "kv"}, /* no difference between legacy and bcp */ |
| {"foo", "$IN"}, /* unknown, bcp ill-formed */ |
| {"ZZ", "$IN"}, /* unknown, bcp well-formed */ |
| {"e=mc2", NULL}, /* unknown, bcp/legacy ill-formed */ |
| {NULL, NULL} |
| }; |
| |
| int32_t i; |
| for (i = 0; DATA[i][0] != NULL; i++) { |
| const char* keyword = DATA[i][0]; |
| const char* expected = DATA[i][1]; |
| const char* legacyKey = NULL; |
| |
| legacyKey = uloc_toLegacyKey(keyword); |
| if (expected == NULL) { |
| if (legacyKey != NULL) { |
| log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey); |
| } |
| } else if (legacyKey == NULL) { |
| log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected); |
| } else if (uprv_strcmp(expected, "$IN") == 0) { |
| if (legacyKey != keyword) { |
| log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword); |
| } |
| } else if (uprv_strcmp(legacyKey, expected) != 0) { |
| log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected); |
| } |
| } |
| } |
| |
| static void TestToUnicodeLocaleType(void) |
| { |
| /* $IN specifies the result should be the input pointer itself */ |
| static const char* DATA[][3] = { |
| {"tz", "Asia/Kolkata", "inccu"}, |
| {"calendar", "gregorian", "gregory"}, |
| {"ca", "gregorian", "gregory"}, |
| {"ca", "Gregorian", "gregory"}, |
| {"ca", "buddhist", "buddhist"}, |
| {"Calendar", "Japanese", "japanese"}, |
| {"calendar", "Islamic-Civil", "islamic-civil"}, |
| {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */ |
| {"colalternate", "NON-IGNORABLE", "noignore"}, |
| {"colcaselevel", "yes", "true"}, |
| {"rg", "GBzzzz", "$IN"}, |
| {"tz", "america/new_york", "usnyc"}, |
| {"tz", "Asia/Kolkata", "inccu"}, |
| {"timezone", "navajo", "usden"}, |
| {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */ |
| {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */ |
| {"zz", "gregorian", NULL}, /* unknown key, ill-formed type */ |
| {"co", "foo-", NULL}, /* unknown type, ill-formed type */ |
| {"variableTop", "00A0", "$IN"}, /* valid codepoints type */ |
| {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */ |
| {"kr", "space-punct", "space-punct"}, /* valid reordercode type */ |
| {"kr", "digit-spacepunct", NULL}, /* invalid (bcp ill-formed) reordercode type */ |
| {NULL, NULL, NULL} |
| }; |
| |
| int32_t i; |
| for (i = 0; DATA[i][0] != NULL; i++) { |
| const char* keyword = DATA[i][0]; |
| const char* value = DATA[i][1]; |
| const char* expected = DATA[i][2]; |
| const char* bcpType = NULL; |
| |
| bcpType = uloc_toUnicodeLocaleType(keyword, value); |
| if (expected == NULL) { |
| if (bcpType != NULL) { |
| log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType); |
| } |
| } else if (bcpType == NULL) { |
| log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected); |
| } else if (uprv_strcmp(expected, "$IN") == 0) { |
| if (bcpType != value) { |
| log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value); |
| } |
| } else if (uprv_strcmp(bcpType, expected) != 0) { |
| log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected); |
| } |
| } |
| } |
| |
| static void TestToLegacyType(void) |
| { |
| /* $IN specifies the result should be the input pointer itself */ |
| static const char* DATA[][3] = { |
| {"calendar", "gregory", "gregorian"}, |
| {"ca", "gregory", "gregorian"}, |
| {"ca", "Gregory", "gregorian"}, |
| {"ca", "buddhist", "buddhist"}, |
| {"Calendar", "Japanese", "japanese"}, |
| {"calendar", "Islamic-Civil", "islamic-civil"}, |
| {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */ |
| {"colalternate", "noignore", "non-ignorable"}, |
| {"colcaselevel", "true", "yes"}, |
| {"rg", "gbzzzz", "gbzzzz"}, |
| {"tz", "usnyc", "America/New_York"}, |
| {"tz", "inccu", "Asia/Calcutta"}, |
| {"timezone", "usden", "America/Denver"}, |
| {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */ |
| {"colstrength", "quarternary", "quaternary"}, /* type alias */ |
| {"ca", "aaaa", "$IN"}, /* unknown type */ |
| {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */ |
| {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */ |
| {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */ |
| {"co", "e=mc2", NULL}, /* known key, ill-formed bcp/legacy type */ |
| {"variableTop", "00A0", "$IN"}, /* valid codepoints type */ |
| {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */ |
| {"kr", "space-punct", "space-punct"}, /* valid reordercode type */ |
| {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */ |
| {NULL, NULL, NULL} |
| }; |
| |
| int32_t i; |
| for (i = 0; DATA[i][0] != NULL; i++) { |
| const char* keyword = DATA[i][0]; |
| const char* value = DATA[i][1]; |
| const char* expected = DATA[i][2]; |
| const char* legacyType = NULL; |
| |
| legacyType = uloc_toLegacyType(keyword, value); |
| if (expected == NULL) { |
| if (legacyType != NULL) { |
| log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType); |
| } |
| } else if (legacyType == NULL) { |
| log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected); |
| } else if (uprv_strcmp(expected, "$IN") == 0) { |
| if (legacyType != value) { |
| log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value); |
| } |
| } else if (uprv_strcmp(legacyType, expected) != 0) { |
| log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected); |
| } else { |
| log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword, value, legacyType); |
| } |
| } |
| } |
| |
| |
| |
| static void test_unicode_define(const char *namech, char ch, |
| const char *nameu, UChar uch) |
| { |
| UChar asUch[1]; |
| asUch[0]=0; |
| log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", |
| namech, ch,(int)ch, nameu, (int) uch); |
| u_charsToUChars(&ch, asUch, 1); |
| if(asUch[0] != uch) { |
| 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); |
| } else { |
| log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]); |
| } |
| } |
| |
| static void checkTerminating(const char* locale, const char* inLocale) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t preflight_length = uloc_getDisplayName( |
| locale, inLocale, NULL, 0, &status); |
| if (status != U_BUFFER_OVERFLOW_ERROR) { |
| log_err("uloc_getDisplayName(%s, %s) preflight failed", |
| locale, inLocale); |
| } |
| UChar buff[256]; |
| const UChar sentinel1 = 0x6C38; // 永- a Han unicode as sentinel. |
| const UChar sentinel2 = 0x92D2; // 鋒- a Han unicode as sentinel. |
| |
| // 1. Test when we set the maxResultSize to preflight_length + 1. |
| // Set sentinel1 in the buff[preflight_length-1] to check it will be |
| // replaced with display name. |
| buff[preflight_length-1] = sentinel1; |
| // Set sentinel2 in the buff[preflight_length] to check it will be |
| // replaced by null. |
| buff[preflight_length] = sentinel2; |
| // It should be properly null terminated at buff[preflight_length]. |
| status = U_ZERO_ERROR; |
| int32_t length = uloc_getDisplayName( |
| locale, inLocale, buff, preflight_length + 1, &status); |
| const char* result = U_SUCCESS(status) ? |
| aescstrdup(buff, length) : "(undefined when failure)"; |
| if (length != preflight_length) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 returns " |
| "length %d different from preflight length %d. Returns '%s'\n", |
| locale, inLocale, length, preflight_length, result); |
| } |
| if (U_ZERO_ERROR != status) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 should " |
| "set status to U_ZERO_ERROR but got %d %s. Returns %s\n", |
| locale, inLocale, status, myErrorName(status), result); |
| } |
| if (buff[length-1] == sentinel1) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 does " |
| "not change memory in the end of buffer while it should. " |
| "Returns %s\n", |
| locale, inLocale, result); |
| } |
| if (buff[length] != 0x0000) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length+1 should " |
| "null terminate at buff[length] but does not %x. Returns %s\n", |
| locale, inLocale, buff[length], result); |
| } |
| |
| // 2. Test when we only set the maxResultSize to preflight_length. |
| |
| // Set sentinel1 in the buff[preflight_length-1] to check it will be |
| // replaced with display name. |
| buff[preflight_length-1] = sentinel1; |
| // Set sentinel2 in the buff[preflight_length] to check it won't be replaced |
| // by null. |
| buff[preflight_length] = sentinel2; |
| status = U_ZERO_ERROR; |
| length = uloc_getDisplayName( |
| locale, inLocale, buff, preflight_length, &status); |
| result = U_SUCCESS(status) ? |
| aescstrdup(buff, length) : "(undefined when failure)"; |
| |
| if (length != preflight_length) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length return " |
| "length %d different from preflight length %d. Returns '%s'\n", |
| locale, inLocale, length, preflight_length, result); |
| } |
| if (U_STRING_NOT_TERMINATED_WARNING != status) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length should " |
| "set status to U_STRING_NOT_TERMINATED_WARNING but got %d %s. " |
| "Returns %s\n", |
| locale, inLocale, status, myErrorName(status), result); |
| } |
| if (buff[length-1] == sentinel1) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length does not " |
| "change memory in the end of buffer while it should. Returns " |
| "'%s'\n", |
| locale, inLocale, result); |
| } |
| if (buff[length] != sentinel2) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length change " |
| "memory beyond maxResultSize to %x. Returns '%s'\n", |
| locale, inLocale, buff[length], result); |
| } |
| if (buff[preflight_length - 1] == 0x0000) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length null " |
| "terminated while it should not. Return '%s'\n", |
| locale, inLocale, result); |
| } |
| |
| // 3. Test when we only set the maxResultSize to preflight_length-1. |
| // Set sentinel1 in the buff[preflight_length-1] to check it will not be |
| // replaced with display name. |
| buff[preflight_length-1] = sentinel1; |
| // Set sentinel2 in the buff[preflight_length] to check it won't be replaced |
| // by null. |
| buff[preflight_length] = sentinel2; |
| status = U_ZERO_ERROR; |
| length = uloc_getDisplayName( |
| locale, inLocale, buff, preflight_length - 1, &status); |
| result = U_SUCCESS(status) ? |
| aescstrdup(buff, length) : "(undefined when failure)"; |
| |
| if (length != preflight_length) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 return " |
| "length %d different from preflight length %d. Returns '%s'\n", |
| locale, inLocale, length, preflight_length, result); |
| } |
| if (U_BUFFER_OVERFLOW_ERROR != status) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 should " |
| "set status to U_BUFFER_OVERFLOW_ERROR but got %d %s. " |
| "Returns %s\n", |
| locale, inLocale, status, myErrorName(status), result); |
| } |
| if (buff[length-1] != sentinel1) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 should " |
| "not change memory in beyond the maxResultSize. Returns '%s'\n", |
| locale, inLocale, result); |
| } |
| if (buff[length] != sentinel2) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 change " |
| "memory beyond maxResultSize to %x. Returns '%s'\n", |
| locale, inLocale, buff[length], result); |
| } |
| if (buff[preflight_length - 2] == 0x0000) { |
| log_err("uloc_getDisplayName(%s, %s) w/ maxResultSize=length-1 null " |
| "terminated while it should not. Return '%s'\n", |
| locale, inLocale, result); |
| } |
| } |
| |
| static void Test21157CorrectTerminating(void) { |
| checkTerminating("fr", "fr"); |
| checkTerminating("fr_BE", "fr"); |
| checkTerminating("fr_Latn_BE", "fr"); |
| checkTerminating("fr_Latn", "fr"); |
| checkTerminating("fr", "fr"); |
| checkTerminating("fr-CN", "fr"); |
| checkTerminating("fr-Hant-CN", "fr"); |
| checkTerminating("fr-Hant", "fr"); |
| checkTerminating("zh-u-co-pinyin", "fr"); |
| } |
| |
| #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y)) |
| |
| static void TestUnicodeDefines(void) { |
| TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE); |
| TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE); |
| TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE); |
| } |
| |
| static void TestIsRightToLeft() { |
| // API test only. More test cases in intltest/LocaleTest. |
| if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) { |
| log_err("uloc_isRightToLeft() failed"); |
| } |
| } |
| |
| typedef struct { |
| const char * badLocaleID; |
| const char * displayLocale; |
| const char * expectedName; |
| UErrorCode expectedStatus; |
| } BadLocaleItem; |
| |
| static const BadLocaleItem badLocaleItems[] = { |
| { "-9223372036854775808", "en", "Unknown language (9223372036854775808)", U_USING_DEFAULT_WARNING }, |
| /* add more in the future */ |
| { NULL, NULL, NULL, U_ZERO_ERROR } /* terminator */ |
| }; |
| |
| enum { kUBufDispNameMax = 128, kBBufDispNameMax = 256 }; |
| |
| static void TestBadLocaleIDs() { |
| const BadLocaleItem* itemPtr; |
| for (itemPtr = badLocaleItems; itemPtr->badLocaleID != NULL; itemPtr++) { |
| UChar ubufExpect[kUBufDispNameMax], ubufGet[kUBufDispNameMax]; |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t ulenExpect = u_unescape(itemPtr->expectedName, ubufExpect, kUBufDispNameMax); |
| int32_t ulenGet = uloc_getDisplayName(itemPtr->badLocaleID, itemPtr->displayLocale, ubufGet, kUBufDispNameMax, &status); |
| if (status != itemPtr->expectedStatus || |
| (U_SUCCESS(status) && (ulenGet != ulenExpect || u_strncmp(ubufGet, ubufExpect, ulenExpect) != 0))) { |
| char bbufExpect[kBBufDispNameMax], bbufGet[kBBufDispNameMax]; |
| u_austrncpy(bbufExpect, ubufExpect, ulenExpect); |
| u_austrncpy(bbufGet, ubufGet, ulenGet); |
| log_err("FAIL: For localeID %s, displayLocale %s, calling uloc_getDisplayName:\n" |
| " expected status %-26s, name (len %2d): %s\n" |
| " got status %-26s, name (len %2d): %s\n", |
| itemPtr->badLocaleID, itemPtr->displayLocale, |
| u_errorName(itemPtr->expectedStatus), ulenExpect, bbufExpect, |
| u_errorName(status), ulenGet, bbufGet ); |
| } |
| } |
| } |
| |
| // Test case for ICU-20370. |
| // The issue shows as an Address Sanitizer failure. |
| static void TestBug20370() { |
| const char *localeID = "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar"; |
| uint32_t lcid = uloc_getLCID(localeID); |
| if (lcid != 0) { |
| log_err("FAIL: Expected LCID value of 0 for invalid localeID input."); |
| } |
| } |
| |
| // Test case for ICU-20149 |
| // Handle the duplicate U extension attribute |
| static void TestBug20149() { |
| const char *localeID = "zh-u-foo-foo-co-pinyin"; |
| char locale[256]; |
| UErrorCode status = U_ZERO_ERROR; |
| int32_t parsedLen; |
| locale[0] = '\0'; |
| uloc_forLanguageTag(localeID, locale, sizeof(locale), &parsedLen, &status); |
| if (U_FAILURE(status) || |
| 0 !=strcmp("zh@attribute=foo;collation=pinyin", locale)) { |
| log_err("ERROR: in uloc_forLanguageTag %s return %s\n", myErrorName(status), locale); |
| } |
| } |
| |
| #if !UCONFIG_NO_FORMATTING |
| typedef enum UldnNameType { |
| TEST_ULDN_LOCALE, |
| TEST_ULDN_LANGUAGE, |
| TEST_ULDN_SCRIPT, |
| TEST_ULDN_REGION, |
| TEST_ULOC_LOCALE, // only valid with optStdMidLong |
| TEST_ULOC_LANGUAGE, // only valid with optStdMidLong |
| TEST_ULOC_SCRIPT, // only valid with optStdMidLong |
| TEST_ULOC_REGION, // only valid with optStdMidLong |
| } UldnNameType; |
| |
| typedef struct { |
| const char * localeToName; // NULL to terminate a list of these |
| UldnNameType nameType; |
| const UChar * expectResult; |
| } UldnItem; |
| |
| typedef struct { |
| const char * displayLocale; |
| const UDisplayContext * displayOptions; // set of 3 UDisplayContext items |
| const UldnItem * testItems; |
| int32_t countItems; |
| } UldnLocAndOpts; |
| |
| static const UDisplayContext optStdMidLong[3] = {UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDISPCTX_LENGTH_FULL}; |
| static const UDisplayContext optStdMidShrt[3] = {UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDISPCTX_LENGTH_SHORT}; |
| static const UDisplayContext optDiaMidLong[3] = {UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDISPCTX_LENGTH_FULL}; |
| static const UDisplayContext optDiaMidShrt[3] = {UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDISPCTX_LENGTH_SHORT}; |
| |
| static const UldnItem en_StdMidLong[] = { |
| { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, |
| { "en", TEST_ULDN_LANGUAGE, u"English" }, |
| { "en_US", TEST_ULOC_LOCALE, u"English (United States)" }, |
| { "en_US", TEST_ULOC_LANGUAGE, u"English" }, |
| { "en", TEST_ULOC_LANGUAGE, u"English" }, |
| // https://unicode-org.atlassian.net/browse/ICU-20870 |
| { "fa_AF", TEST_ULDN_LOCALE, u"Persian (Afghanistan)" }, |
| { "prs", TEST_ULDN_LOCALE, u"Dari" }, |
| { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, |
| { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, |
| { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, |
| { "prs", TEST_ULOC_LANGUAGE, u"Dari" }, |
| // https://unicode-org.atlassian.net/browse/ICU-21742 |
| { "ji", TEST_ULDN_LOCALE, u"Yiddish" }, |
| { "ji_US", TEST_ULDN_LOCALE, u"Yiddish (United States)" }, |
| { "ji", TEST_ULDN_LANGUAGE, u"Yiddish" }, |
| { "ji_US", TEST_ULOC_LOCALE, u"Yiddish (United States)" }, |
| { "ji", TEST_ULOC_LANGUAGE, u"Yiddish" }, |
| // https://unicode-org.atlassian.net/browse/ICU-11563 |
| { "mo", TEST_ULDN_LOCALE, u"Romanian" }, |
| { "mo_MD", TEST_ULDN_LOCALE, u"Romanian (Moldova)" }, |
| { "mo", TEST_ULDN_LANGUAGE, u"Romanian" }, |
| { "mo_MD", TEST_ULOC_LOCALE, u"Romanian (Moldova)" }, |
| { "mo", TEST_ULOC_LANGUAGE, u"Romanian" }, |
| }; |
| |
| static const UldnItem en_StdMidShrt[] = { |
| { "en_US", TEST_ULDN_LOCALE, u"English (US)" }, |
| { "en", TEST_ULDN_LANGUAGE, u"English" }, |
| }; |
| |
| static const UldnItem en_DiaMidLong[] = { |
| { "en_US", TEST_ULDN_LOCALE, u"American English" }, |
| { "fa_AF", TEST_ULDN_LOCALE, u"Dari" }, |
| { "prs", TEST_ULDN_LOCALE, u"Dari" }, |
| { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, |
| { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, |
| { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, |
| { "mo", TEST_ULDN_LOCALE, u"Romanian" }, |
| { "mo", TEST_ULDN_LANGUAGE, u"Romanian" }, |
| }; |
| |
| static const UldnItem en_DiaMidShrt[] = { |
| { "en_US", TEST_ULDN_LOCALE, u"US English" }, |
| }; |
| |
| static const UldnItem ro_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-11563 |
| { "mo", TEST_ULDN_LOCALE, u"română" }, |
| { "mo_MD", TEST_ULDN_LOCALE, u"română (Republica Moldova)" }, |
| { "mo", TEST_ULDN_LANGUAGE, u"română" }, |
| { "mo_MD", TEST_ULOC_LOCALE, u"română (Republica Moldova)" }, |
| { "mo", TEST_ULOC_LANGUAGE, u"română" }, |
| }; |
| |
| static const UldnItem yi_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-21742 |
| { "ji", TEST_ULDN_LOCALE, u"ייִדיש" }, |
| { "ji_US", TEST_ULDN_LOCALE, u"ייִדיש (פֿאַראייניגטע שטאַטן)" }, |
| { "ji", TEST_ULDN_LANGUAGE, u"ייִדיש" }, |
| { "ji_US", TEST_ULOC_LOCALE, u"ייִדיש (פֿאַראייניגטע שטאַטן)" }, |
| { "ji", TEST_ULOC_LANGUAGE, u"ייִדיש" }, |
| }; |
| |
| static const UldnLocAndOpts uldnLocAndOpts[] = { |
| { "en", optStdMidLong, en_StdMidLong, UPRV_LENGTHOF(en_StdMidLong) }, |
| { "en", optStdMidShrt, en_StdMidShrt, UPRV_LENGTHOF(en_StdMidShrt) }, |
| { "en", optDiaMidLong, en_DiaMidLong, UPRV_LENGTHOF(en_DiaMidLong) }, |
| { "en", optDiaMidShrt, en_DiaMidShrt, UPRV_LENGTHOF(en_DiaMidShrt) }, |
| { "ro", optStdMidLong, ro_StdMidLong, UPRV_LENGTHOF(ro_StdMidLong) }, |
| { "yi", optStdMidLong, yi_StdMidLong, UPRV_LENGTHOF(yi_StdMidLong) }, |
| { NULL, NULL, NULL, 0 } |
| }; |
| |
| enum { kUNameBuf = 128, kBNameBuf = 256 }; |
| |
| static void TestUldnNameVariants() { |
| const UldnLocAndOpts * uloPtr; |
| for (uloPtr = uldnLocAndOpts; uloPtr->displayLocale != NULL; uloPtr++) { |
| UErrorCode status = U_ZERO_ERROR; |
| ULocaleDisplayNames * uldn = uldn_openForContext(uloPtr->displayLocale, (UDisplayContext*)uloPtr->displayOptions, 3, &status); |
| if (U_FAILURE(status)) { |
| log_data_err("uldn_openForContext fails, displayLocale %s, contexts %03X %03X %03X: %s - Are you missing data?\n", |
| uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2], |
| u_errorName(status) ); |
| continue; |
| } |
| // API coverage: Expect to get back the dialect handling which is |
| // the first item in the displayOptions test data. |
| UDialectHandling dh = uldn_getDialectHandling(uldn); |
| UDisplayContext dhContext = (UDisplayContext)dh; // same numeric values |
| if (dhContext != uloPtr->displayOptions[0]) { |
| log_err("uldn_getDialectHandling()=%03X != expected UDisplayContext %03X\n", |
| dhContext, uloPtr->displayOptions[0]); |
| } |
| const UldnItem * itemPtr = uloPtr->testItems; |
| int32_t itemCount = uloPtr->countItems; |
| for (; itemCount-- > 0; itemPtr++) { |
| UChar uget[kUNameBuf]; |
| int32_t ulenget, ulenexp; |
| const char* typeString; |
| status = U_ZERO_ERROR; |
| switch (itemPtr->nameType) { |
| case TEST_ULDN_LOCALE: |
| ulenget = uldn_localeDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status); |
| typeString = "uldn_localeDisplayName"; |
| break; |
| case TEST_ULDN_LANGUAGE: |
| ulenget = uldn_languageDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status); |
| typeString = "uldn_languageDisplayName"; |
| break; |
| case TEST_ULDN_SCRIPT: |
| ulenget = uldn_scriptDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status); |
| typeString = "uldn_scriptDisplayName"; |
| break; |
| case TEST_ULDN_REGION: |
| ulenget = uldn_regionDisplayName(uldn, itemPtr->localeToName, uget, kUNameBuf, &status); |
| typeString = "uldn_regionDisplayName"; |
| break; |
| case TEST_ULOC_LOCALE: |
| ulenget = uloc_getDisplayName(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status); |
| typeString = "uloc_getDisplayName"; |
| break; |
| case TEST_ULOC_LANGUAGE: |
| ulenget = uloc_getDisplayLanguage(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status); |
| typeString = "uloc_getDisplayLanguage"; |
| break; |
| case TEST_ULOC_SCRIPT: |
| ulenget = uloc_getDisplayScript(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status); |
| typeString = "uloc_getDisplayScript"; |
| break; |
| case TEST_ULOC_REGION: |
| ulenget = uloc_getDisplayCountry(itemPtr->localeToName, uloPtr->displayLocale, uget, kUNameBuf, &status); |
| typeString = "uloc_getDisplayCountry"; |
| break; |
| default: |
| continue; |
| } |
| if (U_FAILURE(status)) { |
| log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s: %s\n", |
| typeString, uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2], |
| itemPtr->localeToName, u_errorName(status) ); |
| continue; |
| } |
| ulenexp = u_strlen(itemPtr->expectResult); |
| if (ulenget != ulenexp || u_strncmp(uget, itemPtr->expectResult, ulenexp) != 0) { |
| char bexp[kBNameBuf], bget[kBNameBuf]; |
| u_strToUTF8(bexp, kBNameBuf, NULL, itemPtr->expectResult, ulenexp, &status); |
| u_strToUTF8(bget, kBNameBuf, NULL, uget, ulenget, &status); |
| log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s:\n expect %2d: %s\n get %2d: %s\n", |
| typeString, uloPtr->displayLocale, uloPtr->displayOptions[0], uloPtr->displayOptions[1], uloPtr->displayOptions[2], |
| itemPtr->localeToName, ulenexp, bexp, ulenget, bget ); |
| } |
| } |
| |
| uldn_close(uldn); |
| } |
| } |
| #endif |
| |
| static void TestUsingDefaultWarning() { |
| UChar buff[256]; |
| char errorOutputBuff[256]; |
| UErrorCode status = U_ZERO_ERROR; |
| const char* language = "jJj"; |
| int32_t length = uloc_getDisplayLanguage(language, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"jjj") != 0 || |
| length != 3) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayLanguage %s return len:%d %s with status %d %s\n", |
| language, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| const char* script = "und-lALA"; |
| length = uloc_getDisplayScript(script, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"Lala") != 0 || |
| length != 4) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayScript %s return len:%d %s with status %d %s\n", |
| script, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| const char* region = "und-wt"; |
| length = uloc_getDisplayCountry(region, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"WT") != 0 || |
| length != 2) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayCountry %s return len:%d %s with status %d %s\n", |
| region, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| const char* variant = "und-abcde"; |
| length = uloc_getDisplayVariant(variant, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"ABCDE") != 0 || |
| length != 5) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayVariant %s return len:%d %s with status %d %s\n", |
| variant, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| const char* keyword = "postCODE"; |
| length = uloc_getDisplayKeyword(keyword, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"postCODE") != 0 || |
| length != 8) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayKeyword %s return len:%d %s with status %d %s\n", |
| keyword, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| |
| status = U_ZERO_ERROR; |
| const char* keyword_value = "de_DE@postCode=fOObAR"; |
| length = uloc_getDisplayKeywordValue(keyword_value, keyword, "de", buff, 256, &status); |
| if (status != U_USING_DEFAULT_WARNING || |
| u_strcmp(buff, u"fOObAR") != 0 || |
| length != 6) { |
| u_UCharsToChars(buff, errorOutputBuff, length+1); |
| log_err("ERROR: in uloc_getDisplayKeywordValue %s %s return len:%d %s with status %d %s\n", |
| keyword_value, keyword, length, errorOutputBuff, status, myErrorName(status)); |
| } |
| } |
| |
| // Test case for ICU-20575 |
| // This test checks if the environment variable LANG is set, |
| // and if so ensures that both C and C.UTF-8 cause ICU's default locale to be en_US_POSIX. |
| static void TestCDefaultLocale() { |
| const char *defaultLocale = uloc_getDefault(); |
| char *env_var = getenv("LANG"); |
| if (env_var == NULL) { |
| log_verbose("Skipping TestCDefaultLocale test, as the LANG variable is not set."); |
| return; |
| } |
| if ((strcmp(env_var, "C") == 0 || strcmp(env_var, "C.UTF-8") == 0) && strcmp(defaultLocale, "en_US_POSIX") != 0) { |
| log_err("The default locale for LANG=%s should be en_US_POSIX, not %s\n", env_var, defaultLocale); |
| } |
| } |
| |
| // Test case for ICU-21449 |
| static void TestBug21449InfiniteLoop() { |
| UErrorCode status = U_ZERO_ERROR; |
| const char* invalidLocaleId = RES_PATH_SEPARATOR_S; |
| |
| // The issue causes an infinite loop to occur when looking up a non-existent resource for the invalid locale ID, |
| // so the test is considered passed if the call to the API below returns anything at all. |
| uloc_getDisplayLanguage(invalidLocaleId, invalidLocaleId, NULL, 0, &status); |
| } |
| |
| // rdar://79296849 and https://unicode-org.atlassian.net/browse/ICU-21639 |
| static void TestExcessivelyLongIDs(void) { |
| const char* reallyLongID = |
| "de-u-cu-eur-em-default-hc-h23-ks-level1-lb-strict-lw-normal-ms-metric" |
| "-nu-latn-rg-atzzzz-sd-atat1-ss-none-tz-atvie-va-posix"; |
| char minimizedID[ULOC_FULLNAME_CAPACITY]; |
| char maximizedID[ULOC_FULLNAME_CAPACITY]; |
| int32_t actualMinimizedLength = 0; |
| int32_t actualMaximizedLength = 0; |
| UErrorCode err = U_ZERO_ERROR; |
| |
| actualMinimizedLength = uloc_minimizeSubtags(reallyLongID, minimizedID, ULOC_FULLNAME_CAPACITY, &err); |
| assertTrue("uloc_minimizeSubtags() with too-small buffer didn't fail as expected", |
| U_FAILURE(err) && actualMinimizedLength > ULOC_FULLNAME_CAPACITY); |
| |
| err = U_ZERO_ERROR; |
| actualMaximizedLength = uloc_addLikelySubtags(reallyLongID, maximizedID, ULOC_FULLNAME_CAPACITY, &err); |
| assertTrue("uloc_addLikelySubtags() with too-small buffer didn't fail as expected", |
| U_FAILURE(err) && actualMaximizedLength > ULOC_FULLNAME_CAPACITY); |
| |
| err = U_ZERO_ERROR; |
| char* realMinimizedID = (char*)uprv_malloc(actualMinimizedLength + 1); |
| uloc_minimizeSubtags(reallyLongID, realMinimizedID, actualMinimizedLength + 1, &err); |
| if (assertSuccess("uloc_minimizeSubtags() failed", &err)) { |
| assertEquals("Wrong result from uloc_minimizeSubtags()", |
| "de__POSIX@colstrength=primary;currency=eur;em=default;hours=h23;lb=strict;" |
| "lw=normal;measure=metric;numbers=latn;rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna", |
| realMinimizedID); |
| } |
| uprv_free(realMinimizedID); |
| |
| char* realMaximizedID = (char*)uprv_malloc(actualMaximizedLength + 1); |
| uloc_addLikelySubtags(reallyLongID, realMaximizedID, actualMaximizedLength + 1, &err); |
| if (assertSuccess("uloc_addLikelySubtags() failed", &err)) { |
| assertEquals("Wrong result from uloc_addLikelySubtags()", |
| "de_Latn_DE_POSIX@colstrength=primary;currency=eur;em=default;hours=h23;lb=strict;" |
| "lw=normal;measure=metric;numbers=latn;rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna", |
| realMaximizedID); |
| } |
| uprv_free(realMaximizedID); |
| } |