1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /*****************************************************************************
12 * Modification History:
14 * Madhu Katragadda Ported for C API
15 ******************************************************************************
29 #include "unicode/putil.h"
30 #include "unicode/ubrk.h"
31 #include "unicode/uchar.h"
32 #include "unicode/ucol.h"
33 #include "unicode/udat.h"
34 #include "unicode/uloc.h"
35 #include "unicode/umsg.h"
36 #include "unicode/ures.h"
37 #include "unicode/uset.h"
38 #include "unicode/ustring.h"
39 #include "unicode/utypes.h"
40 #include "unicode/ulocdata.h"
41 #include "unicode/uldnames.h"
42 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
44 #if !U_PLATFORM_HAS_WIN32_API
45 #include "unicode/ualoc.h" /* Apple-specific */
48 static void TestNullDefault(void);
49 static void TestNonexistentLanguageExemplars(void);
50 static void TestLocDataErrorCodeChaining(void);
51 static void TestLocDataWithRgTag(void);
52 static void TestLanguageExemplarsFallbacks(void);
53 static void TestDisplayNameBrackets(void);
55 static void TestUnicodeDefines(void);
57 static void TestIsRightToLeft(void);
58 static void TestBadLocaleIDs(void);
59 static void TestBug20370(void);
60 static void TestBug20321UnicodeLocaleKey(void);
62 static void TestUldnNameVariants(void);
63 static void TestRootUndEmpty(void);
64 #if !U_PLATFORM_HAS_WIN32_API
65 static void TestGetLanguagesForRegion(void);
66 static void TestGetAppleParent(void);
67 static void TestAppleLocalizationsToUse(void);
70 void PrintDataTable();
72 /*---------------------------------------------------
74 --------------------------------------------------- */
76 #define LOCALE_INFO_SIZE 28
78 static const char* const rawData2
[LOCALE_INFO_SIZE
][LOCALE_SIZE
] = {
80 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
82 { "", "", "", "", "", "", "", "", "" },
84 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
86 { "", "", "", "", "NY", "", "", "", "" },
88 { "en_US", "fr_FR", "ca_ES",
89 "el_GR", "no_NO_NY", "zh_Hans_CN",
90 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
92 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
94 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
96 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
98 /* display language (English) */
99 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
100 /* display script code (English) */
101 { "", "", "", "", "", "Simplified Han", "", "", "" },
102 /* display country (English) */
103 { "United States", "France", "Spain", "Greece", "Norway", "China mainland", "Germany", "", "Japan" },
104 /* display variant (English) */
105 { "", "", "", "", "NY", "", "", "", "" },
106 /* display name (English) */
107 { "English (United States)", "French (France)", "Catalan (Spain)",
108 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese, Simplified (China mainland)",
109 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
111 /* display language (French) */
112 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
113 /* display script code (French) */
114 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
115 /* display country (French) */
116 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine continentale", "Allemagne", "", "Japon" },
117 /* display variant (French) */
118 { "", "", "", "", "NY", "", "", "", "" },
119 /* display name (French) */
120 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
121 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois simplifi\\u00e9 (Chine continentale)",
122 "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
124 /* display language (Catalan) */
125 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
126 /* display script code (Catalan) */
127 { "", "", "", "", "", "han simplificat", "", "", "" },
128 /* display country (Catalan) */
129 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina continental", "Alemanya", "", "Jap\\u00F3" },
130 /* display variant (Catalan) */
131 { "", "", "", "", "NY", "", "", "", "" },
132 /* display name (Catalan) */
133 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
134 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s simplificat (Xina continental)",
135 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
137 /* display language (Greek) */
139 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
140 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
141 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
142 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
143 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
144 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
145 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
146 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
147 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
149 /* display script code (Greek) */
151 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
152 /* display country (Greek) */
154 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
155 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
156 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
157 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
158 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
159 "\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE",
160 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
162 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
164 /* display variant (Greek) */
165 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
166 /* display name (Greek) */
168 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
169 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
170 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
171 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
172 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
173 "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03b1 \\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE)",
174 "\\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)",
175 "\\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)",
176 "\\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)"
180 static UChar
*** dataTable
=0;
220 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
222 void addLocaleTest(TestNode
** root
);
224 void addLocaleTest(TestNode
** root
)
226 TESTCASE(TestObsoleteNames
); /* srl- move */
227 TESTCASE(TestBasicGetters
);
228 TESTCASE(TestNullDefault
);
229 TESTCASE(TestPrefixes
);
230 TESTCASE(TestSimpleResourceInfo
);
231 TESTCASE(TestDisplayNames
);
232 TESTCASE(TestGetAvailableLocales
);
233 TESTCASE(TestDataDirectory
);
234 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
235 TESTCASE(TestISOFunctions
);
237 TESTCASE(TestISO3Fallback
);
238 TESTCASE(TestUninstalledISO3Names
);
239 TESTCASE(TestSimpleDisplayNames
);
240 TESTCASE(TestVariantParsing
);
241 TESTCASE(TestKeywordVariants
);
242 TESTCASE(TestKeywordVariantParsing
);
243 TESTCASE(TestCanonicalization
);
244 TESTCASE(TestCanonicalizationBuffer
);
245 TESTCASE(TestKeywordSet
);
246 TESTCASE(TestKeywordSetError
);
247 TESTCASE(TestDisplayKeywords
);
248 TESTCASE(TestDisplayKeywordValues
);
249 TESTCASE(TestGetBaseName
);
250 #if !UCONFIG_NO_FILE_IO
251 TESTCASE(TestGetLocale
);
253 TESTCASE(TestDisplayNameWarning
);
254 TESTCASE(TestNonexistentLanguageExemplars
);
255 TESTCASE(TestLocDataErrorCodeChaining
);
256 TESTCASE(TestLocDataWithRgTag
);
257 TESTCASE(TestLanguageExemplarsFallbacks
);
258 TESTCASE(TestCalendar
);
259 TESTCASE(TestDateFormat
);
260 TESTCASE(TestCollation
);
261 TESTCASE(TestULocale
);
262 TESTCASE(TestUResourceBundle
);
263 TESTCASE(TestDisplayName
);
264 TESTCASE(TestAcceptLanguage
);
265 TESTCASE(TestGetLocaleForLCID
);
266 TESTCASE(TestOrientation
);
267 TESTCASE(TestLikelySubtags
);
268 TESTCASE(TestToLanguageTag
);
269 TESTCASE(TestBug20132
);
270 TESTCASE(TestForLanguageTag
);
271 TESTCASE(TestInvalidLanguageTag
);
272 TESTCASE(TestLangAndRegionCanonicalize
);
273 TESTCASE(TestTrailingNull
);
274 TESTCASE(TestUnicodeDefines
);
275 TESTCASE(TestEnglishExemplarCharacters
);
276 TESTCASE(TestDisplayNameBrackets
);
277 TESTCASE(TestIsRightToLeft
);
278 TESTCASE(TestToUnicodeLocaleKey
);
279 TESTCASE(TestToLegacyKey
);
280 TESTCASE(TestToUnicodeLocaleType
);
281 TESTCASE(TestToLegacyType
);
282 TESTCASE(TestBadLocaleIDs
);
283 TESTCASE(TestBug20370
);
284 TESTCASE(TestBug20321UnicodeLocaleKey
);
285 TESTCASE(TestUldnNameVariants
);
286 TESTCASE(TestRootUndEmpty
);
287 #if !U_PLATFORM_HAS_WIN32_API
288 TESTCASE(TestGetLanguagesForRegion
);
289 TESTCASE(TestGetAppleParent
);
290 TESTCASE(TestAppleLocalizationsToUse
);
295 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
296 static void TestBasicGetters() {
299 UErrorCode status
= U_ZERO_ERROR
;
300 char *testLocale
= 0;
301 char *temp
= 0, *name
= 0;
302 log_verbose("Testing Basic Getters\n");
303 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
304 testLocale
=(char*)malloc(sizeof(char) * (strlen(rawData2
[NAME
][i
])+1));
305 strcpy(testLocale
,rawData2
[NAME
][i
]);
307 log_verbose("Testing %s .....\n", testLocale
);
308 cap
=uloc_getLanguage(testLocale
, NULL
, 0, &status
);
309 if(status
==U_BUFFER_OVERFLOW_ERROR
){
311 temp
=(char*)malloc(sizeof(char) * (cap
+1));
312 uloc_getLanguage(testLocale
, temp
, cap
+1, &status
);
314 if(U_FAILURE(status
)){
315 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status
));
317 if (0 !=strcmp(temp
,rawData2
[LANG
][i
])) {
318 log_err(" Language code mismatch: %s versus %s\n", temp
, rawData2
[LANG
][i
]);
322 cap
=uloc_getCountry(testLocale
, temp
, cap
, &status
);
323 if(status
==U_BUFFER_OVERFLOW_ERROR
){
325 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
326 uloc_getCountry(testLocale
, temp
, cap
+1, &status
);
328 if(U_FAILURE(status
)){
329 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status
));
331 if (0 != strcmp(temp
, rawData2
[CTRY
][i
])) {
332 log_err(" Country code mismatch: %s versus %s\n", temp
, rawData2
[CTRY
][i
]);
336 cap
=uloc_getVariant(testLocale
, temp
, cap
, &status
);
337 if(status
==U_BUFFER_OVERFLOW_ERROR
){
339 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
340 uloc_getVariant(testLocale
, temp
, cap
+1, &status
);
342 if(U_FAILURE(status
)){
343 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status
));
345 if (0 != strcmp(temp
, rawData2
[VAR
][i
])) {
346 log_err("Variant code mismatch: %s versus %s\n", temp
, rawData2
[VAR
][i
]);
349 cap
=uloc_getName(testLocale
, NULL
, 0, &status
);
350 if(status
==U_BUFFER_OVERFLOW_ERROR
){
352 name
=(char*)malloc(sizeof(char) * (cap
+1));
353 uloc_getName(testLocale
, name
, cap
+1, &status
);
354 } else if(status
==U_ZERO_ERROR
) {
355 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale
);
357 if(U_FAILURE(status
)){
358 log_err("ERROR: in uloc_getName %s\n", myErrorName(status
));
360 if (0 != strcmp(name
, rawData2
[NAME
][i
])){
361 log_err(" Mismatch in getName: %s versus %s\n", name
, rawData2
[NAME
][i
]);
371 static void TestNullDefault() {
372 UErrorCode status
= U_ZERO_ERROR
;
373 char original
[ULOC_FULLNAME_CAPACITY
];
375 uprv_strcpy(original
, uloc_getDefault());
376 uloc_setDefault("qq_BLA", &status
);
377 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
378 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
380 uloc_setDefault(NULL
, &status
);
381 if (uprv_strcmp(uloc_getDefault(), original
) != 0) {
382 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
386 /* Test that set & get of default locale work, and that
387 * default locales are cached and reused, and not overwritten.
391 const char *n2_en_US
;
393 status
= U_ZERO_ERROR
;
394 uloc_setDefault("en_US", &status
);
395 n_en_US
= uloc_getDefault();
396 if (strcmp(n_en_US
, "en_US") != 0) {
397 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
400 uloc_setDefault("fr_FR", &status
);
401 n_fr_FR
= uloc_getDefault();
402 if (strcmp(n_en_US
, "en_US") != 0) {
403 log_err("uloc_setDefault altered previously default string."
404 "Expected \"en_US\", got \"%s\"\n", n_en_US
);
406 if (strcmp(n_fr_FR
, "fr_FR") != 0) {
407 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR
);
410 uloc_setDefault("en_US", &status
);
411 n2_en_US
= uloc_getDefault();
412 if (strcmp(n2_en_US
, "en_US") != 0) {
413 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
415 if (n2_en_US
!= n_en_US
) {
416 log_err("Default locale cache failed to reuse en_US locale.\n");
419 if (U_FAILURE(status
)) {
420 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status
));
426 /* Test the i- and x- and @ and . functionality
429 #define PREFIXBUFSIZ 128
431 static void TestPrefixes() {
434 const char *loc
, *expected
;
436 static const char * const testData
[][7] =
438 /* NULL canonicalize() column means "expect same as getName()" */
439 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL
},
440 {"en", "", "GB", "", "en-gb", "en_GB", NULL
},
441 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL
},
442 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL
},
443 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL
},
444 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL
},
445 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", "hyw"},
446 {"de", "", "", "1901", "de-1901", "de__1901", NULL
},
447 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
448 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
449 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
450 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
451 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
452 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
453 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
454 {"no", "", "", "NY", "no__ny", "no__NY", NULL
},
455 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
456 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL
},
457 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL
},
458 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL
},
459 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL
},
460 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL
}, /* total garbage */
462 // Before ICU 64, ICU locale canonicalization had some additional mappings.
463 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
464 // The following now use standard canonicalization.
465 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans__PINYIN"},
466 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW_STROKE"},
468 {NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
}
471 static const char * const testTitles
[] = {
472 "uloc_getLanguage()",
478 "uloc_canonicalize()"
481 char buf
[PREFIXBUFSIZ
];
486 for(row
=0;testData
[row
][0] != NULL
;row
++) {
487 loc
= testData
[row
][NAME
];
488 log_verbose("Test #%d: %s\n", row
, loc
);
493 for(n
=0;n
<=(NAME
+2);n
++) {
494 if(n
==NAME
) continue;
496 for(len
=0;len
<PREFIXBUFSIZ
;len
++) {
497 buf
[len
] = '%'; /* Set a tripwire.. */
503 len
= uloc_getLanguage(loc
, buf
, PREFIXBUFSIZ
, &err
);
507 len
= uloc_getScript(loc
, buf
, PREFIXBUFSIZ
, &err
);
511 len
= uloc_getCountry(loc
, buf
, PREFIXBUFSIZ
, &err
);
515 len
= uloc_getVariant(loc
, buf
, PREFIXBUFSIZ
, &err
);
519 len
= uloc_getName(loc
, buf
, PREFIXBUFSIZ
, &err
);
523 len
= uloc_canonicalize(loc
, buf
, PREFIXBUFSIZ
, &err
);
532 log_err("#%d: %s on %s: err %s\n",
533 row
, testTitles
[n
], loc
, u_errorName(err
));
535 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
536 row
, testTitles
[n
], loc
, buf
, len
);
538 if(len
!= (int32_t)strlen(buf
)) {
539 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
540 row
, testTitles
[n
], loc
, buf
, len
, strlen(buf
)+1);
544 /* see if they smashed something */
545 if(buf
[len
+1] != '%') {
546 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
547 row
, testTitles
[n
], loc
, buf
, buf
[len
+1]);
550 expected
= testData
[row
][n
];
551 if (expected
== NULL
&& n
== (NAME
+2)) {
552 /* NULL expected canonicalize() means "expect same as getName()" */
553 expected
= testData
[row
][NAME
+1];
555 if(strcmp(buf
, expected
)) {
556 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
557 row
, testTitles
[n
], loc
, buf
, expected
);
566 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
567 static void TestSimpleResourceInfo() {
569 char* testLocale
= 0;
574 testLocale
=(char*)malloc(sizeof(char) * 1);
575 expected
=(UChar
*)malloc(sizeof(UChar
) * 1);
578 log_verbose("Testing getISO3Language and getISO3Country\n");
579 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
581 testLocale
=(char*)realloc(testLocale
, sizeof(char) * (u_strlen(dataTable
[NAME
][i
])+1));
582 u_austrcpy(testLocale
, dataTable
[NAME
][i
]);
584 log_verbose("Testing %s ......\n", testLocale
);
586 temp
=uloc_getISO3Language(testLocale
);
587 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
588 u_uastrcpy(expected
,temp
);
589 if (0 != u_strcmp(expected
, dataTable
[LANG3
][i
])) {
590 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected
),
591 austrdup(dataTable
[LANG3
][i
]));
594 temp
=uloc_getISO3Country(testLocale
);
595 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
596 u_uastrcpy(expected
,temp
);
597 if (0 != u_strcmp(expected
, dataTable
[CTRY3
][i
])) {
598 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected
),
599 austrdup(dataTable
[CTRY3
][i
]));
601 sprintf(temp2
, "%x", (int)uloc_getLCID(testLocale
));
602 if (strcmp(temp2
, rawData2
[LCID
][i
]) != 0) {
603 log_err("LCID mismatch: %s versus %s\n", temp2
, rawData2
[LCID
][i
]);
612 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
613 * if there's room but won't be included in result. result < 0 indicates an error.
614 * Returns the number of chars written (not those that would be written if there's enough room.*/
615 static int32_t UCharsToEscapedAscii(const UChar
* utext
, int32_t len
, char* resultChars
, int32_t buflen
) {
616 static const struct {
629 static const int32_t ESCAPE_MAP_LENGTH
= UPRV_LENGTHOF(ESCAPE_MAP
);
630 static const char HEX_DIGITS
[] = {
631 '0', '1', '2', '3', '4', '5', '6', '7',
632 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
635 int32_t resultLen
= 0;
636 const int32_t limit
= len
<0 ? buflen
: len
; /* buflen is long enough to hit the buffer limit */
637 const int32_t escapeLimit1
= buflen
-2;
638 const int32_t escapeLimit2
= buflen
-6;
641 if(utext
==NULL
|| resultChars
==NULL
|| buflen
<0) {
645 for(i
=0;i
<limit
&& resultLen
<buflen
;++i
) {
651 for(j
=0;j
<ESCAPE_MAP_LENGTH
&& uc
!=ESCAPE_MAP
[j
].sourceVal
;j
++) {
653 if(j
<ESCAPE_MAP_LENGTH
) {
654 if(resultLen
>escapeLimit1
) {
657 resultChars
[resultLen
++]='\\';
658 resultChars
[resultLen
++]=ESCAPE_MAP
[j
].escapedChar
;
662 u_austrncpy(resultChars
+ resultLen
, &uc
, 1);
667 if(resultLen
>escapeLimit2
) {
671 /* have to escape the uchar */
672 resultChars
[resultLen
++]='\\';
673 resultChars
[resultLen
++]='u';
674 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>12)&0xff];
675 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>8)&0xff];
676 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>4)&0xff];
677 resultChars
[resultLen
++]=HEX_DIGITS
[uc
&0xff];
680 if(resultLen
<buflen
) {
681 resultChars
[resultLen
] = 0;
688 * Jitterbug 2439 -- markus 20030425
690 * The lookup of display names must not fall back through the default
691 * locale because that yields useless results.
693 static void TestDisplayNames()
696 UErrorCode errorCode
=U_ZERO_ERROR
;
698 log_verbose("Testing getDisplayName for different locales\n");
700 log_verbose(" In locale = en_US...\n");
701 doTestDisplayNames("en_US", DLANG_EN
);
702 log_verbose(" In locale = fr_FR....\n");
703 doTestDisplayNames("fr_FR", DLANG_FR
);
704 log_verbose(" In locale = ca_ES...\n");
705 doTestDisplayNames("ca_ES", DLANG_CA
);
706 log_verbose(" In locale = gr_EL..\n");
707 doTestDisplayNames("el_GR", DLANG_EL
);
709 /* test that the default locale has a display name for its own language */
710 errorCode
=U_ZERO_ERROR
;
711 length
=uloc_getDisplayLanguage(NULL
, NULL
, buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
712 if(U_FAILURE(errorCode
) || (length
<=3 && buffer
[0]<=0x7f)) {
713 /* check <=3 to reject getting the language code as a display name */
714 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
));
717 /* test that we get the language code itself for an unknown language, and a default warning */
718 errorCode
=U_ZERO_ERROR
;
719 length
=uloc_getDisplayLanguage("qq", "rr", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
720 if(errorCode
!=U_USING_DEFAULT_WARNING
|| length
!=2 || buffer
[0]!=0x71 || buffer
[1]!=0x71) {
721 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode
));
724 /* test that we get a default warning for a display name where one component is unknown (4255) */
725 errorCode
=U_ZERO_ERROR
;
726 length
=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
727 if(errorCode
!=U_USING_DEFAULT_WARNING
) {
728 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode
));
733 static const char *aLocale
= "es@collation=traditional;calendar=japanese";
734 static const char *testL
[] = { "en_US",
738 static const char *expect
[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
739 "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)",
740 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
741 "\\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)" };
744 for(i
=0;i
<UPRV_LENGTHOF(testL
);i
++) {
745 errorCode
= U_ZERO_ERROR
;
746 uloc_getDisplayName(aLocale
, testL
[i
], buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
747 if(U_FAILURE(errorCode
)) {
748 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale
, testL
[i
], u_errorName(errorCode
));
750 expectBuffer
= CharsToUChars(expect
[i
]);
751 if(u_strcmp(buffer
,expectBuffer
)) {
752 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
));
754 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale
, testL
[i
], expect
[i
]);
761 /* test that we properly preflight and return data when there's a non-default pattern,
765 static const char *locale
="az_Cyrl";
766 static const char *displayLocale
="ja";
767 static const char *expectedChars
=
768 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e"
769 "\\uff08\\u30ad\\u30ea\\u30eb\\u6587\\u5b57\\uff09";
770 UErrorCode ec
=U_ZERO_ERROR
;
773 int32_t preflightLen
=uloc_getDisplayName(locale
, displayLocale
, NULL
, 0, &ec
);
774 /* inconvenient semantics when preflighting, this condition is expected... */
775 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
778 len
=uloc_getDisplayName(locale
, displayLocale
, result
, UPRV_LENGTHOF(result
), &ec
);
780 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
781 locale
, displayLocale
, u_errorName(ec
));
783 UChar
*expected
=CharsToUChars(expectedChars
);
784 int32_t expectedLen
=u_strlen(expected
);
786 if(len
!=expectedLen
) {
787 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
788 locale
, displayLocale
, len
, expectedLen
);
789 } else if(preflightLen
!=expectedLen
) {
790 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
791 locale
, displayLocale
, preflightLen
, expectedLen
);
792 } else if(u_strncmp(result
, expected
, len
)) {
793 int32_t cap
=len
*6+1; /* worst case + space for trailing null */
794 char* resultChars
=(char*)malloc(cap
);
795 int32_t resultCharsLen
=UCharsToEscapedAscii(result
, len
, resultChars
, cap
);
796 if(resultCharsLen
<0 || resultCharsLen
<cap
-1) {
797 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale
, displayLocale
);
799 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
800 locale
, displayLocale
, resultChars
, expectedChars
);
805 /* test all buffer sizes */
806 for(i
=len
+1;i
>=0;--i
) {
807 len
=uloc_getDisplayName(locale
, displayLocale
, result
, i
, &ec
);
808 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
812 log_err("using buffer of length %d returned error %s", i
, u_errorName(ec
));
815 if(len
!=expectedLen
) {
816 log_err("with buffer of length %d, expected length %d but got %d", i
, expectedLen
, len
);
819 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
820 * we don't know that it's been filled, so no point in checking. */
830 /* test for uloc_getAvialable() and uloc_countAvilable()*/
831 static void TestGetAvailableLocales()
837 log_verbose("Testing the no of avialable locales\n");
838 locCount
=uloc_countAvailable();
840 log_data_err("countAvailable() returned an empty list!\n");
842 /* use something sensible w/o hardcoding the count */
843 else if(locCount
< 0){
844 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount
);
847 log_info("Number of locales returned = %d\n", locCount
);
849 for(i
=0;i
<locCount
;i
++){
850 locList
=uloc_getAvailable(i
);
852 log_verbose(" %s\n", locList
);
856 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
857 static void TestDataDirectory()
860 char oldDirectory
[512];
861 const char *temp
,*testValue1
,*testValue2
,*testValue3
;
862 const char path
[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING
; /*give the required path */
864 log_verbose("Testing getDataDirectory()\n");
865 temp
= u_getDataDirectory();
866 strcpy(oldDirectory
, temp
);
868 testValue1
=uloc_getISO3Language("en_US");
869 log_verbose("first fetch of language retrieved %s\n", testValue1
);
871 if (0 != strcmp(testValue1
,"eng")){
872 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1
);
875 /*defining the path for DataDirectory */
876 log_verbose("Testing setDataDirectory\n");
877 u_setDataDirectory( path
);
878 if(strcmp(path
, u_getDataDirectory())==0)
879 log_verbose("setDataDirectory working fine\n");
881 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path
);
883 testValue2
=uloc_getISO3Language("en_US");
884 log_verbose("second fetch of language retrieved %s \n", testValue2
);
886 u_setDataDirectory(oldDirectory
);
887 testValue3
=uloc_getISO3Language("en_US");
888 log_verbose("third fetch of language retrieved %s \n", testValue3
);
890 if (0 != strcmp(testValue3
,"eng")) {
891 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3
);
897 /*=========================================================== */
901 static void doTestDisplayNames(const char* displayLocale
, int32_t compareIndex
)
903 UErrorCode status
= U_ZERO_ERROR
;
905 int32_t maxresultsize
;
907 const char *testLocale
;
911 UChar
*testScript
= 0;
917 UChar
* expectedLang
= 0;
918 UChar
* expectedScript
= 0;
919 UChar
* expectedCtry
= 0;
920 UChar
* expectedVar
= 0;
921 UChar
* expectedName
= 0;
925 for(i
=0;i
<LOCALE_SIZE
; ++i
)
927 testLocale
=rawData2
[NAME
][i
];
929 log_verbose("Testing..... %s\n", testLocale
);
932 maxresultsize
=uloc_getDisplayLanguage(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
933 if(status
==U_BUFFER_OVERFLOW_ERROR
)
936 testLang
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
937 uloc_getDisplayLanguage(testLocale
, displayLocale
, testLang
, maxresultsize
+ 1, &status
);
943 if(U_FAILURE(status
)){
944 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status
));
948 maxresultsize
=uloc_getDisplayScript(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
949 if(status
==U_BUFFER_OVERFLOW_ERROR
)
952 testScript
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
953 uloc_getDisplayScript(testLocale
, displayLocale
, testScript
, maxresultsize
+ 1, &status
);
959 if(U_FAILURE(status
)){
960 log_err("Error in getDisplayScript() %s\n", myErrorName(status
));
964 maxresultsize
=uloc_getDisplayCountry(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
965 if(status
==U_BUFFER_OVERFLOW_ERROR
)
968 testCtry
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
969 uloc_getDisplayCountry(testLocale
, displayLocale
, testCtry
, maxresultsize
+ 1, &status
);
975 if(U_FAILURE(status
)){
976 log_err("Error in getDisplayCountry() %s\n", myErrorName(status
));
980 maxresultsize
=uloc_getDisplayVariant(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
981 if(status
==U_BUFFER_OVERFLOW_ERROR
)
984 testVar
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
985 uloc_getDisplayVariant(testLocale
, displayLocale
, testVar
, maxresultsize
+ 1, &status
);
991 if(U_FAILURE(status
)){
992 log_err("Error in getDisplayVariant() %s\n", myErrorName(status
));
996 maxresultsize
=uloc_getDisplayName(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
997 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1000 testName
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1001 uloc_getDisplayName(testLocale
, displayLocale
, testName
, maxresultsize
+ 1, &status
);
1007 if(U_FAILURE(status
)){
1008 log_err("Error in getDisplayName() %s\n", myErrorName(status
));
1011 expectedLang
=dataTable
[compareIndex
][i
];
1012 if(u_strlen(expectedLang
)== 0)
1013 expectedLang
=dataTable
[DLANG_EN
][i
];
1015 expectedScript
=dataTable
[compareIndex
+ 1][i
];
1016 if(u_strlen(expectedScript
)== 0)
1017 expectedScript
=dataTable
[DSCRIPT_EN
][i
];
1019 expectedCtry
=dataTable
[compareIndex
+ 2][i
];
1020 if(u_strlen(expectedCtry
)== 0)
1021 expectedCtry
=dataTable
[DCTRY_EN
][i
];
1023 expectedVar
=dataTable
[compareIndex
+ 3][i
];
1024 if(u_strlen(expectedVar
)== 0)
1025 expectedVar
=dataTable
[DVAR_EN
][i
];
1027 expectedName
=dataTable
[compareIndex
+ 4][i
];
1028 if(u_strlen(expectedName
) == 0)
1029 expectedName
=dataTable
[DNAME_EN
][i
];
1031 if (0 !=u_strcmp(testLang
,expectedLang
)) {
1032 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang
), austrdup(expectedLang
), displayLocale
);
1035 if (0 != u_strcmp(testScript
,expectedScript
)) {
1036 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript
), austrdup(expectedScript
), displayLocale
);
1039 if (0 != u_strcmp(testCtry
,expectedCtry
)) {
1040 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry
), austrdup(expectedCtry
), displayLocale
);
1043 if (0 != u_strcmp(testVar
,expectedVar
)) {
1044 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar
), austrdup(expectedVar
), displayLocale
);
1047 if(0 != u_strcmp(testName
, expectedName
)) {
1048 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName
), austrdup(expectedName
), displayLocale
);
1051 if(testName
!=&_NUL
) {
1054 if(testLang
!=&_NUL
) {
1057 if(testScript
!=&_NUL
) {
1060 if(testCtry
!=&_NUL
) {
1063 if(testVar
!=&_NUL
) {
1070 /*------------------------------
1071 * TestDisplayNameBrackets
1075 const char * displayLocale
;
1076 const char * namedRegion
;
1077 const char * namedLocale
;
1078 const char * regionName
;
1079 const char * ulocLocaleName
;
1080 const char * uldnLocaleName
;
1081 } DisplayNameBracketsItem
;
1083 static const DisplayNameBracketsItem displayNameBracketsItems
[] = {
1084 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)", "English (Cocos [Keeling] Islands)" },
1085 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])", "Burmese (Myanmar)" },
1086 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])", "Burmese (Myanmar, Myanmar)" },
1087 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B",
1088 "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09",
1089 "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1090 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09",
1091 "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09",
1092 "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1093 { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}
1096 enum { kDisplayNameBracketsMax
= 128 };
1098 static void TestDisplayNameBrackets()
1100 const DisplayNameBracketsItem
* itemPtr
= displayNameBracketsItems
;
1101 for (; itemPtr
->displayLocale
!= NULL
; itemPtr
++) {
1102 ULocaleDisplayNames
* uldn
;
1104 UChar expectRegionName
[kDisplayNameBracketsMax
];
1105 UChar expectUlocLocaleName
[kDisplayNameBracketsMax
];
1106 UChar expectUldnLocaleName
[kDisplayNameBracketsMax
];
1107 UChar getName
[kDisplayNameBracketsMax
];
1110 (void) u_unescape(itemPtr
->regionName
, expectRegionName
, kDisplayNameBracketsMax
);
1111 (void) u_unescape(itemPtr
->ulocLocaleName
, expectUlocLocaleName
, kDisplayNameBracketsMax
);
1112 (void) u_unescape(itemPtr
->uldnLocaleName
, expectUldnLocaleName
, kDisplayNameBracketsMax
);
1114 status
= U_ZERO_ERROR
;
1115 ulen
= uloc_getDisplayCountry(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1116 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1117 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1120 status
= U_ZERO_ERROR
;
1121 ulen
= uloc_getDisplayName(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1122 if ( U_FAILURE(status
) || u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1123 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1125 if ( U_FAILURE(status
) ) {
1126 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1127 } else if ( u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1129 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1130 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1133 #if !UCONFIG_NO_FORMATTING
1134 status
= U_ZERO_ERROR
;
1135 uldn
= uldn_open(itemPtr
->displayLocale
, ULDN_STANDARD_NAMES
, &status
);
1136 if (U_SUCCESS(status
)) {
1137 status
= U_ZERO_ERROR
;
1138 ulen
= uldn_regionDisplayName(uldn
, itemPtr
->namedRegion
, getName
, kDisplayNameBracketsMax
, &status
);
1139 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1140 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedRegion
, myErrorName(status
));
1143 status
= U_ZERO_ERROR
;
1144 ulen
= uldn_localeDisplayName(uldn
, itemPtr
->namedLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1145 if ( U_FAILURE(status
) ) {
1146 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1147 } else if ( u_strcmp(getName
, expectUldnLocaleName
) != 0 ) {
1149 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1150 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1155 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr
->displayLocale
, u_errorName(status
));
1158 (void)ulen
; /* Suppress variable not used warning */
1162 /*------------------------------
1166 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1167 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1168 static void TestISOFunctions()
1170 const char* const* str
=uloc_getISOLanguages();
1171 const char* const* str1
=uloc_getISOCountries();
1173 const char *key
= NULL
;
1174 int32_t count
= 0, skipped
= 0;
1176 UResourceBundle
*res
;
1177 UResourceBundle
*subRes
;
1178 UErrorCode status
= U_ZERO_ERROR
;
1180 /* test getISOLanguages*/
1181 /*str=uloc_getISOLanguages(); */
1182 log_verbose("Testing ISO Languages: \n");
1184 /* use structLocale - this data is no longer in root */
1185 res
= ures_openDirect(loadTestData(&status
), "structLocale", &status
);
1186 subRes
= ures_getByKey(res
, "Languages", NULL
, &status
);
1187 if (U_FAILURE(status
)) {
1188 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status
));
1192 expect
= ures_getSize(subRes
);
1193 for(count
= 0; *(str
+count
) != 0; count
++)
1196 test
= *(str
+count
);
1197 status
= U_ZERO_ERROR
;
1200 /* Skip over language tags. This API only returns language codes. */
1201 skipped
+= (key
!= NULL
);
1202 ures_getNextString(subRes
, NULL
, &key
, &status
);
1204 while (key
!= NULL
&& strchr(key
, '_'));
1208 /* TODO: Consider removing sh, which is deprecated */
1209 if(strcmp(key
,"root") == 0 || strcmp(key
,"Fallback") == 0 || strcmp(key
,"sh") == 0) {
1210 ures_getNextString(subRes
, NULL
, &key
, &status
);
1213 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1214 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1215 if(strcmp(test
,key
)) {
1216 /* The first difference usually implies the place where things get out of sync */
1217 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1221 if(!strcmp(test
,"in"))
1222 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1223 if(!strcmp(test
,"iw"))
1224 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1225 if(!strcmp(test
,"ji"))
1226 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1227 if(!strcmp(test
,"jw"))
1228 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1229 if(!strcmp(test
,"sh"))
1230 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1233 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1236 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count
, expect
);
1239 subRes
= ures_getByKey(res
, "Countries", subRes
, &status
);
1240 log_verbose("Testing ISO Countries");
1242 expect
= ures_getSize(subRes
) - 1; /* Skip ZZ */
1243 for(count
= 0; *(str1
+count
) != 0; count
++)
1246 test
= *(str1
+count
);
1248 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1249 skipped
+= (key
!= NULL
);
1250 ures_getNextString(subRes
, NULL
, &key
, &status
);
1252 while (key
!= NULL
&& strlen(key
) != 2);
1256 /* TODO: Consider removing CS, which is deprecated */
1257 while(strcmp(key
,"QO") == 0 || strcmp(key
,"QU") == 0 || strcmp(key
,"CS") == 0) {
1258 ures_getNextString(subRes
, NULL
, &key
, &status
);
1261 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1262 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1263 if(strcmp(test
,key
)) {
1264 /* The first difference usually implies the place where things get out of sync */
1265 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1268 if(!strcmp(test
,"FX"))
1269 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1270 if(!strcmp(test
,"YU"))
1271 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1272 if(!strcmp(test
,"ZR"))
1273 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1276 ures_getNextString(subRes
, NULL
, &key
, &status
);
1277 if (strcmp(key
, "ZZ") != 0) {
1278 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key
);
1280 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1281 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1284 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1285 skipped
+= (key
!= NULL
);
1286 ures_getNextString(subRes
, NULL
, &key
, &status
);
1288 while (U_SUCCESS(status
) && key
!= NULL
&& strlen(key
) != 2);
1290 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1293 log_err("There is an error in getISOCountries, got %d, expected %d \n", count
, expect
);
1300 static void setUpDataTable()
1303 dataTable
= (UChar
***)(calloc(sizeof(UChar
**),LOCALE_INFO_SIZE
));
1305 for (i
= 0; i
< LOCALE_INFO_SIZE
; i
++) {
1306 dataTable
[i
] = (UChar
**)(calloc(sizeof(UChar
*),LOCALE_SIZE
));
1307 for (j
= 0; j
< LOCALE_SIZE
; j
++){
1308 dataTable
[i
][j
] = CharsToUChars(rawData2
[i
][j
]);
1313 static void cleanUpDataTable()
1316 if(dataTable
!= NULL
) {
1317 for (i
=0; i
<LOCALE_INFO_SIZE
; i
++) {
1318 for(j
= 0; j
< LOCALE_SIZE
; j
++) {
1319 free(dataTable
[i
][j
]);
1329 * @bug 4011756 4011380
1331 static void TestISO3Fallback()
1333 const char* test
="xx_YY";
1335 const char * result
;
1337 result
= uloc_getISO3Language(test
);
1339 /* Conform to C API usage */
1341 if (!result
|| (result
[0] != 0))
1342 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1344 result
= uloc_getISO3Country(test
);
1346 if (!result
|| (result
[0] != 0))
1347 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1353 static void TestSimpleDisplayNames()
1356 This test is different from TestDisplayNames because TestDisplayNames checks
1357 fallback behavior, combination of language and country names to form locale
1358 names, and other stuff like that. This test just checks specific language
1359 and country codes to make sure we have the correct names for them.
1361 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1362 const char* languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1364 const char* inLocale
[] = { "en_US", "zh_Hant"};
1365 UErrorCode status
=U_ZERO_ERROR
;
1368 int32_t localeIndex
= 0;
1369 for (i
= 0; i
< 7; i
++) {
1371 UChar
*expectedLang
=0;
1375 localeIndex
= 1; /* Use the second locale for the rest of the test. */
1378 size
=uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], NULL
, size
, &status
);
1379 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1380 status
=U_ZERO_ERROR
;
1381 testLang
=(UChar
*)malloc(sizeof(UChar
) * (size
+ 1));
1382 uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], testLang
, size
+ 1, &status
);
1384 expectedLang
=(UChar
*)malloc(sizeof(UChar
) * (strlen(languageNames
[i
])+1));
1385 u_uastrcpy(expectedLang
, languageNames
[i
]);
1386 if (u_strcmp(testLang
, expectedLang
) != 0)
1387 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1388 languageCodes
[i
], languageNames
[i
], austrdup(testLang
));
1398 static void TestUninstalledISO3Names()
1400 /* This test checks to make sure getISO3Language and getISO3Country work right
1401 even for locales that are not installed. */
1402 static const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
1404 static const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
1405 "ssw", "twi", "zul" };
1406 static const char iso2Countries
[][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1407 "ss_SB", "tw_TC", "zu_ZW" };
1408 static const char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1409 "SLB", "TCA", "ZWE" };
1412 for (i
= 0; i
< 8; i
++) {
1413 UErrorCode err
= U_ZERO_ERROR
;
1415 test
= uloc_getISO3Language(iso2Languages
[i
]);
1416 if(strcmp(test
, iso3Languages
[i
]) !=0 || U_FAILURE(err
))
1417 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1418 iso2Languages
[i
], iso3Languages
[i
], test
, myErrorName(err
));
1420 for (i
= 0; i
< 8; i
++) {
1421 UErrorCode err
= U_ZERO_ERROR
;
1423 test
= uloc_getISO3Country(iso2Countries
[i
]);
1424 if(strcmp(test
, iso3Countries
[i
]) !=0 || U_FAILURE(err
))
1425 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1426 iso2Countries
[i
], iso3Countries
[i
], test
, myErrorName(err
));
1431 static void TestVariantParsing()
1433 static const char* en_US_custom
="en_US_De Anza_Cupertino_California_United States_Earth";
1434 static const char* dispName
="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1435 static const char* dispVar
="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1436 static const char* shortVariant
="fr_FR_foo";
1437 static const char* bogusVariant
="fr_FR__foo";
1438 static const char* bogusVariant2
="fr_FR_foo_";
1439 static const char* bogusVariant3
="fr_FR__foo_";
1442 UChar displayVar
[100];
1443 UChar displayName
[100];
1444 UErrorCode status
=U_ZERO_ERROR
;
1447 size
=uloc_getDisplayVariant(en_US_custom
, "en_US", NULL
, size
, &status
);
1448 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1449 status
=U_ZERO_ERROR
;
1450 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1451 uloc_getDisplayVariant(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1454 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1456 u_uastrcpy(displayVar
, dispVar
);
1457 if(u_strcmp(got
,displayVar
)!=0) {
1458 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar
, austrdup(got
));
1461 size
=uloc_getDisplayName(en_US_custom
, "en_US", NULL
, size
, &status
);
1462 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1463 status
=U_ZERO_ERROR
;
1464 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1465 uloc_getDisplayName(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1468 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1470 u_uastrcpy(displayName
, dispName
);
1471 if(u_strcmp(got
,displayName
)!=0) {
1472 if (status
== U_USING_DEFAULT_WARNING
) {
1473 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status
));
1475 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName
, austrdup(got
));
1480 status
=U_ZERO_ERROR
;
1481 size
=uloc_getDisplayVariant(shortVariant
, NULL
, NULL
, size
, &status
);
1482 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1483 status
=U_ZERO_ERROR
;
1484 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1485 uloc_getDisplayVariant(shortVariant
, NULL
, got
, size
+ 1, &status
);
1488 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1490 if(strcmp(austrdup(got
),"FOO")!=0) {
1491 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got
));
1494 status
=U_ZERO_ERROR
;
1495 size
=uloc_getDisplayVariant(bogusVariant
, NULL
, NULL
, size
, &status
);
1496 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1497 status
=U_ZERO_ERROR
;
1498 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1499 uloc_getDisplayVariant(bogusVariant
, NULL
, got
, size
+ 1, &status
);
1502 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1504 if(strcmp(austrdup(got
),"_FOO")!=0) {
1505 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got
));
1508 status
=U_ZERO_ERROR
;
1509 size
=uloc_getDisplayVariant(bogusVariant2
, NULL
, NULL
, size
, &status
);
1510 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1511 status
=U_ZERO_ERROR
;
1512 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1513 uloc_getDisplayVariant(bogusVariant2
, NULL
, got
, size
+ 1, &status
);
1516 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1518 if(strcmp(austrdup(got
),"FOO_")!=0) {
1519 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got
));
1522 status
=U_ZERO_ERROR
;
1523 size
=uloc_getDisplayVariant(bogusVariant3
, NULL
, NULL
, size
, &status
);
1524 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1525 status
=U_ZERO_ERROR
;
1526 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1527 uloc_getDisplayVariant(bogusVariant3
, NULL
, got
, size
+ 1, &status
);
1530 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1532 if(strcmp(austrdup(got
),"_FOO_")!=0) {
1533 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got
));
1539 static void TestObsoleteNames(void)
1542 UErrorCode status
= U_ZERO_ERROR
;
1554 { "eng_USA", "eng", "en", "USA", "US" },
1555 { "kok", "kok", "kok", "", "" },
1556 { "in", "ind", "in", "", "" },
1557 { "id", "ind", "id", "", "" }, /* NO aliasing */
1558 { "sh", "srp", "sh", "", "" },
1559 { "zz_CS", "", "zz", "SCG", "CS" },
1560 { "zz_FX", "", "zz", "FXX", "FX" },
1561 { "zz_RO", "", "zz", "ROU", "RO" },
1562 { "zz_TP", "", "zz", "TMP", "TP" },
1563 { "zz_TL", "", "zz", "TLS", "TL" },
1564 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1565 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1566 { "zz_ROM", "", "zz", "ROU", "RO" },
1567 { "zz_ROU", "", "zz", "ROU", "RO" },
1568 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1569 { "zz_TMP", "", "zz", "TMP", "TP" },
1570 { "zz_TLS", "", "zz", "TLS", "TL" },
1571 { "zz_YUG", "", "zz", "YUG", "YU" },
1572 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1573 { "iw", "heb", "iw", "", "" },
1574 { "ji", "yid", "ji", "", "" },
1575 { "jw", "jaw", "jw", "", "" },
1576 { "sh", "srp", "sh", "", "" },
1577 { "", "", "", "", "" }
1580 for(i
=0;tests
[i
].locale
[0];i
++)
1584 locale
= tests
[i
].locale
;
1585 log_verbose("** %s:\n", locale
);
1587 status
= U_ZERO_ERROR
;
1588 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1590 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1591 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1595 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1596 uloc_getISO3Language(locale
) );
1599 status
= U_ZERO_ERROR
;
1600 uloc_getLanguage(locale
, buff
, 256, &status
);
1601 if(U_FAILURE(status
))
1603 log_err("FAIL: error getting language from %s\n", locale
);
1607 if(strcmp(buff
,tests
[i
].lang
))
1609 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1610 locale
, buff
, tests
[i
].lang
);
1614 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale
, buff
);
1617 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1619 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1620 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1624 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1625 uloc_getISO3Language(locale
) );
1628 if(strcmp(tests
[i
].ctry3
,uloc_getISO3Country(locale
)))
1630 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1631 locale
, uloc_getISO3Country(locale
), tests
[i
].ctry3
);
1635 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1636 uloc_getISO3Country(locale
) );
1639 status
= U_ZERO_ERROR
;
1640 uloc_getCountry(locale
, buff
, 256, &status
);
1641 if(U_FAILURE(status
))
1643 log_err("FAIL: error getting country from %s\n", locale
);
1647 if(strcmp(buff
,tests
[i
].ctry
))
1649 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1650 locale
, buff
, tests
[i
].ctry
);
1654 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale
, buff
);
1659 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1660 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1663 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1664 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1669 i
= uloc_getLanguage("kok",NULL
,0,&icu_err
);
1670 if(U_FAILURE(icu_err
))
1672 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err
));
1675 icu_err
= U_ZERO_ERROR
;
1676 uloc_getLanguage("kok",r1_buff
,12,&icu_err
);
1677 if(U_FAILURE(icu_err
))
1679 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err
));
1682 r1_addr
= (char *)uloc_getISO3Language("kok");
1684 icu_err
= U_ZERO_ERROR
;
1685 if (strcmp(r1_buff
,"kok") != 0)
1687 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff
);
1690 r1_addr
= (char *)uloc_getISO3Language("in");
1691 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1692 if (strcmp(r1_buff
,"id") != 0)
1694 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1697 r1_addr
= (char *)uloc_getISO3Language("sh");
1698 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1699 if (strcmp(r1_buff
,"sr") != 0)
1701 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1705 r1_addr
= (char *)uloc_getISO3Country("zz_ZR");
1706 strcpy(p1_buff
,"zz_");
1707 strcat(p1_buff
,r1_addr
);
1708 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1709 if (strcmp(r1_buff
,"ZR") != 0)
1711 printf("uloc_getCountry error (%s)\n",r1_buff
);
1714 r1_addr
= (char *)uloc_getISO3Country("zz_FX");
1715 strcpy(p1_buff
,"zz_");
1716 strcat(p1_buff
,r1_addr
);
1717 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1718 if (strcmp(r1_buff
,"FX") != 0)
1720 printf("uloc_getCountry error (%s)\n",r1_buff
);
1728 static void TestKeywordVariants(void)
1730 static const struct {
1731 const char *localeID
;
1732 const char *expectedLocaleID
; /* uloc_getName */
1733 const char *expectedLocaleIDNoKeywords
; /* uloc_getBaseName */
1734 const char *expectedCanonicalID
; /* uloc_canonicalize */
1735 const char *expectedKeywords
[10];
1736 int32_t numKeywords
;
1737 UErrorCode expectedStatus
; /* from uloc_openKeywords */
1740 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1741 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1743 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1744 {"calendar", "collation", "currency"},
1751 "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */
1753 {"","","","","","",""},
1755 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1758 "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */
1759 "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1760 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1761 "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1762 {"","","","","","",""},
1764 U_INVALID_FORMAT_ERROR
1768 0, /* expected getName to fail */
1769 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1770 0, /* expected canonicalize to fail */
1771 {"","","","","","",""},
1773 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1776 UErrorCode status
= U_ZERO_ERROR
;
1778 int32_t i
= 0, j
= 0;
1779 int32_t resultLen
= 0;
1781 UEnumeration
*keywords
;
1782 int32_t keyCount
= 0;
1783 const char *keyword
= NULL
;
1784 int32_t keywordLen
= 0;
1786 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1787 status
= U_ZERO_ERROR
;
1789 keywords
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
1791 if(status
!= testCases
[i
].expectedStatus
) {
1792 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1793 testCases
[i
].localeID
,
1794 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1796 status
= U_ZERO_ERROR
;
1798 if((keyCount
= uenum_count(keywords
, &status
)) != testCases
[i
].numKeywords
) {
1799 log_err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1803 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1804 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1805 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1810 uenum_reset(keywords
, &status
);
1811 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1812 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1813 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1818 uenum_close(keywords
);
1821 status
= U_ZERO_ERROR
;
1822 resultLen
= uloc_getName(testCases
[i
].localeID
, buffer
, 256, &status
);
1823 U_ASSERT(resultLen
< 256);
1824 if (U_SUCCESS(status
)) {
1825 if (testCases
[i
].expectedLocaleID
== 0) {
1826 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1827 testCases
[i
].localeID
, buffer
);
1828 } else if (uprv_strcmp(testCases
[i
].expectedLocaleID
, buffer
) != 0) {
1829 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1830 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
);
1833 if (testCases
[i
].expectedLocaleID
!= 0) {
1834 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1835 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
, u_errorName(status
));
1839 status
= U_ZERO_ERROR
;
1840 resultLen
= uloc_getBaseName(testCases
[i
].localeID
, buffer
, 256, &status
);
1841 U_ASSERT(resultLen
< 256);
1842 if (U_SUCCESS(status
)) {
1843 if (testCases
[i
].expectedLocaleIDNoKeywords
== 0) {
1844 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
1845 testCases
[i
].localeID
, buffer
);
1846 } else if (uprv_strcmp(testCases
[i
].expectedLocaleIDNoKeywords
, buffer
) != 0) {
1847 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
1848 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
);
1851 if (testCases
[i
].expectedLocaleIDNoKeywords
!= 0) {
1852 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
1853 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
, u_errorName(status
));
1857 status
= U_ZERO_ERROR
;
1858 resultLen
= uloc_canonicalize(testCases
[i
].localeID
, buffer
, 256, &status
);
1859 U_ASSERT(resultLen
< 256);
1860 if (U_SUCCESS(status
)) {
1861 if (testCases
[i
].expectedCanonicalID
== 0) {
1862 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
1863 testCases
[i
].localeID
, buffer
);
1864 } else if (uprv_strcmp(testCases
[i
].expectedCanonicalID
, buffer
) != 0) {
1865 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1866 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
);
1869 if (testCases
[i
].expectedCanonicalID
!= 0) {
1870 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
1871 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
, u_errorName(status
));
1877 static void TestKeywordVariantParsing(void)
1879 static const struct {
1880 const char *localeID
;
1881 const char *keyword
;
1882 const char *expectedValue
; /* NULL if failure is expected */
1884 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", NULL
}, /* malformed key name */
1885 { "de_DE", "collation", ""},
1886 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1887 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1892 int32_t resultLen
= 0;
1895 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1897 status
= U_ZERO_ERROR
;
1898 resultLen
= uloc_getKeywordValue(testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
, 256, &status
);
1899 (void)resultLen
; /* Suppress set but not used warning. */
1900 if (testCases
[i
].expectedValue
) {
1901 /* expect success */
1902 if (U_FAILURE(status
)) {
1903 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got status %s\n",
1904 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, u_errorName(status
));
1905 } else if (uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1906 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got \"%s\"\n",
1907 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1909 } else if (U_SUCCESS(status
)) {
1910 /* expect failure */
1911 log_err("Expected failure but got success from \"%s\" for keyword \"%s\". Got \"%s\"\n",
1912 testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1918 static const struct {
1919 const char *l
; /* locale */
1920 const char *k
; /* kw */
1921 const char *v
; /* value */
1922 const char *x
; /* expected */
1923 } kwSetTestCases
[] = {
1925 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1926 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1927 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1928 { "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 */
1929 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1930 { "de", "Currency", "CHF", "de@currency=CHF" },
1931 { "de", "Currency", "CHF", "de@currency=CHF" },
1933 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1934 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1935 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1936 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1937 { "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 */
1938 { "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 */
1939 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1940 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1943 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1944 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1945 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1946 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1947 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1948 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1949 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1950 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1951 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1955 /* 1. removal of item at end */
1956 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1957 { "de@collation=phonebook;currency=CHF", "currency", NULL
, "de@collation=phonebook" },
1958 /* 2. removal of item at beginning */
1959 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1960 { "de@collation=phonebook;currency=CHF", "collation", NULL
, "de@currency=CHF" },
1961 /* 3. removal of an item not there */
1962 { "de@collation=phonebook;currency=CHF", "calendar", NULL
, "de@collation=phonebook;currency=CHF" },
1963 /* 4. removal of only item */
1964 { "de@collation=phonebook", "collation", NULL
, "de" },
1966 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1967 /* cases with legal extra spacing */
1968 /*31*/{ "en_US@ calendar = islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1969 /*32*/{ "en_US@ calendar = gregorian ; collation = phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1970 /*33*/{ "en_US@ calendar = islamic", "currency", "CHF", "en_US@calendar=islamic;currency=CHF" },
1971 /*34*/{ "en_US@ currency = CHF", "calendar", "japanese", "en_US@calendar=japanese;currency=CHF" },
1972 /* cases in which setKeywordValue expected to fail (implied by NULL for expected); locale need not be canonical */
1973 /*35*/{ "en_US@calendar=gregorian;", "calendar", "japanese", NULL
},
1974 /*36*/{ "en_US@calendar=gregorian;=", "calendar", "japanese", NULL
},
1975 /*37*/{ "en_US@calendar=gregorian;currency=", "calendar", "japanese", NULL
},
1976 /*38*/{ "en_US@=", "calendar", "japanese", NULL
},
1977 /*39*/{ "en_US@=;", "calendar", "japanese", NULL
},
1978 /*40*/{ "en_US@= ", "calendar", "japanese", NULL
},
1979 /*41*/{ "en_US@ =", "calendar", "japanese", NULL
},
1980 /*42*/{ "en_US@ = ", "calendar", "japanese", NULL
},
1981 /*43*/{ "en_US@=;calendar=gregorian", "calendar", "japanese", NULL
},
1982 /*44*/{ "en_US@= calen dar = gregorian", "calendar", "japanese", NULL
},
1983 /*45*/{ "en_US@= calendar = greg orian", "calendar", "japanese", NULL
},
1984 /*46*/{ "en_US@=;cal...endar=gregorian", "calendar", "japanese", NULL
},
1985 /*47*/{ "en_US@=;calendar=greg...orian", "calendar", "japanese", NULL
},
1986 /*48*/{ "en_US@calendar=gregorian", "cale ndar", "japanese", NULL
},
1987 /*49*/{ "en_US@calendar=gregorian", "calendar", "japa..nese", NULL
},
1988 /* cases in which getKeywordValue and setKeyword expected to fail (implied by NULL for value and expected) */
1989 /*50*/{ "en_US@=", "calendar", NULL
, NULL
},
1990 /*51*/{ "en_US@=;", "calendar", NULL
, NULL
},
1991 /*52*/{ "en_US@= ", "calendar", NULL
, NULL
},
1992 /*53*/{ "en_US@ =", "calendar", NULL
, NULL
},
1993 /*54*/{ "en_US@ = ", "calendar", NULL
, NULL
},
1994 /*55*/{ "en_US@=;calendar=gregorian", "calendar", NULL
, NULL
},
1995 /*56*/{ "en_US@= calen dar = gregorian", "calendar", NULL
, NULL
},
1996 /*57*/{ "en_US@= calendar = greg orian", "calendar", NULL
, NULL
},
1997 /*58*/{ "en_US@=;cal...endar=gregorian", "calendar", NULL
, NULL
},
1998 /*59*/{ "en_US@=;calendar=greg...orian", "calendar", NULL
, NULL
},
1999 /*60*/{ "en_US@calendar=gregorian", "cale ndar", NULL
, NULL
},
2003 static void TestKeywordSet(void)
2006 int32_t resultLen
= 0;
2011 for(i
= 0; i
< UPRV_LENGTHOF(kwSetTestCases
); i
++) {
2012 UErrorCode status
= U_ZERO_ERROR
;
2013 memset(buffer
,'%',1023);
2014 strcpy(buffer
, kwSetTestCases
[i
].l
);
2016 if (kwSetTestCases
[i
].x
!= NULL
) {
2017 uloc_canonicalize(kwSetTestCases
[i
].l
, cbuffer
, 1023, &status
);
2018 if(strcmp(buffer
,cbuffer
)) {
2019 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i
, cbuffer
, buffer
);
2021 /* sanity check test case results for canonicity */
2022 uloc_canonicalize(kwSetTestCases
[i
].x
, cbuffer
, 1023, &status
);
2023 if(strcmp(kwSetTestCases
[i
].x
,cbuffer
)) {
2024 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__
, __LINE__
, i
, kwSetTestCases
[i
].x
, cbuffer
);
2027 status
= U_ZERO_ERROR
;
2028 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
2029 if(U_FAILURE(status
)) {
2030 log_err("Err on test case %d for setKeywordValue: got error %s\n", i
, u_errorName(status
));
2031 } else if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=resultLen
)) {
2032 log_err("FAIL: #%d setKeywordValue: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
2033 kwSetTestCases
[i
].v
, buffer
, resultLen
, kwSetTestCases
[i
].x
, strlen(buffer
));
2035 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,buffer
);
2038 if (kwSetTestCases
[i
].v
!= NULL
&& kwSetTestCases
[i
].v
[0] != 0) {
2039 status
= U_ZERO_ERROR
;
2040 resultLen
= uloc_getKeywordValue(kwSetTestCases
[i
].x
, kwSetTestCases
[i
].k
, buffer
, 1023, &status
);
2041 if(U_FAILURE(status
)) {
2042 log_err("Err on test case %d for getKeywordValue: got error %s\n", i
, u_errorName(status
));
2043 } else if (resultLen
!= uprv_strlen(kwSetTestCases
[i
].v
) || uprv_strcmp(buffer
, kwSetTestCases
[i
].v
) != 0) {
2044 log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i
, buffer
, resultLen
,
2045 kwSetTestCases
[i
].v
, uprv_strlen(kwSetTestCases
[i
].v
));
2049 /* test cases expected to result in error */
2050 status
= U_ZERO_ERROR
;
2051 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
2052 if(U_SUCCESS(status
)) {
2053 log_err("Err on test case %d for setKeywordValue: expected to fail but succeeded, got %s (%d)\n", i
, buffer
, resultLen
);
2056 if (kwSetTestCases
[i
].v
== NULL
) {
2057 status
= U_ZERO_ERROR
;
2058 strcpy(cbuffer
, kwSetTestCases
[i
].l
);
2059 resultLen
= uloc_getKeywordValue(cbuffer
, kwSetTestCases
[i
].k
, buffer
, 1023, &status
);
2060 if(U_SUCCESS(status
)) {
2061 log_err("Err on test case %d for getKeywordValue: expected to fail but succeeded\n", i
);
2068 static void TestKeywordSetError(void)
2076 /* 0-test whether an error condition modifies the buffer at all */
2079 memset(buffer
,'%',1023);
2080 status
= U_ZERO_ERROR
;
2081 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2082 if(status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2083 log_err("expected illegal err got %s\n", u_errorName(status
));
2086 /* if(res!=strlen(kwSetTestCases[i].x)) {
2087 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2090 if(buffer
[blen
]!='%') {
2091 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
2094 log_verbose("0-buffer modify OK\n");
2097 /* 1- test a short buffer with growing text */
2098 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2099 memset(buffer
,'%',1023);
2100 strcpy(buffer
,kwSetTestCases
[i
].l
);
2101 status
= U_ZERO_ERROR
;
2102 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2103 if(status
!= U_BUFFER_OVERFLOW_ERROR
) {
2104 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
);
2107 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2108 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2111 if(buffer
[blen
]!='%') {
2112 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
2115 log_verbose("1/%d-buffer modify OK\n",i
);
2119 /* 2- test a short buffer - text the same size or shrinking */
2120 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2121 memset(buffer
,'%',1023);
2122 strcpy(buffer
,kwSetTestCases
[i
].l
);
2123 status
= U_ZERO_ERROR
;
2124 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2125 if(status
!= U_ZERO_ERROR
) {
2126 log_err("expected zero error got %s\n", u_errorName(status
));
2129 if(buffer
[blen
+1]!='%') {
2130 log_err("Buffer byte %d was modified: now %c\n", blen
+1, buffer
[blen
+1]);
2133 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2134 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2137 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=res
)) {
2138 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
2139 kwSetTestCases
[i
].v
, buffer
, res
, kwSetTestCases
[i
].x
, strlen(buffer
));
2141 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,
2144 log_verbose("2/%d-buffer modify OK\n",i
);
2148 static int32_t _canonicalize(int32_t selector
, /* 0==getName, 1==canonicalize */
2149 const char* localeID
,
2151 int32_t resultCapacity
,
2153 /* YOU can change this to use function pointers if you like */
2156 return uloc_getName(localeID
, result
, resultCapacity
, ec
);
2158 return uloc_canonicalize(localeID
, result
, resultCapacity
, ec
);
2164 static void TestCanonicalization(void)
2166 static const struct {
2167 const char *localeID
; /* input */
2168 const char *getNameID
; /* expected getName() result */
2169 const char *canonicalID
; /* expected canonicalize() result */
2171 { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2172 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2173 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2174 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2175 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2176 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2177 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2178 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2179 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2180 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2181 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2182 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
2183 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2184 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2185 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2187 /* posix behavior that used to be performed by getName */
2188 { "mr.utf8", "mr.utf8", "mr" },
2189 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2190 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2191 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2192 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2193 { "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 */
2195 /* fleshing out canonicalization */
2196 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2197 { "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" },
2198 /* already-canonical ids are not changed */
2199 { "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" },
2200 /* norwegian is just too weird, if we handle things in their full generality */
2201 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2203 /* test cases reflecting internal resource bundle usage */
2204 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2205 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2206 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2207 { "ja_JP", "ja_JP", "ja_JP" },
2209 /* test case for "i-default" */
2210 { "i-default", "en@x=i-default", "en@x=i-default" },
2212 // Before ICU 64, ICU locale canonicalization had some additional mappings.
2213 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
2214 // The following now use standard canonicalization.
2215 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
2216 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
2217 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
2218 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
2219 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
2220 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
2221 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
2222 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
2223 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
2224 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
2225 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
2226 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
2227 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
2228 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
2229 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
2230 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
2231 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
2232 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
2233 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
2234 { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
2235 { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
2236 { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
2237 { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
2238 { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
2239 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
2240 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
2241 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
2242 { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
2243 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN_STROKE" },
2244 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
2245 { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
2246 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */
2247 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
2248 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
2249 { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
2250 { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
2251 /* PRE_EURO and EURO conversions don't affect other keywords */
2252 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
2253 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
2254 /* currency keyword overrides PRE_EURO and EURO currency */
2255 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
2256 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
2259 static const char* label
[] = { "getName", "canonicalize" };
2261 UErrorCode status
= U_ZERO_ERROR
;
2262 int32_t i
, j
, resultLen
= 0, origResultLen
;
2265 for (i
=0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2266 for (j
=0; j
<2; ++j
) {
2267 const char* expected
= (j
==0) ? testCases
[i
].getNameID
: testCases
[i
].canonicalID
;
2269 status
= U_ZERO_ERROR
;
2271 if (expected
== NULL
) {
2272 expected
= uloc_getDefault();
2275 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2276 origResultLen
= _canonicalize(j
, testCases
[i
].localeID
, NULL
, 0, &status
);
2277 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
2278 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2279 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2282 status
= U_ZERO_ERROR
;
2283 resultLen
= _canonicalize(j
, testCases
[i
].localeID
, buffer
, sizeof(buffer
), &status
);
2284 if (U_FAILURE(status
)) {
2285 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2286 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2289 if(uprv_strcmp(expected
, buffer
) != 0) {
2290 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2291 label
[j
], testCases
[i
].localeID
, buffer
, expected
);
2293 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2294 label
[j
], testCases
[i
].localeID
, buffer
);
2296 if (resultLen
!= (int32_t)strlen(buffer
)) {
2297 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2298 label
[j
], testCases
[i
].localeID
, resultLen
, strlen(buffer
));
2300 if (origResultLen
!= resultLen
) {
2301 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2302 label
[j
], testCases
[i
].localeID
, origResultLen
, resultLen
);
2308 static void TestCanonicalizationBuffer(void)
2310 UErrorCode status
= U_ZERO_ERROR
;
2313 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
2314 static const char name
[] =
2316 "=foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2317 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2318 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2321 static const size_t len
= sizeof(name
) - 1; // Without NUL terminator.
2323 int32_t reslen
= uloc_canonicalize(name
, buffer
, (int32_t)len
, &status
);
2325 if (U_FAILURE(status
)) {
2326 log_err("FAIL: uloc_canonicalize(%s) => %s, expected !U_FAILURE()\n",
2327 name
, u_errorName(status
));
2331 if (reslen
!= len
) {
2332 log_err("FAIL: uloc_canonicalize(%s) => \"%i\", expected \"%u\"\n",
2337 if (uprv_strncmp(name
, buffer
, len
) != 0) {
2338 log_err("FAIL: uloc_canonicalize(%s) => \"%.*s\", expected \"%s\"\n",
2339 name
, reslen
, buffer
, name
);
2344 static void TestDisplayKeywords(void)
2348 static const struct {
2349 const char *localeID
;
2350 const char *displayLocale
;
2351 UChar displayKeyword
[200];
2353 { "ca_ES@currency=ESP", "de_AT",
2354 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2356 { "ja_JP@calendar=japanese", "de",
2357 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2359 { "de_DE@collation=traditional", "de_DE",
2360 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2363 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2364 UErrorCode status
= U_ZERO_ERROR
;
2365 const char* keyword
=NULL
;
2366 int32_t keywordLen
= 0;
2367 int32_t keywordCount
= 0;
2368 UChar
*displayKeyword
=NULL
;
2369 int32_t displayKeywordLen
= 0;
2370 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2371 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2372 if(U_FAILURE(status
)){
2373 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases
[i
].localeID
, u_errorName(status
));
2376 /* the uenum_next returns NUL terminated string */
2377 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2378 /* fetch the displayKeyword */
2379 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2380 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2381 status
= U_ZERO_ERROR
;
2382 displayKeywordLen
++; /* for null termination */
2383 displayKeyword
= (UChar
*) malloc(displayKeywordLen
* U_SIZEOF_UCHAR
);
2384 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2385 if(U_FAILURE(status
)){
2386 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
));
2389 if(u_strncmp(displayKeyword
, testCases
[i
].displayKeyword
, displayKeywordLen
)!=0){
2390 if (status
== U_USING_DEFAULT_WARNING
) {
2391 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
));
2393 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
);
2398 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status
));
2401 free(displayKeyword
);
2404 uenum_close(keywordEnum
);
2408 static void TestDisplayKeywordValues(void){
2411 static const struct {
2412 const char *localeID
;
2413 const char *displayLocale
;
2414 UChar displayKeywordValue
[500];
2416 { "ca_ES@currency=ESP", "de_AT",
2417 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2419 { "de_AT@currency=ATS", "fr_FR",
2420 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2422 { "de_DE@currency=DEM", "it",
2423 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2425 { "el_GR@currency=GRD", "en",
2426 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2428 { "eu_ES@currency=ESP", "it_IT",
2429 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2431 { "de@collation=phonebook", "es",
2432 {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}
2435 { "de_DE@collation=phonebook", "es",
2436 {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}
2438 { "es_ES@collation=traditional","de",
2439 {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}
2441 { "ja_JP@calendar=japanese", "de",
2442 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2445 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2446 UErrorCode status
= U_ZERO_ERROR
;
2447 const char* keyword
=NULL
;
2448 int32_t keywordLen
= 0;
2449 int32_t keywordCount
= 0;
2450 UChar
*displayKeywordValue
= NULL
;
2451 int32_t displayKeywordValueLen
= 0;
2452 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2453 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2454 if(U_FAILURE(status
)){
2455 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
));
2458 /* the uenum_next returns NUL terminated string */
2459 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2461 /* fetch the displayKeywordValue */
2462 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2463 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2464 status
= U_ZERO_ERROR
;
2465 displayKeywordValueLen
++; /* for null termination */
2466 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2467 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2468 if(U_FAILURE(status
)){
2469 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
));
2472 if(u_strncmp(displayKeywordValue
, testCases
[i
].displayKeywordValue
, displayKeywordValueLen
)!=0){
2473 if (status
== U_USING_DEFAULT_WARNING
) {
2474 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
));
2476 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
));
2481 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2483 free(displayKeywordValue
);
2485 uenum_close(keywordEnum
);
2488 /* test a multiple keywords */
2489 UErrorCode status
= U_ZERO_ERROR
;
2490 const char* keyword
=NULL
;
2491 int32_t keywordLen
= 0;
2492 int32_t keywordCount
= 0;
2493 const char* localeID
= "es@collation=phonebook;calendar=buddhist;currency=DEM";
2494 const char* displayLocale
= "de";
2495 static const UChar expected
[][50] = {
2496 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2498 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2499 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2502 UEnumeration
* keywordEnum
= uloc_openKeywords(localeID
, &status
);
2504 for(keywordCount
= 0; keywordCount
< uenum_count(keywordEnum
, &status
) ; keywordCount
++){
2505 UChar
*displayKeywordValue
= NULL
;
2506 int32_t displayKeywordValueLen
= 0;
2507 if(U_FAILURE(status
)){
2508 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID
, displayLocale
, u_errorName(status
));
2511 /* the uenum_next returns NUL terminated string */
2512 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2514 /* fetch the displayKeywordValue */
2515 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2516 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2517 status
= U_ZERO_ERROR
;
2518 displayKeywordValueLen
++; /* for null termination */
2519 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2520 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2521 if(U_FAILURE(status
)){
2522 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
));
2525 if(u_strncmp(displayKeywordValue
, expected
[keywordCount
], displayKeywordValueLen
)!=0){
2526 if (status
== U_USING_DEFAULT_WARNING
) {
2527 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
));
2529 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID
, keyword
, displayLocale
);
2534 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2536 free(displayKeywordValue
);
2538 uenum_close(keywordEnum
);
2542 /* Test non existent keywords */
2543 UErrorCode status
= U_ZERO_ERROR
;
2544 const char* localeID
= "es";
2545 const char* displayLocale
= "de";
2546 UChar
*displayKeywordValue
= NULL
;
2547 int32_t displayKeywordValueLen
= 0;
2549 /* fetch the displayKeywordValue */
2550 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, "calendar", displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2551 if(U_FAILURE(status
)) {
2552 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status
));
2553 } else if(displayKeywordValueLen
!= 0) {
2554 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen
);
2560 static void TestGetBaseName(void) {
2561 static const struct {
2562 const char *localeID
;
2563 const char *baseName
;
2565 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2566 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2567 { "ja@calendar = buddhist", "ja" }
2570 int32_t i
= 0, baseNameLen
= 0;
2572 UErrorCode status
= U_ZERO_ERROR
;
2574 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2575 baseNameLen
= uloc_getBaseName(testCases
[i
].localeID
, baseName
, 256, &status
);
2576 (void)baseNameLen
; /* Suppress set but not used warning. */
2577 if(strcmp(testCases
[i
].baseName
, baseName
)) {
2578 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2579 testCases
[i
].localeID
, testCases
[i
].baseName
, baseName
);
2585 static void TestTrailingNull(void) {
2586 const char* localeId
= "zh_Hans";
2587 UChar buffer
[128]; /* sufficient for this test */
2589 UErrorCode status
= U_ZERO_ERROR
;
2592 len
= uloc_getDisplayName(localeId
, localeId
, buffer
, 128, &status
);
2594 log_err("buffer too small");
2598 for (i
= 0; i
< len
; ++i
) {
2599 if (buffer
[i
] == 0) {
2600 log_err("name contained null");
2606 /* Jitterbug 4115 */
2607 static void TestDisplayNameWarning(void) {
2610 UErrorCode status
= U_ZERO_ERROR
;
2612 size
= uloc_getDisplayLanguage("qqq", "kl", name
, UPRV_LENGTHOF(name
), &status
);
2613 (void)size
; /* Suppress set but not used warning. */
2614 if (status
!= U_USING_DEFAULT_WARNING
) {
2615 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2616 u_errorName(status
));
2622 * Compare two locale IDs. If they are equal, return 0. If `string'
2623 * starts with `prefix' plus an additional element, that is, string ==
2624 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2626 static UBool
_loccmp(const char* string
, const char* prefix
) {
2627 int32_t slen
= (int32_t)uprv_strlen(string
),
2628 plen
= (int32_t)uprv_strlen(prefix
);
2629 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
2630 /* 'root' is less than everything */
2631 if (uprv_strcmp(prefix
, "root") == 0) {
2632 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
2634 if (c
) return -1; /* mismatch */
2635 if (slen
== plen
) return 0;
2636 if (string
[plen
] == '_') return 1;
2637 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2640 static void _checklocs(const char* label
,
2643 const char* actual
) {
2644 /* We want the valid to be strictly > the bogus requested locale,
2645 and the valid to be >= the actual. */
2646 if (_loccmp(req
, valid
) > 0 &&
2647 _loccmp(valid
, actual
) >= 0) {
2648 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2649 label
, req
, valid
, actual
);
2651 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2652 label
, req
, valid
, actual
);
2656 static void TestGetLocale(void) {
2657 UErrorCode ec
= U_ZERO_ERROR
;
2659 UChar EMPTY
[1] = {0};
2662 #if !UCONFIG_NO_FORMATTING
2665 const char *req
= "en_US_REDWOODSHORES", *valid
, *actual
;
2666 obj
= udat_open(UDAT_DEFAULT
, UDAT_DEFAULT
,
2670 if (U_FAILURE(ec
)) {
2671 log_data_err("udat_open failed.Error %s\n", u_errorName(ec
));
2674 valid
= udat_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2675 actual
= udat_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2676 if (U_FAILURE(ec
)) {
2677 log_err("udat_getLocaleByType() failed\n");
2680 _checklocs("udat", req
, valid
, actual
);
2686 #if !UCONFIG_NO_FORMATTING
2689 const char *req
= "fr_FR_PROVENCAL", *valid
, *actual
;
2690 obj
= ucal_open(NULL
, 0,
2694 if (U_FAILURE(ec
)) {
2695 log_err("ucal_open failed with error: %s\n", u_errorName(ec
));
2698 valid
= ucal_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2699 actual
= ucal_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2700 if (U_FAILURE(ec
)) {
2701 log_err("ucal_getLocaleByType() failed\n");
2704 _checklocs("ucal", req
, valid
, actual
);
2710 #if !UCONFIG_NO_FORMATTING
2713 const char *req
= "zh_Hant_TW_TAINAN", *valid
, *actual
;
2714 obj
= unum_open(UNUM_DECIMAL
,
2718 if (U_FAILURE(ec
)) {
2719 log_err("unum_open failed\n");
2722 valid
= unum_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2723 actual
= unum_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2724 if (U_FAILURE(ec
)) {
2725 log_err("unum_getLocaleByType() failed\n");
2728 _checklocs("unum", req
, valid
, actual
);
2735 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2736 #if !UCONFIG_NO_FORMATTING
2738 UMessageFormat
*obj
;
2739 const char *req
= "ja_JP_TAKAYAMA", *valid
, *actual
;
2741 obj
= umsg_open(EMPTY
, 0,
2744 if (U_FAILURE(ec
)) {
2745 log_err("umsg_open failed\n");
2748 valid
= umsg_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2749 actual
= umsg_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2750 if (U_FAILURE(ec
)) {
2751 log_err("umsg_getLocaleByType() failed\n");
2754 /* We want the valid to be strictly > the bogus requested locale,
2755 and the valid to be >= the actual. */
2756 /* TODO MessageFormat is currently just storing the locale it is given.
2757 As a result, it will return whatever it was given, even if the
2758 locale is invalid. */
2759 test
= (_cmpversion("3.2") <= 0) ?
2760 /* Here is the weakened test for 3.0: */
2761 (_loccmp(req
, valid
) >= 0) :
2762 /* Here is what the test line SHOULD be: */
2763 (_loccmp(req
, valid
) > 0);
2766 _loccmp(valid
, actual
) >= 0) {
2767 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2769 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2777 #if !UCONFIG_NO_BREAK_ITERATION
2779 UBreakIterator
*obj
;
2780 const char *req
= "ar_KW_ABDALI", *valid
, *actual
;
2781 obj
= ubrk_open(UBRK_WORD
,
2786 if (U_FAILURE(ec
)) {
2787 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec
));
2790 valid
= ubrk_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2791 actual
= ubrk_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2792 if (U_FAILURE(ec
)) {
2793 log_err("ubrk_getLocaleByType() failed\n");
2796 _checklocs("ubrk", req
, valid
, actual
);
2802 #if !UCONFIG_NO_COLLATION
2805 const char *req
= "es_AR_BUENOSAIRES", *valid
, *actual
;
2806 obj
= ucol_open(req
, &ec
);
2807 if (U_FAILURE(ec
)) {
2808 log_err("ucol_open failed - %s\n", u_errorName(ec
));
2811 valid
= ucol_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2812 actual
= ucol_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2813 if (U_FAILURE(ec
)) {
2814 log_err("ucol_getLocaleByType() failed\n");
2817 _checklocs("ucol", req
, valid
, actual
);
2822 static void TestEnglishExemplarCharacters(void) {
2823 UErrorCode status
= U_ZERO_ERROR
;
2826 UChar testChars
[] = {
2827 0x61, /* standard */
2828 0xE1, /* auxiliary */
2830 0x2D /* punctuation */
2832 ULocaleData
*uld
= ulocdata_open("en", &status
);
2833 if (U_FAILURE(status
)) {
2834 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status
));
2838 for (i
= 0; i
< ULOCDATA_ES_COUNT
; i
++) {
2839 exSet
= ulocdata_getExemplarSet(uld
, exSet
, 0, (ULocaleDataExemplarSetType
)i
, &status
);
2840 if (U_FAILURE(status
)) {
2841 log_err_status(status
, "ulocdata_getExemplarSet() for type %d failed\n", i
);
2842 status
= U_ZERO_ERROR
;
2845 if (!uset_contains(exSet
, (UChar32
)testChars
[i
])) {
2846 log_err("Character U+%04X is not included in exemplar type %d\n", testChars
[i
], i
);
2851 ulocdata_close(uld
);
2854 static void TestNonexistentLanguageExemplars(void) {
2855 /* JB 4068 - Nonexistent language */
2856 UErrorCode ec
= U_ZERO_ERROR
;
2857 ULocaleData
*uld
= ulocdata_open("qqq",&ec
);
2858 if (ec
!= U_USING_DEFAULT_WARNING
) {
2859 log_err_status(ec
, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2862 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2863 ulocdata_close(uld
);
2866 static void TestLocDataErrorCodeChaining(void) {
2867 UErrorCode ec
= U_USELESS_COLLATOR_ERROR
;
2868 ulocdata_open(NULL
, &ec
);
2869 ulocdata_getExemplarSet(NULL
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
);
2870 ulocdata_getDelimiter(NULL
, ULOCDATA_DELIMITER_COUNT
, NULL
, -1, &ec
);
2871 ulocdata_getMeasurementSystem(NULL
, &ec
);
2872 ulocdata_getPaperSize(NULL
, NULL
, NULL
, &ec
);
2873 if (ec
!= U_USELESS_COLLATOR_ERROR
) {
2874 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec
));
2880 UMeasurementSystem measureSys
;
2883 static const LocToMeasureSys locToMeasures
[] = {
2884 { "fr_FR", UMS_SI
},
2886 { "en_GB", UMS_UK
},
2887 { "fr_FR@rg=GBZZZZ", UMS_UK
},
2888 { "en@rg=frzzzz", UMS_SI
},
2889 { "en_GB@rg=USZZZZ", UMS_US
},
2890 { NULL
, (UMeasurementSystem
)0 } /* terminator */
2893 static void TestLocDataWithRgTag(void) {
2894 const LocToMeasureSys
* locToMeasurePtr
= locToMeasures
;
2895 for (; locToMeasurePtr
->locale
!= NULL
; locToMeasurePtr
++) {
2896 UErrorCode status
= U_ZERO_ERROR
;
2897 UMeasurementSystem measureSys
= ulocdata_getMeasurementSystem(locToMeasurePtr
->locale
, &status
);
2898 if (U_FAILURE(status
)) {
2899 log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
2900 locToMeasurePtr
->locale
, u_errorName(status
));
2901 } else if (measureSys
!= locToMeasurePtr
->measureSys
) {
2902 log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
2903 locToMeasurePtr
->locale
, (int) locToMeasurePtr
->measureSys
, (int)measureSys
);
2908 static void TestLanguageExemplarsFallbacks(void) {
2909 /* Test that en_US fallsback, but en doesn't fallback. */
2910 UErrorCode ec
= U_ZERO_ERROR
;
2911 ULocaleData
*uld
= ulocdata_open("en_US",&ec
);
2912 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2913 if (ec
!= U_USING_FALLBACK_WARNING
) {
2914 log_err_status(ec
, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2917 ulocdata_close(uld
);
2919 uld
= ulocdata_open("en",&ec
);
2920 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2921 if (ec
!= U_ZERO_ERROR
) {
2922 log_err_status(ec
, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2925 ulocdata_close(uld
);
2928 static const char *acceptResult(UAcceptResult uar
) {
2929 return udbg_enumName(UDBG_UAcceptResult
, uar
);
2932 static void TestAcceptLanguage(void) {
2933 UErrorCode status
= U_ZERO_ERROR
;
2934 UAcceptResult outResult
;
2935 UEnumeration
*available
;
2941 int32_t httpSet
; /**< Which of http[] should be used? */
2942 const char *icuSet
; /**< ? */
2943 const char *expect
; /**< The expected locale result */
2944 UAcceptResult res
; /**< The expected error code */
2945 UErrorCode expectStatus
; /**< expected status */
2947 /*0*/{ 0, NULL
, "mt_MT", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
2948 /*1*/{ 1, NULL
, "en", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
2949 /*2*/{ 2, NULL
, "en", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
},
2950 /*3*/{ 3, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
},
2951 /*4*/{ 4, NULL
, "es", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
2952 /*5*/{ 5, NULL
, "en", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
}, /* XF */
2953 /*6*/{ 6, NULL
, "ja", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
}, /* XF */
2954 /*7*/{ 7, NULL
, "zh", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
}, /* XF */
2955 /*8*/{ 8, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
}, /* */
2956 /*9*/{ 9, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
}, /* */
2957 /*10*/{10, NULL
, "", ULOC_ACCEPT_FAILED
, U_BUFFER_OVERFLOW_ERROR
}, /* */
2958 /*11*/{11, NULL
, "", ULOC_ACCEPT_FAILED
, U_BUFFER_OVERFLOW_ERROR
}, /* */
2960 const int32_t numTests
= UPRV_LENGTHOF(tests
);
2961 static const char *http
[] = {
2962 /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=.01",
2963 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2964 /*2*/ "en-wf, de-lx;q=0.8",
2965 /*3*/ "mga-ie;q=0.9, tlh",
2966 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2967 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2968 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2969 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2970 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2971 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2972 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2974 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2976 /*7*/ "zh-xx;q=0.9",
2977 /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2978 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2979 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2980 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
2981 /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2982 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2983 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2984 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
2985 /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2986 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2987 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2988 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
2989 /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2990 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2991 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2992 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
2995 for(i
=0;i
<numTests
;i
++) {
2997 status
=U_ZERO_ERROR
;
2998 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2999 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
3001 available
= ures_openAvailableLocales(tests
[i
].icuSet
, &status
);
3003 rc
= uloc_acceptLanguageFromHTTP(tmp
, 199, &outResult
, http
[tests
[i
].httpSet
], available
, &status
);
3004 (void)rc
; /* Suppress set but not used warning. */
3005 uenum_close(available
);
3006 log_verbose(" got %s, %s [%s]\n", tmp
[0]?tmp
:"(EMPTY)", acceptResult(outResult
), u_errorName(status
));
3007 if(status
!= tests
[i
].expectStatus
) {
3008 log_err_status(status
, "FAIL: expected status %s but got %s\n", u_errorName(tests
[i
].expectStatus
), u_errorName(status
));
3009 } else if(U_SUCCESS(tests
[i
].expectStatus
)) {
3010 /* don't check content if expected failure */
3011 if(outResult
!= tests
[i
].res
) {
3012 log_err_status(status
, "FAIL: #%d: expected outResult of %s but got %s\n", i
,
3013 acceptResult( tests
[i
].res
),
3014 acceptResult( outResult
));
3015 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3016 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
,acceptResult(tests
[i
].res
));
3018 if((outResult
>0)&&uprv_strcmp(tmp
, tests
[i
].expect
)) {
3019 log_err_status(status
, "FAIL: #%d: expected %s but got %s\n", i
, tests
[i
].expect
, tmp
);
3020 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3021 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
3027 static const char* LOCALE_ALIAS
[][2] = {
3041 static UBool
isLocaleAvailable(UResourceBundle
* resIndex
, const char* loc
){
3042 UErrorCode status
= U_ZERO_ERROR
;
3044 ures_getStringByKey(resIndex
, loc
,&len
, &status
);
3045 if(U_FAILURE(status
)){
3051 static void TestCalendar() {
3052 #if !UCONFIG_NO_FORMATTING
3054 UErrorCode status
= U_ZERO_ERROR
;
3055 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3056 if(U_FAILURE(status
)){
3057 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3060 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3061 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3062 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3063 UCalendar
* c1
= NULL
;
3064 UCalendar
* c2
= NULL
;
3066 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
3067 const char* l1
= ucal_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
3068 const char* l2
= ucal_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
3070 if(!isLocaleAvailable(resIndex
, newLoc
)){
3073 c1
= ucal_open(NULL
, -1, oldLoc
, UCAL_GREGORIAN
, &status
);
3074 c2
= ucal_open(NULL
, -1, newLoc
, UCAL_GREGORIAN
, &status
);
3076 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0 || status
!=U_ZERO_ERROR
) {
3077 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3079 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1
, l2
);
3083 ures_close(resIndex
);
3087 static void TestDateFormat() {
3088 #if !UCONFIG_NO_FORMATTING
3090 UErrorCode status
= U_ZERO_ERROR
;
3091 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3092 if(U_FAILURE(status
)){
3093 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3096 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3097 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3098 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3099 UDateFormat
* df1
= NULL
;
3100 UDateFormat
* df2
= NULL
;
3101 const char* l1
= NULL
;
3102 const char* l2
= NULL
;
3104 if(!isLocaleAvailable(resIndex
, newLoc
)){
3107 df1
= udat_open(UDAT_FULL
, UDAT_FULL
,oldLoc
, NULL
, 0, NULL
, -1, &status
);
3108 df2
= udat_open(UDAT_FULL
, UDAT_FULL
,newLoc
, NULL
, 0, NULL
, -1, &status
);
3109 if(U_FAILURE(status
)){
3110 log_err("Creation of date format failed %s\n", u_errorName(status
));
3113 /*Test function "getLocale"*/
3114 l1
= udat_getLocaleByType(df1
, ULOC_VALID_LOCALE
, &status
);
3115 l2
= udat_getLocaleByType(df2
, ULOC_VALID_LOCALE
, &status
);
3116 if(U_FAILURE(status
)){
3117 log_err("Fetching the locale by type failed. %s\n", u_errorName(status
));
3119 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
3120 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3122 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1
, l2
);
3126 ures_close(resIndex
);
3130 static void TestCollation() {
3131 #if !UCONFIG_NO_COLLATION
3133 UErrorCode status
= U_ZERO_ERROR
;
3134 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3135 if(U_FAILURE(status
)){
3136 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3139 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3140 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3141 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3142 UCollator
* c1
= NULL
;
3143 UCollator
* c2
= NULL
;
3144 const char* l1
= NULL
;
3145 const char* l2
= NULL
;
3147 status
= U_ZERO_ERROR
;
3148 if(!isLocaleAvailable(resIndex
, newLoc
)){
3151 if(U_FAILURE(status
)){
3152 log_err("Creation of collators failed %s\n", u_errorName(status
));
3155 c1
= ucol_open(oldLoc
, &status
);
3156 c2
= ucol_open(newLoc
, &status
);
3157 l1
= ucol_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
3158 l2
= ucol_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
3159 if(U_FAILURE(status
)){
3160 log_err("Fetching the locale names failed failed %s\n", u_errorName(status
));
3162 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
3163 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3165 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1
, l2
);
3169 ures_close(resIndex
);
3173 typedef struct OrientationStructTag
{
3174 const char* localeId
;
3175 ULayoutType character
;
3177 } OrientationStruct
;
3179 static const char* ULayoutTypeToString(ULayoutType type
)
3183 case ULOC_LAYOUT_LTR
:
3184 return "ULOC_LAYOUT_LTR";
3186 case ULOC_LAYOUT_RTL
:
3187 return "ULOC_LAYOUT_RTL";
3189 case ULOC_LAYOUT_TTB
:
3190 return "ULOC_LAYOUT_TTB";
3192 case ULOC_LAYOUT_BTT
:
3193 return "ULOC_LAYOUT_BTT";
3195 case ULOC_LAYOUT_UNKNOWN
:
3199 return "Unknown enum value for ULayoutType!";
3202 static void TestOrientation()
3204 static const OrientationStruct toTest
[] = {
3205 { "ar", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3206 { "aR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3207 { "ar_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3208 { "fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3209 { "Fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3210 { "he", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3211 { "ps", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3212 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3213 { "UR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3214 { "en", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3215 // Additional Apple tests for rdar://51447187
3216 { "sd", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3217 { "sd_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3218 { "sd_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3219 { "mni_Beng", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3220 { "mni_Mtei", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3221 { "sat_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3222 { "sat_Olck", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3223 { "ks", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3224 { "ks_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3225 { "ks_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3226 { "ks_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3227 { "pa", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3228 { "pa_Guru", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3229 { "pa_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3230 { "pa_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3231 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3232 { "ur_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3233 { "ur_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3237 for (; i
< UPRV_LENGTHOF(toTest
); ++i
) {
3238 UErrorCode statusCO
= U_ZERO_ERROR
;
3239 UErrorCode statusLO
= U_ZERO_ERROR
;
3240 const char* const localeId
= toTest
[i
].localeId
;
3241 const ULayoutType co
= uloc_getCharacterOrientation(localeId
, &statusCO
);
3242 const ULayoutType expectedCO
= toTest
[i
].character
;
3243 const ULayoutType lo
= uloc_getLineOrientation(localeId
, &statusLO
);
3244 const ULayoutType expectedLO
= toTest
[i
].line
;
3245 if (U_FAILURE(statusCO
)) {
3246 log_err_status(statusCO
,
3247 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3249 u_errorName(statusCO
));
3251 else if (co
!= expectedCO
) {
3253 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3255 ULayoutTypeToString(expectedCO
),
3256 ULayoutTypeToString(co
));
3258 if (U_FAILURE(statusLO
)) {
3259 log_err_status(statusLO
,
3260 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3262 u_errorName(statusLO
));
3264 else if (lo
!= expectedLO
) {
3266 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3268 ULayoutTypeToString(expectedLO
),
3269 ULayoutTypeToString(lo
));
3274 static void TestULocale() {
3276 UErrorCode status
= U_ZERO_ERROR
;
3277 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3278 if(U_FAILURE(status
)){
3279 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3282 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3283 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3284 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3285 UChar name1
[256], name2
[256];
3286 char names1
[256], names2
[256];
3287 int32_t capacity
= 256;
3289 status
= U_ZERO_ERROR
;
3290 if(!isLocaleAvailable(resIndex
, newLoc
)){
3293 uloc_getDisplayName(oldLoc
, ULOC_US
, name1
, capacity
, &status
);
3294 if(U_FAILURE(status
)){
3295 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc
, u_errorName(status
));
3298 uloc_getDisplayName(newLoc
, ULOC_US
, name2
, capacity
, &status
);
3299 if(U_FAILURE(status
)){
3300 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc
, u_errorName(status
));
3303 if (u_strcmp(name1
, name2
)!=0) {
3304 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3306 u_austrcpy(names1
, name1
);
3307 u_austrcpy(names2
, name2
);
3308 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1
, names2
);
3310 ures_close(resIndex
);
3314 static void TestUResourceBundle() {
3318 UResourceBundle
* rb1
= NULL
;
3319 UResourceBundle
* rb2
= NULL
;
3320 UErrorCode status
= U_ZERO_ERROR
;
3322 UResourceBundle
*resIndex
= NULL
;
3323 if(U_FAILURE(status
)){
3324 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3327 resIndex
= ures_open(NULL
,"res_index", &status
);
3328 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3330 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3331 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3332 if(!isLocaleAvailable(resIndex
, newLoc
)){
3335 rb1
= ures_open(NULL
, oldLoc
, &status
);
3336 if (U_FAILURE(status
)) {
3337 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3340 us1
= ures_getLocaleByType(rb1
, ULOC_ACTUAL_LOCALE
, &status
);
3342 status
= U_ZERO_ERROR
;
3343 rb2
= ures_open(NULL
, newLoc
, &status
);
3344 if (U_FAILURE(status
)) {
3345 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3347 us2
= ures_getLocaleByType(rb2
, ULOC_ACTUAL_LOCALE
, &status
);
3349 if (strcmp(us1
,newLoc
)!=0 || strcmp(us1
,us2
)!=0 ) {
3350 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3353 log_verbose("ures_getStringByKey old:%s new:%s\n", us1
, us2
);
3359 ures_close(resIndex
);
3362 static void TestDisplayName() {
3364 UChar oldCountry
[256] = {'\0'};
3365 UChar newCountry
[256] = {'\0'};
3366 UChar oldLang
[256] = {'\0'};
3367 UChar newLang
[256] = {'\0'};
3368 char country
[256] ={'\0'};
3369 char language
[256] ={'\0'};
3370 int32_t capacity
= 256;
3373 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3374 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3375 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3376 UErrorCode status
= U_ZERO_ERROR
;
3377 int32_t available
= uloc_countAvailable();
3379 for(j
=0; j
<available
; j
++){
3381 const char* dispLoc
= uloc_getAvailable(j
);
3382 int32_t oldCountryLen
= uloc_getDisplayCountry(oldLoc
,dispLoc
, oldCountry
, capacity
, &status
);
3383 int32_t newCountryLen
= uloc_getDisplayCountry(newLoc
, dispLoc
, newCountry
, capacity
, &status
);
3384 int32_t oldLangLen
= uloc_getDisplayLanguage(oldLoc
, dispLoc
, oldLang
, capacity
, &status
);
3385 int32_t newLangLen
= uloc_getDisplayLanguage(newLoc
, dispLoc
, newLang
, capacity
, &status
);
3387 int32_t countryLen
= uloc_getCountry(newLoc
, country
, capacity
, &status
);
3388 int32_t langLen
= uloc_getLanguage(newLoc
, language
, capacity
, &status
);
3389 /* there is a display name for the current country ID */
3390 if(countryLen
!= newCountryLen
){
3391 if(u_strncmp(oldCountry
,newCountry
,oldCountryLen
)!=0){
3392 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc
, dispLoc
);
3395 /* there is a display name for the current lang ID */
3396 if(langLen
!=newLangLen
){
3397 if(u_strncmp(oldLang
,newLang
,oldLangLen
)){
3398 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc
, dispLoc
); }
3404 static void TestGetLocaleForLCID() {
3405 int32_t i
, length
, lengthPre
;
3406 const char* testLocale
= 0;
3407 UErrorCode status
= U_ZERO_ERROR
;
3408 char temp2
[40], temp3
[40];
3411 lcid
= uloc_getLCID("en_US");
3412 if (lcid
!= 0x0409) {
3413 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid
);
3416 lengthPre
= uloc_getLocaleForLCID(lcid
, temp2
, 4, &status
);
3417 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
3418 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status
));
3421 status
= U_ZERO_ERROR
;
3424 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3425 if (U_FAILURE(status
)) {
3426 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status
));
3427 status
= U_ZERO_ERROR
;
3430 if (length
!= lengthPre
) {
3431 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length
, lengthPre
);
3434 length
= uloc_getLocaleForLCID(0x12345, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3435 if (U_SUCCESS(status
)) {
3436 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2
, u_errorName(status
));
3438 status
= U_ZERO_ERROR
;
3440 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3441 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
3443 testLocale
=rawData2
[NAME
][i
];
3445 log_verbose("Testing %s ......\n", testLocale
);
3447 sscanf(rawData2
[LCID
][i
], "%x", &lcid
);
3448 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3449 if (U_FAILURE(status
)) {
3450 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid
, u_errorName(status
));
3451 status
= U_ZERO_ERROR
;
3455 if (length
!= uprv_strlen(temp2
)) {
3456 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length
, lcid
, uprv_strlen(temp2
));
3459 /* Compare language, country, script */
3460 length
= uloc_getLanguage(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3461 if (U_FAILURE(status
)) {
3462 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3463 status
= U_ZERO_ERROR
;
3465 else if (uprv_strcmp(temp3
, rawData2
[LANG
][i
]) && !(uprv_strcmp(temp3
, "nn") == 0 && uprv_strcmp(rawData2
[VAR
][i
], "NY") == 0)) {
3466 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[LANG
][i
], lcid
, temp2
);
3469 length
= uloc_getScript(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3470 if (U_FAILURE(status
)) {
3471 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3472 status
= U_ZERO_ERROR
;
3474 else if (uprv_strcmp(temp3
, rawData2
[SCRIPT
][i
])) {
3475 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[SCRIPT
][i
], lcid
, temp2
);
3478 length
= uloc_getCountry(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3479 if (U_FAILURE(status
)) {
3480 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3481 status
= U_ZERO_ERROR
;
3483 else if (uprv_strlen(rawData2
[CTRY
][i
]) && uprv_strcmp(temp3
, rawData2
[CTRY
][i
])) {
3484 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[CTRY
][i
], lcid
, temp2
);
3490 const char* const basic_maximize_data
[][2] = {
3535 "en_Latn_US_POSIX_1901"
3537 "en_Latn__POSIX_1901",
3538 "en_Latn_US_POSIX_1901"
3541 "en_Latn_US_POSIX_1901"
3544 "de_Latn_DE_POSIX_1901"
3549 "th@calendar=buddhist",
3550 "th_Thai_TH@calendar=buddhist"
3580 "de_Latn_DE_U_CO_PHONEBK"
3582 "de_Latn_u_co_phonebk",
3583 "de_Latn_DE_U_CO_PHONEBK"
3585 "de_Latn_DE_u_co_phonebk",
3586 "de_Latn_DE_U_CO_PHONEBK"
3589 "ar_Arab_EG@em=emoji"
3592 "en_Latn_US@em=emoji"
3594 "_Latn_DE@em=emoji",
3595 "de_Latn_DE@em=emoji"
3597 "_Zzzz_DE@em=emoji",
3598 "de_Latn_DE@em=emoji"
3601 "de_Latn_DE@em=emoji"
3602 }, { // start Apple tests for <rdar://problem/47494884>
3626 }, { // start Apple tests for <rdar://problem/54153189>
3647 const char* const basic_minimize_data
[][2] = {
3652 "en_Latn_US_POSIX_1901",
3655 "EN_Latn_US_POSIX_1901",
3658 "en_Zzzz_US_POSIX_1901",
3661 "de_Latn_DE_POSIX_1901",
3667 "en_Latn_US@calendar=gregorian",
3668 "en@calendar=gregorian"
3672 const char* const full_data
[][3] = {
3676 /* "REMOVE-LIKELY" */
4043 "pa_Aran_PK", // <rdar://problem/50687287>
4272 "ur_Arab_IN" // Apple <rdar://problem/47494884>
4276 "ur_Arab", // Apple <rdar://problem/47494884>
5115 "ur_Aran_PK", // Apple <rdar://problem/47494884>
5163 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
5164 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5750 "de@collation=phonebook",
5751 "de_Latn_DE@collation=phonebook",
5752 "de@collation=phonebook"
5756 typedef struct errorDataTag
{
5758 const char* expected
;
5763 const errorData maximizeErrors
[] = {
5767 U_ILLEGAL_ARGUMENT_ERROR
,
5771 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5773 U_ILLEGAL_ARGUMENT_ERROR
,
5777 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5779 U_ILLEGAL_ARGUMENT_ERROR
,
5783 "en_Latn_US_POSIX@currency=EURO",
5784 "en_Latn_US_POSIX@currency=EURO",
5785 U_BUFFER_OVERFLOW_ERROR
,
5789 "en_Latn_US_POSIX@currency=EURO",
5790 "en_Latn_US_POSIX@currency=EURO",
5791 U_STRING_NOT_TERMINATED_WARNING
,
5796 const errorData minimizeErrors
[] = {
5800 U_ILLEGAL_ARGUMENT_ERROR
,
5804 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5806 U_ILLEGAL_ARGUMENT_ERROR
,
5810 "en_Latn_US_POSIX@currency=EURO",
5811 "en__POSIX@currency=EURO",
5812 U_BUFFER_OVERFLOW_ERROR
,
5816 "en_Latn_US_POSIX@currency=EURO",
5817 "en__POSIX@currency=EURO",
5818 U_STRING_NOT_TERMINATED_WARNING
,
5823 static int32_t getExpectedReturnValue(const errorData
* data
)
5825 if (data
->uerror
== U_BUFFER_OVERFLOW_ERROR
||
5826 data
->uerror
== U_STRING_NOT_TERMINATED_WARNING
)
5828 return (int32_t)strlen(data
->expected
);
5836 static int32_t getBufferSize(const errorData
* data
, int32_t actualSize
)
5838 if (data
->expected
== NULL
)
5842 else if (data
->bufferSize
< 0)
5844 return (int32_t)strlen(data
->expected
) + 1;
5848 return data
->bufferSize
;
5852 static void TestLikelySubtags()
5854 char buffer
[ULOC_FULLNAME_CAPACITY
+ ULOC_KEYWORD_AND_VALUES_CAPACITY
+ 1];
5857 for (; i
< UPRV_LENGTHOF(basic_maximize_data
); ++i
)
5859 UErrorCode status
= U_ZERO_ERROR
;
5860 const char* const minimal
= basic_maximize_data
[i
][0];
5861 const char* const maximal
= basic_maximize_data
[i
][1];
5863 /* const int32_t length = */
5864 uloc_addLikelySubtags(
5869 if (U_FAILURE(status
)) {
5870 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal
, u_errorName(status
));
5871 status
= U_ZERO_ERROR
;
5873 else if (uprv_strlen(maximal
) == 0) {
5874 if (uprv_stricmp(minimal
, buffer
) != 0) {
5875 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5878 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5879 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal
, minimal
, buffer
);
5883 for (i
= 0; i
< UPRV_LENGTHOF(basic_minimize_data
); ++i
) {
5885 UErrorCode status
= U_ZERO_ERROR
;
5886 const char* const maximal
= basic_minimize_data
[i
][0];
5887 const char* const minimal
= basic_minimize_data
[i
][1];
5889 /* const int32_t length = */
5890 uloc_minimizeSubtags(
5896 if (U_FAILURE(status
)) {
5897 log_err_status(status
, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5898 status
= U_ZERO_ERROR
;
5900 else if (uprv_strlen(minimal
) == 0) {
5901 if (uprv_stricmp(maximal
, buffer
) != 0) {
5902 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5905 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5906 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5910 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
5912 UErrorCode status
= U_ZERO_ERROR
;
5913 const char* const minimal
= full_data
[i
][0];
5914 const char* const maximal
= full_data
[i
][1];
5916 /* const int32_t length = */
5917 uloc_addLikelySubtags(
5922 if (U_FAILURE(status
)) {
5923 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal
, u_errorName(status
));
5924 status
= U_ZERO_ERROR
;
5926 else if (uprv_strlen(maximal
) == 0) {
5927 if (uprv_stricmp(minimal
, buffer
) != 0) {
5928 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5931 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5932 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5936 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
5938 UErrorCode status
= U_ZERO_ERROR
;
5939 const char* const maximal
= full_data
[i
][1];
5940 const char* const minimal
= full_data
[i
][2];
5942 if (strlen(maximal
) > 0) {
5944 /* const int32_t length = */
5945 uloc_minimizeSubtags(
5951 if (U_FAILURE(status
)) {
5952 log_err_status(status
, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5953 status
= U_ZERO_ERROR
;
5955 else if (uprv_strlen(minimal
) == 0) {
5956 if (uprv_stricmp(maximal
, buffer
) != 0) {
5957 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5960 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5961 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5966 for (i
= 0; i
< UPRV_LENGTHOF(maximizeErrors
); ++i
) {
5968 UErrorCode status
= U_ZERO_ERROR
;
5969 const char* const minimal
= maximizeErrors
[i
].tag
;
5970 const char* const maximal
= maximizeErrors
[i
].expected
;
5971 const UErrorCode expectedStatus
= maximizeErrors
[i
].uerror
;
5972 const int32_t expectedLength
= getExpectedReturnValue(&maximizeErrors
[i
]);
5973 const int32_t bufferSize
= getBufferSize(&maximizeErrors
[i
], sizeof(buffer
));
5975 const int32_t length
=
5976 uloc_addLikelySubtags(
5982 if (status
== U_ZERO_ERROR
) {
5983 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal
, u_errorName(expectedStatus
));
5984 status
= U_ZERO_ERROR
;
5986 else if (status
!= expectedStatus
) {
5987 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
));
5989 else if (length
!= expectedLength
) {
5990 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal
, expectedLength
, length
);
5992 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5993 if (uprv_strnicmp(maximal
, buffer
, bufferSize
) != 0) {
5994 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5995 maximal
, minimal
, (int)sizeof(buffer
), buffer
);
6000 for (i
= 0; i
< UPRV_LENGTHOF(minimizeErrors
); ++i
) {
6002 UErrorCode status
= U_ZERO_ERROR
;
6003 const char* const maximal
= minimizeErrors
[i
].tag
;
6004 const char* const minimal
= minimizeErrors
[i
].expected
;
6005 const UErrorCode expectedStatus
= minimizeErrors
[i
].uerror
;
6006 const int32_t expectedLength
= getExpectedReturnValue(&minimizeErrors
[i
]);
6007 const int32_t bufferSize
= getBufferSize(&minimizeErrors
[i
], sizeof(buffer
));
6009 const int32_t length
=
6010 uloc_minimizeSubtags(
6016 if (status
== U_ZERO_ERROR
) {
6017 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal
, u_errorName(expectedStatus
));
6018 status
= U_ZERO_ERROR
;
6020 else if (status
!= expectedStatus
) {
6021 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
));
6023 else if (length
!= expectedLength
) {
6024 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal
, expectedLength
, length
);
6026 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
6027 if (uprv_strnicmp(minimal
, buffer
, bufferSize
) != 0) {
6028 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
6029 minimal
, maximal
, (int)sizeof(buffer
), buffer
);
6035 const char* const locale_to_langtag
[][3] = {
6038 {"en_US", "en-US", "en-US"},
6039 {"iw_IL", "he-IL", "he-IL"},
6040 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
6041 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
6042 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
6043 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL
}, /* variant POSIX_VAR is processed as regular variant */
6044 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL
}, /* variant VAR_POSIX is processed as regular variant */
6045 {"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 */
6046 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
6047 {"und_555", "und-555", "und-555"},
6048 {"123", "und", NULL
},
6049 {"%$#&", "und", NULL
},
6050 {"_Latn", "und-Latn", "und-Latn"},
6051 {"_DE", "und-DE", "und-DE"},
6052 {"und_FR", "und-FR", "und-FR"},
6053 {"th_TH_TH", "th-TH-x-lvariant-th", NULL
},
6054 {"bogus", "bogus", "bogus"},
6055 {"foooobarrr", "und", NULL
},
6056 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL
},
6057 {"en_US_1234", "en-US-1234", "en-US-1234"},
6058 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
6059 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
6060 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL
},
6061 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL
},
6062 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
6063 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
6064 {"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"},
6065 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
6066 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
6067 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL
},
6068 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL
},
6069 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
6070 {"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"},
6071 {"@x=elmer", "x-elmer", "x-elmer"},
6072 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
6073 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
6074 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
6076 {"en@a=bar;attribute=baz", "en-a-bar-u-baz", "en-a-bar-u-baz"},
6077 {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo", "en-a-bar-u-baz-x-u-foo"},
6078 {"en@attribute=baz", "en-u-baz", "en-u-baz"},
6079 {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"},
6080 {"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"},
6081 {"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"},
6082 {"en@9=efg;a=baz", "en-9-efg-a-baz", "en-9-efg-a-baz"},
6084 // Before ICU 64, ICU locale canonicalization had some additional mappings.
6085 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
6086 // The following now uses standard canonicalization.
6087 {"az_AZ_CYRL", "az-AZ-x-lvariant-cyrl", NULL
},
6092 static void TestToLanguageTag(void) {
6098 const char *expected
;
6100 for (i
= 0; locale_to_langtag
[i
][0] != NULL
; i
++) {
6101 inloc
= locale_to_langtag
[i
][0];
6103 /* testing non-strict mode */
6104 status
= U_ZERO_ERROR
;
6106 expected
= locale_to_langtag
[i
][1];
6108 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), FALSE
, &status
);
6109 (void)len
; /* Suppress set but not used warning. */
6110 if (U_FAILURE(status
)) {
6111 if (expected
!= NULL
) {
6112 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
6113 inloc
, u_errorName(status
));
6116 if (expected
== NULL
) {
6117 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
6119 } else if (uprv_strcmp(langtag
, expected
) != 0) {
6120 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6121 langtag
, inloc
, expected
);
6125 /* testing strict mode */
6126 status
= U_ZERO_ERROR
;
6128 expected
= locale_to_langtag
[i
][2];
6130 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), TRUE
, &status
);
6131 if (U_FAILURE(status
)) {
6132 if (expected
!= NULL
) {
6133 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
6134 inloc
, u_errorName(status
));
6137 if (expected
== NULL
) {
6138 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
6140 } else if (uprv_strcmp(langtag
, expected
) != 0) {
6141 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
6142 langtag
, inloc
, expected
);
6148 static void TestBug20132(void) {
6153 static const char inloc
[] = "en-C";
6154 static const char expected
[] = "en-x-lvariant-c";
6155 const int32_t expected_len
= (int32_t)uprv_strlen(expected
);
6157 /* Before ICU-20132 was fixed, calling uloc_toLanguageTag() with a too small
6158 * buffer would not immediately return the buffer size actually needed, but
6159 * instead require several iterations before getting the correct size. */
6161 status
= U_ZERO_ERROR
;
6162 len
= uloc_toLanguageTag(inloc
, langtag
, 1, FALSE
, &status
);
6164 if (U_FAILURE(status
) && status
!= U_BUFFER_OVERFLOW_ERROR
) {
6165 log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6166 inloc
, u_errorName(status
));
6169 if (len
!= expected_len
) {
6170 log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc
, len
, expected_len
);
6173 status
= U_ZERO_ERROR
;
6174 len
= uloc_toLanguageTag(inloc
, langtag
, expected_len
, FALSE
, &status
);
6176 if (U_FAILURE(status
)) {
6177 log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6178 inloc
, u_errorName(status
));
6181 if (len
!= expected_len
) {
6182 log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc
, len
, expected_len
);
6183 } else if (uprv_strncmp(langtag
, expected
, expected_len
) != 0) {
6184 log_data_err("uloc_toLanguageTag returned language tag [%.*s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6185 len
, langtag
, inloc
, expected
);
6189 #define FULL_LENGTH -1
6190 static const struct {
6194 } langtag_to_locale
[] = {
6195 {"en", "en", FULL_LENGTH
},
6196 {"en-us", "en_US", FULL_LENGTH
},
6197 {"und-US", "_US", FULL_LENGTH
},
6198 {"und-latn", "_Latn", FULL_LENGTH
},
6199 {"en-US-posix", "en_US_POSIX", FULL_LENGTH
},
6200 {"de-de_euro", "de", 2},
6201 {"kok-IN", "kok_IN", FULL_LENGTH
},
6204 {"en-latn-x", "en_Latn", 7},
6205 {"art-lojban", "jbo", FULL_LENGTH
},
6206 {"zh-hakka", "hak", FULL_LENGTH
},
6207 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH
},
6208 {"zh-cmn-CH-u-co-pinyin", "cmn_CH@collation=pinyin", FULL_LENGTH
},
6209 {"xxx-yy", "xxx_YY", FULL_LENGTH
},
6210 {"fr-234", "fr_234", FULL_LENGTH
},
6211 {"i-default", "en@x=i-default", FULL_LENGTH
},
6213 {"ja-jp-jp", "ja_JP", 5},
6214 {"bogus", "bogus", FULL_LENGTH
},
6215 {"boguslang", "", 0},
6216 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH
},
6217 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH
},
6218 {"und-varzero-var1-vartwo", "__VARZERO", 11},
6219 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH
},
6220 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH
},
6221 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH
},
6222 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH
},
6223 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH
},
6224 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH
},
6225 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH
},
6226 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH
},
6227 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH
},
6228 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH
},
6229 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH
},
6230 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH
},
6231 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH
},
6232 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH
},
6233 {"x-elmer", "@x=elmer", FULL_LENGTH
},
6234 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH
},
6235 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH
},
6236 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH
},
6237 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH
},
6238 {"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
},
6239 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
6240 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
6241 {"de-1901-1901", "de__1901", 7},
6242 {"de-DE-1901-1901", "de_DE_1901", 10},
6243 {"en-a-bbb-a-ccc", "en@a=bbb", 8},
6245 {"en-a-bar-u-baz", "en@a=bar;attribute=baz", FULL_LENGTH
},
6246 {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", FULL_LENGTH
},
6247 {"en-u-baz", "en@attribute=baz", FULL_LENGTH
},
6248 {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", FULL_LENGTH
},
6249 {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", FULL_LENGTH
},
6250 {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", FULL_LENGTH
},
6251 {"und-Arab-u-em-emoji", "_Arab@em=emoji", FULL_LENGTH
},
6252 {"und-Latn-u-em-emoji", "_Latn@em=emoji", FULL_LENGTH
},
6253 {"und-Latn-DE-u-em-emoji", "_Latn_DE@em=emoji", FULL_LENGTH
},
6254 {"und-Zzzz-DE-u-em-emoji", "_Zzzz_DE@em=emoji", FULL_LENGTH
},
6255 {"und-DE-u-em-emoji", "_DE@em=emoji", FULL_LENGTH
},
6257 {"hant-cmn-cn", "hant", 4},
6258 {"zh-cmn-TW", "cmn_TW", FULL_LENGTH
},
6259 {"zh-x_t-ab", "zh", 2},
6260 {"zh-hans-cn-u-ca-x_t-u", "zh_Hans_CN@calendar=yes", 15},
6261 /* #20140 dupe keys in U-extension */
6262 {"zh-u-ca-chinese-ca-gregory", "zh@calendar=chinese", FULL_LENGTH
},
6263 {"zh-u-ca-gregory-co-pinyin-ca-chinese", "zh@calendar=gregorian;collation=pinyin", FULL_LENGTH
},
6264 {"de-latn-DE-1901-u-co-phonebk-co-pinyin-ca-gregory", "de_Latn_DE_1901@calendar=gregorian;collation=phonebook", FULL_LENGTH
},
6265 {"th-u-kf-nu-thai-kf-false", "th@colcasefirst=yes;numbers=thai", FULL_LENGTH
},
6266 /* #9562 IANA language tag data update */
6267 {"en-gb-oed", "en_GB_OXENDICT", FULL_LENGTH
},
6268 {"i-navajo", "nv", FULL_LENGTH
},
6269 {"i-navajo-a-foo", "nv@a=foo", FULL_LENGTH
},
6270 {"i-navajo-latn-us", "nv_Latn_US", FULL_LENGTH
},
6271 {"sgn-br", "bzs", FULL_LENGTH
},
6272 {"sgn-br-u-co-phonebk", "bzs@collation=phonebook", FULL_LENGTH
},
6273 {"ja-latn-hepburn-heploc", "ja_Latn__ALALC97", FULL_LENGTH
},
6274 {"ja-latn-hepburn-heploc-u-ca-japanese", "ja_Latn__ALALC97@calendar=japanese", FULL_LENGTH
},
6275 {"en-a-bcde-0-fgh", "en@0=fgh;a=bcde", FULL_LENGTH
},
6278 static void TestForLanguageTag(void) {
6283 int32_t expParsedLen
;
6285 for (i
= 0; i
< UPRV_LENGTHOF(langtag_to_locale
); i
++) {
6286 status
= U_ZERO_ERROR
;
6288 expParsedLen
= langtag_to_locale
[i
].len
;
6289 if (expParsedLen
== FULL_LENGTH
) {
6290 expParsedLen
= (int32_t)uprv_strlen(langtag_to_locale
[i
].bcpID
);
6292 uloc_forLanguageTag(langtag_to_locale
[i
].bcpID
, locale
, sizeof(locale
), &parsedLen
, &status
);
6293 if (U_FAILURE(status
)) {
6294 log_err_status(status
, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
6295 langtag_to_locale
[i
].bcpID
, u_errorName(status
));
6297 if (uprv_strcmp(langtag_to_locale
[i
].locID
, locale
) != 0) {
6298 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
6299 locale
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].locID
);
6301 if (parsedLen
!= expParsedLen
) {
6302 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
6303 parsedLen
, langtag_to_locale
[i
].bcpID
, expParsedLen
);
6309 /* See https://unicode-org.atlassian.net/browse/ICU-20149 .
6310 * Depending on the resolution of that bug, this test may have
6313 static void TestInvalidLanguageTag(void) {
6314 static const char* invalid_lang_tags
[] = {
6315 "zh-u-foo-foo-co-pinyin", /* duplicate attribute in U extension */
6316 "zh-cmn-hans-u-foo-foo-co-pinyin", /* duplicate attribute in U extension */
6319 * These do not lead to an error. Instead, parsing stops at the 1st
6322 "de-DE-1901-1901", /* duplicate variant */
6323 "en-a-bbb-a-ccc", /* duplicate extension */
6328 for (const char** tag
= invalid_lang_tags
; *tag
!= NULL
; tag
++) {
6329 UErrorCode status
= U_ZERO_ERROR
;
6330 uloc_forLanguageTag(*tag
, locale
, sizeof(locale
), NULL
, &status
);
6331 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
6332 log_err("Error returned by uloc_forLanguageTag for input language tag [%s] : %s - expected error: %s\n",
6333 *tag
, u_errorName(status
), u_errorName(U_ILLEGAL_ARGUMENT_ERROR
));
6338 static const struct {
6340 const char *canonical
;
6341 } langtag_to_canonical
[] = {
6343 {"de-DD-u-co-phonebk", "de-DE-u-co-phonebk"},
6345 {"jw-id-u-ca-islamic-civil", "jv-ID-u-ca-islamic-civil"},
6347 {"my-bu-u-nu-mymr", "my-MM-u-nu-mymr"},
6348 {"yuu-ru", "yug-RU"},
6352 static void TestLangAndRegionCanonicalize(void) {
6354 char canonical
[256];
6357 for (i
= 0; i
< UPRV_LENGTHOF(langtag_to_canonical
); i
++) {
6358 status
= U_ZERO_ERROR
;
6359 const char* input
= langtag_to_canonical
[i
].input
;
6360 uloc_forLanguageTag(input
, locale
, sizeof(locale
), NULL
, &status
);
6361 uloc_toLanguageTag(locale
, canonical
, sizeof(canonical
), TRUE
, &status
);
6362 if (U_FAILURE(status
)) {
6363 log_err_status(status
, "Error returned by uloc_forLanguageTag or uloc_toLanguageTag "
6364 "for language tag [%s] - error: %s\n", input
, u_errorName(status
));
6366 const char* expected_canonical
= langtag_to_canonical
[i
].canonical
;
6367 if (uprv_strcmp(expected_canonical
, canonical
) != 0) {
6368 log_data_err("input language tag [%s] is canonicalized to [%s] - expected: [%s]\n",
6369 input
, canonical
, expected_canonical
);
6375 static void TestToUnicodeLocaleKey(void)
6377 /* $IN specifies the result should be the input pointer itself */
6378 static const char* DATA
[][2] = {
6380 {"CALEndar", "ca"}, /* difference casing */
6381 {"ca", "ca"}, /* bcp key itself */
6382 {"kv", "kv"}, /* no difference between legacy and bcp */
6383 {"foo", NULL
}, /* unknown, bcp ill-formed */
6384 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
6389 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6390 const char* keyword
= DATA
[i
][0];
6391 const char* expected
= DATA
[i
][1];
6392 const char* bcpKey
= NULL
;
6394 bcpKey
= uloc_toUnicodeLocaleKey(keyword
);
6395 if (expected
== NULL
) {
6396 if (bcpKey
!= NULL
) {
6397 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword
, bcpKey
);
6399 } else if (bcpKey
== NULL
) {
6400 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6401 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6402 if (bcpKey
!= keyword
) {
6403 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, bcpKey
, keyword
);
6405 } else if (uprv_strcmp(bcpKey
, expected
) != 0) {
6406 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword
, bcpKey
, expected
);
6411 static void TestBug20321UnicodeLocaleKey(void)
6413 // key = alphanum alpha ;
6414 static const char* invalid
[] = {
6424 for (int i
= 0; i
< UPRV_LENGTHOF(invalid
); i
++) {
6425 const char* bcpKey
= NULL
;
6426 bcpKey
= uloc_toUnicodeLocaleKey(invalid
[i
]);
6427 if (bcpKey
!= NULL
) {
6428 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", invalid
[i
], bcpKey
);
6431 static const char* valid
[] = {
6435 for (int i
= 0; i
< UPRV_LENGTHOF(valid
); i
++) {
6436 const char* bcpKey
= NULL
;
6437 bcpKey
= uloc_toUnicodeLocaleKey(valid
[i
]);
6438 if (bcpKey
== NULL
) {
6439 log_err("toUnicodeLocaleKey: keyword=%s => NULL, expected!=NULL\n", valid
[i
]);
6444 static void TestToLegacyKey(void)
6446 /* $IN specifies the result should be the input pointer itself */
6447 static const char* DATA
[][2] = {
6448 {"kb", "colbackwards"},
6449 {"kB", "colbackwards"}, /* different casing */
6450 {"Collation", "collation"}, /* keyword itself with different casing */
6451 {"kv", "kv"}, /* no difference between legacy and bcp */
6452 {"foo", "$IN"}, /* unknown, bcp ill-formed */
6453 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
6454 {"e=mc2", NULL
}, /* unknown, bcp/legacy ill-formed */
6459 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6460 const char* keyword
= DATA
[i
][0];
6461 const char* expected
= DATA
[i
][1];
6462 const char* legacyKey
= NULL
;
6464 legacyKey
= uloc_toLegacyKey(keyword
);
6465 if (expected
== NULL
) {
6466 if (legacyKey
!= NULL
) {
6467 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword
, legacyKey
);
6469 } else if (legacyKey
== NULL
) {
6470 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6471 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6472 if (legacyKey
!= keyword
) {
6473 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, legacyKey
, keyword
);
6475 } else if (uprv_strcmp(legacyKey
, expected
) != 0) {
6476 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword
, legacyKey
, expected
);
6481 static void TestToUnicodeLocaleType(void)
6483 /* $IN specifies the result should be the input pointer itself */
6484 static const char* DATA
[][3] = {
6485 {"tz", "Asia/Kolkata", "inccu"},
6486 {"calendar", "gregorian", "gregory"},
6487 {"ca", "gregorian", "gregory"},
6488 {"ca", "Gregorian", "gregory"},
6489 {"ca", "buddhist", "buddhist"},
6490 {"Calendar", "Japanese", "japanese"},
6491 {"calendar", "Islamic-Civil", "islamic-civil"},
6492 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6493 {"colalternate", "NON-IGNORABLE", "noignore"},
6494 {"colcaselevel", "yes", "true"},
6495 {"rg", "GBzzzz", "$IN"},
6496 {"tz", "america/new_york", "usnyc"},
6497 {"tz", "Asia/Kolkata", "inccu"},
6498 {"timezone", "navajo", "usden"},
6499 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
6500 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6501 {"zz", "gregorian", NULL
}, /* unknown key, ill-formed type */
6502 {"co", "foo-", NULL
}, /* unknown type, ill-formed type */
6503 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6504 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6505 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6506 {"kr", "digit-spacepunct", NULL
}, /* invalid (bcp ill-formed) reordercode type */
6511 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6512 const char* keyword
= DATA
[i
][0];
6513 const char* value
= DATA
[i
][1];
6514 const char* expected
= DATA
[i
][2];
6515 const char* bcpType
= NULL
;
6517 bcpType
= uloc_toUnicodeLocaleType(keyword
, value
);
6518 if (expected
== NULL
) {
6519 if (bcpType
!= NULL
) {
6520 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, bcpType
);
6522 } else if (bcpType
== NULL
) {
6523 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6524 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6525 if (bcpType
!= value
) {
6526 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, bcpType
, value
);
6528 } else if (uprv_strcmp(bcpType
, expected
) != 0) {
6529 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, bcpType
, expected
);
6534 static void TestToLegacyType(void)
6536 /* $IN specifies the result should be the input pointer itself */
6537 static const char* DATA
[][3] = {
6538 {"calendar", "gregory", "gregorian"},
6539 {"ca", "gregory", "gregorian"},
6540 {"ca", "Gregory", "gregorian"},
6541 {"ca", "buddhist", "buddhist"},
6542 {"Calendar", "Japanese", "japanese"},
6543 {"calendar", "Islamic-Civil", "islamic-civil"},
6544 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6545 {"colalternate", "noignore", "non-ignorable"},
6546 {"colcaselevel", "true", "yes"},
6547 {"rg", "gbzzzz", "gbzzzz"},
6548 {"tz", "usnyc", "America/New_York"},
6549 {"tz", "inccu", "Asia/Calcutta"},
6550 {"timezone", "usden", "America/Denver"},
6551 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6552 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6553 {"ca", "aaaa", "$IN"}, /* unknown type */
6554 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6555 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6556 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6557 {"co", "e=mc2", NULL
}, /* known key, ill-formed bcp/legacy type */
6558 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6559 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6560 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6561 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6566 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6567 const char* keyword
= DATA
[i
][0];
6568 const char* value
= DATA
[i
][1];
6569 const char* expected
= DATA
[i
][2];
6570 const char* legacyType
= NULL
;
6572 legacyType
= uloc_toLegacyType(keyword
, value
);
6573 if (expected
== NULL
) {
6574 if (legacyType
!= NULL
) {
6575 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, legacyType
);
6577 } else if (legacyType
== NULL
) {
6578 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6579 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6580 if (legacyType
!= value
) {
6581 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, legacyType
, value
);
6583 } else if (uprv_strcmp(legacyType
, expected
) != 0) {
6584 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, legacyType
, expected
);
6586 log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword
, value
, legacyType
);
6593 static void test_unicode_define(const char *namech
, char ch
, const char *nameu
, UChar uch
)
6597 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech
, ch
,(int)ch
, nameu
, (int) uch
);
6598 u_charsToUChars(&ch
, asUch
, 1);
6599 if(asUch
[0] != uch
) {
6600 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
);
6602 log_verbose(" .. OK, == U+%04X\n", (int)asUch
[0]);
6606 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6608 static void TestUnicodeDefines(void) {
6609 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR
, ULOC_KEYWORD_SEPARATOR_UNICODE
);
6610 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN
, ULOC_KEYWORD_ASSIGN_UNICODE
);
6611 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR
, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE
);
6614 static void TestIsRightToLeft() {
6615 // API test only. More test cases in intltest/LocaleTest.
6616 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6617 log_err("uloc_isRightToLeft() failed");
6622 const char * badLocaleID
;
6623 const char * displayLocale
;
6624 const char * expectedName
;
6625 UErrorCode expectedStatus
;
6628 static const BadLocaleItem badLocaleItems
[] = {
6629 { "-9223372036854775808", "en", "9223372036854775808", U_USING_DEFAULT_WARNING
},
6630 /* add more in the future */
6631 { NULL
, NULL
, NULL
, U_ZERO_ERROR
} /* terminator */
6634 enum { kUBufDispNameMax
= 128, kBBufDispNameMax
= 256 };
6636 static void TestBadLocaleIDs() {
6637 const BadLocaleItem
* itemPtr
;
6638 for (itemPtr
= badLocaleItems
; itemPtr
->badLocaleID
!= NULL
; itemPtr
++) {
6639 UChar ubufExpect
[kUBufDispNameMax
], ubufGet
[kUBufDispNameMax
];
6640 UErrorCode status
= U_ZERO_ERROR
;
6641 int32_t ulenExpect
= u_unescape(itemPtr
->expectedName
, ubufExpect
, kUBufDispNameMax
);
6642 int32_t ulenGet
= uloc_getDisplayName(itemPtr
->badLocaleID
, itemPtr
->displayLocale
, ubufGet
, kUBufDispNameMax
, &status
);
6643 if (status
!= itemPtr
->expectedStatus
||
6644 (U_SUCCESS(status
) && (ulenGet
!= ulenExpect
|| u_strncmp(ubufGet
, ubufExpect
, ulenExpect
) != 0))) {
6645 char bbufExpect
[kBBufDispNameMax
], bbufGet
[kBBufDispNameMax
];
6646 u_austrncpy(bbufExpect
, ubufExpect
, ulenExpect
);
6647 u_austrncpy(bbufGet
, ubufGet
, ulenGet
);
6648 log_err("FAIL: For localeID %s, displayLocale %s, calling uloc_getDisplayName:\n"
6649 " expected status %-26s, name (len %2d): %s\n"
6650 " got status %-26s, name (len %2d): %s\n",
6651 itemPtr
->badLocaleID
, itemPtr
->displayLocale
,
6652 u_errorName(itemPtr
->expectedStatus
), ulenExpect
, bbufExpect
,
6653 u_errorName(status
), ulenGet
, bbufGet
);
6658 // Test case for ICU-20370.
6659 // The issue shows as an Addresss Sanitizer failure.
6660 static void TestBug20370() {
6661 const char *localeID
= "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar";
6662 uint32_t lcid
= uloc_getLCID(localeID
);
6664 log_err("FAIL: Expected LCID value of 0 for invalid localeID input.");
6668 typedef enum UldnNameType
{
6673 TEST_ULOC_LOCALE
, // only valid with optStdMidLong
6674 TEST_ULOC_LANGUAGE
, // only valid with optStdMidLong
6675 TEST_ULOC_SCRIPT
, // only valid with optStdMidLong
6676 TEST_ULOC_REGION
, // only valid with optStdMidLong
6680 const char * localeToName
; // NULL to terminate a list of these
6681 UldnNameType nameType
;
6682 const UChar
* expectResult
;
6686 const char * displayLocale
;
6687 const UDisplayContext
* displayOptions
; // set of 3 UDisplayContext items
6688 const UldnItem
* testItems
;
6692 static const UDisplayContext optStdMidLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6693 static const UDisplayContext optStdMidShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6694 static const UDisplayContext optDiaMidLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6695 static const UDisplayContext optDiaMidShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6697 static const UDisplayContext optStdBegLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6698 static const UDisplayContext optStdBegShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6699 static const UDisplayContext optDiaBegLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6700 static const UDisplayContext optDiaBegShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6702 static const UDisplayContext optStdLstLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6703 static const UDisplayContext optStdLstShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6704 static const UDisplayContext optDiaLstLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6705 static const UDisplayContext optDiaLstShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6707 static const UldnItem en_StdMidLong
[] = {
6708 { "en_US", TEST_ULDN_LOCALE
, u
"English (US)" },
6709 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"English (US, Computer)" },
6710 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"English (US, Chinese Calendar)" },
6711 { "en_CA", TEST_ULDN_LOCALE
, u
"English (Canada)" },
6712 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6713 { "pt_BR", TEST_ULDN_LOCALE
, u
"Portuguese (Brazil)" },
6714 { "pt_PT", TEST_ULDN_LOCALE
, u
"Portuguese (Portugal)" },
6715 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" }, // Apple <rdar://problem/50750364>
6716 { "zh_Hans_CN", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (China mainland)" }, // Apple <rdar://problem/50750364>
6717 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" }, // Apple <rdar://problem/50750364>
6718 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" }, // Apple <rdar://problem/50750364>
6719 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" }, // Apple <rdar://problem/50750364>
6720 { "yue_Hans_CN", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (China mainland)" }, // Apple <rdar://problem/50750364>
6721 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" }, // Apple <rdar://problem/50750364>
6722 { "yue_Hant_HK", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Hong Kong)" }, // Apple <rdar://problem/50750364>
6723 { "zh_Hans@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6724 { "zh_Hans_CN@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6725 { "zh_Hant@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6726 { "zh_Hant_HK@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6727 { "yue_Hans@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6728 { "yue_Hans_CN@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6729 { "yue_Hant@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6730 { "yue_Hant_HK@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6731 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6732 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6733 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6734 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6735 { "US", TEST_ULDN_REGION
, u
"United States" },
6736 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6737 { "GB", TEST_ULDN_REGION
, u
"United Kingdom" },
6738 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6739 { "ps_Arab", TEST_ULDN_LOCALE
, u
"Pashto (Arabic)" },
6740 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Afghanistan)" },
6741 { "ks_Arab", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh)" }, // Apple <rdar://problem/50687287>
6742 { "ks_Aran", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq)" }, // Apple <rdar://problem/47494884>
6743 { "ks_Arab_IN", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, India)" }, // Apple <rdar://problem/50687287>
6744 { "ks_Aran_IN", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, India)" }, // Apple <rdar://problem/47494884>
6745 { "pa_Arab", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh)" }, // Apple <rdar://problem/50687287>
6746 { "pa_Aran", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq)" }, // Apple <rdar://problem/50687287>
6747 { "pa_Arab_PK", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Pakistan)" }, // Apple <rdar://problem/50687287>
6748 { "pa_Aran_PK", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Pakistan)" }, // Apple <rdar://problem/50687287>
6749 { "ur_Arab", TEST_ULDN_LOCALE
, u
"Urdu (Naskh)" }, // Apple <rdar://problem/50687287>
6750 { "ur_Aran", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq)" }, // Apple <rdar://problem/47494884>
6751 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Pakistan)" }, // Apple <rdar://problem/50687287>
6752 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Pakistan)" }, // Apple <rdar://problem/47494884>
6753 { "ps_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Islamic Calendar)" },
6754 { "ps_Arab_AF@calendar=islamic", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Afghanistan, Islamic Calendar)" },
6755 { "ks_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6756 { "ks_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6757 { "ks_Arab_IN@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, India, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6758 { "ks_Aran_IN@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, India, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6759 { "pa_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6760 { "pa_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6761 { "pa_Arab_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6762 { "pa_Aran_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6763 { "ur_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6764 { "ur_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6765 { "ur_Arab_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6766 { "ur_Aran_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6767 { "Arab", TEST_ULDN_SCRIPT
, u
"Arabic" },
6768 { "Aran", TEST_ULDN_SCRIPT
, u
"Nastaliq" }, // Apple <rdar://problem/47494884>
6769 { "Qaag", TEST_ULDN_SCRIPT
, u
"Zawgyi" }, // Apple <rdar://problem/51471316>
6770 { "my_Qaag", TEST_ULDN_LOCALE
, u
"Burmese (Zawgyi)" }, // Apple <rdar://problem/51471316>
6772 { "zh_Hans", TEST_ULOC_LOCALE
, u
"Chinese, Simplified" }, // Apple <rdar://problem/51418203>
6773 { "zh_Hans_CN", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (China mainland)" }, // Apple <rdar://problem/51418203>
6774 { "zh_Hant", TEST_ULOC_LOCALE
, u
"Chinese, Traditional" }, // Apple <rdar://problem/51418203>
6775 { "zh_Hant_HK", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Hong Kong)" }, // Apple <rdar://problem/51418203>
6776 { "yue_Hans", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified" }, // Apple <rdar://problem/51418203>
6777 { "yue_Hans_CN", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (China mainland)" }, // Apple <rdar://problem/51418203>
6778 { "yue_Hant", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional" }, // Apple <rdar://problem/51418203>
6779 { "yue_Hant_HK", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Hong Kong)" }, // Apple <rdar://problem/51418203>
6780 { "zh_Hans@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6781 { "zh_Hans_CN@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6782 { "zh_Hant@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6783 { "zh_Hant_HK@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6784 { "yue_Hans@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6785 { "yue_Hans_CN@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6786 { "yue_Hant@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6787 { "yue_Hant_HK@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6788 { "ks_Arab", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh)" }, // Apple <rdar://problem/51418203>
6789 { "ks_Aran", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq)" }, // Apple <rdar://problem/47494884>
6790 { "ks_Arab_IN", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, India)" }, // Apple <rdar://problem/51418203>
6791 { "ks_Aran_IN", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, India)" }, // Apple <rdar://problem/47494884>
6792 { "pa_Arab", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh)" }, // Apple <rdar://problem/51418203>
6793 { "pa_Aran", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq)" }, // Apple <rdar://problem/51418203>
6794 { "pa_Arab_PK", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Pakistan)" }, // Apple <rdar://problem/51418203>
6795 { "pa_Aran_PK", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Pakistan)" }, // Apple <rdar://problem/51418203>
6796 { "ur_Arab", TEST_ULOC_LOCALE
, u
"Urdu (Naskh)" }, // Apple <rdar://problem/51418203>
6797 { "ur_Aran", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq)" }, // Apple <rdar://problem/47494884>
6798 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Pakistan)" }, // Apple <rdar://problem/51418203>
6799 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Pakistan)" }, // Apple <rdar://problem/47494884>
6800 { "ks_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6801 { "ks_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6802 { "ks_Arab_IN@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, India, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6803 { "ks_Aran_IN@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, India, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6804 { "pa_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6805 { "pa_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6806 { "pa_Arab_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6807 { "pa_Aran_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6808 { "ur_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6809 { "ur_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6810 { "ur_Arab_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6811 { "ur_Aran_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6812 { "my_Qaag", TEST_ULOC_LOCALE
, u
"Burmese (Zawgyi)" }, // Apple <rdar://problem/51471316>
6815 static const UldnItem en_StdMidShrt
[] = {
6816 { "en_US", TEST_ULDN_LOCALE
, u
"English (US)" },
6817 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"English (US, Computer)" },
6818 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"English (US, Calendar: chinese)" },
6819 { "en_CA", TEST_ULDN_LOCALE
, u
"English (Canada)" },
6820 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6821 { "pt_BR", TEST_ULDN_LOCALE
, u
"Portuguese (Brazil)" },
6822 { "pt_PT", TEST_ULDN_LOCALE
, u
"Portuguese (Portugal)" },
6823 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6824 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6825 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6826 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6827 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6828 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6829 { "US", TEST_ULDN_REGION
, u
"US" },
6830 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6831 { "GB", TEST_ULDN_REGION
, u
"UK" },
6832 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6835 static const UldnItem en_DiaMidLong
[] = {
6836 { "en_US", TEST_ULDN_LOCALE
, u
"American English" },
6837 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"American English (Computer)" },
6838 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"American English (Chinese Calendar)" },
6839 { "en_CA", TEST_ULDN_LOCALE
, u
"Canadian English" },
6840 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6841 { "pt_BR", TEST_ULDN_LOCALE
, u
"Brazilian Portuguese" },
6842 { "pt_PT", TEST_ULDN_LOCALE
, u
"European Portuguese" },
6843 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6844 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6845 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6846 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6847 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6848 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6849 { "US", TEST_ULDN_REGION
, u
"United States" },
6850 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6851 { "GB", TEST_ULDN_REGION
, u
"United Kingdom" },
6852 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6855 static const UldnItem en_DiaMidShrt
[] = {
6856 { "en_US", TEST_ULDN_LOCALE
, u
"US English" },
6857 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"US English (Computer)" },
6858 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"US English (Calendar: chinese)" },
6859 { "en_CA", TEST_ULDN_LOCALE
, u
"Canadian English" },
6860 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6861 { "pt_BR", TEST_ULDN_LOCALE
, u
"Brazilian Portuguese" },
6862 { "pt_PT", TEST_ULDN_LOCALE
, u
"European Portuguese" },
6863 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6864 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6865 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6866 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6867 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6868 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6869 { "US", TEST_ULDN_REGION
, u
"US" },
6870 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6871 { "GB", TEST_ULDN_REGION
, u
"UK" },
6872 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6875 static const UldnItem fr_StdMidLong
[] = {
6876 { "en_US", TEST_ULDN_LOCALE
, u
"anglais (É.-U.)" },
6877 { "US", TEST_ULDN_REGION
, u
"États-Unis" },
6878 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6881 static const UldnItem fr_StdMidShrt
[] = {
6882 { "en_US", TEST_ULDN_LOCALE
, u
"anglais (É.-U.)" },
6883 { "US", TEST_ULDN_REGION
, u
"É.-U." },
6884 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6887 static const UldnItem fr_StdBegLong
[] = {
6888 { "en_US", TEST_ULDN_LOCALE
, u
"Anglais (É.-U.)" },
6891 static const UldnItem fr_StdLstLong
[] = {
6892 { "en_US", TEST_ULDN_LOCALE
, u
"Anglais (É.-U.)" },
6893 { "PS", TEST_ULDN_REGION
, u
"Territoires palestiniens" },
6896 static const UldnItem fr_DiaMidLong
[] = {
6897 { "en_US", TEST_ULDN_LOCALE
, u
"anglais américain" },
6900 static const UldnItem ca_StdLstLong
[] = {
6901 { "PS", TEST_ULDN_REGION
, u
"Territoris palestins" },
6904 static const UldnItem ur_StdMidLong
[] = {
6905 { "ps_Arab", TEST_ULDN_LOCALE
, u
"پشتو (عربی)" },
6906 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"پشتو (عربی،افغانستان)" },
6907 { "ur_Aran", TEST_ULDN_LOCALE
, u
"اردو (نستعلیق)" }, // Apple <rdar://problem/47494884>
6908 { "ur_Arab", TEST_ULDN_LOCALE
, u
"اردو (نسخ)" }, // Apple <rdar://problem/50687287>
6909 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"اردو (نستعلیق،پاکستان)" }, // Apple <rdar://problem/47494884>
6910 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"اردو (نسخ،پاکستان)" }, // Apple <rdar://problem/50687287>
6912 { "ps_Arab", TEST_ULOC_LOCALE
, u
"پشتو (عربی)" },
6913 { "ps_Arab_AF", TEST_ULOC_LOCALE
, u
"پشتو (عربی،افغانستان)" },
6914 { "ur_Aran", TEST_ULOC_LOCALE
, u
"اردو (نستعلیق)" }, // Apple <rdar://problem/47494884>
6915 { "ur_Arab", TEST_ULOC_LOCALE
, u
"اردو (نسخ)" }, // Apple <rdar://problem/51418203>
6916 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"اردو (نستعلیق،پاکستان)" }, // Apple <rdar://problem/47494884>
6917 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"اردو (نسخ،پاکستان)" }, // Apple <rdar://problem/51418203>
6920 static const UldnItem pa_Arab_StdMidLong
[] = {
6921 { "pa_Aran", TEST_ULDN_LOCALE
, u
"پنجابی (نستعلیق)" }, // Apple <rdar://problem/47494884>
6922 { "pa_Arab", TEST_ULDN_LOCALE
, u
"پنجابی (نسخ)" }, // Apple <rdar://problem/50687287>
6923 { "pa_Aran_PK", TEST_ULDN_LOCALE
, u
"پنجابی (نستعلیق, پاکستان)" }, // Apple <rdar://problem/47494884>
6924 { "pa_Arab_PK", TEST_ULDN_LOCALE
, u
"پنجابی (نسخ, پاکستان)" }, // Apple <rdar://problem/50687287>
6926 { "pa_Aran", TEST_ULOC_LOCALE
, u
"پنجابی (نستعلیق)" }, // Apple <rdar://problem/51418203>
6927 { "pa_Arab", TEST_ULOC_LOCALE
, u
"پنجابی (نسخ)" }, // Apple <rdar://problem/51418203>
6928 { "pa_Aran_PK", TEST_ULOC_LOCALE
, u
"پنجابی (نستعلیق, پاکستان)" }, // Apple <rdar://problem/51418203>
6929 { "pa_Arab_PK", TEST_ULOC_LOCALE
, u
"پنجابی (نسخ, پاکستان)" }, // Apple <rdar://problem/51418203>
6932 static const UldnItem zh_StdMidLong
[] = {
6933 { "zh_Hans", TEST_ULDN_LOCALE
, u
"简体中文" }, // Apple <rdar://problem/50750364>
6934 { "zh_Hans_CN", TEST_ULDN_LOCALE
, u
"简体中文(中国大陆)" }, // Apple <rdar://problem/50750364>
6935 { "zh_Hant", TEST_ULDN_LOCALE
, u
"繁体中文" }, // Apple <rdar://problem/50750364>
6936 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"繁体中文(香港)" }, // Apple <rdar://problem/50750364>
6937 { "yue_Hans", TEST_ULDN_LOCALE
, u
"简体粤语" }, // Apple <rdar://problem/50750364>
6938 { "yue_Hans_CN", TEST_ULDN_LOCALE
, u
"简体粤语(中国大陆)" }, // Apple <rdar://problem/50750364>
6939 { "yue_Hant", TEST_ULDN_LOCALE
, u
"繁体粤语" }, // Apple <rdar://problem/50750364>
6940 { "yue_Hant_HK", TEST_ULDN_LOCALE
, u
"繁体粤语(香港)" }, // Apple <rdar://problem/50750364>
6941 { "ps_Arab", TEST_ULDN_LOCALE
, u
"普什图语(阿拉伯文)" },
6942 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"普什图语(阿拉伯文,阿富汗)" },
6943 { "ur_Aran", TEST_ULDN_LOCALE
, u
"乌尔都语(波斯体)" }, // Apple <rdar://problem/47494884>
6944 { "ur_Arab", TEST_ULDN_LOCALE
, u
"乌尔都语(誊抄体)" }, // Apple <rdar://problem/50687287>
6945 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"乌尔都语(波斯体,巴基斯坦)" }, // Apple <rdar://problem/47494884>
6946 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"乌尔都语(誊抄体,巴基斯坦)" }, // Apple <rdar://problem/50687287>
6948 { "zh_Hans", TEST_ULOC_LOCALE
, u
"简体中文" }, // Apple <rdar://problem/51418203>
6949 { "zh_Hans_CN", TEST_ULOC_LOCALE
, u
"简体中文(中国大陆)" }, // Apple <rdar://problem/51418203>
6950 { "zh_Hant", TEST_ULOC_LOCALE
, u
"繁体中文" }, // Apple <rdar://problem/51418203>
6951 { "zh_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体中文(香港)" }, // Apple <rdar://problem/51418203>
6952 { "yue_Hans", TEST_ULOC_LOCALE
, u
"简体粤语" }, // Apple <rdar://problem/51418203>
6953 { "yue_Hans_CN", TEST_ULOC_LOCALE
, u
"简体粤语(中国大陆)" }, // Apple <rdar://problem/51418203>
6954 { "yue_Hant", TEST_ULOC_LOCALE
, u
"繁体粤语" }, // Apple <rdar://problem/51418203>
6955 { "yue_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体粤语(香港)" }, // Apple <rdar://problem/51418203>
6956 { "ur_Aran", TEST_ULOC_LOCALE
, u
"乌尔都语(波斯体)" }, // Apple <rdar://problem/47494884>
6957 { "ur_Arab", TEST_ULOC_LOCALE
, u
"乌尔都语(誊抄体)" }, // Apple <rdar://problem/51418203>
6958 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"乌尔都语(波斯体,巴基斯坦)" }, // Apple <rdar://problem/47494884>
6959 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"乌尔都语(誊抄体,巴基斯坦)" }, // Apple <rdar://problem/51418203>
6962 static const UldnItem hi_Latn_StdMidLong
[] = { // Apple <rdar://problem/53216112>
6963 { "en", TEST_ULDN_LOCALE
, u
"English" },
6964 { "hi_Deva", TEST_ULDN_LOCALE
, u
"Hindi (Devanagari)" },
6965 { "hi_Latn", TEST_ULDN_LOCALE
, u
"Hindi (Latin)" },
6966 { "hi_Latn_IN", TEST_ULDN_LOCALE
, u
"Hindi (Latin, Bhaarat)" },
6969 static const UldnItem mni_Beng_StdMidLong
[] = { // Apple <rdar://problem/54153189>
6970 { "mni_Beng", TEST_ULDN_LOCALE
, u
"মৈতৈলোন্ (বাংলা)" },
6971 { "mni_Mtei", TEST_ULDN_LOCALE
, u
"মৈতৈলোন্ (মেইটেই মায়েক)" },
6974 static const UldnItem mni_Mtei_StdMidLong
[] = { // Apple <rdar://problem/54153189>
6975 { "mni_Beng", TEST_ULDN_LOCALE
, u
"ꯃꯤꯇꯩꯂꯣꯟ (ꯕꯪꯂꯥ)" },
6976 { "mni_Mtei", TEST_ULDN_LOCALE
, u
"ꯃꯤꯇꯩꯂꯣꯟ (ꯃꯤꯇꯩ ꯃꯌꯦꯛ)" },
6979 static const UldnItem sat_Olck_StdMidLong
[] = { // Apple <rdar://problem/54153189>
6980 { "sat_Olck", TEST_ULDN_LOCALE
, u
"ᱥᱟᱱᱛᱟᱲᱤ (ᱚᱞ ᱪᱤᱠᱤ)" },
6981 { "sat_Deva", TEST_ULDN_LOCALE
, u
"ᱥᱟᱱᱛᱟᱲᱤ (ᱫᱮᱣᱟᱱᱟᱜᱟᱨᱤ)" },
6984 static const UldnItem sat_Deva_StdMidLong
[] = { // Apple <rdar://problem/54153189>
6985 { "sat_Olck", TEST_ULDN_LOCALE
, u
"सानताड़ी (अल चीकी)" },
6986 { "sat_Deva", TEST_ULDN_LOCALE
, u
"सानताड़ी (देवानागारी)" },
6989 static const UldnLocAndOpts uldnLocAndOpts
[] = {
6990 { "en", optStdMidLong
, en_StdMidLong
, UPRV_LENGTHOF(en_StdMidLong
) },
6991 { "en", optStdMidShrt
, en_StdMidShrt
, UPRV_LENGTHOF(en_StdMidShrt
) },
6992 { "en", optDiaMidLong
, en_DiaMidLong
, UPRV_LENGTHOF(en_DiaMidLong
) },
6993 { "en", optDiaMidShrt
, en_DiaMidShrt
, UPRV_LENGTHOF(en_DiaMidShrt
) },
6994 { "fr", optStdMidLong
, fr_StdMidLong
, UPRV_LENGTHOF(fr_StdMidLong
) },
6995 { "fr", optStdMidShrt
, fr_StdMidShrt
, UPRV_LENGTHOF(fr_StdMidShrt
) },
6996 { "fr", optStdBegLong
, fr_StdBegLong
, UPRV_LENGTHOF(fr_StdBegLong
) },
6997 { "fr", optStdLstLong
, fr_StdLstLong
, UPRV_LENGTHOF(fr_StdLstLong
) },
6998 { "fr_CA", optStdLstLong
, fr_StdLstLong
, UPRV_LENGTHOF(fr_StdLstLong
) },
6999 { "fr", optDiaMidLong
, fr_DiaMidLong
, UPRV_LENGTHOF(fr_DiaMidLong
) },
7000 { "ca", optStdLstLong
, ca_StdLstLong
, UPRV_LENGTHOF(ca_StdLstLong
) },
7001 { "ur", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7002 { "ur_Arab", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7003 { "ur_Aran", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7004 { "pa_Arab", optStdMidLong
, pa_Arab_StdMidLong
, UPRV_LENGTHOF(pa_Arab_StdMidLong
) },
7005 { "pa_Aran", optStdMidLong
, pa_Arab_StdMidLong
, UPRV_LENGTHOF(pa_Arab_StdMidLong
) },
7006 { "zh", optStdMidLong
, zh_StdMidLong
, UPRV_LENGTHOF(zh_StdMidLong
) },
7007 { "hi_Latn", optStdMidLong
, hi_Latn_StdMidLong
, UPRV_LENGTHOF(hi_Latn_StdMidLong
) },
7008 { "mni_Beng", optStdMidLong
, mni_Beng_StdMidLong
, UPRV_LENGTHOF(mni_Beng_StdMidLong
) },
7009 { "mni_Mtei", optStdMidLong
, mni_Mtei_StdMidLong
, UPRV_LENGTHOF(mni_Mtei_StdMidLong
) },
7010 { "sat_Olck", optStdMidLong
, sat_Olck_StdMidLong
, UPRV_LENGTHOF(sat_Olck_StdMidLong
) },
7011 { "sat_Deva", optStdMidLong
, sat_Deva_StdMidLong
, UPRV_LENGTHOF(sat_Deva_StdMidLong
) },
7012 { NULL
, NULL
, NULL
, 0 }
7015 enum { kUNameBuf
= 128, kBNameBuf
= 256 };
7017 static void TestUldnNameVariants() {
7018 const UldnLocAndOpts
* uloPtr
;
7019 for (uloPtr
= uldnLocAndOpts
; uloPtr
->displayLocale
!= NULL
; uloPtr
++) {
7020 UErrorCode status
= U_ZERO_ERROR
;
7021 ULocaleDisplayNames
* uldn
= uldn_openForContext(uloPtr
->displayLocale
, (UDisplayContext
*)uloPtr
->displayOptions
, 3, &status
);
7022 if (U_FAILURE(status
)) {
7023 log_data_err("uldn_openForContext fails, displayLocale %s, contexts %03X %03X %03X: %s - Are you missing data?\n",
7024 uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7025 u_errorName(status
) );
7028 const UldnItem
* itemPtr
= uloPtr
->testItems
;
7029 int32_t itemCount
= uloPtr
->countItems
;
7030 for (; itemCount
-- > 0; itemPtr
++) {
7031 UChar uget
[kUNameBuf
];
7032 int32_t ulenget
, ulenexp
;
7033 const char* typeString
;
7034 status
= U_ZERO_ERROR
;
7035 switch (itemPtr
->nameType
) {
7036 case TEST_ULDN_LOCALE
:
7037 ulenget
= uldn_localeDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7038 typeString
= "uldn_localeDisplayName";
7040 case TEST_ULDN_LANGUAGE
:
7041 ulenget
= uldn_languageDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7042 typeString
= "uldn_languageDisplayName";
7044 case TEST_ULDN_SCRIPT
:
7045 ulenget
= uldn_scriptDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7046 typeString
= "uldn_scriptDisplayName";
7048 case TEST_ULDN_REGION
:
7049 ulenget
= uldn_regionDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7050 typeString
= "uldn_regionDisplayName";
7052 case TEST_ULOC_LOCALE
:
7053 ulenget
= uloc_getDisplayName(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7054 typeString
= "uloc_getDisplayName";
7056 case TEST_ULOC_LANGUAGE
:
7057 ulenget
= uloc_getDisplayLanguage(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7058 typeString
= "uloc_getDisplayLanguage";
7060 case TEST_ULOC_SCRIPT
:
7061 ulenget
= uloc_getDisplayScript(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7062 typeString
= "uloc_getDisplayScript";
7064 case TEST_ULOC_REGION
:
7065 ulenget
= uloc_getDisplayCountry(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7066 typeString
= "uloc_getDisplayCountry";
7071 if (U_FAILURE(status
)) {
7072 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s: %s\n",
7073 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7074 itemPtr
->localeToName
, u_errorName(status
) );
7077 ulenexp
= u_strlen(itemPtr
->expectResult
);
7078 if (ulenget
!= ulenexp
|| u_strncmp(uget
, itemPtr
->expectResult
, ulenexp
) != 0) {
7079 char bexp
[kBNameBuf
], bget
[kBNameBuf
];
7080 u_strToUTF8(bexp
, kBNameBuf
, NULL
, itemPtr
->expectResult
, ulenexp
, &status
);
7081 u_strToUTF8(bget
, kBNameBuf
, NULL
, uget
, ulenget
, &status
);
7082 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s:\n expect %2d: %s\n get %2d: %s\n",
7083 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7084 itemPtr
->localeToName
, ulenexp
, bexp
, ulenget
, bget
);
7092 #define ULOC_UND_TESTNUM 9
7094 static const char* for_empty
[ULOC_UND_TESTNUM
] = { // ""
7096 "", // uloc_getLanguage
7097 "en_Latn_US_POSIX", // uloc_addLikelySubtags
7098 "en__POSIX", // uloc_minimizeSubtags
7099 "en_US_POSIX", // uloc_canonicalize
7100 "", // uloc_getParent
7101 "und", // uloc_toLanguageTag
7102 "", // uloc_getDisplayName in en
7103 "", // uloc_getDisplayLanguage in en
7105 static const char* for_root
[ULOC_UND_TESTNUM
] = { // "root"
7106 "root", // uloc_getName
7107 "root", // uloc_getLanguage
7108 "root", // uloc_addLikelySubtags
7109 "root", // uloc_minimizeSubtags
7110 "root", // uloc_canonicalize
7111 "", // uloc_getParent
7112 "root", // uloc_toLanguageTag
7113 "Root", // uloc_getDisplayName in en
7114 "Root", // uloc_getDisplayLanguage in en
7116 static const char* for_und
[ULOC_UND_TESTNUM
] = { // "und"
7117 "und", // uloc_getName
7118 "und", // uloc_getLanguage
7119 "en_Latn_US", // uloc_addLikelySubtags
7120 "und", // uloc_minimizeSubtags
7121 "und", // uloc_canonicalize
7122 "", // uloc_getParent
7123 "und", // uloc_toLanguageTag
7124 "Unknown language", // uloc_getDisplayName in en
7125 "Unknown language", // uloc_getDisplayLanguage in en
7127 static const char* for_und_ZZ
[ULOC_UND_TESTNUM
] = { // "und_ZZ"
7128 "und_ZZ", // uloc_getName
7129 "und", // uloc_getLanguage
7130 "en_Latn_US", // uloc_addLikelySubtags
7131 "und", // uloc_minimizeSubtags
7132 "und_ZZ", // uloc_canonicalize
7133 "und", // uloc_getParent
7134 "und-ZZ", // uloc_toLanguageTag
7135 "Unknown language (Unknown Region)", // uloc_getDisplayName in en
7136 "Unknown language", // uloc_getDisplayLanguage in en
7138 static const char* for_empty_ZZ
[ULOC_UND_TESTNUM
] = { // "_ZZ"
7139 "_ZZ", // uloc_getName
7140 "", // uloc_getLanguage
7141 "en_Latn_US", // uloc_addLikelySubtags
7142 "und", // uloc_minimizeSubtags
7143 "_ZZ", // uloc_canonicalize
7144 "", // uloc_getParent
7145 "und-ZZ", // uloc_toLanguageTag
7146 "Unknown Region", // uloc_getDisplayName in en
7147 "", // uloc_getDisplayLanguage in en
7151 const char * locale
;
7152 const char ** expResults
;
7155 static const RootUndEmptyItem rootUndEmptryItems
[] = {
7157 { "root", for_root
},
7159 { "und_ZZ", for_und_ZZ
},
7160 { "_ZZ", for_empty_ZZ
},
7164 enum { kULocMax
= 64, kBLocMax
= 128 };
7166 static void TestRootUndEmpty() {
7167 const RootUndEmptyItem
* itemPtr
;
7168 for (itemPtr
= rootUndEmptryItems
; itemPtr
->locale
!= NULL
; itemPtr
++) {
7169 const char* loc
= itemPtr
->locale
;
7170 const char** expResultsPtr
= itemPtr
->expResults
;
7172 char bget
[kBLocMax
];
7173 UChar uexp
[kULocMax
];
7174 UChar uget
[kULocMax
];
7178 status
= U_ZERO_ERROR
;
7179 bexp
= *expResultsPtr
++;
7180 blen
= uloc_getName(loc
, bget
, kBLocMax
, &status
);
7181 if (U_FAILURE(status
)) {
7182 log_err("loc \"%s\", uloc_getName status: %s\n", loc
, u_errorName(status
) );
7183 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7184 log_err("loc \"%s\", uloc_getName expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7187 status
= U_ZERO_ERROR
;
7188 bexp
= *expResultsPtr
++;
7189 blen
= uloc_getLanguage(loc
, bget
, kBLocMax
, &status
);
7190 if (U_FAILURE(status
)) {
7191 log_err("loc \"%s\", uloc_getLanguage status: %s\n", loc
, u_errorName(status
) );
7192 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7193 log_err("loc \"%s\", uloc_getLanguage expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7196 status
= U_ZERO_ERROR
;
7197 bexp
= *expResultsPtr
++;
7198 blen
= uloc_addLikelySubtags(loc
, bget
, kBLocMax
, &status
);
7199 if (U_FAILURE(status
)) {
7200 log_err("loc \"%s\", uloc_addLikelySubtags status: %s\n", loc
, u_errorName(status
) );
7201 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7202 log_err("loc \"%s\", uloc_addLikelySubtags expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7205 status
= U_ZERO_ERROR
;
7206 bexp
= *expResultsPtr
++;
7207 blen
= uloc_minimizeSubtags(loc
, bget
, kBLocMax
, &status
);
7208 if (U_FAILURE(status
)) {
7209 log_err("loc \"%s\", uloc_minimizeSubtags status: %s\n", loc
, u_errorName(status
) );
7210 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7211 log_err("loc \"%s\", uloc_minimizeSubtags expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7214 status
= U_ZERO_ERROR
;
7215 bexp
= *expResultsPtr
++;
7216 blen
= uloc_canonicalize(loc
, bget
, kBLocMax
, &status
);
7217 if (U_FAILURE(status
)) {
7218 log_err("loc \"%s\", uloc_canonicalize status: %s\n", loc
, u_errorName(status
) );
7219 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7220 log_err("loc \"%s\", uloc_canonicalize expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7223 status
= U_ZERO_ERROR
;
7224 bexp
= *expResultsPtr
++;
7225 blen
= uloc_getParent(loc
, bget
, kBLocMax
, &status
);
7226 if (U_FAILURE(status
)) {
7227 log_err("loc \"%s\", uloc_getParent status: %s\n", loc
, u_errorName(status
) );
7228 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7229 log_err("loc \"%s\", uloc_getParent expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7232 status
= U_ZERO_ERROR
;
7233 bexp
= *expResultsPtr
++;
7234 blen
= uloc_toLanguageTag(loc
, bget
, kBLocMax
, TRUE
, &status
);
7235 if (U_FAILURE(status
)) {
7236 log_err("loc \"%s\", uloc_toLanguageTag status: %s\n", loc
, u_errorName(status
) );
7237 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7238 log_err("loc \"%s\", uloc_toLanguageTag expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7241 status
= U_ZERO_ERROR
;
7242 bexp
= *expResultsPtr
++;
7243 u_unescape(bexp
, uexp
, kULocMax
);
7244 uexp
[kULocMax
-1] = 0; // force zero term
7245 ulen
= uloc_getDisplayName(loc
, "en", uget
, kULocMax
, &status
);
7246 if (U_FAILURE(status
)) {
7247 log_err("loc \"%s\", uloc_getDisplayName en status: %s\n", loc
, u_errorName(status
) );
7248 } else if (u_strcmp(uget
, uexp
) != 0) {
7249 u_austrncpy(bget
, uget
, kBLocMax
);
7250 bget
[kBLocMax
-1] = 0;
7251 log_err("loc \"%s\", uloc_getDisplayName en expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7254 status
= U_ZERO_ERROR
;
7255 bexp
= *expResultsPtr
++;
7256 u_unescape(bexp
, uexp
, kULocMax
);
7257 uexp
[kULocMax
-1] = 0; // force zero term
7258 ulen
= uloc_getDisplayLanguage(loc
, "en", uget
, kULocMax
, &status
);
7259 if (U_FAILURE(status
)) {
7260 log_err("loc \"%s\", uloc_getDisplayLanguage en status: %s\n", loc
, u_errorName(status
) );
7261 } else if (u_strcmp(uget
, uexp
) != 0) {
7262 u_austrncpy(bget
, uget
, kBLocMax
);
7263 bget
[kBLocMax
-1] = 0;
7264 log_err("loc \"%s\", uloc_getDisplayLanguage en expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7270 #if !U_PLATFORM_HAS_WIN32_API
7271 /* Apple-specific, test for Apple-specific function ualoc_getAppleParent */
7272 static const char* localesAndAppleParent
[] = {
7343 "zh_HK", "zh_Hant_HK",
7344 "zh-HK", "zh_Hant_HK",
7346 "zh-Hant-HK", "zh_Hant",
7347 "zh_Hant_HK", "zh_Hant",
7348 "zh-Hant-MO", "zh_Hant_HK",
7349 "zh-Hans-HK", "zh_Hans",
7352 "en-Latn-US", "en_Latn",
7353 "en_US_POSIX", "en_US",
7354 "en_Latn_US_POSIX", "en_Latn_US",
7355 "en-u-ca-hebrew", "root",
7356 "en@calendar=hebrew", "root",
7357 "en_@calendar=hebrew", "root",
7360 "Default@2x", "root",
7362 NULL
/* terminator */
7365 static void TestGetAppleParent() {
7366 const char **localesPtr
= localesAndAppleParent
;
7367 const char * locale
;
7368 while ((locale
= *localesPtr
++) != NULL
) {
7369 const char * expectParent
= *localesPtr
++;
7370 UErrorCode status
= U_ZERO_ERROR
;
7371 char getParent
[ULOC_FULLNAME_CAPACITY
];
7372 int32_t plen
= ualoc_getAppleParent(locale
, getParent
, ULOC_FULLNAME_CAPACITY
, &status
);
7373 if (U_FAILURE(status
)) {
7374 log_err("FAIL: ualoc_getAppleParent input \"%s\", status %s\n", locale
, u_errorName(status
));
7375 } else if (uprv_strcmp(expectParent
, getParent
) != 0) {
7376 log_err("FAIL: ualoc_getAppleParent input \"%s\", expected parent \"%s\", got parent \"%s\"\n", locale
, expectParent
, getParent
);
7381 /* Apple-specific, test for Apple-specific function ualoc_getLanguagesForRegion */
7382 enum { kUALanguageEntryMax
= 10 };
7384 static void TestGetLanguagesForRegion() {
7385 UALanguageEntry entries
[kUALanguageEntryMax
];
7388 const char * region
;
7390 status
= U_ZERO_ERROR
;
7392 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
7393 if (U_FAILURE(status
)) {
7394 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7396 // Expect approximately:
7397 // zh_Hans 0.90 UALANGSTATUS_OFFICIAL
7400 // yue 0.043 Yue including Cantonese
7405 // ug_Arab 0.0055 Uighur UALANGSTATUS_REGIONAL_OFFICIAL
7406 // ...at least 4 more with fractions >= 0.001
7407 if (entryCount
< kUALanguageEntryMax
) {
7408 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7410 UALanguageEntry
* entryPtr
= entries
;
7411 if (uprv_strcmp(entryPtr
->languageCode
, "zh_Hans") != 0 || entryPtr
->userFraction
< 0.8 || entryPtr
->userFraction
> 1.0 || entryPtr
->status
!= UALANGSTATUS_OFFICIAL
) {
7412 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entryPtr
->languageCode
, entryPtr
->userFraction
, (int)entryPtr
->status
);
7414 for (entryPtr
++; entryPtr
< entries
+ kUALanguageEntryMax
&& uprv_strcmp(entryPtr
->languageCode
, "ug_Arab") != 0; entryPtr
++)
7416 if (entryPtr
< entries
+ kUALanguageEntryMax
) {
7417 // we found ug_Arab, make sure it has correct status
7418 if (entryPtr
->status
!= UALANGSTATUS_REGIONAL_OFFICIAL
) {
7419 log_err("FAIL: ualoc_getLanguagesForRegion %s, ug_Arab had incorrect status %d\n", (int)entryPtr
->status
);
7422 // did not find ug_Arab
7423 log_err("FAIL: ualoc_getLanguagesForRegion %s, entries did not include ug_Arab\n", region
);
7428 status
= U_ZERO_ERROR
;
7430 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
7431 if (U_FAILURE(status
)) {
7432 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7434 // Expect approximately:
7435 // en 0.85 UALANGSTATUS_OFFICIAL
7436 // fr 0.22 UALANGSTATUS_OFFICIAL
7438 if (entryCount
< 2) {
7439 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7441 if (uprv_strcmp(entries
[0].languageCode
, "en") != 0 || entries
[0].userFraction
< 0.7 || entries
[0].userFraction
> 1.0 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
7442 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
7444 if (uprv_strcmp(entries
[1].languageCode
, "fr") != 0 || entries
[1].userFraction
< 0.1 || entries
[1].userFraction
> 1.0 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
7445 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
7450 status
= U_ZERO_ERROR
;
7452 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, NULL
, 0, &status
);
7453 if (U_FAILURE(status
)) {
7454 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7456 if (entryCount
< 40) {
7457 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7461 status
= U_ZERO_ERROR
;
7463 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
7464 if (U_FAILURE(status
)) {
7465 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7467 // Expect approximately:
7468 // fo 0.93 UALANGSTATUS_OFFICIAL
7469 // da 0.03 UALANGSTATUS_OFFICIAL
7471 if (entryCount
< 2) {
7472 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7474 if (uprv_strcmp(entries
[0].languageCode
, "fo") != 0 || entries
[0].userFraction
< 0.90 || entries
[0].userFraction
> 0.98 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
7475 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
7477 if (uprv_strcmp(entries
[1].languageCode
, "da") != 0 || entries
[1].userFraction
< 0.02 || entries
[1].userFraction
> 0.04 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
7478 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
7484 /* data for TestAppleLocalizationsToUse */
7487 const char * const *locs
;
7489 } AppleLocsAndCount
;
7491 enum { kNumLocSets
= 6 };
7494 const char * language
;
7495 const char ** expLocsForSets
[kNumLocSets
];
7499 static const char * appleLocs1
[] = {
7533 static const char * appleLocs2
[] = {
7540 "en", "en_AU", "en_GB",
7564 "zh_CN", "zh_HK", "zh_TW",
7567 static const char * appleLocs3
[] = {
7574 "en", "en_AU", "en_CA", "en_GB",
7577 "fr", "fr_CA", "fr_FR",
7582 "it", "it_CH", // <rdar://problem/35829322>
7589 "pt", "pt_BR", "pt_PT",
7598 "zh_CN", "zh_HK", "zh_MO", "zh_TW",
7601 static const char * appleLocs4
[] = {
7602 "en", "en_AU", "en_CA", "en_GB", "en_IN", "en_US",
7603 "es", "es_419", "es_MX",
7604 "fr", "fr_CA", "fr_CH", "fr_FR",
7605 "it", "it_CH", "it_IT", // <rdar://problem/35829322>
7606 "nl", "nl_BE", "nl_NL",
7608 "ro", "ro_MD", "ro_RO",
7609 "zh_Hans", "zh_Hant", "zh_Hant_HK",
7612 static const char * appleLocs5
[] = {
7613 "en", "en_001", "en_AU", "en_GB",
7614 "es", "es_ES", "es_MX",
7615 "zh_CN", "zh_Hans", "zh_Hant", "zh_TW",
7625 static const char * appleLocs6
[] = {
7626 "en", "en_001", "en_150", "en_AU", "en_GB",
7627 "es", "es_419", "es_ES", "es_MX",
7628 "zh_CN", "zh_Hans", "zh_Hant", "zh_Hant_HK", "zh_HK", "zh_TW",
7635 static const AppleLocsAndCount locAndCountEntries
[kNumLocSets
] = {
7636 { appleLocs1
, UPRV_LENGTHOF(appleLocs1
) },
7637 { appleLocs2
, UPRV_LENGTHOF(appleLocs2
) },
7638 { appleLocs3
, UPRV_LENGTHOF(appleLocs3
) },
7639 { appleLocs4
, UPRV_LENGTHOF(appleLocs4
) },
7640 { appleLocs5
, UPRV_LENGTHOF(appleLocs5
) },
7641 { appleLocs6
, UPRV_LENGTHOF(appleLocs6
) },
7645 static const char* l1_ar
[] = { "ar", NULL
};
7646 static const char* l1_Ara
[] = { "Arabic", NULL
};
7647 static const char* l1_ca
[] = { "ca", NULL
};
7648 static const char* l1_cs
[] = { "cs", NULL
};
7649 static const char* l1_da
[] = { "da", NULL
};
7650 static const char* l1_Dan
[] = { "Danish", NULL
};
7651 static const char* l1_de
[] = { "de", NULL
};
7652 static const char* l1_Ger
[] = { "German", NULL
};
7653 static const char* l1_el
[] = { "el", NULL
};
7654 static const char* l1_en
[] = { "en", NULL
};
7655 static const char* l1_Eng
[] = { "English", NULL
};
7656 static const char* l2_en_001_
[] = { "en_001", "en", NULL
};
7657 static const char* l2_en_CA_
[] = { "en_CA", "en", NULL
};
7658 static const char* l2_en_GB_
[] = { "en_GB", "en", NULL
};
7659 static const char* l2_en_US_
[] = { "en_US", "en", NULL
};
7660 static const char* l2_en_GB_Eng
[] = { "en_GB", "English", NULL
};
7661 static const char* l3_en_GB001_
[] = { "en_GB", "en_001", "en", NULL
};
7662 static const char* l3_en_AUGB_
[] = { "en_AU", "en_GB", "en", NULL
};
7663 static const char* l3_en_INGB_
[] = { "en_IN", "en_GB", "en", NULL
};
7664 static const char* l4_en_150GB001_
[] = { "en_150", "en_GB", "en_001", "en", NULL
};
7665 static const char* l4_en_AUGB001_
[] = { "en_AU", "en_GB", "en_001", "en", NULL
};
7666 static const char* l1_es
[] = { "es", NULL
};
7667 static const char* l1_Spa
[] = { "Spanish", NULL
};
7668 static const char* l2_es_419_
[] = { "es_419", "es", NULL
};
7669 static const char* l2_es_ES_
[] = { "es_ES", "es", NULL
};
7670 static const char* l2_es_MX_
[] = { "es_MX", "es", NULL
};
7671 static const char* l2_es_MX_Spa
[] = { "es_MX", "Spanish", NULL
};
7672 static const char* l3_es_MX419_
[] = { "es_MX", "es_419", "es", NULL
};
7673 static const char* l1_fi
[] = { "fi", NULL
};
7674 static const char* l1_Fin
[] = { "Finnish", NULL
};
7675 static const char* l1_fil
[] = { "fil", NULL
};
7676 static const char* l1_tl
[] = { "tl", NULL
};
7677 static const char* l1_fr
[] = { "fr", NULL
};
7678 static const char* l1_Fre
[] = { "French", NULL
};
7679 static const char* l2_fr_CA_
[] = { "fr_CA", "fr", NULL
};
7680 static const char* l2_fr_CH_
[] = { "fr_CH", "fr", NULL
};
7681 static const char* l2_fr_FR_
[] = { "fr_FR", "fr", NULL
};
7682 static const char* l1_haw
[] = { "haw", NULL
};
7683 static const char* l1_he
[] = { "he", NULL
};
7684 static const char* l1_hr
[] = { "hr", NULL
};
7685 static const char* l1_hu
[] = { "hu", NULL
};
7686 static const char* l1_id
[] = { "id", NULL
};
7687 static const char* l1_in
[] = { "in", NULL
};
7688 static const char* l1_it
[] = { "it", NULL
};
7689 static const char* l2_it_CH
[] = { "it_CH", "it", NULL
}; // <rdar://problem/35829322>
7690 static const char* l2_it_IT
[] = { "it_IT", "it", NULL
}; // <rdar://problem/35829322>
7691 static const char* l1_Ita
[] = { "Italian", NULL
};
7692 static const char* l1_ja
[] = { "ja", NULL
};
7693 static const char* l1_Japn
[] = { "Japanese", NULL
};
7694 static const char* l1_ko
[] = { "ko", NULL
};
7695 static const char* l1_Kor
[] = { "Korean", NULL
};
7696 static const char* l1_ms
[] = { "ms", NULL
};
7697 static const char* l1_nb
[] = { "nb", NULL
};
7698 static const char* l1_no
[] = { "no", NULL
};
7699 static const char* l1_Nor
[] = { "Norwegian", NULL
};
7700 static const char* l2_no_NO_
[] = { "no_NO", "no", NULL
};
7701 static const char* l1_nl
[] = { "nl", NULL
};
7702 static const char* l1_Dut
[] = { "Dutch", NULL
};
7703 static const char* l2_nl_BE_
[] = { "nl_BE", "nl", NULL
};
7704 static const char* l1_pl
[] = { "pl", NULL
};
7705 static const char* l1_Pol
[] = { "Polish", NULL
};
7706 static const char* l1_pt
[] = { "pt", NULL
};
7707 static const char* l1_pt_PT
[] = { "pt_PT", NULL
};
7708 static const char* l1_Port
[] = { "Portuguese", NULL
};
7709 static const char* l2_pt_BR_
[] = { "pt_BR", "pt", NULL
};
7710 static const char* l2_pt_PT_
[] = { "pt_PT", "pt", NULL
};
7711 static const char* l1_ro
[] = { "ro", NULL
};
7712 static const char* l2_ro_MD_
[] = { "ro_MD", "ro", NULL
};
7713 static const char* l1_mo
[] = { "mo", NULL
};
7714 static const char* l1_ru
[] = { "ru", NULL
};
7715 static const char* l1_Rus
[] = { "Russian", NULL
};
7716 static const char* l1_sk
[] = { "sk", NULL
};
7717 static const char* l1_sr
[] = { "sr", NULL
};
7718 static const char* l1_srLatn
[] = { "sr-Latn", NULL
};
7719 static const char* l1_sv
[] = { "sv", NULL
};
7720 static const char* l1_Swe
[] = { "Swedish", NULL
};
7721 static const char* l1_th
[] = { "th", NULL
};
7722 static const char* l1_Thai
[] = { "Thai", NULL
};
7723 static const char* l1_tlh
[] = { "tlh", NULL
};
7724 static const char* l1_tr
[] = { "tr", NULL
};
7725 static const char* l1_Tur
[] = { "Turkish", NULL
};
7726 static const char* l1_uk
[] = { "uk", NULL
};
7727 static const char* l1_vi
[] = { "vi", NULL
};
7728 static const char* l1_yi
[] = { "yi", NULL
};
7729 static const char* l1_iw
[] = { "iw", NULL
};
7730 static const char* l1_zh_CN
[] = { "zh_CN", NULL
};
7731 static const char* l1_zh_TW
[] = { "zh_TW", NULL
};
7732 static const char* l1_zh_Hans
[] = { "zh_Hans", NULL
};
7733 static const char* l1_zh_Hant
[] = { "zh_Hant", NULL
};
7734 static const char* l1_zhHant
[] = { "zh-Hant", NULL
};
7735 static const char* l2_zh_HKTW
[] = { "zh_HK", "zh_TW", NULL
};
7736 static const char* l2_zh_Hant_HK_
[] = { "zh_Hant_HK", "zh_Hant", NULL
};
7737 static const char* l2_zh_CN_Hans
[] = { "zh_CN", "zh_Hans", NULL
};
7738 static const char* l2_zh_TW_Hant
[] = { "zh_TW", "zh_Hant", NULL
};
7739 static const char* l3_zh_MOHKTW
[] = { "zh_MO", "zh_HK", "zh_TW", NULL
};
7740 static const char* l3_zh_HK_HantHK_Hant
[] = { "zh_HK", "zh_Hant_HK", "zh_Hant", NULL
};
7742 static const LangAndExpLocs appleLangAndLoc
[] = {
7743 // language\ result for appleLocs1 appleLocs2 appleLocs3 appleLocs4 appleLocs5 appleLocs6
7744 { "zh", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
7745 { "zh-Hans", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
7746 { "zh-Hant", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} },
7747 { "zh-Hans-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
7748 { "zh-Hans-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
7749 { "zh-Hant-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
7750 { "zh-Hant-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
7751 { "zh-Hant-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
7752 { "zh-Hans-HK", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
7753 { "zh-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
7754 { "zh-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
7755 { "zh-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
7756 { "zh-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HK_HantHK_Hant
} },
7757 { "zh-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
7758 { "en", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7759 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
7760 { "en_US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
7761 { "en-CN", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7762 { "en-JP", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7763 { "en-TW", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7764 { "en-TR", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7765 { "en-001", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
7766 { "en-CA", { l1_Eng
, l1_en
, l2_en_CA_
, l2_en_CA_
, l2_en_001_
, l2_en_001_
} },
7767 { "en-IL", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
7768 { "en-GB", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7769 { "en-IN", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l3_en_INGB_
, l3_en_GB001_
, l3_en_GB001_
} },
7770 { "en-BD", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7771 { "en-LK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7772 { "en-GG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7773 { "en-HK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7774 { "en-IE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7775 { "en-JM", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7776 { "en-MO", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7777 { "en-MT", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7778 { "en-PK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7779 { "en-SG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7780 { "en-VG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7781 { "en-ZA", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
7782 { "en-AU", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
7783 { "en-NZ", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
7784 { "en-WS", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
7785 { "en-150", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
7786 { "en-FR", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
7787 { "en-BE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
7788 { "en-Latn", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7789 { "en-Latn-US", { l1_Eng
, l1_en
, l1_en
, l1_en
,/*TODO*/ l1_en
, l1_en
} },
7790 { "en-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
7791 { "en-Latn-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7792 { "en-u-ca-hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7793 { "en@calendar=hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7794 { "en-", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7795 { "en_", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
7796 { "es", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
7797 { "es-ES", { l1_Spa
, l1_es
, l1_es
, l1_es
, l2_es_ES_
, l2_es_ES_
} },
7798 { "es-419", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7799 { "es-MX", { l1_Spa
, l2_es_MX_
, l2_es_419_
, l3_es_MX419_
, l2_es_MX_
, l3_es_MX419_
} },
7800 { "es-AR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7801 { "es-BO", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} }, // <rdar://problem/34459988>
7802 { "es-BR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7803 { "es-BZ", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7804 { "es-AG", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7805 { "es-AW", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7806 { "es-CA", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7807 { "es-CW", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7808 { "es-SX", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7809 { "es-TT", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
7810 { "es-Latn", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
7811 { "es-Latn-MX", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
7812 { "pt", { l1_Port
, l1_pt
, l1_pt
, l1_pt
, NULL
, NULL
} },
7813 { "pt-BR", { l1_Port
, l1_pt
, l2_pt_BR_
, l2_pt_BR_
, NULL
, NULL
} },
7814 { "pt-PT", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7815 { "pt-MO", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7816 { "pt-CH", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7817 { "pt-FR", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7818 { "pt-GQ", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7819 { "pt-LU", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
7820 { "fr", { l1_Fre
, l1_fr
, l1_fr
, l1_fr
, NULL
, NULL
} },
7821 { "fr-FR", { l1_Fre
, l1_fr
, l2_fr_FR_
, l2_fr_FR_
, NULL
, NULL
} },
7822 { "fr-CA", { l1_Fre
, l2_fr_CA_
, l2_fr_CA_
, l2_fr_CA_
, NULL
, NULL
} },
7823 { "fr-CH", { l1_Fre
, l1_fr
, l1_fr
, l2_fr_CH_
, NULL
, NULL
} },
7824 { "ar", { l1_Ara
, l1_ar
, l1_ar
, NULL
, NULL
, NULL
} },
7825 { "da", { l1_Dan
, l1_da
, l1_da
, NULL
, NULL
, NULL
} },
7826 { "nl", { l1_Dut
, l1_nl
, l1_nl
, l1_nl
, NULL
, NULL
} },
7827 { "nl-BE", { l1_Dut
, l1_nl
, l1_nl
, l2_nl_BE_
, NULL
, NULL
} },
7828 { "fi", { l1_Fin
, l1_fi
, l1_fi
, NULL
, NULL
, NULL
} },
7829 { "de", { l1_Ger
, l1_de
, l1_de
, NULL
, NULL
, NULL
} },
7830 { "it", { l1_Ita
, l1_it
, l1_it
, l1_it
, NULL
, NULL
} },
7831 { "it_CH", { l1_Ita
, l1_it
, l2_it_CH
, l2_it_CH
, NULL
, NULL
} }, // <rdar://problem/35829322>
7832 { "it_IT", { l1_Ita
, l1_it
, l1_it
, l2_it_IT
, NULL
, NULL
} }, // <rdar://problem/35829322>
7833 { "it_VA", { l1_Ita
, l1_it
, l1_it
, l1_it
, NULL
, NULL
} }, // <rdar://problem/35829322>
7834 { "ja", { l1_Japn
, l1_ja
, l1_ja
, NULL
, NULL
, NULL
} },
7835 { "ko", { l1_Kor
, l1_ko
, l1_ko
, NULL
, NULL
, NULL
} },
7836 { "nb", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
7837 { "no", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
7838 { "pl", { l1_Pol
, l1_pl
, l1_pl
, NULL
, NULL
, NULL
} },
7839 { "ru", { l1_Rus
, l1_ru
, l1_ru
, NULL
, NULL
, NULL
} },
7840 { "sv", { l1_Swe
, l1_sv
, l1_sv
, NULL
, NULL
, NULL
} },
7841 { "th", { l1_Thai
, l1_th
, l1_th
, NULL
, NULL
, NULL
} },
7842 { "tr", { l1_Tur
, l1_tr
, l1_tr
, NULL
, NULL
, NULL
} },
7843 { "ca", { l1_ca
, l1_ca
, l1_ca
, NULL
, NULL
, NULL
} },
7844 { "cs", { l1_cs
, l1_cs
, l1_cs
, NULL
, NULL
, NULL
} },
7845 { "el", { l1_el
, l1_el
, l1_el
, NULL
, NULL
, NULL
} },
7846 { "he", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
7847 { "iw", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
7848 { "hr", { l1_hr
, l1_hr
, l1_hr
, NULL
, NULL
, NULL
} },
7849 { "hu", { l1_hu
, l1_hu
, l1_hu
, NULL
, NULL
, NULL
} },
7850 { "id", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
7851 { "in", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
7852 { "ms", { l1_ms
, l1_ms
, l1_ms
, NULL
, NULL
, NULL
} },
7853 { "ro", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, l1_mo
} },
7854 { "mo", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, l1_mo
} },
7855 { "sk", { l1_sk
, l1_sk
, l1_sk
, NULL
, NULL
, NULL
} },
7856 { "uk", { l1_uk
, l1_uk
, l1_uk
, NULL
, NULL
, NULL
} },
7857 { "vi", { l1_vi
, l1_vi
, l1_vi
, NULL
, NULL
, NULL
} },
7858 { "yi", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
7859 { "ji", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
7860 { "fil", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
7861 { "tl", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
7862 { "haw", { NULL
, NULL
, NULL
, NULL
, l1_haw
, NULL
} },
7863 { "sr", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
7864 { "sr-Cyrl", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
7865 { "sr-Latn", { NULL
, NULL
, NULL
, NULL
, l1_srLatn
, NULL
} },
7866 { "tlh", { NULL
, NULL
, NULL
, NULL
, l1_tlh
, NULL
} },
7867 { "Default@2x", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7868 { "default", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7869 { "root", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7870 { "", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7871 { "_US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7872 { "-US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7873 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7874 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7875 { "@calendar=hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
7877 enum { kNumAppleLangAndLoc
= UPRV_LENGTHOF(appleLangAndLoc
) };
7879 /* tests from <rdar://problem/21518031> */
7881 static const char * appleLocsA1
[] = { "en", "fr", "no", "zh-Hant" };
7882 static const char * appleLocsA2
[] = { "en", "fr", "nb", "zh_TW", "zh_CN", "zh-Hant" };
7883 static const char * appleLocsA3
[] = { "en", "en_IN", "en_GB", "fr", "de", "zh_TW" };
7884 static const char * appleLocsA4
[] = { "Spanish", "es_MX", "English", "en_GB" };
7885 static const char * appleLocsA5
[] = { "en", "fr", "de", "pt", "pt_PT" };
7886 static const char * appleLocsA6
[] = { "en", "no", "no_NO", "pt_PT" };
7888 static const AppleLocsAndCount locAndCountEntriesA
[kNumLocSets
] = {
7889 { appleLocsA1
, UPRV_LENGTHOF(appleLocsA1
) },
7890 { appleLocsA2
, UPRV_LENGTHOF(appleLocsA2
) },
7891 { appleLocsA3
, UPRV_LENGTHOF(appleLocsA3
) },
7892 { appleLocsA4
, UPRV_LENGTHOF(appleLocsA4
) },
7893 { appleLocsA5
, UPRV_LENGTHOF(appleLocsA5
) },
7894 { appleLocsA6
, UPRV_LENGTHOF(appleLocsA6
) },
7897 static const LangAndExpLocs appleLangAndLocA
[] = {
7898 // language\ result for appleLocsA1 appleLocsA2 appleLocsA3 appleLocsA4 appleLocsA5 appleLocsA6
7899 { "zh-Hant", { l1_zhHant
,/*0*/ l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
7900 { "zh_Hant", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
7901 { "zh_HK", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
7902 { "en_IN", { l1_en
, l1_en
, l3_en_INGB_
, l2_en_GB_Eng
, l1_en
, l1_en
} },
7903 { "es_MX", { NULL
, NULL
, NULL
, l2_es_MX_Spa
, NULL
, NULL
} },
7904 { "pt_PT", { NULL
, NULL
, NULL
, NULL
, l2_pt_PT_
, l1_pt_PT
} },
7905 { "pt", { NULL
, NULL
, NULL
, NULL
, l1_pt
, l1_pt_PT
} },
7906 { "no", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
7907 { "no_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
7908 { "nb", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
7909 { "nb_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
7911 enum { kNumAppleLangAndLocA
= UPRV_LENGTHOF(appleLangAndLocA
) };
7913 /* tests from log attached to 21682790 */
7915 static const char * appleLocsB1
[] = {
7916 "ar", "Base", "ca", "cs",
7917 "da", "Dutch", "el", "English",
7918 "es_MX", "fi", "French", "German",
7919 "he", "hr", "hu", "id",
7920 "Italian", "Japanese", "ko", "ms",
7921 "no", "pl", "pt", "pt_PT",
7922 "ro", "ru", "sk", "Spanish",
7923 "sv", "th", "tr", "uk",
7924 "vi", "zh_CN", "zh_TW"
7927 static const char * appleLocsB2
[] = {
7929 "da", "Dutch", "el", "English",
7930 "es_MX", "fi", "French", "German",
7931 "he", "hr", "hu", "id",
7932 "Italian", "Japanese", "ko", "ms",
7933 "no", "pl", "pt", "pt_PT",
7934 "ro", "ru", "sk", "Spanish",
7935 "sv", "th", "tr", "uk",
7936 "vi", "zh_CN", "zh_TW"
7939 static const char * appleLocsB3
[] = {
7940 "ar", "ca", "cs", "da",
7941 "de", "el", "en", "es",
7942 "es_MX", "fi", "French", "he",
7943 "hr", "hu", "id", "Italian",
7944 "ja", "ko", "ms", "nl",
7945 "no", "pl", "pt", "pt_PT",
7946 "ro", "ru", "sk", "sv",
7947 "th", "tr", "uk", "vi",
7951 static const char * appleLocsB4
[] = {
7952 "ar", "ca", "cs", "da",
7953 "de", "el", "en", "es",
7954 "es_MX", "fi", "fr", "he",
7955 "hr", "hu", "id", "it",
7956 "ja", "ko", "ms", "nl",
7957 "no", "pl", "pt", "pt_PT",
7958 "ro", "ru", "sk", "sv",
7959 "th", "tr", "uk", "vi",
7963 static const char * appleLocsB5
[] = { "en" };
7965 static const char * appleLocsB6
[] = { "English" };
7967 static const AppleLocsAndCount locAndCountEntriesB
[kNumLocSets
] = {
7968 { appleLocsB1
, UPRV_LENGTHOF(appleLocsB1
) },
7969 { appleLocsB2
, UPRV_LENGTHOF(appleLocsB2
) },
7970 { appleLocsB3
, UPRV_LENGTHOF(appleLocsB3
) },
7971 { appleLocsB4
, UPRV_LENGTHOF(appleLocsB4
) },
7972 { appleLocsB5
, UPRV_LENGTHOF(appleLocsB5
) },
7973 { appleLocsB6
, UPRV_LENGTHOF(appleLocsB6
) },
7976 static const LangAndExpLocs appleLangAndLocB
[] = {
7977 // language\ result for appleLocsB1 appleLocsB2 appleLocsB3 appleLocsB4 appleLocsB5 appleLocsB6
7978 // Prefs 1, logged with sets B1-B3
7979 { "en", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
7980 { "es", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
7981 // Prefs 2, logged with sets B1-B6
7982 { "English", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
7983 { "Spanish", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
7985 enum { kNumAppleLangAndLocB
= UPRV_LENGTHOF(appleLangAndLocB
) };
7988 const AppleLocsAndCount
* locAndCountEntriesPtr
;
7989 const LangAndExpLocs
* appleLangAndLocPtr
;
7990 int32_t appleLangAndLocCount
;
7991 } AppleLocToUseTestSet
;
7993 static const AppleLocToUseTestSet altuTestSets
[] = {
7994 { locAndCountEntries
, appleLangAndLoc
, kNumAppleLangAndLoc
},
7995 { locAndCountEntriesA
, appleLangAndLocA
, kNumAppleLangAndLocA
},
7996 { locAndCountEntriesB
, appleLangAndLocB
, kNumAppleLangAndLocB
},
8000 /* tests for multiple prefs sets */
8002 static const char * appleLocsM1
[] = { "en", "en_GB", "pt", "pt_PT", "zh_CN", "zh_Hant" };
8003 static const char * prefLangsM1
[] = { "tlh", "zh_HK", "zh_SG", "zh_Hans", "pt_BR", "pt_PT", "en_IN", "en" };
8004 static const char * locsToUseM1
[] = { "zh_Hant" };
8006 // Tests from first pass at <rdar://problem/22012864>, 2015-11-18
8008 static const char * appleLocsM2
[] = { "fr-FR", "en-US", "en-GB" };
8009 static const char * prefLangsM2
[] = { "fr-CH" };
8010 static const char * locsToUseM2
[] = { "fr-FR" };
8012 static const char * appleLocsM3
[] = { "es-es", "fr-fr" };
8013 static const char * prefLangsM3
[] = { "fr-US", "fr", "en-US" };
8014 static const char * locsToUseM3
[] = { "fr-fr" };
8016 static const char * appleLocsM4
[] = { "es-es", "fr-fr", "fr" };
8017 static const char * prefLangsM4
[] = { "fr-US", "fr", "en-US" };
8018 static const char * locsToUseM4
[] = { "fr" };
8020 // Tests from second pass at <rdar://problem/22012864>, 2015-12-08
8022 static const char * appleLocsM5
[] = { "en-US", "fr-FR", "de-DE", "es-ES", "es-419", "pt-PT", "pt-BR", "zh-CN", "zh-TW", "zh-HK", "ja-JP", "ko-KR" };
8023 static const char * prefLangsM5
[] = { "fr-US", "en-US" };
8024 static const char * locsToUseM5
[] = { "fr-FR" };
8025 // Per Peter E; expected result changed from "en-US" to "de-CH" per <rdar://problem/26559053>
8026 static const char * appleLocsM6
[] = { "de-CH", "en-US" };
8027 static const char * prefLangsM6
[] = { "de-DE", "en-US" };
8028 static const char * locsToUseM6
[] = { "de-CH" };
8029 // The following is used for M7-MD
8030 static const char * appleLocsMx
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-HK", "zh-TW" };
8032 static const char * prefLangsM7
[] = { "fr-ES", "en-AU" };
8033 static const char * locsToUseM7
[] = { "fr-FR" };
8035 static const char * prefLangsM8
[] = { "de-IT", "en-AU" };
8036 static const char * locsToUseM8
[] = { "de-DE" };
8038 static const char * prefLangsM9
[] = { "hi-US", "en-AU" };
8039 static const char * locsToUseM9
[] = { "hi-IN" };
8041 static const char * prefLangsMA
[] = { "en-IN", "zh-HK" };
8042 static const char * locsToUseMA
[] = { "en-AU" };
8044 static const char * prefLangsMB
[] = { "pt-PT", "en-AU" };
8045 static const char * locsToUseMB
[] = { "en-AU" };
8047 static const char * prefLangsMC
[] = { "pt-PT", "ar" };
8048 static const char * locsToUseMC
[] = { "pt-BR" };
8050 static const char * prefLangsMD
[] = { "zh-CN", "en-AU" };
8051 static const char * locsToUseMD
[] = { "en-AU" };
8053 static const char * appleLocsME
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-CN", "zh-HK" };
8054 static const char * prefLangsME
[] = { "zh-TW", "en-AU" };
8055 static const char * locsToUseME
[] = { "zh-HK" };
8056 // Per Peter E in diagnosis for <rdar://problem/22012864> and <rdar://problem/23815194>
8057 static const char * appleLocsMF
[] = { "en", "en-GB", "fr", "es" };
8058 static const char * prefLangsMF
[] = { "en-IN", "en-GB", "de", "fr" };
8059 static const char * locsToUseMF
[] = { "en-GB", "en" };
8060 // Per Karan M in <rdar://problem/23982460>
8061 static const char * appleLocsMG
[] = { "zh-Hans", "zh-Hant", "zh-HK" };
8062 static const char * prefLangsMG
[] = { "zh-Hans-US", "zh-HK", "en-US" };
8063 static const char * locsToUseMG
[] = { "zh-Hans" };
8064 // Per <rdar://problem/25903891>
8065 static const char * appleLocsMH
[] = { "zh-TW", "zh-CN", "zh-HK" };
8066 static const char * prefLangsMH
[] = { "zh-Hans-HK", "zh-HK", "en" };
8067 static const char * locsToUseMH
[] = { "zh-CN" };
8068 // Per <rdar://problem/26559053>
8069 static const char * appleLocsMI
[] = { "unk", "en-US", "ar-SA" };
8070 static const char * prefLangsMI
[] = { "ar-US" };
8071 static const char * locsToUseMI
[] = { "ar-SA" };
8072 // Per <rdar://problem/30501523> - first for comparison with zh, then real test
8073 static const char * appleLocsMJ
[] = { "zh-CN", "en-US" };
8074 static const char * prefLangsMJ
[] = { "zh", "zh_AC" };
8075 static const char * locsToUseMJ
[] = { "zh-CN" };
8076 static const char * appleLocsMK
[] = { "yue-CN", "en-US" };
8077 static const char * prefLangsMK
[] = { "yue", "yue_AC" };
8078 static const char * locsToUseMK
[] = { "yue-CN" };
8079 // Per <rdar://problem/30433534>
8080 static const char * appleLocsML
[] = { "nl_NL", "es_MX", "fr_FR", "zh_TW", "it_IT", "vi_VN", "fr_CH", "es_CL",
8081 "en_ZA", "ko_KR", "ca_ES", "ro_RO", "en_PH", "en_CA", "en_SG", "en_IN",
8082 "en_NZ", "it_CH", "fr_CA", "da_DK", "de_AT", "pt_BR", "yue_CN", "zh_CN",
8083 "sv_SE", "es_ES", "ar_SA", "hu_HU", "fr_BE", "en_GB", "ja_JP", "zh_HK",
8084 "fi_FI", "tr_TR", "nb_NO", "en_ID", "en_SA", "pl_PL", "ms_MY", "cs_CZ",
8085 "el_GR", "id_ID", "hr_HR", "en_AE", "he_IL", "ru_RU", "wuu_CN", "de_DE",
8086 "de_CH", "en_AU", "nl_BE", "th_TH", "pt_PT", "sk_SK", "en_US", "en_IE",
8087 "es_CO", "uk_UA", "es_US" };
8088 static const char * prefLangsML
[] = { "en-JP" };
8089 static const char * locsToUseML
[] = { "en_US" };
8090 // Per <rdar://problem/32421203>
8091 static const char * appleLocsMM1
[] = { "pt-PT" };
8092 static const char * appleLocsMM2
[] = { "pt-BR" };
8093 static const char * appleLocsMM3
[] = { "pt-PT", "pt-BR" };
8094 static const char * appleLocsMM4
[] = { "en", "pt-PT" };
8095 static const char * appleLocsMM5
[] = { "en", "pt-BR" };
8096 static const char * appleLocsMM6
[] = { "en", "pt-PT", "pt-BR" };
8097 static const char * prefLangsMM1
[] = { "pt-PT" };
8098 static const char * prefLangsMM2
[] = { "pt-BR" };
8099 static const char * prefLangsMM3
[] = { "pt" };
8100 static const char * prefLangsMM4
[] = { "pt-PT", "en" };
8101 static const char * prefLangsMM5
[] = { "pt-BR", "en" };
8102 static const char * prefLangsMM6
[] = { "pt", "en" };
8103 static const char * locsToUseMMptPT
[] = { "pt-PT" };
8104 static const char * locsToUseMMptBR
[] = { "pt-BR" };
8105 static const char * locsToUseMMen
[] = { "en" };
8106 // Per <rdar://problem/32658828>
8107 static const char * appleLocsMN
[] = { "en-US", "en-GB" };
8108 static const char * prefLangsMN1
[] = { "en-KR" };
8109 static const char * prefLangsMN2
[] = { "en-SA" };
8110 static const char * prefLangsMN3
[] = { "en-TW" };
8111 static const char * prefLangsMN4
[] = { "en-JP" };
8112 static const char * locsToUseMN_U
[] = { "en-US" };
8113 // Per <rdar://problem/36010857>
8114 static const char * appleLocsMO
[] = { "Dutch", "French", "German", "Italian", "Japanese", "Spanish",
8115 "ar", "ca", "cs", "da", "el", "en_AU", "en_GB", "en_IN",
8116 "es_419", "fi", "fr_CA", "he", "hi", "hr", "hu", "id", "ko",
8117 "ms", "no", "pl", "pt", "pt_PT", "ro", "ru", "sk", "sv",
8118 "th", "tr", "uk", "vi", "zh_CN", "zh_HK", "zh_TW" };
8119 static const char * prefLangsMO1
[] = { "en-US" };
8120 static const char * locsToUseMO1
[] = { "en_GB" };
8121 // Per <rdar://problem/47494729>
8122 static const char * appleLocsMP
[] = { "en-IN", "hi-IN" };
8123 static const char * prefLangsMP
[] = { "hi-Latn-IN", "en-IN" };
8124 static const char * locsToUseMP
[] = { "en-IN" };
8125 // Per <rdar://problem/34459988&35829322>
8126 static const char * appleLocsMQa
[] = { "en_AU", "en_IE", "en_IN", "en_SA", "en_UK", "en_US", "es_AR", "es_CO", "es_ES", "es_MX", "fr_CA", "fr_FR", "it_CH", "it_IT", "zh_CN", "zh_HK", "zh_TW" };
8127 static const char * appleLocsMQb
[] = { "en_AU", "en_IE", "en_IN", "en_SA", "en_UK", "en", "es_AR", "es_CO", "es", "es_MX", "fr_CA", "fr", "it_CH", "it", "zh_CN", "zh_HK", "zh_TW" };
8128 static const char * prefLangsMQ1
[] = { "es-BO" };
8129 static const char * locsToUseMQ1
[] = { "es_MX" };
8130 static const char * prefLangsMQ2
[] = { "it-VA" };
8131 static const char * locsToUseMQ2a
[] = { "it_IT" };
8132 static const char * locsToUseMQ2b
[] = { "it" };
8133 // Per <rdar://problem/50913699>
8134 static const char * appleLocsMRa
[] = { "en", "hi" };
8135 static const char * appleLocsMRb
[] = { "en", "hi", "hi_Latn" };
8136 static const char * prefLangsMRx
[] = { "hi_Latn_IN", "en_IN", "hi_IN" };
8137 static const char * prefLangsMRy
[] = { "hi_Latn", "en", "hi" };
8138 static const char * locsToUseMRa
[] = { "en" };
8139 static const char * locsToUseMRb
[] = { "hi_Latn", "en" };
8140 // For <rdar://problem/50280505>
8141 static const char * appleLocsMSa
[] = { "en", "en_GB" };
8142 static const char * appleLocsMSb
[] = { "en", "en_GB", "en_AU" };
8143 static const char * prefLangsMSx
[] = { "en_NZ" };
8144 static const char * prefLangsMSy
[] = { "en_NZ", "en_AU" };
8145 static const char * locsToUseMSa
[] = { "en_GB", "en" };
8146 static const char * locsToUseMSb
[] = { "en_AU", "en_GB", "en" };
8150 const char ** availLocs
;
8151 int32_t availLocsCount
;
8152 const char ** prefLangs
;
8153 int32_t prefLangsCount
;
8154 const char ** locsToUse
;
8155 int32_t locsToUseCount
;
8158 static const MultiPrefTest multiTestSets
[] = {
8159 { "M1", appleLocsM1
, UPRV_LENGTHOF(appleLocsM1
), prefLangsM1
, UPRV_LENGTHOF(prefLangsM1
), locsToUseM1
, UPRV_LENGTHOF(locsToUseM1
) },
8161 { "M2", appleLocsM2
, UPRV_LENGTHOF(appleLocsM2
), prefLangsM2
, UPRV_LENGTHOF(prefLangsM2
), locsToUseM2
, UPRV_LENGTHOF(locsToUseM2
) },
8162 { "M3", appleLocsM3
, UPRV_LENGTHOF(appleLocsM3
), prefLangsM3
, UPRV_LENGTHOF(prefLangsM3
), locsToUseM3
, UPRV_LENGTHOF(locsToUseM3
) },
8163 { "M4", appleLocsM4
, UPRV_LENGTHOF(appleLocsM4
), prefLangsM4
, UPRV_LENGTHOF(prefLangsM4
), locsToUseM4
, UPRV_LENGTHOF(locsToUseM4
) },
8165 { "M5", appleLocsM5
, UPRV_LENGTHOF(appleLocsM5
), prefLangsM5
, UPRV_LENGTHOF(prefLangsM5
), locsToUseM5
, UPRV_LENGTHOF(locsToUseM5
) },
8166 { "M6", appleLocsM6
, UPRV_LENGTHOF(appleLocsM6
), prefLangsM6
, UPRV_LENGTHOF(prefLangsM6
), locsToUseM6
, UPRV_LENGTHOF(locsToUseM6
) },
8167 { "M7", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM7
, UPRV_LENGTHOF(prefLangsM7
), locsToUseM7
, UPRV_LENGTHOF(locsToUseM7
) },
8168 { "M8", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM8
, UPRV_LENGTHOF(prefLangsM8
), locsToUseM8
, UPRV_LENGTHOF(locsToUseM8
) },
8169 { "M9", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM9
, UPRV_LENGTHOF(prefLangsM9
), locsToUseM9
, UPRV_LENGTHOF(locsToUseM9
) },
8170 { "MA", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMA
, UPRV_LENGTHOF(prefLangsMA
), locsToUseMA
, UPRV_LENGTHOF(locsToUseMA
) },
8171 { "MB", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMB
, UPRV_LENGTHOF(prefLangsMB
), locsToUseMB
, UPRV_LENGTHOF(locsToUseMB
) },
8172 { "MC", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMC
, UPRV_LENGTHOF(prefLangsMC
), locsToUseMC
, UPRV_LENGTHOF(locsToUseMC
) },
8173 { "MD", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMD
, UPRV_LENGTHOF(prefLangsMD
), locsToUseMD
, UPRV_LENGTHOF(locsToUseMD
) },
8174 { "ME", appleLocsME
, UPRV_LENGTHOF(appleLocsME
), prefLangsME
, UPRV_LENGTHOF(prefLangsME
), locsToUseME
, UPRV_LENGTHOF(locsToUseME
) },
8175 { "MF", appleLocsMF
, UPRV_LENGTHOF(appleLocsMF
), prefLangsMF
, UPRV_LENGTHOF(prefLangsMF
), locsToUseMF
, UPRV_LENGTHOF(locsToUseMF
) },
8176 { "MG", appleLocsMG
, UPRV_LENGTHOF(appleLocsMG
), prefLangsMG
, UPRV_LENGTHOF(prefLangsMG
), locsToUseMG
, UPRV_LENGTHOF(locsToUseMG
) },
8177 { "MH", appleLocsMH
, UPRV_LENGTHOF(appleLocsMH
), prefLangsMH
, UPRV_LENGTHOF(prefLangsMH
), locsToUseMH
, UPRV_LENGTHOF(locsToUseMH
) },
8178 { "MI", appleLocsMI
, UPRV_LENGTHOF(appleLocsMI
), prefLangsMI
, UPRV_LENGTHOF(prefLangsMI
), locsToUseMI
, UPRV_LENGTHOF(locsToUseMI
) },
8179 { "MJ", appleLocsMJ
, UPRV_LENGTHOF(appleLocsMJ
), prefLangsMJ
, UPRV_LENGTHOF(prefLangsMJ
), locsToUseMJ
, UPRV_LENGTHOF(locsToUseMJ
) },
8180 { "MK", appleLocsMK
, UPRV_LENGTHOF(appleLocsMK
), prefLangsMK
, UPRV_LENGTHOF(prefLangsMK
), locsToUseMK
, UPRV_LENGTHOF(locsToUseMK
) },
8181 { "ML", appleLocsML
, UPRV_LENGTHOF(appleLocsML
), prefLangsML
, UPRV_LENGTHOF(prefLangsML
), locsToUseML
, UPRV_LENGTHOF(locsToUseML
) },
8182 { "MM11", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8183 { "MM21", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8184 { "MM31", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8185 { "MM41", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8186 { "MM51", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8187 { "MM61", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8188 { "MM12", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8189 { "MM22", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8190 { "MM32", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8191 { "MM42", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8192 { "MM52", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8193 { "MM62", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8194 { "MM13", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8195 { "MM23", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8196 { "MM33", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8197 { "MM43", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8198 { "MM53", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8199 { "MM63", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8200 { "MM14", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8201 { "MM24", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8202 { "MM34", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8203 { "MM44", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8204 { "MM54", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMen
, UPRV_LENGTHOF(locsToUseMMen
) }, // want en, see <rdar://problem/22012864>
8205 { "MM64", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8206 { "MM15", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8207 { "MM25", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8208 { "MM35", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8209 { "MM45", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8210 { "MM55", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8211 { "MM65", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8212 { "MM16", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8213 { "MM26", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8214 { "MM36", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8215 { "MM46", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8216 { "MM56", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8217 { "MM66", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8218 { "MN1", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN1
, UPRV_LENGTHOF(prefLangsMN1
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8219 { "MN2", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN2
, UPRV_LENGTHOF(prefLangsMN2
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8220 { "MN3", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN3
, UPRV_LENGTHOF(prefLangsMN3
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8221 { "MN4", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN4
, UPRV_LENGTHOF(prefLangsMN4
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8222 { "MO", appleLocsMO
, UPRV_LENGTHOF(appleLocsMO
), prefLangsMO1
, UPRV_LENGTHOF(prefLangsMO1
), locsToUseMO1
, UPRV_LENGTHOF(locsToUseMO1
) },
8223 { "MP", appleLocsMP
, UPRV_LENGTHOF(appleLocsMP
), prefLangsMP
, UPRV_LENGTHOF(prefLangsMP
), locsToUseMP
, UPRV_LENGTHOF(locsToUseMP
) },
8224 { "MQ1a", appleLocsMQa
, UPRV_LENGTHOF(appleLocsMQa
), prefLangsMQ1
, UPRV_LENGTHOF(prefLangsMQ1
), locsToUseMQ1
, UPRV_LENGTHOF(locsToUseMQ1
) },
8225 // { "MQ1b", appleLocsMQb, UPRV_LENGTHOF(appleLocsMQb), prefLangsMQ1, UPRV_LENGTHOF(prefLangsMQ1), locsToUseMQ1, UPRV_LENGTHOF(locsToUseMQ1) }, // still to do for <rdar://problem/34459988>
8226 { "MQ2a", appleLocsMQa
, UPRV_LENGTHOF(appleLocsMQa
), prefLangsMQ2
, UPRV_LENGTHOF(prefLangsMQ2
), locsToUseMQ2a
, UPRV_LENGTHOF(locsToUseMQ2a
) },
8227 { "MQ2b", appleLocsMQb
, UPRV_LENGTHOF(appleLocsMQb
), prefLangsMQ2
, UPRV_LENGTHOF(prefLangsMQ2
), locsToUseMQ2b
, UPRV_LENGTHOF(locsToUseMQ2b
) },
8228 { "MRa", appleLocsMRa
, UPRV_LENGTHOF(appleLocsMRa
), prefLangsMRx
, UPRV_LENGTHOF(prefLangsMRx
), locsToUseMRa
, UPRV_LENGTHOF(locsToUseMRa
) },
8229 { "MRb", appleLocsMRb
, UPRV_LENGTHOF(appleLocsMRb
), prefLangsMRx
, UPRV_LENGTHOF(prefLangsMRx
), locsToUseMRb
, UPRV_LENGTHOF(locsToUseMRb
) },
8230 { "MRa", appleLocsMRa
, UPRV_LENGTHOF(appleLocsMRa
), prefLangsMRy
, UPRV_LENGTHOF(prefLangsMRy
), locsToUseMRa
, UPRV_LENGTHOF(locsToUseMRa
) },
8231 { "MRb", appleLocsMRb
, UPRV_LENGTHOF(appleLocsMRb
), prefLangsMRy
, UPRV_LENGTHOF(prefLangsMRy
), locsToUseMRb
, UPRV_LENGTHOF(locsToUseMRb
) },
8232 { "MSax", appleLocsMSa
, UPRV_LENGTHOF(appleLocsMSa
), prefLangsMSx
, UPRV_LENGTHOF(prefLangsMSx
), locsToUseMSa
, UPRV_LENGTHOF(locsToUseMSa
) },
8233 { "MSay", appleLocsMSa
, UPRV_LENGTHOF(appleLocsMSa
), prefLangsMSy
, UPRV_LENGTHOF(prefLangsMSy
), locsToUseMSa
, UPRV_LENGTHOF(locsToUseMSa
) },
8234 { "MSbx", appleLocsMSb
, UPRV_LENGTHOF(appleLocsMSb
), prefLangsMSx
, UPRV_LENGTHOF(prefLangsMSx
), locsToUseMSb
, UPRV_LENGTHOF(locsToUseMSb
) },
8235 { "MSby", appleLocsMSb
, UPRV_LENGTHOF(appleLocsMSb
), prefLangsMSy
, UPRV_LENGTHOF(prefLangsMSy
), locsToUseMSb
, UPRV_LENGTHOF(locsToUseMSb
) },
8237 { NULL
, NULL
, 0, NULL
, 0, NULL
, 0 }
8243 enum { kMaxLocalizationsToUse
= 8, kPrintArrayBufSize
= 128 };
8245 // array, array of pointers to strings to print
8246 // count, count of array elements, may be -1 if array is terminated by a NULL entry
8247 // buf, buffer into which to put concatenated strings
8248 // bufSize, length of buf
8249 static void printStringArray(const char **array
, int32_t count
, char *buf
, int32_t bufSize
) {
8250 char * bufPtr
= buf
;
8251 const char * curEntry
;
8252 int32_t idx
, countMax
= bufSize
/16;
8253 if (count
< 0 || count
> countMax
) {
8256 for (idx
= 0; idx
< count
&& (curEntry
= *array
++) != NULL
; idx
++) {
8257 int32_t len
= sprintf(bufPtr
, "%s\"%.12s\"", (idx
> 0)? ", ": "", curEntry
);
8263 *bufPtr
= 0; /* ensure termination */
8266 static UBool
equalStringArrays(const char **array1
, int32_t count1
, const char **array2
, int32_t count2
) {
8267 const char ** array1Ptr
= array1
;
8268 const char ** array2Ptr
= array2
;
8272 while (*array1Ptr
++ != NULL
) {
8278 while (*array2Ptr
++ != NULL
) {
8282 if (count1
!= count2
) {
8285 for (idx
= 0; idx
< count1
; idx
++) {
8286 if (uprv_strcmp(array1
[idx
], array2
[idx
]) != 0) {
8293 static void TestAppleLocalizationsToUse() {
8294 const AppleLocToUseTestSet
* testSetPtr
;
8295 const MultiPrefTest
* multiSetPtr
;
8296 const char * locsToUse
[kMaxLocalizationsToUse
];
8297 int32_t numLocsToUse
;
8299 char printExpected
[kPrintArrayBufSize
];
8300 char printActual
[kPrintArrayBufSize
];
8302 for (testSetPtr
= altuTestSets
; testSetPtr
->locAndCountEntriesPtr
!= NULL
; testSetPtr
++) {
8303 int32_t iLocSet
, iLang
;
8305 for (iLocSet
= 0; iLocSet
< kNumLocSets
; iLocSet
++) {
8306 for (iLang
= 0; iLang
< testSetPtr
->appleLangAndLocCount
; iLang
++) {
8307 const char * language
= testSetPtr
->appleLangAndLocPtr
[iLang
].language
;
8308 const char ** expLocsForSet
= testSetPtr
->appleLangAndLocPtr
[iLang
].expLocsForSets
[iLocSet
];
8309 status
= U_ZERO_ERROR
;
8311 numLocsToUse
= ualoc_localizationsToUse(&language
, 1,
8312 testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locs
, testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locCount
,
8313 locsToUse
, kMaxLocalizationsToUse
, &status
);
8314 if (U_FAILURE(status
)) {
8315 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, status %s\n",
8316 testSetPtr
-altuTestSets
, iLocSet
+1, language
, u_errorName(status
));
8317 } else if (numLocsToUse
== 0 && expLocsForSet
!= NULL
) {
8318 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
8319 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect {%s}, get no results\n",
8320 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
);
8321 } else if (numLocsToUse
> 0 && expLocsForSet
== NULL
) {
8322 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8323 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect no results, get {%s}\n",
8324 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printActual
);
8325 } else if (numLocsToUse
> 0 && !equalStringArrays(expLocsForSet
, -1, locsToUse
, numLocsToUse
)) {
8326 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
8327 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8328 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s:\n expect {%s}\n get {%s}\n",
8329 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
, printActual
);
8335 for (multiSetPtr
= multiTestSets
; multiSetPtr
->name
!= NULL
; multiSetPtr
++) {
8336 status
= U_ZERO_ERROR
;
8337 numLocsToUse
= ualoc_localizationsToUse(multiSetPtr
->prefLangs
, multiSetPtr
->prefLangsCount
, multiSetPtr
->availLocs
, multiSetPtr
->availLocsCount
, locsToUse
, kMaxLocalizationsToUse
, &status
);
8338 if (U_FAILURE(status
)) {
8339 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s, status %s\n", multiSetPtr
->name
, multiSetPtr
->name
, u_errorName(status
));
8340 } else if (!equalStringArrays(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, locsToUse
, numLocsToUse
)) {
8341 printStringArray(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, printExpected
, kPrintArrayBufSize
);
8342 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8343 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s:\n expect {%s}\n get {%s}\n",
8344 multiSetPtr
->name
, multiSetPtr
->name
, printExpected
, printActual
);