1 /********************************************************************
3 * Copyright (c) 1997-2016, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
10 * Modification History:
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
26 #include "unicode/putil.h"
27 #include "unicode/ubrk.h"
28 #include "unicode/uchar.h"
29 #include "unicode/ucol.h"
30 #include "unicode/udat.h"
31 #include "unicode/uloc.h"
32 #include "unicode/umsg.h"
33 #include "unicode/ures.h"
34 #include "unicode/uset.h"
35 #include "unicode/ustring.h"
36 #include "unicode/utypes.h"
37 #include "unicode/ulocdata.h"
38 #include "unicode/uldnames.h"
39 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
41 #include "unicode/ualoc.h" /* Apple-specific */
43 static void TestNullDefault(void);
44 static void TestNonexistentLanguageExemplars(void);
45 static void TestLocDataErrorCodeChaining(void);
46 static void TestLocDataWithRgTag(void);
47 static void TestLanguageExemplarsFallbacks(void);
48 static void TestDisplayNameBrackets(void);
50 static void TestUnicodeDefines(void);
52 static void TestIsRightToLeft(void);
53 static void TestUldnNameVariants(void);
55 static void TestGetLanguagesForRegion(void);
56 static void TestGetAppleParent(void);
57 static void TestAppleLocalizationsToUse(void);
59 void PrintDataTable();
61 /*---------------------------------------------------
63 --------------------------------------------------- */
65 #define LOCALE_INFO_SIZE 28
67 static const char* const rawData2
[LOCALE_INFO_SIZE
][LOCALE_SIZE
] = {
69 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
71 { "", "", "", "", "", "", "", "", "" },
73 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
75 { "", "", "", "", "NY", "", "", "", "" },
77 { "en_US", "fr_FR", "ca_ES",
78 "el_GR", "no_NO_NY", "zh_Hans_CN",
79 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
81 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
83 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
85 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
87 /* display language (English) */
88 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
89 /* display script code (English) */
90 { "", "", "", "", "", "Simplified Han", "", "", "" },
91 /* display country (English) */
92 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
93 /* display variant (English) */
94 { "", "", "", "", "NY", "", "", "", "" },
95 /* display name (English) */
96 { "English (United States)", "French (France)", "Catalan (Spain)",
97 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
98 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
100 /* display language (French) */
101 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
102 /* display script code (French) */
103 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
104 /* display country (French) */
105 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
106 /* display variant (French) */
107 { "", "", "", "", "NY", "", "", "", "" },
108 /* display name (French) */
109 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
110 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)",
111 "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
113 /* display language (Catalan) */
114 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
115 /* display script code (Catalan) */
116 { "", "", "", "", "", "han simplificat", "", "", "" },
117 /* display country (Catalan) */
118 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
119 /* display variant (Catalan) */
120 { "", "", "", "", "NY", "", "", "", "" },
121 /* display name (Catalan) */
122 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
123 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
124 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
126 /* display language (Greek) */
128 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
129 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
130 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
131 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
132 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
133 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
134 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
135 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
136 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
138 /* display script code (Greek) */
140 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
141 /* display country (Greek) */
143 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
144 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
145 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
146 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
147 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
148 "\\u039A\\u03AF\\u03BD\\u03B1",
149 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
151 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
153 /* display variant (Greek) */
154 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
155 /* display name (Greek) */
157 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
158 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
159 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
160 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
161 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
162 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
163 "\\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)",
164 "\\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)",
165 "\\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)"
169 static UChar
*** dataTable
=0;
209 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
211 void addLocaleTest(TestNode
** root
);
213 void addLocaleTest(TestNode
** root
)
215 TESTCASE(TestObsoleteNames
); /* srl- move */
216 TESTCASE(TestBasicGetters
);
217 TESTCASE(TestNullDefault
);
218 TESTCASE(TestPrefixes
);
219 TESTCASE(TestSimpleResourceInfo
);
220 TESTCASE(TestDisplayNames
);
221 TESTCASE(TestGetAvailableLocales
);
222 TESTCASE(TestDataDirectory
);
223 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
224 TESTCASE(TestISOFunctions
);
226 TESTCASE(TestISO3Fallback
);
227 TESTCASE(TestUninstalledISO3Names
);
228 TESTCASE(TestSimpleDisplayNames
);
229 TESTCASE(TestVariantParsing
);
230 TESTCASE(TestKeywordVariants
);
231 TESTCASE(TestKeywordVariantParsing
);
232 TESTCASE(TestCanonicalization
);
233 TESTCASE(TestKeywordSet
);
234 TESTCASE(TestKeywordSetError
);
235 TESTCASE(TestDisplayKeywords
);
236 TESTCASE(TestDisplayKeywordValues
);
237 TESTCASE(TestGetBaseName
);
238 #if !UCONFIG_NO_FILE_IO
239 TESTCASE(TestGetLocale
);
241 TESTCASE(TestDisplayNameWarning
);
242 TESTCASE(TestNonexistentLanguageExemplars
);
243 TESTCASE(TestLocDataErrorCodeChaining
);
244 TESTCASE(TestLocDataWithRgTag
);
245 TESTCASE(TestLanguageExemplarsFallbacks
);
246 TESTCASE(TestCalendar
);
247 TESTCASE(TestDateFormat
);
248 TESTCASE(TestCollation
);
249 TESTCASE(TestULocale
);
250 TESTCASE(TestUResourceBundle
);
251 TESTCASE(TestDisplayName
);
252 TESTCASE(TestAcceptLanguage
);
253 TESTCASE(TestGetLocaleForLCID
);
254 TESTCASE(TestOrientation
);
255 TESTCASE(TestLikelySubtags
);
256 TESTCASE(TestToLanguageTag
);
257 TESTCASE(TestForLanguageTag
);
258 TESTCASE(TestTrailingNull
);
259 TESTCASE(TestUnicodeDefines
);
260 TESTCASE(TestEnglishExemplarCharacters
);
261 TESTCASE(TestDisplayNameBrackets
);
262 TESTCASE(TestIsRightToLeft
);
263 TESTCASE(TestToUnicodeLocaleKey
);
264 TESTCASE(TestToLegacyKey
);
265 TESTCASE(TestToUnicodeLocaleType
);
266 TESTCASE(TestToLegacyType
);
267 TESTCASE(TestUldnNameVariants
);
268 TESTCASE(TestGetLanguagesForRegion
);
269 TESTCASE(TestGetAppleParent
);
270 TESTCASE(TestAppleLocalizationsToUse
);
274 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
275 static void TestBasicGetters() {
278 UErrorCode status
= U_ZERO_ERROR
;
279 char *testLocale
= 0;
280 char *temp
= 0, *name
= 0;
281 log_verbose("Testing Basic Getters\n");
282 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
283 testLocale
=(char*)malloc(sizeof(char) * (strlen(rawData2
[NAME
][i
])+1));
284 strcpy(testLocale
,rawData2
[NAME
][i
]);
286 log_verbose("Testing %s .....\n", testLocale
);
287 cap
=uloc_getLanguage(testLocale
, NULL
, 0, &status
);
288 if(status
==U_BUFFER_OVERFLOW_ERROR
){
290 temp
=(char*)malloc(sizeof(char) * (cap
+1));
291 uloc_getLanguage(testLocale
, temp
, cap
+1, &status
);
293 if(U_FAILURE(status
)){
294 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status
));
296 if (0 !=strcmp(temp
,rawData2
[LANG
][i
])) {
297 log_err(" Language code mismatch: %s versus %s\n", temp
, rawData2
[LANG
][i
]);
301 cap
=uloc_getCountry(testLocale
, temp
, cap
, &status
);
302 if(status
==U_BUFFER_OVERFLOW_ERROR
){
304 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
305 uloc_getCountry(testLocale
, temp
, cap
+1, &status
);
307 if(U_FAILURE(status
)){
308 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status
));
310 if (0 != strcmp(temp
, rawData2
[CTRY
][i
])) {
311 log_err(" Country code mismatch: %s versus %s\n", temp
, rawData2
[CTRY
][i
]);
315 cap
=uloc_getVariant(testLocale
, temp
, cap
, &status
);
316 if(status
==U_BUFFER_OVERFLOW_ERROR
){
318 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
319 uloc_getVariant(testLocale
, temp
, cap
+1, &status
);
321 if(U_FAILURE(status
)){
322 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status
));
324 if (0 != strcmp(temp
, rawData2
[VAR
][i
])) {
325 log_err("Variant code mismatch: %s versus %s\n", temp
, rawData2
[VAR
][i
]);
328 cap
=uloc_getName(testLocale
, NULL
, 0, &status
);
329 if(status
==U_BUFFER_OVERFLOW_ERROR
){
331 name
=(char*)malloc(sizeof(char) * (cap
+1));
332 uloc_getName(testLocale
, name
, cap
+1, &status
);
333 } else if(status
==U_ZERO_ERROR
) {
334 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale
);
336 if(U_FAILURE(status
)){
337 log_err("ERROR: in uloc_getName %s\n", myErrorName(status
));
339 if (0 != strcmp(name
, rawData2
[NAME
][i
])){
340 log_err(" Mismatch in getName: %s versus %s\n", name
, rawData2
[NAME
][i
]);
350 static void TestNullDefault() {
351 UErrorCode status
= U_ZERO_ERROR
;
352 char original
[ULOC_FULLNAME_CAPACITY
];
354 uprv_strcpy(original
, uloc_getDefault());
355 uloc_setDefault("qq_BLA", &status
);
356 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
357 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
359 uloc_setDefault(NULL
, &status
);
360 if (uprv_strcmp(uloc_getDefault(), original
) != 0) {
361 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
365 /* Test that set & get of default locale work, and that
366 * default locales are cached and reused, and not overwritten.
370 const char *n2_en_US
;
372 status
= U_ZERO_ERROR
;
373 uloc_setDefault("en_US", &status
);
374 n_en_US
= uloc_getDefault();
375 if (strcmp(n_en_US
, "en_US") != 0) {
376 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
379 uloc_setDefault("fr_FR", &status
);
380 n_fr_FR
= uloc_getDefault();
381 if (strcmp(n_en_US
, "en_US") != 0) {
382 log_err("uloc_setDefault altered previously default string."
383 "Expected \"en_US\", got \"%s\"\n", n_en_US
);
385 if (strcmp(n_fr_FR
, "fr_FR") != 0) {
386 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR
);
389 uloc_setDefault("en_US", &status
);
390 n2_en_US
= uloc_getDefault();
391 if (strcmp(n2_en_US
, "en_US") != 0) {
392 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
394 if (n2_en_US
!= n_en_US
) {
395 log_err("Default locale cache failed to reuse en_US locale.\n");
398 if (U_FAILURE(status
)) {
399 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status
));
405 /* Test the i- and x- and @ and . functionality
408 #define PREFIXBUFSIZ 128
410 static void TestPrefixes() {
413 const char *loc
, *expected
;
415 static const char * const testData
[][7] =
417 /* NULL canonicalize() column means "expect same as getName()" */
418 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL
},
419 {"en", "", "GB", "", "en-gb", "en_GB", NULL
},
420 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL
},
421 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL
},
422 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL
},
423 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL
},
425 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans@collation=pinyin"},
426 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", NULL
},
428 {"de", "", "", "1901", "de-1901", "de__1901", NULL
},
429 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
430 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
431 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
432 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
433 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
434 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
435 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
436 {"no", "", "", "NY", "no__ny", "no__NY", NULL
},
437 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
438 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL
},
439 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL
},
440 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
441 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL
},
442 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL
},
443 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL
}, /* total garbage */
445 {NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
}
448 static const char * const testTitles
[] = {
449 "uloc_getLanguage()",
455 "uloc_canonicalize()"
458 char buf
[PREFIXBUFSIZ
];
463 for(row
=0;testData
[row
][0] != NULL
;row
++) {
464 loc
= testData
[row
][NAME
];
465 log_verbose("Test #%d: %s\n", row
, loc
);
470 for(n
=0;n
<=(NAME
+2);n
++) {
471 if(n
==NAME
) continue;
473 for(len
=0;len
<PREFIXBUFSIZ
;len
++) {
474 buf
[len
] = '%'; /* Set a tripwire.. */
480 len
= uloc_getLanguage(loc
, buf
, PREFIXBUFSIZ
, &err
);
484 len
= uloc_getScript(loc
, buf
, PREFIXBUFSIZ
, &err
);
488 len
= uloc_getCountry(loc
, buf
, PREFIXBUFSIZ
, &err
);
492 len
= uloc_getVariant(loc
, buf
, PREFIXBUFSIZ
, &err
);
496 len
= uloc_getName(loc
, buf
, PREFIXBUFSIZ
, &err
);
500 len
= uloc_canonicalize(loc
, buf
, PREFIXBUFSIZ
, &err
);
509 log_err("#%d: %s on %s: err %s\n",
510 row
, testTitles
[n
], loc
, u_errorName(err
));
512 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
513 row
, testTitles
[n
], loc
, buf
, len
);
515 if(len
!= (int32_t)strlen(buf
)) {
516 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
517 row
, testTitles
[n
], loc
, buf
, len
, strlen(buf
)+1);
521 /* see if they smashed something */
522 if(buf
[len
+1] != '%') {
523 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
524 row
, testTitles
[n
], loc
, buf
, buf
[len
+1]);
527 expected
= testData
[row
][n
];
528 if (expected
== NULL
&& n
== (NAME
+2)) {
529 /* NULL expected canonicalize() means "expect same as getName()" */
530 expected
= testData
[row
][NAME
+1];
532 if(strcmp(buf
, expected
)) {
533 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
534 row
, testTitles
[n
], loc
, buf
, expected
);
543 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
544 static void TestSimpleResourceInfo() {
546 char* testLocale
= 0;
551 testLocale
=(char*)malloc(sizeof(char) * 1);
552 expected
=(UChar
*)malloc(sizeof(UChar
) * 1);
555 log_verbose("Testing getISO3Language and getISO3Country\n");
556 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
558 testLocale
=(char*)realloc(testLocale
, sizeof(char) * (u_strlen(dataTable
[NAME
][i
])+1));
559 u_austrcpy(testLocale
, dataTable
[NAME
][i
]);
561 log_verbose("Testing %s ......\n", testLocale
);
563 temp
=uloc_getISO3Language(testLocale
);
564 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
565 u_uastrcpy(expected
,temp
);
566 if (0 != u_strcmp(expected
, dataTable
[LANG3
][i
])) {
567 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected
),
568 austrdup(dataTable
[LANG3
][i
]));
571 temp
=uloc_getISO3Country(testLocale
);
572 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
573 u_uastrcpy(expected
,temp
);
574 if (0 != u_strcmp(expected
, dataTable
[CTRY3
][i
])) {
575 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected
),
576 austrdup(dataTable
[CTRY3
][i
]));
578 sprintf(temp2
, "%x", (int)uloc_getLCID(testLocale
));
579 if (strcmp(temp2
, rawData2
[LCID
][i
]) != 0) {
580 log_err("LCID mismatch: %s versus %s\n", temp2
, rawData2
[LCID
][i
]);
589 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
590 * if there's room but won't be included in result. result < 0 indicates an error.
591 * Returns the number of chars written (not those that would be written if there's enough room.*/
592 static int32_t UCharsToEscapedAscii(const UChar
* utext
, int32_t len
, char* resultChars
, int32_t buflen
) {
593 static const struct {
606 static const int32_t ESCAPE_MAP_LENGTH
= UPRV_LENGTHOF(ESCAPE_MAP
);
607 static const char HEX_DIGITS
[] = {
608 '0', '1', '2', '3', '4', '5', '6', '7',
609 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
612 int32_t resultLen
= 0;
613 const int32_t limit
= len
<0 ? buflen
: len
; /* buflen is long enough to hit the buffer limit */
614 const int32_t escapeLimit1
= buflen
-2;
615 const int32_t escapeLimit2
= buflen
-6;
618 if(utext
==NULL
|| resultChars
==NULL
|| buflen
<0) {
622 for(i
=0;i
<limit
&& resultLen
<buflen
;++i
) {
628 for(j
=0;j
<ESCAPE_MAP_LENGTH
&& uc
!=ESCAPE_MAP
[j
].sourceVal
;j
++) {
630 if(j
<ESCAPE_MAP_LENGTH
) {
631 if(resultLen
>escapeLimit1
) {
634 resultChars
[resultLen
++]='\\';
635 resultChars
[resultLen
++]=ESCAPE_MAP
[j
].escapedChar
;
639 u_austrncpy(resultChars
+ resultLen
, &uc
, 1);
644 if(resultLen
>escapeLimit2
) {
648 /* have to escape the uchar */
649 resultChars
[resultLen
++]='\\';
650 resultChars
[resultLen
++]='u';
651 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>12)&0xff];
652 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>8)&0xff];
653 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>4)&0xff];
654 resultChars
[resultLen
++]=HEX_DIGITS
[uc
&0xff];
657 if(resultLen
<buflen
) {
658 resultChars
[resultLen
] = 0;
665 * Jitterbug 2439 -- markus 20030425
667 * The lookup of display names must not fall back through the default
668 * locale because that yields useless results.
670 static void TestDisplayNames()
673 UErrorCode errorCode
=U_ZERO_ERROR
;
675 log_verbose("Testing getDisplayName for different locales\n");
677 log_verbose(" In locale = en_US...\n");
678 doTestDisplayNames("en_US", DLANG_EN
);
679 log_verbose(" In locale = fr_FR....\n");
680 doTestDisplayNames("fr_FR", DLANG_FR
);
681 log_verbose(" In locale = ca_ES...\n");
682 doTestDisplayNames("ca_ES", DLANG_CA
);
683 log_verbose(" In locale = gr_EL..\n");
684 doTestDisplayNames("el_GR", DLANG_EL
);
686 /* test that the default locale has a display name for its own language */
687 errorCode
=U_ZERO_ERROR
;
688 length
=uloc_getDisplayLanguage(NULL
, NULL
, buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
689 if(U_FAILURE(errorCode
) || (length
<=3 && buffer
[0]<=0x7f)) {
690 /* check <=3 to reject getting the language code as a display name */
691 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
));
694 /* test that we get the language code itself for an unknown language, and a default warning */
695 errorCode
=U_ZERO_ERROR
;
696 length
=uloc_getDisplayLanguage("qq", "rr", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
697 if(errorCode
!=U_USING_DEFAULT_WARNING
|| length
!=2 || buffer
[0]!=0x71 || buffer
[1]!=0x71) {
698 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode
));
701 /* test that we get a default warning for a display name where one component is unknown (4255) */
702 errorCode
=U_ZERO_ERROR
;
703 length
=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
704 if(errorCode
!=U_USING_DEFAULT_WARNING
) {
705 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode
));
710 static const char *aLocale
= "es@collation=traditional;calendar=japanese";
711 static const char *testL
[] = { "en_US",
715 static const char *expect
[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
716 "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)",
717 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
718 "\\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)" };
721 for(i
=0;i
<UPRV_LENGTHOF(testL
);i
++) {
722 errorCode
= U_ZERO_ERROR
;
723 uloc_getDisplayName(aLocale
, testL
[i
], buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
724 if(U_FAILURE(errorCode
)) {
725 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale
, testL
[i
], u_errorName(errorCode
));
727 expectBuffer
= CharsToUChars(expect
[i
]);
728 if(u_strcmp(buffer
,expectBuffer
)) {
729 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
));
731 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale
, testL
[i
], expect
[i
]);
738 /* test that we properly preflight and return data when there's a non-default pattern,
742 static const char *locale
="az_Cyrl";
743 static const char *displayLocale
="ja";
744 static const char *expectedChars
=
745 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e "
746 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
747 UErrorCode ec
=U_ZERO_ERROR
;
750 int32_t preflightLen
=uloc_getDisplayName(locale
, displayLocale
, NULL
, 0, &ec
);
751 /* inconvenient semantics when preflighting, this condition is expected... */
752 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
755 len
=uloc_getDisplayName(locale
, displayLocale
, result
, UPRV_LENGTHOF(result
), &ec
);
757 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
758 locale
, displayLocale
, u_errorName(ec
));
760 UChar
*expected
=CharsToUChars(expectedChars
);
761 int32_t expectedLen
=u_strlen(expected
);
763 if(len
!=expectedLen
) {
764 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
765 locale
, displayLocale
, len
, expectedLen
);
766 } else if(preflightLen
!=expectedLen
) {
767 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
768 locale
, displayLocale
, preflightLen
, expectedLen
);
769 } else if(u_strncmp(result
, expected
, len
)) {
770 int32_t cap
=len
*6+1; /* worst case + space for trailing null */
771 char* resultChars
=(char*)malloc(cap
);
772 int32_t resultCharsLen
=UCharsToEscapedAscii(result
, len
, resultChars
, cap
);
773 if(resultCharsLen
<0 || resultCharsLen
<cap
-1) {
774 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale
, displayLocale
);
776 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
777 locale
, displayLocale
, resultChars
, expectedChars
);
782 /* test all buffer sizes */
783 for(i
=len
+1;i
>=0;--i
) {
784 len
=uloc_getDisplayName(locale
, displayLocale
, result
, i
, &ec
);
785 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
789 log_err("using buffer of length %d returned error %s", i
, u_errorName(ec
));
792 if(len
!=expectedLen
) {
793 log_err("with buffer of length %d, expected length %d but got %d", i
, expectedLen
, len
);
796 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
797 * we don't know that it's been filled, so no point in checking. */
807 /* test for uloc_getAvialable() and uloc_countAvilable()*/
808 static void TestGetAvailableLocales()
814 log_verbose("Testing the no of avialable locales\n");
815 locCount
=uloc_countAvailable();
817 log_data_err("countAvailable() returned an empty list!\n");
819 /* use something sensible w/o hardcoding the count */
820 else if(locCount
< 0){
821 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount
);
824 log_info("Number of locales returned = %d\n", locCount
);
826 for(i
=0;i
<locCount
;i
++){
827 locList
=uloc_getAvailable(i
);
829 log_verbose(" %s\n", locList
);
833 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
834 static void TestDataDirectory()
837 char oldDirectory
[512];
838 const char *temp
,*testValue1
,*testValue2
,*testValue3
;
839 const char path
[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING
; /*give the required path */
841 log_verbose("Testing getDataDirectory()\n");
842 temp
= u_getDataDirectory();
843 strcpy(oldDirectory
, temp
);
845 testValue1
=uloc_getISO3Language("en_US");
846 log_verbose("first fetch of language retrieved %s\n", testValue1
);
848 if (0 != strcmp(testValue1
,"eng")){
849 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1
);
852 /*defining the path for DataDirectory */
853 log_verbose("Testing setDataDirectory\n");
854 u_setDataDirectory( path
);
855 if(strcmp(path
, u_getDataDirectory())==0)
856 log_verbose("setDataDirectory working fine\n");
858 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path
);
860 testValue2
=uloc_getISO3Language("en_US");
861 log_verbose("second fetch of language retrieved %s \n", testValue2
);
863 u_setDataDirectory(oldDirectory
);
864 testValue3
=uloc_getISO3Language("en_US");
865 log_verbose("third fetch of language retrieved %s \n", testValue3
);
867 if (0 != strcmp(testValue3
,"eng")) {
868 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3
);
874 /*=========================================================== */
878 static void doTestDisplayNames(const char* displayLocale
, int32_t compareIndex
)
880 UErrorCode status
= U_ZERO_ERROR
;
882 int32_t maxresultsize
;
884 const char *testLocale
;
888 UChar
*testScript
= 0;
894 UChar
* expectedLang
= 0;
895 UChar
* expectedScript
= 0;
896 UChar
* expectedCtry
= 0;
897 UChar
* expectedVar
= 0;
898 UChar
* expectedName
= 0;
902 for(i
=0;i
<LOCALE_SIZE
; ++i
)
904 testLocale
=rawData2
[NAME
][i
];
906 log_verbose("Testing..... %s\n", testLocale
);
909 maxresultsize
=uloc_getDisplayLanguage(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
910 if(status
==U_BUFFER_OVERFLOW_ERROR
)
913 testLang
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
914 uloc_getDisplayLanguage(testLocale
, displayLocale
, testLang
, maxresultsize
+ 1, &status
);
920 if(U_FAILURE(status
)){
921 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status
));
925 maxresultsize
=uloc_getDisplayScript(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
926 if(status
==U_BUFFER_OVERFLOW_ERROR
)
929 testScript
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
930 uloc_getDisplayScript(testLocale
, displayLocale
, testScript
, maxresultsize
+ 1, &status
);
936 if(U_FAILURE(status
)){
937 log_err("Error in getDisplayScript() %s\n", myErrorName(status
));
941 maxresultsize
=uloc_getDisplayCountry(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
942 if(status
==U_BUFFER_OVERFLOW_ERROR
)
945 testCtry
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
946 uloc_getDisplayCountry(testLocale
, displayLocale
, testCtry
, maxresultsize
+ 1, &status
);
952 if(U_FAILURE(status
)){
953 log_err("Error in getDisplayCountry() %s\n", myErrorName(status
));
957 maxresultsize
=uloc_getDisplayVariant(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
958 if(status
==U_BUFFER_OVERFLOW_ERROR
)
961 testVar
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
962 uloc_getDisplayVariant(testLocale
, displayLocale
, testVar
, maxresultsize
+ 1, &status
);
968 if(U_FAILURE(status
)){
969 log_err("Error in getDisplayVariant() %s\n", myErrorName(status
));
973 maxresultsize
=uloc_getDisplayName(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
974 if(status
==U_BUFFER_OVERFLOW_ERROR
)
977 testName
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
978 uloc_getDisplayName(testLocale
, displayLocale
, testName
, maxresultsize
+ 1, &status
);
984 if(U_FAILURE(status
)){
985 log_err("Error in getDisplayName() %s\n", myErrorName(status
));
988 expectedLang
=dataTable
[compareIndex
][i
];
989 if(u_strlen(expectedLang
)== 0)
990 expectedLang
=dataTable
[DLANG_EN
][i
];
992 expectedScript
=dataTable
[compareIndex
+ 1][i
];
993 if(u_strlen(expectedScript
)== 0)
994 expectedScript
=dataTable
[DSCRIPT_EN
][i
];
996 expectedCtry
=dataTable
[compareIndex
+ 2][i
];
997 if(u_strlen(expectedCtry
)== 0)
998 expectedCtry
=dataTable
[DCTRY_EN
][i
];
1000 expectedVar
=dataTable
[compareIndex
+ 3][i
];
1001 if(u_strlen(expectedVar
)== 0)
1002 expectedVar
=dataTable
[DVAR_EN
][i
];
1004 expectedName
=dataTable
[compareIndex
+ 4][i
];
1005 if(u_strlen(expectedName
) == 0)
1006 expectedName
=dataTable
[DNAME_EN
][i
];
1008 if (0 !=u_strcmp(testLang
,expectedLang
)) {
1009 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang
), austrdup(expectedLang
), displayLocale
);
1012 if (0 != u_strcmp(testScript
,expectedScript
)) {
1013 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript
), austrdup(expectedScript
), displayLocale
);
1016 if (0 != u_strcmp(testCtry
,expectedCtry
)) {
1017 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry
), austrdup(expectedCtry
), displayLocale
);
1020 if (0 != u_strcmp(testVar
,expectedVar
)) {
1021 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar
), austrdup(expectedVar
), displayLocale
);
1024 if(0 != u_strcmp(testName
, expectedName
)) {
1025 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName
), austrdup(expectedName
), displayLocale
);
1028 if(testName
!=&_NUL
) {
1031 if(testLang
!=&_NUL
) {
1034 if(testScript
!=&_NUL
) {
1037 if(testCtry
!=&_NUL
) {
1040 if(testVar
!=&_NUL
) {
1047 /*------------------------------
1048 * TestDisplayNameBrackets
1052 const char * displayLocale
;
1053 const char * namedRegion
;
1054 const char * namedLocale
;
1055 const char * regionName
;
1056 const char * ulocLocaleName
;
1057 const char * uldnLocaleName
;
1058 } DisplayNameBracketsItem
;
1060 static const DisplayNameBracketsItem displayNameBracketsItems
[] = {
1061 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)", "English (Cocos [Keeling] Islands)" },
1062 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])", "Burmese (Myanmar)" },
1063 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])", "Burmese (Myanmar, Myanmar)" },
1064 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B",
1065 "\\u82F1\\u6587\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09",
1066 "\\u82F1\\u6587\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1067 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09",
1068 "\\u6CD5\\u6587\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09",
1069 "\\u6CD5\\u6587\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1070 { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}
1073 enum { kDisplayNameBracketsMax
= 128 };
1075 static void TestDisplayNameBrackets()
1077 const DisplayNameBracketsItem
* itemPtr
= displayNameBracketsItems
;
1078 for (; itemPtr
->displayLocale
!= NULL
; itemPtr
++) {
1079 ULocaleDisplayNames
* uldn
;
1081 UChar expectRegionName
[kDisplayNameBracketsMax
];
1082 UChar expectUlocLocaleName
[kDisplayNameBracketsMax
];
1083 UChar expectUldnLocaleName
[kDisplayNameBracketsMax
];
1084 UChar getName
[kDisplayNameBracketsMax
];
1087 (void) u_unescape(itemPtr
->regionName
, expectRegionName
, kDisplayNameBracketsMax
);
1088 (void) u_unescape(itemPtr
->ulocLocaleName
, expectUlocLocaleName
, kDisplayNameBracketsMax
);
1089 (void) u_unescape(itemPtr
->uldnLocaleName
, expectUldnLocaleName
, kDisplayNameBracketsMax
);
1091 status
= U_ZERO_ERROR
;
1092 ulen
= uloc_getDisplayCountry(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1093 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1094 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1097 status
= U_ZERO_ERROR
;
1098 ulen
= uloc_getDisplayName(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1099 if ( U_FAILURE(status
) || u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1100 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1102 if ( U_FAILURE(status
) ) {
1103 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1104 } else if ( u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1106 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1107 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1110 #if !UCONFIG_NO_FORMATTING
1111 status
= U_ZERO_ERROR
;
1112 uldn
= uldn_open(itemPtr
->displayLocale
, ULDN_STANDARD_NAMES
, &status
);
1113 if (U_SUCCESS(status
)) {
1114 status
= U_ZERO_ERROR
;
1115 ulen
= uldn_regionDisplayName(uldn
, itemPtr
->namedRegion
, getName
, kDisplayNameBracketsMax
, &status
);
1116 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1117 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedRegion
, myErrorName(status
));
1120 status
= U_ZERO_ERROR
;
1121 ulen
= uldn_localeDisplayName(uldn
, itemPtr
->namedLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1122 if ( U_FAILURE(status
) ) {
1123 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1124 } else if ( u_strcmp(getName
, expectUldnLocaleName
) != 0 ) {
1126 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1127 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1132 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr
->displayLocale
, u_errorName(status
));
1135 (void)ulen
; /* Suppress variable not used warning */
1139 /*------------------------------
1143 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1144 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1145 static void TestISOFunctions()
1147 const char* const* str
=uloc_getISOLanguages();
1148 const char* const* str1
=uloc_getISOCountries();
1150 const char *key
= NULL
;
1151 int32_t count
= 0, skipped
= 0;
1153 UResourceBundle
*res
;
1154 UResourceBundle
*subRes
;
1155 UErrorCode status
= U_ZERO_ERROR
;
1157 /* test getISOLanguages*/
1158 /*str=uloc_getISOLanguages(); */
1159 log_verbose("Testing ISO Languages: \n");
1161 /* use structLocale - this data is no longer in root */
1162 res
= ures_openDirect(loadTestData(&status
), "structLocale", &status
);
1163 subRes
= ures_getByKey(res
, "Languages", NULL
, &status
);
1164 if (U_FAILURE(status
)) {
1165 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status
));
1169 expect
= ures_getSize(subRes
);
1170 for(count
= 0; *(str
+count
) != 0; count
++)
1173 test
= *(str
+count
);
1174 status
= U_ZERO_ERROR
;
1177 /* Skip over language tags. This API only returns language codes. */
1178 skipped
+= (key
!= NULL
);
1179 ures_getNextString(subRes
, NULL
, &key
, &status
);
1181 while (key
!= NULL
&& strchr(key
, '_'));
1185 /* TODO: Consider removing sh, which is deprecated */
1186 if(strcmp(key
,"root") == 0 || strcmp(key
,"Fallback") == 0 || strcmp(key
,"sh") == 0) {
1187 ures_getNextString(subRes
, NULL
, &key
, &status
);
1190 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1191 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1192 if(strcmp(test
,key
)) {
1193 /* The first difference usually implies the place where things get out of sync */
1194 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1198 if(!strcmp(test
,"in"))
1199 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1200 if(!strcmp(test
,"iw"))
1201 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1202 if(!strcmp(test
,"ji"))
1203 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1204 if(!strcmp(test
,"jw"))
1205 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1206 if(!strcmp(test
,"sh"))
1207 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1210 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1213 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count
, expect
);
1216 subRes
= ures_getByKey(res
, "Countries", subRes
, &status
);
1217 log_verbose("Testing ISO Countries");
1219 expect
= ures_getSize(subRes
) - 1; /* Skip ZZ */
1220 for(count
= 0; *(str1
+count
) != 0; count
++)
1223 test
= *(str1
+count
);
1225 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1226 skipped
+= (key
!= NULL
);
1227 ures_getNextString(subRes
, NULL
, &key
, &status
);
1229 while (key
!= NULL
&& strlen(key
) != 2);
1233 /* TODO: Consider removing CS, which is deprecated */
1234 while(strcmp(key
,"QO") == 0 || strcmp(key
,"QU") == 0 || strcmp(key
,"CS") == 0) {
1235 ures_getNextString(subRes
, NULL
, &key
, &status
);
1238 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1239 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1240 if(strcmp(test
,key
)) {
1241 /* The first difference usually implies the place where things get out of sync */
1242 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1245 if(!strcmp(test
,"FX"))
1246 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1247 if(!strcmp(test
,"YU"))
1248 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1249 if(!strcmp(test
,"ZR"))
1250 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1253 ures_getNextString(subRes
, NULL
, &key
, &status
);
1254 if (strcmp(key
, "ZZ") != 0) {
1255 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key
);
1257 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1258 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1261 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1262 skipped
+= (key
!= NULL
);
1263 ures_getNextString(subRes
, NULL
, &key
, &status
);
1265 while (U_SUCCESS(status
) && key
!= NULL
&& strlen(key
) != 2);
1267 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1270 log_err("There is an error in getISOCountries, got %d, expected %d \n", count
, expect
);
1277 static void setUpDataTable()
1280 dataTable
= (UChar
***)(calloc(sizeof(UChar
**),LOCALE_INFO_SIZE
));
1282 for (i
= 0; i
< LOCALE_INFO_SIZE
; i
++) {
1283 dataTable
[i
] = (UChar
**)(calloc(sizeof(UChar
*),LOCALE_SIZE
));
1284 for (j
= 0; j
< LOCALE_SIZE
; j
++){
1285 dataTable
[i
][j
] = CharsToUChars(rawData2
[i
][j
]);
1290 static void cleanUpDataTable()
1293 if(dataTable
!= NULL
) {
1294 for (i
=0; i
<LOCALE_INFO_SIZE
; i
++) {
1295 for(j
= 0; j
< LOCALE_SIZE
; j
++) {
1296 free(dataTable
[i
][j
]);
1306 * @bug 4011756 4011380
1308 static void TestISO3Fallback()
1310 const char* test
="xx_YY";
1312 const char * result
;
1314 result
= uloc_getISO3Language(test
);
1316 /* Conform to C API usage */
1318 if (!result
|| (result
[0] != 0))
1319 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1321 result
= uloc_getISO3Country(test
);
1323 if (!result
|| (result
[0] != 0))
1324 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1330 static void TestSimpleDisplayNames()
1333 This test is different from TestDisplayNames because TestDisplayNames checks
1334 fallback behavior, combination of language and country names to form locale
1335 names, and other stuff like that. This test just checks specific language
1336 and country codes to make sure we have the correct names for them.
1338 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1339 const char* languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1341 const char* inLocale
[] = { "en_US", "zh_Hant"};
1342 UErrorCode status
=U_ZERO_ERROR
;
1345 int32_t localeIndex
= 0;
1346 for (i
= 0; i
< 7; i
++) {
1348 UChar
*expectedLang
=0;
1352 localeIndex
= 1; /* Use the second locale for the rest of the test. */
1355 size
=uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], NULL
, size
, &status
);
1356 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1357 status
=U_ZERO_ERROR
;
1358 testLang
=(UChar
*)malloc(sizeof(UChar
) * (size
+ 1));
1359 uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], testLang
, size
+ 1, &status
);
1361 expectedLang
=(UChar
*)malloc(sizeof(UChar
) * (strlen(languageNames
[i
])+1));
1362 u_uastrcpy(expectedLang
, languageNames
[i
]);
1363 if (u_strcmp(testLang
, expectedLang
) != 0)
1364 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1365 languageCodes
[i
], languageNames
[i
], austrdup(testLang
));
1375 static void TestUninstalledISO3Names()
1377 /* This test checks to make sure getISO3Language and getISO3Country work right
1378 even for locales that are not installed. */
1379 static const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
1381 static const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
1382 "ssw", "twi", "zul" };
1383 static const char iso2Countries
[][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1384 "ss_SB", "tw_TC", "zu_ZW" };
1385 static const char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1386 "SLB", "TCA", "ZWE" };
1389 for (i
= 0; i
< 8; i
++) {
1390 UErrorCode err
= U_ZERO_ERROR
;
1392 test
= uloc_getISO3Language(iso2Languages
[i
]);
1393 if(strcmp(test
, iso3Languages
[i
]) !=0 || U_FAILURE(err
))
1394 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1395 iso2Languages
[i
], iso3Languages
[i
], test
, myErrorName(err
));
1397 for (i
= 0; i
< 8; i
++) {
1398 UErrorCode err
= U_ZERO_ERROR
;
1400 test
= uloc_getISO3Country(iso2Countries
[i
]);
1401 if(strcmp(test
, iso3Countries
[i
]) !=0 || U_FAILURE(err
))
1402 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1403 iso2Countries
[i
], iso3Countries
[i
], test
, myErrorName(err
));
1408 static void TestVariantParsing()
1410 static const char* en_US_custom
="en_US_De Anza_Cupertino_California_United States_Earth";
1411 static const char* dispName
="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1412 static const char* dispVar
="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1413 static const char* shortVariant
="fr_FR_foo";
1414 static const char* bogusVariant
="fr_FR__foo";
1415 static const char* bogusVariant2
="fr_FR_foo_";
1416 static const char* bogusVariant3
="fr_FR__foo_";
1419 UChar displayVar
[100];
1420 UChar displayName
[100];
1421 UErrorCode status
=U_ZERO_ERROR
;
1424 size
=uloc_getDisplayVariant(en_US_custom
, "en_US", NULL
, size
, &status
);
1425 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1426 status
=U_ZERO_ERROR
;
1427 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1428 uloc_getDisplayVariant(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1431 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1433 u_uastrcpy(displayVar
, dispVar
);
1434 if(u_strcmp(got
,displayVar
)!=0) {
1435 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar
, austrdup(got
));
1438 size
=uloc_getDisplayName(en_US_custom
, "en_US", NULL
, size
, &status
);
1439 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1440 status
=U_ZERO_ERROR
;
1441 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1442 uloc_getDisplayName(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1445 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1447 u_uastrcpy(displayName
, dispName
);
1448 if(u_strcmp(got
,displayName
)!=0) {
1449 if (status
== U_USING_DEFAULT_WARNING
) {
1450 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status
));
1452 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName
, austrdup(got
));
1457 status
=U_ZERO_ERROR
;
1458 size
=uloc_getDisplayVariant(shortVariant
, NULL
, NULL
, size
, &status
);
1459 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1460 status
=U_ZERO_ERROR
;
1461 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1462 uloc_getDisplayVariant(shortVariant
, NULL
, got
, size
+ 1, &status
);
1465 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1467 if(strcmp(austrdup(got
),"FOO")!=0) {
1468 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got
));
1471 status
=U_ZERO_ERROR
;
1472 size
=uloc_getDisplayVariant(bogusVariant
, NULL
, NULL
, size
, &status
);
1473 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1474 status
=U_ZERO_ERROR
;
1475 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1476 uloc_getDisplayVariant(bogusVariant
, NULL
, got
, size
+ 1, &status
);
1479 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1481 if(strcmp(austrdup(got
),"_FOO")!=0) {
1482 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got
));
1485 status
=U_ZERO_ERROR
;
1486 size
=uloc_getDisplayVariant(bogusVariant2
, NULL
, NULL
, size
, &status
);
1487 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1488 status
=U_ZERO_ERROR
;
1489 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1490 uloc_getDisplayVariant(bogusVariant2
, NULL
, got
, size
+ 1, &status
);
1493 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1495 if(strcmp(austrdup(got
),"FOO_")!=0) {
1496 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got
));
1499 status
=U_ZERO_ERROR
;
1500 size
=uloc_getDisplayVariant(bogusVariant3
, NULL
, NULL
, size
, &status
);
1501 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1502 status
=U_ZERO_ERROR
;
1503 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1504 uloc_getDisplayVariant(bogusVariant3
, NULL
, got
, size
+ 1, &status
);
1507 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1509 if(strcmp(austrdup(got
),"_FOO_")!=0) {
1510 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got
));
1516 static void TestObsoleteNames(void)
1519 UErrorCode status
= U_ZERO_ERROR
;
1531 { "eng_USA", "eng", "en", "USA", "US" },
1532 { "kok", "kok", "kok", "", "" },
1533 { "in", "ind", "in", "", "" },
1534 { "id", "ind", "id", "", "" }, /* NO aliasing */
1535 { "sh", "srp", "sh", "", "" },
1536 { "zz_CS", "", "zz", "SCG", "CS" },
1537 { "zz_FX", "", "zz", "FXX", "FX" },
1538 { "zz_RO", "", "zz", "ROU", "RO" },
1539 { "zz_TP", "", "zz", "TMP", "TP" },
1540 { "zz_TL", "", "zz", "TLS", "TL" },
1541 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1542 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1543 { "zz_ROM", "", "zz", "ROU", "RO" },
1544 { "zz_ROU", "", "zz", "ROU", "RO" },
1545 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1546 { "zz_TMP", "", "zz", "TMP", "TP" },
1547 { "zz_TLS", "", "zz", "TLS", "TL" },
1548 { "zz_YUG", "", "zz", "YUG", "YU" },
1549 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1550 { "iw", "heb", "iw", "", "" },
1551 { "ji", "yid", "ji", "", "" },
1552 { "jw", "jaw", "jw", "", "" },
1553 { "sh", "srp", "sh", "", "" },
1554 { "", "", "", "", "" }
1557 for(i
=0;tests
[i
].locale
[0];i
++)
1561 locale
= tests
[i
].locale
;
1562 log_verbose("** %s:\n", locale
);
1564 status
= U_ZERO_ERROR
;
1565 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1567 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1568 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1572 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1573 uloc_getISO3Language(locale
) );
1576 status
= U_ZERO_ERROR
;
1577 uloc_getLanguage(locale
, buff
, 256, &status
);
1578 if(U_FAILURE(status
))
1580 log_err("FAIL: error getting language from %s\n", locale
);
1584 if(strcmp(buff
,tests
[i
].lang
))
1586 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1587 locale
, buff
, tests
[i
].lang
);
1591 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale
, buff
);
1594 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1596 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1597 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1601 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1602 uloc_getISO3Language(locale
) );
1605 if(strcmp(tests
[i
].ctry3
,uloc_getISO3Country(locale
)))
1607 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1608 locale
, uloc_getISO3Country(locale
), tests
[i
].ctry3
);
1612 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1613 uloc_getISO3Country(locale
) );
1616 status
= U_ZERO_ERROR
;
1617 uloc_getCountry(locale
, buff
, 256, &status
);
1618 if(U_FAILURE(status
))
1620 log_err("FAIL: error getting country from %s\n", locale
);
1624 if(strcmp(buff
,tests
[i
].ctry
))
1626 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1627 locale
, buff
, tests
[i
].ctry
);
1631 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale
, buff
);
1636 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1637 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1640 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1641 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1646 i
= uloc_getLanguage("kok",NULL
,0,&icu_err
);
1647 if(U_FAILURE(icu_err
))
1649 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err
));
1652 icu_err
= U_ZERO_ERROR
;
1653 uloc_getLanguage("kok",r1_buff
,12,&icu_err
);
1654 if(U_FAILURE(icu_err
))
1656 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err
));
1659 r1_addr
= (char *)uloc_getISO3Language("kok");
1661 icu_err
= U_ZERO_ERROR
;
1662 if (strcmp(r1_buff
,"kok") != 0)
1664 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff
);
1667 r1_addr
= (char *)uloc_getISO3Language("in");
1668 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1669 if (strcmp(r1_buff
,"id") != 0)
1671 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1674 r1_addr
= (char *)uloc_getISO3Language("sh");
1675 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1676 if (strcmp(r1_buff
,"sr") != 0)
1678 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1682 r1_addr
= (char *)uloc_getISO3Country("zz_ZR");
1683 strcpy(p1_buff
,"zz_");
1684 strcat(p1_buff
,r1_addr
);
1685 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1686 if (strcmp(r1_buff
,"ZR") != 0)
1688 printf("uloc_getCountry error (%s)\n",r1_buff
);
1691 r1_addr
= (char *)uloc_getISO3Country("zz_FX");
1692 strcpy(p1_buff
,"zz_");
1693 strcat(p1_buff
,r1_addr
);
1694 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1695 if (strcmp(r1_buff
,"FX") != 0)
1697 printf("uloc_getCountry error (%s)\n",r1_buff
);
1705 static void TestKeywordVariants(void)
1707 static const struct {
1708 const char *localeID
;
1709 const char *expectedLocaleID
; /* uloc_getName */
1710 const char *expectedLocaleIDNoKeywords
; /* uloc_getBaseName */
1711 const char *expectedCanonicalID
; /* uloc_canonicalize */
1712 const char *expectedKeywords
[10];
1713 int32_t numKeywords
;
1714 UErrorCode expectedStatus
; /* from uloc_openKeywords */
1717 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1718 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1720 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1721 {"calendar", "collation", "currency"},
1728 "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */
1729 "de_DE@currency=EUR",
1730 {"","","","","","",""},
1732 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1735 "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */
1736 "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1737 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1738 "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1739 {"","","","","","",""},
1741 U_INVALID_FORMAT_ERROR
1745 0, /* expected getName to fail */
1746 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1747 0, /* expected canonicalize to fail */
1748 {"","","","","","",""},
1750 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1753 UErrorCode status
= U_ZERO_ERROR
;
1755 int32_t i
= 0, j
= 0;
1756 int32_t resultLen
= 0;
1758 UEnumeration
*keywords
;
1759 int32_t keyCount
= 0;
1760 const char *keyword
= NULL
;
1761 int32_t keywordLen
= 0;
1763 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1764 status
= U_ZERO_ERROR
;
1766 keywords
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
1768 if(status
!= testCases
[i
].expectedStatus
) {
1769 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1770 testCases
[i
].localeID
,
1771 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1773 status
= U_ZERO_ERROR
;
1775 if((keyCount
= uenum_count(keywords
, &status
)) != testCases
[i
].numKeywords
) {
1776 log_err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1780 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1781 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1782 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1787 uenum_reset(keywords
, &status
);
1788 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1789 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1790 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1795 uenum_close(keywords
);
1798 status
= U_ZERO_ERROR
;
1799 resultLen
= uloc_getName(testCases
[i
].localeID
, buffer
, 256, &status
);
1800 if (U_SUCCESS(status
)) {
1801 if (testCases
[i
].expectedLocaleID
== 0) {
1802 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1803 testCases
[i
].localeID
, buffer
);
1804 } else if (uprv_strcmp(testCases
[i
].expectedLocaleID
, buffer
) != 0) {
1805 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1806 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
);
1809 if (testCases
[i
].expectedLocaleID
!= 0) {
1810 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1811 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
, u_errorName(status
));
1815 status
= U_ZERO_ERROR
;
1816 resultLen
= uloc_getBaseName(testCases
[i
].localeID
, buffer
, 256, &status
);
1817 if (U_SUCCESS(status
)) {
1818 if (testCases
[i
].expectedLocaleIDNoKeywords
== 0) {
1819 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
1820 testCases
[i
].localeID
, buffer
);
1821 } else if (uprv_strcmp(testCases
[i
].expectedLocaleIDNoKeywords
, buffer
) != 0) {
1822 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
1823 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
);
1826 if (testCases
[i
].expectedLocaleIDNoKeywords
!= 0) {
1827 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
1828 testCases
[i
].localeID
, testCases
[i
].expectedLocaleIDNoKeywords
, buffer
, u_errorName(status
));
1832 status
= U_ZERO_ERROR
;
1833 resultLen
= uloc_canonicalize(testCases
[i
].localeID
, buffer
, 256, &status
);
1834 if (U_SUCCESS(status
)) {
1835 if (testCases
[i
].expectedCanonicalID
== 0) {
1836 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
1837 testCases
[i
].localeID
, buffer
);
1838 } else if (uprv_strcmp(testCases
[i
].expectedCanonicalID
, buffer
) != 0) {
1839 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1840 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
);
1843 if (testCases
[i
].expectedCanonicalID
!= 0) {
1844 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
1845 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
, u_errorName(status
));
1851 static void TestKeywordVariantParsing(void)
1853 static const struct {
1854 const char *localeID
;
1855 const char *keyword
;
1856 const char *expectedValue
;
1858 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
1859 { "de_DE", "collation", ""},
1860 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1861 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1864 UErrorCode status
= U_ZERO_ERROR
;
1867 int32_t resultLen
= 0;
1870 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
1872 resultLen
= uloc_getKeywordValue(testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
, 256, &status
);
1873 (void)resultLen
; /* Suppress set but not used warning. */
1874 if(uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1875 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1876 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1881 static const struct {
1882 const char *l
; /* locale */
1883 const char *k
; /* kw */
1884 const char *v
; /* value */
1885 const char *x
; /* expected */
1886 } kwSetTestCases
[] = {
1888 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1889 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1890 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1891 { "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 */
1892 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1893 { "de", "Currency", "CHF", "de@currency=CHF" },
1894 { "de", "Currency", "CHF", "de@currency=CHF" },
1896 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1897 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1898 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1899 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1900 { "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 */
1901 { "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 */
1902 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1903 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1906 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1907 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1908 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1909 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1910 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1911 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1912 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1913 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1914 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1918 /* 1. removal of item at end */
1919 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1920 { "de@collation=phonebook;currency=CHF", "currency", NULL
, "de@collation=phonebook" },
1921 /* 2. removal of item at beginning */
1922 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1923 { "de@collation=phonebook;currency=CHF", "collation", NULL
, "de@currency=CHF" },
1924 /* 3. removal of an item not there */
1925 { "de@collation=phonebook;currency=CHF", "calendar", NULL
, "de@collation=phonebook;currency=CHF" },
1926 /* 4. removal of only item */
1927 { "de@collation=phonebook", "collation", NULL
, "de" },
1929 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1933 static void TestKeywordSet(void)
1936 int32_t resultLen
= 0;
1941 for(i
= 0; i
< UPRV_LENGTHOF(kwSetTestCases
); i
++) {
1942 UErrorCode status
= U_ZERO_ERROR
;
1943 memset(buffer
,'%',1023);
1944 strcpy(buffer
, kwSetTestCases
[i
].l
);
1946 uloc_canonicalize(kwSetTestCases
[i
].l
, cbuffer
, 1023, &status
);
1947 if(strcmp(buffer
,cbuffer
)) {
1948 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i
, cbuffer
, buffer
);
1950 /* sanity check test case results for canonicity */
1951 uloc_canonicalize(kwSetTestCases
[i
].x
, cbuffer
, 1023, &status
);
1952 if(strcmp(kwSetTestCases
[i
].x
,cbuffer
)) {
1953 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__
, __LINE__
, i
, kwSetTestCases
[i
].x
, cbuffer
);
1956 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
1957 if(U_FAILURE(status
)) {
1958 log_err("Err on test case %d: got error %s\n", i
, u_errorName(status
));
1961 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=resultLen
)) {
1962 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
1963 kwSetTestCases
[i
].v
, buffer
, resultLen
, kwSetTestCases
[i
].x
, strlen(buffer
));
1965 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,buffer
);
1970 static void TestKeywordSetError(void)
1978 /* 0-test whether an error condition modifies the buffer at all */
1981 memset(buffer
,'%',1023);
1982 status
= U_ZERO_ERROR
;
1983 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1984 if(status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1985 log_err("expected illegal err got %s\n", u_errorName(status
));
1988 /* if(res!=strlen(kwSetTestCases[i].x)) {
1989 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1992 if(buffer
[blen
]!='%') {
1993 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
1996 log_verbose("0-buffer modify OK\n");
1999 /* 1- test a short buffer with growing text */
2000 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2001 memset(buffer
,'%',1023);
2002 strcpy(buffer
,kwSetTestCases
[i
].l
);
2003 status
= U_ZERO_ERROR
;
2004 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2005 if(status
!= U_BUFFER_OVERFLOW_ERROR
) {
2006 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
);
2009 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2010 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2013 if(buffer
[blen
]!='%') {
2014 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
2017 log_verbose("1/%d-buffer modify OK\n",i
);
2021 /* 2- test a short buffer - text the same size or shrinking */
2022 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
2023 memset(buffer
,'%',1023);
2024 strcpy(buffer
,kwSetTestCases
[i
].l
);
2025 status
= U_ZERO_ERROR
;
2026 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
2027 if(status
!= U_ZERO_ERROR
) {
2028 log_err("expected zero error got %s\n", u_errorName(status
));
2031 if(buffer
[blen
+1]!='%') {
2032 log_err("Buffer byte %d was modified: now %c\n", blen
+1, buffer
[blen
+1]);
2035 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
2036 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
2039 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=res
)) {
2040 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
2041 kwSetTestCases
[i
].v
, buffer
, res
, kwSetTestCases
[i
].x
, strlen(buffer
));
2043 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,
2046 log_verbose("2/%d-buffer modify OK\n",i
);
2050 static int32_t _canonicalize(int32_t selector
, /* 0==getName, 1==canonicalize */
2051 const char* localeID
,
2053 int32_t resultCapacity
,
2055 /* YOU can change this to use function pointers if you like */
2058 return uloc_getName(localeID
, result
, resultCapacity
, ec
);
2060 return uloc_canonicalize(localeID
, result
, resultCapacity
, ec
);
2066 static void TestCanonicalization(void)
2068 static const struct {
2069 const char *localeID
; /* input */
2070 const char *getNameID
; /* expected getName() result */
2071 const char *canonicalID
; /* expected canonicalize() result */
2073 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2074 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2075 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2076 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
2077 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
2078 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
2079 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2080 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2081 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2082 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2083 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2084 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2085 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2086 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2087 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2088 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2089 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2090 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2091 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2092 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2093 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2094 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2095 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2096 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2097 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2098 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2099 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2100 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2101 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2102 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2103 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2104 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2105 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2106 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
2107 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2108 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2109 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2110 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2111 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2112 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2113 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2114 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2115 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2116 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2117 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2118 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2119 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2120 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2121 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2122 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2123 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2125 /* posix behavior that used to be performed by getName */
2126 { "mr.utf8", "mr.utf8", "mr" },
2127 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2128 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2129 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2130 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2131 { "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 */
2133 /* fleshing out canonicalization */
2134 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2135 { "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" },
2136 /* already-canonical ids are not changed */
2137 { "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" },
2138 /* PRE_EURO and EURO conversions don't affect other keywords */
2139 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2140 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2141 /* currency keyword overrides PRE_EURO and EURO currency */
2142 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2143 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2144 /* norwegian is just too weird, if we handle things in their full generality */
2145 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2147 /* test cases reflecting internal resource bundle usage */
2148 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2149 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2150 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2151 { "ja_JP", "ja_JP", "ja_JP" },
2153 /* test case for "i-default" */
2154 { "i-default", "en@x=i-default", "en@x=i-default" }
2157 static const char* label
[] = { "getName", "canonicalize" };
2159 UErrorCode status
= U_ZERO_ERROR
;
2160 int32_t i
, j
, resultLen
= 0, origResultLen
;
2163 for (i
=0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2164 for (j
=0; j
<2; ++j
) {
2165 const char* expected
= (j
==0) ? testCases
[i
].getNameID
: testCases
[i
].canonicalID
;
2167 status
= U_ZERO_ERROR
;
2169 if (expected
== NULL
) {
2170 expected
= uloc_getDefault();
2173 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2174 origResultLen
= _canonicalize(j
, testCases
[i
].localeID
, NULL
, 0, &status
);
2175 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
2176 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2177 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2180 status
= U_ZERO_ERROR
;
2181 resultLen
= _canonicalize(j
, testCases
[i
].localeID
, buffer
, sizeof(buffer
), &status
);
2182 if (U_FAILURE(status
)) {
2183 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2184 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2187 if(uprv_strcmp(expected
, buffer
) != 0) {
2188 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2189 label
[j
], testCases
[i
].localeID
, buffer
, expected
);
2191 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2192 label
[j
], testCases
[i
].localeID
, buffer
);
2194 if (resultLen
!= (int32_t)strlen(buffer
)) {
2195 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2196 label
[j
], testCases
[i
].localeID
, resultLen
, strlen(buffer
));
2198 if (origResultLen
!= resultLen
) {
2199 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2200 label
[j
], testCases
[i
].localeID
, origResultLen
, resultLen
);
2206 static void TestDisplayKeywords(void)
2210 static const struct {
2211 const char *localeID
;
2212 const char *displayLocale
;
2213 UChar displayKeyword
[200];
2215 { "ca_ES@currency=ESP", "de_AT",
2216 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2218 { "ja_JP@calendar=japanese", "de",
2219 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2221 { "de_DE@collation=traditional", "de_DE",
2222 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2225 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2226 UErrorCode status
= U_ZERO_ERROR
;
2227 const char* keyword
=NULL
;
2228 int32_t keywordLen
= 0;
2229 int32_t keywordCount
= 0;
2230 UChar
*displayKeyword
=NULL
;
2231 int32_t displayKeywordLen
= 0;
2232 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2233 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2234 if(U_FAILURE(status
)){
2235 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases
[i
].localeID
, u_errorName(status
));
2238 /* the uenum_next returns NUL terminated string */
2239 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2240 /* fetch the displayKeyword */
2241 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2242 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2243 status
= U_ZERO_ERROR
;
2244 displayKeywordLen
++; /* for null termination */
2245 displayKeyword
= (UChar
*) malloc(displayKeywordLen
* U_SIZEOF_UCHAR
);
2246 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2247 if(U_FAILURE(status
)){
2248 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
));
2251 if(u_strncmp(displayKeyword
, testCases
[i
].displayKeyword
, displayKeywordLen
)!=0){
2252 if (status
== U_USING_DEFAULT_WARNING
) {
2253 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
));
2255 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
);
2260 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status
));
2263 free(displayKeyword
);
2266 uenum_close(keywordEnum
);
2270 static void TestDisplayKeywordValues(void){
2273 static const struct {
2274 const char *localeID
;
2275 const char *displayLocale
;
2276 UChar displayKeywordValue
[500];
2278 { "ca_ES@currency=ESP", "de_AT",
2279 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2281 { "de_AT@currency=ATS", "fr_FR",
2282 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2284 { "de_DE@currency=DEM", "it",
2285 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2287 { "el_GR@currency=GRD", "en",
2288 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2290 { "eu_ES@currency=ESP", "it_IT",
2291 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2293 { "de@collation=phonebook", "es",
2294 {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}
2297 { "de_DE@collation=phonebook", "es",
2298 {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}
2300 { "es_ES@collation=traditional","de",
2301 {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}
2303 { "ja_JP@calendar=japanese", "de",
2304 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2307 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2308 UErrorCode status
= U_ZERO_ERROR
;
2309 const char* keyword
=NULL
;
2310 int32_t keywordLen
= 0;
2311 int32_t keywordCount
= 0;
2312 UChar
*displayKeywordValue
= NULL
;
2313 int32_t displayKeywordValueLen
= 0;
2314 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2315 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2316 if(U_FAILURE(status
)){
2317 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
));
2320 /* the uenum_next returns NUL terminated string */
2321 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2323 /* fetch the displayKeywordValue */
2324 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2325 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2326 status
= U_ZERO_ERROR
;
2327 displayKeywordValueLen
++; /* for null termination */
2328 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2329 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2330 if(U_FAILURE(status
)){
2331 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
));
2334 if(u_strncmp(displayKeywordValue
, testCases
[i
].displayKeywordValue
, displayKeywordValueLen
)!=0){
2335 if (status
== U_USING_DEFAULT_WARNING
) {
2336 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
));
2338 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
));
2343 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2345 free(displayKeywordValue
);
2347 uenum_close(keywordEnum
);
2350 /* test a multiple keywords */
2351 UErrorCode status
= U_ZERO_ERROR
;
2352 const char* keyword
=NULL
;
2353 int32_t keywordLen
= 0;
2354 int32_t keywordCount
= 0;
2355 const char* localeID
= "es@collation=phonebook;calendar=buddhist;currency=DEM";
2356 const char* displayLocale
= "de";
2357 static const UChar expected
[][50] = {
2358 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2360 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2361 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2364 UEnumeration
* keywordEnum
= uloc_openKeywords(localeID
, &status
);
2366 for(keywordCount
= 0; keywordCount
< uenum_count(keywordEnum
, &status
) ; keywordCount
++){
2367 UChar
*displayKeywordValue
= NULL
;
2368 int32_t displayKeywordValueLen
= 0;
2369 if(U_FAILURE(status
)){
2370 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID
, displayLocale
, u_errorName(status
));
2373 /* the uenum_next returns NUL terminated string */
2374 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2376 /* fetch the displayKeywordValue */
2377 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2378 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2379 status
= U_ZERO_ERROR
;
2380 displayKeywordValueLen
++; /* for null termination */
2381 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2382 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2383 if(U_FAILURE(status
)){
2384 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
));
2387 if(u_strncmp(displayKeywordValue
, expected
[keywordCount
], displayKeywordValueLen
)!=0){
2388 if (status
== U_USING_DEFAULT_WARNING
) {
2389 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
));
2391 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID
, keyword
, displayLocale
);
2396 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2398 free(displayKeywordValue
);
2400 uenum_close(keywordEnum
);
2404 /* Test non existent keywords */
2405 UErrorCode status
= U_ZERO_ERROR
;
2406 const char* localeID
= "es";
2407 const char* displayLocale
= "de";
2408 UChar
*displayKeywordValue
= NULL
;
2409 int32_t displayKeywordValueLen
= 0;
2411 /* fetch the displayKeywordValue */
2412 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, "calendar", displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2413 if(U_FAILURE(status
)) {
2414 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status
));
2415 } else if(displayKeywordValueLen
!= 0) {
2416 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen
);
2422 static void TestGetBaseName(void) {
2423 static const struct {
2424 const char *localeID
;
2425 const char *baseName
;
2427 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2428 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2429 { "ja@calendar = buddhist", "ja" }
2432 int32_t i
= 0, baseNameLen
= 0;
2434 UErrorCode status
= U_ZERO_ERROR
;
2436 for(i
= 0; i
< UPRV_LENGTHOF(testCases
); i
++) {
2437 baseNameLen
= uloc_getBaseName(testCases
[i
].localeID
, baseName
, 256, &status
);
2438 (void)baseNameLen
; /* Suppress set but not used warning. */
2439 if(strcmp(testCases
[i
].baseName
, baseName
)) {
2440 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2441 testCases
[i
].localeID
, testCases
[i
].baseName
, baseName
);
2447 static void TestTrailingNull(void) {
2448 const char* localeId
= "zh_Hans";
2449 UChar buffer
[128]; /* sufficient for this test */
2451 UErrorCode status
= U_ZERO_ERROR
;
2454 len
= uloc_getDisplayName(localeId
, localeId
, buffer
, 128, &status
);
2456 log_err("buffer too small");
2460 for (i
= 0; i
< len
; ++i
) {
2461 if (buffer
[i
] == 0) {
2462 log_err("name contained null");
2468 /* Jitterbug 4115 */
2469 static void TestDisplayNameWarning(void) {
2472 UErrorCode status
= U_ZERO_ERROR
;
2474 size
= uloc_getDisplayLanguage("qqq", "kl", name
, UPRV_LENGTHOF(name
), &status
);
2475 (void)size
; /* Suppress set but not used warning. */
2476 if (status
!= U_USING_DEFAULT_WARNING
) {
2477 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2478 u_errorName(status
));
2484 * Compare two locale IDs. If they are equal, return 0. If `string'
2485 * starts with `prefix' plus an additional element, that is, string ==
2486 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2488 static UBool
_loccmp(const char* string
, const char* prefix
) {
2489 int32_t slen
= (int32_t)uprv_strlen(string
),
2490 plen
= (int32_t)uprv_strlen(prefix
);
2491 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
2492 /* 'root' is less than everything */
2493 if (uprv_strcmp(prefix
, "root") == 0) {
2494 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
2496 if (c
) return -1; /* mismatch */
2497 if (slen
== plen
) return 0;
2498 if (string
[plen
] == '_') return 1;
2499 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2502 static void _checklocs(const char* label
,
2505 const char* actual
) {
2506 /* We want the valid to be strictly > the bogus requested locale,
2507 and the valid to be >= the actual. */
2508 if (_loccmp(req
, valid
) > 0 &&
2509 _loccmp(valid
, actual
) >= 0) {
2510 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2511 label
, req
, valid
, actual
);
2513 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2514 label
, req
, valid
, actual
);
2518 static void TestGetLocale(void) {
2519 UErrorCode ec
= U_ZERO_ERROR
;
2521 UChar EMPTY
[1] = {0};
2524 #if !UCONFIG_NO_FORMATTING
2527 const char *req
= "en_US_REDWOODSHORES", *valid
, *actual
;
2528 obj
= udat_open(UDAT_DEFAULT
, UDAT_DEFAULT
,
2532 if (U_FAILURE(ec
)) {
2533 log_data_err("udat_open failed.Error %s\n", u_errorName(ec
));
2536 valid
= udat_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2537 actual
= udat_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2538 if (U_FAILURE(ec
)) {
2539 log_err("udat_getLocaleByType() failed\n");
2542 _checklocs("udat", req
, valid
, actual
);
2548 #if !UCONFIG_NO_FORMATTING
2551 const char *req
= "fr_FR_PROVENCAL", *valid
, *actual
;
2552 obj
= ucal_open(NULL
, 0,
2556 if (U_FAILURE(ec
)) {
2557 log_err("ucal_open failed with error: %s\n", u_errorName(ec
));
2560 valid
= ucal_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2561 actual
= ucal_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2562 if (U_FAILURE(ec
)) {
2563 log_err("ucal_getLocaleByType() failed\n");
2566 _checklocs("ucal", req
, valid
, actual
);
2572 #if !UCONFIG_NO_FORMATTING
2575 const char *req
= "zh_Hant_TW_TAINAN", *valid
, *actual
;
2576 obj
= unum_open(UNUM_DECIMAL
,
2580 if (U_FAILURE(ec
)) {
2581 log_err("unum_open failed\n");
2584 valid
= unum_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2585 actual
= unum_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2586 if (U_FAILURE(ec
)) {
2587 log_err("unum_getLocaleByType() failed\n");
2590 _checklocs("unum", req
, valid
, actual
);
2597 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2598 #if !UCONFIG_NO_FORMATTING
2600 UMessageFormat
*obj
;
2601 const char *req
= "ja_JP_TAKAYAMA", *valid
, *actual
;
2603 obj
= umsg_open(EMPTY
, 0,
2606 if (U_FAILURE(ec
)) {
2607 log_err("umsg_open failed\n");
2610 valid
= umsg_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2611 actual
= umsg_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2612 if (U_FAILURE(ec
)) {
2613 log_err("umsg_getLocaleByType() failed\n");
2616 /* We want the valid to be strictly > the bogus requested locale,
2617 and the valid to be >= the actual. */
2618 /* TODO MessageFormat is currently just storing the locale it is given.
2619 As a result, it will return whatever it was given, even if the
2620 locale is invalid. */
2621 test
= (_cmpversion("3.2") <= 0) ?
2622 /* Here is the weakened test for 3.0: */
2623 (_loccmp(req
, valid
) >= 0) :
2624 /* Here is what the test line SHOULD be: */
2625 (_loccmp(req
, valid
) > 0);
2628 _loccmp(valid
, actual
) >= 0) {
2629 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2631 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2639 #if !UCONFIG_NO_BREAK_ITERATION
2641 UBreakIterator
*obj
;
2642 const char *req
= "ar_KW_ABDALI", *valid
, *actual
;
2643 obj
= ubrk_open(UBRK_WORD
,
2648 if (U_FAILURE(ec
)) {
2649 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec
));
2652 valid
= ubrk_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2653 actual
= ubrk_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2654 if (U_FAILURE(ec
)) {
2655 log_err("ubrk_getLocaleByType() failed\n");
2658 _checklocs("ubrk", req
, valid
, actual
);
2664 #if !UCONFIG_NO_COLLATION
2667 const char *req
= "es_AR_BUENOSAIRES", *valid
, *actual
;
2668 obj
= ucol_open(req
, &ec
);
2669 if (U_FAILURE(ec
)) {
2670 log_err("ucol_open failed - %s\n", u_errorName(ec
));
2673 valid
= ucol_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2674 actual
= ucol_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2675 if (U_FAILURE(ec
)) {
2676 log_err("ucol_getLocaleByType() failed\n");
2679 _checklocs("ucol", req
, valid
, actual
);
2684 static void TestEnglishExemplarCharacters(void) {
2685 UErrorCode status
= U_ZERO_ERROR
;
2688 UChar testChars
[] = {
2689 0x61, /* standard */
2690 0xE1, /* auxiliary */
2692 0x2D /* punctuation */
2694 ULocaleData
*uld
= ulocdata_open("en", &status
);
2695 if (U_FAILURE(status
)) {
2696 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status
));
2700 for (i
= 0; i
< ULOCDATA_ES_COUNT
; i
++) {
2701 exSet
= ulocdata_getExemplarSet(uld
, exSet
, 0, (ULocaleDataExemplarSetType
)i
, &status
);
2702 if (U_FAILURE(status
)) {
2703 log_err_status(status
, "ulocdata_getExemplarSet() for type %d failed\n", i
);
2704 status
= U_ZERO_ERROR
;
2707 if (!uset_contains(exSet
, (UChar32
)testChars
[i
])) {
2708 log_err("Character U+%04X is not included in exemplar type %d\n", testChars
[i
], i
);
2713 ulocdata_close(uld
);
2716 static void TestNonexistentLanguageExemplars(void) {
2717 /* JB 4068 - Nonexistent language */
2718 UErrorCode ec
= U_ZERO_ERROR
;
2719 ULocaleData
*uld
= ulocdata_open("qqq",&ec
);
2720 if (ec
!= U_USING_DEFAULT_WARNING
) {
2721 log_err_status(ec
, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2724 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2725 ulocdata_close(uld
);
2728 static void TestLocDataErrorCodeChaining(void) {
2729 UErrorCode ec
= U_USELESS_COLLATOR_ERROR
;
2730 ulocdata_open(NULL
, &ec
);
2731 ulocdata_getExemplarSet(NULL
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
);
2732 ulocdata_getDelimiter(NULL
, ULOCDATA_DELIMITER_COUNT
, NULL
, -1, &ec
);
2733 ulocdata_getMeasurementSystem(NULL
, &ec
);
2734 ulocdata_getPaperSize(NULL
, NULL
, NULL
, &ec
);
2735 if (ec
!= U_USELESS_COLLATOR_ERROR
) {
2736 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec
));
2742 UMeasurementSystem measureSys
;
2745 static const LocToMeasureSys locToMeasures
[] = {
2746 { "fr_FR", UMS_SI
},
2748 { "en_GB", UMS_UK
},
2749 { "fr_FR@rg=GBZZZZ", UMS_UK
},
2750 { "en@rg=frzzzz", UMS_SI
},
2751 { "en_GB@rg=USZZZZ", UMS_US
},
2752 { NULL
, (UMeasurementSystem
)0 } /* terminator */
2755 static void TestLocDataWithRgTag(void) {
2756 const LocToMeasureSys
* locToMeasurePtr
= locToMeasures
;
2757 for (; locToMeasurePtr
->locale
!= NULL
; locToMeasurePtr
++) {
2758 UErrorCode status
= U_ZERO_ERROR
;
2759 UMeasurementSystem measureSys
= ulocdata_getMeasurementSystem(locToMeasurePtr
->locale
, &status
);
2760 if (U_FAILURE(status
)) {
2761 log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
2762 locToMeasurePtr
->locale
, u_errorName(status
));
2763 } else if (measureSys
!= locToMeasurePtr
->measureSys
) {
2764 log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
2765 locToMeasurePtr
->locale
, (int) locToMeasurePtr
->measureSys
, (int)measureSys
);
2770 static void TestLanguageExemplarsFallbacks(void) {
2771 /* Test that en_US fallsback, but en doesn't fallback. */
2772 UErrorCode ec
= U_ZERO_ERROR
;
2773 ULocaleData
*uld
= ulocdata_open("en_US",&ec
);
2774 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2775 if (ec
!= U_USING_FALLBACK_WARNING
) {
2776 log_err_status(ec
, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2779 ulocdata_close(uld
);
2781 uld
= ulocdata_open("en",&ec
);
2782 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2783 if (ec
!= U_ZERO_ERROR
) {
2784 log_err_status(ec
, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2787 ulocdata_close(uld
);
2790 static const char *acceptResult(UAcceptResult uar
) {
2791 return udbg_enumName(UDBG_UAcceptResult
, uar
);
2794 static void TestAcceptLanguage(void) {
2795 UErrorCode status
= U_ZERO_ERROR
;
2796 UAcceptResult outResult
;
2797 UEnumeration
*available
;
2803 int32_t httpSet
; /**< Which of http[] should be used? */
2804 const char *icuSet
; /**< ? */
2805 const char *expect
; /**< The expected locale result */
2806 UAcceptResult res
; /**< The expected error code */
2808 /*0*/{ 0, NULL
, "mt_MT", ULOC_ACCEPT_VALID
},
2809 /*1*/{ 1, NULL
, "en", ULOC_ACCEPT_VALID
},
2810 /*2*/{ 2, NULL
, "en", ULOC_ACCEPT_FALLBACK
},
2811 /*3*/{ 3, NULL
, "", ULOC_ACCEPT_FAILED
},
2812 /*4*/{ 4, NULL
, "es", ULOC_ACCEPT_VALID
},
2814 /*5*/{ 5, NULL
, "en", ULOC_ACCEPT_VALID
}, /* XF */
2815 /*6*/{ 6, NULL
, "ja", ULOC_ACCEPT_FALLBACK
}, /* XF */
2816 /*7*/{ 7, NULL
, "zh", ULOC_ACCEPT_FALLBACK
}, /* XF */
2818 const int32_t numTests
= UPRV_LENGTHOF(tests
);
2819 static const char *http
[] = {
2820 /*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",
2821 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2822 /*2*/ "en-wf, de-lx;q=0.8",
2823 /*3*/ "mga-ie;q=0.9, tlh",
2824 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2825 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2826 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2827 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2828 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2829 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2830 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2833 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2835 /*7*/ "zh-xx;q=0.9",
2838 for(i
=0;i
<numTests
;i
++) {
2840 status
=U_ZERO_ERROR
;
2841 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2842 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2844 available
= ures_openAvailableLocales(tests
[i
].icuSet
, &status
);
2846 rc
= uloc_acceptLanguageFromHTTP(tmp
, 199, &outResult
, http
[tests
[i
].httpSet
], available
, &status
);
2847 (void)rc
; /* Suppress set but not used warning. */
2848 uenum_close(available
);
2849 log_verbose(" got %s, %s [%s]\n", tmp
[0]?tmp
:"(EMPTY)", acceptResult(outResult
), u_errorName(status
));
2850 if(outResult
!= tests
[i
].res
) {
2851 log_err_status(status
, "FAIL: #%d: expected outResult of %s but got %s\n", i
,
2852 acceptResult( tests
[i
].res
),
2853 acceptResult( outResult
));
2854 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2855 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
,acceptResult(tests
[i
].res
));
2857 if((outResult
>0)&&uprv_strcmp(tmp
, tests
[i
].expect
)) {
2858 log_err_status(status
, "FAIL: #%d: expected %s but got %s\n", i
, tests
[i
].expect
, tmp
);
2859 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2860 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2865 static const char* LOCALE_ALIAS
[][2] = {
2879 static UBool
isLocaleAvailable(UResourceBundle
* resIndex
, const char* loc
){
2880 UErrorCode status
= U_ZERO_ERROR
;
2882 ures_getStringByKey(resIndex
, loc
,&len
, &status
);
2883 if(U_FAILURE(status
)){
2889 static void TestCalendar() {
2890 #if !UCONFIG_NO_FORMATTING
2892 UErrorCode status
= U_ZERO_ERROR
;
2893 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2894 if(U_FAILURE(status
)){
2895 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2898 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2899 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2900 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2901 UCalendar
* c1
= NULL
;
2902 UCalendar
* c2
= NULL
;
2904 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2905 const char* l1
= ucal_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2906 const char* l2
= ucal_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2908 if(!isLocaleAvailable(resIndex
, newLoc
)){
2911 c1
= ucal_open(NULL
, -1, oldLoc
, UCAL_GREGORIAN
, &status
);
2912 c2
= ucal_open(NULL
, -1, newLoc
, UCAL_GREGORIAN
, &status
);
2914 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0 || status
!=U_ZERO_ERROR
) {
2915 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2917 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1
, l2
);
2921 ures_close(resIndex
);
2925 static void TestDateFormat() {
2926 #if !UCONFIG_NO_FORMATTING
2928 UErrorCode status
= U_ZERO_ERROR
;
2929 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2930 if(U_FAILURE(status
)){
2931 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2934 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2935 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2936 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2937 UDateFormat
* df1
= NULL
;
2938 UDateFormat
* df2
= NULL
;
2939 const char* l1
= NULL
;
2940 const char* l2
= NULL
;
2942 if(!isLocaleAvailable(resIndex
, newLoc
)){
2945 df1
= udat_open(UDAT_FULL
, UDAT_FULL
,oldLoc
, NULL
, 0, NULL
, -1, &status
);
2946 df2
= udat_open(UDAT_FULL
, UDAT_FULL
,newLoc
, NULL
, 0, NULL
, -1, &status
);
2947 if(U_FAILURE(status
)){
2948 log_err("Creation of date format failed %s\n", u_errorName(status
));
2951 /*Test function "getLocale"*/
2952 l1
= udat_getLocaleByType(df1
, ULOC_VALID_LOCALE
, &status
);
2953 l2
= udat_getLocaleByType(df2
, ULOC_VALID_LOCALE
, &status
);
2954 if(U_FAILURE(status
)){
2955 log_err("Fetching the locale by type failed. %s\n", u_errorName(status
));
2957 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
2958 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2960 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1
, l2
);
2964 ures_close(resIndex
);
2968 static void TestCollation() {
2969 #if !UCONFIG_NO_COLLATION
2971 UErrorCode status
= U_ZERO_ERROR
;
2972 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2973 if(U_FAILURE(status
)){
2974 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2977 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2978 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2979 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2980 UCollator
* c1
= NULL
;
2981 UCollator
* c2
= NULL
;
2982 const char* l1
= NULL
;
2983 const char* l2
= NULL
;
2985 status
= U_ZERO_ERROR
;
2986 if(!isLocaleAvailable(resIndex
, newLoc
)){
2989 if(U_FAILURE(status
)){
2990 log_err("Creation of collators failed %s\n", u_errorName(status
));
2993 c1
= ucol_open(oldLoc
, &status
);
2994 c2
= ucol_open(newLoc
, &status
);
2995 l1
= ucol_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2996 l2
= ucol_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2997 if(U_FAILURE(status
)){
2998 log_err("Fetching the locale names failed failed %s\n", u_errorName(status
));
3000 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
3001 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3003 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1
, l2
);
3007 ures_close(resIndex
);
3011 typedef struct OrientationStructTag
{
3012 const char* localeId
;
3013 ULayoutType character
;
3015 } OrientationStruct
;
3017 static const char* ULayoutTypeToString(ULayoutType type
)
3021 case ULOC_LAYOUT_LTR
:
3022 return "ULOC_LAYOUT_LTR";
3024 case ULOC_LAYOUT_RTL
:
3025 return "ULOC_LAYOUT_RTL";
3027 case ULOC_LAYOUT_TTB
:
3028 return "ULOC_LAYOUT_TTB";
3030 case ULOC_LAYOUT_BTT
:
3031 return "ULOC_LAYOUT_BTT";
3033 case ULOC_LAYOUT_UNKNOWN
:
3037 return "Unknown enum value for ULayoutType!";
3040 static void TestOrientation()
3042 static const OrientationStruct toTest
[] = {
3043 { "ar", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3044 { "aR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3045 { "ar_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3046 { "fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3047 { "Fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3048 { "he", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3049 { "ps", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3050 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3051 { "UR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
3052 { "en", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
}
3056 for (; i
< UPRV_LENGTHOF(toTest
); ++i
) {
3057 UErrorCode statusCO
= U_ZERO_ERROR
;
3058 UErrorCode statusLO
= U_ZERO_ERROR
;
3059 const char* const localeId
= toTest
[i
].localeId
;
3060 const ULayoutType co
= uloc_getCharacterOrientation(localeId
, &statusCO
);
3061 const ULayoutType expectedCO
= toTest
[i
].character
;
3062 const ULayoutType lo
= uloc_getLineOrientation(localeId
, &statusLO
);
3063 const ULayoutType expectedLO
= toTest
[i
].line
;
3064 if (U_FAILURE(statusCO
)) {
3065 log_err_status(statusCO
,
3066 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3068 u_errorName(statusCO
));
3070 else if (co
!= expectedCO
) {
3072 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3074 ULayoutTypeToString(expectedCO
),
3075 ULayoutTypeToString(co
));
3077 if (U_FAILURE(statusLO
)) {
3078 log_err_status(statusLO
,
3079 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3081 u_errorName(statusLO
));
3083 else if (lo
!= expectedLO
) {
3085 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3087 ULayoutTypeToString(expectedLO
),
3088 ULayoutTypeToString(lo
));
3093 static void TestULocale() {
3095 UErrorCode status
= U_ZERO_ERROR
;
3096 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3097 if(U_FAILURE(status
)){
3098 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3101 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3102 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3103 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3104 UChar name1
[256], name2
[256];
3105 char names1
[256], names2
[256];
3106 int32_t capacity
= 256;
3108 status
= U_ZERO_ERROR
;
3109 if(!isLocaleAvailable(resIndex
, newLoc
)){
3112 uloc_getDisplayName(oldLoc
, ULOC_US
, name1
, capacity
, &status
);
3113 if(U_FAILURE(status
)){
3114 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc
, u_errorName(status
));
3117 uloc_getDisplayName(newLoc
, ULOC_US
, name2
, capacity
, &status
);
3118 if(U_FAILURE(status
)){
3119 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc
, u_errorName(status
));
3122 if (u_strcmp(name1
, name2
)!=0) {
3123 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3125 u_austrcpy(names1
, name1
);
3126 u_austrcpy(names2
, name2
);
3127 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1
, names2
);
3129 ures_close(resIndex
);
3133 static void TestUResourceBundle() {
3137 UResourceBundle
* rb1
= NULL
;
3138 UResourceBundle
* rb2
= NULL
;
3139 UErrorCode status
= U_ZERO_ERROR
;
3141 UResourceBundle
*resIndex
= NULL
;
3142 if(U_FAILURE(status
)){
3143 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3146 resIndex
= ures_open(NULL
,"res_index", &status
);
3147 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3149 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3150 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3151 if(!isLocaleAvailable(resIndex
, newLoc
)){
3154 rb1
= ures_open(NULL
, oldLoc
, &status
);
3155 if (U_FAILURE(status
)) {
3156 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3159 us1
= ures_getLocaleByType(rb1
, ULOC_ACTUAL_LOCALE
, &status
);
3161 status
= U_ZERO_ERROR
;
3162 rb2
= ures_open(NULL
, newLoc
, &status
);
3163 if (U_FAILURE(status
)) {
3164 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3166 us2
= ures_getLocaleByType(rb2
, ULOC_ACTUAL_LOCALE
, &status
);
3168 if (strcmp(us1
,newLoc
)!=0 || strcmp(us1
,us2
)!=0 ) {
3169 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3172 log_verbose("ures_getStringByKey old:%s new:%s\n", us1
, us2
);
3178 ures_close(resIndex
);
3181 static void TestDisplayName() {
3183 UChar oldCountry
[256] = {'\0'};
3184 UChar newCountry
[256] = {'\0'};
3185 UChar oldLang
[256] = {'\0'};
3186 UChar newLang
[256] = {'\0'};
3187 char country
[256] ={'\0'};
3188 char language
[256] ={'\0'};
3189 int32_t capacity
= 256;
3192 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3193 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3194 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3195 UErrorCode status
= U_ZERO_ERROR
;
3196 int32_t available
= uloc_countAvailable();
3198 for(j
=0; j
<available
; j
++){
3200 const char* dispLoc
= uloc_getAvailable(j
);
3201 int32_t oldCountryLen
= uloc_getDisplayCountry(oldLoc
,dispLoc
, oldCountry
, capacity
, &status
);
3202 int32_t newCountryLen
= uloc_getDisplayCountry(newLoc
, dispLoc
, newCountry
, capacity
, &status
);
3203 int32_t oldLangLen
= uloc_getDisplayLanguage(oldLoc
, dispLoc
, oldLang
, capacity
, &status
);
3204 int32_t newLangLen
= uloc_getDisplayLanguage(newLoc
, dispLoc
, newLang
, capacity
, &status
);
3206 int32_t countryLen
= uloc_getCountry(newLoc
, country
, capacity
, &status
);
3207 int32_t langLen
= uloc_getLanguage(newLoc
, language
, capacity
, &status
);
3208 /* there is a display name for the current country ID */
3209 if(countryLen
!= newCountryLen
){
3210 if(u_strncmp(oldCountry
,newCountry
,oldCountryLen
)!=0){
3211 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc
, dispLoc
);
3214 /* there is a display name for the current lang ID */
3215 if(langLen
!=newLangLen
){
3216 if(u_strncmp(oldLang
,newLang
,oldLangLen
)){
3217 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc
, dispLoc
); }
3223 static void TestGetLocaleForLCID() {
3224 int32_t i
, length
, lengthPre
;
3225 const char* testLocale
= 0;
3226 UErrorCode status
= U_ZERO_ERROR
;
3227 char temp2
[40], temp3
[40];
3230 lcid
= uloc_getLCID("en_US");
3231 if (lcid
!= 0x0409) {
3232 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid
);
3235 lengthPre
= uloc_getLocaleForLCID(lcid
, temp2
, 4, &status
);
3236 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
3237 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status
));
3240 status
= U_ZERO_ERROR
;
3243 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3244 if (U_FAILURE(status
)) {
3245 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status
));
3246 status
= U_ZERO_ERROR
;
3249 if (length
!= lengthPre
) {
3250 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length
, lengthPre
);
3253 length
= uloc_getLocaleForLCID(0x12345, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3254 if (U_SUCCESS(status
)) {
3255 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2
, u_errorName(status
));
3257 status
= U_ZERO_ERROR
;
3259 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3260 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
3262 testLocale
=rawData2
[NAME
][i
];
3264 log_verbose("Testing %s ......\n", testLocale
);
3266 sscanf(rawData2
[LCID
][i
], "%x", &lcid
);
3267 length
= uloc_getLocaleForLCID(lcid
, temp2
, UPRV_LENGTHOF(temp2
), &status
);
3268 if (U_FAILURE(status
)) {
3269 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid
, u_errorName(status
));
3270 status
= U_ZERO_ERROR
;
3274 if (length
!= uprv_strlen(temp2
)) {
3275 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length
, lcid
, uprv_strlen(temp2
));
3278 /* Compare language, country, script */
3279 length
= uloc_getLanguage(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3280 if (U_FAILURE(status
)) {
3281 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3282 status
= U_ZERO_ERROR
;
3284 else if (uprv_strcmp(temp3
, rawData2
[LANG
][i
]) && !(uprv_strcmp(temp3
, "nn") == 0 && uprv_strcmp(rawData2
[VAR
][i
], "NY") == 0)) {
3285 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[LANG
][i
], lcid
, temp2
);
3288 length
= uloc_getScript(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3289 if (U_FAILURE(status
)) {
3290 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3291 status
= U_ZERO_ERROR
;
3293 else if (uprv_strcmp(temp3
, rawData2
[SCRIPT
][i
])) {
3294 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[SCRIPT
][i
], lcid
, temp2
);
3297 length
= uloc_getCountry(temp2
, temp3
, UPRV_LENGTHOF(temp3
), &status
);
3298 if (U_FAILURE(status
)) {
3299 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3300 status
= U_ZERO_ERROR
;
3302 else if (uprv_strlen(rawData2
[CTRY
][i
]) && uprv_strcmp(temp3
, rawData2
[CTRY
][i
])) {
3303 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[CTRY
][i
], lcid
, temp2
);
3309 const char* const basic_maximize_data
[][2] = {
3354 "en_Latn_US_POSIX_1901"
3356 "en_Latn__POSIX_1901",
3357 "en_Latn_US_POSIX_1901"
3360 "en_Latn_US_POSIX_1901"
3363 "de_Latn_DE_POSIX_1901"
3368 "th@calendar=buddhist",
3369 "th_Thai_TH@calendar=buddhist"
3399 "de_Latn_DE_U_CO_PHONEBK"
3401 "de_Latn_u_co_phonebk",
3402 "de_Latn_DE_U_CO_PHONEBK"
3404 "de_Latn_DE_u_co_phonebk",
3405 "de_Latn_DE_U_CO_PHONEBK"
3409 const char* const basic_minimize_data
[][2] = {
3414 "en_Latn_US_POSIX_1901",
3417 "EN_Latn_US_POSIX_1901",
3420 "en_Zzzz_US_POSIX_1901",
3423 "de_Latn_DE_POSIX_1901",
3429 "en_Latn_US@calendar=gregorian",
3430 "en@calendar=gregorian"
3434 const char* const full_data
[][3] = {
3438 /* "REMOVE-LIKELY" */
4921 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
4922 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5504 "de@collation=phonebook",
5505 "de_Latn_DE@collation=phonebook",
5506 "de@collation=phonebook"
5510 typedef struct errorDataTag
{
5512 const char* expected
;
5517 const errorData maximizeErrors
[] = {
5521 U_ILLEGAL_ARGUMENT_ERROR
,
5525 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5527 U_ILLEGAL_ARGUMENT_ERROR
,
5531 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5533 U_ILLEGAL_ARGUMENT_ERROR
,
5537 "en_Latn_US_POSIX@currency=EURO",
5538 "en_Latn_US_POSIX@currency=EURO",
5539 U_BUFFER_OVERFLOW_ERROR
,
5543 "en_Latn_US_POSIX@currency=EURO",
5544 "en_Latn_US_POSIX@currency=EURO",
5545 U_STRING_NOT_TERMINATED_WARNING
,
5550 const errorData minimizeErrors
[] = {
5554 U_ILLEGAL_ARGUMENT_ERROR
,
5558 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5560 U_ILLEGAL_ARGUMENT_ERROR
,
5564 "en_Latn_US_POSIX@currency=EURO",
5565 "en__POSIX@currency=EURO",
5566 U_BUFFER_OVERFLOW_ERROR
,
5570 "en_Latn_US_POSIX@currency=EURO",
5571 "en__POSIX@currency=EURO",
5572 U_STRING_NOT_TERMINATED_WARNING
,
5577 static int32_t getExpectedReturnValue(const errorData
* data
)
5579 if (data
->uerror
== U_BUFFER_OVERFLOW_ERROR
||
5580 data
->uerror
== U_STRING_NOT_TERMINATED_WARNING
)
5582 return strlen(data
->expected
);
5590 static int32_t getBufferSize(const errorData
* data
, int32_t actualSize
)
5592 if (data
->expected
== NULL
)
5596 else if (data
->bufferSize
< 0)
5598 return strlen(data
->expected
) + 1;
5602 return data
->bufferSize
;
5606 static void TestLikelySubtags()
5608 char buffer
[ULOC_FULLNAME_CAPACITY
+ ULOC_KEYWORD_AND_VALUES_CAPACITY
+ 1];
5611 for (; i
< UPRV_LENGTHOF(basic_maximize_data
); ++i
)
5613 UErrorCode status
= U_ZERO_ERROR
;
5614 const char* const minimal
= basic_maximize_data
[i
][0];
5615 const char* const maximal
= basic_maximize_data
[i
][1];
5617 /* const int32_t length = */
5618 uloc_addLikelySubtags(
5623 if (U_FAILURE(status
)) {
5624 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal
, u_errorName(status
));
5625 status
= U_ZERO_ERROR
;
5627 else if (uprv_strlen(maximal
) == 0) {
5628 if (uprv_stricmp(minimal
, buffer
) != 0) {
5629 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5632 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5633 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal
, minimal
, buffer
);
5637 for (i
= 0; i
< UPRV_LENGTHOF(basic_minimize_data
); ++i
) {
5639 UErrorCode status
= U_ZERO_ERROR
;
5640 const char* const maximal
= basic_minimize_data
[i
][0];
5641 const char* const minimal
= basic_minimize_data
[i
][1];
5643 /* const int32_t length = */
5644 uloc_minimizeSubtags(
5650 if (U_FAILURE(status
)) {
5651 log_err_status(status
, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5652 status
= U_ZERO_ERROR
;
5654 else if (uprv_strlen(minimal
) == 0) {
5655 if (uprv_stricmp(maximal
, buffer
) != 0) {
5656 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5659 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5660 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5664 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
5666 UErrorCode status
= U_ZERO_ERROR
;
5667 const char* const minimal
= full_data
[i
][0];
5668 const char* const maximal
= full_data
[i
][1];
5670 /* const int32_t length = */
5671 uloc_addLikelySubtags(
5676 if (U_FAILURE(status
)) {
5677 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal
, u_errorName(status
));
5678 status
= U_ZERO_ERROR
;
5680 else if (uprv_strlen(maximal
) == 0) {
5681 if (uprv_stricmp(minimal
, buffer
) != 0) {
5682 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5685 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5686 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5690 for (i
= 0; i
< UPRV_LENGTHOF(full_data
); ++i
) {
5692 UErrorCode status
= U_ZERO_ERROR
;
5693 const char* const maximal
= full_data
[i
][1];
5694 const char* const minimal
= full_data
[i
][2];
5696 if (strlen(maximal
) > 0) {
5698 /* const int32_t length = */
5699 uloc_minimizeSubtags(
5705 if (U_FAILURE(status
)) {
5706 log_err_status(status
, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5707 status
= U_ZERO_ERROR
;
5709 else if (uprv_strlen(minimal
) == 0) {
5710 if (uprv_stricmp(maximal
, buffer
) != 0) {
5711 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5714 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5715 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5720 for (i
= 0; i
< UPRV_LENGTHOF(maximizeErrors
); ++i
) {
5722 UErrorCode status
= U_ZERO_ERROR
;
5723 const char* const minimal
= maximizeErrors
[i
].tag
;
5724 const char* const maximal
= maximizeErrors
[i
].expected
;
5725 const UErrorCode expectedStatus
= maximizeErrors
[i
].uerror
;
5726 const int32_t expectedLength
= getExpectedReturnValue(&maximizeErrors
[i
]);
5727 const int32_t bufferSize
= getBufferSize(&maximizeErrors
[i
], sizeof(buffer
));
5729 const int32_t length
=
5730 uloc_addLikelySubtags(
5736 if (status
== U_ZERO_ERROR
) {
5737 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal
, u_errorName(expectedStatus
));
5738 status
= U_ZERO_ERROR
;
5740 else if (status
!= expectedStatus
) {
5741 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
));
5743 else if (length
!= expectedLength
) {
5744 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal
, expectedLength
, length
);
5746 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5747 if (uprv_strnicmp(maximal
, buffer
, bufferSize
) != 0) {
5748 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5749 maximal
, minimal
, (int)sizeof(buffer
), buffer
);
5754 for (i
= 0; i
< UPRV_LENGTHOF(minimizeErrors
); ++i
) {
5756 UErrorCode status
= U_ZERO_ERROR
;
5757 const char* const maximal
= minimizeErrors
[i
].tag
;
5758 const char* const minimal
= minimizeErrors
[i
].expected
;
5759 const UErrorCode expectedStatus
= minimizeErrors
[i
].uerror
;
5760 const int32_t expectedLength
= getExpectedReturnValue(&minimizeErrors
[i
]);
5761 const int32_t bufferSize
= getBufferSize(&minimizeErrors
[i
], sizeof(buffer
));
5763 const int32_t length
=
5764 uloc_minimizeSubtags(
5770 if (status
== U_ZERO_ERROR
) {
5771 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal
, u_errorName(expectedStatus
));
5772 status
= U_ZERO_ERROR
;
5774 else if (status
!= expectedStatus
) {
5775 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
));
5777 else if (length
!= expectedLength
) {
5778 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal
, expectedLength
, length
);
5780 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5781 if (uprv_strnicmp(minimal
, buffer
, bufferSize
) != 0) {
5782 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5783 minimal
, maximal
, (int)sizeof(buffer
), buffer
);
5789 const char* const locale_to_langtag
[][3] = {
5792 {"en_US", "en-US", "en-US"},
5793 {"iw_IL", "he-IL", "he-IL"},
5794 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5795 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5796 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5797 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL
}, /* variant POSIX_VAR is processed as regular variant */
5798 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL
}, /* variant VAR_POSIX is processed as regular variant */
5799 {"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 */
5800 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5801 {"und_555", "und-555", "und-555"},
5802 {"123", "und", NULL
},
5803 {"%$#&", "und", NULL
},
5804 {"_Latn", "und-Latn", "und-Latn"},
5805 {"_DE", "und-DE", "und-DE"},
5806 {"und_FR", "und-FR", "und-FR"},
5807 {"th_TH_TH", "th-TH-x-lvariant-th", NULL
},
5808 {"bogus", "bogus", "bogus"},
5809 {"foooobarrr", "und", NULL
},
5810 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5811 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL
},
5812 {"en_US_1234", "en-US-1234", "en-US-1234"},
5813 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5814 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5815 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL
},
5816 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL
},
5817 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5818 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5819 {"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"},
5820 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5821 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5822 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL
},
5823 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL
},
5824 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5825 {"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"},
5826 {"@x=elmer", "x-elmer", "x-elmer"},
5827 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5828 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5829 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5833 static void TestToLanguageTag(void) {
5839 const char *expected
;
5841 for (i
= 0; locale_to_langtag
[i
][0] != NULL
; i
++) {
5842 inloc
= locale_to_langtag
[i
][0];
5844 /* testing non-strict mode */
5845 status
= U_ZERO_ERROR
;
5847 expected
= locale_to_langtag
[i
][1];
5849 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), FALSE
, &status
);
5850 (void)len
; /* Suppress set but not used warning. */
5851 if (U_FAILURE(status
)) {
5852 if (expected
!= NULL
) {
5853 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5854 inloc
, u_errorName(status
));
5857 if (expected
== NULL
) {
5858 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5860 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5861 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5862 langtag
, inloc
, expected
);
5866 /* testing strict mode */
5867 status
= U_ZERO_ERROR
;
5869 expected
= locale_to_langtag
[i
][2];
5871 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), TRUE
, &status
);
5872 if (U_FAILURE(status
)) {
5873 if (expected
!= NULL
) {
5874 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5875 inloc
, u_errorName(status
));
5878 if (expected
== NULL
) {
5879 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5881 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5882 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5883 langtag
, inloc
, expected
);
5889 #define FULL_LENGTH -1
5890 static const struct {
5894 } langtag_to_locale
[] = {
5895 {"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
},
5896 {"en", "en", FULL_LENGTH
},
5897 {"en-us", "en_US", FULL_LENGTH
},
5898 {"und-US", "_US", FULL_LENGTH
},
5899 {"und-latn", "_Latn", FULL_LENGTH
},
5900 {"en-US-posix", "en_US_POSIX", FULL_LENGTH
},
5901 {"de-de_euro", "de", 2},
5902 {"kok-IN", "kok_IN", FULL_LENGTH
},
5905 {"en-latn-x", "en_Latn", 7},
5906 {"art-lojban", "jbo", FULL_LENGTH
},
5907 {"zh-hakka", "hak", FULL_LENGTH
},
5908 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH
},
5909 {"xxx-yy", "xxx_YY", FULL_LENGTH
},
5910 {"fr-234", "fr_234", FULL_LENGTH
},
5911 {"i-default", "en@x=i-default", FULL_LENGTH
},
5913 {"ja-jp-jp", "ja_JP", 5},
5914 {"bogus", "bogus", FULL_LENGTH
},
5915 {"boguslang", "", 0},
5916 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH
},
5917 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH
},
5918 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5919 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH
},
5920 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH
},
5921 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH
},
5922 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH
},
5923 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH
},
5924 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH
},
5925 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH
},
5926 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH
},
5927 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH
},
5928 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH
},
5929 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH
},
5930 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH
},
5931 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH
},
5932 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH
},
5933 {"x-elmer", "@x=elmer", FULL_LENGTH
},
5934 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH
},
5935 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH
},
5936 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH
},
5937 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH
},
5938 {"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
},
5940 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5941 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
5945 static void TestForLanguageTag(void) {
5950 int32_t expParsedLen
;
5952 for (i
= 0; langtag_to_locale
[i
].bcpID
!= NULL
; i
++) {
5953 status
= U_ZERO_ERROR
;
5955 expParsedLen
= langtag_to_locale
[i
].len
;
5956 if (expParsedLen
== FULL_LENGTH
) {
5957 expParsedLen
= uprv_strlen(langtag_to_locale
[i
].bcpID
);
5959 uloc_forLanguageTag(langtag_to_locale
[i
].bcpID
, locale
, sizeof(locale
), &parsedLen
, &status
);
5960 if (U_FAILURE(status
)) {
5961 log_err_status(status
, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5962 langtag_to_locale
[i
].bcpID
, u_errorName(status
));
5964 if (uprv_strcmp(langtag_to_locale
[i
].locID
, locale
) != 0) {
5965 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5966 locale
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].locID
);
5968 if (parsedLen
!= expParsedLen
) {
5969 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5970 parsedLen
, langtag_to_locale
[i
].bcpID
, expParsedLen
);
5976 static void TestToUnicodeLocaleKey(void)
5978 /* $IN specifies the result should be the input pointer itself */
5979 static const char* DATA
[][2] = {
5981 {"CALEndar", "ca"}, /* difference casing */
5982 {"ca", "ca"}, /* bcp key itself */
5983 {"kv", "kv"}, /* no difference between legacy and bcp */
5984 {"foo", NULL
}, /* unknown, bcp ill-formed */
5985 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
5990 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
5991 const char* keyword
= DATA
[i
][0];
5992 const char* expected
= DATA
[i
][1];
5993 const char* bcpKey
= NULL
;
5995 bcpKey
= uloc_toUnicodeLocaleKey(keyword
);
5996 if (expected
== NULL
) {
5997 if (bcpKey
!= NULL
) {
5998 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword
, bcpKey
);
6000 } else if (bcpKey
== NULL
) {
6001 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6002 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6003 if (bcpKey
!= keyword
) {
6004 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, bcpKey
, keyword
);
6006 } else if (uprv_strcmp(bcpKey
, expected
) != 0) {
6007 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword
, bcpKey
, expected
);
6012 static void TestToLegacyKey(void)
6014 /* $IN specifies the result should be the input pointer itself */
6015 static const char* DATA
[][2] = {
6016 {"kb", "colbackwards"},
6017 {"kB", "colbackwards"}, /* different casing */
6018 {"Collation", "collation"}, /* keyword itself with different casing */
6019 {"kv", "kv"}, /* no difference between legacy and bcp */
6020 {"foo", "$IN"}, /* unknown, bcp ill-formed */
6021 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
6022 {"e=mc2", NULL
}, /* unknown, bcp/legacy ill-formed */
6027 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6028 const char* keyword
= DATA
[i
][0];
6029 const char* expected
= DATA
[i
][1];
6030 const char* legacyKey
= NULL
;
6032 legacyKey
= uloc_toLegacyKey(keyword
);
6033 if (expected
== NULL
) {
6034 if (legacyKey
!= NULL
) {
6035 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword
, legacyKey
);
6037 } else if (legacyKey
== NULL
) {
6038 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
6039 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6040 if (legacyKey
!= keyword
) {
6041 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, legacyKey
, keyword
);
6043 } else if (uprv_strcmp(legacyKey
, expected
) != 0) {
6044 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword
, legacyKey
, expected
);
6049 static void TestToUnicodeLocaleType(void)
6051 /* $IN specifies the result should be the input pointer itself */
6052 static const char* DATA
[][3] = {
6053 {"tz", "Asia/Kolkata", "inccu"},
6054 {"calendar", "gregorian", "gregory"},
6055 {"ca", "gregorian", "gregory"},
6056 {"ca", "Gregorian", "gregory"},
6057 {"ca", "buddhist", "buddhist"},
6058 {"Calendar", "Japanese", "japanese"},
6059 {"calendar", "Islamic-Civil", "islamic-civil"},
6060 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6061 {"colalternate", "NON-IGNORABLE", "noignore"},
6062 {"colcaselevel", "yes", "true"},
6063 {"rg", "GBzzzz", "$IN"},
6064 {"tz", "america/new_york", "usnyc"},
6065 {"tz", "Asia/Kolkata", "inccu"},
6066 {"timezone", "navajo", "usden"},
6067 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
6068 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6069 {"zz", "gregorian", NULL
}, /* unknown key, ill-formed type */
6070 {"co", "foo-", NULL
}, /* unknown type, ill-formed type */
6071 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6072 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6073 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6074 {"kr", "digit-spacepunct", NULL
}, /* invalid (bcp ill-formed) reordercode type */
6079 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6080 const char* keyword
= DATA
[i
][0];
6081 const char* value
= DATA
[i
][1];
6082 const char* expected
= DATA
[i
][2];
6083 const char* bcpType
= NULL
;
6085 bcpType
= uloc_toUnicodeLocaleType(keyword
, value
);
6086 if (expected
== NULL
) {
6087 if (bcpType
!= NULL
) {
6088 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, bcpType
);
6090 } else if (bcpType
== NULL
) {
6091 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6092 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6093 if (bcpType
!= value
) {
6094 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, bcpType
, value
);
6096 } else if (uprv_strcmp(bcpType
, expected
) != 0) {
6097 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, bcpType
, expected
);
6102 static void TestToLegacyType(void)
6104 /* $IN specifies the result should be the input pointer itself */
6105 static const char* DATA
[][3] = {
6106 {"calendar", "gregory", "gregorian"},
6107 {"ca", "gregory", "gregorian"},
6108 {"ca", "Gregory", "gregorian"},
6109 {"ca", "buddhist", "buddhist"},
6110 {"Calendar", "Japanese", "japanese"},
6111 {"calendar", "Islamic-Civil", "islamic-civil"},
6112 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6113 {"colalternate", "noignore", "non-ignorable"},
6114 {"colcaselevel", "true", "yes"},
6115 {"rg", "gbzzzz", "gbzzzz"},
6116 {"tz", "usnyc", "America/New_York"},
6117 {"tz", "inccu", "Asia/Calcutta"},
6118 {"timezone", "usden", "America/Denver"},
6119 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6120 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6121 {"ca", "aaaa", "$IN"}, /* unknown type */
6122 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6123 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6124 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6125 {"co", "e=mc2", NULL
}, /* known key, ill-formed bcp/legacy type */
6126 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6127 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6128 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6129 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6134 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6135 const char* keyword
= DATA
[i
][0];
6136 const char* value
= DATA
[i
][1];
6137 const char* expected
= DATA
[i
][2];
6138 const char* legacyType
= NULL
;
6140 legacyType
= uloc_toLegacyType(keyword
, value
);
6141 if (expected
== NULL
) {
6142 if (legacyType
!= NULL
) {
6143 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, legacyType
);
6145 } else if (legacyType
== NULL
) {
6146 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6147 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6148 if (legacyType
!= value
) {
6149 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, legacyType
, value
);
6151 } else if (uprv_strcmp(legacyType
, expected
) != 0) {
6152 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, legacyType
, expected
);
6159 static void test_unicode_define(const char *namech
, char ch
, const char *nameu
, UChar uch
)
6163 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech
, ch
,(int)ch
, nameu
, (int) uch
);
6164 u_charsToUChars(&ch
, asUch
, 1);
6165 if(asUch
[0] != uch
) {
6166 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
);
6168 log_verbose(" .. OK, == U+%04X\n", (int)asUch
[0]);
6172 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6174 static void TestUnicodeDefines(void) {
6175 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR
, ULOC_KEYWORD_SEPARATOR_UNICODE
);
6176 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN
, ULOC_KEYWORD_ASSIGN_UNICODE
);
6177 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR
, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE
);
6180 static void TestIsRightToLeft() {
6181 // API test only. More test cases in intltest/LocaleTest.
6182 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6183 log_err("uloc_isRightToLeft() failed");
6187 typedef enum UldnNameType
{
6195 const char * localeToName
; // NULL to terminate a list of these
6196 UldnNameType nameType
;
6197 const char * expectResult
;
6201 const char * displayLocale
;
6202 const UDisplayContext
* displayOptions
; // set of 3 UDisplayContext items
6203 const UldnItem
* testItems
;
6207 static const UDisplayContext optStdMidLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6208 static const UDisplayContext optStdMidShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6209 static const UDisplayContext optDiaMidLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6210 static const UDisplayContext optDiaMidShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6212 static const UDisplayContext optStdBegLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6213 static const UDisplayContext optStdBegShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6214 static const UDisplayContext optDiaBegLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_FULL
};
6215 static const UDisplayContext optDiaBegShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
, UDISPCTX_LENGTH_SHORT
};
6217 static const UDisplayContext optStdLstLong
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6218 static const UDisplayContext optStdLstShrt
[3] = {UDISPCTX_STANDARD_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6219 static const UDisplayContext optDiaLstLong
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_FULL
};
6220 static const UDisplayContext optDiaLstShrt
[3] = {UDISPCTX_DIALECT_NAMES
, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
, UDISPCTX_LENGTH_SHORT
};
6222 static const UldnItem en_StdMidLong
[] = {
6223 { "en_US", TEST_ULDN_LOCALE
, "English (US)" },
6224 { "en_US_POSIX", TEST_ULDN_LOCALE
, "English (US, Computer)" },
6225 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, "English (US, Chinese Calendar)" },
6226 { "en_CA", TEST_ULDN_LOCALE
, "English (Canada)" },
6227 { "pt", TEST_ULDN_LOCALE
, "Portuguese" },
6228 { "pt_BR", TEST_ULDN_LOCALE
, "Portuguese (Brazil)" },
6229 { "pt_PT", TEST_ULDN_LOCALE
, "Portuguese (Portugal)" },
6230 { "zh_Hans", TEST_ULDN_LOCALE
, "Chinese (Simplified)" },
6231 { "zh_Hant_HK", TEST_ULDN_LOCALE
, "Chinese (Traditional, Hong Kong)" },
6232 { "zh_HK", TEST_ULDN_LOCALE
, "Chinese (Hong Kong)" },
6233 { "Latn", TEST_ULDN_SCRIPT
, "Latin" },
6234 { "Hans", TEST_ULDN_SCRIPT
, "Simplified Han" },
6235 { "Hant", TEST_ULDN_SCRIPT
, "Traditional Han" },
6236 { "US", TEST_ULDN_REGION
, "United States" },
6237 { "CA", TEST_ULDN_REGION
, "Canada" },
6238 { "GB", TEST_ULDN_REGION
, "United Kingdom" },
6239 { "HK", TEST_ULDN_REGION
, "Hong Kong (China)" },
6242 static const UldnItem en_StdMidShrt
[] = {
6243 { "en_US", TEST_ULDN_LOCALE
, "English (US)" },
6244 { "en_US_POSIX", TEST_ULDN_LOCALE
, "English (US, Computer)" },
6245 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, "English (US, Calendar: chinese)" },
6246 { "en_CA", TEST_ULDN_LOCALE
, "English (Canada)" },
6247 { "pt", TEST_ULDN_LOCALE
, "Portuguese" },
6248 { "pt_BR", TEST_ULDN_LOCALE
, "Portuguese (Brazil)" },
6249 { "pt_PT", TEST_ULDN_LOCALE
, "Portuguese (Portugal)" },
6250 { "zh_Hans", TEST_ULDN_LOCALE
, "Chinese (Simplified)" },
6251 { "zh_Hant_HK", TEST_ULDN_LOCALE
, "Chinese (Traditional, Hong Kong)" },
6252 { "zh_HK", TEST_ULDN_LOCALE
, "Chinese (Hong Kong)" },
6253 { "Latn", TEST_ULDN_SCRIPT
, "Latin" },
6254 { "Hans", TEST_ULDN_SCRIPT
, "Simplified Han" },
6255 { "Hant", TEST_ULDN_SCRIPT
, "Traditional Han" },
6256 { "US", TEST_ULDN_REGION
, "US" },
6257 { "CA", TEST_ULDN_REGION
, "Canada" },
6258 { "GB", TEST_ULDN_REGION
, "UK" },
6259 { "HK", TEST_ULDN_REGION
, "Hong Kong" },
6262 static const UldnItem en_DiaMidLong
[] = {
6263 { "en_US", TEST_ULDN_LOCALE
, "American English" },
6264 { "en_US_POSIX", TEST_ULDN_LOCALE
, "American English (Computer)" },
6265 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, "American English (Chinese Calendar)" },
6266 { "en_CA", TEST_ULDN_LOCALE
, "Canadian English" },
6267 { "pt", TEST_ULDN_LOCALE
, "Portuguese" },
6268 { "pt_BR", TEST_ULDN_LOCALE
, "Brazilian Portuguese" },
6269 { "pt_PT", TEST_ULDN_LOCALE
, "European Portuguese" },
6270 { "zh_Hans", TEST_ULDN_LOCALE
, "Simplified Chinese" },
6271 { "zh_Hant_HK", TEST_ULDN_LOCALE
, "Traditional Chinese (Hong Kong)" },
6272 { "zh_HK", TEST_ULDN_LOCALE
, "Chinese (Hong Kong)" },
6273 { "Latn", TEST_ULDN_SCRIPT
, "Latin" },
6274 { "Hans", TEST_ULDN_SCRIPT
, "Simplified Han" },
6275 { "Hant", TEST_ULDN_SCRIPT
, "Traditional Han" },
6276 { "US", TEST_ULDN_REGION
, "United States" },
6277 { "CA", TEST_ULDN_REGION
, "Canada" },
6278 { "GB", TEST_ULDN_REGION
, "United Kingdom" },
6279 { "HK", TEST_ULDN_REGION
, "Hong Kong (China)" },
6282 static const UldnItem en_DiaMidShrt
[] = {
6283 { "en_US", TEST_ULDN_LOCALE
, "US English" },
6284 { "en_US_POSIX", TEST_ULDN_LOCALE
, "US English (Computer)" },
6285 { "en_US@calendar=chinese", TEST_ULDN_LOCALE
, "US English (Calendar: chinese)" },
6286 { "en_CA", TEST_ULDN_LOCALE
, "Canadian English" },
6287 { "pt", TEST_ULDN_LOCALE
, "Portuguese" },
6288 { "pt_BR", TEST_ULDN_LOCALE
, "Brazilian Portuguese" },
6289 { "pt_PT", TEST_ULDN_LOCALE
, "European Portuguese" },
6290 { "zh_Hans", TEST_ULDN_LOCALE
, "Simplified Chinese" },
6291 { "zh_Hant_HK", TEST_ULDN_LOCALE
, "Traditional Chinese (Hong Kong)" },
6292 { "zh_HK", TEST_ULDN_LOCALE
, "Chinese (Hong Kong)" },
6293 { "Latn", TEST_ULDN_SCRIPT
, "Latin" },
6294 { "Hans", TEST_ULDN_SCRIPT
, "Simplified Han" },
6295 { "Hant", TEST_ULDN_SCRIPT
, "Traditional Han" },
6296 { "US", TEST_ULDN_REGION
, "US" },
6297 { "CA", TEST_ULDN_REGION
, "Canada" },
6298 { "GB", TEST_ULDN_REGION
, "UK" },
6299 { "HK", TEST_ULDN_REGION
, "Hong Kong" },
6302 static const UldnItem fr_StdMidLong
[] = {
6303 { "en_US", TEST_ULDN_LOCALE
, "anglais (\\u00C9.-U.)" },
6304 { "US", TEST_ULDN_REGION
, "\\u00C9tats-Unis" },
6305 { "HK", TEST_ULDN_REGION
, "R.A.S. chinoise de Hong Kong" },
6308 static const UldnItem fr_StdMidShrt
[] = {
6309 { "en_US", TEST_ULDN_LOCALE
, "anglais (\\u00C9.-U.)" },
6310 { "US", TEST_ULDN_REGION
, "\\u00C9.-U." },
6311 { "HK", TEST_ULDN_REGION
, "Hong Kong" },
6314 static const UldnItem fr_StdBegLong
[] = {
6315 { "en_US", TEST_ULDN_LOCALE
, "Anglais (\\u00C9.-U.)" },
6318 static const UldnItem fr_StdLstLong
[] = {
6319 { "en_US", TEST_ULDN_LOCALE
, "Anglais (\\u00C9.-U.)" },
6322 static const UldnItem fr_DiaMidLong
[] = {
6323 { "en_US", TEST_ULDN_LOCALE
, "anglais am\\u00E9ricain" },
6326 static const UldnLocAndOpts uldnLocAndOpts
[] = {
6327 { "en", optStdMidLong
, en_StdMidLong
, UPRV_LENGTHOF(en_StdMidLong
) },
6328 { "en", optStdMidShrt
, en_StdMidShrt
, UPRV_LENGTHOF(en_StdMidShrt
) },
6329 { "en", optDiaMidLong
, en_DiaMidLong
, UPRV_LENGTHOF(en_DiaMidLong
) },
6330 { "en", optDiaMidShrt
, en_DiaMidShrt
, UPRV_LENGTHOF(en_DiaMidShrt
) },
6331 { "fr", optStdMidLong
, fr_StdMidLong
, UPRV_LENGTHOF(fr_StdMidLong
) },
6332 { "fr", optStdMidShrt
, fr_StdMidShrt
, UPRV_LENGTHOF(fr_StdMidShrt
) },
6333 { "fr", optStdBegLong
, fr_StdBegLong
, UPRV_LENGTHOF(fr_StdBegLong
) },
6334 { "fr", optStdLstLong
, fr_StdLstLong
, UPRV_LENGTHOF(fr_StdLstLong
) },
6335 { "fr", optDiaMidLong
, fr_DiaMidLong
, UPRV_LENGTHOF(fr_DiaMidLong
) },
6336 { NULL
, NULL
, NULL
, 0 }
6339 enum { kUNameBuf
= 128, kBNameBuf
= 256 };
6341 static void TestUldnNameVariants() {
6342 const UldnLocAndOpts
* uloPtr
;
6343 for (uloPtr
= uldnLocAndOpts
; uloPtr
->displayLocale
!= NULL
; uloPtr
++) {
6344 UErrorCode status
= U_ZERO_ERROR
;
6345 ULocaleDisplayNames
* uldn
= uldn_openForContext(uloPtr
->displayLocale
, (UDisplayContext
*)uloPtr
->displayOptions
, 3, &status
);
6346 if (U_FAILURE(status
)) {
6347 log_data_err("uldn_openForContext fails, displayLocale %s, contexts %03X %03X %03X: %s - Are you missing data?\n",
6348 uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
6349 u_errorName(status
) );
6352 const UldnItem
* itemPtr
= uloPtr
->testItems
;
6353 int32_t itemCount
= uloPtr
->countItems
;
6354 for (; itemCount
-- > 0; itemPtr
++) {
6355 UChar uget
[kUNameBuf
], uexp
[kUNameBuf
];
6356 int32_t ulenget
, ulenexp
;
6357 const char* typeString
;
6359 status
= U_ZERO_ERROR
;
6360 switch (itemPtr
->nameType
) {
6361 case TEST_ULDN_LOCALE
:
6362 ulenget
= uldn_localeDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
6363 typeString
= "locale";
6365 case TEST_ULDN_LANGUAGE
:
6366 ulenget
= uldn_languageDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
6367 typeString
= "language";
6369 case TEST_ULDN_SCRIPT
:
6370 ulenget
= uldn_scriptDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
6371 typeString
= "script";
6373 case TEST_ULDN_REGION
:
6374 ulenget
= uldn_regionDisplayName(uldn
, itemPtr
->localeToName
, uget
, kUNameBuf
, &status
);
6375 typeString
= "region";
6380 if (U_FAILURE(status
)) {
6381 log_data_err("uldn_%sDisplayName fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s: %s\n",
6382 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
6383 itemPtr
->localeToName
, u_errorName(status
) );
6386 ulenexp
= u_unescape(itemPtr
->expectResult
, uexp
, kUNameBuf
);
6387 if (ulenget
!= ulenexp
|| u_strncmp(uget
, uexp
, ulenexp
) != 0) {
6388 char bexp
[kBNameBuf
], bget
[kBNameBuf
];
6389 u_strToUTF8(bexp
, kBNameBuf
, NULL
, uexp
, ulenexp
, &status
);
6390 u_strToUTF8(bget
, kBNameBuf
, NULL
, uget
, ulenget
, &status
);
6391 log_data_err("uldn_%sDisplayName fails, displayLocale %s, contexts %03X %03X %03X, localeToName %s:\n expect %2d: %s\n get %2d: %s\n",
6392 typeString
, uloPtr
->displayLocale
, uloPtr
->displayOptions
[0], uloPtr
->displayOptions
[1], uloPtr
->displayOptions
[2],
6393 itemPtr
->localeToName
, ulenexp
, bexp
, ulenget
, bget
);
6401 /* Apple-specific, test for Apple-specific function ualoc_getAppleParent */
6402 static const char* localesAndAppleParent
[] = {
6462 "zh_HK", "zh_Hant_HK",
6463 "zh-HK", "zh_Hant_HK",
6465 "zh-Hant-HK", "zh_Hant",
6466 "zh_Hant_HK", "zh_Hant",
6467 "zh-Hant-MO", "zh_Hant_HK",
6468 "zh-Hans-HK", "zh_Hans",
6471 "en-Latn-US", "en_Latn",
6472 "en_US_POSIX", "en_US",
6473 "en_Latn_US_POSIX", "en_Latn_US",
6474 "en-u-ca-hebrew", "root",
6475 "en@calendar=hebrew", "root",
6476 "en_@calendar=hebrew", "root",
6479 "Default@2x", "root",
6481 NULL
/* terminator */
6484 static void TestGetAppleParent() {
6485 const char **localesPtr
= localesAndAppleParent
;
6486 const char * locale
;
6487 while ((locale
= *localesPtr
++) != NULL
) {
6488 const char * expectParent
= *localesPtr
++;
6489 UErrorCode status
= U_ZERO_ERROR
;
6490 char getParent
[ULOC_FULLNAME_CAPACITY
];
6491 int32_t plen
= ualoc_getAppleParent(locale
, getParent
, ULOC_FULLNAME_CAPACITY
, &status
);
6492 if (U_FAILURE(status
)) {
6493 log_err("FAIL: ualoc_getAppleParent input \"%s\", status %s\n", locale
, u_errorName(status
));
6494 } else if (uprv_strcmp(expectParent
, getParent
) != 0) {
6495 log_err("FAIL: ualoc_getAppleParent input \"%s\", expected parent \"%s\", got parent \"%s\"\n", locale
, expectParent
, getParent
);
6500 /* Apple-specific, test for Apple-specific function ualoc_getLanguagesForRegion */
6501 enum { kUALanguageEntryMax
= 10 };
6503 static void TestGetLanguagesForRegion() {
6504 UALanguageEntry entries
[kUALanguageEntryMax
];
6507 const char * region
;
6509 status
= U_ZERO_ERROR
;
6511 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
6512 if (U_FAILURE(status
)) {
6513 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6515 // Expect approximately:
6516 // zh_Hans 0.90 UALANGSTATUS_OFFICIAL
6519 // yue 0.043 Yue including Cantonese
6524 // ug_Arab 0.0055 Uighur UALANGSTATUS_REGIONAL_OFFICIAL
6525 // ...at least 4 more with fractions >= 0.001
6526 if (entryCount
< kUALanguageEntryMax
) {
6527 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6529 UALanguageEntry
* entryPtr
= entries
;
6530 if (uprv_strcmp(entryPtr
->languageCode
, "zh_Hans") != 0 || entryPtr
->userFraction
< 0.8 || entryPtr
->userFraction
> 1.0 || entryPtr
->status
!= UALANGSTATUS_OFFICIAL
) {
6531 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entryPtr
->languageCode
, entryPtr
->userFraction
, (int)entryPtr
->status
);
6533 for (entryPtr
++; entryPtr
< entries
+ kUALanguageEntryMax
&& uprv_strcmp(entryPtr
->languageCode
, "ug_Arab") != 0; entryPtr
++)
6535 if (entryPtr
< entries
+ kUALanguageEntryMax
) {
6536 // we found ug_Arab, make sure it has correct status
6537 if (entryPtr
->status
!= UALANGSTATUS_REGIONAL_OFFICIAL
) {
6538 log_err("FAIL: ualoc_getLanguagesForRegion %s, ug_Arab had incorrect status %d\n", (int)entryPtr
->status
);
6541 // did not find ug_Arab
6542 log_err("FAIL: ualoc_getLanguagesForRegion %s, entries did not include ug_Arab\n", region
);
6547 status
= U_ZERO_ERROR
;
6549 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
6550 if (U_FAILURE(status
)) {
6551 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6553 // Expect approximately:
6554 // en 0.85 UALANGSTATUS_OFFICIAL
6555 // fr 0.22 UALANGSTATUS_OFFICIAL
6557 if (entryCount
< 2) {
6558 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6560 if (uprv_strcmp(entries
[0].languageCode
, "en") != 0 || entries
[0].userFraction
< 0.7 || entries
[0].userFraction
> 1.0 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
6561 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
6563 if (uprv_strcmp(entries
[1].languageCode
, "fr") != 0 || entries
[1].userFraction
< 0.1 || entries
[1].userFraction
> 1.0 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
6564 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
6569 status
= U_ZERO_ERROR
;
6571 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, NULL
, 0, &status
);
6572 if (U_FAILURE(status
)) {
6573 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6575 if (entryCount
< 40) {
6576 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6581 /* data for TestAppleLocalizationsToUse */
6584 const char * const *locs
;
6586 } AppleLocsAndCount
;
6588 enum { kNumLocSets
= 6 };
6591 const char * language
;
6592 const char ** expLocsForSets
[kNumLocSets
];
6596 static const char * appleLocs1
[] = {
6630 static const char * appleLocs2
[] = {
6637 "en", "en_AU", "en_GB",
6661 "zh_CN", "zh_HK", "zh_TW",
6664 static const char * appleLocs3
[] = {
6671 "en", "en_AU", "en_CA", "en_GB",
6674 "fr", "fr_CA", "fr_FR",
6686 "pt", "pt_BR", "pt_PT",
6695 "zh_CN", "zh_HK", "zh_MO", "zh_TW",
6698 static const char * appleLocs4
[] = {
6699 "en", "en_AU", "en_CA", "en_GB", "en_IN", "en_US",
6700 "es", "es_419", "es_MX",
6701 "fr", "fr_CA", "fr_CH", "fr_FR",
6702 "nl", "nl_BE", "nl_NL",
6704 "ro", "ro_MD", "ro_RO",
6705 "zh_Hans", "zh_Hant", "zh_Hant_HK",
6708 static const char * appleLocs5
[] = {
6709 "en", "en_001", "en_AU", "en_GB",
6710 "es", "es_ES", "es_MX",
6711 "zh_CN", "zh_Hans", "zh_Hant", "zh_TW",
6721 static const char * appleLocs6
[] = {
6722 "en", "en_001", "en_150", "en_AU", "en_GB",
6723 "es", "es_419", "es_ES", "es_MX",
6724 "zh_CN", "zh_Hans", "zh_Hant", "zh_Hant_HK", "zh_HK", "zh_TW",
6731 static const AppleLocsAndCount locAndCountEntries
[kNumLocSets
] = {
6732 { appleLocs1
, UPRV_LENGTHOF(appleLocs1
) },
6733 { appleLocs2
, UPRV_LENGTHOF(appleLocs2
) },
6734 { appleLocs3
, UPRV_LENGTHOF(appleLocs3
) },
6735 { appleLocs4
, UPRV_LENGTHOF(appleLocs4
) },
6736 { appleLocs5
, UPRV_LENGTHOF(appleLocs5
) },
6737 { appleLocs6
, UPRV_LENGTHOF(appleLocs6
) },
6741 static const char* l1_ar
[] = { "ar", NULL
};
6742 static const char* l1_Ara
[] = { "Arabic", NULL
};
6743 static const char* l1_ca
[] = { "ca", NULL
};
6744 static const char* l1_cs
[] = { "cs", NULL
};
6745 static const char* l1_da
[] = { "da", NULL
};
6746 static const char* l1_Dan
[] = { "Danish", NULL
};
6747 static const char* l1_de
[] = { "de", NULL
};
6748 static const char* l1_Ger
[] = { "German", NULL
};
6749 static const char* l1_el
[] = { "el", NULL
};
6750 static const char* l1_en
[] = { "en", NULL
};
6751 static const char* l1_Eng
[] = { "English", NULL
};
6752 static const char* l2_en_001_
[] = { "en_001", "en", NULL
};
6753 static const char* l2_en_CA_
[] = { "en_CA", "en", NULL
};
6754 static const char* l2_en_GB_
[] = { "en_GB", "en", NULL
};
6755 static const char* l2_en_US_
[] = { "en_US", "en", NULL
};
6756 static const char* l2_en_GB_Eng
[] = { "en_GB", "English", NULL
};
6757 static const char* l3_en_GB001_
[] = { "en_GB", "en_001", "en", NULL
};
6758 static const char* l3_en_AUGB_
[] = { "en_AU", "en_GB", "en", NULL
};
6759 static const char* l3_en_INGB_
[] = { "en_IN", "en_GB", "en", NULL
};
6760 static const char* l4_en_150GB001_
[] = { "en_150", "en_GB", "en_001", "en", NULL
};
6761 static const char* l4_en_AUGB001_
[] = { "en_AU", "en_GB", "en_001", "en", NULL
};
6762 static const char* l1_es
[] = { "es", NULL
};
6763 static const char* l1_Spa
[] = { "Spanish", NULL
};
6764 static const char* l2_es_419_
[] = { "es_419", "es", NULL
};
6765 static const char* l2_es_ES_
[] = { "es_ES", "es", NULL
};
6766 static const char* l2_es_MX_
[] = { "es_MX", "es", NULL
};
6767 static const char* l2_es_MX_Spa
[] = { "es_MX", "Spanish", NULL
};
6768 static const char* l3_es_MX419_
[] = { "es_MX", "es_419", "es", NULL
};
6769 static const char* l1_fi
[] = { "fi", NULL
};
6770 static const char* l1_Fin
[] = { "Finnish", NULL
};
6771 static const char* l1_fil
[] = { "fil", NULL
};
6772 static const char* l1_tl
[] = { "tl", NULL
};
6773 static const char* l1_fr
[] = { "fr", NULL
};
6774 static const char* l1_Fre
[] = { "French", NULL
};
6775 static const char* l2_fr_CA_
[] = { "fr_CA", "fr", NULL
};
6776 static const char* l2_fr_CH_
[] = { "fr_CH", "fr", NULL
};
6777 static const char* l2_fr_FR_
[] = { "fr_FR", "fr", NULL
};
6778 static const char* l1_haw
[] = { "haw", NULL
};
6779 static const char* l1_he
[] = { "he", NULL
};
6780 static const char* l1_hr
[] = { "hr", NULL
};
6781 static const char* l1_hu
[] = { "hu", NULL
};
6782 static const char* l1_id
[] = { "id", NULL
};
6783 static const char* l1_in
[] = { "in", NULL
};
6784 static const char* l1_it
[] = { "it", NULL
};
6785 static const char* l1_Ita
[] = { "Italian", NULL
};
6786 static const char* l1_ja
[] = { "ja", NULL
};
6787 static const char* l1_Japn
[] = { "Japanese", NULL
};
6788 static const char* l1_ko
[] = { "ko", NULL
};
6789 static const char* l1_Kor
[] = { "Korean", NULL
};
6790 static const char* l1_ms
[] = { "ms", NULL
};
6791 static const char* l1_nb
[] = { "nb", NULL
};
6792 static const char* l1_no
[] = { "no", NULL
};
6793 static const char* l1_Nor
[] = { "Norwegian", NULL
};
6794 static const char* l2_no_NO_
[] = { "no_NO", "no", NULL
};
6795 static const char* l1_nl
[] = { "nl", NULL
};
6796 static const char* l1_Dut
[] = { "Dutch", NULL
};
6797 static const char* l2_nl_BE_
[] = { "nl_BE", "nl", NULL
};
6798 static const char* l1_pl
[] = { "pl", NULL
};
6799 static const char* l1_Pol
[] = { "Polish", NULL
};
6800 static const char* l1_pt
[] = { "pt", NULL
};
6801 static const char* l1_pt_PT
[] = { "pt_PT", NULL
};
6802 static const char* l1_Port
[] = { "Portuguese", NULL
};
6803 static const char* l2_pt_BR_
[] = { "pt_BR", "pt", NULL
};
6804 static const char* l2_pt_PT_
[] = { "pt_PT", "pt", NULL
};
6805 static const char* l1_ro
[] = { "ro", NULL
};
6806 static const char* l2_ro_MD_
[] = { "ro_MD", "ro", NULL
};
6807 static const char* l1_mo
[] = { "mo", NULL
};
6808 static const char* l1_ru
[] = { "ru", NULL
};
6809 static const char* l1_Rus
[] = { "Russian", NULL
};
6810 static const char* l1_sk
[] = { "sk", NULL
};
6811 static const char* l1_sr
[] = { "sr", NULL
};
6812 static const char* l1_srLatn
[] = { "sr-Latn", NULL
};
6813 static const char* l1_sv
[] = { "sv", NULL
};
6814 static const char* l1_Swe
[] = { "Swedish", NULL
};
6815 static const char* l1_th
[] = { "th", NULL
};
6816 static const char* l1_Thai
[] = { "Thai", NULL
};
6817 static const char* l1_tlh
[] = { "tlh", NULL
};
6818 static const char* l1_tr
[] = { "tr", NULL
};
6819 static const char* l1_Tur
[] = { "Turkish", NULL
};
6820 static const char* l1_uk
[] = { "uk", NULL
};
6821 static const char* l1_vi
[] = { "vi", NULL
};
6822 static const char* l1_yi
[] = { "yi", NULL
};
6823 static const char* l1_iw
[] = { "iw", NULL
};
6824 static const char* l1_zh_CN
[] = { "zh_CN", NULL
};
6825 static const char* l1_zh_TW
[] = { "zh_TW", NULL
};
6826 static const char* l1_zh_Hans
[] = { "zh_Hans", NULL
};
6827 static const char* l1_zh_Hant
[] = { "zh_Hant", NULL
};
6828 static const char* l1_zhHant
[] = { "zh-Hant", NULL
};
6829 static const char* l2_zh_HKTW
[] = { "zh_HK", "zh_TW", NULL
};
6830 static const char* l2_zh_Hant_HK_
[] = { "zh_Hant_HK", "zh_Hant", NULL
};
6831 static const char* l2_zh_CN_Hans
[] = { "zh_CN", "zh_Hans", NULL
};
6832 static const char* l2_zh_TW_Hant
[] = { "zh_TW", "zh_Hant", NULL
};
6833 static const char* l3_zh_MOHKTW
[] = { "zh_MO", "zh_HK", "zh_TW", NULL
};
6834 static const char* l3_zh_HK_HantHK_Hant
[] = { "zh_HK", "zh_Hant_HK", "zh_Hant", NULL
};
6836 static const LangAndExpLocs appleLangAndLoc
[] = {
6837 // language\ result for appleLocs1 appleLocs2 appleLocs3 appleLocs4 appleLocs5 appleLocs6
6838 { "zh", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6839 { "zh-Hans", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6840 { "zh-Hant", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} },
6841 { "zh-Hans-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
6842 { "zh-Hans-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6843 { "zh-Hant-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
6844 { "zh-Hant-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6845 { "zh-Hant-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6846 { "zh-Hans-HK", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6847 { "zh-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
6848 { "zh-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6849 { "zh-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
6850 { "zh-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HK_HantHK_Hant
} },
6851 { "zh-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6852 { "en", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6853 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6854 { "en-AU", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
6855 { "en-CA", { l1_Eng
, l1_en
, l2_en_CA_
, l2_en_CA_
, l2_en_001_
, l2_en_001_
} },
6856 { "en-GB", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6857 { "en-IN", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l3_en_INGB_
, l3_en_GB001_
, l3_en_GB001_
} },
6858 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6859 { "en_US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6860 { "en-FR", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
6861 { "en-BE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
6862 { "en-GG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6863 { "en-HK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6864 { "en-IE", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6865 { "en-MO", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6866 { "en-MT", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6867 { "en-NZ", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
6868 { "en-PK", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6869 { "en-SG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6870 { "en-VG", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6871 { "en-IL", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
6872 { "en-001", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
6873 { "en-150", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
6874 { "en-Latn", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6875 { "en-Latn-US", { l1_Eng
, l1_en
, l1_en
, l1_en
,/*TODO*/ l1_en
, l1_en
} },
6876 { "en-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6877 { "en-Latn-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6878 { "en-u-ca-hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6879 { "en@calendar=hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6880 { "en-", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6881 { "en_", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6882 { "es", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6883 { "es-ES", { l1_Spa
, l1_es
, l1_es
, l1_es
, l2_es_ES_
, l2_es_ES_
} },
6884 { "es-419", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
6885 { "es-MX", { l1_Spa
, l2_es_MX_
, l2_es_419_
, l3_es_MX419_
, l2_es_MX_
, l3_es_MX419_
} },
6886 { "es-AR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
6887 { "es-BR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
6888 { "es-Latn", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6889 { "es-Latn-MX", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6890 { "pt", { l1_Port
, l1_pt
, l1_pt
, l1_pt
, NULL
, NULL
} },
6891 { "pt-BR", { l1_Port
, l1_pt
, l2_pt_BR_
, l2_pt_BR_
, NULL
, NULL
} },
6892 { "pt-PT", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6893 { "pt-MO", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6894 { "pt-CH", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6895 { "pt-GQ", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6896 { "pt-LU", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6897 { "fr", { l1_Fre
, l1_fr
, l1_fr
, l1_fr
, NULL
, NULL
} },
6898 { "fr-FR", { l1_Fre
, l1_fr
, l2_fr_FR_
, l2_fr_FR_
, NULL
, NULL
} },
6899 { "fr-CA", { l1_Fre
, l2_fr_CA_
, l2_fr_CA_
, l2_fr_CA_
, NULL
, NULL
} },
6900 { "fr-CH", { l1_Fre
, l1_fr
, l1_fr
, l2_fr_CH_
, NULL
, NULL
} },
6901 { "ar", { l1_Ara
, l1_ar
, l1_ar
, NULL
, NULL
, NULL
} },
6902 { "da", { l1_Dan
, l1_da
, l1_da
, NULL
, NULL
, NULL
} },
6903 { "nl", { l1_Dut
, l1_nl
, l1_nl
, l1_nl
, NULL
, NULL
} },
6904 { "nl-BE", { l1_Dut
, l1_nl
, l1_nl
, l2_nl_BE_
, NULL
, NULL
} },
6905 { "fi", { l1_Fin
, l1_fi
, l1_fi
, NULL
, NULL
, NULL
} },
6906 { "de", { l1_Ger
, l1_de
, l1_de
, NULL
, NULL
, NULL
} },
6907 { "it", { l1_Ita
, l1_it
, l1_it
, NULL
, NULL
, NULL
} },
6908 { "ja", { l1_Japn
, l1_ja
, l1_ja
, NULL
, NULL
, NULL
} },
6909 { "ko", { l1_Kor
, l1_ko
, l1_ko
, NULL
, NULL
, NULL
} },
6910 { "nb", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
6911 { "no", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
6912 { "pl", { l1_Pol
, l1_pl
, l1_pl
, NULL
, NULL
, NULL
} },
6913 { "ru", { l1_Rus
, l1_ru
, l1_ru
, NULL
, NULL
, NULL
} },
6914 { "sv", { l1_Swe
, l1_sv
, l1_sv
, NULL
, NULL
, NULL
} },
6915 { "th", { l1_Thai
, l1_th
, l1_th
, NULL
, NULL
, NULL
} },
6916 { "tr", { l1_Tur
, l1_tr
, l1_tr
, NULL
, NULL
, NULL
} },
6917 { "ca", { l1_ca
, l1_ca
, l1_ca
, NULL
, NULL
, NULL
} },
6918 { "cs", { l1_cs
, l1_cs
, l1_cs
, NULL
, NULL
, NULL
} },
6919 { "el", { l1_el
, l1_el
, l1_el
, NULL
, NULL
, NULL
} },
6920 { "he", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
6921 { "iw", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
6922 { "hr", { l1_hr
, l1_hr
, l1_hr
, NULL
, NULL
, NULL
} },
6923 { "hu", { l1_hu
, l1_hu
, l1_hu
, NULL
, NULL
, NULL
} },
6924 { "id", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
6925 { "in", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
6926 { "ms", { l1_ms
, l1_ms
, l1_ms
, NULL
, NULL
, NULL
} },
6927 { "ro", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, l1_mo
} },
6928 { "mo", { l1_ro
, l1_ro
, l1_ro
, l2_ro_MD_
, NULL
, l1_mo
} },
6929 { "sk", { l1_sk
, l1_sk
, l1_sk
, NULL
, NULL
, NULL
} },
6930 { "uk", { l1_uk
, l1_uk
, l1_uk
, NULL
, NULL
, NULL
} },
6931 { "vi", { l1_vi
, l1_vi
, l1_vi
, NULL
, NULL
, NULL
} },
6932 { "yi", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
6933 { "ji", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
6934 { "fil", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
6935 { "tl", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
6936 { "haw", { NULL
, NULL
, NULL
, NULL
, l1_haw
, NULL
} },
6937 { "sr", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
6938 { "sr-Cyrl", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
6939 { "sr-Latn", { NULL
, NULL
, NULL
, NULL
, l1_srLatn
, NULL
} },
6940 { "tlh", { NULL
, NULL
, NULL
, NULL
, l1_tlh
, NULL
} },
6941 { "Default@2x", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6942 { "default", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6943 { "root", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6944 { "", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6945 { "_US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6946 { "-US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6947 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6948 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6949 { "@calendar=hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6951 enum { kNumAppleLangAndLoc
= UPRV_LENGTHOF(appleLangAndLoc
) };
6953 /* tests from <rdar://problem/21518031> */
6955 static const char * appleLocsA1
[] = { "en", "fr", "no", "zh-Hant" };
6956 static const char * appleLocsA2
[] = { "en", "fr", "nb", "zh_TW", "zh_CN", "zh-Hant" };
6957 static const char * appleLocsA3
[] = { "en", "en_IN", "en_GB", "fr", "de", "zh_TW" };
6958 static const char * appleLocsA4
[] = { "Spanish", "es_MX", "English", "en_GB" };
6959 static const char * appleLocsA5
[] = { "en", "fr", "de", "pt", "pt_PT" };
6960 static const char * appleLocsA6
[] = { "en", "no", "no_NO", "pt_PT" };
6962 static const AppleLocsAndCount locAndCountEntriesA
[kNumLocSets
] = {
6963 { appleLocsA1
, UPRV_LENGTHOF(appleLocsA1
) },
6964 { appleLocsA2
, UPRV_LENGTHOF(appleLocsA2
) },
6965 { appleLocsA3
, UPRV_LENGTHOF(appleLocsA3
) },
6966 { appleLocsA4
, UPRV_LENGTHOF(appleLocsA4
) },
6967 { appleLocsA5
, UPRV_LENGTHOF(appleLocsA5
) },
6968 { appleLocsA6
, UPRV_LENGTHOF(appleLocsA6
) },
6971 static const LangAndExpLocs appleLangAndLocA
[] = {
6972 // language\ result for appleLocsA1 appleLocsA2 appleLocsA3 appleLocsA4 appleLocsA5 appleLocsA6
6973 { "zh-Hant", { l1_zhHant
,/*0*/ l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6974 { "zh_Hant", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6975 { "zh_HK", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6976 { "en_IN", { l1_en
, l1_en
, l3_en_INGB_
, l2_en_GB_Eng
, l1_en
, l1_en
} },
6977 { "es_MX", { NULL
, NULL
, NULL
, l2_es_MX_Spa
, NULL
, NULL
} },
6978 { "pt_PT", { NULL
, NULL
, NULL
, NULL
, l2_pt_PT_
, l1_pt_PT
} },
6979 { "pt", { NULL
, NULL
, NULL
, NULL
, l1_pt
, l1_pt_PT
} },
6980 { "no", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
6981 { "no_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
6982 { "nb", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l1_no
} },
6983 { "nb_NO", { l1_no
, l1_nb
, NULL
, NULL
, NULL
, l2_no_NO_
} },
6985 enum { kNumAppleLangAndLocA
= UPRV_LENGTHOF(appleLangAndLocA
) };
6987 /* tests from log attached to 21682790 */
6989 static const char * appleLocsB1
[] = {
6990 "ar", "Base", "ca", "cs",
6991 "da", "Dutch", "el", "English",
6992 "es_MX", "fi", "French", "German",
6993 "he", "hr", "hu", "id",
6994 "Italian", "Japanese", "ko", "ms",
6995 "no", "pl", "pt", "pt_PT",
6996 "ro", "ru", "sk", "Spanish",
6997 "sv", "th", "tr", "uk",
6998 "vi", "zh_CN", "zh_TW"
7001 static const char * appleLocsB2
[] = {
7003 "da", "Dutch", "el", "English",
7004 "es_MX", "fi", "French", "German",
7005 "he", "hr", "hu", "id",
7006 "Italian", "Japanese", "ko", "ms",
7007 "no", "pl", "pt", "pt_PT",
7008 "ro", "ru", "sk", "Spanish",
7009 "sv", "th", "tr", "uk",
7010 "vi", "zh_CN", "zh_TW"
7013 static const char * appleLocsB3
[] = {
7014 "ar", "ca", "cs", "da",
7015 "de", "el", "en", "es",
7016 "es_MX", "fi", "French", "he",
7017 "hr", "hu", "id", "Italian",
7018 "ja", "ko", "ms", "nl",
7019 "no", "pl", "pt", "pt_PT",
7020 "ro", "ru", "sk", "sv",
7021 "th", "tr", "uk", "vi",
7025 static const char * appleLocsB4
[] = {
7026 "ar", "ca", "cs", "da",
7027 "de", "el", "en", "es",
7028 "es_MX", "fi", "fr", "he",
7029 "hr", "hu", "id", "it",
7030 "ja", "ko", "ms", "nl",
7031 "no", "pl", "pt", "pt_PT",
7032 "ro", "ru", "sk", "sv",
7033 "th", "tr", "uk", "vi",
7037 static const char * appleLocsB5
[] = { "en" };
7039 static const char * appleLocsB6
[] = { "English" };
7041 static const AppleLocsAndCount locAndCountEntriesB
[kNumLocSets
] = {
7042 { appleLocsB1
, UPRV_LENGTHOF(appleLocsB1
) },
7043 { appleLocsB2
, UPRV_LENGTHOF(appleLocsB2
) },
7044 { appleLocsB3
, UPRV_LENGTHOF(appleLocsB3
) },
7045 { appleLocsB4
, UPRV_LENGTHOF(appleLocsB4
) },
7046 { appleLocsB5
, UPRV_LENGTHOF(appleLocsB5
) },
7047 { appleLocsB6
, UPRV_LENGTHOF(appleLocsB6
) },
7050 static const LangAndExpLocs appleLangAndLocB
[] = {
7051 // language\ result for appleLocsB1 appleLocsB2 appleLocsB3 appleLocsB4 appleLocsB5 appleLocsB6
7052 // Prefs 1, logged with sets B1-B3
7053 { "en", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
7054 { "es", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
7055 // Prefs 2, logged with sets B1-B6
7056 { "English", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
7057 { "Spanish", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
7059 enum { kNumAppleLangAndLocB
= UPRV_LENGTHOF(appleLangAndLocB
) };
7062 const AppleLocsAndCount
* locAndCountEntriesPtr
;
7063 const LangAndExpLocs
* appleLangAndLocPtr
;
7064 int32_t appleLangAndLocCount
;
7065 } AppleLocToUseTestSet
;
7067 static const AppleLocToUseTestSet altuTestSets
[] = {
7068 { locAndCountEntries
, appleLangAndLoc
, kNumAppleLangAndLoc
},
7069 { locAndCountEntriesA
, appleLangAndLocA
, kNumAppleLangAndLocA
},
7070 { locAndCountEntriesB
, appleLangAndLocB
, kNumAppleLangAndLocB
},
7074 /* tests for multiple prefs sets */
7076 static const char * appleLocsM1
[] = { "en", "en_GB", "pt", "pt_PT", "zh_CN", "zh_Hant" };
7077 static const char * prefLangsM1
[] = { "tlh", "zh_HK", "zh_SG", "zh_Hans", "pt_BR", "pt_PT", "en_IN", "en" };
7078 static const char * locsToUseM1
[] = { "zh_Hant" };
7080 // Tests from first pass at <rdar://problem/22012864>, 2015-11-18
7082 static const char * appleLocsM2
[] = { "fr-FR", "en-US", "en-GB" };
7083 static const char * prefLangsM2
[] = { "fr-CH" };
7084 static const char * locsToUseM2
[] = { "fr-FR" };
7086 static const char * appleLocsM3
[] = { "es-es", "fr-fr" };
7087 static const char * prefLangsM3
[] = { "fr-US", "fr", "en-US" };
7088 static const char * locsToUseM3
[] = { "fr-fr" };
7090 static const char * appleLocsM4
[] = { "es-es", "fr-fr", "fr" };
7091 static const char * prefLangsM4
[] = { "fr-US", "fr", "en-US" };
7092 static const char * locsToUseM4
[] = { "fr" };
7094 // Tests from second pass at <rdar://problem/22012864>, 2015-12-08
7096 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" };
7097 static const char * prefLangsM5
[] = { "fr-US", "en-US" };
7098 static const char * locsToUseM5
[] = { "fr-FR" };
7099 // Per Peter E; expected result changed from "en-US" to "de-CH" per <rdar://problem/26559053>
7100 static const char * appleLocsM6
[] = { "de-CH", "en-US" };
7101 static const char * prefLangsM6
[] = { "de-DE", "en-US" };
7102 static const char * locsToUseM6
[] = { "de-CH" };
7103 // The following is used for M7-MD
7104 static const char * appleLocsMx
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-HK", "zh-TW" };
7106 static const char * prefLangsM7
[] = { "fr-ES", "en-AU" };
7107 static const char * locsToUseM7
[] = { "fr-FR" };
7109 static const char * prefLangsM8
[] = { "de-IT", "en-AU" };
7110 static const char * locsToUseM8
[] = { "de-DE" };
7112 static const char * prefLangsM9
[] = { "hi-US", "en-AU" };
7113 static const char * locsToUseM9
[] = { "hi-IN" };
7115 static const char * prefLangsMA
[] = { "en-IN", "zh-HK" };
7116 static const char * locsToUseMA
[] = { "en-AU" };
7118 static const char * prefLangsMB
[] = { "pt-PT", "en-AU" };
7119 static const char * locsToUseMB
[] = { "en-AU" };
7121 static const char * prefLangsMC
[] = { "pt-PT", "ar" };
7122 static const char * locsToUseMC
[] = { "pt-BR" };
7124 static const char * prefLangsMD
[] = { "zh-CN", "en-AU" };
7125 static const char * locsToUseMD
[] = { "en-AU" };
7127 static const char * appleLocsME
[] = { "de-DE", "en-AU", "es-ES", "fr-FR", "hi-IN", "pt-BR", "zh-CN", "zh-HK" };
7128 static const char * prefLangsME
[] = { "zh-TW", "en-AU" };
7129 static const char * locsToUseME
[] = { "zh-HK" };
7130 // Per Peter E in diagnosis for <rdar://problem/22012864> and <rdar://problem/23815194>
7131 static const char * appleLocsMF
[] = { "en", "en-GB", "fr", "es" };
7132 static const char * prefLangsMF
[] = { "en-IN", "en-GB", "de", "fr" };
7133 static const char * locsToUseMF
[] = { "en-GB", "en" };
7134 // Per Karan M in <rdar://problem/23982460>
7135 static const char * appleLocsMG
[] = { "zh-Hans", "zh-Hant", "zh-HK" };
7136 static const char * prefLangsMG
[] = { "zh-Hans-US", "zh-HK", "en-US" };
7137 static const char * locsToUseMG
[] = { "zh-Hans" };
7138 // Per <rdar://problem/25903891>
7139 static const char * appleLocsMH
[] = { "zh-TW", "zh-CN", "zh-HK" };
7140 static const char * prefLangsMH
[] = { "zh-Hans-HK", "zh-HK", "en" };
7141 static const char * locsToUseMH
[] = { "zh-CN" };
7142 // Per <rdar://problem/26559053>
7143 static const char * appleLocsMI
[] = { "unk", "en-US", "ar-SA" };
7144 static const char * prefLangsMI
[] = { "ar-US" };
7145 static const char * locsToUseMI
[] = { "ar-SA" };
7149 const char ** availLocs
;
7150 int32_t availLocsCount
;
7151 const char ** prefLangs
;
7152 int32_t prefLangsCount
;
7153 const char ** locsToUse
;
7154 int32_t locsToUseCount
;
7157 static const MultiPrefTest multiTestSets
[] = {
7158 { "M1", appleLocsM1
, UPRV_LENGTHOF(appleLocsM1
), prefLangsM1
, UPRV_LENGTHOF(prefLangsM1
), locsToUseM1
, UPRV_LENGTHOF(locsToUseM1
) },
7160 { "M2", appleLocsM2
, UPRV_LENGTHOF(appleLocsM2
), prefLangsM2
, UPRV_LENGTHOF(prefLangsM2
), locsToUseM2
, UPRV_LENGTHOF(locsToUseM2
) },
7161 { "M3", appleLocsM3
, UPRV_LENGTHOF(appleLocsM3
), prefLangsM3
, UPRV_LENGTHOF(prefLangsM3
), locsToUseM3
, UPRV_LENGTHOF(locsToUseM3
) },
7162 { "M4", appleLocsM4
, UPRV_LENGTHOF(appleLocsM4
), prefLangsM4
, UPRV_LENGTHOF(prefLangsM4
), locsToUseM4
, UPRV_LENGTHOF(locsToUseM4
) },
7164 { "M5", appleLocsM5
, UPRV_LENGTHOF(appleLocsM5
), prefLangsM5
, UPRV_LENGTHOF(prefLangsM5
), locsToUseM5
, UPRV_LENGTHOF(locsToUseM5
) },
7165 { "M6", appleLocsM6
, UPRV_LENGTHOF(appleLocsM6
), prefLangsM6
, UPRV_LENGTHOF(prefLangsM6
), locsToUseM6
, UPRV_LENGTHOF(locsToUseM6
) },
7166 { "M7", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM7
, UPRV_LENGTHOF(prefLangsM7
), locsToUseM7
, UPRV_LENGTHOF(locsToUseM7
) },
7167 { "M8", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM8
, UPRV_LENGTHOF(prefLangsM8
), locsToUseM8
, UPRV_LENGTHOF(locsToUseM8
) },
7168 { "M9", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsM9
, UPRV_LENGTHOF(prefLangsM9
), locsToUseM9
, UPRV_LENGTHOF(locsToUseM9
) },
7169 { "MA", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMA
, UPRV_LENGTHOF(prefLangsMA
), locsToUseMA
, UPRV_LENGTHOF(locsToUseMA
) },
7170 { "MB", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMB
, UPRV_LENGTHOF(prefLangsMB
), locsToUseMB
, UPRV_LENGTHOF(locsToUseMB
) },
7171 { "MC", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMC
, UPRV_LENGTHOF(prefLangsMC
), locsToUseMC
, UPRV_LENGTHOF(locsToUseMC
) },
7172 { "MD", appleLocsMx
, UPRV_LENGTHOF(appleLocsMx
), prefLangsMD
, UPRV_LENGTHOF(prefLangsMD
), locsToUseMD
, UPRV_LENGTHOF(locsToUseMD
) },
7173 { "ME", appleLocsME
, UPRV_LENGTHOF(appleLocsME
), prefLangsME
, UPRV_LENGTHOF(prefLangsME
), locsToUseME
, UPRV_LENGTHOF(locsToUseME
) },
7174 { "MF", appleLocsMF
, UPRV_LENGTHOF(appleLocsMF
), prefLangsMF
, UPRV_LENGTHOF(prefLangsMF
), locsToUseMF
, UPRV_LENGTHOF(locsToUseMF
) },
7175 { "MG", appleLocsMG
, UPRV_LENGTHOF(appleLocsMG
), prefLangsMG
, UPRV_LENGTHOF(prefLangsMG
), locsToUseMG
, UPRV_LENGTHOF(locsToUseMG
) },
7176 { "MH", appleLocsMH
, UPRV_LENGTHOF(appleLocsMH
), prefLangsMH
, UPRV_LENGTHOF(prefLangsMH
), locsToUseMH
, UPRV_LENGTHOF(locsToUseMH
) },
7177 { "MI", appleLocsMI
, UPRV_LENGTHOF(appleLocsMI
), prefLangsMI
, UPRV_LENGTHOF(prefLangsMI
), locsToUseMI
, UPRV_LENGTHOF(locsToUseMI
) },
7178 { NULL
, NULL
, 0, NULL
, 0, NULL
, 0 }
7184 enum { kMaxLocalizationsToUse
= 8, kPrintArrayBufSize
= 128 };
7186 // array, array of pointers to strings to print
7187 // count, count of array elements, may be -1 if array is terminated by a NULL entry
7188 // buf, buffer into which to put concatenated strings
7189 // bufSize, length of buf
7190 static void printStringArray(const char **array
, int32_t count
, char *buf
, int32_t bufSize
) {
7191 char * bufPtr
= buf
;
7192 const char * curEntry
;
7193 int32_t idx
, countMax
= bufSize
/16;
7194 if (count
< 0 || count
> countMax
) {
7197 for (idx
= 0; idx
< count
&& (curEntry
= *array
++) != NULL
; idx
++) {
7198 int32_t len
= sprintf(bufPtr
, "%s\"%.12s\"", (idx
> 0)? ", ": "", curEntry
);
7204 *bufPtr
= 0; /* ensure termination */
7207 static UBool
equalStringArrays(const char **array1
, int32_t count1
, const char **array2
, int32_t count2
) {
7208 const char ** array1Ptr
= array1
;
7209 const char ** array2Ptr
= array2
;
7213 while (*array1Ptr
++ != NULL
) {
7219 while (*array2Ptr
++ != NULL
) {
7223 if (count1
!= count2
) {
7226 for (idx
= 0; idx
< count1
; idx
++) {
7227 if (uprv_strcmp(array1
[idx
], array2
[idx
]) != 0) {
7234 static void TestAppleLocalizationsToUse() {
7235 const AppleLocToUseTestSet
* testSetPtr
;
7236 const MultiPrefTest
* multiSetPtr
;
7237 const char * locsToUse
[kMaxLocalizationsToUse
];
7238 int32_t numLocsToUse
;
7240 char printExpected
[kPrintArrayBufSize
];
7241 char printActual
[kPrintArrayBufSize
];
7243 for (testSetPtr
= altuTestSets
; testSetPtr
->locAndCountEntriesPtr
!= NULL
; testSetPtr
++) {
7244 int32_t iLocSet
, iLang
;
7246 for (iLocSet
= 0; iLocSet
< kNumLocSets
; iLocSet
++) {
7247 for (iLang
= 0; iLang
< testSetPtr
->appleLangAndLocCount
; iLang
++) {
7248 const char * language
= testSetPtr
->appleLangAndLocPtr
[iLang
].language
;
7249 const char ** expLocsForSet
= testSetPtr
->appleLangAndLocPtr
[iLang
].expLocsForSets
[iLocSet
];
7250 status
= U_ZERO_ERROR
;
7252 numLocsToUse
= ualoc_localizationsToUse(&language
, 1,
7253 testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locs
, testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locCount
,
7254 locsToUse
, kMaxLocalizationsToUse
, &status
);
7255 if (U_FAILURE(status
)) {
7256 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, status %s\n",
7257 testSetPtr
-altuTestSets
, iLocSet
+1, language
, u_errorName(status
));
7258 } else if (numLocsToUse
== 0 && expLocsForSet
!= NULL
) {
7259 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
7260 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect {%s}, get no results\n",
7261 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
);
7262 } else if (numLocsToUse
> 0 && expLocsForSet
== NULL
) {
7263 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
7264 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect no results, get {%s}\n",
7265 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printActual
);
7266 } else if (numLocsToUse
> 0 && !equalStringArrays(expLocsForSet
, -1, locsToUse
, numLocsToUse
)) {
7267 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
7268 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
7269 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s:\n expect {%s}\n get {%s}\n",
7270 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
, printActual
);
7276 for (multiSetPtr
= multiTestSets
; multiSetPtr
->name
!= NULL
; multiSetPtr
++) {
7277 status
= U_ZERO_ERROR
;
7278 numLocsToUse
= ualoc_localizationsToUse(multiSetPtr
->prefLangs
, multiSetPtr
->prefLangsCount
, multiSetPtr
->availLocs
, multiSetPtr
->availLocsCount
, locsToUse
, kMaxLocalizationsToUse
, &status
);
7279 if (U_FAILURE(status
)) {
7280 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s, status %s\n", multiSetPtr
->name
, multiSetPtr
->name
, u_errorName(status
));
7281 } else if (!equalStringArrays(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, locsToUse
, numLocsToUse
)) {
7282 printStringArray(multiSetPtr
->locsToUse
, multiSetPtr
->locsToUseCount
, printExpected
, kPrintArrayBufSize
);
7283 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
7284 log_err("FAIL: ualoc_localizationsToUse appleLocs%s, langs prefLangs%s:\n expect {%s}\n get {%s}\n",
7285 multiSetPtr
->name
, multiSetPtr
->name
, printExpected
, printActual
);