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