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 // These test functionality that does not exist in the AAS/Windows version of Apple ICU
66 static void TestGetLanguagesForRegion(void);
67 static void TestGetAppleParent(void);
68 static void TestAppleLocalizationsToUsePerf(void);
69 static void TestAppleLocalizationsToUse(void);
71 static void TestNorwegianDisplayNames(void);
72 static void TestSpecificDisplayNames(void);
74 void PrintDataTable();
76 /*---------------------------------------------------
78 --------------------------------------------------- */
80 #define LOCALE_INFO_SIZE 28
82 static const char* const rawData2
[LOCALE_INFO_SIZE
][LOCALE_SIZE
] = {
84 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
86 { "", "", "", "", "", "", "", "", "" },
88 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
90 { "", "", "", "", "NY", "", "", "", "" },
92 { "en_US", "fr_FR", "ca_ES",
93 "el_GR", "no_NO_NY", "zh_Hans_CN",
94 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
96 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
98 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
100 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
102 /* display language (English) */
103 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
104 /* display script code (English) */
105 { "", "", "", "", "", "Simplified Han", "", "", "" },
106 /* display country (English) */
107 { "United States", "France", "Spain", "Greece", "Norway", "China mainland", "Germany", "", "Japan" },
108 /* display variant (English) */
109 { "", "", "", "", "NY", "", "", "", "" },
110 /* display name (English) */
111 { "English (United States)", "French (France)", "Catalan (Spain)",
112 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese, Simplified (China mainland)",
113 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
115 /* display language (French) */
116 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
117 /* display script code (French) */
118 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
119 /* display country (French) */
120 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine continentale", "Allemagne", "", "Japon" },
121 /* display variant (French) */
122 { "", "", "", "", "NY", "", "", "", "" },
123 /* display name (French) */
124 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
125 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois simplifi\\u00e9 (Chine continentale)",
126 "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
128 /* display language (Catalan) */
129 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
130 /* display script code (Catalan) */
131 { "", "", "", "", "", "han simplificat", "", "", "" },
132 /* display country (Catalan) */
133 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina continental", "Alemanya", "", "Jap\\u00F3" },
134 /* display variant (Catalan) */
135 { "", "", "", "", "NY", "", "", "", "" },
136 /* display name (Catalan) */
137 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
138 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s simplificat (Xina continental)",
139 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
141 /* display language (Greek) */
143 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
144 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
145 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
146 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
147 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
148 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
149 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
150 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
151 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
153 /* display script code (Greek) */
155 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
156 /* display country (Greek) */
158 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
159 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
160 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
161 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
162 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
163 "\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE",
164 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
166 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
168 /* display variant (Greek) */
169 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
170 /* display name (Greek) */
172 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
173 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
174 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
175 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
176 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
177 "\\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)",
178 "\\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)",
179 "\\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)",
180 "\\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)"
184 static UChar
*** dataTable
=0;
224 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
226 void addLocaleTest(TestNode
** root
);
228 void addLocaleTest(TestNode
** root
)
230 TESTCASE(TestObsoleteNames
); /* srl- move */
231 TESTCASE(TestBasicGetters
);
232 TESTCASE(TestNullDefault
);
233 TESTCASE(TestPrefixes
);
234 TESTCASE(TestSimpleResourceInfo
);
235 TESTCASE(TestDisplayNames
);
236 TESTCASE(TestGetAvailableLocales
);
237 TESTCASE(TestGetAvailableLocalesByType
);
238 TESTCASE(TestDataDirectory
);
239 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
240 TESTCASE(TestISOFunctions
);
242 TESTCASE(TestISO3Fallback
);
243 TESTCASE(TestUninstalledISO3Names
);
244 TESTCASE(TestSimpleDisplayNames
);
245 TESTCASE(TestVariantParsing
);
246 TESTCASE(TestKeywordVariants
);
247 TESTCASE(TestKeywordVariantParsing
);
248 TESTCASE(TestCanonicalization
);
249 TESTCASE(TestCanonicalizationBuffer
);
250 TESTCASE(TestKeywordSet
);
251 TESTCASE(TestKeywordSetError
);
252 TESTCASE(TestDisplayKeywords
);
253 TESTCASE(TestDisplayKeywordValues
);
254 TESTCASE(TestGetBaseName
);
255 #if !UCONFIG_NO_FILE_IO
256 TESTCASE(TestGetLocale
);
258 TESTCASE(TestDisplayNameWarning
);
259 TESTCASE(TestNonexistentLanguageExemplars
);
260 TESTCASE(TestLocDataErrorCodeChaining
);
261 TESTCASE(TestLocDataWithRgTag
);
262 TESTCASE(TestLanguageExemplarsFallbacks
);
263 TESTCASE(TestCalendar
);
264 TESTCASE(TestDateFormat
);
265 TESTCASE(TestCollation
);
266 TESTCASE(TestULocale
);
267 TESTCASE(TestUResourceBundle
);
268 TESTCASE(TestDisplayName
);
269 TESTCASE(TestAcceptLanguage
);
270 TESTCASE(TestGetLocaleForLCID
);
271 TESTCASE(TestOrientation
);
272 TESTCASE(TestLikelySubtags
);
273 TESTCASE(TestToLanguageTag
);
274 TESTCASE(TestBug20132
);
275 TESTCASE(TestBug20149
);
276 TESTCASE(TestForLanguageTag
);
277 TESTCASE(TestLangAndRegionCanonicalize
);
278 TESTCASE(TestTrailingNull
);
279 TESTCASE(TestUnicodeDefines
);
280 TESTCASE(TestEnglishExemplarCharacters
);
281 TESTCASE(TestDisplayNameBrackets
);
282 TESTCASE(TestIsRightToLeft
);
283 TESTCASE(TestToUnicodeLocaleKey
);
284 TESTCASE(TestToLegacyKey
);
285 TESTCASE(TestToUnicodeLocaleType
);
286 TESTCASE(TestToLegacyType
);
287 TESTCASE(TestBadLocaleIDs
);
288 TESTCASE(TestBug20370
);
289 TESTCASE(TestBug20321UnicodeLocaleKey
);
290 TESTCASE(TestUldnNameVariants
);
291 TESTCASE(TestRootUndEmpty
);
292 #if !U_PLATFORM_HAS_WIN32_API
293 // These test functionality that does not exist in the AAS/Windows version of Apple ICU
294 TESTCASE(TestGetLanguagesForRegion
);
295 TESTCASE(TestGetAppleParent
);
296 TESTCASE(TestAppleLocalizationsToUsePerf
); // must be the first test to call ualoc_localizationsToUse
297 TESTCASE(TestAppleLocalizationsToUse
);
299 TESTCASE(TestNorwegianDisplayNames
);
300 TESTCASE(TestSpecificDisplayNames
);
304 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
305 static void TestBasicGetters() {
308 UErrorCode status
= U_ZERO_ERROR
;
309 char *testLocale
= 0;
310 char *temp
= 0, *name
= 0;
311 log_verbose("Testing Basic Getters\n");
312 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
313 testLocale
=(char*)malloc(sizeof(char) * (strlen(rawData2
[NAME
][i
])+1));
314 strcpy(testLocale
,rawData2
[NAME
][i
]);
316 log_verbose("Testing %s .....\n", testLocale
);
317 cap
=uloc_getLanguage(testLocale
, NULL
, 0, &status
);
318 if(status
==U_BUFFER_OVERFLOW_ERROR
){
320 temp
=(char*)malloc(sizeof(char) * (cap
+1));
321 uloc_getLanguage(testLocale
, temp
, cap
+1, &status
);
323 if(U_FAILURE(status
)){
324 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status
));
326 if (0 !=strcmp(temp
,rawData2
[LANG
][i
])) {
327 log_err(" Language code mismatch: %s versus %s\n", temp
, rawData2
[LANG
][i
]);
331 cap
=uloc_getCountry(testLocale
, temp
, cap
, &status
);
332 if(status
==U_BUFFER_OVERFLOW_ERROR
){
334 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
335 uloc_getCountry(testLocale
, temp
, cap
+1, &status
);
337 if(U_FAILURE(status
)){
338 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status
));
340 if (0 != strcmp(temp
, rawData2
[CTRY
][i
])) {
341 log_err(" Country code mismatch: %s versus %s\n", temp
, rawData2
[CTRY
][i
]);
345 cap
=uloc_getVariant(testLocale
, temp
, cap
, &status
);
346 if(status
==U_BUFFER_OVERFLOW_ERROR
){
348 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
349 uloc_getVariant(testLocale
, temp
, cap
+1, &status
);
351 if(U_FAILURE(status
)){
352 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status
));
354 if (0 != strcmp(temp
, rawData2
[VAR
][i
])) {
355 log_err("Variant code mismatch: %s versus %s\n", temp
, rawData2
[VAR
][i
]);
358 cap
=uloc_getName(testLocale
, NULL
, 0, &status
);
359 if(status
==U_BUFFER_OVERFLOW_ERROR
){
361 name
=(char*)malloc(sizeof(char) * (cap
+1));
362 uloc_getName(testLocale
, name
, cap
+1, &status
);
363 } else if(status
==U_ZERO_ERROR
) {
364 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale
);
366 if(U_FAILURE(status
)){
367 log_err("ERROR: in uloc_getName %s\n", myErrorName(status
));
369 if (0 != strcmp(name
, rawData2
[NAME
][i
])){
370 log_err(" Mismatch in getName: %s versus %s\n", name
, rawData2
[NAME
][i
]);
380 static void TestNullDefault() {
381 UErrorCode status
= U_ZERO_ERROR
;
382 char original
[ULOC_FULLNAME_CAPACITY
];
384 uprv_strcpy(original
, uloc_getDefault());
385 uloc_setDefault("qq_BLA", &status
);
386 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
387 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
389 uloc_setDefault(NULL
, &status
);
390 if (uprv_strcmp(uloc_getDefault(), original
) != 0) {
391 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
395 /* Test that set & get of default locale work, and that
396 * default locales are cached and reused, and not overwritten.
400 const char *n2_en_US
;
402 status
= U_ZERO_ERROR
;
403 uloc_setDefault("en_US", &status
);
404 n_en_US
= uloc_getDefault();
405 if (strcmp(n_en_US
, "en_US") != 0) {
406 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
409 uloc_setDefault("fr_FR", &status
);
410 n_fr_FR
= uloc_getDefault();
411 if (strcmp(n_en_US
, "en_US") != 0) {
412 log_err("uloc_setDefault altered previously default string."
413 "Expected \"en_US\", got \"%s\"\n", n_en_US
);
415 if (strcmp(n_fr_FR
, "fr_FR") != 0) {
416 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR
);
419 uloc_setDefault("en_US", &status
);
420 n2_en_US
= uloc_getDefault();
421 if (strcmp(n2_en_US
, "en_US") != 0) {
422 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
424 if (n2_en_US
!= n_en_US
) {
425 log_err("Default locale cache failed to reuse en_US locale.\n");
428 if (U_FAILURE(status
)) {
429 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status
));
435 /* Test the i- and x- and @ and . functionality
438 #define PREFIXBUFSIZ 128
440 static void TestPrefixes() {
443 const char *loc
, *expected
;
445 static const char * const testData
[][7] =
447 /* NULL canonicalize() column means "expect same as getName()" */
448 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL
},
449 {"en", "", "GB", "", "en-gb", "en_GB", NULL
},
450 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL
},
451 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL
},
452 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL
},
453 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL
},
454 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", "hyw"},
455 {"de", "", "", "1901", "de-1901", "de__1901", NULL
},
456 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
457 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
458 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
459 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
460 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
461 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
462 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
463 {"no", "", "", "NY", "no__ny", "no__NY", NULL
},
464 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
465 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL
},
466 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL
},
467 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL
},
468 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL
},
469 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL
}, /* total garbage */
471 // Before ICU 64, ICU locale canonicalization had some additional mappings.
472 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
473 // The following now use standard canonicalization.
474 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans__PINYIN"},
475 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW_STROKE"},
477 {NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
}
480 static const char * const testTitles
[] = {
481 "uloc_getLanguage()",
487 "uloc_canonicalize()"
490 char buf
[PREFIXBUFSIZ
];
495 for(row
=0;testData
[row
][0] != NULL
;row
++) {
496 loc
= testData
[row
][NAME
];
497 log_verbose("Test #%d: %s\n", row
, loc
);
502 for(n
=0;n
<=(NAME
+2);n
++) {
503 if(n
==NAME
) continue;
505 for(len
=0;len
<PREFIXBUFSIZ
;len
++) {
506 buf
[len
] = '%'; /* Set a tripwire.. */
512 len
= uloc_getLanguage(loc
, buf
, PREFIXBUFSIZ
, &err
);
516 len
= uloc_getScript(loc
, buf
, PREFIXBUFSIZ
, &err
);
520 len
= uloc_getCountry(loc
, buf
, PREFIXBUFSIZ
, &err
);
524 len
= uloc_getVariant(loc
, buf
, PREFIXBUFSIZ
, &err
);
528 len
= uloc_getName(loc
, buf
, PREFIXBUFSIZ
, &err
);
532 len
= uloc_canonicalize(loc
, buf
, PREFIXBUFSIZ
, &err
);
541 log_err("#%d: %s on %s: err %s\n",
542 row
, testTitles
[n
], loc
, u_errorName(err
));
544 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
545 row
, testTitles
[n
], loc
, buf
, len
);
547 if(len
!= (int32_t)strlen(buf
)) {
548 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
549 row
, testTitles
[n
], loc
, buf
, len
, strlen(buf
)+1);
553 /* see if they smashed something */
554 if(buf
[len
+1] != '%') {
555 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
556 row
, testTitles
[n
], loc
, buf
, buf
[len
+1]);
559 expected
= testData
[row
][n
];
560 if (expected
== NULL
&& n
== (NAME
+2)) {
561 /* NULL expected canonicalize() means "expect same as getName()" */
562 expected
= testData
[row
][NAME
+1];
564 if(strcmp(buf
, expected
)) {
565 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
566 row
, testTitles
[n
], loc
, buf
, expected
);
575 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
576 static void TestSimpleResourceInfo() {
578 char* testLocale
= 0;
583 testLocale
=(char*)malloc(sizeof(char) * 1);
584 expected
=(UChar
*)malloc(sizeof(UChar
) * 1);
587 log_verbose("Testing getISO3Language and getISO3Country\n");
588 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
590 testLocale
=(char*)realloc(testLocale
, sizeof(char) * (u_strlen(dataTable
[NAME
][i
])+1));
591 u_austrcpy(testLocale
, dataTable
[NAME
][i
]);
593 log_verbose("Testing %s ......\n", testLocale
);
595 temp
=uloc_getISO3Language(testLocale
);
596 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
597 u_uastrcpy(expected
,temp
);
598 if (0 != u_strcmp(expected
, dataTable
[LANG3
][i
])) {
599 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected
),
600 austrdup(dataTable
[LANG3
][i
]));
603 temp
=uloc_getISO3Country(testLocale
);
604 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
605 u_uastrcpy(expected
,temp
);
606 if (0 != u_strcmp(expected
, dataTable
[CTRY3
][i
])) {
607 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected
),
608 austrdup(dataTable
[CTRY3
][i
]));
610 sprintf(temp2
, "%x", (int)uloc_getLCID(testLocale
));
611 if (strcmp(temp2
, rawData2
[LCID
][i
]) != 0) {
612 log_err("LCID mismatch: %s versus %s\n", temp2
, rawData2
[LCID
][i
]);
621 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
622 * if there's room but won't be included in result. result < 0 indicates an error.
623 * Returns the number of chars written (not those that would be written if there's enough room.*/
624 static int32_t UCharsToEscapedAscii(const UChar
* utext
, int32_t len
, char* resultChars
, int32_t buflen
) {
625 static const struct {
638 static const int32_t ESCAPE_MAP_LENGTH
= UPRV_LENGTHOF(ESCAPE_MAP
);
639 static const char HEX_DIGITS
[] = {
640 '0', '1', '2', '3', '4', '5', '6', '7',
641 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
644 int32_t resultLen
= 0;
645 const int32_t limit
= len
<0 ? buflen
: len
; /* buflen is long enough to hit the buffer limit */
646 const int32_t escapeLimit1
= buflen
-2;
647 const int32_t escapeLimit2
= buflen
-6;
650 if(utext
==NULL
|| resultChars
==NULL
|| buflen
<0) {
654 for(i
=0;i
<limit
&& resultLen
<buflen
;++i
) {
660 for(j
=0;j
<ESCAPE_MAP_LENGTH
&& uc
!=ESCAPE_MAP
[j
].sourceVal
;j
++) {
662 if(j
<ESCAPE_MAP_LENGTH
) {
663 if(resultLen
>escapeLimit1
) {
666 resultChars
[resultLen
++]='\\';
667 resultChars
[resultLen
++]=ESCAPE_MAP
[j
].escapedChar
;
671 u_austrncpy(resultChars
+ resultLen
, &uc
, 1);
676 if(resultLen
>escapeLimit2
) {
680 /* have to escape the uchar */
681 resultChars
[resultLen
++]='\\';
682 resultChars
[resultLen
++]='u';
683 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>12)&0xff];
684 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>8)&0xff];
685 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>4)&0xff];
686 resultChars
[resultLen
++]=HEX_DIGITS
[uc
&0xff];
689 if(resultLen
<buflen
) {
690 resultChars
[resultLen
] = 0;
697 * Jitterbug 2439 -- markus 20030425
699 * The lookup of display names must not fall back through the default
700 * locale because that yields useless results.
702 static void TestDisplayNames()
705 UErrorCode errorCode
=U_ZERO_ERROR
;
707 log_verbose("Testing getDisplayName for different locales\n");
709 log_verbose(" In locale = en_US...\n");
710 doTestDisplayNames("en_US", DLANG_EN
);
711 log_verbose(" In locale = fr_FR....\n");
712 doTestDisplayNames("fr_FR", DLANG_FR
);
713 log_verbose(" In locale = ca_ES...\n");
714 doTestDisplayNames("ca_ES", DLANG_CA
);
715 log_verbose(" In locale = gr_EL..\n");
716 doTestDisplayNames("el_GR", DLANG_EL
);
718 /* test that the default locale has a display name for its own language */
719 errorCode
=U_ZERO_ERROR
;
720 length
=uloc_getDisplayLanguage(NULL
, NULL
, buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
721 if(U_FAILURE(errorCode
) || (length
<=3 && buffer
[0]<=0x7f)) {
722 /* check <=3 to reject getting the language code as a display name */
723 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
));
726 /* test that we get the language code itself for an unknown language, and a default warning */
727 errorCode
=U_ZERO_ERROR
;
728 length
=uloc_getDisplayLanguage("qq", "rr", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
729 if(errorCode
!=U_USING_DEFAULT_WARNING
|| length
!=2 || buffer
[0]!=0x71 || buffer
[1]!=0x71) {
730 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode
));
733 /* test that we get a default warning for a display name where one component is unknown (4255) */
734 errorCode
=U_ZERO_ERROR
;
735 length
=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
736 if(errorCode
!=U_USING_DEFAULT_WARNING
) {
737 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode
));
742 static const char *aLocale
= "es@collation=traditional;calendar=japanese";
743 static const char *testL
[] = { "en_US",
747 static const char *expect
[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
748 "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)",
749 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
750 "\\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)" };
753 for(i
=0;i
<UPRV_LENGTHOF(testL
);i
++) {
754 errorCode
= U_ZERO_ERROR
;
755 uloc_getDisplayName(aLocale
, testL
[i
], buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
756 if(U_FAILURE(errorCode
)) {
757 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale
, testL
[i
], u_errorName(errorCode
));
759 expectBuffer
= CharsToUChars(expect
[i
]);
760 if(u_strcmp(buffer
,expectBuffer
)) {
761 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
));
763 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale
, testL
[i
], expect
[i
]);
770 /* test that we properly preflight and return data when there's a non-default pattern,
774 static const char *locale
="az_Cyrl";
775 static const char *displayLocale
="ja";
776 static const char *expectedChars
=
777 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e"
778 "\\uff08\\u30ad\\u30ea\\u30eb\\u6587\\u5b57\\uff09";
779 UErrorCode ec
=U_ZERO_ERROR
;
782 int32_t preflightLen
=uloc_getDisplayName(locale
, displayLocale
, NULL
, 0, &ec
);
783 /* inconvenient semantics when preflighting, this condition is expected... */
784 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
787 len
=uloc_getDisplayName(locale
, displayLocale
, result
, UPRV_LENGTHOF(result
), &ec
);
789 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
790 locale
, displayLocale
, u_errorName(ec
));
792 UChar
*expected
=CharsToUChars(expectedChars
);
793 int32_t expectedLen
=u_strlen(expected
);
795 if(len
!=expectedLen
) {
796 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
797 locale
, displayLocale
, len
, expectedLen
);
798 } else if(preflightLen
!=expectedLen
) {
799 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
800 locale
, displayLocale
, preflightLen
, expectedLen
);
801 } else if(u_strncmp(result
, expected
, len
)) {
802 int32_t cap
=len
*6+1; /* worst case + space for trailing null */
803 char* resultChars
=(char*)malloc(cap
);
804 int32_t resultCharsLen
=UCharsToEscapedAscii(result
, len
, resultChars
, cap
);
805 if(resultCharsLen
<0 || resultCharsLen
<cap
-1) {
806 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale
, displayLocale
);
808 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
809 locale
, displayLocale
, resultChars
, expectedChars
);
814 /* test all buffer sizes */
815 for(i
=len
+1;i
>=0;--i
) {
816 len
=uloc_getDisplayName(locale
, displayLocale
, result
, i
, &ec
);
817 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
821 log_err("using buffer of length %d returned error %s", i
, u_errorName(ec
));
824 if(len
!=expectedLen
) {
825 log_err("with buffer of length %d, expected length %d but got %d", i
, expectedLen
, len
);
828 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
829 * we don't know that it's been filled, so no point in checking. */
839 /* test for uloc_getAvialable() and uloc_countAvilable()*/
840 static void TestGetAvailableLocales()
846 log_verbose("Testing the no of avialable locales\n");
847 locCount
=uloc_countAvailable();
849 log_data_err("countAvailable() returned an empty list!\n");
851 /* use something sensible w/o hardcoding the count */
852 else if(locCount
< 0){
853 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount
);
856 log_info("Number of locales returned = %d\n", locCount
);
858 for(i
=0;i
<locCount
;i
++){
859 locList
=uloc_getAvailable(i
);
861 log_verbose(" %s\n", locList
);
865 static void TestGetAvailableLocalesByType() {
866 UErrorCode status
= U_ZERO_ERROR
;
868 UEnumeration
* uenum
= uloc_openAvailableByType(ULOC_AVAILABLE_DEFAULT
, &status
);
869 assertSuccess("Constructing the UEnumeration", &status
);
871 assertIntEquals("countAvailable() should be same in old and new methods",
872 uloc_countAvailable(),
873 uenum_count(uenum
, &status
));
875 for (int32_t i
= 0; i
< uloc_countAvailable(); i
++) {
876 const char* old
= uloc_getAvailable(i
);
878 const char* new = uenum_next(uenum
, &len
, &status
);
879 assertEquals("Old and new strings should equal", old
, new);
880 assertIntEquals("String length should be correct", uprv_strlen(old
), len
);
882 assertPtrEquals("Should get nullptr on the last string",
883 NULL
, uenum_next(uenum
, NULL
, &status
));
887 uenum
= uloc_openAvailableByType(ULOC_AVAILABLE_ONLY_LEGACY_ALIASES
, &status
);
888 UBool found_he
= FALSE
;
889 UBool found_iw
= FALSE
;
891 while ((loc
= uenum_next(uenum
, NULL
, &status
))) {
892 if (uprv_strcmp("he", loc
) == 0) {
895 if (uprv_strcmp("iw", loc
) == 0) {
899 assertTrue("Should NOT have found he amongst the legacy/alias locales", !found_he
);
900 assertTrue("Should have found iw amongst the legacy/alias locales", found_iw
);
903 uenum
= uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES
, &status
);
906 const UChar
* uloc
; // test the UChar conversion
908 while ((uloc
= uenum_unext(uenum
, NULL
, &status
))) {
909 if (u_strcmp(u
"iw", uloc
) == 0) {
912 if (u_strcmp(u
"he", uloc
) == 0) {
917 assertTrue("Should have found he amongst all locales", found_he
);
918 assertTrue("Should have found iw amongst all locales", found_iw
);
919 assertIntEquals("Should return as many strings as claimed",
920 count
, uenum_count(uenum
, &status
));
922 // Reset the enumeration and it should still work
923 uenum_reset(uenum
, &status
);
925 while ((loc
= uenum_next(uenum
, NULL
, &status
))) {
928 assertIntEquals("After reset, should return as many strings as claimed",
929 count
, uenum_count(uenum
, &status
));
933 assertSuccess("No errors should have occurred", &status
);
936 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
937 static void TestDataDirectory()
940 char oldDirectory
[512];
941 const char *temp
,*testValue1
,*testValue2
,*testValue3
;
942 const char path
[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING
; /*give the required path */
944 log_verbose("Testing getDataDirectory()\n");
945 temp
= u_getDataDirectory();
946 strcpy(oldDirectory
, temp
);
948 testValue1
=uloc_getISO3Language("en_US");
949 log_verbose("first fetch of language retrieved %s\n", testValue1
);
951 if (0 != strcmp(testValue1
,"eng")){
952 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1
);
955 /*defining the path for DataDirectory */
956 log_verbose("Testing setDataDirectory\n");
957 u_setDataDirectory( path
);
958 if(strcmp(path
, u_getDataDirectory())==0)
959 log_verbose("setDataDirectory working fine\n");
961 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path
);
963 testValue2
=uloc_getISO3Language("en_US");
964 log_verbose("second fetch of language retrieved %s \n", testValue2
);
966 u_setDataDirectory(oldDirectory
);
967 testValue3
=uloc_getISO3Language("en_US");
968 log_verbose("third fetch of language retrieved %s \n", testValue3
);
970 if (0 != strcmp(testValue3
,"eng")) {
971 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3
);
977 /*=========================================================== */
981 static void doTestDisplayNames(const char* displayLocale
, int32_t compareIndex
)
983 UErrorCode status
= U_ZERO_ERROR
;
985 int32_t maxresultsize
;
987 const char *testLocale
;
991 UChar
*testScript
= 0;
997 UChar
* expectedLang
= 0;
998 UChar
* expectedScript
= 0;
999 UChar
* expectedCtry
= 0;
1000 UChar
* expectedVar
= 0;
1001 UChar
* expectedName
= 0;
1005 for(i
=0;i
<LOCALE_SIZE
; ++i
)
1007 testLocale
=rawData2
[NAME
][i
];
1009 log_verbose("Testing..... %s\n", testLocale
);
1012 maxresultsize
=uloc_getDisplayLanguage(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
1013 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1015 status
=U_ZERO_ERROR
;
1016 testLang
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1017 uloc_getDisplayLanguage(testLocale
, displayLocale
, testLang
, maxresultsize
+ 1, &status
);
1023 if(U_FAILURE(status
)){
1024 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status
));
1028 maxresultsize
=uloc_getDisplayScript(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
1029 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1031 status
=U_ZERO_ERROR
;
1032 testScript
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1033 uloc_getDisplayScript(testLocale
, displayLocale
, testScript
, maxresultsize
+ 1, &status
);
1039 if(U_FAILURE(status
)){
1040 log_err("Error in getDisplayScript() %s\n", myErrorName(status
));
1044 maxresultsize
=uloc_getDisplayCountry(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
1045 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1047 status
=U_ZERO_ERROR
;
1048 testCtry
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1049 uloc_getDisplayCountry(testLocale
, displayLocale
, testCtry
, maxresultsize
+ 1, &status
);
1055 if(U_FAILURE(status
)){
1056 log_err("Error in getDisplayCountry() %s\n", myErrorName(status
));
1060 maxresultsize
=uloc_getDisplayVariant(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
1061 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1063 status
=U_ZERO_ERROR
;
1064 testVar
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1065 uloc_getDisplayVariant(testLocale
, displayLocale
, testVar
, maxresultsize
+ 1, &status
);
1071 if(U_FAILURE(status
)){
1072 log_err("Error in getDisplayVariant() %s\n", myErrorName(status
));
1076 maxresultsize
=uloc_getDisplayName(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
1077 if(status
==U_BUFFER_OVERFLOW_ERROR
)
1079 status
=U_ZERO_ERROR
;
1080 testName
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
1081 uloc_getDisplayName(testLocale
, displayLocale
, testName
, maxresultsize
+ 1, &status
);
1087 if(U_FAILURE(status
)){
1088 log_err("Error in getDisplayName() %s\n", myErrorName(status
));
1091 expectedLang
=dataTable
[compareIndex
][i
];
1092 if(u_strlen(expectedLang
)== 0)
1093 expectedLang
=dataTable
[DLANG_EN
][i
];
1095 expectedScript
=dataTable
[compareIndex
+ 1][i
];
1096 if(u_strlen(expectedScript
)== 0)
1097 expectedScript
=dataTable
[DSCRIPT_EN
][i
];
1099 expectedCtry
=dataTable
[compareIndex
+ 2][i
];
1100 if(u_strlen(expectedCtry
)== 0)
1101 expectedCtry
=dataTable
[DCTRY_EN
][i
];
1103 expectedVar
=dataTable
[compareIndex
+ 3][i
];
1104 if(u_strlen(expectedVar
)== 0)
1105 expectedVar
=dataTable
[DVAR_EN
][i
];
1107 expectedName
=dataTable
[compareIndex
+ 4][i
];
1108 if(u_strlen(expectedName
) == 0)
1109 expectedName
=dataTable
[DNAME_EN
][i
];
1111 if (0 !=u_strcmp(testLang
,expectedLang
)) {
1112 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang
), austrdup(expectedLang
), displayLocale
);
1115 if (0 != u_strcmp(testScript
,expectedScript
)) {
1116 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript
), austrdup(expectedScript
), displayLocale
);
1119 if (0 != u_strcmp(testCtry
,expectedCtry
)) {
1120 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry
), austrdup(expectedCtry
), displayLocale
);
1123 if (0 != u_strcmp(testVar
,expectedVar
)) {
1124 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar
), austrdup(expectedVar
), displayLocale
);
1127 if(0 != u_strcmp(testName
, expectedName
)) {
1128 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName
), austrdup(expectedName
), displayLocale
);
1131 if(testName
!=&_NUL
) {
1134 if(testLang
!=&_NUL
) {
1137 if(testScript
!=&_NUL
) {
1140 if(testCtry
!=&_NUL
) {
1143 if(testVar
!=&_NUL
) {
1150 /*------------------------------
1151 * TestDisplayNameBrackets
1155 const char * displayLocale
;
1156 const char * namedRegion
;
1157 const char * namedLocale
;
1158 const char * regionName
;
1159 const char * ulocLocaleName
;
1160 const char * uldnLocaleName
;
1161 } DisplayNameBracketsItem
;
1163 static const DisplayNameBracketsItem displayNameBracketsItems
[] = {
1164 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)", "English (Cocos [Keeling] Islands)" },
1165 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])", "Burmese (Myanmar)" },
1166 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])", "Burmese (Myanmar, Myanmar)" },
1167 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B",
1168 "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09",
1169 "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1170 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09",
1171 "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09",
1172 "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1173 { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}
1176 enum { kDisplayNameBracketsMax
= 128 };
1178 static void TestDisplayNameBrackets()
1180 const DisplayNameBracketsItem
* itemPtr
= displayNameBracketsItems
;
1181 for (; itemPtr
->displayLocale
!= NULL
; itemPtr
++) {
1182 ULocaleDisplayNames
* uldn
;
1184 UChar expectRegionName
[kDisplayNameBracketsMax
];
1185 UChar expectUlocLocaleName
[kDisplayNameBracketsMax
];
1186 UChar expectUldnLocaleName
[kDisplayNameBracketsMax
];
1187 UChar getName
[kDisplayNameBracketsMax
];
1190 (void) u_unescape(itemPtr
->regionName
, expectRegionName
, kDisplayNameBracketsMax
);
1191 (void) u_unescape(itemPtr
->ulocLocaleName
, expectUlocLocaleName
, kDisplayNameBracketsMax
);
1192 (void) u_unescape(itemPtr
->uldnLocaleName
, expectUldnLocaleName
, kDisplayNameBracketsMax
);
1194 status
= U_ZERO_ERROR
;
1195 ulen
= uloc_getDisplayCountry(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1196 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1197 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1200 status
= U_ZERO_ERROR
;
1201 ulen
= uloc_getDisplayName(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1202 if ( U_FAILURE(status
) || u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1203 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1205 if ( U_FAILURE(status
) ) {
1206 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1207 } else if ( u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1209 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1210 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1213 #if !UCONFIG_NO_FORMATTING
1214 status
= U_ZERO_ERROR
;
1215 uldn
= uldn_open(itemPtr
->displayLocale
, ULDN_STANDARD_NAMES
, &status
);
1216 if (U_SUCCESS(status
)) {
1217 status
= U_ZERO_ERROR
;
1218 ulen
= uldn_regionDisplayName(uldn
, itemPtr
->namedRegion
, getName
, kDisplayNameBracketsMax
, &status
);
1219 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1220 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedRegion
, myErrorName(status
));
1223 status
= U_ZERO_ERROR
;
1224 ulen
= uldn_localeDisplayName(uldn
, itemPtr
->namedLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1225 if ( U_FAILURE(status
) ) {
1226 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1227 } else if ( u_strcmp(getName
, expectUldnLocaleName
) != 0 ) {
1229 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1230 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1235 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr
->displayLocale
, u_errorName(status
));
1238 (void)ulen
; /* Suppress variable not used warning */
1242 /*------------------------------
1246 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1247 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1248 static void TestISOFunctions()
1250 const char* const* str
=uloc_getISOLanguages();
1251 const char* const* str1
=uloc_getISOCountries();
1253 const char *key
= NULL
;
1254 int32_t count
= 0, skipped
= 0;
1256 UResourceBundle
*res
;
1257 UResourceBundle
*subRes
;
1258 UErrorCode status
= U_ZERO_ERROR
;
1260 /* test getISOLanguages*/
1261 /*str=uloc_getISOLanguages(); */
1262 log_verbose("Testing ISO Languages: \n");
1264 /* use structLocale - this data is no longer in root */
1265 res
= ures_openDirect(loadTestData(&status
), "structLocale", &status
);
1266 subRes
= ures_getByKey(res
, "Languages", NULL
, &status
);
1267 if (U_FAILURE(status
)) {
1268 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status
));
1272 expect
= ures_getSize(subRes
);
1273 for(count
= 0; *(str
+count
) != 0; count
++)
1276 test
= *(str
+count
);
1277 status
= U_ZERO_ERROR
;
1280 /* Skip over language tags. This API only returns language codes. */
1281 skipped
+= (key
!= NULL
);
1282 ures_getNextString(subRes
, NULL
, &key
, &status
);
1284 while (key
!= NULL
&& strchr(key
, '_'));
1288 /* TODO: Consider removing sh, which is deprecated */
1289 if(strcmp(key
,"root") == 0 || strcmp(key
,"Fallback") == 0 || strcmp(key
,"sh") == 0) {
1290 ures_getNextString(subRes
, NULL
, &key
, &status
);
1293 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1294 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1295 if(strcmp(test
,key
)) {
1296 /* The first difference usually implies the place where things get out of sync */
1297 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1301 if(!strcmp(test
,"in"))
1302 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1303 if(!strcmp(test
,"iw"))
1304 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1305 if(!strcmp(test
,"ji"))
1306 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1307 if(!strcmp(test
,"jw"))
1308 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1309 if(!strcmp(test
,"sh"))
1310 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1313 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1316 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count
, expect
);
1319 subRes
= ures_getByKey(res
, "Countries", subRes
, &status
);
1320 log_verbose("Testing ISO Countries");
1322 expect
= ures_getSize(subRes
) - 1; /* Skip ZZ */
1323 for(count
= 0; *(str1
+count
) != 0; count
++)
1326 test
= *(str1
+count
);
1328 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1329 skipped
+= (key
!= NULL
);
1330 ures_getNextString(subRes
, NULL
, &key
, &status
);
1332 while (key
!= NULL
&& strlen(key
) != 2);
1336 /* TODO: Consider removing CS, which is deprecated */
1337 while(strcmp(key
,"QO") == 0 || strcmp(key
,"QU") == 0 || strcmp(key
,"CS") == 0) {
1338 ures_getNextString(subRes
, NULL
, &key
, &status
);
1341 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1342 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1343 if(strcmp(test
,key
)) {
1344 /* The first difference usually implies the place where things get out of sync */
1345 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1348 if(!strcmp(test
,"FX"))
1349 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1350 if(!strcmp(test
,"YU"))
1351 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1352 if(!strcmp(test
,"ZR"))
1353 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1356 ures_getNextString(subRes
, NULL
, &key
, &status
);
1357 if (strcmp(key
, "ZZ") != 0) {
1358 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key
);
1360 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1361 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1364 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1365 skipped
+= (key
!= NULL
);
1366 ures_getNextString(subRes
, NULL
, &key
, &status
);
1368 while (U_SUCCESS(status
) && key
!= NULL
&& strlen(key
) != 2);
1370 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1373 log_err("There is an error in getISOCountries, got %d, expected %d \n", count
, expect
);
1380 static void setUpDataTable()
1383 dataTable
= (UChar
***)(calloc(sizeof(UChar
**),LOCALE_INFO_SIZE
));
1385 for (i
= 0; i
< LOCALE_INFO_SIZE
; i
++) {
1386 dataTable
[i
] = (UChar
**)(calloc(sizeof(UChar
*),LOCALE_SIZE
));
1387 for (j
= 0; j
< LOCALE_SIZE
; j
++){
1388 dataTable
[i
][j
] = CharsToUChars(rawData2
[i
][j
]);
1393 static void cleanUpDataTable()
1396 if(dataTable
!= NULL
) {
1397 for (i
=0; i
<LOCALE_INFO_SIZE
; i
++) {
1398 for(j
= 0; j
< LOCALE_SIZE
; j
++) {
1399 free(dataTable
[i
][j
]);
1409 * @bug 4011756 4011380
1411 static void TestISO3Fallback()
1413 const char* test
="xx_YY";
1415 const char * result
;
1417 result
= uloc_getISO3Language(test
);
1419 /* Conform to C API usage */
1421 if (!result
|| (result
[0] != 0))
1422 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1424 result
= uloc_getISO3Country(test
);
1426 if (!result
|| (result
[0] != 0))
1427 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1433 static void TestSimpleDisplayNames()
1436 This test is different from TestDisplayNames because TestDisplayNames checks
1437 fallback behavior, combination of language and country names to form locale
1438 names, and other stuff like that. This test just checks specific language
1439 and country codes to make sure we have the correct names for them.
1441 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1442 const char* languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1444 const char* inLocale
[] = { "en_US", "zh_Hant"};
1445 UErrorCode status
=U_ZERO_ERROR
;
1448 int32_t localeIndex
= 0;
1449 for (i
= 0; i
< 7; i
++) {
1451 UChar
*expectedLang
=0;
1455 localeIndex
= 1; /* Use the second locale for the rest of the test. */
1458 size
=uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], NULL
, size
, &status
);
1459 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1460 status
=U_ZERO_ERROR
;
1461 testLang
=(UChar
*)malloc(sizeof(UChar
) * (size
+ 1));
1462 uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], testLang
, size
+ 1, &status
);
1464 expectedLang
=(UChar
*)malloc(sizeof(UChar
) * (strlen(languageNames
[i
])+1));
1465 u_uastrcpy(expectedLang
, languageNames
[i
]);
1466 if (u_strcmp(testLang
, expectedLang
) != 0)
1467 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1468 languageCodes
[i
], languageNames
[i
], austrdup(testLang
));
1478 static void TestUninstalledISO3Names()
1480 /* This test checks to make sure getISO3Language and getISO3Country work right
1481 even for locales that are not installed. */
1482 static const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
1484 static const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
1485 "ssw", "twi", "zul" };
1486 static const char iso2Countries
[][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1487 "ss_SB", "tw_TC", "zu_ZW" };
1488 static const char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1489 "SLB", "TCA", "ZWE" };
1492 for (i
= 0; i
< 8; i
++) {
1493 UErrorCode err
= U_ZERO_ERROR
;
1495 test
= uloc_getISO3Language(iso2Languages
[i
]);
1496 if(strcmp(test
, iso3Languages
[i
]) !=0 || U_FAILURE(err
))
1497 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1498 iso2Languages
[i
], iso3Languages
[i
], test
, myErrorName(err
));
1500 for (i
= 0; i
< 8; i
++) {
1501 UErrorCode err
= U_ZERO_ERROR
;
1503 test
= uloc_getISO3Country(iso2Countries
[i
]);
1504 if(strcmp(test
, iso3Countries
[i
]) !=0 || U_FAILURE(err
))
1505 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1506 iso2Countries
[i
], iso3Countries
[i
], test
, myErrorName(err
));
1511 static void TestVariantParsing()
1513 static const char* en_US_custom
="en_US_De Anza_Cupertino_California_United States_Earth";
1514 static const char* dispName
="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1515 static const char* dispVar
="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1516 static const char* shortVariant
="fr_FR_foo";
1517 static const char* bogusVariant
="fr_FR__foo";
1518 static const char* bogusVariant2
="fr_FR_foo_";
1519 static const char* bogusVariant3
="fr_FR__foo_";
1522 UChar displayVar
[100];
1523 UChar displayName
[100];
1524 UErrorCode status
=U_ZERO_ERROR
;
1527 size
=uloc_getDisplayVariant(en_US_custom
, "en_US", NULL
, size
, &status
);
1528 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1529 status
=U_ZERO_ERROR
;
1530 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1531 uloc_getDisplayVariant(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1534 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1536 u_uastrcpy(displayVar
, dispVar
);
1537 if(u_strcmp(got
,displayVar
)!=0) {
1538 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar
, austrdup(got
));
1541 size
=uloc_getDisplayName(en_US_custom
, "en_US", NULL
, size
, &status
);
1542 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1543 status
=U_ZERO_ERROR
;
1544 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1545 uloc_getDisplayName(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1548 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1550 u_uastrcpy(displayName
, dispName
);
1551 if(u_strcmp(got
,displayName
)!=0) {
1552 if (status
== U_USING_DEFAULT_WARNING
) {
1553 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status
));
1555 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName
, austrdup(got
));
1560 status
=U_ZERO_ERROR
;
1561 size
=uloc_getDisplayVariant(shortVariant
, NULL
, NULL
, size
, &status
);
1562 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1563 status
=U_ZERO_ERROR
;
1564 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1565 uloc_getDisplayVariant(shortVariant
, NULL
, got
, size
+ 1, &status
);
1568 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1570 if(strcmp(austrdup(got
),"FOO")!=0) {
1571 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got
));
1574 status
=U_ZERO_ERROR
;
1575 size
=uloc_getDisplayVariant(bogusVariant
, NULL
, NULL
, size
, &status
);
1576 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1577 status
=U_ZERO_ERROR
;
1578 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1579 uloc_getDisplayVariant(bogusVariant
, NULL
, got
, size
+ 1, &status
);
1582 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1584 if(strcmp(austrdup(got
),"_FOO")!=0) {
1585 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got
));
1588 status
=U_ZERO_ERROR
;
1589 size
=uloc_getDisplayVariant(bogusVariant2
, NULL
, NULL
, size
, &status
);
1590 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1591 status
=U_ZERO_ERROR
;
1592 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1593 uloc_getDisplayVariant(bogusVariant2
, NULL
, got
, size
+ 1, &status
);
1596 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1598 if(strcmp(austrdup(got
),"FOO_")!=0) {
1599 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got
));
1602 status
=U_ZERO_ERROR
;
1603 size
=uloc_getDisplayVariant(bogusVariant3
, NULL
, NULL
, size
, &status
);
1604 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1605 status
=U_ZERO_ERROR
;
1606 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1607 uloc_getDisplayVariant(bogusVariant3
, NULL
, got
, size
+ 1, &status
);
1610 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1612 if(strcmp(austrdup(got
),"_FOO_")!=0) {
1613 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got
));
1619 static void TestObsoleteNames(void)
1622 UErrorCode status
= U_ZERO_ERROR
;
1634 { "eng_USA", "eng", "en", "USA", "US" },
1635 { "kok", "kok", "kok", "", "" },
1636 { "in", "ind", "in", "", "" },
1637 { "id", "ind", "id", "", "" }, /* NO aliasing */
1638 { "sh", "srp", "sh", "", "" },
1639 { "zz_CS", "", "zz", "SCG", "CS" },
1640 { "zz_FX", "", "zz", "FXX", "FX" },
1641 { "zz_RO", "", "zz", "ROU", "RO" },
1642 { "zz_TP", "", "zz", "TMP", "TP" },
1643 { "zz_TL", "", "zz", "TLS", "TL" },
1644 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1645 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1646 { "zz_ROM", "", "zz", "ROU", "RO" },
1647 { "zz_ROU", "", "zz", "ROU", "RO" },
1648 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1649 { "zz_TMP", "", "zz", "TMP", "TP" },
1650 { "zz_TLS", "", "zz", "TLS", "TL" },
1651 { "zz_YUG", "", "zz", "YUG", "YU" },
1652 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1653 { "iw", "heb", "iw", "", "" },
1654 { "ji", "yid", "ji", "", "" },
1655 { "jw", "jaw", "jw", "", "" },
1656 { "sh", "srp", "sh", "", "" },
1657 { "", "", "", "", "" }
1660 for(i
=0;tests
[i
].locale
[0];i
++)
1664 locale
= tests
[i
].locale
;
1665 log_verbose("** %s:\n", locale
);
1667 status
= U_ZERO_ERROR
;
1668 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1670 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1671 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1675 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1676 uloc_getISO3Language(locale
) );
1679 status
= U_ZERO_ERROR
;
1680 uloc_getLanguage(locale
, buff
, 256, &status
);
1681 if(U_FAILURE(status
))
1683 log_err("FAIL: error getting language from %s\n", locale
);
1687 if(strcmp(buff
,tests
[i
].lang
))
1689 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1690 locale
, buff
, tests
[i
].lang
);
1694 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale
, buff
);
1697 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1699 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1700 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1704 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1705 uloc_getISO3Language(locale
) );
1708 if(strcmp(tests
[i
].ctry3
,uloc_getISO3Country(locale
)))
1710 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1711 locale
, uloc_getISO3Country(locale
), tests
[i
].ctry3
);
1715 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1716 uloc_getISO3Country(locale
) );
1719 status
= U_ZERO_ERROR
;
1720 uloc_getCountry(locale
, buff
, 256, &status
);
1721 if(U_FAILURE(status
))
1723 log_err("FAIL: error getting country from %s\n", locale
);
1727 if(strcmp(buff
,tests
[i
].ctry
))
1729 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1730 locale
, buff
, tests
[i
].ctry
);
1734 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale
, buff
);
1739 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1740 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1743 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1744 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1749 i
= uloc_getLanguage("kok",NULL
,0,&icu_err
);
1750 if(U_FAILURE(icu_err
))
1752 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err
));
1755 icu_err
= U_ZERO_ERROR
;
1756 uloc_getLanguage("kok",r1_buff
,12,&icu_err
);
1757 if(U_FAILURE(icu_err
))
1759 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err
));
1762 r1_addr
= (char *)uloc_getISO3Language("kok");
1764 icu_err
= U_ZERO_ERROR
;
1765 if (strcmp(r1_buff
,"kok") != 0)
1767 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff
);
1770 r1_addr
= (char *)uloc_getISO3Language("in");
1771 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1772 if (strcmp(r1_buff
,"id") != 0)
1774 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1777 r1_addr
= (char *)uloc_getISO3Language("sh");
1778 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1779 if (strcmp(r1_buff
,"sr") != 0)
1781 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1785 r1_addr
= (char *)uloc_getISO3Country("zz_ZR");
1786 strcpy(p1_buff
,"zz_");
1787 strcat(p1_buff
,r1_addr
);
1788 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1789 if (strcmp(r1_buff
,"ZR") != 0)
1791 printf("uloc_getCountry error (%s)\n",r1_buff
);
1794 r1_addr
= (char *)uloc_getISO3Country("zz_FX");
1795 strcpy(p1_buff
,"zz_");
1796 strcat(p1_buff
,r1_addr
);
1797 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1798 if (strcmp(r1_buff
,"FX") != 0)
1800 printf("uloc_getCountry error (%s)\n",r1_buff
);
1808 static void TestKeywordVariants(void)
1810 static const struct {
1811 const char *localeID
;
1812 const char *expectedLocaleID
; /* uloc_getName */
1813 const char *expectedLocaleIDNoKeywords
; /* uloc_getBaseName */
1814 const char *expectedCanonicalID
; /* uloc_canonicalize */
1815 const char *expectedKeywords
[10];
1816 int32_t numKeywords
;
1817 UErrorCode expectedStatus
; /* from uloc_openKeywords */
1820 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1821 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1823 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1824 {"calendar", "collation", "currency"},
1831 "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */
1833 {"","","","","","",""},
1835 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1838 "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */
1839 "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1840 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1841 "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1842 {"","","","","","",""},
1844 U_INVALID_FORMAT_ERROR
1848 0, /* expected getName to fail */
1849 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1850 0, /* expected canonicalize to fail */
1851 {"","","","","","",""},
1853 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1856 UErrorCode status
= U_ZERO_ERROR
;
1858 int32_t i
= 0, j
= 0;
1859 int32_t resultLen
= 0;
1861 UEnumeration
*keywords
;
1862 int32_t keyCount
= 0;
1863 const char *keyword
= NULL
;
1864 int32_t keywordLen
= 0;
1866 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1867 status
= U_ZERO_ERROR
;
1869 keywords
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
1871 if(status
!= testCases
[i
].expectedStatus
) {
1872 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1873 testCases
[i
].localeID
,
1874 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1876 status
= U_ZERO_ERROR
;
1878 if((keyCount
= uenum_count(keywords
, &status
)) != testCases
[i
].numKeywords
) {
1879 log_err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1883 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1884 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1885 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1890 uenum_reset(keywords
, &status
);
1891 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1892 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1893 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1898 uenum_close(keywords
);
1901 status
= U_ZERO_ERROR
;
1902 resultLen
= uloc_getName(testCases
[i
].localeID
, buffer
, 256, &status
);
1904 U_ASSERT(resultLen
< 256);
1905 if (U_SUCCESS(status
)) {
1906 if (testCases
[i
].expectedLocaleID
== 0) {
1907 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1908 testCases
[i
].localeID
, buffer
);
1909 } else if (uprv_strcmp(testCases
[i
].expectedLocaleID
, buffer
) != 0) {
1910 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1911 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
);
1914 if (testCases
[i
].expectedLocaleID
!= 0) {
1915 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1916 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
, u_errorName(status
));
1920 status
= U_ZERO_ERROR
;
1921 resultLen
= uloc_getBaseName(testCases
[i
].localeID
, buffer
, 256, &status
);
1922 U_ASSERT(resultLen
< 256);
1923 if (U_SUCCESS(status
)) {
1924 if (testCases
[i
].expectedLocaleIDNoKeywords
== 0) {
1925 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
1926 testCases
[i
].localeID
, buffer
);
1927 } else if (uprv_strcmp(testCases
[i
].expectedLocaleIDNoKeywords
, buffer
) != 0) {
1928 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
1929 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
);
1932 if (testCases
[i
].expectedLocaleIDNoKeywords
!= 0) {
1933 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
1934 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
, u_errorName(status
));
1938 status
= U_ZERO_ERROR
;
1939 resultLen
= uloc_canonicalize(testCases
[i
].localeID
, buffer
, 256, &status
);
1940 U_ASSERT(resultLen
< 256);
1941 if (U_SUCCESS(status
)) {
1942 if (testCases
[i
].expectedCanonicalID
== 0) {
1943 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
1944 testCases
[i
].localeID
, buffer
);
1945 } else if (uprv_strcmp(testCases
[i
].expectedCanonicalID
, buffer
) != 0) {
1946 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1947 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
);
1950 if (testCases
[i
].expectedCanonicalID
!= 0) {
1951 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
1952 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
, u_errorName(status
));
1958 static void TestKeywordVariantParsing(void)
1960 static const struct {
1961 const char *localeID
;
1962 const char *keyword
;
1963 const char *expectedValue
; /* NULL if failure is expected */
1965 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", NULL
}, /* malformed key name */
1966 { "de_DE", "collation", ""},
1967 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1968 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1973 int32_t resultLen
= 0;
1976 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1978 status
= U_ZERO_ERROR
;
1979 resultLen
= uloc_getKeywordValue(testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
, 256, &status
);
1980 (void)resultLen
; /* Suppress set but not used warning. */
1981 if (testCases
[i
].expectedValue
) {
1982 /* expect success */
1983 if (U_FAILURE(status
)) {
1984 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got status %s\n",
1985 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, u_errorName(status
));
1986 } else if (uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1987 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got \"%s\"\n",
1988 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1990 } else if (U_SUCCESS(status
)) {
1991 /* expect failure */
1992 log_err("Expected failure but got success from \"%s\" for keyword \"%s\". Got \"%s\"\n",
1993 testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1999 static const struct {
2000 const char *l
; /* locale */
2001 const char *k
; /* kw */
2002 const char *v
; /* value */
2003 const char *x
; /* expected */
2004 } kwSetTestCases
[] = {
2006 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
2007 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
2008 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
2009 { "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 */
2010 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
2011 { "de", "Currency", "CHF", "de@currency=CHF" },
2012 { "de", "Currency", "CHF", "de@currency=CHF" },
2014 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2015 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
2016 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2017 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2018 { "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 */
2019 { "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 */
2020 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2021 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2024 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
2025 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
2026 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
2027 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
2028 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
2029 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
2030 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
2031 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
2032 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
2036 /* 1. removal of item at end */
2037 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
2038 { "de@collation=phonebook;currency=CHF", "currency", NULL
, "de@collation=phonebook" },
2039 /* 2. removal of item at beginning */
2040 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
2041 { "de@collation=phonebook;currency=CHF", "collation", NULL
, "de@currency=CHF" },
2042 /* 3. removal of an item not there */
2043 { "de@collation=phonebook;currency=CHF", "calendar", NULL
, "de@collation=phonebook;currency=CHF" },
2044 /* 4. removal of only item */
2045 { "de@collation=phonebook", "collation", NULL
, "de" },
2047 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
2048 /* cases with legal extra spacing */
2049 /*31*/{ "en_US@ calendar = islamic", "calendar", "japanese", "en_US@calendar=japanese" },
2050 /*32*/{ "en_US@ calendar = gregorian ; collation = phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
2051 /*33*/{ "en_US@ calendar = islamic", "currency", "CHF", "en_US@calendar=islamic;currency=CHF" },
2052 /*34*/{ "en_US@ currency = CHF", "calendar", "japanese", "en_US@calendar=japanese;currency=CHF" },
2053 /* cases in which setKeywordValue expected to fail (implied by NULL for expected); locale need not be canonical */
2054 /*35*/{ "en_US@calendar=gregorian;", "calendar", "japanese", NULL
},
2055 /*36*/{ "en_US@calendar=gregorian;=", "calendar", "japanese", NULL
},
2056 /*37*/{ "en_US@calendar=gregorian;currency=", "calendar", "japanese", NULL
},
2057 /*38*/{ "en_US@=", "calendar", "japanese", NULL
},
2058 /*39*/{ "en_US@=;", "calendar", "japanese", NULL
},
2059 /*40*/{ "en_US@= ", "calendar", "japanese", NULL
},
2060 /*41*/{ "en_US@ =", "calendar", "japanese", NULL
},
2061 /*42*/{ "en_US@ = ", "calendar", "japanese", NULL
},
2062 /*43*/{ "en_US@=;calendar=gregorian", "calendar", "japanese", NULL
},
2063 /*44*/{ "en_US@= calen dar = gregorian", "calendar", "japanese", NULL
},
2064 /*45*/{ "en_US@= calendar = greg orian", "calendar", "japanese", NULL
},
2065 /*46*/{ "en_US@=;cal...endar=gregorian", "calendar", "japanese", NULL
},
2066 /*47*/{ "en_US@=;calendar=greg...orian", "calendar", "japanese", NULL
},
2067 /*48*/{ "en_US@calendar=gregorian", "cale ndar", "japanese", NULL
},
2068 /*49*/{ "en_US@calendar=gregorian", "calendar", "japa..nese", NULL
},
2069 /* cases in which getKeywordValue and setKeyword expected to fail (implied by NULL for value and expected) */
2070 /*50*/{ "en_US@=", "calendar", NULL
, NULL
},
2071 /*51*/{ "en_US@=;", "calendar", NULL
, NULL
},
2072 /*52*/{ "en_US@= ", "calendar", NULL
, NULL
},
2073 /*53*/{ "en_US@ =", "calendar", NULL
, NULL
},
2074 /*54*/{ "en_US@ = ", "calendar", NULL
, NULL
},
2075 /*55*/{ "en_US@=;calendar=gregorian", "calendar", NULL
, NULL
},
2076 /*56*/{ "en_US@= calen dar = gregorian", "calendar", NULL
, NULL
},
2077 /*57*/{ "en_US@= calendar = greg orian", "calendar", NULL
, NULL
},
2078 /*58*/{ "en_US@=;cal...endar=gregorian", "calendar", NULL
, NULL
},
2079 /*59*/{ "en_US@=;calendar=greg...orian", "calendar", NULL
, NULL
},
2080 /*60*/{ "en_US@calendar=gregorian", "cale ndar", NULL
, NULL
},
2084 static void TestKeywordSet(void)
2087 int32_t resultLen
= 0;
2092 for(i
= 0; i
< UPRV_LENGTHOF(kwSetTestCases
); i
++) {
2093 UErrorCode status
= U_ZERO_ERROR
;
2094 memset(buffer
,'%',1023);
2095 strcpy(buffer
, kwSetTestCases
[i
].l
);
2097 if (kwSetTestCases
[i
].x
!= NULL
) {
2098 uloc_canonicalize(kwSetTestCases
[i
].l
, cbuffer
, 1023, &status
);
2099 if(strcmp(buffer
,cbuffer
)) {
2100 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i
, cbuffer
, buffer
);
2102 /* sanity check test case results for canonicity */
2103 uloc_canonicalize(kwSetTestCases
[i
].x
, cbuffer
, 1023, &status
);
2104 if(strcmp(kwSetTestCases
[i
].x
,cbuffer
)) {
2105 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__
, __LINE__
, i
, kwSetTestCases
[i
].x
, cbuffer
);
2108 status
= U_ZERO_ERROR
;
2109 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
2110 if(U_FAILURE(status
)) {
2111 log_err("Err on test case %d for setKeywordValue: got error %s\n", i
, u_errorName(status
));
2112 } else if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=resultLen
)) {
2113 log_err("FAIL: #%d setKeywordValue: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
2114 kwSetTestCases
[i
].v
, buffer
, resultLen
, kwSetTestCases
[i
].x
, strlen(buffer
));
2116 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,buffer
);
2119 if (kwSetTestCases
[i
].v
!= NULL
&& kwSetTestCases
[i
].v
[0] != 0) {
2120 status
= U_ZERO_ERROR
;
2121 resultLen
= uloc_getKeywordValue(kwSetTestCases
[i
].x
, kwSetTestCases
[i
].k
, buffer
, 1023, &status
);
2122 if(U_FAILURE(status
)) {
2123 log_err("Err on test case %d for getKeywordValue: got error %s\n", i
, u_errorName(status
));
2124 } else if (resultLen
!= (int32_t)uprv_strlen(kwSetTestCases
[i
].v
) || uprv_strcmp(buffer
, kwSetTestCases
[i
].v
) != 0) {
2125 log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i
, buffer
, resultLen
,
2126 kwSetTestCases
[i
].v
, uprv_strlen(kwSetTestCases
[i
].v
));
2130 /* test cases expected to result in error */
2131 status
= U_ZERO_ERROR
;
2132 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
2133 if(U_SUCCESS(status
)) {
2134 log_err("Err on test case %d for setKeywordValue: expected to fail but succeeded, got %s (%d)\n", i
, buffer
, resultLen
);
2137 if (kwSetTestCases
[i
].v
== NULL
) {
2138 status
= U_ZERO_ERROR
;
2139 strcpy(cbuffer
, kwSetTestCases
[i
].l
);
2140 resultLen
= uloc_getKeywordValue(cbuffer
, kwSetTestCases
[i
].k
, buffer
, 1023, &status
);
2141 if(U_SUCCESS(status
)) {
2142 log_err("Err on test case %d for getKeywordValue: expected to fail but succeeded\n", i
);
2149 static void TestKeywordSetError(void)
2157 /* 0-test whether an error condition modifies the buffer at all */
2160 memset(buffer
,'%',1023);
2161 status
= U_ZERO_ERROR
;
2162 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2163 if(status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2164 log_err("expected illegal err got %s\n", u_errorName(status
));
2167 /* if(res!=strlen(kwSetTestCases[i].x)) {
2168 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2171 if(buffer
[blen
]!='%') {
2172 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
2175 log_verbose("0-buffer modify OK\n");
2178 /* 1- test a short buffer with growing text */
2179 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2180 memset(buffer
,'%',1023);
2181 strcpy(buffer
,kwSetTestCases
[i
].l
);
2182 status
= U_ZERO_ERROR
;
2183 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2184 if(status
!= U_BUFFER_OVERFLOW_ERROR
) {
2185 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
);
2188 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2189 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2192 if(buffer
[blen
]!='%') {
2193 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
2196 log_verbose("1/%d-buffer modify OK\n",i
);
2200 /* 2- test a short buffer - text the same size or shrinking */
2201 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2202 memset(buffer
,'%',1023);
2203 strcpy(buffer
,kwSetTestCases
[i
].l
);
2204 status
= U_ZERO_ERROR
;
2205 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2206 if(status
!= U_ZERO_ERROR
) {
2207 log_err("expected zero error got %s\n", u_errorName(status
));
2210 if(buffer
[blen
+1]!='%') {
2211 log_err("Buffer byte %d was modified: now %c\n", blen
+1, buffer
[blen
+1]);
2214 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2215 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2218 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=res
)) {
2219 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
2220 kwSetTestCases
[i
].v
, buffer
, res
, kwSetTestCases
[i
].x
, strlen(buffer
));
2222 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,
2225 log_verbose("2/%d-buffer modify OK\n",i
);
2229 static int32_t _canonicalize(int32_t selector
, /* 0==getName, 1==canonicalize */
2230 const char* localeID
,
2232 int32_t resultCapacity
,
2234 /* YOU can change this to use function pointers if you like */
2237 return uloc_getName(localeID
, result
, resultCapacity
, ec
);
2239 return uloc_canonicalize(localeID
, result
, resultCapacity
, ec
);
2245 static void TestCanonicalization(void)
2247 static const struct {
2248 const char *localeID
; /* input */
2249 const char *getNameID
; /* expected getName() result */
2250 const char *canonicalID
; /* expected canonicalize() result */
2252 { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2253 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2254 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2255 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2256 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2257 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2258 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2259 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2260 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2261 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2262 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2263 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
2264 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2265 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2266 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2268 /* posix behavior that used to be performed by getName */
2269 { "mr.utf8", "mr.utf8", "mr" },
2270 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2271 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2272 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2273 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2274 { "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 */
2276 /* fleshing out canonicalization */
2277 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2278 { "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" },
2279 /* already-canonical ids are not changed */
2280 { "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" },
2281 /* norwegian is just too weird, if we handle things in their full generality */
2282 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2284 /* test cases reflecting internal resource bundle usage */
2285 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2286 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2287 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2288 { "ja_JP", "ja_JP", "ja_JP" },
2290 /* test case for "i-default" */
2291 { "i-default", "en@x=i-default", "en@x=i-default" },
2293 // Before ICU 64, ICU locale canonicalization had some additional mappings.
2294 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
2295 // The following now use standard canonicalization.
2296 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
2297 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
2298 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
2299 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
2300 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
2301 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
2302 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
2303 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
2304 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
2305 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
2306 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
2307 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
2308 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
2309 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
2310 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
2311 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
2312 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
2313 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
2314 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
2315 { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
2316 { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
2317 { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
2318 { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
2319 { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
2320 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
2321 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
2322 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
2323 { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
2324 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN_STROKE" },
2325 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
2326 { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
2327 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */
2328 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
2329 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
2330 { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
2331 { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
2332 /* PRE_EURO and EURO conversions don't affect other keywords */
2333 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
2334 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
2335 /* currency keyword overrides PRE_EURO and EURO currency */
2336 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
2337 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
2340 static const char* label
[] = { "getName", "canonicalize" };
2342 UErrorCode status
= U_ZERO_ERROR
;
2343 int32_t i
, j
, resultLen
= 0, origResultLen
;
2346 for (i
=0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2347 for (j
=0; j
<2; ++j
) {
2348 const char* expected
= (j
==0) ? testCases
[i
].getNameID
: testCases
[i
].canonicalID
;
2350 status
= U_ZERO_ERROR
;
2352 if (expected
== NULL
) {
2353 expected
= uloc_getDefault();
2356 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2357 origResultLen
= _canonicalize(j
, testCases
[i
].localeID
, NULL
, 0, &status
);
2358 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
2359 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2360 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2363 status
= U_ZERO_ERROR
;
2364 resultLen
= _canonicalize(j
, testCases
[i
].localeID
, buffer
, sizeof(buffer
), &status
);
2365 if (U_FAILURE(status
)) {
2366 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2367 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2370 if(uprv_strcmp(expected
, buffer
) != 0) {
2371 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2372 label
[j
], testCases
[i
].localeID
, buffer
, expected
);
2374 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2375 label
[j
], testCases
[i
].localeID
, buffer
);
2377 if (resultLen
!= (int32_t)strlen(buffer
)) {
2378 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2379 label
[j
], testCases
[i
].localeID
, resultLen
, strlen(buffer
));
2381 if (origResultLen
!= resultLen
) {
2382 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2383 label
[j
], testCases
[i
].localeID
, origResultLen
, resultLen
);
2389 static void TestCanonicalizationBuffer(void)
2391 UErrorCode status
= U_ZERO_ERROR
;
2394 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
2395 static const char name
[] =
2397 "=foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2398 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2399 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
2402 static const size_t len
= sizeof(name
) - 1; // Without NUL terminator.
2404 int32_t reslen
= uloc_canonicalize(name
, buffer
, (int32_t)len
, &status
);
2406 if (U_FAILURE(status
)) {
2407 log_err("FAIL: uloc_canonicalize(%s) => %s, expected !U_FAILURE()\n",
2408 name
, u_errorName(status
));
2412 if (reslen
!= len
) {
2413 log_err("FAIL: uloc_canonicalize(%s) => \"%i\", expected \"%u\"\n",
2418 if (uprv_strncmp(name
, buffer
, len
) != 0) {
2419 log_err("FAIL: uloc_canonicalize(%s) => \"%.*s\", expected \"%s\"\n",
2420 name
, reslen
, buffer
, name
);
2425 static void TestDisplayKeywords(void)
2429 static const struct {
2430 const char *localeID
;
2431 const char *displayLocale
;
2432 UChar displayKeyword
[200];
2434 { "ca_ES@currency=ESP", "de_AT",
2435 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2437 { "ja_JP@calendar=japanese", "de",
2438 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2440 { "de_DE@collation=traditional", "de_DE",
2441 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2444 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2445 UErrorCode status
= U_ZERO_ERROR
;
2446 const char* keyword
=NULL
;
2447 int32_t keywordLen
= 0;
2448 int32_t keywordCount
= 0;
2449 UChar
*displayKeyword
=NULL
;
2450 int32_t displayKeywordLen
= 0;
2451 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2452 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2453 if(U_FAILURE(status
)){
2454 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases
[i
].localeID
, u_errorName(status
));
2457 /* the uenum_next returns NUL terminated string */
2458 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2459 /* fetch the displayKeyword */
2460 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2461 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2462 status
= U_ZERO_ERROR
;
2463 displayKeywordLen
++; /* for null termination */
2464 displayKeyword
= (UChar
*) malloc(displayKeywordLen
* U_SIZEOF_UCHAR
);
2465 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2466 if(U_FAILURE(status
)){
2467 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
));
2468 free(displayKeyword
);
2471 if(u_strncmp(displayKeyword
, testCases
[i
].displayKeyword
, displayKeywordLen
)!=0){
2472 if (status
== U_USING_DEFAULT_WARNING
) {
2473 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
));
2475 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
);
2477 free(displayKeyword
);
2481 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status
));
2484 free(displayKeyword
);
2487 uenum_close(keywordEnum
);
2491 static void TestDisplayKeywordValues(void){
2494 static const struct {
2495 const char *localeID
;
2496 const char *displayLocale
;
2497 UChar displayKeywordValue
[500];
2499 { "ca_ES@currency=ESP", "de_AT",
2500 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2502 { "de_AT@currency=ATS", "fr_FR",
2503 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2505 { "de_DE@currency=DEM", "it",
2506 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2508 { "el_GR@currency=GRD", "en",
2509 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2511 { "eu_ES@currency=ESP", "it_IT",
2512 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2514 { "de@collation=phonebook", "es",
2515 {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}
2518 { "de_DE@collation=phonebook", "es",
2519 {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}
2521 { "es_ES@collation=traditional","de",
2522 {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}
2524 { "ja_JP@calendar=japanese", "de",
2525 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2528 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2529 UErrorCode status
= U_ZERO_ERROR
;
2530 const char* keyword
=NULL
;
2531 int32_t keywordLen
= 0;
2532 int32_t keywordCount
= 0;
2533 UChar
*displayKeywordValue
= NULL
;
2534 int32_t displayKeywordValueLen
= 0;
2535 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2536 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2537 if(U_FAILURE(status
)){
2538 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
));
2541 /* the uenum_next returns NUL terminated string */
2542 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2544 /* fetch the displayKeywordValue */
2545 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2546 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2547 status
= U_ZERO_ERROR
;
2548 displayKeywordValueLen
++; /* for null termination */
2549 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2550 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2551 if(U_FAILURE(status
)){
2552 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
));
2553 free(displayKeywordValue
);
2556 if(u_strncmp(displayKeywordValue
, testCases
[i
].displayKeywordValue
, displayKeywordValueLen
)!=0){
2557 if (status
== U_USING_DEFAULT_WARNING
) {
2558 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
));
2560 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
));
2562 free(displayKeywordValue
);
2566 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2568 free(displayKeywordValue
);
2570 uenum_close(keywordEnum
);
2573 /* test a multiple keywords */
2574 UErrorCode status
= U_ZERO_ERROR
;
2575 const char* keyword
=NULL
;
2576 int32_t keywordLen
= 0;
2577 int32_t keywordCount
= 0;
2578 const char* localeID
= "es@collation=phonebook;calendar=buddhist;currency=DEM";
2579 const char* displayLocale
= "de";
2580 static const UChar expected
[][50] = {
2581 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2583 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2584 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2587 UEnumeration
* keywordEnum
= uloc_openKeywords(localeID
, &status
);
2589 for(keywordCount
= 0; keywordCount
< uenum_count(keywordEnum
, &status
) ; keywordCount
++){
2590 UChar
*displayKeywordValue
= NULL
;
2591 int32_t displayKeywordValueLen
= 0;
2592 if(U_FAILURE(status
)){
2593 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID
, displayLocale
, u_errorName(status
));
2596 /* the uenum_next returns NUL terminated string */
2597 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2599 /* fetch the displayKeywordValue */
2600 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2601 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2602 status
= U_ZERO_ERROR
;
2603 displayKeywordValueLen
++; /* for null termination */
2604 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2605 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2606 if(U_FAILURE(status
)){
2607 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
));
2608 free(displayKeywordValue
);
2611 if(u_strncmp(displayKeywordValue
, expected
[keywordCount
], displayKeywordValueLen
)!=0){
2612 if (status
== U_USING_DEFAULT_WARNING
) {
2613 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
));
2615 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID
, keyword
, displayLocale
);
2617 free(displayKeywordValue
);
2621 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2623 free(displayKeywordValue
);
2625 uenum_close(keywordEnum
);
2629 /* Test non existent keywords */
2630 UErrorCode status
= U_ZERO_ERROR
;
2631 const char* localeID
= "es";
2632 const char* displayLocale
= "de";
2633 UChar
*displayKeywordValue
= NULL
;
2634 int32_t displayKeywordValueLen
= 0;
2636 /* fetch the displayKeywordValue */
2637 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, "calendar", displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2638 if(U_FAILURE(status
)) {
2639 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status
));
2640 } else if(displayKeywordValueLen
!= 0) {
2641 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen
);
2647 static void TestGetBaseName(void) {
2648 static const struct {
2649 const char *localeID
;
2650 const char *baseName
;
2652 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2653 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2654 { "ja@calendar = buddhist", "ja" }
2657 int32_t i
= 0, baseNameLen
= 0;
2659 UErrorCode status
= U_ZERO_ERROR
;
2661 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2662 baseNameLen
= uloc_getBaseName(testCases
[i
].localeID
, baseName
, 256, &status
);
2663 (void)baseNameLen
; /* Suppress set but not used warning. */
2664 if(strcmp(testCases
[i
].baseName
, baseName
)) {
2665 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2666 testCases
[i
].localeID
, testCases
[i
].baseName
, baseName
);
2672 static void TestTrailingNull(void) {
2673 const char* localeId
= "zh_Hans";
2674 UChar buffer
[128]; /* sufficient for this test */
2676 UErrorCode status
= U_ZERO_ERROR
;
2679 len
= uloc_getDisplayName(localeId
, localeId
, buffer
, 128, &status
);
2681 log_err("buffer too small");
2685 for (i
= 0; i
< len
; ++i
) {
2686 if (buffer
[i
] == 0) {
2687 log_err("name contained null");
2693 /* Jitterbug 4115 */
2694 static void TestDisplayNameWarning(void) {
2697 UErrorCode status
= U_ZERO_ERROR
;
2699 size
= uloc_getDisplayLanguage("qqq", "kl", name
, UPRV_LENGTHOF(name
), &status
);
2700 (void)size
; /* Suppress set but not used warning. */
2701 if (status
!= U_USING_DEFAULT_WARNING
) {
2702 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2703 u_errorName(status
));
2709 * Compare two locale IDs. If they are equal, return 0. If `string'
2710 * starts with `prefix' plus an additional element, that is, string ==
2711 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2713 static UBool
_loccmp(const char* string
, const char* prefix
) {
2714 int32_t slen
= (int32_t)uprv_strlen(string
),
2715 plen
= (int32_t)uprv_strlen(prefix
);
2716 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
2717 /* 'root' is less than everything */
2718 if (uprv_strcmp(prefix
, "root") == 0) {
2719 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
2721 if (c
) return -1; /* mismatch */
2722 if (slen
== plen
) return 0;
2723 if (string
[plen
] == '_') return 1;
2724 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2727 static void _checklocs(const char* label
,
2730 const char* actual
) {
2731 /* We want the valid to be strictly > the bogus requested locale,
2732 and the valid to be >= the actual. */
2733 if (_loccmp(req
, valid
) > 0 &&
2734 _loccmp(valid
, actual
) >= 0) {
2735 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2736 label
, req
, valid
, actual
);
2738 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2739 label
, req
, valid
, actual
);
2743 static void TestGetLocale(void) {
2744 UErrorCode ec
= U_ZERO_ERROR
;
2746 UChar EMPTY
[1] = {0};
2749 #if !UCONFIG_NO_FORMATTING
2752 const char *req
= "en_US_REDWOODSHORES", *valid
, *actual
;
2753 obj
= udat_open(UDAT_DEFAULT
, UDAT_DEFAULT
,
2757 if (U_FAILURE(ec
)) {
2758 log_data_err("udat_open failed.Error %s\n", u_errorName(ec
));
2761 valid
= udat_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2762 actual
= udat_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2763 if (U_FAILURE(ec
)) {
2764 log_err("udat_getLocaleByType() failed\n");
2767 _checklocs("udat", req
, valid
, actual
);
2773 #if !UCONFIG_NO_FORMATTING
2776 const char *req
= "fr_FR_PROVENCAL", *valid
, *actual
;
2777 obj
= ucal_open(NULL
, 0,
2781 if (U_FAILURE(ec
)) {
2782 log_err("ucal_open failed with error: %s\n", u_errorName(ec
));
2785 valid
= ucal_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2786 actual
= ucal_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2787 if (U_FAILURE(ec
)) {
2788 log_err("ucal_getLocaleByType() failed\n");
2791 _checklocs("ucal", req
, valid
, actual
);
2797 #if !UCONFIG_NO_FORMATTING
2800 const char *req
= "zh_Hant_TW_TAINAN", *valid
, *actual
;
2801 obj
= unum_open(UNUM_DECIMAL
,
2805 if (U_FAILURE(ec
)) {
2806 log_err("unum_open failed\n");
2809 valid
= unum_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2810 actual
= unum_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2811 if (U_FAILURE(ec
)) {
2812 log_err("unum_getLocaleByType() failed\n");
2815 _checklocs("unum", req
, valid
, actual
);
2822 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2823 #if !UCONFIG_NO_FORMATTING
2825 UMessageFormat
*obj
;
2826 const char *req
= "ja_JP_TAKAYAMA", *valid
, *actual
;
2828 obj
= umsg_open(EMPTY
, 0,
2831 if (U_FAILURE(ec
)) {
2832 log_err("umsg_open failed\n");
2835 valid
= umsg_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2836 actual
= umsg_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2837 if (U_FAILURE(ec
)) {
2838 log_err("umsg_getLocaleByType() failed\n");
2841 /* We want the valid to be strictly > the bogus requested locale,
2842 and the valid to be >= the actual. */
2843 /* TODO MessageFormat is currently just storing the locale it is given.
2844 As a result, it will return whatever it was given, even if the
2845 locale is invalid. */
2846 test
= (_cmpversion("3.2") <= 0) ?
2847 /* Here is the weakened test for 3.0: */
2848 (_loccmp(req
, valid
) >= 0) :
2849 /* Here is what the test line SHOULD be: */
2850 (_loccmp(req
, valid
) > 0);
2853 _loccmp(valid
, actual
) >= 0) {
2854 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2856 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2864 #if !UCONFIG_NO_BREAK_ITERATION
2866 UBreakIterator
*obj
;
2867 const char *req
= "ar_KW_ABDALI", *valid
, *actual
;
2868 obj
= ubrk_open(UBRK_WORD
,
2873 if (U_FAILURE(ec
)) {
2874 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec
));
2877 valid
= ubrk_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2878 actual
= ubrk_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2879 if (U_FAILURE(ec
)) {
2880 log_err("ubrk_getLocaleByType() failed\n");
2883 _checklocs("ubrk", req
, valid
, actual
);
2889 #if !UCONFIG_NO_COLLATION
2892 const char *req
= "es_AR_BUENOSAIRES", *valid
, *actual
;
2893 obj
= ucol_open(req
, &ec
);
2894 if (U_FAILURE(ec
)) {
2895 log_err("ucol_open failed - %s\n", u_errorName(ec
));
2898 valid
= ucol_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2899 actual
= ucol_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2900 if (U_FAILURE(ec
)) {
2901 log_err("ucol_getLocaleByType() failed\n");
2904 _checklocs("ucol", req
, valid
, actual
);
2909 static void TestEnglishExemplarCharacters(void) {
2910 UErrorCode status
= U_ZERO_ERROR
;
2913 UChar testChars
[] = {
2914 0x61, /* standard */
2915 0xE1, /* auxiliary */
2917 0x2D /* punctuation */
2919 ULocaleData
*uld
= ulocdata_open("en", &status
);
2920 if (U_FAILURE(status
)) {
2921 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status
));
2925 for (i
= 0; i
< ULOCDATA_ES_COUNT
; i
++) {
2926 exSet
= ulocdata_getExemplarSet(uld
, exSet
, 0, (ULocaleDataExemplarSetType
)i
, &status
);
2927 if (U_FAILURE(status
)) {
2928 log_err_status(status
, "ulocdata_getExemplarSet() for type %d failed\n", i
);
2929 status
= U_ZERO_ERROR
;
2932 if (!uset_contains(exSet
, (UChar32
)testChars
[i
])) {
2933 log_err("Character U+%04X is not included in exemplar type %d\n", testChars
[i
], i
);
2938 ulocdata_close(uld
);
2941 static void TestNonexistentLanguageExemplars(void) {
2942 /* JB 4068 - Nonexistent language */
2943 UErrorCode ec
= U_ZERO_ERROR
;
2944 ULocaleData
*uld
= ulocdata_open("qqq",&ec
);
2945 if (ec
!= U_USING_DEFAULT_WARNING
) {
2946 log_err_status(ec
, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2949 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2950 ulocdata_close(uld
);
2953 static void TestLocDataErrorCodeChaining(void) {
2954 UErrorCode ec
= U_USELESS_COLLATOR_ERROR
;
2955 ulocdata_open(NULL
, &ec
);
2956 ulocdata_getExemplarSet(NULL
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
);
2957 ulocdata_getDelimiter(NULL
, ULOCDATA_DELIMITER_COUNT
, NULL
, -1, &ec
);
2958 ulocdata_getMeasurementSystem(NULL
, &ec
);
2959 ulocdata_getPaperSize(NULL
, NULL
, NULL
, &ec
);
2960 if (ec
!= U_USELESS_COLLATOR_ERROR
) {
2961 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec
));
2967 UMeasurementSystem measureSys
;
2970 static const LocToMeasureSys locToMeasures
[] = {
2971 { "fr_FR", UMS_SI
},
2973 { "en_GB", UMS_UK
},
2974 { "fr_FR@rg=GBZZZZ", UMS_UK
},
2975 { "en@rg=frzzzz", UMS_SI
},
2976 { "en_GB@rg=USZZZZ", UMS_US
},
2977 { NULL
, (UMeasurementSystem
)0 } /* terminator */
2980 static void TestLocDataWithRgTag(void) {
2981 const LocToMeasureSys
* locToMeasurePtr
= locToMeasures
;
2982 for (; locToMeasurePtr
->locale
!= NULL
; locToMeasurePtr
++) {
2983 UErrorCode status
= U_ZERO_ERROR
;
2984 UMeasurementSystem measureSys
= ulocdata_getMeasurementSystem(locToMeasurePtr
->locale
, &status
);
2985 if (U_FAILURE(status
)) {
2986 log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
2987 locToMeasurePtr
->locale
, u_errorName(status
));
2988 } else if (measureSys
!= locToMeasurePtr
->measureSys
) {
2989 log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
2990 locToMeasurePtr
->locale
, (int) locToMeasurePtr
->measureSys
, (int)measureSys
);
2995 static void TestLanguageExemplarsFallbacks(void) {
2996 /* Test that en_US fallsback, but en doesn't fallback. */
2997 UErrorCode ec
= U_ZERO_ERROR
;
2998 ULocaleData
*uld
= ulocdata_open("en_US",&ec
);
2999 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
3000 if (ec
!= U_USING_FALLBACK_WARNING
) {
3001 log_err_status(ec
, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
3004 ulocdata_close(uld
);
3006 uld
= ulocdata_open("en",&ec
);
3007 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
3008 if (ec
!= U_ZERO_ERROR
) {
3009 log_err_status(ec
, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
3012 ulocdata_close(uld
);
3015 static const char *acceptResult(UAcceptResult uar
) {
3016 return udbg_enumName(UDBG_UAcceptResult
, uar
);
3019 static void TestAcceptLanguage(void) {
3020 UErrorCode status
= U_ZERO_ERROR
;
3021 UAcceptResult outResult
;
3022 UEnumeration
*available
;
3028 int32_t httpSet
; /**< Which of http[] should be used? */
3029 const char *icuSet
; /**< ? */
3030 const char *expect
; /**< The expected locale result */
3031 UAcceptResult res
; /**< The expected error code */
3032 UErrorCode expectStatus
; /**< expected status */
3034 /*0*/{ 0, NULL
, "mt_MT", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
3035 /*1*/{ 1, NULL
, "en", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
3036 /*2*/{ 2, NULL
, "en", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
},
3037 /*3*/{ 3, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
},
3038 /*4*/{ 4, NULL
, "es", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
},
3039 /*5*/{ 5, NULL
, "en", ULOC_ACCEPT_VALID
, U_ZERO_ERROR
}, /* XF */
3040 /*6*/{ 6, NULL
, "ja", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
}, /* XF */
3041 /*7*/{ 7, NULL
, "zh", ULOC_ACCEPT_FALLBACK
, U_ZERO_ERROR
}, /* XF */
3042 /*8*/{ 8, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
}, /* */
3043 /*9*/{ 9, NULL
, "", ULOC_ACCEPT_FAILED
, U_ZERO_ERROR
}, /* */
3044 /*10*/{10, NULL
, "", ULOC_ACCEPT_FAILED
, U_BUFFER_OVERFLOW_ERROR
}, /* */
3045 /*11*/{11, NULL
, "", ULOC_ACCEPT_FAILED
, U_BUFFER_OVERFLOW_ERROR
}, /* */
3047 const int32_t numTests
= UPRV_LENGTHOF(tests
);
3048 static const char *http
[] = {
3049 /*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",
3050 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
3051 /*2*/ "en-wf, de-lx;q=0.8",
3052 /*3*/ "mga-ie;q=0.9, tlh",
3053 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3054 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3055 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3056 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3057 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3058 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
3059 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
3061 /*5*/ "zh-xx;q=0.9, en;q=0.6",
3063 /*7*/ "zh-xx;q=0.9",
3064 /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3065 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3066 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3067 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
3068 /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3069 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3070 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3071 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
3072 /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3073 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3074 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3075 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
3076 /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3077 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3078 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3079 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
3082 for(i
=0;i
<numTests
;i
++) {
3084 status
=U_ZERO_ERROR
;
3085 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3086 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
3088 available
= ures_openAvailableLocales(tests
[i
].icuSet
, &status
);
3090 rc
= uloc_acceptLanguageFromHTTP(tmp
, 199, &outResult
, http
[tests
[i
].httpSet
], available
, &status
);
3091 (void)rc
; /* Suppress set but not used warning. */
3092 uenum_close(available
);
3093 log_verbose(" got %s, %s [%s]\n", tmp
[0]?tmp
:"(EMPTY)", acceptResult(outResult
), u_errorName(status
));
3094 if(status
!= tests
[i
].expectStatus
) {
3095 log_err_status(status
, "FAIL: expected status %s but got %s\n", u_errorName(tests
[i
].expectStatus
), u_errorName(status
));
3096 } else if(U_SUCCESS(tests
[i
].expectStatus
)) {
3097 /* don't check content if expected failure */
3098 if(outResult
!= tests
[i
].res
) {
3099 log_err_status(status
, "FAIL: #%d: expected outResult of %s but got %s\n", i
,
3100 acceptResult( tests
[i
].res
),
3101 acceptResult( outResult
));
3102 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3103 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
,acceptResult(tests
[i
].res
));
3105 if((outResult
>0)&&uprv_strcmp(tmp
, tests
[i
].expect
)) {
3106 log_err_status(status
, "FAIL: #%d: expected %s but got %s\n", i
, tests
[i
].expect
, tmp
);
3107 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
3108 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
3114 static const char* LOCALE_ALIAS
[][2] = {
3128 static UBool
isLocaleAvailable(UResourceBundle
* resIndex
, const char* loc
){
3129 UErrorCode status
= U_ZERO_ERROR
;
3131 ures_getStringByKey(resIndex
, loc
,&len
, &status
);
3132 if(U_FAILURE(status
)){
3138 static void TestCalendar() {
3139 #if !UCONFIG_NO_FORMATTING
3141 UErrorCode status
= U_ZERO_ERROR
;
3142 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3143 if(U_FAILURE(status
)){
3144 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3147 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3148 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3149 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3150 UCalendar
* c1
= NULL
;
3151 UCalendar
* c2
= NULL
;
3153 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
3154 const char* l1
= ucal_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
3155 const char* l2
= ucal_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
3157 if(!isLocaleAvailable(resIndex
, newLoc
)){
3160 c1
= ucal_open(NULL
, -1, oldLoc
, UCAL_GREGORIAN
, &status
);
3161 c2
= ucal_open(NULL
, -1, newLoc
, UCAL_GREGORIAN
, &status
);
3163 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0 || status
!=U_ZERO_ERROR
) {
3164 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3166 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1
, l2
);
3170 ures_close(resIndex
);
3174 static void TestDateFormat() {
3175 #if !UCONFIG_NO_FORMATTING
3177 UErrorCode status
= U_ZERO_ERROR
;
3178 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3179 if(U_FAILURE(status
)){
3180 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3183 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3184 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3185 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3186 UDateFormat
* df1
= NULL
;
3187 UDateFormat
* df2
= NULL
;
3188 const char* l1
= NULL
;
3189 const char* l2
= NULL
;
3191 if(!isLocaleAvailable(resIndex
, newLoc
)){
3194 df1
= udat_open(UDAT_FULL
, UDAT_FULL
,oldLoc
, NULL
, 0, NULL
, -1, &status
);
3195 df2
= udat_open(UDAT_FULL
, UDAT_FULL
,newLoc
, NULL
, 0, NULL
, -1, &status
);
3196 if(U_FAILURE(status
)){
3197 log_err("Creation of date format failed %s\n", u_errorName(status
));
3200 /*Test function "getLocale"*/
3201 l1
= udat_getLocaleByType(df1
, ULOC_VALID_LOCALE
, &status
);
3202 l2
= udat_getLocaleByType(df2
, ULOC_VALID_LOCALE
, &status
);
3203 if(U_FAILURE(status
)){
3204 log_err("Fetching the locale by type failed. %s\n", u_errorName(status
));
3206 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
3207 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3209 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1
, l2
);
3213 ures_close(resIndex
);
3217 static void TestCollation() {
3218 #if !UCONFIG_NO_COLLATION
3220 UErrorCode status
= U_ZERO_ERROR
;
3221 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3222 if(U_FAILURE(status
)){
3223 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3226 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3227 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3228 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3229 UCollator
* c1
= NULL
;
3230 UCollator
* c2
= NULL
;
3231 const char* l1
= NULL
;
3232 const char* l2
= NULL
;
3234 status
= U_ZERO_ERROR
;
3235 if(!isLocaleAvailable(resIndex
, newLoc
)){
3238 if(U_FAILURE(status
)){
3239 log_err("Creation of collators failed %s\n", u_errorName(status
));
3242 c1
= ucol_open(oldLoc
, &status
);
3243 c2
= ucol_open(newLoc
, &status
);
3244 l1
= ucol_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
3245 l2
= ucol_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
3246 if(U_FAILURE(status
)){
3247 log_err("Fetching the locale names failed failed %s\n", u_errorName(status
));
3249 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
3250 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3252 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1
, l2
);
3256 ures_close(resIndex
);
3260 typedef struct OrientationStructTag
{
3261 const char* localeId
;
3262 ULayoutType character
;
3264 } OrientationStruct
;
3266 static const char* ULayoutTypeToString(ULayoutType type
)
3270 case ULOC_LAYOUT_LTR
:
3271 return "ULOC_LAYOUT_LTR";
3273 case ULOC_LAYOUT_RTL
:
3274 return "ULOC_LAYOUT_RTL";
3276 case ULOC_LAYOUT_TTB
:
3277 return "ULOC_LAYOUT_TTB";
3279 case ULOC_LAYOUT_BTT
:
3280 return "ULOC_LAYOUT_BTT";
3282 case ULOC_LAYOUT_UNKNOWN
:
3286 return "Unknown enum value for ULayoutType!";
3289 static void TestOrientation()
3291 static const OrientationStruct toTest
[] = {
3292 { "ar", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3293 { "aR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3294 { "ar_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3295 { "fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3296 { "Fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3297 { "he", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3298 { "ps", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3299 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3300 { "UR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3301 { "en", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3302 // Additional Apple tests for rdar://51447187
3303 { "sd", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3304 { "sd_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3305 { "sd_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3306 { "mni_Beng", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3307 { "mni_Mtei", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3308 { "sat_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3309 { "sat_Olck", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3310 { "ks", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3311 { "ks_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3312 { "ks_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3313 { "ks_Deva", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3314 { "pa", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3315 { "pa_Guru", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
},
3316 { "pa_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3317 { "pa_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3318 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3319 { "ur_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3320 { "ur_Aran", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3324 for (; i
< UPRV_LENGTHOF(toTest
); ++i
) {
3325 UErrorCode statusCO
= U_ZERO_ERROR
;
3326 UErrorCode statusLO
= U_ZERO_ERROR
;
3327 const char* const localeId
= toTest
[i
].localeId
;
3328 const ULayoutType co
= uloc_getCharacterOrientation(localeId
, &statusCO
);
3329 const ULayoutType expectedCO
= toTest
[i
].character
;
3330 const ULayoutType lo
= uloc_getLineOrientation(localeId
, &statusLO
);
3331 const ULayoutType expectedLO
= toTest
[i
].line
;
3332 if (U_FAILURE(statusCO
)) {
3333 log_err_status(statusCO
,
3334 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3336 u_errorName(statusCO
));
3338 else if (co
!= expectedCO
) {
3340 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3342 ULayoutTypeToString(expectedCO
),
3343 ULayoutTypeToString(co
));
3345 if (U_FAILURE(statusLO
)) {
3346 log_err_status(statusLO
,
3347 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3349 u_errorName(statusLO
));
3351 else if (lo
!= expectedLO
) {
3353 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3355 ULayoutTypeToString(expectedLO
),
3356 ULayoutTypeToString(lo
));
3361 static void TestULocale() {
3363 UErrorCode status
= U_ZERO_ERROR
;
3364 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3365 if(U_FAILURE(status
)){
3366 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3369 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3370 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3371 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3372 UChar name1
[256], name2
[256];
3373 char names1
[256], names2
[256];
3374 int32_t capacity
= 256;
3376 status
= U_ZERO_ERROR
;
3377 if(!isLocaleAvailable(resIndex
, newLoc
)){
3380 uloc_getDisplayName(oldLoc
, ULOC_US
, name1
, capacity
, &status
);
3381 if(U_FAILURE(status
)){
3382 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc
, u_errorName(status
));
3385 uloc_getDisplayName(newLoc
, ULOC_US
, name2
, capacity
, &status
);
3386 if(U_FAILURE(status
)){
3387 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc
, u_errorName(status
));
3390 if (u_strcmp(name1
, name2
)!=0) {
3391 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3393 u_austrcpy(names1
, name1
);
3394 u_austrcpy(names2
, name2
);
3395 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1
, names2
);
3397 ures_close(resIndex
);
3401 static void TestUResourceBundle() {
3405 UResourceBundle
* rb1
= NULL
;
3406 UResourceBundle
* rb2
= NULL
;
3407 UErrorCode status
= U_ZERO_ERROR
;
3409 UResourceBundle
*resIndex
= NULL
;
3410 if(U_FAILURE(status
)){
3411 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3414 resIndex
= ures_open(NULL
,"res_index", &status
);
3415 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3417 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3418 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3419 if(!isLocaleAvailable(resIndex
, newLoc
)){
3422 rb1
= ures_open(NULL
, oldLoc
, &status
);
3423 if (U_FAILURE(status
)) {
3424 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3427 us1
= ures_getLocaleByType(rb1
, ULOC_ACTUAL_LOCALE
, &status
);
3429 status
= U_ZERO_ERROR
;
3430 rb2
= ures_open(NULL
, newLoc
, &status
);
3431 if (U_FAILURE(status
)) {
3432 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3434 us2
= ures_getLocaleByType(rb2
, ULOC_ACTUAL_LOCALE
, &status
);
3436 if (strcmp(us1
,newLoc
)!=0 || strcmp(us1
,us2
)!=0 ) {
3437 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3440 log_verbose("ures_getStringByKey old:%s new:%s\n", us1
, us2
);
3446 ures_close(resIndex
);
3449 static void TestDisplayName() {
3451 UChar oldCountry
[256] = {'\0'};
3452 UChar newCountry
[256] = {'\0'};
3453 UChar oldLang
[256] = {'\0'};
3454 UChar newLang
[256] = {'\0'};
3455 char country
[256] ={'\0'};
3456 char language
[256] ={'\0'};
3457 int32_t capacity
= 256;
3460 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3461 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3462 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3463 UErrorCode status
= U_ZERO_ERROR
;
3464 int32_t available
= uloc_countAvailable();
3466 for(j
=0; j
<available
; j
++){
3468 const char* dispLoc
= uloc_getAvailable(j
);
3469 int32_t oldCountryLen
= uloc_getDisplayCountry(oldLoc
,dispLoc
, oldCountry
, capacity
, &status
);
3470 int32_t newCountryLen
= uloc_getDisplayCountry(newLoc
, dispLoc
, newCountry
, capacity
, &status
);
3471 int32_t oldLangLen
= uloc_getDisplayLanguage(oldLoc
, dispLoc
, oldLang
, capacity
, &status
);
3472 int32_t newLangLen
= uloc_getDisplayLanguage(newLoc
, dispLoc
, newLang
, capacity
, &status
);
3474 int32_t countryLen
= uloc_getCountry(newLoc
, country
, capacity
, &status
);
3475 int32_t langLen
= uloc_getLanguage(newLoc
, language
, capacity
, &status
);
3476 /* there is a display name for the current country ID */
3477 if(countryLen
!= newCountryLen
){
3478 if(u_strncmp(oldCountry
,newCountry
,oldCountryLen
)!=0){
3479 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc
, dispLoc
);
3482 /* there is a display name for the current lang ID */
3483 if(langLen
!=newLangLen
){
3484 if(u_strncmp(oldLang
,newLang
,oldLangLen
)){
3485 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc
, dispLoc
); }
3491 static void TestGetLocaleForLCID() {
3492 int32_t i
, length
, lengthPre
;
3493 const char* testLocale
= 0;
3494 UErrorCode status
= U_ZERO_ERROR
;
3495 char temp2
[40], temp3
[40];
3498 lcid
= uloc_getLCID("en_US");
3499 if (lcid
!= 0x0409) {
3500 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid
);
3503 lengthPre
= uloc_getLocaleForLCID(lcid
, temp2
, 4, &status
);
3504 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
3505 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status
));
3508 status
= U_ZERO_ERROR
;
3511 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3512 if (U_FAILURE(status
)) {
3513 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status
));
3514 status
= U_ZERO_ERROR
;
3517 if (length
!= lengthPre
) {
3518 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length
, lengthPre
);
3521 length
= uloc_getLocaleForLCID(0x12345, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3522 if (U_SUCCESS(status
)) {
3523 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2
, u_errorName(status
));
3525 status
= U_ZERO_ERROR
;
3527 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3528 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
3530 testLocale
=rawData2
[NAME
][i
];
3532 log_verbose("Testing %s ......\n", testLocale
);
3534 sscanf(rawData2
[LCID
][i
], "%x", &lcid
);
3535 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3536 if (U_FAILURE(status
)) {
3537 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid
, u_errorName(status
));
3538 status
= U_ZERO_ERROR
;
3542 if (length
!= (int32_t)uprv_strlen(temp2
)) {
3543 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length
, lcid
, uprv_strlen(temp2
));
3546 /* Compare language, country, script */
3547 length
= uloc_getLanguage(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3548 if (U_FAILURE(status
)) {
3549 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3550 status
= U_ZERO_ERROR
;
3552 else if (uprv_strcmp(temp3
, rawData2
[LANG
][i
]) && !(uprv_strcmp(temp3
, "nn") == 0 && uprv_strcmp(rawData2
[VAR
][i
], "NY") == 0)) {
3553 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[LANG
][i
], lcid
, temp2
);
3556 length
= uloc_getScript(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3557 if (U_FAILURE(status
)) {
3558 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3559 status
= U_ZERO_ERROR
;
3561 else if (uprv_strcmp(temp3
, rawData2
[SCRIPT
][i
])) {
3562 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[SCRIPT
][i
], lcid
, temp2
);
3565 length
= uloc_getCountry(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3566 if (U_FAILURE(status
)) {
3567 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3568 status
= U_ZERO_ERROR
;
3570 else if (uprv_strlen(rawData2
[CTRY
][i
]) && uprv_strcmp(temp3
, rawData2
[CTRY
][i
])) {
3571 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[CTRY
][i
], lcid
, temp2
);
3577 const char* const basic_maximize_data
[][2] = {
3622 "en_Latn_US_POSIX_1901"
3624 "en_Latn__POSIX_1901",
3625 "en_Latn_US_POSIX_1901"
3628 "en_Latn_US_POSIX_1901"
3631 "de_Latn_DE_POSIX_1901"
3636 "th@calendar=buddhist",
3637 "th_Thai_TH@calendar=buddhist"
3667 "de_Latn_DE_U_CO_PHONEBK"
3669 "de_Latn_u_co_phonebk",
3670 "de_Latn_DE_U_CO_PHONEBK"
3672 "de_Latn_DE_u_co_phonebk",
3673 "de_Latn_DE_U_CO_PHONEBK"
3676 "ar_Arab_EG@em=emoji"
3679 "en_Latn_US@em=emoji"
3681 "_Latn_DE@em=emoji",
3682 "de_Latn_DE@em=emoji"
3684 "_Zzzz_DE@em=emoji",
3685 "de_Latn_DE@em=emoji"
3688 "de_Latn_DE@em=emoji"
3689 }, { // start Apple tests for <rdar://problem/47494884>
3713 }, { // start Apple tests for <rdar://problem/54153189>
3734 const char* const basic_minimize_data
[][2] = {
3739 "en_Latn_US_POSIX_1901",
3742 "EN_Latn_US_POSIX_1901",
3745 "en_Zzzz_US_POSIX_1901",
3748 "de_Latn_DE_POSIX_1901",
3754 "en_Latn_US@calendar=gregorian",
3755 "en@calendar=gregorian"
3759 const char* const full_data
[][3] = {
3763 /* "REMOVE-LIKELY" */
4068 }, { // <rdar://problem/27943264>
4072 }, { // <rdar://problem/27943264>
4138 "pa_Aran_PK", // <rdar://problem/50687287>
4367 "ur_Arab_IN" // Apple <rdar://problem/47494884>
4371 "ur_Arab", // Apple <rdar://problem/47494884>
5210 "ur_Aran_PK", // Apple <rdar://problem/47494884>
5258 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
5259 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5845 "de@collation=phonebook",
5846 "de_Latn_DE@collation=phonebook",
5847 "de@collation=phonebook"
5851 typedef struct errorDataTag
{
5853 const char* expected
;
5858 const errorData maximizeErrors
[] = {
5862 U_ILLEGAL_ARGUMENT_ERROR
,
5866 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5868 U_ILLEGAL_ARGUMENT_ERROR
,
5872 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5874 U_ILLEGAL_ARGUMENT_ERROR
,
5878 "en_Latn_US_POSIX@currency=EURO",
5879 "en_Latn_US_POSIX@currency=EURO",
5880 U_BUFFER_OVERFLOW_ERROR
,
5884 "en_Latn_US_POSIX@currency=EURO",
5885 "en_Latn_US_POSIX@currency=EURO",
5886 U_STRING_NOT_TERMINATED_WARNING
,
5891 const errorData minimizeErrors
[] = {
5895 U_ILLEGAL_ARGUMENT_ERROR
,
5899 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5901 U_ILLEGAL_ARGUMENT_ERROR
,
5905 "en_Latn_US_POSIX@currency=EURO",
5906 "en__POSIX@currency=EURO",
5907 U_BUFFER_OVERFLOW_ERROR
,
5911 "en_Latn_US_POSIX@currency=EURO",
5912 "en__POSIX@currency=EURO",
5913 U_STRING_NOT_TERMINATED_WARNING
,
5918 static int32_t getExpectedReturnValue(const errorData
* data
)
5920 if (data
->uerror
== U_BUFFER_OVERFLOW_ERROR
||
5921 data
->uerror
== U_STRING_NOT_TERMINATED_WARNING
)
5923 return (int32_t)strlen(data
->expected
);
5931 static int32_t getBufferSize(const errorData
* data
, int32_t actualSize
)
5933 if (data
->expected
== NULL
)
5937 else if (data
->bufferSize
< 0)
5939 return (int32_t)strlen(data
->expected
) + 1;
5943 return data
->bufferSize
;
5947 static void TestLikelySubtags()
5949 char buffer
[ULOC_FULLNAME_CAPACITY
+ ULOC_KEYWORD_AND_VALUES_CAPACITY
+ 1];
5952 for (; i
< UPRV_LENGTHOF(basic_maximize_data
); ++i
)
5954 UErrorCode status
= U_ZERO_ERROR
;
5955 const char* const minimal
= basic_maximize_data
[i
][0];
5956 const char* const maximal
= basic_maximize_data
[i
][1];
5958 /* const int32_t length = */
5959 uloc_addLikelySubtags(
5964 if (U_FAILURE(status
)) {
5965 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal
, u_errorName(status
));
5966 status
= U_ZERO_ERROR
;
5968 else if (uprv_strlen(maximal
) == 0) {
5969 if (uprv_stricmp(minimal
, buffer
) != 0) {
5970 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5973 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5974 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal
, minimal
, buffer
);
5978 for (i
= 0; i
< UPRV_LENGTHOF(basic_minimize_data
); ++i
) {
5980 UErrorCode status
= U_ZERO_ERROR
;
5981 const char* const maximal
= basic_minimize_data
[i
][0];
5982 const char* const minimal
= basic_minimize_data
[i
][1];
5984 /* const int32_t length = */
5985 uloc_minimizeSubtags(
5991 if (U_FAILURE(status
)) {
5992 log_err_status(status
, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5993 status
= U_ZERO_ERROR
;
5995 else if (uprv_strlen(minimal
) == 0) {
5996 if (uprv_stricmp(maximal
, buffer
) != 0) {
5997 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
6000 else if (uprv_stricmp(minimal
, buffer
) != 0) {
6001 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
6005 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
6007 UErrorCode status
= U_ZERO_ERROR
;
6008 const char* const minimal
= full_data
[i
][0];
6009 const char* const maximal
= full_data
[i
][1];
6011 /* const int32_t length = */
6012 uloc_addLikelySubtags(
6017 if (U_FAILURE(status
)) {
6018 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal
, u_errorName(status
));
6019 status
= U_ZERO_ERROR
;
6021 else if (uprv_strlen(maximal
) == 0) {
6022 if (uprv_stricmp(minimal
, buffer
) != 0) {
6023 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
6026 else if (uprv_stricmp(maximal
, buffer
) != 0) {
6027 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
6031 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
6033 UErrorCode status
= U_ZERO_ERROR
;
6034 const char* const maximal
= full_data
[i
][1];
6035 const char* const minimal
= full_data
[i
][2];
6037 if (strlen(maximal
) > 0) {
6039 /* const int32_t length = */
6040 uloc_minimizeSubtags(
6046 if (U_FAILURE(status
)) {
6047 log_err_status(status
, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
6048 status
= U_ZERO_ERROR
;
6050 else if (uprv_strlen(minimal
) == 0) {
6051 if (uprv_stricmp(maximal
, buffer
) != 0) {
6052 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
6055 else if (uprv_stricmp(minimal
, buffer
) != 0) {
6056 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
6061 for (i
= 0; i
< UPRV_LENGTHOF(maximizeErrors
); ++i
) {
6063 UErrorCode status
= U_ZERO_ERROR
;
6064 const char* const minimal
= maximizeErrors
[i
].tag
;
6065 const char* const maximal
= maximizeErrors
[i
].expected
;
6066 const UErrorCode expectedStatus
= maximizeErrors
[i
].uerror
;
6067 const int32_t expectedLength
= getExpectedReturnValue(&maximizeErrors
[i
]);
6068 const int32_t bufferSize
= getBufferSize(&maximizeErrors
[i
], sizeof(buffer
));
6070 const int32_t length
=
6071 uloc_addLikelySubtags(
6077 if (status
== U_ZERO_ERROR
) {
6078 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal
, u_errorName(expectedStatus
));
6079 status
= U_ZERO_ERROR
;
6081 else if (status
!= expectedStatus
) {
6082 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
));
6084 else if (length
!= expectedLength
) {
6085 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal
, expectedLength
, length
);
6087 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
6088 if (uprv_strnicmp(maximal
, buffer
, bufferSize
) != 0) {
6089 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
6090 maximal
, minimal
, (int)sizeof(buffer
), buffer
);
6095 for (i
= 0; i
< UPRV_LENGTHOF(minimizeErrors
); ++i
) {
6097 UErrorCode status
= U_ZERO_ERROR
;
6098 const char* const maximal
= minimizeErrors
[i
].tag
;
6099 const char* const minimal
= minimizeErrors
[i
].expected
;
6100 const UErrorCode expectedStatus
= minimizeErrors
[i
].uerror
;
6101 const int32_t expectedLength
= getExpectedReturnValue(&minimizeErrors
[i
]);
6102 const int32_t bufferSize
= getBufferSize(&minimizeErrors
[i
], sizeof(buffer
));
6104 const int32_t length
=
6105 uloc_minimizeSubtags(
6111 if (status
== U_ZERO_ERROR
) {
6112 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal
, u_errorName(expectedStatus
));
6113 status
= U_ZERO_ERROR
;
6115 else if (status
!= expectedStatus
) {
6116 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
));
6118 else if (length
!= expectedLength
) {
6119 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal
, expectedLength
, length
);
6121 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
6122 if (uprv_strnicmp(minimal
, buffer
, bufferSize
) != 0) {
6123 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
6124 minimal
, maximal
, (int)sizeof(buffer
), buffer
);
6130 const char* const locale_to_langtag
[][3] = {
6133 {"en_US", "en-US", "en-US"},
6134 {"iw_IL", "he-IL", "he-IL"},
6135 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
6136 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
6137 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
6138 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL
}, /* variant POSIX_VAR is processed as regular variant */
6139 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL
}, /* variant VAR_POSIX is processed as regular variant */
6140 {"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 */
6141 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
6142 {"und_555", "und-555", "und-555"},
6143 {"123", "und", NULL
},
6144 {"%$#&", "und", NULL
},
6145 {"_Latn", "und-Latn", "und-Latn"},
6146 {"_DE", "und-DE", "und-DE"},
6147 {"und_FR", "und-FR", "und-FR"},
6148 {"th_TH_TH", "th-TH-x-lvariant-th", NULL
},
6149 {"bogus", "bogus", "bogus"},
6150 {"foooobarrr", "und", NULL
},
6151 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL
},
6152 {"en_US_1234", "en-US-1234", "en-US-1234"},
6153 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
6154 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
6155 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL
},
6156 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL
},
6157 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
6158 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
6159 {"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"},
6160 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
6161 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
6162 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL
},
6163 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL
},
6164 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
6165 {"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"},
6166 {"@x=elmer", "x-elmer", "x-elmer"},
6167 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
6168 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
6169 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
6171 {"en@a=bar;attribute=baz", "en-a-bar-u-baz", "en-a-bar-u-baz"},
6172 {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo", "en-a-bar-u-baz-x-u-foo"},
6173 {"en@attribute=baz", "en-u-baz", "en-u-baz"},
6174 {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"},
6175 {"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"},
6176 {"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"},
6177 {"en@9=efg;a=baz", "en-9-efg-a-baz", "en-9-efg-a-baz"},
6179 // Before ICU 64, ICU locale canonicalization had some additional mappings.
6180 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
6181 // The following now uses standard canonicalization.
6182 {"az_AZ_CYRL", "az-AZ-x-lvariant-cyrl", NULL
},
6187 static void TestToLanguageTag(void) {
6193 const char *expected
;
6195 for (i
= 0; locale_to_langtag
[i
][0] != NULL
; i
++) {
6196 inloc
= locale_to_langtag
[i
][0];
6198 /* testing non-strict mode */
6199 status
= U_ZERO_ERROR
;
6201 expected
= locale_to_langtag
[i
][1];
6203 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), FALSE
, &status
);
6204 (void)len
; /* Suppress set but not used warning. */
6205 if (U_FAILURE(status
)) {
6206 if (expected
!= NULL
) {
6207 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
6208 inloc
, u_errorName(status
));
6211 if (expected
== NULL
) {
6212 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
6214 } else if (uprv_strcmp(langtag
, expected
) != 0) {
6215 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6216 langtag
, inloc
, expected
);
6220 /* testing strict mode */
6221 status
= U_ZERO_ERROR
;
6223 expected
= locale_to_langtag
[i
][2];
6225 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), TRUE
, &status
);
6226 if (U_FAILURE(status
)) {
6227 if (expected
!= NULL
) {
6228 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
6229 inloc
, u_errorName(status
));
6232 if (expected
== NULL
) {
6233 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
6235 } else if (uprv_strcmp(langtag
, expected
) != 0) {
6236 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
6237 langtag
, inloc
, expected
);
6243 static void TestBug20132(void) {
6248 static const char inloc
[] = "en-C";
6249 static const char expected
[] = "en-x-lvariant-c";
6250 const int32_t expected_len
= (int32_t)uprv_strlen(expected
);
6252 /* Before ICU-20132 was fixed, calling uloc_toLanguageTag() with a too small
6253 * buffer would not immediately return the buffer size actually needed, but
6254 * instead require several iterations before getting the correct size. */
6256 status
= U_ZERO_ERROR
;
6257 len
= uloc_toLanguageTag(inloc
, langtag
, 1, FALSE
, &status
);
6259 if (U_FAILURE(status
) && status
!= U_BUFFER_OVERFLOW_ERROR
) {
6260 log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6261 inloc
, u_errorName(status
));
6264 if (len
!= expected_len
) {
6265 log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc
, len
, expected_len
);
6268 status
= U_ZERO_ERROR
;
6269 len
= uloc_toLanguageTag(inloc
, langtag
, expected_len
, FALSE
, &status
);
6271 if (U_FAILURE(status
)) {
6272 log_data_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s Are you missing data?\n",
6273 inloc
, u_errorName(status
));
6276 if (len
!= expected_len
) {
6277 log_err("Bad length returned by uloc_toLanguageTag for locale id [%s]: %i != %i\n", inloc
, len
, expected_len
);
6278 } else if (uprv_strncmp(langtag
, expected
, expected_len
) != 0) {
6279 log_data_err("uloc_toLanguageTag returned language tag [%.*s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
6280 len
, langtag
, inloc
, expected
);
6284 #define FULL_LENGTH -1
6285 static const struct {
6289 } langtag_to_locale
[] = {
6290 {"en", "en", FULL_LENGTH
},
6291 {"en-us", "en_US", FULL_LENGTH
},
6292 {"und-US", "_US", FULL_LENGTH
},
6293 {"und-latn", "_Latn", FULL_LENGTH
},
6294 {"en-US-posix", "en_US_POSIX", FULL_LENGTH
},
6295 {"de-de_euro", "de", 2},
6296 {"kok-IN", "kok_IN", FULL_LENGTH
},
6299 {"en-latn-x", "en_Latn", 7},
6300 {"art-lojban", "jbo", FULL_LENGTH
},
6301 {"zh-hakka", "hak", FULL_LENGTH
},
6302 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH
},
6303 {"zh-cmn-CH-u-co-pinyin", "cmn_CH@collation=pinyin", FULL_LENGTH
},
6304 {"xxx-yy", "xxx_YY", FULL_LENGTH
},
6305 {"fr-234", "fr_234", FULL_LENGTH
},
6306 {"i-default", "en@x=i-default", FULL_LENGTH
},
6308 {"ja-jp-jp", "ja_JP", 5},
6309 {"bogus", "bogus", FULL_LENGTH
},
6310 {"boguslang", "", 0},
6311 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH
},
6312 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH
},
6313 {"und-varzero-var1-vartwo", "__VARZERO", 11},
6314 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH
},
6315 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH
},
6316 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH
},
6317 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH
},
6318 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH
},
6319 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH
},
6320 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH
},
6321 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH
},
6322 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH
},
6323 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH
},
6324 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH
},
6325 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH
},
6326 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH
},
6327 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH
},
6328 {"x-elmer", "@x=elmer", FULL_LENGTH
},
6329 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH
},
6330 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH
},
6331 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH
},
6332 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH
},
6333 {"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
},
6334 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
6335 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
6336 {"de-1901-1901", "de__1901", 7},
6337 {"de-DE-1901-1901", "de_DE_1901", 10},
6338 {"en-a-bbb-a-ccc", "en@a=bbb", 8},
6340 {"en-a-bar-u-baz", "en@a=bar;attribute=baz", FULL_LENGTH
},
6341 {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", FULL_LENGTH
},
6342 {"en-u-baz", "en@attribute=baz", FULL_LENGTH
},
6343 {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", FULL_LENGTH
},
6344 {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", FULL_LENGTH
},
6345 {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", FULL_LENGTH
},
6346 {"und-Arab-u-em-emoji", "_Arab@em=emoji", FULL_LENGTH
},
6347 {"und-Latn-u-em-emoji", "_Latn@em=emoji", FULL_LENGTH
},
6348 {"und-Latn-DE-u-em-emoji", "_Latn_DE@em=emoji", FULL_LENGTH
},
6349 {"und-Zzzz-DE-u-em-emoji", "_Zzzz_DE@em=emoji", FULL_LENGTH
},
6350 {"und-DE-u-em-emoji", "_DE@em=emoji", FULL_LENGTH
},
6352 {"hant-cmn-cn", "hant", 4},
6353 {"zh-cmn-TW", "cmn_TW", FULL_LENGTH
},
6354 {"zh-x_t-ab", "zh", 2},
6355 {"zh-hans-cn-u-ca-x_t-u", "zh_Hans_CN@calendar=yes", 15},
6356 /* #20140 dupe keys in U-extension */
6357 {"zh-u-ca-chinese-ca-gregory", "zh@calendar=chinese", FULL_LENGTH
},
6358 {"zh-u-ca-gregory-co-pinyin-ca-chinese", "zh@calendar=gregorian;collation=pinyin", FULL_LENGTH
},
6359 {"de-latn-DE-1901-u-co-phonebk-co-pinyin-ca-gregory", "de_Latn_DE_1901@calendar=gregorian;collation=phonebook", FULL_LENGTH
},
6360 {"th-u-kf-nu-thai-kf-false", "th@colcasefirst=yes;numbers=thai", FULL_LENGTH
},
6361 /* #9562 IANA language tag data update */
6362 {"en-gb-oed", "en_GB_OXENDICT", FULL_LENGTH
},
6363 {"i-navajo", "nv", FULL_LENGTH
},
6364 {"i-navajo-a-foo", "nv@a=foo", FULL_LENGTH
},
6365 {"i-navajo-latn-us", "nv_Latn_US", FULL_LENGTH
},
6366 {"sgn-br", "bzs", FULL_LENGTH
},
6367 {"sgn-br-u-co-phonebk", "bzs@collation=phonebook", FULL_LENGTH
},
6368 {"ja-latn-hepburn-heploc", "ja_Latn__ALALC97", FULL_LENGTH
},
6369 {"ja-latn-hepburn-heploc-u-ca-japanese", "ja_Latn__ALALC97@calendar=japanese", FULL_LENGTH
},
6370 {"en-a-bcde-0-fgh", "en@0=fgh;a=bcde", FULL_LENGTH
},
6373 static void TestForLanguageTag(void) {
6378 int32_t expParsedLen
;
6380 for (i
= 0; i
< UPRV_LENGTHOF(langtag_to_locale
); i
++) {
6381 status
= U_ZERO_ERROR
;
6383 expParsedLen
= langtag_to_locale
[i
].len
;
6384 if (expParsedLen
== FULL_LENGTH
) {
6385 expParsedLen
= (int32_t)uprv_strlen(langtag_to_locale
[i
].bcpID
);
6387 uloc_forLanguageTag(langtag_to_locale
[i
].bcpID
, locale
, sizeof(locale
), &parsedLen
, &status
);
6388 if (U_FAILURE(status
)) {
6389 log_err_status(status
, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
6390 langtag_to_locale
[i
].bcpID
, u_errorName(status
));
6392 if (uprv_strcmp(langtag_to_locale
[i
].locID
, locale
) != 0) {
6393 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
6394 locale
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].locID
);
6396 if (parsedLen
!= expParsedLen
) {
6397 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
6398 parsedLen
, langtag_to_locale
[i
].bcpID
, expParsedLen
);
6404 static const struct {
6406 const char *canonical
;
6407 } langtag_to_canonical
[] = {
6409 {"de-DD-u-co-phonebk", "de-DE-u-co-phonebk"},
6411 {"jw-id-u-ca-islamic-civil", "jv-ID-u-ca-islamic-civil"},
6413 {"my-bu-u-nu-mymr", "my-MM-u-nu-mymr"},
6414 {"yuu-ru", "yug-RU"},
6418 static void TestLangAndRegionCanonicalize(void) {
6420 char canonical
[256];
6423 for (i
= 0; i
< UPRV_LENGTHOF(langtag_to_canonical
); i
++) {
6424 status
= U_ZERO_ERROR
;
6425 const char* input
= langtag_to_canonical
[i
].input
;
6426 uloc_forLanguageTag(input
, locale
, sizeof(locale
), NULL
, &status
);
6427 uloc_toLanguageTag(locale
, canonical
, sizeof(canonical
), TRUE
, &status
);
6428 if (U_FAILURE(status
)) {
6429 log_err_status(status
, "Error returned by uloc_forLanguageTag or uloc_toLanguageTag "
6430 "for language tag [%s] - error: %s\n", input
, u_errorName(status
));
6432 const char* expected_canonical
= langtag_to_canonical
[i
].canonical
;
6433 if (uprv_strcmp(expected_canonical
, canonical
) != 0) {
6434 log_data_err("input language tag [%s] is canonicalized to [%s] - expected: [%s]\n",
6435 input
, canonical
, expected_canonical
);
6441 static void TestToUnicodeLocaleKey(void)
6443 /* $IN specifies the result should be the input pointer itself */
6444 static const char* DATA
[][2] = {
6446 {"CALEndar", "ca"}, /* difference casing */
6447 {"ca", "ca"}, /* bcp key itself */
6448 {"kv", "kv"}, /* no difference between legacy and bcp */
6449 {"foo", NULL
}, /* unknown, bcp ill-formed */
6450 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
6455 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6456 const char* keyword
= DATA
[i
][0];
6457 const char* expected
= DATA
[i
][1];
6458 const char* bcpKey
= NULL
;
6460 bcpKey
= uloc_toUnicodeLocaleKey(keyword
);
6461 if (expected
== NULL
) {
6462 if (bcpKey
!= NULL
) {
6463 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword
, bcpKey
);
6465 } else if (bcpKey
== NULL
) {
6466 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6467 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6468 if (bcpKey
!= keyword
) {
6469 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, bcpKey
, keyword
);
6471 } else if (uprv_strcmp(bcpKey
, expected
) != 0) {
6472 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword
, bcpKey
, expected
);
6477 static void TestBug20321UnicodeLocaleKey(void)
6479 // key = alphanum alpha ;
6480 static const char* invalid
[] = {
6490 for (int i
= 0; i
< UPRV_LENGTHOF(invalid
); i
++) {
6491 const char* bcpKey
= NULL
;
6492 bcpKey
= uloc_toUnicodeLocaleKey(invalid
[i
]);
6493 if (bcpKey
!= NULL
) {
6494 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", invalid
[i
], bcpKey
);
6497 static const char* valid
[] = {
6501 for (int i
= 0; i
< UPRV_LENGTHOF(valid
); i
++) {
6502 const char* bcpKey
= NULL
;
6503 bcpKey
= uloc_toUnicodeLocaleKey(valid
[i
]);
6504 if (bcpKey
== NULL
) {
6505 log_err("toUnicodeLocaleKey: keyword=%s => NULL, expected!=NULL\n", valid
[i
]);
6510 static void TestToLegacyKey(void)
6512 /* $IN specifies the result should be the input pointer itself */
6513 static const char* DATA
[][2] = {
6514 {"kb", "colbackwards"},
6515 {"kB", "colbackwards"}, /* different casing */
6516 {"Collation", "collation"}, /* keyword itself with different casing */
6517 {"kv", "kv"}, /* no difference between legacy and bcp */
6518 {"foo", "$IN"}, /* unknown, bcp ill-formed */
6519 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
6520 {"e=mc2", NULL
}, /* unknown, bcp/legacy ill-formed */
6525 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6526 const char* keyword
= DATA
[i
][0];
6527 const char* expected
= DATA
[i
][1];
6528 const char* legacyKey
= NULL
;
6530 legacyKey
= uloc_toLegacyKey(keyword
);
6531 if (expected
== NULL
) {
6532 if (legacyKey
!= NULL
) {
6533 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword
, legacyKey
);
6535 } else if (legacyKey
== NULL
) {
6536 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6537 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6538 if (legacyKey
!= keyword
) {
6539 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, legacyKey
, keyword
);
6541 } else if (uprv_strcmp(legacyKey
, expected
) != 0) {
6542 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword
, legacyKey
, expected
);
6547 static void TestToUnicodeLocaleType(void)
6549 /* $IN specifies the result should be the input pointer itself */
6550 static const char* DATA
[][3] = {
6551 {"tz", "Asia/Kolkata", "inccu"},
6552 {"calendar", "gregorian", "gregory"},
6553 {"ca", "gregorian", "gregory"},
6554 {"ca", "Gregorian", "gregory"},
6555 {"ca", "buddhist", "buddhist"},
6556 {"Calendar", "Japanese", "japanese"},
6557 {"calendar", "Islamic-Civil", "islamic-civil"},
6558 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6559 {"colalternate", "NON-IGNORABLE", "noignore"},
6560 {"colcaselevel", "yes", "true"},
6561 {"rg", "GBzzzz", "$IN"},
6562 {"tz", "america/new_york", "usnyc"},
6563 {"tz", "Asia/Kolkata", "inccu"},
6564 {"timezone", "navajo", "usden"},
6565 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
6566 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6567 {"zz", "gregorian", NULL
}, /* unknown key, ill-formed type */
6568 {"co", "foo-", NULL
}, /* unknown type, ill-formed type */
6569 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6570 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6571 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6572 {"kr", "digit-spacepunct", NULL
}, /* invalid (bcp ill-formed) reordercode type */
6577 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6578 const char* keyword
= DATA
[i
][0];
6579 const char* value
= DATA
[i
][1];
6580 const char* expected
= DATA
[i
][2];
6581 const char* bcpType
= NULL
;
6583 bcpType
= uloc_toUnicodeLocaleType(keyword
, value
);
6584 if (expected
== NULL
) {
6585 if (bcpType
!= NULL
) {
6586 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, bcpType
);
6588 } else if (bcpType
== NULL
) {
6589 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6590 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6591 if (bcpType
!= value
) {
6592 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, bcpType
, value
);
6594 } else if (uprv_strcmp(bcpType
, expected
) != 0) {
6595 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, bcpType
, expected
);
6600 static void TestToLegacyType(void)
6602 /* $IN specifies the result should be the input pointer itself */
6603 static const char* DATA
[][3] = {
6604 {"calendar", "gregory", "gregorian"},
6605 {"ca", "gregory", "gregorian"},
6606 {"ca", "Gregory", "gregorian"},
6607 {"ca", "buddhist", "buddhist"},
6608 {"Calendar", "Japanese", "japanese"},
6609 {"calendar", "Islamic-Civil", "islamic-civil"},
6610 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6611 {"colalternate", "noignore", "non-ignorable"},
6612 {"colcaselevel", "true", "yes"},
6613 {"rg", "gbzzzz", "gbzzzz"},
6614 {"tz", "usnyc", "America/New_York"},
6615 {"tz", "inccu", "Asia/Calcutta"},
6616 {"timezone", "usden", "America/Denver"},
6617 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6618 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6619 {"ca", "aaaa", "$IN"}, /* unknown type */
6620 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6621 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6622 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6623 {"co", "e=mc2", NULL
}, /* known key, ill-formed bcp/legacy type */
6624 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6625 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6626 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6627 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6632 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6633 const char* keyword
= DATA
[i
][0];
6634 const char* value
= DATA
[i
][1];
6635 const char* expected
= DATA
[i
][2];
6636 const char* legacyType
= NULL
;
6638 legacyType
= uloc_toLegacyType(keyword
, value
);
6639 if (expected
== NULL
) {
6640 if (legacyType
!= NULL
) {
6641 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, legacyType
);
6643 } else if (legacyType
== NULL
) {
6644 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6645 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6646 if (legacyType
!= value
) {
6647 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, legacyType
, value
);
6649 } else if (uprv_strcmp(legacyType
, expected
) != 0) {
6650 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, legacyType
, expected
);
6652 log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword
, value
, legacyType
);
6659 static void test_unicode_define(const char *namech
, char ch
, const char *nameu
, UChar uch
)
6663 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech
, ch
,(int)ch
, nameu
, (int) uch
);
6664 u_charsToUChars(&ch
, asUch
, 1);
6665 if(asUch
[0] != uch
) {
6666 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
);
6668 log_verbose(" .. OK, == U+%04X\n", (int)asUch
[0]);
6672 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6674 static void TestUnicodeDefines(void) {
6675 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR
, ULOC_KEYWORD_SEPARATOR_UNICODE
);
6676 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN
, ULOC_KEYWORD_ASSIGN_UNICODE
);
6677 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR
, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE
);
6680 static void TestIsRightToLeft() {
6681 // API test only. More test cases in intltest/LocaleTest.
6682 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6683 log_err("uloc_isRightToLeft() failed");
6688 const char * badLocaleID
;
6689 const char * displayLocale
;
6690 const char * expectedName
;
6691 UErrorCode expectedStatus
;
6694 static const BadLocaleItem badLocaleItems
[] = {
6695 { "-9223372036854775808", "en", "9223372036854775808", U_USING_DEFAULT_WARNING
},
6696 /* add more in the future */
6697 { NULL
, NULL
, NULL
, U_ZERO_ERROR
} /* terminator */
6700 enum { kUBufDispNameMax
= 128, kBBufDispNameMax
= 256 };
6702 static void TestBadLocaleIDs() {
6703 const BadLocaleItem
* itemPtr
;
6704 for (itemPtr
= badLocaleItems
; itemPtr
->badLocaleID
!= NULL
; itemPtr
++) {
6705 UChar ubufExpect
[kUBufDispNameMax
], ubufGet
[kUBufDispNameMax
];
6706 UErrorCode status
= U_ZERO_ERROR
;
6707 int32_t ulenExpect
= u_unescape(itemPtr
->expectedName
, ubufExpect
, kUBufDispNameMax
);
6708 int32_t ulenGet
= uloc_getDisplayName(itemPtr
->badLocaleID
, itemPtr
->displayLocale
, ubufGet
, kUBufDispNameMax
, &status
);
6709 if (status
!= itemPtr
->expectedStatus
||
6710 (U_SUCCESS(status
) && (ulenGet
!= ulenExpect
|| u_strncmp(ubufGet
, ubufExpect
, ulenExpect
) != 0))) {
6711 char bbufExpect
[kBBufDispNameMax
], bbufGet
[kBBufDispNameMax
];
6712 u_austrncpy(bbufExpect
, ubufExpect
, ulenExpect
);
6713 u_austrncpy(bbufGet
, ubufGet
, ulenGet
);
6714 log_err("FAIL: For localeID %s, displayLocale %s, calling uloc_getDisplayName:\n"
6715 " expected status %-26s, name (len %2d): %s\n"
6716 " got status %-26s, name (len %2d): %s\n",
6717 itemPtr
->badLocaleID
, itemPtr
->displayLocale
,
6718 u_errorName(itemPtr
->expectedStatus
), ulenExpect
, bbufExpect
,
6719 u_errorName(status
), ulenGet
, bbufGet
);
6724 // Test case for ICU-20370.
6725 // The issue shows as an Addresss Sanitizer failure.
6726 static void TestBug20370() {
6727 const char *localeID
= "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar";
6728 uint32_t lcid
= uloc_getLCID(localeID
);
6730 log_err("FAIL: Expected LCID value of 0 for invalid localeID input.");
6735 // Test case for ICU-20149
6736 // Handle the duplicate U extension attribute
6737 static void TestBug20149() {
6738 const char *localeID
= "zh-u-foo-foo-co-pinyin";
6740 UErrorCode status
= U_ZERO_ERROR
;
6743 uloc_forLanguageTag(localeID
, locale
, sizeof(locale
), &parsedLen
, &status
);
6744 if (U_FAILURE(status
) ||
6745 0 !=strcmp("zh@attribute=foo;collation=pinyin", locale
)) {
6746 log_err("ERROR: in uloc_forLanguageTag %s return %s\n", myErrorName(status
), locale
);
6751 typedef enum UldnNameType
{
6756 TEST_ULOC_LOCALE
, // only valid with optStdMidLong
6757 TEST_ULOC_LANGUAGE
, // only valid with optStdMidLong
6758 TEST_ULOC_SCRIPT
, // only valid with optStdMidLong
6759 TEST_ULOC_REGION
, // only valid with optStdMidLong
6763 const char * localeToName
; // NULL to terminate a list of these
6764 UldnNameType nameType
;
6765 const UChar
* expectResult
;
6769 const char * displayLocale
;
6770 const UDisplayContext
* displayOptions
; // set of 3 UDisplayContext items
6771 const UldnItem
* testItems
;
6775 static const UDisplayContext optStdMidLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6776 static const UDisplayContext optStdMidShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6777 static const UDisplayContext optDiaMidLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6778 static const UDisplayContext optDiaMidShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6780 static const UDisplayContext optStdBegLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6781 static const UDisplayContext optStdBegShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6782 static const UDisplayContext optDiaBegLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6783 static const UDisplayContext optDiaBegShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6785 static const UDisplayContext optStdLstLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6786 static const UDisplayContext optStdLstShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6787 static const UDisplayContext optDiaLstLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6788 static const UDisplayContext optDiaLstShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6790 static const UldnItem en_StdMidLong
[] = {
6791 { "en_US", TEST_ULDN_LOCALE
, u
"English (US)" },
6792 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"English (US, Computer)" },
6793 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"English (US, Chinese Calendar)" },
6794 { "en_CA", TEST_ULDN_LOCALE
, u
"English (Canada)" },
6795 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6796 { "pt_BR", TEST_ULDN_LOCALE
, u
"Portuguese (Brazil)" },
6797 { "pt_PT", TEST_ULDN_LOCALE
, u
"Portuguese (Portugal)" },
6798 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" }, // Apple <rdar://problem/50750364>
6799 { "zh_Hans_CN", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (China mainland)" }, // Apple <rdar://problem/50750364>
6800 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" }, // Apple <rdar://problem/50750364>
6801 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" }, // Apple <rdar://problem/50750364>
6802 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" }, // Apple <rdar://problem/50750364>
6803 { "yue_Hans_CN", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (China mainland)" }, // Apple <rdar://problem/50750364>
6804 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" }, // Apple <rdar://problem/50750364>
6805 { "yue_Hant_HK", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Hong Kong)" }, // Apple <rdar://problem/50750364>
6806 { "zh_Hans@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6807 { "zh_Hans_CN@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6808 { "zh_Hant@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6809 { "zh_Hant_HK@calendar=chinese", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6810 { "yue_Hans@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6811 { "yue_Hans_CN@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6812 { "yue_Hant@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6813 { "yue_Hant_HK@calendar=chinese", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6814 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6815 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6816 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6817 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6818 { "US", TEST_ULDN_REGION
, u
"United States" },
6819 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6820 { "GB", TEST_ULDN_REGION
, u
"United Kingdom" },
6821 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6822 { "ps_Arab", TEST_ULDN_LOCALE
, u
"Pashto (Arabic)" },
6823 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Afghanistan)" },
6824 { "ks_Arab", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh)" }, // Apple <rdar://problem/50687287>
6825 { "ks_Aran", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq)" }, // Apple <rdar://problem/47494884>
6826 { "ks_Arab_IN", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, India)" }, // Apple <rdar://problem/50687287>
6827 { "ks_Aran_IN", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, India)" }, // Apple <rdar://problem/47494884>
6828 { "pa_Arab", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh)" }, // Apple <rdar://problem/50687287>
6829 { "pa_Aran", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq)" }, // Apple <rdar://problem/50687287>
6830 { "pa_Arab_PK", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Pakistan)" }, // Apple <rdar://problem/50687287>
6831 { "pa_Aran_PK", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Pakistan)" }, // Apple <rdar://problem/50687287>
6832 { "ur_Arab", TEST_ULDN_LOCALE
, u
"Urdu (Naskh)" }, // Apple <rdar://problem/50687287>
6833 { "ur_Aran", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq)" }, // Apple <rdar://problem/47494884>
6834 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Pakistan)" }, // Apple <rdar://problem/50687287>
6835 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Pakistan)" }, // Apple <rdar://problem/47494884>
6836 { "ps_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Islamic Calendar)" },
6837 { "ps_Arab_AF@calendar=islamic", TEST_ULDN_LOCALE
, u
"Pashto (Arabic, Afghanistan, Islamic Calendar)" },
6838 { "ks_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6839 { "ks_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6840 { "ks_Arab_IN@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Naskh, India, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6841 { "ks_Aran_IN@calendar=islamic", TEST_ULDN_LOCALE
, u
"Kashmiri (Nastaliq, India, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6842 { "pa_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6843 { "pa_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6844 { "pa_Arab_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6845 { "pa_Aran_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Punjabi (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6846 { "ur_Arab@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6847 { "ur_Aran@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6848 { "ur_Arab_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6849 { "ur_Aran_PK@calendar=islamic", TEST_ULDN_LOCALE
, u
"Urdu (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6850 { "Arab", TEST_ULDN_SCRIPT
, u
"Arabic" },
6851 { "Aran", TEST_ULDN_SCRIPT
, u
"Nastaliq" }, // Apple <rdar://problem/47494884>
6852 { "Qaag", TEST_ULDN_SCRIPT
, u
"Zawgyi" }, // Apple <rdar://problem/51471316>
6853 { "my_Qaag", TEST_ULDN_LOCALE
, u
"Burmese (Zawgyi)" }, // Apple <rdar://problem/51471316>
6855 { "zh_Hans", TEST_ULOC_LOCALE
, u
"Chinese, Simplified" }, // Apple <rdar://problem/51418203>
6856 { "zh_Hans_CN", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (China mainland)" }, // Apple <rdar://problem/51418203>
6857 { "zh_Hant", TEST_ULOC_LOCALE
, u
"Chinese, Traditional" }, // Apple <rdar://problem/51418203>
6858 { "zh_Hant_HK", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Hong Kong)" }, // Apple <rdar://problem/51418203>
6859 { "yue_Hans", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified" }, // Apple <rdar://problem/51418203>
6860 { "yue_Hans_CN", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (China mainland)" }, // Apple <rdar://problem/51418203>
6861 { "yue_Hant", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional" }, // Apple <rdar://problem/51418203>
6862 { "yue_Hant_HK", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Hong Kong)" }, // Apple <rdar://problem/51418203>
6863 { "zh_Hans@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6864 { "zh_Hans_CN@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6865 { "zh_Hant@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6866 { "zh_Hant_HK@calendar=chinese", TEST_ULOC_LOCALE
, u
"Chinese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6867 { "yue_Hans@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6868 { "yue_Hans_CN@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Simplified (China mainland, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6869 { "yue_Hant@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6870 { "yue_Hant_HK@calendar=chinese", TEST_ULOC_LOCALE
, u
"Cantonese, Traditional (Hong Kong, Chinese Calendar)" }, // Apple <rdar://problem/50750364>
6871 { "ks_Arab", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh)" }, // Apple <rdar://problem/51418203>
6872 { "ks_Aran", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq)" }, // Apple <rdar://problem/47494884>
6873 { "ks_Arab_IN", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, India)" }, // Apple <rdar://problem/51418203>
6874 { "ks_Aran_IN", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, India)" }, // Apple <rdar://problem/47494884>
6875 { "pa_Arab", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh)" }, // Apple <rdar://problem/51418203>
6876 { "pa_Aran", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq)" }, // Apple <rdar://problem/51418203>
6877 { "pa_Arab_PK", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Pakistan)" }, // Apple <rdar://problem/51418203>
6878 { "pa_Aran_PK", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Pakistan)" }, // Apple <rdar://problem/51418203>
6879 { "ur_Arab", TEST_ULOC_LOCALE
, u
"Urdu (Naskh)" }, // Apple <rdar://problem/51418203>
6880 { "ur_Aran", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq)" }, // Apple <rdar://problem/47494884>
6881 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Pakistan)" }, // Apple <rdar://problem/51418203>
6882 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Pakistan)" }, // Apple <rdar://problem/47494884>
6883 { "ks_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6884 { "ks_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6885 { "ks_Arab_IN@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Naskh, India, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6886 { "ks_Aran_IN@calendar=islamic", TEST_ULOC_LOCALE
, u
"Kashmiri (Nastaliq, India, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6887 { "pa_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6888 { "pa_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6889 { "pa_Arab_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6890 { "pa_Aran_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Punjabi (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6891 { "ur_Arab@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6892 { "ur_Aran@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6893 { "ur_Arab_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Naskh, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/50687287>
6894 { "ur_Aran_PK@calendar=islamic", TEST_ULOC_LOCALE
, u
"Urdu (Nastaliq, Pakistan, Islamic Calendar)" }, // Apple <rdar://problem/47494884>
6895 { "my_Qaag", TEST_ULOC_LOCALE
, u
"Burmese (Zawgyi)" }, // Apple <rdar://problem/51471316>
6898 static const UldnItem en_StdMidShrt
[] = {
6899 { "en_US", TEST_ULDN_LOCALE
, u
"English (US)" },
6900 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"English (US, Computer)" },
6901 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"English (US, Chinese Calendar)" },
6902 { "en_CA", TEST_ULDN_LOCALE
, u
"English (Canada)" },
6903 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6904 { "pt_BR", TEST_ULDN_LOCALE
, u
"Portuguese (Brazil)" },
6905 { "pt_PT", TEST_ULDN_LOCALE
, u
"Portuguese (Portugal)" },
6906 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6907 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6908 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6909 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6910 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6911 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6912 { "US", TEST_ULDN_REGION
, u
"US" },
6913 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6914 { "GB", TEST_ULDN_REGION
, u
"UK" },
6915 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6918 static const UldnItem en_DiaMidLong
[] = {
6919 { "en_US", TEST_ULDN_LOCALE
, u
"American English" },
6920 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"American English (Computer)" },
6921 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"American English (Chinese Calendar)" },
6922 { "en_CA", TEST_ULDN_LOCALE
, u
"Canadian English" },
6923 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6924 { "pt_BR", TEST_ULDN_LOCALE
, u
"Brazilian Portuguese" },
6925 { "pt_PT", TEST_ULDN_LOCALE
, u
"European Portuguese" },
6926 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6927 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6928 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6929 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6930 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6931 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6932 { "US", TEST_ULDN_REGION
, u
"United States" },
6933 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6934 { "GB", TEST_ULDN_REGION
, u
"United Kingdom" },
6935 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6938 static const UldnItem en_DiaMidShrt
[] = {
6939 { "en_US", TEST_ULDN_LOCALE
, u
"US English" },
6940 { "en_US_POSIX", TEST_ULDN_LOCALE
, u
"US English (Computer)" },
6941 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, u
"US English (Chinese Calendar)" },
6942 { "en_CA", TEST_ULDN_LOCALE
, u
"Canadian English" },
6943 { "pt", TEST_ULDN_LOCALE
, u
"Portuguese" },
6944 { "pt_BR", TEST_ULDN_LOCALE
, u
"Brazilian Portuguese" },
6945 { "pt_PT", TEST_ULDN_LOCALE
, u
"European Portuguese" },
6946 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6947 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"Chinese, Traditional (Hong Kong)" },
6948 { "zh_HK", TEST_ULDN_LOCALE
, u
"Chinese (Hong Kong)" },
6949 { "Latn", TEST_ULDN_SCRIPT
, u
"Latin" },
6950 { "Hans", TEST_ULDN_SCRIPT
, u
"Simplified Han" },
6951 { "Hant", TEST_ULDN_SCRIPT
, u
"Traditional Han" },
6952 { "US", TEST_ULDN_REGION
, u
"US" },
6953 { "CA", TEST_ULDN_REGION
, u
"Canada" },
6954 { "GB", TEST_ULDN_REGION
, u
"UK" },
6955 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
6958 static const UldnItem en_CA_DiaMidLong
[] = { // <rdar://problem/60916890>
6959 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" },
6960 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" },
6961 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6962 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" },
6963 { "ar_001", TEST_ULDN_LOCALE
, u
"Modern Standard Arabic" },
6964 { "de_AT", TEST_ULDN_LOCALE
, u
"Austrian German" },
6965 { "es_419", TEST_ULDN_LOCALE
, u
"Latin American Spanish" },
6966 { "fr_CA", TEST_ULDN_LOCALE
, u
"Canadian French" },
6967 { "en_GB", TEST_ULDN_LOCALE
, u
"British English" },
6968 { "en_US", TEST_ULDN_LOCALE
, u
"American English" },
6971 static const UldnItem en_CA_DiaMidShrt
[] = { // <rdar://problem/60916890>
6972 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" },
6973 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" },
6974 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6975 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" },
6976 { "ar_001", TEST_ULDN_LOCALE
, u
"Modern Standard Arabic" },
6977 { "de_AT", TEST_ULDN_LOCALE
, u
"Austrian German" },
6978 { "es_419", TEST_ULDN_LOCALE
, u
"Latin American Spanish" },
6979 { "fr_CA", TEST_ULDN_LOCALE
, u
"Canadian French" },
6980 { "en_GB", TEST_ULDN_LOCALE
, u
"UK English" },
6981 { "en_US", TEST_ULDN_LOCALE
, u
"US English" },
6984 static const UldnItem en_GB_DiaMidLong
[] = { // <rdar://problem/60916890>
6985 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" },
6986 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" },
6987 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
6988 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" },
6989 { "ar_001", TEST_ULDN_LOCALE
, u
"Modern Standard Arabic" },
6990 { "de_AT", TEST_ULDN_LOCALE
, u
"Austrian German" },
6991 { "es_419", TEST_ULDN_LOCALE
, u
"Latin American Spanish" },
6992 { "fr_CA", TEST_ULDN_LOCALE
, u
"Canadian French" },
6993 { "en_GB", TEST_ULDN_LOCALE
, u
"British English" },
6994 { "en_US", TEST_ULDN_LOCALE
, u
"American English" },
6997 static const UldnItem en_GB_DiaMidShrt
[] = { // <rdar://problem/60916890>
6998 { "yue_Hans", TEST_ULDN_LOCALE
, u
"Cantonese, Simplified" },
6999 { "yue_Hant", TEST_ULDN_LOCALE
, u
"Cantonese, Traditional" },
7000 { "zh_Hans", TEST_ULDN_LOCALE
, u
"Chinese, Simplified" },
7001 { "zh_Hant", TEST_ULDN_LOCALE
, u
"Chinese, Traditional" },
7002 { "ar_001", TEST_ULDN_LOCALE
, u
"Modern Standard Arabic" },
7003 { "de_AT", TEST_ULDN_LOCALE
, u
"Austrian German" },
7004 { "es_419", TEST_ULDN_LOCALE
, u
"Latin American Spanish" },
7005 { "fr_CA", TEST_ULDN_LOCALE
, u
"Canadian French" },
7006 { "en_GB", TEST_ULDN_LOCALE
, u
"UK English" },
7007 { "en_US", TEST_ULDN_LOCALE
, u
"US English" },
7010 static const UldnItem en_IN_StdMidLong
[] = {
7011 { "bn", TEST_ULDN_LOCALE
, u
"Bangla" },
7012 { "bn_Beng", TEST_ULDN_LOCALE
, u
"Bangla (Bangla)" },
7013 { "or", TEST_ULDN_LOCALE
, u
"Odia" },
7014 { "or_Orya", TEST_ULDN_LOCALE
, u
"Odia (Odia)" },
7017 static const UldnItem fr_StdMidLong
[] = {
7018 { "en_US", TEST_ULDN_LOCALE
, u
"anglais (É.-U.)" },
7019 { "US", TEST_ULDN_REGION
, u
"États-Unis" },
7020 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
7023 static const UldnItem fr_StdMidShrt
[] = {
7024 { "en_US", TEST_ULDN_LOCALE
, u
"anglais (É.-U.)" },
7025 { "US", TEST_ULDN_REGION
, u
"É.-U." },
7026 { "HK", TEST_ULDN_REGION
, u
"Hong Kong" },
7029 static const UldnItem fr_StdBegLong
[] = {
7030 { "en_US", TEST_ULDN_LOCALE
, u
"Anglais (É.-U.)" },
7033 static const UldnItem fr_StdLstLong
[] = {
7034 { "en_US", TEST_ULDN_LOCALE
, u
"Anglais (É.-U.)" },
7035 { "PS", TEST_ULDN_REGION
, u
"Territoires palestiniens" },
7038 static const UldnItem fr_DiaMidLong
[] = {
7039 { "en_US", TEST_ULDN_LOCALE
, u
"anglais américain" },
7042 static const UldnItem ca_StdLstLong
[] = {
7043 { "PS", TEST_ULDN_REGION
, u
"Territoris palestins" },
7044 { "SZ", TEST_ULDN_REGION
, u
"eSwatini" }, // Apple <rdar://65139631>
7047 static const UldnItem nb_StdMidLong
[] = {
7048 { "ur_Arab", TEST_ULDN_LOCALE
, u
"urdu (naskh)" },
7051 static const UldnItem ur_StdMidLong
[] = {
7052 { "ps_Arab", TEST_ULDN_LOCALE
, u
"پشتو (عربی)" },
7053 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"پشتو (عربی،افغانستان)" },
7054 { "ur_Aran", TEST_ULDN_LOCALE
, u
"اردو (نستعلیق)" }, // Apple <rdar://problem/47494884>
7055 { "ur_Arab", TEST_ULDN_LOCALE
, u
"اردو (نسخ)" }, // Apple <rdar://problem/50687287>
7056 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"اردو (نستعلیق،پاکستان)" }, // Apple <rdar://problem/47494884>
7057 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"اردو (نسخ،پاکستان)" }, // Apple <rdar://problem/50687287>
7059 { "ps_Arab", TEST_ULOC_LOCALE
, u
"پشتو (عربی)" },
7060 { "ps_Arab_AF", TEST_ULOC_LOCALE
, u
"پشتو (عربی،افغانستان)" },
7061 { "ur_Aran", TEST_ULOC_LOCALE
, u
"اردو (نستعلیق)" }, // Apple <rdar://problem/47494884>
7062 { "ur_Arab", TEST_ULOC_LOCALE
, u
"اردو (نسخ)" }, // Apple <rdar://problem/51418203>
7063 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"اردو (نستعلیق،پاکستان)" }, // Apple <rdar://problem/47494884>
7064 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"اردو (نسخ،پاکستان)" }, // Apple <rdar://problem/51418203>
7067 static const UldnItem pa_Arab_StdMidLong
[] = {
7068 { "pa_Aran", TEST_ULDN_LOCALE
, u
"پنجابی (نستعلیق)" }, // Apple <rdar://problem/47494884>
7069 { "pa_Arab", TEST_ULDN_LOCALE
, u
"پنجابی (نسخ)" }, // Apple <rdar://problem/50687287>
7070 { "pa_Aran_PK", TEST_ULDN_LOCALE
, u
"پنجابی (نستعلیق, پاکستان)" }, // Apple <rdar://problem/47494884>
7071 { "pa_Arab_PK", TEST_ULDN_LOCALE
, u
"پنجابی (نسخ, پاکستان)" }, // Apple <rdar://problem/50687287>
7073 { "pa_Aran", TEST_ULOC_LOCALE
, u
"پنجابی (نستعلیق)" }, // Apple <rdar://problem/51418203>
7074 { "pa_Arab", TEST_ULOC_LOCALE
, u
"پنجابی (نسخ)" }, // Apple <rdar://problem/51418203>
7075 { "pa_Aran_PK", TEST_ULOC_LOCALE
, u
"پنجابی (نستعلیق, پاکستان)" }, // Apple <rdar://problem/51418203>
7076 { "pa_Arab_PK", TEST_ULOC_LOCALE
, u
"پنجابی (نسخ, پاکستان)" }, // Apple <rdar://problem/51418203>
7079 static const UldnItem zh_StdMidLong
[] = {
7080 { "zh_Hans", TEST_ULDN_LOCALE
, u
"简体中文" }, // Apple <rdar://problem/50750364>
7081 { "zh_Hans_CN", TEST_ULDN_LOCALE
, u
"简体中文(中国大陆)" }, // Apple <rdar://problem/50750364>
7082 { "zh_Hant", TEST_ULDN_LOCALE
, u
"繁体中文" }, // Apple <rdar://problem/50750364>
7083 { "zh_Hant_HK", TEST_ULDN_LOCALE
, u
"繁体中文(香港)" }, // Apple <rdar://problem/50750364>
7084 { "yue_Hans", TEST_ULDN_LOCALE
, u
"简体粤语" }, // Apple <rdar://problem/50750364>
7085 { "yue_Hans_CN", TEST_ULDN_LOCALE
, u
"简体粤语(中国大陆)" }, // Apple <rdar://problem/50750364>
7086 { "yue_Hant", TEST_ULDN_LOCALE
, u
"繁体粤语" }, // Apple <rdar://problem/50750364>
7087 { "yue_Hant_HK", TEST_ULDN_LOCALE
, u
"繁体粤语(香港)" }, // Apple <rdar://problem/50750364>
7088 { "ps_Arab", TEST_ULDN_LOCALE
, u
"普什图语(阿拉伯文)" },
7089 { "ps_Arab_AF", TEST_ULDN_LOCALE
, u
"普什图语(阿拉伯文,阿富汗)" },
7090 { "ur_Aran", TEST_ULDN_LOCALE
, u
"乌尔都语(波斯体)" }, // Apple <rdar://problem/47494884>
7091 { "ur_Arab", TEST_ULDN_LOCALE
, u
"乌尔都语(誊抄体)" }, // Apple <rdar://problem/50687287>
7092 { "ur_Aran_PK", TEST_ULDN_LOCALE
, u
"乌尔都语(波斯体,巴基斯坦)" }, // Apple <rdar://problem/47494884>
7093 { "ur_Arab_PK", TEST_ULDN_LOCALE
, u
"乌尔都语(誊抄体,巴基斯坦)" }, // Apple <rdar://problem/50687287>
7095 { "zh_Hans", TEST_ULOC_LOCALE
, u
"简体中文" }, // Apple <rdar://problem/51418203>
7096 { "zh_Hans_CN", TEST_ULOC_LOCALE
, u
"简体中文(中国大陆)" }, // Apple <rdar://problem/51418203>
7097 { "zh_Hant", TEST_ULOC_LOCALE
, u
"繁体中文" }, // Apple <rdar://problem/51418203>
7098 { "zh_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体中文(香港)" }, // Apple <rdar://problem/51418203>
7099 { "yue_Hans", TEST_ULOC_LOCALE
, u
"简体粤语" }, // Apple <rdar://problem/51418203>
7100 { "yue_Hans_CN", TEST_ULOC_LOCALE
, u
"简体粤语(中国大陆)" }, // Apple <rdar://problem/51418203>
7101 { "yue_Hant", TEST_ULOC_LOCALE
, u
"繁体粤语" }, // Apple <rdar://problem/51418203>
7102 { "yue_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体粤语(香港)" }, // Apple <rdar://problem/51418203>
7103 { "ur_Aran", TEST_ULOC_LOCALE
, u
"乌尔都语(波斯体)" }, // Apple <rdar://problem/47494884>
7104 { "ur_Arab", TEST_ULOC_LOCALE
, u
"乌尔都语(誊抄体)" }, // Apple <rdar://problem/51418203>
7105 { "ur_Aran_PK", TEST_ULOC_LOCALE
, u
"乌尔都语(波斯体,巴基斯坦)" }, // Apple <rdar://problem/47494884>
7106 { "ur_Arab_PK", TEST_ULOC_LOCALE
, u
"乌尔都语(誊抄体,巴基斯坦)" }, // Apple <rdar://problem/51418203>
7109 static const UldnItem yue_Hans_StdMidLong
[] = {
7110 { "zh_Hans_CN", TEST_ULOC_LOCALE
, u
"简体中文(中国大陆)" }, // Apple <rdar://problem/53136228>
7111 { "zh_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体中文(香港)" }, // Apple <rdar://problem/53136228>
7112 { "yue_Hans_CN", TEST_ULOC_LOCALE
, u
"简体粤语(中国大陆)" }, // Apple <rdar://problem/53136228>
7113 { "yue_Hant_HK", TEST_ULOC_LOCALE
, u
"繁体粤语(香港)" }, // Apple <rdar://problem/53136228>
7116 static const UldnItem nds_StdMidLong
[] = { // Apple <rdar://problem/64703717>
7117 { "nds", TEST_ULOC_LOCALE
, u
"Neddersass’sch" },
7120 static const UldnItem hi_StdMidLong
[] = { // Apple <rdar://problem/53653337>
7121 { "Aran", TEST_ULDN_SCRIPT
, u
"नसतालीक़" },
7124 static const UldnItem hi_Latn_StdMidLong
[] = { // Apple <rdar://problem/53216112>
7125 { "en", TEST_ULDN_LOCALE
, u
"English" },
7126 { "hi_Deva", TEST_ULDN_LOCALE
, u
"Hindi (Devanagari)" },
7127 { "hi_Latn", TEST_ULDN_LOCALE
, u
"Hindi (Latin)" },
7128 { "hi_Latn_IN", TEST_ULDN_LOCALE
, u
"Hindi (Latin, Bhaarat)" },
7131 static const UldnItem mni_Beng_StdMidLong
[] = { // Apple <rdar://problem/54153189>
7132 { "mni_Beng", TEST_ULDN_LOCALE
, u
"মৈতৈলোন্ (বাংলা)" },
7133 { "mni_Mtei", TEST_ULDN_LOCALE
, u
"মৈতৈলোন্ (মেইটেই মায়েক)" },
7136 static const UldnItem mni_Mtei_StdMidLong
[] = { // Apple <rdar://problem/54153189>
7137 { "mni_Beng", TEST_ULDN_LOCALE
, u
"ꯃꯤꯇꯩꯂꯣꯟ (ꯕꯪꯂꯥ)" },
7138 { "mni_Mtei", TEST_ULDN_LOCALE
, u
"ꯃꯤꯇꯩꯂꯣꯟ (ꯃꯤꯇꯩ ꯃꯌꯦꯛ)" },
7141 static const UldnItem sat_Olck_StdMidLong
[] = { // Apple <rdar://problem/54153189>
7142 { "sat_Olck", TEST_ULDN_LOCALE
, u
"ᱥᱟᱱᱛᱟᱲᱤ (ᱚᱞ ᱪᱤᱠᱤ)" },
7143 { "sat_Deva", TEST_ULDN_LOCALE
, u
"ᱥᱟᱱᱛᱟᱲᱤ (ᱫᱮᱣᱟᱱᱟᱜᱟᱨᱤ)" },
7146 static const UldnItem sat_Deva_StdMidLong
[] = { // Apple <rdar://problem/54153189>
7147 { "sat_Olck", TEST_ULDN_LOCALE
, u
"सानताड़ी (अल चीकी)" },
7148 { "sat_Deva", TEST_ULDN_LOCALE
, u
"सानताड़ी (देवानागारी)" },
7151 static const UldnItem en_AU_StdBegLong
[] = { // Apple <rrdar://69835367>
7152 { "019", TEST_ULDN_REGION
, u
"Americas" },
7153 { "002", TEST_ULDN_REGION
, u
"Africa" },
7154 { "150", TEST_ULDN_REGION
, u
"Europe" },
7155 { "142", TEST_ULDN_REGION
, u
"Asia" },
7156 { "009", TEST_ULDN_REGION
, u
"Oceania" },
7159 static const UldnItem es_MX_StdBegLong
[] = { // Apple <rrdar://69835367>
7160 { "019", TEST_ULDN_REGION
, u
"América" },
7161 { "002", TEST_ULDN_REGION
, u
"África" },
7162 { "150", TEST_ULDN_REGION
, u
"Europa" },
7163 { "142", TEST_ULDN_REGION
, u
"Asia" },
7164 { "009", TEST_ULDN_REGION
, u
"Oceanía" },
7167 static const UldnLocAndOpts uldnLocAndOpts
[] = {
7168 { "en", optStdMidLong
, en_StdMidLong
, UPRV_LENGTHOF(en_StdMidLong
) },
7169 { "en", optStdMidShrt
, en_StdMidShrt
, UPRV_LENGTHOF(en_StdMidShrt
) },
7170 { "en", optDiaMidLong
, en_DiaMidLong
, UPRV_LENGTHOF(en_DiaMidLong
) },
7171 { "en", optDiaMidShrt
, en_DiaMidShrt
, UPRV_LENGTHOF(en_DiaMidShrt
) },
7172 { "en_CA", optDiaMidLong
, en_CA_DiaMidLong
, UPRV_LENGTHOF(en_CA_DiaMidLong
) }, // <rdar://problem/60916890>
7173 { "en_CA", optDiaMidShrt
, en_CA_DiaMidShrt
, UPRV_LENGTHOF(en_CA_DiaMidShrt
) }, // <rdar://problem/60916890>
7174 { "en_GB", optDiaMidLong
, en_GB_DiaMidLong
, UPRV_LENGTHOF(en_GB_DiaMidLong
) }, // <rdar://problem/60916890>
7175 { "en_GB", optDiaMidShrt
, en_GB_DiaMidShrt
, UPRV_LENGTHOF(en_GB_DiaMidShrt
) }, // <rdar://problem/60916890>
7176 { "en_IN", optStdMidLong
, en_IN_StdMidLong
, UPRV_LENGTHOF(en_IN_StdMidLong
) }, // <rdar://problem/65959353>
7177 { "fr", optStdMidLong
, fr_StdMidLong
, UPRV_LENGTHOF(fr_StdMidLong
) },
7178 { "fr", optStdMidShrt
, fr_StdMidShrt
, UPRV_LENGTHOF(fr_StdMidShrt
) },
7179 { "fr", optStdBegLong
, fr_StdBegLong
, UPRV_LENGTHOF(fr_StdBegLong
) },
7180 { "fr", optStdLstLong
, fr_StdLstLong
, UPRV_LENGTHOF(fr_StdLstLong
) },
7181 { "fr_CA", optStdLstLong
, fr_StdLstLong
, UPRV_LENGTHOF(fr_StdLstLong
) },
7182 { "fr", optDiaMidLong
, fr_DiaMidLong
, UPRV_LENGTHOF(fr_DiaMidLong
) },
7183 { "ca", optStdLstLong
, ca_StdLstLong
, UPRV_LENGTHOF(ca_StdLstLong
) },
7184 { "nb", optStdMidLong
, nb_StdMidLong
, UPRV_LENGTHOF(nb_StdMidLong
) }, // <rdar://problem/65008672>
7185 { "ur", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7186 { "ur_Arab", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7187 { "ur_Aran", optStdMidLong
, ur_StdMidLong
, UPRV_LENGTHOF(ur_StdMidLong
) },
7188 { "pa_Arab", optStdMidLong
, pa_Arab_StdMidLong
, UPRV_LENGTHOF(pa_Arab_StdMidLong
) },
7189 { "pa_Aran", optStdMidLong
, pa_Arab_StdMidLong
, UPRV_LENGTHOF(pa_Arab_StdMidLong
) },
7190 { "zh", optStdMidLong
, zh_StdMidLong
, UPRV_LENGTHOF(zh_StdMidLong
) },
7191 { "yue_Hans", optStdMidLong
, yue_Hans_StdMidLong
, UPRV_LENGTHOF(yue_Hans_StdMidLong
) },
7192 { "nds", optStdMidLong
, nds_StdMidLong
, UPRV_LENGTHOF(nds_StdMidLong
) },
7193 { "hi", optStdMidLong
, hi_StdMidLong
, UPRV_LENGTHOF(hi_StdMidLong
) },
7194 { "hi_Latn", optStdMidLong
, hi_Latn_StdMidLong
, UPRV_LENGTHOF(hi_Latn_StdMidLong
) },
7195 { "mni_Beng", optStdMidLong
, mni_Beng_StdMidLong
, UPRV_LENGTHOF(mni_Beng_StdMidLong
) },
7196 { "mni_Mtei", optStdMidLong
, mni_Mtei_StdMidLong
, UPRV_LENGTHOF(mni_Mtei_StdMidLong
) },
7197 { "sat_Olck", optStdMidLong
, sat_Olck_StdMidLong
, UPRV_LENGTHOF(sat_Olck_StdMidLong
) },
7198 { "sat_Deva", optStdMidLong
, sat_Deva_StdMidLong
, UPRV_LENGTHOF(sat_Deva_StdMidLong
) },
7199 { "en_AU", optStdBegLong
, en_AU_StdBegLong
, UPRV_LENGTHOF(en_AU_StdBegLong
) }, // <rdar://69835367>
7200 { "es_MX", optStdBegLong
, es_MX_StdBegLong
, UPRV_LENGTHOF(es_MX_StdBegLong
) }, // <rdar://69835367>
7201 { NULL
, NULL
, NULL
, 0 }
7204 enum { kUNameBuf
= 128, kBNameBuf
= 256 };
7206 static void TestUldnNameVariants() {
7207 const UldnLocAndOpts
* uloPtr
;
7208 for (uloPtr
= uldnLocAndOpts
; uloPtr
->displayLocale
!= NULL
; uloPtr
++) {
7209 UErrorCode status
= U_ZERO_ERROR
;
7210 ULocaleDisplayNames
* uldn
= uldn_openForContext(uloPtr
->displayLocale
, (UDisplayContext
*)uloPtr
->displayOptions
, 3, &status
);
7211 if (U_FAILURE(status
)) {
7212 log_data_err("uldn_openForContext fails, displayLocale %s, contexts %03X %03X %03X: %s - Are you missing data?\n",
7213 uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7214 u_errorName(status
) );
7217 const UldnItem
* itemPtr
= uloPtr
->testItems
;
7218 int32_t itemCount
= uloPtr
->countItems
;
7219 for (; itemCount
-- > 0; itemPtr
++) {
7220 UChar uget
[kUNameBuf
];
7221 int32_t ulenget
, ulenexp
;
7222 const char* typeString
;
7223 status
= U_ZERO_ERROR
;
7224 switch (itemPtr
->nameType
) {
7225 case TEST_ULDN_LOCALE
:
7226 ulenget
= uldn_localeDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7227 typeString
= "uldn_localeDisplayName";
7229 case TEST_ULDN_LANGUAGE
:
7230 ulenget
= uldn_languageDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7231 typeString
= "uldn_languageDisplayName";
7233 case TEST_ULDN_SCRIPT
:
7234 ulenget
= uldn_scriptDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7235 typeString
= "uldn_scriptDisplayName";
7237 case TEST_ULDN_REGION
:
7238 ulenget
= uldn_regionDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
7239 typeString
= "uldn_regionDisplayName";
7241 case TEST_ULOC_LOCALE
:
7242 ulenget
= uloc_getDisplayName(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7243 typeString
= "uloc_getDisplayName";
7245 case TEST_ULOC_LANGUAGE
:
7246 ulenget
= uloc_getDisplayLanguage(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7247 typeString
= "uloc_getDisplayLanguage";
7249 case TEST_ULOC_SCRIPT
:
7250 ulenget
= uloc_getDisplayScript(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7251 typeString
= "uloc_getDisplayScript";
7253 case TEST_ULOC_REGION
:
7254 ulenget
= uloc_getDisplayCountry(itemPtr
->localeToName
, uloPtr
->displayLocale
, uget
, kUNameBuf
, &status
);
7255 typeString
= "uloc_getDisplayCountry";
7260 if (U_FAILURE(status
)) {
7261 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s: %s\n",
7262 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7263 itemPtr
->localeToName
, u_errorName(status
) );
7266 ulenexp
= u_strlen(itemPtr
->expectResult
);
7267 if (ulenget
!= ulenexp
|| u_strncmp(uget
, itemPtr
->expectResult
, ulenexp
) != 0) {
7268 char bexp
[kBNameBuf
], bget
[kBNameBuf
];
7269 u_strToUTF8(bexp
, kBNameBuf
, NULL
, itemPtr
->expectResult
, ulenexp
, &status
);
7270 u_strToUTF8(bget
, kBNameBuf
, NULL
, uget
, ulenget
, &status
);
7271 log_data_err("%s fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s:\n expect %2d: %s\n get %2d: %s\n",
7272 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
7273 itemPtr
->localeToName
, ulenexp
, bexp
, ulenget
, bget
);
7281 #define ULOC_UND_TESTNUM 9
7283 static const char* for_empty
[ULOC_UND_TESTNUM
] = { // ""
7285 "", // uloc_getLanguage
7286 "en_Latn_US_POSIX", // uloc_addLikelySubtags
7287 "en__POSIX", // uloc_minimizeSubtags
7288 "en_US_POSIX", // uloc_canonicalize
7289 "", // uloc_getParent
7290 "und", // uloc_toLanguageTag
7291 "", // uloc_getDisplayName in en
7292 "", // uloc_getDisplayLanguage in en
7294 static const char* for_root
[ULOC_UND_TESTNUM
] = { // "root"
7295 "root", // uloc_getName
7296 "root", // uloc_getLanguage
7297 "root", // uloc_addLikelySubtags
7298 "root", // uloc_minimizeSubtags
7299 "root", // uloc_canonicalize
7300 "", // uloc_getParent
7301 "root", // uloc_toLanguageTag
7302 "Root", // uloc_getDisplayName in en
7303 "Root", // uloc_getDisplayLanguage in en
7305 static const char* for_und
[ULOC_UND_TESTNUM
] = { // "und"
7306 "und", // uloc_getName
7307 "und", // uloc_getLanguage
7308 "en_Latn_US", // uloc_addLikelySubtags
7309 "und", // uloc_minimizeSubtags
7310 "und", // uloc_canonicalize
7311 "", // uloc_getParent
7312 "und", // uloc_toLanguageTag
7313 "Unknown language", // uloc_getDisplayName in en
7314 "Unknown language", // uloc_getDisplayLanguage in en
7316 static const char* for_und_ZZ
[ULOC_UND_TESTNUM
] = { // "und_ZZ"
7317 "und_ZZ", // uloc_getName
7318 "und", // uloc_getLanguage
7319 "en_Latn_US", // uloc_addLikelySubtags
7320 "und", // uloc_minimizeSubtags
7321 "und_ZZ", // uloc_canonicalize
7322 "und", // uloc_getParent
7323 "und-ZZ", // uloc_toLanguageTag
7324 "Unknown language (Unknown Region)", // uloc_getDisplayName in en
7325 "Unknown language", // uloc_getDisplayLanguage in en
7327 static const char* for_empty_ZZ
[ULOC_UND_TESTNUM
] = { // "_ZZ"
7328 "_ZZ", // uloc_getName
7329 "", // uloc_getLanguage
7330 "en_Latn_US", // uloc_addLikelySubtags
7331 "und", // uloc_minimizeSubtags
7332 "_ZZ", // uloc_canonicalize
7333 "", // uloc_getParent
7334 "und-ZZ", // uloc_toLanguageTag
7335 "Unknown Region", // uloc_getDisplayName in en
7336 "", // uloc_getDisplayLanguage in en
7340 const char * locale
;
7341 const char ** expResults
;
7344 static const RootUndEmptyItem rootUndEmptryItems
[] = {
7346 { "root", for_root
},
7348 { "und_ZZ", for_und_ZZ
},
7349 { "_ZZ", for_empty_ZZ
},
7353 enum { kULocMax
= 64, kBLocMax
= 128 };
7355 static void TestRootUndEmpty() {
7356 const RootUndEmptyItem
* itemPtr
;
7357 for (itemPtr
= rootUndEmptryItems
; itemPtr
->locale
!= NULL
; itemPtr
++) {
7358 const char* loc
= itemPtr
->locale
;
7359 const char** expResultsPtr
= itemPtr
->expResults
;
7361 char bget
[kBLocMax
];
7362 UChar uexp
[kULocMax
];
7363 UChar uget
[kULocMax
];
7367 status
= U_ZERO_ERROR
;
7368 bexp
= *expResultsPtr
++;
7369 blen
= uloc_getName(loc
, bget
, kBLocMax
, &status
);
7370 if (U_FAILURE(status
)) {
7371 log_err("loc \"%s\", uloc_getName status: %s\n", loc
, u_errorName(status
) );
7372 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7373 log_err("loc \"%s\", uloc_getName expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7376 status
= U_ZERO_ERROR
;
7377 bexp
= *expResultsPtr
++;
7378 blen
= uloc_getLanguage(loc
, bget
, kBLocMax
, &status
);
7379 if (U_FAILURE(status
)) {
7380 log_err("loc \"%s\", uloc_getLanguage status: %s\n", loc
, u_errorName(status
) );
7381 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7382 log_err("loc \"%s\", uloc_getLanguage expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7385 status
= U_ZERO_ERROR
;
7386 bexp
= *expResultsPtr
++;
7387 blen
= uloc_addLikelySubtags(loc
, bget
, kBLocMax
, &status
);
7388 if (U_FAILURE(status
)) {
7389 log_err("loc \"%s\", uloc_addLikelySubtags status: %s\n", loc
, u_errorName(status
) );
7390 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7391 log_err("loc \"%s\", uloc_addLikelySubtags expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7394 status
= U_ZERO_ERROR
;
7395 bexp
= *expResultsPtr
++;
7396 blen
= uloc_minimizeSubtags(loc
, bget
, kBLocMax
, &status
);
7397 if (U_FAILURE(status
)) {
7398 log_err("loc \"%s\", uloc_minimizeSubtags status: %s\n", loc
, u_errorName(status
) );
7399 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7400 log_err("loc \"%s\", uloc_minimizeSubtags expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7403 status
= U_ZERO_ERROR
;
7404 bexp
= *expResultsPtr
++;
7405 blen
= uloc_canonicalize(loc
, bget
, kBLocMax
, &status
);
7406 if (U_FAILURE(status
)) {
7407 log_err("loc \"%s\", uloc_canonicalize status: %s\n", loc
, u_errorName(status
) );
7408 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7409 log_err("loc \"%s\", uloc_canonicalize expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7412 status
= U_ZERO_ERROR
;
7413 bexp
= *expResultsPtr
++;
7414 blen
= uloc_getParent(loc
, bget
, kBLocMax
, &status
);
7415 if (U_FAILURE(status
)) {
7416 log_err("loc \"%s\", uloc_getParent status: %s\n", loc
, u_errorName(status
) );
7417 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7418 log_err("loc \"%s\", uloc_getParent expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7421 status
= U_ZERO_ERROR
;
7422 bexp
= *expResultsPtr
++;
7423 blen
= uloc_toLanguageTag(loc
, bget
, kBLocMax
, TRUE
, &status
);
7424 if (U_FAILURE(status
)) {
7425 log_err("loc \"%s\", uloc_toLanguageTag status: %s\n", loc
, u_errorName(status
) );
7426 } else if (uprv_strcmp(bget
, bexp
) != 0) {
7427 log_err("loc \"%s\", uloc_toLanguageTag expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7430 status
= U_ZERO_ERROR
;
7431 bexp
= *expResultsPtr
++;
7432 u_unescape(bexp
, uexp
, kULocMax
);
7433 uexp
[kULocMax
-1] = 0; // force zero term
7434 ulen
= uloc_getDisplayName(loc
, "en", uget
, kULocMax
, &status
);
7435 if (U_FAILURE(status
)) {
7436 log_err("loc \"%s\", uloc_getDisplayName en status: %s\n", loc
, u_errorName(status
) );
7437 } else if (u_strcmp(uget
, uexp
) != 0) {
7438 u_austrncpy(bget
, uget
, kBLocMax
);
7439 bget
[kBLocMax
-1] = 0;
7440 log_err("loc \"%s\", uloc_getDisplayName en expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7443 status
= U_ZERO_ERROR
;
7444 bexp
= *expResultsPtr
++;
7445 u_unescape(bexp
, uexp
, kULocMax
);
7446 uexp
[kULocMax
-1] = 0; // force zero term
7447 ulen
= uloc_getDisplayLanguage(loc
, "en", uget
, kULocMax
, &status
);
7448 if (U_FAILURE(status
)) {
7449 log_err("loc \"%s\", uloc_getDisplayLanguage en status: %s\n", loc
, u_errorName(status
) );
7450 } else if (u_strcmp(uget
, uexp
) != 0) {
7451 u_austrncpy(bget
, uget
, kBLocMax
);
7452 bget
[kBLocMax
-1] = 0;
7453 log_err("loc \"%s\", uloc_getDisplayLanguage en expect \"%s\", get \"%s\"\n", loc
, bexp
, bget
);
7459 #if !U_PLATFORM_HAS_WIN32_API
7460 /* Apple-specific, test for Apple-specific function ualoc_getAppleParent */
7461 static const char* localesAndAppleParent
[] = {
7532 "zh_HK", "zh_Hant_HK",
7533 "zh-HK", "zh_Hant_HK",
7535 "zh-Hant-HK", "zh_Hant",
7536 "zh_Hant_HK", "zh_Hant",
7537 "zh-Hant-MO", "zh_Hant_HK",
7538 "zh-Hans-HK", "zh_Hans",
7541 "en-Latn-US", "en_Latn",
7542 "en_US_POSIX", "en_US",
7543 "en_Latn_US_POSIX", "en_Latn_US",
7544 "en-u-ca-hebrew", "root",
7545 "en@calendar=hebrew", "root",
7546 "en_@calendar=hebrew", "root",
7549 "Default@2x", "root",
7551 NULL
/* terminator */
7554 static void TestGetAppleParent() {
7555 const char **localesPtr
= localesAndAppleParent
;
7556 const char * locale
;
7557 while ((locale
= *localesPtr
++) != NULL
) {
7558 const char * expectParent
= *localesPtr
++;
7559 UErrorCode status
= U_ZERO_ERROR
;
7560 char getParent
[ULOC_FULLNAME_CAPACITY
];
7561 int32_t plen
= ualoc_getAppleParent(locale
, getParent
, ULOC_FULLNAME_CAPACITY
, &status
);
7562 if (U_FAILURE(status
)) {
7563 log_err("FAIL: ualoc_getAppleParent input \"%s\", status %s\n", locale
, u_errorName(status
));
7564 } else if (uprv_strcmp(expectParent
, getParent
) != 0) {
7565 log_err("FAIL: ualoc_getAppleParent input \"%s\", expected parent \"%s\", got parent \"%s\"\n", locale
, expectParent
, getParent
);
7570 /* Apple-specific, test for Apple-specific function ualoc_getLanguagesForRegion */
7571 enum { kUALanguageEntryMin
= 10, kUALanguageEntryMax
= 20 };
7573 static void TestGetLanguagesForRegion() {
7574 UALanguageEntry entries
[kUALanguageEntryMax
];
7577 const char * region
;
7579 status
= U_ZERO_ERROR
;
7581 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMin
, &status
);
7582 if (U_FAILURE(status
)) {
7583 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7585 // Expect approximately:
7586 // zh_Hans 0.90 UALANGSTATUS_OFFICIAL
7589 // yue 0.043 Yue including Cantonese
7594 // ug_Arab 0.0055 Uighur UALANGSTATUS_REGIONAL_OFFICIAL
7595 // ...at least 4 more with fractions >= 0.001
7596 if (entryCount
< kUALanguageEntryMin
) {
7597 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7599 UALanguageEntry
* entryPtr
= entries
;
7600 if (uprv_strcmp(entryPtr
->languageCode
, "zh_Hans") != 0 || entryPtr
->userFraction
< 0.8 || entryPtr
->userFraction
> 1.0 || entryPtr
->status
!= UALANGSTATUS_OFFICIAL
) {
7601 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entryPtr
->languageCode
, entryPtr
->userFraction
, (int)entryPtr
->status
);
7603 for (entryPtr
++; entryPtr
< entries
+ kUALanguageEntryMin
&& uprv_strcmp(entryPtr
->languageCode
, "ug_Arab") != 0; entryPtr
++)
7605 if (entryPtr
< entries
+ kUALanguageEntryMin
) {
7606 // we found ug_Arab, make sure it has correct status
7607 if (entryPtr
->status
!= UALANGSTATUS_REGIONAL_OFFICIAL
) {
7608 log_err("FAIL: ualoc_getLanguagesForRegion %s, ug_Arab had incorrect status %d\n", (int)entryPtr
->status
);
7611 // did not find ug_Arab
7612 log_err("FAIL: ualoc_getLanguagesForRegion %s, entries did not include ug_Arab\n", region
);
7617 status
= U_ZERO_ERROR
;
7619 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMin
, &status
);
7620 if (U_FAILURE(status
)) {
7621 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7623 // Expect approximately:
7624 // en 0.85 UALANGSTATUS_OFFICIAL
7625 // fr 0.22 UALANGSTATUS_OFFICIAL
7627 if (entryCount
< 2) {
7628 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7630 if (uprv_strcmp(entries
[0].languageCode
, "en") != 0 || entries
[0].userFraction
< 0.7 || entries
[0].userFraction
> 1.0 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
7631 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
7633 if (uprv_strcmp(entries
[1].languageCode
, "fr") != 0 || entries
[1].userFraction
< 0.1 || entries
[1].userFraction
> 1.0 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
7634 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
7639 status
= U_ZERO_ERROR
;
7641 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, NULL
, 0, &status
);
7642 if (U_FAILURE(status
)) {
7643 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7645 if (entryCount
< 40) {
7646 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7650 status
= U_ZERO_ERROR
;
7652 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMin
, &status
);
7653 if (U_FAILURE(status
)) {
7654 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7656 // Expect approximately:
7657 // fo 0.93 UALANGSTATUS_OFFICIAL
7658 // da 0.03 UALANGSTATUS_OFFICIAL
7660 if (entryCount
< 2) {
7661 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
7663 if (uprv_strcmp(entries
[0].languageCode
, "fo") != 0 || entries
[0].userFraction
< 0.90 || entries
[0].userFraction
> 0.98 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
7664 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
7666 if (uprv_strcmp(entries
[1].languageCode
, "da") != 0 || entries
[1].userFraction
< 0.02 || entries
[1].userFraction
> 0.04 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
7667 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
7672 status
= U_ZERO_ERROR
;
7674 entryCount
= ualoc_getLanguagesForRegion(region
, 0.0075, entries
, kUALanguageEntryMax
, &status
);
7675 if (U_FAILURE(status
)) {
7676 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
7678 // Expect about 15 entries, the last should be for ms_Arab with a fraction < 0.01 // <rdar://problem/27943264>
7679 if (entryCount
< 10) {
7680 log_err("FAIL: ualoc_getLanguagesForRegion %s with minFraction=0.0075, entryCount %d is too small\n", region
, entryCount
);
7682 if (uprv_strcmp(entries
[entryCount
-1].languageCode
, "ms_Arab") != 0 || entries
[entryCount
-1].userFraction
>= 0.01) {
7683 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[entryCount-1] { %s, %.3f, %d }\n",
7684 region
, entries
[entryCount
-1].languageCode
, entries
[entryCount
-1].userFraction
, (int)entries
[entryCount
-1].status
);
7691 #if U_PLATFORM_IS_DARWIN_BASED
7693 #include <mach/mach_time.h>
7694 #define GET_START() mach_absolute_time()
7695 #define GET_DURATION(start, info) ((mach_absolute_time() - start) * info.numer)/info.denom
7697 // Here we already know !U_PLATFORM_HAS_WIN32_API is true
7698 // So the following is for Linux
7700 #include "putilimp.h"
7701 #define GET_START() (uint64_t)uprv_getUTCtime()
7702 #define GET_DURATION(start, info) ((uint64_t)uprv_getUTCtime() - start)
7705 enum { kMaxLocsToUse
= 8 };
7706 static void TestAppleLocalizationsToUsePerf() { // <rdar://problem/62458844&63471438>
7707 static const char* preferredLangs
[] = {"zh_Hans","pt_BR","fr_BE"};
7708 static const char* availableLocs
[] = {"ar","de","en","en_AU","en_GB","es","es_419","fr","fr_CA","it","ja","ko","nl","no","pt","pt_PT","ru","zh_CN","zh_HK","zh_TW"};
7709 const char * locsToUse
[kMaxLocsToUse
];
7711 int32_t numLocsToUse
;
7712 uint64_t start
, duration
;
7713 #if U_PLATFORM_IS_DARWIN_BASED
7714 mach_timebase_info_data_t info
;
7715 mach_timebase_info(&info
);
7718 log_info("sleeping 10 sec to check heap before...\n");
7720 status
= U_ZERO_ERROR
;
7721 start
= GET_START();
7722 numLocsToUse
= ualoc_localizationsToUse(preferredLangs
, UPRV_LENGTHOF(preferredLangs
),
7723 availableLocs
, UPRV_LENGTHOF(availableLocs
),
7724 locsToUse
, kMaxLocsToUse
, &status
);
7725 duration
= GET_DURATION(start
, info
);
7726 log_info("ualoc_localizationsToUse first use nsec %llu; status %s, numLocsToUse %d: %s ...\n",
7727 duration
, u_errorName(status
), numLocsToUse
, (numLocsToUse
>=0)? locsToUse
[0]: "");
7728 log_info("sleeping 10 sec to check heap after...\n");
7731 status
= U_ZERO_ERROR
;
7732 start
= GET_START();
7733 numLocsToUse
= ualoc_localizationsToUse(preferredLangs
, UPRV_LENGTHOF(preferredLangs
),
7734 availableLocs
, UPRV_LENGTHOF(availableLocs
),
7735 locsToUse
, kMaxLocsToUse
, &status
);
7736 duration
= GET_DURATION(start
, info
);
7737 log_info("ualoc_localizationsToUse second use nsec %llu; status %s, numLocsToUse %d\n",
7738 duration
, u_errorName(status
), numLocsToUse
);
7741 /* data for TestAppleLocalizationsToUse */
7744 const char * const *locs
;
7746 } AppleLocsAndCount
;
7748 enum { kNumLocSets
= 6 };
7751 const char * language
;
7752 const char ** expLocsForSets
[kNumLocSets
];
7756 static const char * appleLocs1
[] = {
7790 static const char * appleLocs2
[] = {
7797 "en", "en_AU", "en_GB",
7821 "zh_CN", "zh_HK", "zh_TW",
7824 static const char * appleLocs3
[] = {
7831 "en", "en_AU", "en_CA", "en_GB",
7834 "fr", "fr_CA", "fr_FR",
7839 "it", "it_CH", // <rdar://problem/35829322>
7846 "pt", "pt_BR", "pt_PT",
7855 "zh_CN", "zh_HK", "zh_MO", "zh_TW",
7858 static const char * appleLocs4
[] = {
7859 "en", "en_AU", "en_CA", "en_GB", "en_IN", "en_US",
7860 "es", "es_419", "es_MX",
7861 "fr", "fr_CA", "fr_CH", "fr_FR",
7862 "it", "it_CH", "it_IT", // <rdar://problem/35829322>
7863 "nl", "nl_BE", "nl_NL",
7865 "ro", "ro_MD", "ro_RO",
7866 "zh_Hans", "zh_Hant", "zh_Hant_HK",
7869 static const char * appleLocs5
[] = {
7870 "en", "en_001", "en_AU", "en_GB",
7871 "es", "es_ES", "es_MX",
7872 "zh_CN", "zh_Hans", "zh_Hant", "zh_TW",
7882 static const char * appleLocs6
[] = {
7883 "en", "en_001", "en_150", "en_AU", "en_GB",
7884 "es", "es_419", "es_ES", "es_MX",
7885 "zh_CN", "zh_Hans", "zh_Hant", "zh_Hant_HK", "zh_HK", "zh_TW",
7892 static const AppleLocsAndCount locAndCountEntries
[kNumLocSets
] = {
7893 { appleLocs1
, UPRV_LENGTHOF(appleLocs1
) },
7894 { appleLocs2
, UPRV_LENGTHOF(appleLocs2
) },
7895 { appleLocs3
, UPRV_LENGTHOF(appleLocs3
) },
7896 { appleLocs4
, UPRV_LENGTHOF(appleLocs4
) },
7897 { appleLocs5
, UPRV_LENGTHOF(appleLocs5
) },
7898 { appleLocs6
, UPRV_LENGTHOF(appleLocs6
) },
7902 static const char* l1_ar
[] = { "ar", NULL
};
7903 static const char* l1_Ara
[] = { "Arabic", NULL
};
7904 static const char* l1_ca
[] = { "ca", NULL
};
7905 static const char* l1_cs
[] = { "cs", NULL
};
7906 static const char* l1_da
[] = { "da", NULL
};
7907 static const char* l1_Dan
[] = { "Danish", NULL
};
7908 static const char* l1_de
[] = { "de", NULL
};
7909 static const char* l1_Ger
[] = { "German", NULL
};
7910 static const char* l1_el
[] = { "el", NULL
};
7911 static const char* l1_en
[] = { "en", NULL
};
7912 static const char* l1_Eng
[] = { "English", NULL
};
7913 static const char* l2_en_001_
[] = { "en_001", "en", NULL
};
7914 static const char* l2_en_CA_
[] = { "en_CA", "en", NULL
};
7915 static const char* l2_en_GB_
[] = { "en_GB", "en", NULL
};
7916 static const char* l2_en_US_
[] = { "en_US", "en", NULL
};
7917 static const char* l2_en_GB_Eng
[] = { "en_GB", "English", NULL
};
7918 static const char* l3_en_GB001_
[] = { "en_GB", "en_001", "en", NULL
};
7919 static const char* l3_en_AUGB_
[] = { "en_AU", "en_GB", "en", NULL
};
7920 static const char* l3_en_INGB_
[] = { "en_IN", "en_GB", "en", NULL
};
7921 static const char* l4_en_150GB001_
[] = { "en_150", "en_GB", "en_001", "en", NULL
};
7922 static const char* l4_en_AUGB001_
[] = { "en_AU", "en_GB", "en_001", "en", NULL
};
7923 static const char* l1_es
[] = { "es", NULL
};
7924 static const char* l1_Spa
[] = { "Spanish", NULL
};
7925 static const char* l2_es_419_
[] = { "es_419", "es", NULL
};
7926 static const char* l2_es_ES_
[] = { "es_ES", "es", NULL
};
7927 static const char* l2_es_MX_
[] = { "es_MX", "es", NULL
};
7928 static const char* l2_es_MX_Spa
[] = { "es_MX", "Spanish", NULL
};
7929 static const char* l3_es_MX419_
[] = { "es_MX", "es_419", "es", NULL
};
7930 static const char* l1_fi
[] = { "fi", NULL
};
7931 static const char* l1_Fin
[] = { "Finnish", NULL
};
7932 static const char* l1_fil
[] = { "fil", NULL
};
7933 static const char* l1_tl
[] = { "tl", NULL
};
7934 static const char* l1_fr
[] = { "fr", NULL
};
7935 static const char* l1_Fre
[] = { "French", NULL
};
7936 static const char* l2_fr_CA_
[] = { "fr_CA", "fr", NULL
};
7937 static const char* l2_fr_CH_
[] = { "fr_CH", "fr", NULL
};
7938 static const char* l2_fr_FR_
[] = { "fr_FR", "fr", NULL
};
7939 static const char* l1_haw
[] = { "haw", NULL
};
7940 static const char* l1_he
[] = { "he", NULL
};
7941 static const char* l1_hr
[] = { "hr", NULL
};
7942 static const char* l1_hu
[] = { "hu", NULL
};
7943 static const char* l1_id
[] = { "id", NULL
};
7944 static const char* l1_in
[] = { "in", NULL
};
7945 static const char* l1_it
[] = { "it", NULL
};
7946 static const char* l2_it_CH
[] = { "it_CH", "it", NULL
}; // <rdar://problem/35829322>
7947 static const char* l2_it_IT
[] = { "it_IT", "it", NULL
}; // <rdar://problem/35829322>
7948 static const char* l1_Ita
[] = { "Italian", NULL
};
7949 static const char* l1_ja
[] = { "ja", NULL
};
7950 static const char* l1_Japn
[] = { "Japanese", NULL
};
7951 static const char* l1_ko
[] = { "ko", NULL
};
7952 static const char* l1_Kor
[] = { "Korean", NULL
};
7953 static const char* l1_ms
[] = { "ms", NULL
};
7954 static const char* l1_nb
[] = { "nb", NULL
};
7955 static const char* l1_no
[] = { "no", NULL
};
7956 static const char* l1_Nor
[] = { "Norwegian", NULL
};
7957 static const char* l2_no_NO_
[] = { "no_NO", "no", NULL
};
7958 static const char* l1_nl
[] = { "nl", NULL
};
7959 static const char* l1_Dut
[] = { "Dutch", NULL
};
7960 static const char* l2_nl_BE_
[] = { "nl_BE", "nl", NULL
};
7961 static const char* l1_pl
[] = { "pl", NULL
};
7962 static const char* l1_Pol
[] = { "Polish", NULL
};
7963 static const char* l1_pt
[] = { "pt", NULL
};
7964 static const char* l1_pt_PT
[] = { "pt_PT", NULL
};
7965 static const char* l1_Port
[] = { "Portuguese", NULL
};
7966 static const char* l2_pt_BR_
[] = { "pt_BR", "pt", NULL
};
7967 static const char* l2_pt_PT_
[] = { "pt_PT", "pt", NULL
};
7968 static const char* l1_ro
[] = { "ro", NULL
};
7969 static const char* l2_ro_MD_
[] = { "ro_MD", "ro", NULL
};
7970 static const char* l1_mo
[] = { "mo", NULL
};
7971 static const char* l1_ru
[] = { "ru", NULL
};
7972 static const char* l1_Rus
[] = { "Russian", NULL
};
7973 static const char* l1_sk
[] = { "sk", NULL
};
7974 static const char* l1_sr
[] = { "sr", NULL
};
7975 static const char* l1_srLatn
[] = { "sr-Latn", NULL
};
7976 static const char* l1_sv
[] = { "sv", NULL
};
7977 static const char* l1_Swe
[] = { "Swedish", NULL
};
7978 static const char* l1_th
[] = { "th", NULL
};
7979 static const char* l1_Thai
[] = { "Thai", NULL
};
7980 static const char* l1_tlh
[] = { "tlh", NULL
};
7981 static const char* l1_tr
[] = { "tr", NULL
};
7982 static const char* l1_Tur
[] = { "Turkish", NULL
};
7983 static const char* l1_uk
[] = { "uk", NULL
};
7984 static const char* l1_vi
[] = { "vi", NULL
};
7985 static const char* l1_yi
[] = { "yi", NULL
};
7986 static const char* l1_iw
[] = { "iw", NULL
};
7987 static const char* l1_zh_CN
[] = { "zh_CN", NULL
};
7988 static const char* l1_zh_TW
[] = { "zh_TW", NULL
};
7989 static const char* l1_zh_HK
[] = { "zh_HK", NULL
};
7990 static const char* l1_zh_Hans
[] = { "zh_Hans", NULL
};
7991 static const char* l1_zh_Hant
[] = { "zh_Hant", NULL
};
7992 static const char* l1_zhHant
[] = { "zh-Hant", NULL
};
7993 static const char* l2_zh_HKTW
[] = { "zh_HK", "zh_TW", NULL
};
7994 static const char* l2_zh_Hant_HK_
[] = { "zh_Hant_HK", "zh_Hant", NULL
};
7995 static const char* l2_zh_CN_Hans
[] = { "zh_CN", "zh_Hans", NULL
};
7996 static const char* l2_zh_TW_Hant
[] = { "zh_TW", "zh_Hant", NULL
};
7997 static const char* l2_zh_TW_Hant_
[] = { "zh_TW", "zh-Hant", NULL
};
7998 static const char* l3_zh_MOHKTW
[] = { "zh_MO", "zh_HK", "zh_TW", NULL
};
7999 static const char* l3_zh_HK_HantHK_Hant
[] = { "zh_HK", "zh_Hant_HK", "zh_Hant", NULL
};
8000 static const char* l3_zh_HKTW_Hant
[] = { "zh_Hant_HK", "zh_HK", "zh_TW", "zh_Hant", NULL
};
8001 static const char* l3_zh_HantHKHKTW_Hant
[] = { "zh_HK", "zh_Hant_HK", "zh_TW", "zh_Hant", NULL
};
8003 static const LangAndExpLocs appleLangAndLoc
[] = {
8004 // language\ result for appleLocs1 appleLocs2 appleLocs3 appleLocs4 appleLocs5 appleLocs6
8005 { "zh", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8006 { "zh-Hans", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8007 { "zh-Hant", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} },
8008 { "zh-Hans-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
8009 { "zh-Hans-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8010 { "zh-Hant-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
8011 { "zh-Hant-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HKTW_Hant
} },
8012 { "zh-Hant-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HKTW_Hant
} },
8013 { "zh-Hans-HK", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8014 { "zh-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
8015 { "zh-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8016 { "zh-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
8017 { "zh-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HantHKHKTW_Hant
} },
8018 { "zh-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HKTW_Hant
} },
8019 { "yue-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} }, // <rdar://problem/30671866> should 5/6 be zh_CN?
8020 { "yue-HK", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} }, // <rdar://problem/30671866> should 2/3 be zh_HK, 4/6 be zh_Hant_HK_ ?
8021 { "yue-Hans", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
8022 { "yue-Hant", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} },
8023 { "en", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8024 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
8025 { "en_US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
8026 { "en-CN", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8027 { "en-JP", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8028 { "en-TW", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8029 { "en-TR", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8030 { "en-001", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
8031 { "en-CA", { l1_Eng
, l1_en
, l2_en_CA_
, l2_en_CA_
, l2_en_001_
, l2_en_001_
} },
8032 { "en-IL", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
8033 { "en-GB", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8034 { "en-IN", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l3_en_INGB_
, l3_en_GB001_
, l3_en_GB001_
} },
8035 { "en-BD", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8036 { "en-LK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8037 { "en-GG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8038 { "en-HK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8039 { "en-IE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8040 { "en-JM", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8041 { "en-MO", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8042 { "en-MT", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8043 { "en-PK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8044 { "en-SG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8045 { "en-VG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8046 { "en-ZA", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
8047 { "en-AU", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
8048 { "en-NZ", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
8049 { "en-WS", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
8050 { "en-150", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
8051 { "en-FR", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
8052 { "en-BE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
8053 { "en-Latn", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8054 { "en-Latn-US", { l1_Eng
, l1_en
, l1_en
, l1_en
,/*TODO*/ l1_en
, l1_en
} },
8055 { "en-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
8056 { "en-Latn-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8057 { "en-u-ca-hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8058 { "en@calendar=hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8059 { "en-", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8060 { "en_", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
8061 { "es", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
8062 { "es-ES", { l1_Spa
, l1_es
, l1_es
, l1_es
, l2_es_ES_
, l2_es_ES_
} },
8063 { "es-419", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8064 { "es-MX", { l1_Spa
, l2_es_MX_
, l2_es_419_
, l3_es_MX419_
, l2_es_MX_
, l3_es_MX419_
} },
8065 { "es-AR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8066 { "es-BO", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} }, // <rdar://problem/34459988>
8067 { "es-BR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8068 { "es-BZ", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8069 { "es-AG", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8070 { "es-AW", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8071 { "es-CA", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8072 { "es-CW", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8073 { "es-SX", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8074 { "es-TT", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
8075 { "es-Latn", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
8076 { "es-Latn-MX", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
8077 { "pt", { l1_Port
, l1_pt
, l1_pt
, l1_pt
, NULL
, NULL
} },
8078 { "pt-BR", { l1_Port
, l1_pt
, l2_pt_BR_
, l2_pt_BR_
, NULL
, NULL
} },
8079 { "pt-PT", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8080 { "pt-MO", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8081 { "pt-CH", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8082 { "pt-FR", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8083 { "pt-GQ", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8084 { "pt-LU", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
8085 { "fr", { l1_Fre
, l1_fr
, l1_fr
, l1_fr
, NULL
, NULL
} },
8086 { "fr-FR", { l1_Fre
, l1_fr
, l2_fr_FR_
, l2_fr_FR_
, NULL
, NULL
} },
8087 { "fr-CA", { l1_Fre
, l2_fr_CA_
, l2_fr_CA_
, l2_fr_CA_
, NULL
, NULL
} },
8088 { "fr-CH", { l1_Fre
, l1_fr
, l1_fr
, l2_fr_CH_
, NULL
, NULL
} },
8089 { "ar", { l1_Ara
, l1_ar
, l1_ar
, NULL
, NULL
, NULL
} },
8090 { "da", { l1_Dan
, l1_da
, l1_da
, NULL
, NULL
, NULL
} },
8091 { "nl", { l1_Dut
, l1_nl
, l1_nl
, l1_nl
, NULL
, NULL
} },
8092 { "nl-BE", { l1_Dut
, l1_nl
, l1_nl
, l2_nl_BE_
, NULL
, NULL
} },
8093 { "fi", { l1_Fin
, l1_fi
, l1_fi
, NULL
, NULL
, NULL
} },
8094 { "de", { l1_Ger
, l1_de
, l1_de
, NULL
, NULL
, NULL
} },
8095 { "it", { l1_Ita
, l1_it
, l1_it
, l1_it
, NULL
, NULL
} },
8096 { "it_CH", { l1_Ita
, l1_it
, l2_it_CH
, l2_it_CH
, NULL
, NULL
} }, // <rdar://problem/35829322>
8097 { "it_IT", { l1_Ita
, l1_it
, l1_it
, l2_it_IT
, NULL
, NULL
} }, // <rdar://problem/35829322>
8098 { "it_VA", { l1_Ita
, l1_it
, l1_it
, l1_it
, NULL
, NULL
} }, // <rdar://problem/35829322>
8099 { "ja", { l1_Japn
, l1_ja
, l1_ja
, NULL
, NULL
, NULL
} },
8100 { "ko", { l1_Kor
, l1_ko
, l1_ko
, NULL
, NULL
, NULL
} },
8101 { "nb", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
8102 { "no", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
8103 { "pl", { l1_Pol
, l1_pl
, l1_pl
, NULL
, NULL
, NULL
} },
8104 { "ru", { l1_Rus
, l1_ru
, l1_ru
, NULL
, NULL
, NULL
} },
8105 { "sv", { l1_Swe
, l1_sv
, l1_sv
, NULL
, NULL
, NULL
} },
8106 { "th", { l1_Thai
, l1_th
, l1_th
, NULL
, NULL
, NULL
} },
8107 { "tr", { l1_Tur
, l1_tr
, l1_tr
, NULL
, NULL
, NULL
} },
8108 { "ca", { l1_ca
, l1_ca
, l1_ca
, NULL
, NULL
, NULL
} },
8109 { "cs", { l1_cs
, l1_cs
, l1_cs
, NULL
, NULL
, NULL
} },
8110 { "el", { l1_el
, l1_el
, l1_el
, NULL
, NULL
, NULL
} },
8111 { "he", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
8112 { "iw", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
8113 { "hr", { l1_hr
, l1_hr
, l1_hr
, NULL
, NULL
, NULL
} },
8114 { "hu", { l1_hu
, l1_hu
, l1_hu
, NULL
, NULL
, NULL
} },
8115 { "id", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
8116 { "in", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
8117 { "ms", { l1_ms
, l1_ms
, l1_ms
, NULL
, NULL
, NULL
} },
8118 { "ro", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, l1_mo
} },
8119 { "mo", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, l1_mo
} },
8120 { "sk", { l1_sk
, l1_sk
, l1_sk
, NULL
, NULL
, NULL
} },
8121 { "uk", { l1_uk
, l1_uk
, l1_uk
, NULL
, NULL
, NULL
} },
8122 { "vi", { l1_vi
, l1_vi
, l1_vi
, NULL
, NULL
, NULL
} },
8123 { "yi", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
8124 { "ji", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
8125 { "fil", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
8126 { "tl", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
8127 { "haw", { NULL
, NULL
, NULL
, NULL
, l1_haw
, NULL
} },
8128 { "sr", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
8129 { "sr-Cyrl", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
8130 { "sr-Latn", { NULL
, NULL
, NULL
, NULL
, l1_srLatn
, NULL
} },
8131 { "tlh", { NULL
, NULL
, NULL
, NULL
, l1_tlh
, NULL
} },
8132 { "Default@2x", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8133 { "default", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8134 { "root", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8135 { "", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8136 { "_US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8137 { "-US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8138 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8139 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8140 { "@calendar=hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
8142 enum { kNumAppleLangAndLoc
= UPRV_LENGTHOF(appleLangAndLoc
) };
8144 /* tests from <rdar://problem/21518031> */
8146 static const char * appleLocsA1
[] = { "en", "fr", "no", "zh-Hant" };
8147 static const char * appleLocsA2
[] = { "en", "fr", "nb", "zh_TW", "zh_CN", "zh-Hant" };
8148 static const char * appleLocsA3
[] = { "en", "en_IN", "en_GB", "fr", "de", "zh_TW" };
8149 static const char * appleLocsA4
[] = { "Spanish", "es_MX", "English", "en_GB" };
8150 static const char * appleLocsA5
[] = { "en", "fr", "de", "pt", "pt_PT" };
8151 static const char * appleLocsA6
[] = { "en", "no", "no_NO", "pt_PT" };
8153 static const AppleLocsAndCount locAndCountEntriesA
[kNumLocSets
] = {
8154 { appleLocsA1
, UPRV_LENGTHOF(appleLocsA1
) },
8155 { appleLocsA2
, UPRV_LENGTHOF(appleLocsA2
) },
8156 { appleLocsA3
, UPRV_LENGTHOF(appleLocsA3
) },
8157 { appleLocsA4
, UPRV_LENGTHOF(appleLocsA4
) },
8158 { appleLocsA5
, UPRV_LENGTHOF(appleLocsA5
) },
8159 { appleLocsA6
, UPRV_LENGTHOF(appleLocsA6
) },
8162 static const LangAndExpLocs appleLangAndLocA
[] = {
8163 // language\ result for appleLocsA1 appleLocsA2 appleLocsA3 appleLocsA4 appleLocsA5 appleLocsA6
8164 { "zh-Hant", { l1_zhHant
,/*0*/ l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
8165 { "zh_Hant", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
8166 { "zh_HK", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
8167 { "en_IN", { l1_en
, l1_en
, l3_en_INGB_
, l2_en_GB_Eng
, l1_en
, l1_en
} },
8168 { "es_MX", { NULL
, NULL
, NULL
, l2_es_MX_Spa
, NULL
, NULL
} },
8169 { "pt_PT", { NULL
, NULL
, NULL
, NULL
, l2_pt_PT_
, l1_pt_PT
} },
8170 { "pt", { NULL
, NULL
, NULL
, NULL
, l1_pt
, l1_pt_PT
} },
8171 { "no", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
8172 { "no_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
8173 { "nb", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
8174 { "nb_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
8176 enum { kNumAppleLangAndLocA
= UPRV_LENGTHOF(appleLangAndLocA
) };
8178 /* tests from log attached to 21682790 */
8180 static const char * appleLocsB1
[] = {
8181 "ar", "Base", "ca", "cs",
8182 "da", "Dutch", "el", "English",
8183 "es_MX", "fi", "French", "German",
8184 "he", "hr", "hu", "id",
8185 "Italian", "Japanese", "ko", "ms",
8186 "no", "pl", "pt", "pt_PT",
8187 "ro", "ru", "sk", "Spanish",
8188 "sv", "th", "tr", "uk",
8189 "vi", "zh_CN", "zh_TW"
8192 static const char * appleLocsB2
[] = {
8194 "da", "Dutch", "el", "English",
8195 "es_MX", "fi", "French", "German",
8196 "he", "hr", "hu", "id",
8197 "Italian", "Japanese", "ko", "ms",
8198 "no", "pl", "pt", "pt_PT",
8199 "ro", "ru", "sk", "Spanish",
8200 "sv", "th", "tr", "uk",
8201 "vi", "zh_CN", "zh_TW"
8204 static const char * appleLocsB3
[] = {
8205 "ar", "ca", "cs", "da",
8206 "de", "el", "en", "es",
8207 "es_MX", "fi", "French", "he",
8208 "hr", "hu", "id", "Italian",
8209 "ja", "ko", "ms", "nl",
8210 "no", "pl", "pt", "pt_PT",
8211 "ro", "ru", "sk", "sv",
8212 "th", "tr", "uk", "vi",
8216 static const char * appleLocsB4
[] = {
8217 "ar", "ca", "cs", "da",
8218 "de", "el", "en", "es",
8219 "es_MX", "fi", "fr", "he",
8220 "hr", "hu", "id", "it",
8221 "ja", "ko", "ms", "nl",
8222 "no", "pl", "pt", "pt_PT",
8223 "ro", "ru", "sk", "sv",
8224 "th", "tr", "uk", "vi",
8228 static const char * appleLocsB5
[] = { "en" };
8230 static const char * appleLocsB6
[] = { "English" };
8232 static const AppleLocsAndCount locAndCountEntriesB
[kNumLocSets
] = {
8233 { appleLocsB1
, UPRV_LENGTHOF(appleLocsB1
) },
8234 { appleLocsB2
, UPRV_LENGTHOF(appleLocsB2
) },
8235 { appleLocsB3
, UPRV_LENGTHOF(appleLocsB3
) },
8236 { appleLocsB4
, UPRV_LENGTHOF(appleLocsB4
) },
8237 { appleLocsB5
, UPRV_LENGTHOF(appleLocsB5
) },
8238 { appleLocsB6
, UPRV_LENGTHOF(appleLocsB6
) },
8241 static const LangAndExpLocs appleLangAndLocB
[] = {
8242 // language\ result for appleLocsB1 appleLocsB2 appleLocsB3 appleLocsB4 appleLocsB5 appleLocsB6
8243 // Prefs 1, logged with sets B1-B3
8244 { "en", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
8245 { "es", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
8246 // Prefs 2, logged with sets B1-B6
8247 { "English", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
8248 { "Spanish", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
8250 enum { kNumAppleLangAndLocB
= UPRV_LENGTHOF(appleLangAndLocB
) };
8253 const AppleLocsAndCount
* locAndCountEntriesPtr
;
8254 const LangAndExpLocs
* appleLangAndLocPtr
;
8255 int32_t appleLangAndLocCount
;
8256 } AppleLocToUseTestSet
;
8258 static const AppleLocToUseTestSet altuTestSets
[] = {
8259 { locAndCountEntries
, appleLangAndLoc
, kNumAppleLangAndLoc
},
8260 { locAndCountEntriesA
, appleLangAndLocA
, kNumAppleLangAndLocA
},
8261 { locAndCountEntriesB
, appleLangAndLocB
, kNumAppleLangAndLocB
},
8265 /* tests for multiple prefs sets */
8267 static const char * appleLocsM1
[] = { "en", "en_GB", "pt", "pt_PT", "zh_CN", "zh_Hant" };
8268 static const char * prefLangsM1
[] = { "tlh", "zh_HK", "zh_SG", "zh_Hans", "pt_BR", "pt_PT", "en_IN", "en" };
8269 static const char * locsToUseM1
[] = { "zh_Hant" };
8271 // Tests from first pass at <rdar://problem/22012864>, 2015-11-18
8273 static const char * appleLocsM2
[] = { "fr-FR", "en-US", "en-GB" };
8274 static const char * prefLangsM2
[] = { "fr-CH" };
8275 static const char * locsToUseM2
[] = { "fr-FR" };
8277 static const char * appleLocsM3
[] = { "es-es", "fr-fr" };
8278 static const char * prefLangsM3
[] = { "fr-US", "fr", "en-US" };
8279 static const char * locsToUseM3
[] = { "fr-fr" };
8281 static const char * appleLocsM4
[] = { "es-es", "fr-fr", "fr" };
8282 static const char * prefLangsM4
[] = { "fr-US", "fr", "en-US" };
8283 static const char * locsToUseM4
[] = { "fr" };
8285 // Tests from second pass at <rdar://problem/22012864>, 2015-12-08
8287 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" };
8288 static const char * prefLangsM5
[] = { "fr-US", "en-US" };
8289 static const char * locsToUseM5
[] = { "fr-FR" };
8290 // Per Peter E; expected result changed from "en-US" to "de-CH" per <rdar://problem/26559053>
8291 static const char * appleLocsM6
[] = { "de-CH", "en-US" };
8292 static const char * prefLangsM6
[] = { "de-DE", "en-US" };
8293 static const char * locsToUseM6
[] = { "de-CH" };
8294 // The following is used for M7-MD
8295 static const char * appleLocsMx
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-HK", "zh-TW" };
8297 static const char * prefLangsM7
[] = { "fr-ES", "en-AU" };
8298 static const char * locsToUseM7
[] = { "fr-FR" };
8300 static const char * prefLangsM8
[] = { "de-IT", "en-AU" };
8301 static const char * locsToUseM8
[] = { "de-DE" };
8303 static const char * prefLangsM9
[] = { "hi-US", "en-AU" };
8304 static const char * locsToUseM9
[] = { "hi-IN" };
8306 static const char * prefLangsMA
[] = { "en-IN", "zh-HK" };
8307 static const char * locsToUseMA
[] = { "en-AU" };
8309 static const char * prefLangsMB
[] = { "pt-PT", "en-AU" };
8310 static const char * locsToUseMB
[] = { "en-AU" };
8312 static const char * prefLangsMC
[] = { "pt-PT", "ar" };
8313 static const char * locsToUseMC
[] = { "pt-BR" };
8315 static const char * prefLangsMD
[] = { "zh-CN", "en-AU" };
8316 static const char * locsToUseMD
[] = { "en-AU" };
8318 static const char * appleLocsME
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-CN", "zh-HK" };
8319 static const char * prefLangsME
[] = { "zh-TW", "en-AU" };
8320 static const char * locsToUseME
[] = { "zh-HK" };
8321 // Per Peter E in diagnosis for <rdar://problem/22012864> and <rdar://problem/23815194>
8322 static const char * appleLocsMF
[] = { "en", "en-GB", "fr", "es" };
8323 static const char * prefLangsMF
[] = { "en-IN", "en-GB", "de", "fr" };
8324 static const char * locsToUseMF
[] = { "en-GB", "en" };
8325 // Per Karan M in <rdar://problem/23982460>
8326 static const char * appleLocsMG
[] = { "zh-Hans", "zh-Hant", "zh-HK" };
8327 static const char * prefLangsMG
[] = { "zh-Hans-US", "zh-HK", "en-US" };
8328 static const char * locsToUseMG
[] = { "zh-Hans" };
8329 // Per <rdar://problem/25903891>
8330 static const char * appleLocsMH
[] = { "zh-TW", "zh-CN", "zh-HK" };
8331 static const char * prefLangsMH
[] = { "zh-Hans-HK", "zh-HK", "en" };
8332 static const char * locsToUseMH
[] = { "zh-CN" };
8333 // Per <rdar://problem/26559053>
8334 static const char * appleLocsMI
[] = { "unk", "en-US", "ar-SA" };
8335 static const char * prefLangsMI
[] = { "ar-US" };
8336 static const char * locsToUseMI
[] = { "ar-SA" };
8337 // Per <rdar://problem/30501523> - first for comparison with zh, then real test
8338 static const char * appleLocsMJ
[] = { "zh-CN", "en-US" };
8339 static const char * prefLangsMJ
[] = { "zh", "zh_AC" };
8340 static const char * locsToUseMJ
[] = { "zh-CN" };
8341 static const char * appleLocsMK
[] = { "yue-CN", "en-US" };
8342 static const char * prefLangsMK
[] = { "yue", "yue_AC" };
8343 static const char * locsToUseMK
[] = { };
8344 // NOTE: Test MK was changed to expect "yue" NOT to match "yue-CN"-- the default script for "yue" is "Hant", and we don't
8345 // allow cross-script matching (we believe our original fix for rdar://30501523 was mistaken). Tests MK1a and MK1b are
8346 // added to make sure that "yue-CN" DOES still match "yue_CN" and "yue_Hans", even with the change for rdar://66938404.
8347 static const char * prefLangsMK1a
[] = { "yue", "yue_Hans" };
8348 static const char * prefLangsMK1b
[] = { "yue", "yue_CN" };
8349 static const char * locsToUseMK1
[] = { "yue-CN" };
8350 // Per <rdar://problem/30433534>
8351 static const char * appleLocsML
[] = { "nl_NL", "es_MX", "fr_FR", "zh_TW", "it_IT", "vi_VN", "fr_CH", "es_CL",
8352 "en_ZA", "ko_KR", "ca_ES", "ro_RO", "en_PH", "en_CA", "en_SG", "en_IN",
8353 "en_NZ", "it_CH", "fr_CA", "da_DK", "de_AT", "pt_BR", "yue_CN", "zh_CN",
8354 "sv_SE", "es_ES", "ar_SA", "hu_HU", "fr_BE", "en_GB", "ja_JP", "zh_HK",
8355 "fi_FI", "tr_TR", "nb_NO", "en_ID", "en_SA", "pl_PL", "ms_MY", "cs_CZ",
8356 "el_GR", "id_ID", "hr_HR", "en_AE", "he_IL", "ru_RU", "wuu_CN", "de_DE",
8357 "de_CH", "en_AU", "nl_BE", "th_TH", "pt_PT", "sk_SK", "en_US", "en_IE",
8358 "es_CO", "uk_UA", "es_US" };
8359 static const char * prefLangsML
[] = { "en-JP" };
8360 static const char * locsToUseML
[] = { "en_US" };
8361 // Per <rdar://problem/30671866>
8362 static const char * prefLangsML1
[] = { "yue-CN", "zh-CN" };
8363 static const char * locsToUseML1
[] = { "yue_CN" }; // should we also get "zh-CN" as a second option?
8364 static const char * prefLangsML2
[] = { "yue-Hans", "zh-Hans" };
8365 static const char * locsToUseML2
[] = { "yue_CN" }; // should we also get "zh-CN" as a second option?
8366 // Per <rdar://problem/32421203>
8367 static const char * appleLocsMM1
[] = { "pt-PT" };
8368 static const char * appleLocsMM2
[] = { "pt-BR" };
8369 static const char * appleLocsMM3
[] = { "pt-PT", "pt-BR" };
8370 static const char * appleLocsMM4
[] = { "en", "pt-PT" };
8371 static const char * appleLocsMM5
[] = { "en", "pt-BR" };
8372 static const char * appleLocsMM6
[] = { "en", "pt-PT", "pt-BR" };
8373 static const char * prefLangsMM1
[] = { "pt-PT" };
8374 static const char * prefLangsMM2
[] = { "pt-BR" };
8375 static const char * prefLangsMM3
[] = { "pt" };
8376 static const char * prefLangsMM4
[] = { "pt-PT", "en" };
8377 static const char * prefLangsMM5
[] = { "pt-BR", "en" };
8378 static const char * prefLangsMM6
[] = { "pt", "en" };
8379 static const char * locsToUseMMptPT
[] = { "pt-PT" };
8380 static const char * locsToUseMMptBR
[] = { "pt-BR" };
8381 static const char * locsToUseMMen
[] = { "en" };
8382 // Per <rdar://problem/32658828>
8383 static const char * appleLocsMN
[] = { "en-US", "en-GB" };
8384 static const char * prefLangsMN1
[] = { "en-KR" };
8385 static const char * prefLangsMN2
[] = { "en-SA" };
8386 static const char * prefLangsMN3
[] = { "en-TW" };
8387 static const char * prefLangsMN4
[] = { "en-JP" };
8388 static const char * locsToUseMN_U
[] = { "en-US" };
8389 // Per <rdar://problem/36010857>
8390 static const char * appleLocsMO
[] = { "Dutch", "French", "German", "Italian", "Japanese", "Spanish",
8391 "ar", "ca", "cs", "da", "el", "en_AU", "en_GB", "en_IN",
8392 "es_419", "fi", "fr_CA", "he", "hi", "hr", "hu", "id", "ko",
8393 "ms", "no", "pl", "pt", "pt_PT", "ro", "ru", "sk", "sv",
8394 "th", "tr", "uk", "vi", "zh_CN", "zh_HK", "zh_TW" };
8395 static const char * prefLangsMO1
[] = { "en-US" };
8396 static const char * locsToUseMO1
[] = { "en_GB" };
8397 // Per <rdar://problem/47494729>
8398 static const char * appleLocsMP
[] = { "en-IN", "hi-IN" };
8399 static const char * prefLangsMP
[] = { "hi-Latn-IN", "en-IN" };
8400 static const char * locsToUseMP
[] = { "en-IN" };
8401 // Per <rdar://problem/34459988&35829322>
8402 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" };
8403 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" };
8404 static const char * prefLangsMQ1
[] = { "es-BO" };
8405 static const char * locsToUseMQ1
[] = { "es_MX" };
8406 static const char * prefLangsMQ2
[] = { "it-VA" };
8407 static const char * locsToUseMQ2a
[] = { "it_IT" };
8408 static const char * locsToUseMQ2b
[] = { "it" };
8409 // Per <rdar://problem/50913699>
8410 static const char * appleLocsMRa
[] = { "en", "hi" };
8411 static const char * appleLocsMRb
[] = { "en", "hi", "hi_Latn" };
8412 static const char * prefLangsMRx
[] = { "hi_Latn_IN", "en_IN", "hi_IN" };
8413 static const char * prefLangsMRy
[] = { "hi_Latn", "en", "hi" };
8414 static const char * locsToUseMRa
[] = { "en" };
8415 static const char * locsToUseMRb
[] = { "hi_Latn", "en" };
8416 // For <rdar://problem/50280505>
8417 static const char * appleLocsMSa
[] = { "en", "en_GB" };
8418 static const char * appleLocsMSb
[] = { "en", "en_GB", "en_AU" };
8419 static const char * prefLangsMSx
[] = { "en_NZ" };
8420 static const char * prefLangsMSy
[] = { "en_NZ", "en_AU" };
8421 static const char * locsToUseMSa
[] = { "en_GB", "en" };
8422 static const char * locsToUseMSb
[] = { "en_AU", "en_GB", "en" };
8423 // For <rdar://problem/55885283>
8424 static const char * appleLocsMT
[] = { "ca-ES", "fi", "nl", "en-US", "hu", "pt-BR", "pl-PL", "it",
8425 "ru", "el", "el-GR", "ca", "de-DE", "sv-SE", "tr", "pl",
8426 "sv", "tr-TR", "da", "en", "nb", "pt-PT", "nb-NO",
8427 "es-ES@collation=traditional", "sl-SI", "cs", "hu-HU",
8428 "cs-CZ", "sk", "sl", "de", "da-DK", "es-MX", "vi", "nl-NL",
8429 "es", "fi-FI", "fr", "it-IT", "es-ES", "fr-CA", "vi-VN",
8430 "pt", "sk-SK", "eu-ES", "ru-RU", "eu", "fr-FR", "unk" };
8431 static const char * prefLangsMTa
[] = { "en" };
8432 static const char * prefLangsMTb
[] = { "he" };
8433 static const char * locsToUseMTa
[] = { "en" };
8434 static const char * locsToUseMTb
[] = { };
8435 // For rdar://64350332
8436 static const char * appleLocsMU
[] = { "hi", "en-IN" };
8437 static const char * prefLangsMU
[] = { "en-US" };
8438 static const char * locsToUseMU
[] = { "en-IN" };
8439 // For rdar://59520369
8440 static const char * appleLocsMVa
[] = { "zh", "zh-Hans", "zh-Hant" };
8441 static const char * appleLocsMVb
[] = { "zh-Hans", "zh", "zh-Hant" };
8442 static const char * prefLangsMVa
[] = { "zh-Hans-US" };
8443 static const char * prefLangsMVc
[] = { "zh-Hans" };
8444 static const char * locsToUseMV
[] = { "zh-Hans", "zh" };
8445 // comment in Developer Forums, not made into a Radar
8446 static const char * appleLocsMW
[] = { "fr-CA", "pt-BR", "es-MX", "en-US", "en" };
8447 static const char * prefLangsMW
[] = { "es-ES" };
8448 static const char * locsToUseMW
[] = { "es-MX" };
8449 // For rdar://64811575
8450 static const char * appleLocsMX
[] = { "en", "fr", "de", "zh_CN", "zh_TW", "zh-Hant"};
8451 static const char * prefLangsMX
[] = { "zh_HK" };
8452 static const char * locsToUseMX
[] = { "zh-Hant" };
8453 // For rdar://59520369
8454 static const char * appleLocsMYa
[] = { "en", "ars", "ar" };
8455 static const char * appleLocsMYb
[] = { "en", "ar" };
8456 static const char * appleLocsMYc
[] = { "en", "ars" };
8457 static const char * prefLangsMYa
[] = { "ars_SA" };
8458 static const char * prefLangsMYb
[] = { "ar_SA" };
8459 static const char * locsToUseMYa
[] = { "ars", "ar" };
8460 static const char * locsToUseMYb
[] = { "ars" };
8461 static const char * locsToUseMYc
[] = { "ar" };
8462 // For rdar://59520369
8463 static const char * appleLocsMZa
[] = { "en", "wuu-Hans", "zh-Hans" };
8464 static const char * appleLocsMZb
[] = { "en", "zh-Hans" };
8465 static const char * appleLocsMZc
[] = { "en", "wuu-Hans" };
8466 static const char * prefLangsMZa
[] = { "wuu_CN" };
8467 static const char * prefLangsMZb
[] = { "zh_CN" };
8468 static const char * locsToUseMZa
[] = { "wuu-Hans", "zh-Hans" };
8469 static const char * locsToUseMZb
[] = { "wuu-Hans" };
8470 static const char * locsToUseMZc
[] = { "zh-Hans" };
8471 // For rdar://64916132
8472 static const char * appleLocsMAA
[] = { "fr-CH", "ja-JP", "fr-CA" };
8473 static const char * prefLangsMAA
[] = { "fr-FR", "ja-JP", "fr-CA" };
8474 static const char * locsToUseMAA
[] = { "fr-CA" };
8475 // For rdar://65843542
8476 static const char * appleLocsMAB
[] = { "en", "yue", "yue-Hans", "zh-CN", "zh-HK" };
8477 static const char * prefLangsMAB
[] = { "zh-Hans-US" };
8478 static const char * locsToUseMAB
[] = { "zh-CN" };
8479 // For rdar://66729600
8480 static const char * appleLocsMAC
[] = { "en", "en-AU", "en-GB"};
8481 static const char * prefLangsMAC
[] = { "en-US", "en-GB" };
8482 static const char * locsToUseMAC
[] = { "en" };
8483 static const char * appleLocsMAD
[] = { "en", "zh-CN", "en-AU" };
8484 static const char * prefLangsMAD
[] = { "en-CN", "zh-CN", "en-AU" };
8485 static const char * locsToUseMAD
[] = { "en" };
8486 // For rdar://66403688
8487 static const char * appleLocsMAE
[] = { "unk", "zh-Hant", "yue" };
8488 static const char * prefLangsMAE
[] = { "zh-Hans" };
8489 static const char * locsToUseMAE
[] = { };
8490 // For rdar://68146613
8491 static const char * appleLocsMAF
[] = { "zxx", "en_HK", "en_MO" };
8492 static const char * prefLangsMAF
[] = { "th_TH" };
8493 static const char * locsToUseMAF
[] = { "zxx" };
8494 // For rdar://69272236
8495 static const char * appleLocsMAG
[] = { "en_US", "en_GB" };
8496 static const char * prefLangsMAG
[] = { "en_BN" };
8497 static const char * locsToUseMAG
[] = { "en_GB" };
8502 const char ** availLocs
;
8503 int32_t availLocsCount
;
8504 const char ** prefLangs
;
8505 int32_t prefLangsCount
;
8506 const char ** locsToUse
;
8507 int32_t locsToUseCount
;
8510 static const MultiPrefTest multiTestSets
[] = {
8511 { "M1", appleLocsM1
, UPRV_LENGTHOF(appleLocsM1
), prefLangsM1
, UPRV_LENGTHOF(prefLangsM1
), locsToUseM1
, UPRV_LENGTHOF(locsToUseM1
) },
8513 { "M2", appleLocsM2
, UPRV_LENGTHOF(appleLocsM2
), prefLangsM2
, UPRV_LENGTHOF(prefLangsM2
), locsToUseM2
, UPRV_LENGTHOF(locsToUseM2
) },
8514 { "M3", appleLocsM3
, UPRV_LENGTHOF(appleLocsM3
), prefLangsM3
, UPRV_LENGTHOF(prefLangsM3
), locsToUseM3
, UPRV_LENGTHOF(locsToUseM3
) },
8515 { "M4", appleLocsM4
, UPRV_LENGTHOF(appleLocsM4
), prefLangsM4
, UPRV_LENGTHOF(prefLangsM4
), locsToUseM4
, UPRV_LENGTHOF(locsToUseM4
) },
8517 { "M5", appleLocsM5
, UPRV_LENGTHOF(appleLocsM5
), prefLangsM5
, UPRV_LENGTHOF(prefLangsM5
), locsToUseM5
, UPRV_LENGTHOF(locsToUseM5
) },
8518 { "M6", appleLocsM6
, UPRV_LENGTHOF(appleLocsM6
), prefLangsM6
, UPRV_LENGTHOF(prefLangsM6
), locsToUseM6
, UPRV_LENGTHOF(locsToUseM6
) },
8519 { "M7", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM7
, UPRV_LENGTHOF(prefLangsM7
), locsToUseM7
, UPRV_LENGTHOF(locsToUseM7
) },
8520 { "M8", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM8
, UPRV_LENGTHOF(prefLangsM8
), locsToUseM8
, UPRV_LENGTHOF(locsToUseM8
) },
8521 { "M9", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM9
, UPRV_LENGTHOF(prefLangsM9
), locsToUseM9
, UPRV_LENGTHOF(locsToUseM9
) },
8522 { "MA", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMA
, UPRV_LENGTHOF(prefLangsMA
), locsToUseMA
, UPRV_LENGTHOF(locsToUseMA
) },
8523 { "MB", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMB
, UPRV_LENGTHOF(prefLangsMB
), locsToUseMB
, UPRV_LENGTHOF(locsToUseMB
) },
8524 { "MC", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMC
, UPRV_LENGTHOF(prefLangsMC
), locsToUseMC
, UPRV_LENGTHOF(locsToUseMC
) },
8525 { "MD", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMD
, UPRV_LENGTHOF(prefLangsMD
), locsToUseMD
, UPRV_LENGTHOF(locsToUseMD
) },
8526 { "ME", appleLocsME
, UPRV_LENGTHOF(appleLocsME
), prefLangsME
, UPRV_LENGTHOF(prefLangsME
), locsToUseME
, UPRV_LENGTHOF(locsToUseME
) },
8527 { "MF", appleLocsMF
, UPRV_LENGTHOF(appleLocsMF
), prefLangsMF
, UPRV_LENGTHOF(prefLangsMF
), locsToUseMF
, UPRV_LENGTHOF(locsToUseMF
) },
8528 { "MG", appleLocsMG
, UPRV_LENGTHOF(appleLocsMG
), prefLangsMG
, UPRV_LENGTHOF(prefLangsMG
), locsToUseMG
, UPRV_LENGTHOF(locsToUseMG
) },
8529 { "MH", appleLocsMH
, UPRV_LENGTHOF(appleLocsMH
), prefLangsMH
, UPRV_LENGTHOF(prefLangsMH
), locsToUseMH
, UPRV_LENGTHOF(locsToUseMH
) },
8530 { "MI", appleLocsMI
, UPRV_LENGTHOF(appleLocsMI
), prefLangsMI
, UPRV_LENGTHOF(prefLangsMI
), locsToUseMI
, UPRV_LENGTHOF(locsToUseMI
) },
8531 { "MJ", appleLocsMJ
, UPRV_LENGTHOF(appleLocsMJ
), prefLangsMJ
, UPRV_LENGTHOF(prefLangsMJ
), locsToUseMJ
, UPRV_LENGTHOF(locsToUseMJ
) },
8532 { "MK", appleLocsMK
, UPRV_LENGTHOF(appleLocsMK
), prefLangsMK
, UPRV_LENGTHOF(prefLangsMK
), locsToUseMK
, UPRV_LENGTHOF(locsToUseMK
) },
8533 { "MK1a", appleLocsMK
, UPRV_LENGTHOF(appleLocsMK
), prefLangsMK1a
, UPRV_LENGTHOF(prefLangsMK1a
), locsToUseMK1
, UPRV_LENGTHOF(locsToUseMK1
) },
8534 { "MK1b", appleLocsMK
, UPRV_LENGTHOF(appleLocsMK
), prefLangsMK1b
, UPRV_LENGTHOF(prefLangsMK1b
), locsToUseMK1
, UPRV_LENGTHOF(locsToUseMK1
) },
8535 { "ML", appleLocsML
, UPRV_LENGTHOF(appleLocsML
), prefLangsML
, UPRV_LENGTHOF(prefLangsML
), locsToUseML
, UPRV_LENGTHOF(locsToUseML
) },
8536 { "ML1", appleLocsML
, UPRV_LENGTHOF(appleLocsML
), prefLangsML1
, UPRV_LENGTHOF(prefLangsML1
), locsToUseML1
, UPRV_LENGTHOF(locsToUseML1
) },
8537 { "ML2", appleLocsML
, UPRV_LENGTHOF(appleLocsML
), prefLangsML2
, UPRV_LENGTHOF(prefLangsML2
), locsToUseML2
, UPRV_LENGTHOF(locsToUseML2
) },
8538 { "MM11", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8539 { "MM21", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8540 { "MM31", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8541 { "MM41", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8542 { "MM51", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8543 { "MM61", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM1
, UPRV_LENGTHOF(prefLangsMM1
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8544 { "MM12", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8545 { "MM22", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8546 { "MM32", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8547 { "MM42", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8548 { "MM52", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8549 { "MM62", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM2
, UPRV_LENGTHOF(prefLangsMM2
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8550 { "MM13", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8551 { "MM23", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8552 { "MM33", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8553 { "MM43", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8554 { "MM53", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8555 { "MM63", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM3
, UPRV_LENGTHOF(prefLangsMM3
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8556 { "MM14", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8557 { "MM24", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8558 { "MM34", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8559 { "MM44", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8560 { "MM54", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMen
, UPRV_LENGTHOF(locsToUseMMen
) }, // want en, see <rdar://problem/22012864>
8561 { "MM64", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM4
, UPRV_LENGTHOF(prefLangsMM4
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8562 { "MM15", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8563 { "MM25", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8564 { "MM35", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8565 { "MM45", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8566 { "MM55", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8567 { "MM65", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM5
, UPRV_LENGTHOF(prefLangsMM5
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8568 { "MM16", appleLocsMM1
, UPRV_LENGTHOF(appleLocsMM1
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8569 { "MM26", appleLocsMM2
, UPRV_LENGTHOF(appleLocsMM2
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8570 { "MM36", appleLocsMM3
, UPRV_LENGTHOF(appleLocsMM3
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8571 { "MM46", appleLocsMM4
, UPRV_LENGTHOF(appleLocsMM4
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptPT
, UPRV_LENGTHOF(locsToUseMMptPT
) },
8572 { "MM56", appleLocsMM5
, UPRV_LENGTHOF(appleLocsMM5
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8573 { "MM66", appleLocsMM6
, UPRV_LENGTHOF(appleLocsMM6
), prefLangsMM6
, UPRV_LENGTHOF(prefLangsMM6
), locsToUseMMptBR
, UPRV_LENGTHOF(locsToUseMMptBR
) },
8574 { "MN1", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN1
, UPRV_LENGTHOF(prefLangsMN1
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8575 { "MN2", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN2
, UPRV_LENGTHOF(prefLangsMN2
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8576 { "MN3", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN3
, UPRV_LENGTHOF(prefLangsMN3
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8577 { "MN4", appleLocsMN
, UPRV_LENGTHOF(appleLocsMN
), prefLangsMN4
, UPRV_LENGTHOF(prefLangsMN4
), locsToUseMN_U
, UPRV_LENGTHOF(locsToUseMN_U
) },
8578 { "MO", appleLocsMO
, UPRV_LENGTHOF(appleLocsMO
), prefLangsMO1
, UPRV_LENGTHOF(prefLangsMO1
), locsToUseMO1
, UPRV_LENGTHOF(locsToUseMO1
) },
8579 { "MP", appleLocsMP
, UPRV_LENGTHOF(appleLocsMP
), prefLangsMP
, UPRV_LENGTHOF(prefLangsMP
), locsToUseMP
, UPRV_LENGTHOF(locsToUseMP
) },
8580 { "MQ1a", appleLocsMQa
, UPRV_LENGTHOF(appleLocsMQa
), prefLangsMQ1
, UPRV_LENGTHOF(prefLangsMQ1
), locsToUseMQ1
, UPRV_LENGTHOF(locsToUseMQ1
) },
8581 // { "MQ1b", appleLocsMQb, UPRV_LENGTHOF(appleLocsMQb), prefLangsMQ1, UPRV_LENGTHOF(prefLangsMQ1), locsToUseMQ1, UPRV_LENGTHOF(locsToUseMQ1) }, // still to do for <rdar://problem/34459988>
8582 { "MQ2a", appleLocsMQa
, UPRV_LENGTHOF(appleLocsMQa
), prefLangsMQ2
, UPRV_LENGTHOF(prefLangsMQ2
), locsToUseMQ2a
, UPRV_LENGTHOF(locsToUseMQ2a
) },
8583 { "MQ2b", appleLocsMQb
, UPRV_LENGTHOF(appleLocsMQb
), prefLangsMQ2
, UPRV_LENGTHOF(prefLangsMQ2
), locsToUseMQ2b
, UPRV_LENGTHOF(locsToUseMQ2b
) },
8584 { "MRa", appleLocsMRa
, UPRV_LENGTHOF(appleLocsMRa
), prefLangsMRx
, UPRV_LENGTHOF(prefLangsMRx
), locsToUseMRa
, UPRV_LENGTHOF(locsToUseMRa
) },
8585 { "MRb", appleLocsMRb
, UPRV_LENGTHOF(appleLocsMRb
), prefLangsMRx
, UPRV_LENGTHOF(prefLangsMRx
), locsToUseMRb
, UPRV_LENGTHOF(locsToUseMRb
) },
8586 { "MRa", appleLocsMRa
, UPRV_LENGTHOF(appleLocsMRa
), prefLangsMRy
, UPRV_LENGTHOF(prefLangsMRy
), locsToUseMRa
, UPRV_LENGTHOF(locsToUseMRa
) },
8587 { "MRb", appleLocsMRb
, UPRV_LENGTHOF(appleLocsMRb
), prefLangsMRy
, UPRV_LENGTHOF(prefLangsMRy
), locsToUseMRb
, UPRV_LENGTHOF(locsToUseMRb
) },
8588 { "MSax", appleLocsMSa
, UPRV_LENGTHOF(appleLocsMSa
), prefLangsMSx
, UPRV_LENGTHOF(prefLangsMSx
), locsToUseMSa
, UPRV_LENGTHOF(locsToUseMSa
) },
8589 { "MSay", appleLocsMSa
, UPRV_LENGTHOF(appleLocsMSa
), prefLangsMSy
, UPRV_LENGTHOF(prefLangsMSy
), locsToUseMSa
, UPRV_LENGTHOF(locsToUseMSa
) },
8590 { "MSbx", appleLocsMSb
, UPRV_LENGTHOF(appleLocsMSb
), prefLangsMSx
, UPRV_LENGTHOF(prefLangsMSx
), locsToUseMSb
, UPRV_LENGTHOF(locsToUseMSb
) },
8591 { "MSby", appleLocsMSb
, UPRV_LENGTHOF(appleLocsMSb
), prefLangsMSy
, UPRV_LENGTHOF(prefLangsMSy
), locsToUseMSb
, UPRV_LENGTHOF(locsToUseMSb
) },
8592 { "MTa", appleLocsMT
, UPRV_LENGTHOF(appleLocsMT
), prefLangsMTa
, UPRV_LENGTHOF(prefLangsMTa
), locsToUseMTa
, UPRV_LENGTHOF(locsToUseMTa
) },
8593 { "MTb", appleLocsMT
, UPRV_LENGTHOF(appleLocsMT
), prefLangsMTb
, UPRV_LENGTHOF(prefLangsMTb
), locsToUseMTb
, UPRV_LENGTHOF(locsToUseMTb
) },
8594 { "MU", appleLocsMU
, UPRV_LENGTHOF(appleLocsMU
), prefLangsMU
, UPRV_LENGTHOF(prefLangsMU
), locsToUseMU
, UPRV_LENGTHOF(locsToUseMU
) }, // rdar://64350332
8595 { "MVa", appleLocsMVa
, UPRV_LENGTHOF(appleLocsMVa
), prefLangsMVa
, UPRV_LENGTHOF(prefLangsMVa
), locsToUseMV
, UPRV_LENGTHOF(locsToUseMV
) }, // rdar://59520369
8596 { "MVb", appleLocsMVb
, UPRV_LENGTHOF(appleLocsMVb
), prefLangsMVa
, UPRV_LENGTHOF(prefLangsMVa
), locsToUseMV
, UPRV_LENGTHOF(locsToUseMV
) }, // rdar://59520369
8597 { "MVc", appleLocsMVa
, UPRV_LENGTHOF(appleLocsMVa
), prefLangsMVc
, UPRV_LENGTHOF(prefLangsMVc
), locsToUseMV
, UPRV_LENGTHOF(locsToUseMV
) }, // rdar://59520369
8598 { "MW", appleLocsMW
, UPRV_LENGTHOF(appleLocsMW
), prefLangsMW
, UPRV_LENGTHOF(prefLangsMW
), locsToUseMW
, UPRV_LENGTHOF(locsToUseMW
) }, // rdar://59520369
8599 { "MX", appleLocsMX
, UPRV_LENGTHOF(appleLocsMX
), prefLangsMX
, UPRV_LENGTHOF(prefLangsMX
), locsToUseMX
, UPRV_LENGTHOF(locsToUseMW
) }, // rdar://64811575
8600 { "MYaa", appleLocsMYa
, UPRV_LENGTHOF(appleLocsMYa
), prefLangsMYa
, UPRV_LENGTHOF(prefLangsMYa
), locsToUseMYa
, UPRV_LENGTHOF(locsToUseMYa
) }, // rdar://64497611
8601 { "MYba", appleLocsMYb
, UPRV_LENGTHOF(appleLocsMYb
), prefLangsMYa
, UPRV_LENGTHOF(prefLangsMYa
), locsToUseMYc
, UPRV_LENGTHOF(locsToUseMYc
) }, // rdar://64497611
8602 { "MYca", appleLocsMYc
, UPRV_LENGTHOF(appleLocsMYc
), prefLangsMYa
, UPRV_LENGTHOF(prefLangsMYa
), locsToUseMYb
, UPRV_LENGTHOF(locsToUseMYb
) }, // rdar://64497611
8603 { "MYab", appleLocsMYa
, UPRV_LENGTHOF(appleLocsMYa
), prefLangsMYb
, UPRV_LENGTHOF(prefLangsMYb
), locsToUseMYc
, UPRV_LENGTHOF(locsToUseMYc
) }, // rdar://64497611
8604 { "MYbb", appleLocsMYb
, UPRV_LENGTHOF(appleLocsMYb
), prefLangsMYb
, UPRV_LENGTHOF(prefLangsMYb
), locsToUseMYc
, UPRV_LENGTHOF(locsToUseMYc
) }, // rdar://64497611
8605 { "MYcb", appleLocsMYc
, UPRV_LENGTHOF(appleLocsMYc
), prefLangsMYb
, UPRV_LENGTHOF(prefLangsMYb
), locsToUseMYb
, UPRV_LENGTHOF(locsToUseMYb
) }, // rdar://64497611
8606 { "MZaa", appleLocsMZa
, UPRV_LENGTHOF(appleLocsMZa
), prefLangsMZa
, UPRV_LENGTHOF(prefLangsMZa
), locsToUseMZa
, UPRV_LENGTHOF(locsToUseMZa
) }, // rdar://64497611
8607 { "MZba", appleLocsMZb
, UPRV_LENGTHOF(appleLocsMZb
), prefLangsMZa
, UPRV_LENGTHOF(prefLangsMZa
), locsToUseMZc
, UPRV_LENGTHOF(locsToUseMZc
) }, // rdar://64497611
8608 { "MZca", appleLocsMZc
, UPRV_LENGTHOF(appleLocsMZc
), prefLangsMZa
, UPRV_LENGTHOF(prefLangsMZa
), locsToUseMZb
, UPRV_LENGTHOF(locsToUseMZb
) }, // rdar://64497611
8609 { "MZab", appleLocsMZa
, UPRV_LENGTHOF(appleLocsMZa
), prefLangsMZb
, UPRV_LENGTHOF(prefLangsMZb
), locsToUseMZc
, UPRV_LENGTHOF(locsToUseMZc
) }, // rdar://64497611
8610 { "MZbb", appleLocsMZb
, UPRV_LENGTHOF(appleLocsMZb
), prefLangsMZb
, UPRV_LENGTHOF(prefLangsMZb
), locsToUseMZc
, UPRV_LENGTHOF(locsToUseMZc
) }, // rdar://64497611
8611 { "MZcb", appleLocsMZc
, UPRV_LENGTHOF(appleLocsMZc
), prefLangsMZb
, UPRV_LENGTHOF(prefLangsMZb
), locsToUseMZb
, UPRV_LENGTHOF(locsToUseMZb
) }, // rdar://64497611
8612 { "MAA", appleLocsMAA
, UPRV_LENGTHOF(appleLocsMAA
), prefLangsMAA
, UPRV_LENGTHOF(prefLangsMAA
), locsToUseMAA
, UPRV_LENGTHOF(locsToUseMAA
) }, // rdar://64916132
8613 { "MAB", appleLocsMAB
, UPRV_LENGTHOF(appleLocsMAB
), prefLangsMAB
, UPRV_LENGTHOF(prefLangsMAB
), locsToUseMAB
, UPRV_LENGTHOF(locsToUseMAB
) }, // rdar://65843542
8614 { "MAC", appleLocsMAC
, UPRV_LENGTHOF(appleLocsMAC
), prefLangsMAC
, UPRV_LENGTHOF(prefLangsMAC
), locsToUseMAC
, UPRV_LENGTHOF(locsToUseMAC
) }, // rdar://66729600
8615 { "MAD", appleLocsMAD
, UPRV_LENGTHOF(appleLocsMAD
), prefLangsMAD
, UPRV_LENGTHOF(prefLangsMAD
), locsToUseMAD
, UPRV_LENGTHOF(locsToUseMAD
) }, // rdar://66729600
8616 { "MAE", appleLocsMAE
, UPRV_LENGTHOF(appleLocsMAE
), prefLangsMAE
, UPRV_LENGTHOF(prefLangsMAE
), locsToUseMAE
, UPRV_LENGTHOF(locsToUseMAE
) }, // rdar://66403688
8617 { "MAF", appleLocsMAF
, UPRV_LENGTHOF(appleLocsMAF
), prefLangsMAF
, UPRV_LENGTHOF(prefLangsMAF
), locsToUseMAF
, UPRV_LENGTHOF(locsToUseMAF
) }, // rdar://68146613
8618 { "MAG", appleLocsMAG
, UPRV_LENGTHOF(appleLocsMAG
), prefLangsMAG
, UPRV_LENGTHOF(prefLangsMAG
), locsToUseMAG
, UPRV_LENGTHOF(locsToUseMAG
) }, // rdar://69272236
8620 { NULL
, NULL
, 0, NULL
, 0, NULL
, 0 }
8626 enum { kMaxLocalizationsToUse
= 8, kPrintArrayBufSize
= 128 };
8628 // array, array of pointers to strings to print
8629 // count, count of array elements, may be -1 if array is terminated by a NULL entry
8630 // buf, buffer into which to put concatenated strings
8631 // bufSize, length of buf
8632 static void printStringArray(const char **array
, int32_t count
, char *buf
, int32_t bufSize
) {
8633 char * bufPtr
= buf
;
8634 const char * curEntry
;
8635 int32_t idx
, countMax
= bufSize
/16;
8636 if (count
< 0 || count
> countMax
) {
8639 for (idx
= 0; idx
< count
&& (curEntry
= *array
++) != NULL
; idx
++) {
8640 int32_t len
= sprintf(bufPtr
, "%s\"%.12s\"", (idx
> 0)? ", ": "", curEntry
);
8646 *bufPtr
= 0; /* ensure termination */
8649 static UBool
equalStringArrays(const char **array1
, int32_t count1
, const char **array2
, int32_t count2
) {
8650 const char ** array1Ptr
= array1
;
8651 const char ** array2Ptr
= array2
;
8655 while (*array1Ptr
++ != NULL
) {
8661 while (*array2Ptr
++ != NULL
) {
8665 if (count1
!= count2
) {
8668 for (idx
= 0; idx
< count1
; idx
++) {
8669 if (uprv_strcmp(array1
[idx
], array2
[idx
]) != 0) {
8676 static void TestAppleLocalizationsToUse() {
8677 const AppleLocToUseTestSet
* testSetPtr
;
8678 const MultiPrefTest
* multiSetPtr
;
8679 const char * locsToUse
[kMaxLocalizationsToUse
];
8680 int32_t numLocsToUse
;
8682 char printExpected
[kPrintArrayBufSize
];
8683 char printActual
[kPrintArrayBufSize
];
8685 for (testSetPtr
= altuTestSets
; testSetPtr
->locAndCountEntriesPtr
!= NULL
; testSetPtr
++) {
8686 int32_t iLocSet
, iLang
;
8688 for (iLocSet
= 0; iLocSet
< kNumLocSets
; iLocSet
++) {
8689 for (iLang
= 0; iLang
< testSetPtr
->appleLangAndLocCount
; iLang
++) {
8690 const char * language
= testSetPtr
->appleLangAndLocPtr
[iLang
].language
;
8691 const char ** expLocsForSet
= testSetPtr
->appleLangAndLocPtr
[iLang
].expLocsForSets
[iLocSet
];
8692 status
= U_ZERO_ERROR
;
8694 numLocsToUse
= ualoc_localizationsToUse(&language
, 1,
8695 testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locs
, testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locCount
,
8696 locsToUse
, kMaxLocalizationsToUse
, &status
);
8697 if (U_FAILURE(status
)) {
8698 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, status %s\n",
8699 testSetPtr
-altuTestSets
, iLocSet
+1, language
, u_errorName(status
));
8700 } else if (numLocsToUse
== 0 && expLocsForSet
!= NULL
) {
8701 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
8702 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect {%s}, get no results\n",
8703 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
);
8704 } else if (numLocsToUse
> 0 && expLocsForSet
== NULL
) {
8705 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8706 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect no results, get {%s}\n",
8707 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printActual
);
8708 } else if (numLocsToUse
> 0 && !equalStringArrays(expLocsForSet
, -1, locsToUse
, numLocsToUse
)) {
8709 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
8710 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8711 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s:\n expect {%s}\n get {%s}\n",
8712 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
, printActual
);
8718 for (multiSetPtr
= multiTestSets
; multiSetPtr
->name
!= NULL
; multiSetPtr
++) {
8719 status
= U_ZERO_ERROR
;
8720 numLocsToUse
= ualoc_localizationsToUse(multiSetPtr
->prefLangs
, multiSetPtr
->prefLangsCount
, multiSetPtr
->availLocs
, multiSetPtr
->availLocsCount
, locsToUse
, kMaxLocalizationsToUse
, &status
);
8721 if (U_FAILURE(status
)) {
8722 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s, status %s\n", multiSetPtr
->name
, multiSetPtr
->name
, u_errorName(status
));
8723 } else if (!equalStringArrays(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, locsToUse
, numLocsToUse
)) {
8724 printStringArray(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, printExpected
, kPrintArrayBufSize
);
8725 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
8726 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s:\n expect {%s}\n get {%s}\n",
8727 multiSetPtr
->name
, multiSetPtr
->name
, printExpected
, printActual
);
8734 // rdar://problem/63313283
8735 static void TestNorwegianDisplayNames(void) {
8736 UChar bokmalInBokmal
[50];
8737 UChar bokmalInNynorsk
[50];
8738 UChar nynorskInBokmal
[50];
8739 UChar nynorskInNynorsk
[50];
8740 UErrorCode err
= U_ZERO_ERROR
;
8742 uloc_getDisplayLanguage("nb", "nb", bokmalInBokmal
, 50, &err
);
8743 uloc_getDisplayLanguage("nb", "nn", bokmalInNynorsk
, 50, &err
);
8744 uloc_getDisplayLanguage("nn", "nb", nynorskInBokmal
, 50, &err
);
8745 uloc_getDisplayLanguage("nn", "nn", nynorskInNynorsk
, 50, &err
);
8747 if (assertSuccess("Error getting display names", &err
)) {
8748 assertUEquals("Bokmal and Nynorsk don't have the same names for Bokmal", bokmalInBokmal
, bokmalInNynorsk
);
8749 assertUEquals("Bokmal and Nynorsk don't have the same names for Nynorsk", nynorskInBokmal
, nynorskInNynorsk
);
8754 static void TestSpecificDisplayNames(void) {
8756 // first column is language whose name we want, second column is language to display it in, third column is expected result
8757 static const char* testLanguages
[] = {
8758 "wuu", "sv", "shanghainesiska"
8760 int32_t numTests
= UPRV_LENGTHOF(testLanguages
) / 3;
8762 for (int32_t i
= 0; i
< numTests
; i
+= 3) {
8763 UErrorCode err
= U_ZERO_ERROR
;
8764 UChar displayName
[200];
8765 char displayNameUTF8
[200];
8766 uloc_getDisplayLanguage(testLanguages
[i
], testLanguages
[i
+ 1], displayName
, 200, &err
);
8768 if (assertSuccess("Error getting display language", &err
)) {
8769 u_strToUTF8(displayNameUTF8
, 200, NULL
, displayName
, -1, &err
);
8770 if (assertSuccess("Error translating display name to UTF-8", &err
)) {
8771 assertEquals("Display name mismatch", testLanguages
[i
+ 2], displayNameUTF8
);