1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /*****************************************************************************
12 * Modification History:
14 * Madhu Katragadda Ported for C API
15 ******************************************************************************
27 #include "unicode/putil.h"
28 #include "unicode/ubrk.h"
29 #include "unicode/uchar.h"
30 #include "unicode/ucol.h"
31 #include "unicode/udat.h"
32 #include "unicode/uloc.h"
33 #include "unicode/umsg.h"
34 #include "unicode/ures.h"
35 #include "unicode/uset.h"
36 #include "unicode/ustring.h"
37 #include "unicode/utypes.h"
38 #include "unicode/ulocdata.h"
39 #include "unicode/uldnames.h"
40 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
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);
54 void PrintDataTable();
56 /*---------------------------------------------------
58 --------------------------------------------------- */
60 #define LOCALE_INFO_SIZE 28
62 static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
64 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
66 { "", "", "", "", "", "", "", "", "" },
68 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
70 { "", "", "", "", "NY", "", "", "", "" },
72 { "en_US", "fr_FR", "ca_ES",
73 "el_GR", "no_NO_NY", "zh_Hans_CN",
74 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
76 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
78 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
80 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
82 /* display language (English) */
83 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
84 /* display script code (English) */
85 { "", "", "", "", "", "Simplified Han", "", "", "" },
86 /* display country (English) */
87 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
88 /* display variant (English) */
89 { "", "", "", "", "NY", "", "", "", "" },
90 /* display name (English) */
91 { "English (United States)", "French (France)", "Catalan (Spain)",
92 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
93 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
95 /* display language (French) */
96 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
97 /* display script code (French) */
98 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
99 /* display country (French) */
100 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
101 /* display variant (French) */
102 { "", "", "", "", "NY", "", "", "", "" },
103 /* display name (French) */
104 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
105 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)",
106 "allemand (Allemagne, ordre de tri=Ordre de l\\u2019annuaire)", "espagnol (ordre de tri=Ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
108 /* display language (Catalan) */
109 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
110 /* display script code (Catalan) */
111 { "", "", "", "", "", "han simplificat", "", "", "" },
112 /* display country (Catalan) */
113 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
114 /* display variant (Catalan) */
115 { "", "", "", "", "NY", "", "", "", "" },
116 /* display name (Catalan) */
117 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
118 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
119 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
121 /* display language (Greek) */
123 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
124 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
125 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
126 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
127 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
128 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
129 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
130 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
131 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
133 /* display script code (Greek) */
135 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
136 /* display country (Greek) */
138 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
139 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
140 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
141 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
142 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
143 "\\u039A\\u03AF\\u03BD\\u03B1",
144 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
146 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
148 /* display variant (Greek) */
149 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
150 /* display name (Greek) */
152 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
153 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
154 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
155 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
156 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
157 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
158 "\\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)",
159 "\\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)",
160 "\\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)"
164 static UChar*** dataTable=0;
204 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
206 void addLocaleTest(TestNode** root);
208 void addLocaleTest(TestNode** root)
210 TESTCASE(TestObsoleteNames); /* srl- move */
211 TESTCASE(TestBasicGetters);
212 TESTCASE(TestNullDefault);
213 TESTCASE(TestPrefixes);
214 TESTCASE(TestSimpleResourceInfo);
215 TESTCASE(TestDisplayNames);
216 TESTCASE(TestGetAvailableLocales);
217 TESTCASE(TestDataDirectory);
218 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
219 TESTCASE(TestISOFunctions);
221 TESTCASE(TestISO3Fallback);
222 TESTCASE(TestUninstalledISO3Names);
223 TESTCASE(TestSimpleDisplayNames);
224 TESTCASE(TestVariantParsing);
225 TESTCASE(TestKeywordVariants);
226 TESTCASE(TestKeywordVariantParsing);
227 TESTCASE(TestCanonicalization);
228 TESTCASE(TestKeywordSet);
229 TESTCASE(TestKeywordSetError);
230 TESTCASE(TestDisplayKeywords);
231 TESTCASE(TestDisplayKeywordValues);
232 TESTCASE(TestGetBaseName);
233 #if !UCONFIG_NO_FILE_IO
234 TESTCASE(TestGetLocale);
236 TESTCASE(TestDisplayNameWarning);
237 TESTCASE(TestNonexistentLanguageExemplars);
238 TESTCASE(TestLocDataErrorCodeChaining);
239 TESTCASE(TestLocDataWithRgTag);
240 TESTCASE(TestLanguageExemplarsFallbacks);
241 TESTCASE(TestCalendar);
242 TESTCASE(TestDateFormat);
243 TESTCASE(TestCollation);
244 TESTCASE(TestULocale);
245 TESTCASE(TestUResourceBundle);
246 TESTCASE(TestDisplayName);
247 TESTCASE(TestAcceptLanguage);
248 TESTCASE(TestGetLocaleForLCID);
249 TESTCASE(TestOrientation);
250 TESTCASE(TestLikelySubtags);
251 TESTCASE(TestToLanguageTag);
252 TESTCASE(TestForLanguageTag);
253 TESTCASE(TestTrailingNull);
254 TESTCASE(TestUnicodeDefines);
255 TESTCASE(TestEnglishExemplarCharacters);
256 TESTCASE(TestDisplayNameBrackets);
257 TESTCASE(TestIsRightToLeft);
258 TESTCASE(TestToUnicodeLocaleKey);
259 TESTCASE(TestToLegacyKey);
260 TESTCASE(TestToUnicodeLocaleType);
261 TESTCASE(TestToLegacyType);
265 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
266 static void TestBasicGetters() {
269 UErrorCode status = U_ZERO_ERROR;
270 char *testLocale = 0;
271 char *temp = 0, *name = 0;
272 log_verbose("Testing Basic Getters\n");
273 for (i = 0; i < LOCALE_SIZE; i++) {
274 testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
275 strcpy(testLocale,rawData2[NAME][i]);
277 log_verbose("Testing %s .....\n", testLocale);
278 cap=uloc_getLanguage(testLocale, NULL, 0, &status);
279 if(status==U_BUFFER_OVERFLOW_ERROR){
281 temp=(char*)malloc(sizeof(char) * (cap+1));
282 uloc_getLanguage(testLocale, temp, cap+1, &status);
284 if(U_FAILURE(status)){
285 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status));
287 if (0 !=strcmp(temp,rawData2[LANG][i])) {
288 log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]);
292 cap=uloc_getCountry(testLocale, temp, cap, &status);
293 if(status==U_BUFFER_OVERFLOW_ERROR){
295 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
296 uloc_getCountry(testLocale, temp, cap+1, &status);
298 if(U_FAILURE(status)){
299 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status));
301 if (0 != strcmp(temp, rawData2[CTRY][i])) {
302 log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]);
306 cap=uloc_getVariant(testLocale, temp, cap, &status);
307 if(status==U_BUFFER_OVERFLOW_ERROR){
309 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
310 uloc_getVariant(testLocale, temp, cap+1, &status);
312 if(U_FAILURE(status)){
313 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status));
315 if (0 != strcmp(temp, rawData2[VAR][i])) {
316 log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]);
319 cap=uloc_getName(testLocale, NULL, 0, &status);
320 if(status==U_BUFFER_OVERFLOW_ERROR){
322 name=(char*)malloc(sizeof(char) * (cap+1));
323 uloc_getName(testLocale, name, cap+1, &status);
324 } else if(status==U_ZERO_ERROR) {
325 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale);
327 if(U_FAILURE(status)){
328 log_err("ERROR: in uloc_getName %s\n", myErrorName(status));
330 if (0 != strcmp(name, rawData2[NAME][i])){
331 log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]);
341 static void TestNullDefault() {
342 UErrorCode status = U_ZERO_ERROR;
343 char original[ULOC_FULLNAME_CAPACITY];
345 uprv_strcpy(original, uloc_getDefault());
346 uloc_setDefault("qq_BLA", &status);
347 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
348 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
350 uloc_setDefault(NULL, &status);
351 if (uprv_strcmp(uloc_getDefault(), original) != 0) {
352 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
356 /* Test that set & get of default locale work, and that
357 * default locales are cached and reused, and not overwritten.
361 const char *n2_en_US;
363 status = U_ZERO_ERROR;
364 uloc_setDefault("en_US", &status);
365 n_en_US = uloc_getDefault();
366 if (strcmp(n_en_US, "en_US") != 0) {
367 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
370 uloc_setDefault("fr_FR", &status);
371 n_fr_FR = uloc_getDefault();
372 if (strcmp(n_en_US, "en_US") != 0) {
373 log_err("uloc_setDefault altered previously default string."
374 "Expected \"en_US\", got \"%s\"\n", n_en_US);
376 if (strcmp(n_fr_FR, "fr_FR") != 0) {
377 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR);
380 uloc_setDefault("en_US", &status);
381 n2_en_US = uloc_getDefault();
382 if (strcmp(n2_en_US, "en_US") != 0) {
383 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
385 if (n2_en_US != n_en_US) {
386 log_err("Default locale cache failed to reuse en_US locale.\n");
389 if (U_FAILURE(status)) {
390 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status));
396 /* Test the i- and x- and @ and . functionality
399 #define PREFIXBUFSIZ 128
401 static void TestPrefixes() {
404 const char *loc, *expected;
406 static const char * const testData[][7] =
408 /* NULL canonicalize() column means "expect same as getName()" */
409 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL},
410 {"en", "", "GB", "", "en-gb", "en_GB", NULL},
411 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL},
412 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL},
413 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL},
414 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL},
416 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans@collation=pinyin"},
417 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", NULL},
419 {"de", "", "", "1901", "de-1901", "de__1901", NULL},
420 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
421 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
422 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
423 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
424 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
425 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
426 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
427 {"no", "", "", "NY", "no__ny", "no__NY", NULL},
428 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
429 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL},
430 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL},
431 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
432 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL},
433 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL},
434 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL}, /* total garbage */
436 {NULL,NULL,NULL,NULL,NULL,NULL,NULL}
439 static const char * const testTitles[] = {
440 "uloc_getLanguage()",
446 "uloc_canonicalize()"
449 char buf[PREFIXBUFSIZ];
454 for(row=0;testData[row][0] != NULL;row++) {
455 loc = testData[row][NAME];
456 log_verbose("Test #%d: %s\n", row, loc);
461 for(n=0;n<=(NAME+2);n++) {
462 if(n==NAME) continue;
464 for(len=0;len<PREFIXBUFSIZ;len++) {
465 buf[len] = '%'; /* Set a tripwire.. */
471 len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err);
475 len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err);
479 len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err);
483 len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err);
487 len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err);
491 len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err);
500 log_err("#%d: %s on %s: err %s\n",
501 row, testTitles[n], loc, u_errorName(err));
503 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
504 row, testTitles[n], loc, buf, len);
506 if(len != (int32_t)strlen(buf)) {
507 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
508 row, testTitles[n], loc, buf, len, strlen(buf)+1);
512 /* see if they smashed something */
513 if(buf[len+1] != '%') {
514 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
515 row, testTitles[n], loc, buf, buf[len+1]);
518 expected = testData[row][n];
519 if (expected == NULL && n == (NAME+2)) {
520 /* NULL expected canonicalize() means "expect same as getName()" */
521 expected = testData[row][NAME+1];
523 if(strcmp(buf, expected)) {
524 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
525 row, testTitles[n], loc, buf, expected);
534 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
535 static void TestSimpleResourceInfo() {
537 char* testLocale = 0;
542 testLocale=(char*)malloc(sizeof(char) * 1);
543 expected=(UChar*)malloc(sizeof(UChar) * 1);
546 log_verbose("Testing getISO3Language and getISO3Country\n");
547 for (i = 0; i < LOCALE_SIZE; i++) {
549 testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
550 u_austrcpy(testLocale, dataTable[NAME][i]);
552 log_verbose("Testing %s ......\n", testLocale);
554 temp=uloc_getISO3Language(testLocale);
555 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
556 u_uastrcpy(expected,temp);
557 if (0 != u_strcmp(expected, dataTable[LANG3][i])) {
558 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected),
559 austrdup(dataTable[LANG3][i]));
562 temp=uloc_getISO3Country(testLocale);
563 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
564 u_uastrcpy(expected,temp);
565 if (0 != u_strcmp(expected, dataTable[CTRY3][i])) {
566 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected),
567 austrdup(dataTable[CTRY3][i]));
569 sprintf(temp2, "%x", (int)uloc_getLCID(testLocale));
570 if (strcmp(temp2, rawData2[LCID][i]) != 0) {
571 log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]);
580 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
581 * if there's room but won't be included in result. result < 0 indicates an error.
582 * Returns the number of chars written (not those that would be written if there's enough room.*/
583 static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) {
584 static const struct {
597 static const int32_t ESCAPE_MAP_LENGTH = UPRV_LENGTHOF(ESCAPE_MAP);
598 static const char HEX_DIGITS[] = {
599 '0', '1', '2', '3', '4', '5', '6', '7',
600 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
603 int32_t resultLen = 0;
604 const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */
605 const int32_t escapeLimit1 = buflen-2;
606 const int32_t escapeLimit2 = buflen-6;
609 if(utext==NULL || resultChars==NULL || buflen<0) {
613 for(i=0;i<limit && resultLen<buflen;++i) {
619 for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) {
621 if(j<ESCAPE_MAP_LENGTH) {
622 if(resultLen>escapeLimit1) {
625 resultChars[resultLen++]='\\';
626 resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar;
630 u_austrncpy(resultChars + resultLen, &uc, 1);
635 if(resultLen>escapeLimit2) {
639 /* have to escape the uchar */
640 resultChars[resultLen++]='\\';
641 resultChars[resultLen++]='u';
642 resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff];
643 resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff];
644 resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff];
645 resultChars[resultLen++]=HEX_DIGITS[uc&0xff];
648 if(resultLen<buflen) {
649 resultChars[resultLen] = 0;
656 * Jitterbug 2439 -- markus 20030425
658 * The lookup of display names must not fall back through the default
659 * locale because that yields useless results.
661 static void TestDisplayNames()
664 UErrorCode errorCode=U_ZERO_ERROR;
666 log_verbose("Testing getDisplayName for different locales\n");
668 log_verbose(" In locale = en_US...\n");
669 doTestDisplayNames("en_US", DLANG_EN);
670 log_verbose(" In locale = fr_FR....\n");
671 doTestDisplayNames("fr_FR", DLANG_FR);
672 log_verbose(" In locale = ca_ES...\n");
673 doTestDisplayNames("ca_ES", DLANG_CA);
674 log_verbose(" In locale = gr_EL..\n");
675 doTestDisplayNames("el_GR", DLANG_EL);
677 /* test that the default locale has a display name for its own language */
678 errorCode=U_ZERO_ERROR;
679 length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode);
680 if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) {
681 /* check <=3 to reject getting the language code as a display name */
682 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));
685 /* test that we get the language code itself for an unknown language, and a default warning */
686 errorCode=U_ZERO_ERROR;
687 length=uloc_getDisplayLanguage("qq", "rr", buffer, UPRV_LENGTHOF(buffer), &errorCode);
688 if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
689 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
692 /* test that we get a default warning for a display name where one component is unknown (4255) */
693 errorCode=U_ZERO_ERROR;
694 length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, UPRV_LENGTHOF(buffer), &errorCode);
695 if(errorCode!=U_USING_DEFAULT_WARNING) {
696 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode));
701 static const char *aLocale = "es@collation=traditional;calendar=japanese";
702 static const char *testL[] = { "en_US",
706 static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
707 "espagnol (calendrier=calendrier japonais, ordre de tri=Ordre traditionnel)",
708 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
709 "\\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)" };
712 for(i=0;i<UPRV_LENGTHOF(testL);i++) {
713 errorCode = U_ZERO_ERROR;
714 uloc_getDisplayName(aLocale, testL[i], buffer, UPRV_LENGTHOF(buffer), &errorCode);
715 if(U_FAILURE(errorCode)) {
716 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode));
718 expectBuffer = CharsToUChars(expect[i]);
719 if(u_strcmp(buffer,expectBuffer)) {
720 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));
722 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]);
729 /* test that we properly preflight and return data when there's a non-default pattern,
733 static const char *locale="az_Cyrl";
734 static const char *displayLocale="ja";
735 static const char *expectedChars =
736 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e "
737 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
738 UErrorCode ec=U_ZERO_ERROR;
741 int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec);
742 /* inconvenient semantics when preflighting, this condition is expected... */
743 if(ec==U_BUFFER_OVERFLOW_ERROR) {
746 len=uloc_getDisplayName(locale, displayLocale, result, UPRV_LENGTHOF(result), &ec);
748 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
749 locale, displayLocale, u_errorName(ec));
751 UChar *expected=CharsToUChars(expectedChars);
752 int32_t expectedLen=u_strlen(expected);
754 if(len!=expectedLen) {
755 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
756 locale, displayLocale, len, expectedLen);
757 } else if(preflightLen!=expectedLen) {
758 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
759 locale, displayLocale, preflightLen, expectedLen);
760 } else if(u_strncmp(result, expected, len)) {
761 int32_t cap=len*6+1; /* worst case + space for trailing null */
762 char* resultChars=(char*)malloc(cap);
763 int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap);
764 if(resultCharsLen<0 || resultCharsLen<cap-1) {
765 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale);
767 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
768 locale, displayLocale, resultChars, expectedChars);
773 /* test all buffer sizes */
774 for(i=len+1;i>=0;--i) {
775 len=uloc_getDisplayName(locale, displayLocale, result, i, &ec);
776 if(ec==U_BUFFER_OVERFLOW_ERROR) {
780 log_err("using buffer of length %d returned error %s", i, u_errorName(ec));
783 if(len!=expectedLen) {
784 log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len);
787 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
788 * we don't know that it's been filled, so no point in checking. */
798 /* test for uloc_getAvialable() and uloc_countAvilable()*/
799 static void TestGetAvailableLocales()
805 log_verbose("Testing the no of avialable locales\n");
806 locCount=uloc_countAvailable();
808 log_data_err("countAvailable() returned an empty list!\n");
810 /* use something sensible w/o hardcoding the count */
811 else if(locCount < 0){
812 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount);
815 log_info("Number of locales returned = %d\n", locCount);
817 for(i=0;i<locCount;i++){
818 locList=uloc_getAvailable(i);
820 log_verbose(" %s\n", locList);
824 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
825 static void TestDataDirectory()
828 char oldDirectory[512];
829 const char *temp,*testValue1,*testValue2,*testValue3;
830 const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */
832 log_verbose("Testing getDataDirectory()\n");
833 temp = u_getDataDirectory();
834 strcpy(oldDirectory, temp);
836 testValue1=uloc_getISO3Language("en_US");
837 log_verbose("first fetch of language retrieved %s\n", testValue1);
839 if (0 != strcmp(testValue1,"eng")){
840 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1);
843 /*defining the path for DataDirectory */
844 log_verbose("Testing setDataDirectory\n");
845 u_setDataDirectory( path );
846 if(strcmp(path, u_getDataDirectory())==0)
847 log_verbose("setDataDirectory working fine\n");
849 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path);
851 testValue2=uloc_getISO3Language("en_US");
852 log_verbose("second fetch of language retrieved %s \n", testValue2);
854 u_setDataDirectory(oldDirectory);
855 testValue3=uloc_getISO3Language("en_US");
856 log_verbose("third fetch of language retrieved %s \n", testValue3);
858 if (0 != strcmp(testValue3,"eng")) {
859 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3);
865 /*=========================================================== */
869 static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
871 UErrorCode status = U_ZERO_ERROR;
873 int32_t maxresultsize;
875 const char *testLocale;
879 UChar *testScript = 0;
885 UChar* expectedLang = 0;
886 UChar* expectedScript = 0;
887 UChar* expectedCtry = 0;
888 UChar* expectedVar = 0;
889 UChar* expectedName = 0;
893 for(i=0;i<LOCALE_SIZE; ++i)
895 testLocale=rawData2[NAME][i];
897 log_verbose("Testing..... %s\n", testLocale);
900 maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
901 if(status==U_BUFFER_OVERFLOW_ERROR)
904 testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
905 uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
911 if(U_FAILURE(status)){
912 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
916 maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status);
917 if(status==U_BUFFER_OVERFLOW_ERROR)
920 testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
921 uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status);
927 if(U_FAILURE(status)){
928 log_err("Error in getDisplayScript() %s\n", myErrorName(status));
932 maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
933 if(status==U_BUFFER_OVERFLOW_ERROR)
936 testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
937 uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
943 if(U_FAILURE(status)){
944 log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
948 maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
949 if(status==U_BUFFER_OVERFLOW_ERROR)
952 testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
953 uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
959 if(U_FAILURE(status)){
960 log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
964 maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
965 if(status==U_BUFFER_OVERFLOW_ERROR)
968 testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
969 uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
975 if(U_FAILURE(status)){
976 log_err("Error in getDisplayName() %s\n", myErrorName(status));
979 expectedLang=dataTable[compareIndex][i];
980 if(u_strlen(expectedLang)== 0)
981 expectedLang=dataTable[DLANG_EN][i];
983 expectedScript=dataTable[compareIndex + 1][i];
984 if(u_strlen(expectedScript)== 0)
985 expectedScript=dataTable[DSCRIPT_EN][i];
987 expectedCtry=dataTable[compareIndex + 2][i];
988 if(u_strlen(expectedCtry)== 0)
989 expectedCtry=dataTable[DCTRY_EN][i];
991 expectedVar=dataTable[compareIndex + 3][i];
992 if(u_strlen(expectedVar)== 0)
993 expectedVar=dataTable[DVAR_EN][i];
995 expectedName=dataTable[compareIndex + 4][i];
996 if(u_strlen(expectedName) == 0)
997 expectedName=dataTable[DNAME_EN][i];
999 if (0 !=u_strcmp(testLang,expectedLang)) {
1000 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
1003 if (0 != u_strcmp(testScript,expectedScript)) {
1004 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale);
1007 if (0 != u_strcmp(testCtry,expectedCtry)) {
1008 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
1011 if (0 != u_strcmp(testVar,expectedVar)) {
1012 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
1015 if(0 != u_strcmp(testName, expectedName)) {
1016 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale);
1019 if(testName!=&_NUL) {
1022 if(testLang!=&_NUL) {
1025 if(testScript!=&_NUL) {
1028 if(testCtry!=&_NUL) {
1031 if(testVar!=&_NUL) {
1038 /*------------------------------
1039 * TestDisplayNameBrackets
1043 const char * displayLocale;
1044 const char * namedRegion;
1045 const char * namedLocale;
1046 const char * regionName;
1047 const char * localeName;
1048 } DisplayNameBracketsItem;
1050 static const DisplayNameBracketsItem displayNameBracketsItems[] = {
1051 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" },
1052 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" },
1053 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" },
1054 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1055 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1056 { NULL, NULL, NULL, NULL, NULL }
1059 enum { kDisplayNameBracketsMax = 128 };
1061 static void TestDisplayNameBrackets()
1063 const DisplayNameBracketsItem * itemPtr = displayNameBracketsItems;
1064 for (; itemPtr->displayLocale != NULL; itemPtr++) {
1065 ULocaleDisplayNames * uldn;
1067 UChar expectRegionName[kDisplayNameBracketsMax];
1068 UChar expectLocaleName[kDisplayNameBracketsMax];
1069 UChar getName[kDisplayNameBracketsMax];
1072 (void) u_unescape(itemPtr->regionName, expectRegionName, kDisplayNameBracketsMax);
1073 (void) u_unescape(itemPtr->localeName, expectLocaleName, kDisplayNameBracketsMax);
1075 status = U_ZERO_ERROR;
1076 ulen = uloc_getDisplayCountry(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1077 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1078 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1081 status = U_ZERO_ERROR;
1082 ulen = uloc_getDisplayName(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1083 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1084 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1087 #if !UCONFIG_NO_FORMATTING
1088 status = U_ZERO_ERROR;
1089 uldn = uldn_open(itemPtr->displayLocale, ULDN_STANDARD_NAMES, &status);
1090 if (U_SUCCESS(status)) {
1091 status = U_ZERO_ERROR;
1092 ulen = uldn_regionDisplayName(uldn, itemPtr->namedRegion, getName, kDisplayNameBracketsMax, &status);
1093 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1094 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedRegion, myErrorName(status));
1097 status = U_ZERO_ERROR;
1098 ulen = uldn_localeDisplayName(uldn, itemPtr->namedLocale, getName, kDisplayNameBracketsMax, &status);
1099 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1100 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1105 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr->displayLocale, u_errorName(status));
1108 (void)ulen; /* Suppress variable not used warning */
1112 /*------------------------------
1116 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1117 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1118 static void TestISOFunctions()
1120 const char* const* str=uloc_getISOLanguages();
1121 const char* const* str1=uloc_getISOCountries();
1123 const char *key = NULL;
1124 int32_t count = 0, skipped = 0;
1126 UResourceBundle *res;
1127 UResourceBundle *subRes;
1128 UErrorCode status = U_ZERO_ERROR;
1130 /* test getISOLanguages*/
1131 /*str=uloc_getISOLanguages(); */
1132 log_verbose("Testing ISO Languages: \n");
1134 /* use structLocale - this data is no longer in root */
1135 res = ures_openDirect(loadTestData(&status), "structLocale", &status);
1136 subRes = ures_getByKey(res, "Languages", NULL, &status);
1137 if (U_FAILURE(status)) {
1138 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status));
1142 expect = ures_getSize(subRes);
1143 for(count = 0; *(str+count) != 0; count++)
1146 test = *(str+count);
1147 status = U_ZERO_ERROR;
1150 /* Skip over language tags. This API only returns language codes. */
1151 skipped += (key != NULL);
1152 ures_getNextString(subRes, NULL, &key, &status);
1154 while (key != NULL && strchr(key, '_'));
1158 /* TODO: Consider removing sh, which is deprecated */
1159 if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) {
1160 ures_getNextString(subRes, NULL, &key, &status);
1163 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1164 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1165 if(strcmp(test,key)) {
1166 /* The first difference usually implies the place where things get out of sync */
1167 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1171 if(!strcmp(test,"in"))
1172 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1173 if(!strcmp(test,"iw"))
1174 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1175 if(!strcmp(test,"ji"))
1176 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1177 if(!strcmp(test,"jw"))
1178 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1179 if(!strcmp(test,"sh"))
1180 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1183 expect -= skipped; /* Ignore the skipped resources from structLocale */
1186 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect);
1189 subRes = ures_getByKey(res, "Countries", subRes, &status);
1190 log_verbose("Testing ISO Countries");
1192 expect = ures_getSize(subRes) - 1; /* Skip ZZ */
1193 for(count = 0; *(str1+count) != 0; count++)
1196 test = *(str1+count);
1198 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1199 skipped += (key != NULL);
1200 ures_getNextString(subRes, NULL, &key, &status);
1202 while (key != NULL && strlen(key) != 2);
1206 /* TODO: Consider removing CS, which is deprecated */
1207 while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) {
1208 ures_getNextString(subRes, NULL, &key, &status);
1211 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1212 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1213 if(strcmp(test,key)) {
1214 /* The first difference usually implies the place where things get out of sync */
1215 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1218 if(!strcmp(test,"FX"))
1219 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1220 if(!strcmp(test,"YU"))
1221 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1222 if(!strcmp(test,"ZR"))
1223 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1226 ures_getNextString(subRes, NULL, &key, &status);
1227 if (strcmp(key, "ZZ") != 0) {
1228 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key);
1230 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1231 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1234 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1235 skipped += (key != NULL);
1236 ures_getNextString(subRes, NULL, &key, &status);
1238 while (U_SUCCESS(status) && key != NULL && strlen(key) != 2);
1240 expect -= skipped; /* Ignore the skipped resources from structLocale */
1243 log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect);
1250 static void setUpDataTable()
1253 dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE));
1255 for (i = 0; i < LOCALE_INFO_SIZE; i++) {
1256 dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE));
1257 for (j = 0; j < LOCALE_SIZE; j++){
1258 dataTable[i][j] = CharsToUChars(rawData2[i][j]);
1263 static void cleanUpDataTable()
1266 if(dataTable != NULL) {
1267 for (i=0; i<LOCALE_INFO_SIZE; i++) {
1268 for(j = 0; j < LOCALE_SIZE; j++) {
1269 free(dataTable[i][j]);
1279 * @bug 4011756 4011380
1281 static void TestISO3Fallback()
1283 const char* test="xx_YY";
1285 const char * result;
1287 result = uloc_getISO3Language(test);
1289 /* Conform to C API usage */
1291 if (!result || (result[0] != 0))
1292 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1294 result = uloc_getISO3Country(test);
1296 if (!result || (result[0] != 0))
1297 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1303 static void TestSimpleDisplayNames()
1306 This test is different from TestDisplayNames because TestDisplayNames checks
1307 fallback behavior, combination of language and country names to form locale
1308 names, and other stuff like that. This test just checks specific language
1309 and country codes to make sure we have the correct names for them.
1311 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1312 const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1314 const char* inLocale [] = { "en_US", "zh_Hant"};
1315 UErrorCode status=U_ZERO_ERROR;
1318 int32_t localeIndex = 0;
1319 for (i = 0; i < 7; i++) {
1321 UChar *expectedLang=0;
1325 localeIndex = 1; /* Use the second locale for the rest of the test. */
1328 size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status);
1329 if(status==U_BUFFER_OVERFLOW_ERROR) {
1330 status=U_ZERO_ERROR;
1331 testLang=(UChar*)malloc(sizeof(UChar) * (size + 1));
1332 uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status);
1334 expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1));
1335 u_uastrcpy(expectedLang, languageNames[i]);
1336 if (u_strcmp(testLang, expectedLang) != 0)
1337 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1338 languageCodes[i], languageNames[i], austrdup(testLang));
1348 static void TestUninstalledISO3Names()
1350 /* This test checks to make sure getISO3Language and getISO3Country work right
1351 even for locales that are not installed. */
1352 static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
1354 static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
1355 "ssw", "twi", "zul" };
1356 static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1357 "ss_SB", "tw_TC", "zu_ZW" };
1358 static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1359 "SLB", "TCA", "ZWE" };
1362 for (i = 0; i < 8; i++) {
1363 UErrorCode err = U_ZERO_ERROR;
1365 test = uloc_getISO3Language(iso2Languages[i]);
1366 if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err))
1367 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1368 iso2Languages[i], iso3Languages[i], test, myErrorName(err));
1370 for (i = 0; i < 8; i++) {
1371 UErrorCode err = U_ZERO_ERROR;
1373 test = uloc_getISO3Country(iso2Countries[i]);
1374 if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err))
1375 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1376 iso2Countries[i], iso3Countries[i], test, myErrorName(err));
1381 static void TestVariantParsing()
1383 static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth";
1384 static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1385 static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1386 static const char* shortVariant="fr_FR_foo";
1387 static const char* bogusVariant="fr_FR__foo";
1388 static const char* bogusVariant2="fr_FR_foo_";
1389 static const char* bogusVariant3="fr_FR__foo_";
1392 UChar displayVar[100];
1393 UChar displayName[100];
1394 UErrorCode status=U_ZERO_ERROR;
1397 size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status);
1398 if(status==U_BUFFER_OVERFLOW_ERROR) {
1399 status=U_ZERO_ERROR;
1400 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1401 uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status);
1404 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1406 u_uastrcpy(displayVar, dispVar);
1407 if(u_strcmp(got,displayVar)!=0) {
1408 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got));
1411 size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status);
1412 if(status==U_BUFFER_OVERFLOW_ERROR) {
1413 status=U_ZERO_ERROR;
1414 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1415 uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status);
1418 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1420 u_uastrcpy(displayName, dispName);
1421 if(u_strcmp(got,displayName)!=0) {
1422 if (status == U_USING_DEFAULT_WARNING) {
1423 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status));
1425 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got));
1430 status=U_ZERO_ERROR;
1431 size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status);
1432 if(status==U_BUFFER_OVERFLOW_ERROR) {
1433 status=U_ZERO_ERROR;
1434 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1435 uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status);
1438 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1440 if(strcmp(austrdup(got),"FOO")!=0) {
1441 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got));
1444 status=U_ZERO_ERROR;
1445 size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status);
1446 if(status==U_BUFFER_OVERFLOW_ERROR) {
1447 status=U_ZERO_ERROR;
1448 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1449 uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status);
1452 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1454 if(strcmp(austrdup(got),"_FOO")!=0) {
1455 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got));
1458 status=U_ZERO_ERROR;
1459 size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status);
1460 if(status==U_BUFFER_OVERFLOW_ERROR) {
1461 status=U_ZERO_ERROR;
1462 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1463 uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status);
1466 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1468 if(strcmp(austrdup(got),"FOO_")!=0) {
1469 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got));
1472 status=U_ZERO_ERROR;
1473 size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status);
1474 if(status==U_BUFFER_OVERFLOW_ERROR) {
1475 status=U_ZERO_ERROR;
1476 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1477 uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status);
1480 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1482 if(strcmp(austrdup(got),"_FOO_")!=0) {
1483 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got));
1489 static void TestObsoleteNames(void)
1492 UErrorCode status = U_ZERO_ERROR;
1504 { "eng_USA", "eng", "en", "USA", "US" },
1505 { "kok", "kok", "kok", "", "" },
1506 { "in", "ind", "in", "", "" },
1507 { "id", "ind", "id", "", "" }, /* NO aliasing */
1508 { "sh", "srp", "sh", "", "" },
1509 { "zz_CS", "", "zz", "SCG", "CS" },
1510 { "zz_FX", "", "zz", "FXX", "FX" },
1511 { "zz_RO", "", "zz", "ROU", "RO" },
1512 { "zz_TP", "", "zz", "TMP", "TP" },
1513 { "zz_TL", "", "zz", "TLS", "TL" },
1514 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1515 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1516 { "zz_ROM", "", "zz", "ROU", "RO" },
1517 { "zz_ROU", "", "zz", "ROU", "RO" },
1518 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1519 { "zz_TMP", "", "zz", "TMP", "TP" },
1520 { "zz_TLS", "", "zz", "TLS", "TL" },
1521 { "zz_YUG", "", "zz", "YUG", "YU" },
1522 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1523 { "iw", "heb", "iw", "", "" },
1524 { "ji", "yid", "ji", "", "" },
1525 { "jw", "jaw", "jw", "", "" },
1526 { "sh", "srp", "sh", "", "" },
1527 { "", "", "", "", "" }
1530 for(i=0;tests[i].locale[0];i++)
1534 locale = tests[i].locale;
1535 log_verbose("** %s:\n", locale);
1537 status = U_ZERO_ERROR;
1538 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1540 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1541 locale, uloc_getISO3Language(locale), tests[i].lang3);
1545 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1546 uloc_getISO3Language(locale) );
1549 status = U_ZERO_ERROR;
1550 uloc_getLanguage(locale, buff, 256, &status);
1551 if(U_FAILURE(status))
1553 log_err("FAIL: error getting language from %s\n", locale);
1557 if(strcmp(buff,tests[i].lang))
1559 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1560 locale, buff, tests[i].lang);
1564 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff);
1567 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1569 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1570 locale, uloc_getISO3Language(locale), tests[i].lang3);
1574 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1575 uloc_getISO3Language(locale) );
1578 if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale)))
1580 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1581 locale, uloc_getISO3Country(locale), tests[i].ctry3);
1585 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1586 uloc_getISO3Country(locale) );
1589 status = U_ZERO_ERROR;
1590 uloc_getCountry(locale, buff, 256, &status);
1591 if(U_FAILURE(status))
1593 log_err("FAIL: error getting country from %s\n", locale);
1597 if(strcmp(buff,tests[i].ctry))
1599 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1600 locale, buff, tests[i].ctry);
1604 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff);
1609 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1610 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1613 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1614 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1619 i = uloc_getLanguage("kok",NULL,0,&icu_err);
1620 if(U_FAILURE(icu_err))
1622 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err));
1625 icu_err = U_ZERO_ERROR;
1626 uloc_getLanguage("kok",r1_buff,12,&icu_err);
1627 if(U_FAILURE(icu_err))
1629 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err));
1632 r1_addr = (char *)uloc_getISO3Language("kok");
1634 icu_err = U_ZERO_ERROR;
1635 if (strcmp(r1_buff,"kok") != 0)
1637 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff);
1640 r1_addr = (char *)uloc_getISO3Language("in");
1641 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1642 if (strcmp(r1_buff,"id") != 0)
1644 printf("uloc_getLanguage error (%s)\n",r1_buff);
1647 r1_addr = (char *)uloc_getISO3Language("sh");
1648 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1649 if (strcmp(r1_buff,"sr") != 0)
1651 printf("uloc_getLanguage error (%s)\n",r1_buff);
1655 r1_addr = (char *)uloc_getISO3Country("zz_ZR");
1656 strcpy(p1_buff,"zz_");
1657 strcat(p1_buff,r1_addr);
1658 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1659 if (strcmp(r1_buff,"ZR") != 0)
1661 printf("uloc_getCountry error (%s)\n",r1_buff);
1664 r1_addr = (char *)uloc_getISO3Country("zz_FX");
1665 strcpy(p1_buff,"zz_");
1666 strcat(p1_buff,r1_addr);
1667 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1668 if (strcmp(r1_buff,"FX") != 0)
1670 printf("uloc_getCountry error (%s)\n",r1_buff);
1678 static void TestKeywordVariants(void)
1680 static const struct {
1681 const char *localeID;
1682 const char *expectedLocaleID; /* uloc_getName */
1683 const char *expectedLocaleIDNoKeywords; /* uloc_getBaseName */
1684 const char *expectedCanonicalID; /* uloc_canonicalize */
1685 const char *expectedKeywords[10];
1686 int32_t numKeywords;
1687 UErrorCode expectedStatus; /* from uloc_openKeywords */
1690 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1691 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1693 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1694 {"calendar", "collation", "currency"},
1701 "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */
1702 "de_DE@currency=EUR",
1703 {"","","","","","",""},
1705 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1708 "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */
1709 "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1710 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1711 "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1712 {"","","","","","",""},
1714 U_INVALID_FORMAT_ERROR
1718 0, /* expected getName to fail */
1719 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1720 0, /* expected canonicalize to fail */
1721 {"","","","","","",""},
1723 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1726 UErrorCode status = U_ZERO_ERROR;
1728 int32_t i = 0, j = 0;
1729 int32_t resultLen = 0;
1731 UEnumeration *keywords;
1732 int32_t keyCount = 0;
1733 const char *keyword = NULL;
1734 int32_t keywordLen = 0;
1736 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1737 status = U_ZERO_ERROR;
1739 keywords = uloc_openKeywords(testCases[i].localeID, &status);
1741 if(status != testCases[i].expectedStatus) {
1742 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1743 testCases[i].localeID,
1744 u_errorName(testCases[i].expectedStatus), u_errorName(status));
1746 status = U_ZERO_ERROR;
1748 if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
1749 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1753 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1754 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1755 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1760 uenum_reset(keywords, &status);
1761 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1762 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1763 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1768 uenum_close(keywords);
1771 status = U_ZERO_ERROR;
1772 resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
1773 if (U_SUCCESS(status)) {
1774 if (testCases[i].expectedLocaleID == 0) {
1775 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1776 testCases[i].localeID, buffer);
1777 } else if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
1778 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1779 testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
1782 if (testCases[i].expectedLocaleID != 0) {
1783 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1784 testCases[i].localeID, testCases[i].expectedLocaleID, buffer, u_errorName(status));
1788 status = U_ZERO_ERROR;
1789 resultLen = uloc_getBaseName(testCases[i].localeID, buffer, 256, &status);
1790 if (U_SUCCESS(status)) {
1791 if (testCases[i].expectedLocaleIDNoKeywords == 0) {
1792 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
1793 testCases[i].localeID, buffer);
1794 } else if (uprv_strcmp(testCases[i].expectedLocaleIDNoKeywords, buffer) != 0) {
1795 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
1796 testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer);
1799 if (testCases[i].expectedLocaleIDNoKeywords != 0) {
1800 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
1801 testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer, u_errorName(status));
1805 status = U_ZERO_ERROR;
1806 resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
1807 if (U_SUCCESS(status)) {
1808 if (testCases[i].expectedCanonicalID == 0) {
1809 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
1810 testCases[i].localeID, buffer);
1811 } else if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
1812 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1813 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
1816 if (testCases[i].expectedCanonicalID != 0) {
1817 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
1818 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer, u_errorName(status));
1824 static void TestKeywordVariantParsing(void)
1826 static const struct {
1827 const char *localeID;
1828 const char *keyword;
1829 const char *expectedValue;
1831 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
1832 { "de_DE", "collation", ""},
1833 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1834 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1837 UErrorCode status = U_ZERO_ERROR;
1840 int32_t resultLen = 0;
1843 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1845 resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
1846 (void)resultLen; /* Suppress set but not used warning. */
1847 if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
1848 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1849 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
1854 static const struct {
1855 const char *l; /* locale */
1856 const char *k; /* kw */
1857 const char *v; /* value */
1858 const char *x; /* expected */
1859 } kwSetTestCases[] = {
1861 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1862 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1863 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1864 { "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 */
1865 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1866 { "de", "Currency", "CHF", "de@currency=CHF" },
1867 { "de", "Currency", "CHF", "de@currency=CHF" },
1869 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1870 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1871 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1872 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1873 { "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 */
1874 { "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 */
1875 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1876 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1879 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1880 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1881 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1882 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1883 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1884 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1885 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1886 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1887 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1891 /* 1. removal of item at end */
1892 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1893 { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
1894 /* 2. removal of item at beginning */
1895 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1896 { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
1897 /* 3. removal of an item not there */
1898 { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
1899 /* 4. removal of only item */
1900 { "de@collation=phonebook", "collation", NULL, "de" },
1902 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1906 static void TestKeywordSet(void)
1909 int32_t resultLen = 0;
1914 for(i = 0; i < UPRV_LENGTHOF(kwSetTestCases); i++) {
1915 UErrorCode status = U_ZERO_ERROR;
1916 memset(buffer,'%',1023);
1917 strcpy(buffer, kwSetTestCases[i].l);
1919 uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
1920 if(strcmp(buffer,cbuffer)) {
1921 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
1923 /* sanity check test case results for canonicity */
1924 uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
1925 if(strcmp(kwSetTestCases[i].x,cbuffer)) {
1926 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
1929 resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
1930 if(U_FAILURE(status)) {
1931 log_err("Err on test case %d: got error %s\n", i, u_errorName(status));
1934 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
1935 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1936 kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
1938 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
1943 static void TestKeywordSetError(void)
1951 /* 0-test whether an error condition modifies the buffer at all */
1954 memset(buffer,'%',1023);
1955 status = U_ZERO_ERROR;
1956 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1957 if(status != U_ILLEGAL_ARGUMENT_ERROR) {
1958 log_err("expected illegal err got %s\n", u_errorName(status));
1961 /* if(res!=strlen(kwSetTestCases[i].x)) {
1962 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1965 if(buffer[blen]!='%') {
1966 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1969 log_verbose("0-buffer modify OK\n");
1972 /* 1- test a short buffer with growing text */
1973 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1974 memset(buffer,'%',1023);
1975 strcpy(buffer,kwSetTestCases[i].l);
1976 status = U_ZERO_ERROR;
1977 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1978 if(status != U_BUFFER_OVERFLOW_ERROR) {
1979 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);
1982 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
1983 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1986 if(buffer[blen]!='%') {
1987 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1990 log_verbose("1/%d-buffer modify OK\n",i);
1994 /* 2- test a short buffer - text the same size or shrinking */
1995 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1996 memset(buffer,'%',1023);
1997 strcpy(buffer,kwSetTestCases[i].l);
1998 status = U_ZERO_ERROR;
1999 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2000 if(status != U_ZERO_ERROR) {
2001 log_err("expected zero error got %s\n", u_errorName(status));
2004 if(buffer[blen+1]!='%') {
2005 log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
2008 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
2009 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2012 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
2013 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
2014 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
2016 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
2019 log_verbose("2/%d-buffer modify OK\n",i);
2023 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
2024 const char* localeID,
2026 int32_t resultCapacity,
2028 /* YOU can change this to use function pointers if you like */
2031 return uloc_getName(localeID, result, resultCapacity, ec);
2033 return uloc_canonicalize(localeID, result, resultCapacity, ec);
2039 static void TestCanonicalization(void)
2041 static const struct {
2042 const char *localeID; /* input */
2043 const char *getNameID; /* expected getName() result */
2044 const char *canonicalID; /* expected canonicalize() result */
2046 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2047 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2048 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2049 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
2050 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
2051 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
2052 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2053 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2054 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2055 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2056 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2057 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2058 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2059 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2060 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2061 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2062 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2063 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2064 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2065 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2066 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2067 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2068 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2069 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2070 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2071 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2072 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2073 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2074 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2075 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2076 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2077 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2078 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2079 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
2080 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2081 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2082 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2083 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2084 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2085 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2086 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2087 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2088 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2089 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2090 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2091 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2092 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2093 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2094 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2095 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2096 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2098 /* posix behavior that used to be performed by getName */
2099 { "mr.utf8", "mr.utf8", "mr" },
2100 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2101 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2102 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2103 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2104 { "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 */
2106 /* fleshing out canonicalization */
2107 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2108 { "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" },
2109 /* already-canonical ids are not changed */
2110 { "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" },
2111 /* PRE_EURO and EURO conversions don't affect other keywords */
2112 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2113 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2114 /* currency keyword overrides PRE_EURO and EURO currency */
2115 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2116 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2117 /* norwegian is just too weird, if we handle things in their full generality */
2118 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2120 /* test cases reflecting internal resource bundle usage */
2121 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2122 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2123 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2124 { "ja_JP", "ja_JP", "ja_JP" },
2126 /* test case for "i-default" */
2127 { "i-default", "en@x=i-default", "en@x=i-default" }
2130 static const char* label[] = { "getName", "canonicalize" };
2132 UErrorCode status = U_ZERO_ERROR;
2133 int32_t i, j, resultLen = 0, origResultLen;
2136 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
2137 for (j=0; j<2; ++j) {
2138 const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
2140 status = U_ZERO_ERROR;
2142 if (expected == NULL) {
2143 expected = uloc_getDefault();
2146 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2147 origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
2148 if (status != U_BUFFER_OVERFLOW_ERROR) {
2149 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2150 label[j], testCases[i].localeID, u_errorName(status));
2153 status = U_ZERO_ERROR;
2154 resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
2155 if (U_FAILURE(status)) {
2156 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2157 label[j], testCases[i].localeID, u_errorName(status));
2160 if(uprv_strcmp(expected, buffer) != 0) {
2161 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2162 label[j], testCases[i].localeID, buffer, expected);
2164 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2165 label[j], testCases[i].localeID, buffer);
2167 if (resultLen != (int32_t)strlen(buffer)) {
2168 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2169 label[j], testCases[i].localeID, resultLen, strlen(buffer));
2171 if (origResultLen != resultLen) {
2172 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2173 label[j], testCases[i].localeID, origResultLen, resultLen);
2179 static void TestDisplayKeywords(void)
2183 static const struct {
2184 const char *localeID;
2185 const char *displayLocale;
2186 UChar displayKeyword[200];
2188 { "ca_ES@currency=ESP", "de_AT",
2189 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2191 { "ja_JP@calendar=japanese", "de",
2192 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2194 { "de_DE@collation=traditional", "de_DE",
2195 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2198 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2199 UErrorCode status = U_ZERO_ERROR;
2200 const char* keyword =NULL;
2201 int32_t keywordLen = 0;
2202 int32_t keywordCount = 0;
2203 UChar *displayKeyword=NULL;
2204 int32_t displayKeywordLen = 0;
2205 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2206 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2207 if(U_FAILURE(status)){
2208 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
2211 /* the uenum_next returns NUL terminated string */
2212 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2213 /* fetch the displayKeyword */
2214 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2215 if(status==U_BUFFER_OVERFLOW_ERROR){
2216 status = U_ZERO_ERROR;
2217 displayKeywordLen++; /* for null termination */
2218 displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
2219 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2220 if(U_FAILURE(status)){
2221 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));
2224 if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
2225 if (status == U_USING_DEFAULT_WARNING) {
2226 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));
2228 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);
2233 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
2236 free(displayKeyword);
2239 uenum_close(keywordEnum);
2243 static void TestDisplayKeywordValues(void){
2246 static const struct {
2247 const char *localeID;
2248 const char *displayLocale;
2249 UChar displayKeywordValue[500];
2251 { "ca_ES@currency=ESP", "de_AT",
2252 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2254 { "de_AT@currency=ATS", "fr_FR",
2255 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2257 { "de_DE@currency=DEM", "it",
2258 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2260 { "el_GR@currency=GRD", "en",
2261 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2263 { "eu_ES@currency=ESP", "it_IT",
2264 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2266 { "de@collation=phonebook", "es",
2267 {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}
2270 { "de_DE@collation=phonebook", "es",
2271 {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}
2273 { "es_ES@collation=traditional","de",
2274 {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}
2276 { "ja_JP@calendar=japanese", "de",
2277 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2280 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2281 UErrorCode status = U_ZERO_ERROR;
2282 const char* keyword =NULL;
2283 int32_t keywordLen = 0;
2284 int32_t keywordCount = 0;
2285 UChar *displayKeywordValue = NULL;
2286 int32_t displayKeywordValueLen = 0;
2287 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2288 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2289 if(U_FAILURE(status)){
2290 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));
2293 /* the uenum_next returns NUL terminated string */
2294 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2296 /* fetch the displayKeywordValue */
2297 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2298 if(status==U_BUFFER_OVERFLOW_ERROR){
2299 status = U_ZERO_ERROR;
2300 displayKeywordValueLen++; /* for null termination */
2301 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2302 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2303 if(U_FAILURE(status)){
2304 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));
2307 if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
2308 if (status == U_USING_DEFAULT_WARNING) {
2309 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));
2311 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));
2316 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2318 free(displayKeywordValue);
2320 uenum_close(keywordEnum);
2323 /* test a multiple keywords */
2324 UErrorCode status = U_ZERO_ERROR;
2325 const char* keyword =NULL;
2326 int32_t keywordLen = 0;
2327 int32_t keywordCount = 0;
2328 const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
2329 const char* displayLocale = "de";
2330 static const UChar expected[][50] = {
2331 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2333 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2334 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2337 UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
2339 for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
2340 UChar *displayKeywordValue = NULL;
2341 int32_t displayKeywordValueLen = 0;
2342 if(U_FAILURE(status)){
2343 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
2346 /* the uenum_next returns NUL terminated string */
2347 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2349 /* fetch the displayKeywordValue */
2350 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2351 if(status==U_BUFFER_OVERFLOW_ERROR){
2352 status = U_ZERO_ERROR;
2353 displayKeywordValueLen++; /* for null termination */
2354 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2355 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2356 if(U_FAILURE(status)){
2357 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));
2360 if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
2361 if (status == U_USING_DEFAULT_WARNING) {
2362 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));
2364 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
2369 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2371 free(displayKeywordValue);
2373 uenum_close(keywordEnum);
2377 /* Test non existent keywords */
2378 UErrorCode status = U_ZERO_ERROR;
2379 const char* localeID = "es";
2380 const char* displayLocale = "de";
2381 UChar *displayKeywordValue = NULL;
2382 int32_t displayKeywordValueLen = 0;
2384 /* fetch the displayKeywordValue */
2385 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2386 if(U_FAILURE(status)) {
2387 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
2388 } else if(displayKeywordValueLen != 0) {
2389 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
2395 static void TestGetBaseName(void) {
2396 static const struct {
2397 const char *localeID;
2398 const char *baseName;
2400 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2401 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2402 { "ja@calendar = buddhist", "ja" }
2405 int32_t i = 0, baseNameLen = 0;
2407 UErrorCode status = U_ZERO_ERROR;
2409 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2410 baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
2411 (void)baseNameLen; /* Suppress set but not used warning. */
2412 if(strcmp(testCases[i].baseName, baseName)) {
2413 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2414 testCases[i].localeID, testCases[i].baseName, baseName);
2420 static void TestTrailingNull(void) {
2421 const char* localeId = "zh_Hans";
2422 UChar buffer[128]; /* sufficient for this test */
2424 UErrorCode status = U_ZERO_ERROR;
2427 len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status);
2429 log_err("buffer too small");
2433 for (i = 0; i < len; ++i) {
2434 if (buffer[i] == 0) {
2435 log_err("name contained null");
2441 /* Jitterbug 4115 */
2442 static void TestDisplayNameWarning(void) {
2445 UErrorCode status = U_ZERO_ERROR;
2447 size = uloc_getDisplayLanguage("qqq", "kl", name, UPRV_LENGTHOF(name), &status);
2448 (void)size; /* Suppress set but not used warning. */
2449 if (status != U_USING_DEFAULT_WARNING) {
2450 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2451 u_errorName(status));
2457 * Compare two locale IDs. If they are equal, return 0. If `string'
2458 * starts with `prefix' plus an additional element, that is, string ==
2459 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2461 static UBool _loccmp(const char* string, const char* prefix) {
2462 int32_t slen = (int32_t)uprv_strlen(string),
2463 plen = (int32_t)uprv_strlen(prefix);
2464 int32_t c = uprv_strncmp(string, prefix, plen);
2465 /* 'root' is less than everything */
2466 if (uprv_strcmp(prefix, "root") == 0) {
2467 return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
2469 if (c) return -1; /* mismatch */
2470 if (slen == plen) return 0;
2471 if (string[plen] == '_') return 1;
2472 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2475 static void _checklocs(const char* label,
2478 const char* actual) {
2479 /* We want the valid to be strictly > the bogus requested locale,
2480 and the valid to be >= the actual. */
2481 if (_loccmp(req, valid) > 0 &&
2482 _loccmp(valid, actual) >= 0) {
2483 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2484 label, req, valid, actual);
2486 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2487 label, req, valid, actual);
2491 static void TestGetLocale(void) {
2492 UErrorCode ec = U_ZERO_ERROR;
2494 UChar EMPTY[1] = {0};
2497 #if !UCONFIG_NO_FORMATTING
2500 const char *req = "en_US_REDWOODSHORES", *valid, *actual;
2501 obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
2505 if (U_FAILURE(ec)) {
2506 log_data_err("udat_open failed.Error %s\n", u_errorName(ec));
2509 valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2510 actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2511 if (U_FAILURE(ec)) {
2512 log_err("udat_getLocaleByType() failed\n");
2515 _checklocs("udat", req, valid, actual);
2521 #if !UCONFIG_NO_FORMATTING
2524 const char *req = "fr_FR_PROVENCAL", *valid, *actual;
2525 obj = ucal_open(NULL, 0,
2529 if (U_FAILURE(ec)) {
2530 log_err("ucal_open failed with error: %s\n", u_errorName(ec));
2533 valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2534 actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2535 if (U_FAILURE(ec)) {
2536 log_err("ucal_getLocaleByType() failed\n");
2539 _checklocs("ucal", req, valid, actual);
2545 #if !UCONFIG_NO_FORMATTING
2548 const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
2549 obj = unum_open(UNUM_DECIMAL,
2553 if (U_FAILURE(ec)) {
2554 log_err("unum_open failed\n");
2557 valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2558 actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2559 if (U_FAILURE(ec)) {
2560 log_err("unum_getLocaleByType() failed\n");
2563 _checklocs("unum", req, valid, actual);
2570 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2571 #if !UCONFIG_NO_FORMATTING
2573 UMessageFormat *obj;
2574 const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
2576 obj = umsg_open(EMPTY, 0,
2579 if (U_FAILURE(ec)) {
2580 log_err("umsg_open failed\n");
2583 valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2584 actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2585 if (U_FAILURE(ec)) {
2586 log_err("umsg_getLocaleByType() failed\n");
2589 /* We want the valid to be strictly > the bogus requested locale,
2590 and the valid to be >= the actual. */
2591 /* TODO MessageFormat is currently just storing the locale it is given.
2592 As a result, it will return whatever it was given, even if the
2593 locale is invalid. */
2594 test = (_cmpversion("3.2") <= 0) ?
2595 /* Here is the weakened test for 3.0: */
2596 (_loccmp(req, valid) >= 0) :
2597 /* Here is what the test line SHOULD be: */
2598 (_loccmp(req, valid) > 0);
2601 _loccmp(valid, actual) >= 0) {
2602 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2604 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2612 #if !UCONFIG_NO_BREAK_ITERATION
2614 UBreakIterator *obj;
2615 const char *req = "ar_KW_ABDALI", *valid, *actual;
2616 obj = ubrk_open(UBRK_WORD,
2621 if (U_FAILURE(ec)) {
2622 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
2625 valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2626 actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2627 if (U_FAILURE(ec)) {
2628 log_err("ubrk_getLocaleByType() failed\n");
2631 _checklocs("ubrk", req, valid, actual);
2637 #if !UCONFIG_NO_COLLATION
2640 const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
2641 obj = ucol_open(req, &ec);
2642 if (U_FAILURE(ec)) {
2643 log_err("ucol_open failed - %s\n", u_errorName(ec));
2646 valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2647 actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2648 if (U_FAILURE(ec)) {
2649 log_err("ucol_getLocaleByType() failed\n");
2652 _checklocs("ucol", req, valid, actual);
2657 static void TestEnglishExemplarCharacters(void) {
2658 UErrorCode status = U_ZERO_ERROR;
2661 UChar testChars[] = {
2662 0x61, /* standard */
2663 0xE1, /* auxiliary */
2665 0x2D /* punctuation */
2667 ULocaleData *uld = ulocdata_open("en", &status);
2668 if (U_FAILURE(status)) {
2669 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status));
2673 for (i = 0; i < ULOCDATA_ES_COUNT; i++) {
2674 exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status);
2675 if (U_FAILURE(status)) {
2676 log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i);
2677 status = U_ZERO_ERROR;
2680 if (!uset_contains(exSet, (UChar32)testChars[i])) {
2681 log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i);
2686 ulocdata_close(uld);
2689 static void TestNonexistentLanguageExemplars(void) {
2690 /* JB 4068 - Nonexistent language */
2691 UErrorCode ec = U_ZERO_ERROR;
2692 ULocaleData *uld = ulocdata_open("qqq",&ec);
2693 if (ec != U_USING_DEFAULT_WARNING) {
2694 log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2697 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2698 ulocdata_close(uld);
2701 static void TestLocDataErrorCodeChaining(void) {
2702 UErrorCode ec = U_USELESS_COLLATOR_ERROR;
2703 ulocdata_open(NULL, &ec);
2704 ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
2705 ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
2706 ulocdata_getMeasurementSystem(NULL, &ec);
2707 ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
2708 if (ec != U_USELESS_COLLATOR_ERROR) {
2709 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
2715 UMeasurementSystem measureSys;
2718 static const LocToMeasureSys locToMeasures[] = {
2719 { "fr_FR", UMS_SI },
2721 { "en_GB", UMS_UK },
2722 { "fr_FR@rg=GBZZZZ", UMS_UK },
2723 { "en@rg=frzzzz", UMS_SI },
2724 { "en_GB@rg=USZZZZ", UMS_US },
2725 { NULL, (UMeasurementSystem)0 } /* terminator */
2728 static void TestLocDataWithRgTag(void) {
2729 const LocToMeasureSys* locToMeasurePtr = locToMeasures;
2730 for (; locToMeasurePtr->locale != NULL; locToMeasurePtr++) {
2731 UErrorCode status = U_ZERO_ERROR;
2732 UMeasurementSystem measureSys = ulocdata_getMeasurementSystem(locToMeasurePtr->locale, &status);
2733 if (U_FAILURE(status)) {
2734 log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
2735 locToMeasurePtr->locale, u_errorName(status));
2736 } else if (measureSys != locToMeasurePtr->measureSys) {
2737 log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
2738 locToMeasurePtr->locale, (int) locToMeasurePtr->measureSys, (int)measureSys);
2743 static void TestLanguageExemplarsFallbacks(void) {
2744 /* Test that en_US fallsback, but en doesn't fallback. */
2745 UErrorCode ec = U_ZERO_ERROR;
2746 ULocaleData *uld = ulocdata_open("en_US",&ec);
2747 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2748 if (ec != U_USING_FALLBACK_WARNING) {
2749 log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2752 ulocdata_close(uld);
2754 uld = ulocdata_open("en",&ec);
2755 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2756 if (ec != U_ZERO_ERROR) {
2757 log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2760 ulocdata_close(uld);
2763 static const char *acceptResult(UAcceptResult uar) {
2764 return udbg_enumName(UDBG_UAcceptResult, uar);
2767 static void TestAcceptLanguage(void) {
2768 UErrorCode status = U_ZERO_ERROR;
2769 UAcceptResult outResult;
2770 UEnumeration *available;
2776 int32_t httpSet; /**< Which of http[] should be used? */
2777 const char *icuSet; /**< ? */
2778 const char *expect; /**< The expected locale result */
2779 UAcceptResult res; /**< The expected error code */
2780 UErrorCode expectStatus; /**< expected status */
2782 /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2783 /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2784 /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},
2785 /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR},
2786 /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2787 /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, /* XF */
2788 /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
2789 /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
2790 /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
2791 /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
2792 /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
2793 /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
2795 const int32_t numTests = UPRV_LENGTHOF(tests);
2796 static const char *http[] = {
2797 /*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",
2798 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2799 /*2*/ "en-wf, de-lx;q=0.8",
2800 /*3*/ "mga-ie;q=0.9, tlh",
2801 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2802 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2803 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2804 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2805 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2806 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2807 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2809 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2811 /*7*/ "zh-xx;q=0.9",
2812 /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2813 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2814 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2815 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
2816 /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2817 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2818 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2819 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
2820 /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2821 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2822 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2823 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
2824 /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2825 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2826 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2827 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
2830 for(i=0;i<numTests;i++) {
2832 status=U_ZERO_ERROR;
2833 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2834 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2836 available = ures_openAvailableLocales(tests[i].icuSet, &status);
2838 rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status);
2839 (void)rc; /* Suppress set but not used warning. */
2840 uenum_close(available);
2841 log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
2842 if(status != tests[i].expectStatus) {
2843 log_err_status(status, "FAIL: expected status %s but got %s\n", u_errorName(tests[i].expectStatus), u_errorName(status));
2844 } else if(U_SUCCESS(tests[i].expectStatus)) {
2845 /* don't check content if expected failure */
2846 if(outResult != tests[i].res) {
2847 log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
2848 acceptResult( tests[i].res),
2849 acceptResult( outResult));
2850 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2851 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res));
2853 if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
2854 log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
2855 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2856 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2862 static const char* LOCALE_ALIAS[][2] = {
2876 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
2877 UErrorCode status = U_ZERO_ERROR;
2879 ures_getStringByKey(resIndex, loc,&len, &status);
2880 if(U_FAILURE(status)){
2886 static void TestCalendar() {
2887 #if !UCONFIG_NO_FORMATTING
2889 UErrorCode status = U_ZERO_ERROR;
2890 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2891 if(U_FAILURE(status)){
2892 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2895 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2896 const char* oldLoc = LOCALE_ALIAS[i][0];
2897 const char* newLoc = LOCALE_ALIAS[i][1];
2898 UCalendar* c1 = NULL;
2899 UCalendar* c2 = NULL;
2901 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2902 const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2903 const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2905 if(!isLocaleAvailable(resIndex, newLoc)){
2908 c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
2909 c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
2911 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
2912 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2914 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2);
2918 ures_close(resIndex);
2922 static void TestDateFormat() {
2923 #if !UCONFIG_NO_FORMATTING
2925 UErrorCode status = U_ZERO_ERROR;
2926 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2927 if(U_FAILURE(status)){
2928 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2931 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2932 const char* oldLoc = LOCALE_ALIAS[i][0];
2933 const char* newLoc = LOCALE_ALIAS[i][1];
2934 UDateFormat* df1 = NULL;
2935 UDateFormat* df2 = NULL;
2936 const char* l1 = NULL;
2937 const char* l2 = NULL;
2939 if(!isLocaleAvailable(resIndex, newLoc)){
2942 df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
2943 df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
2944 if(U_FAILURE(status)){
2945 log_err("Creation of date format failed %s\n", u_errorName(status));
2948 /*Test function "getLocale"*/
2949 l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
2950 l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
2951 if(U_FAILURE(status)){
2952 log_err("Fetching the locale by type failed. %s\n", u_errorName(status));
2954 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2955 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2957 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2);
2961 ures_close(resIndex);
2965 static void TestCollation() {
2966 #if !UCONFIG_NO_COLLATION
2968 UErrorCode status = U_ZERO_ERROR;
2969 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2970 if(U_FAILURE(status)){
2971 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2974 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2975 const char* oldLoc = LOCALE_ALIAS[i][0];
2976 const char* newLoc = LOCALE_ALIAS[i][1];
2977 UCollator* c1 = NULL;
2978 UCollator* c2 = NULL;
2979 const char* l1 = NULL;
2980 const char* l2 = NULL;
2982 status = U_ZERO_ERROR;
2983 if(!isLocaleAvailable(resIndex, newLoc)){
2986 if(U_FAILURE(status)){
2987 log_err("Creation of collators failed %s\n", u_errorName(status));
2990 c1 = ucol_open(oldLoc, &status);
2991 c2 = ucol_open(newLoc, &status);
2992 l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2993 l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2994 if(U_FAILURE(status)){
2995 log_err("Fetching the locale names failed failed %s\n", u_errorName(status));
2997 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2998 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3000 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2);
3004 ures_close(resIndex);
3008 typedef struct OrientationStructTag {
3009 const char* localeId;
3010 ULayoutType character;
3012 } OrientationStruct;
3014 static const char* ULayoutTypeToString(ULayoutType type)
3018 case ULOC_LAYOUT_LTR:
3019 return "ULOC_LAYOUT_LTR";
3021 case ULOC_LAYOUT_RTL:
3022 return "ULOC_LAYOUT_RTL";
3024 case ULOC_LAYOUT_TTB:
3025 return "ULOC_LAYOUT_TTB";
3027 case ULOC_LAYOUT_BTT:
3028 return "ULOC_LAYOUT_BTT";
3030 case ULOC_LAYOUT_UNKNOWN:
3034 return "Unknown enum value for ULayoutType!";
3037 static void TestOrientation()
3039 static const OrientationStruct toTest [] = {
3040 { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3041 { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3042 { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3043 { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3044 { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3045 { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3046 { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3047 { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3048 { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3049 { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB }
3053 for (; i < UPRV_LENGTHOF(toTest); ++i) {
3054 UErrorCode statusCO = U_ZERO_ERROR;
3055 UErrorCode statusLO = U_ZERO_ERROR;
3056 const char* const localeId = toTest[i].localeId;
3057 const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO);
3058 const ULayoutType expectedCO = toTest[i].character;
3059 const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO);
3060 const ULayoutType expectedLO = toTest[i].line;
3061 if (U_FAILURE(statusCO)) {
3062 log_err_status(statusCO,
3063 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3065 u_errorName(statusCO));
3067 else if (co != expectedCO) {
3069 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3071 ULayoutTypeToString(expectedCO),
3072 ULayoutTypeToString(co));
3074 if (U_FAILURE(statusLO)) {
3075 log_err_status(statusLO,
3076 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3078 u_errorName(statusLO));
3080 else if (lo != expectedLO) {
3082 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3084 ULayoutTypeToString(expectedLO),
3085 ULayoutTypeToString(lo));
3090 static void TestULocale() {
3092 UErrorCode status = U_ZERO_ERROR;
3093 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3094 if(U_FAILURE(status)){
3095 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3098 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3099 const char* oldLoc = LOCALE_ALIAS[i][0];
3100 const char* newLoc = LOCALE_ALIAS[i][1];
3101 UChar name1[256], name2[256];
3102 char names1[256], names2[256];
3103 int32_t capacity = 256;
3105 status = U_ZERO_ERROR;
3106 if(!isLocaleAvailable(resIndex, newLoc)){
3109 uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
3110 if(U_FAILURE(status)){
3111 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
3114 uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
3115 if(U_FAILURE(status)){
3116 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
3119 if (u_strcmp(name1, name2)!=0) {
3120 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3122 u_austrcpy(names1, name1);
3123 u_austrcpy(names2, name2);
3124 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2);
3126 ures_close(resIndex);
3130 static void TestUResourceBundle() {
3134 UResourceBundle* rb1 = NULL;
3135 UResourceBundle* rb2 = NULL;
3136 UErrorCode status = U_ZERO_ERROR;
3138 UResourceBundle *resIndex = NULL;
3139 if(U_FAILURE(status)){
3140 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3143 resIndex = ures_open(NULL,"res_index", &status);
3144 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3146 const char* oldLoc = LOCALE_ALIAS[i][0];
3147 const char* newLoc = LOCALE_ALIAS[i][1];
3148 if(!isLocaleAvailable(resIndex, newLoc)){
3151 rb1 = ures_open(NULL, oldLoc, &status);
3152 if (U_FAILURE(status)) {
3153 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3156 us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status);
3158 status = U_ZERO_ERROR;
3159 rb2 = ures_open(NULL, newLoc, &status);
3160 if (U_FAILURE(status)) {
3161 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3163 us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status);
3165 if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
3166 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3169 log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2);
3175 ures_close(resIndex);
3178 static void TestDisplayName() {
3180 UChar oldCountry[256] = {'\0'};
3181 UChar newCountry[256] = {'\0'};
3182 UChar oldLang[256] = {'\0'};
3183 UChar newLang[256] = {'\0'};
3184 char country[256] ={'\0'};
3185 char language[256] ={'\0'};
3186 int32_t capacity = 256;
3189 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3190 const char* oldLoc = LOCALE_ALIAS[i][0];
3191 const char* newLoc = LOCALE_ALIAS[i][1];
3192 UErrorCode status = U_ZERO_ERROR;
3193 int32_t available = uloc_countAvailable();
3195 for(j=0; j<available; j++){
3197 const char* dispLoc = uloc_getAvailable(j);
3198 int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
3199 int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
3200 int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
3201 int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
3203 int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
3204 int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status);
3205 /* there is a display name for the current country ID */
3206 if(countryLen != newCountryLen ){
3207 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
3208 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
3211 /* there is a display name for the current lang ID */
3212 if(langLen!=newLangLen){
3213 if(u_strncmp(oldLang,newLang,oldLangLen)){
3214 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); }
3220 static void TestGetLocaleForLCID() {
3221 int32_t i, length, lengthPre;
3222 const char* testLocale = 0;
3223 UErrorCode status = U_ZERO_ERROR;
3224 char temp2[40], temp3[40];
3227 lcid = uloc_getLCID("en_US");
3228 if (lcid != 0x0409) {
3229 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
3232 lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
3233 if (status != U_BUFFER_OVERFLOW_ERROR) {
3234 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
3237 status = U_ZERO_ERROR;
3240 length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3241 if (U_FAILURE(status)) {
3242 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
3243 status = U_ZERO_ERROR;
3246 if (length != lengthPre) {
3247 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
3250 length = uloc_getLocaleForLCID(0x12345, temp2, UPRV_LENGTHOF(temp2), &status);
3251 if (U_SUCCESS(status)) {
3252 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
3254 status = U_ZERO_ERROR;
3256 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3257 for (i = 0; i < LOCALE_SIZE; i++) {
3259 testLocale=rawData2[NAME][i];
3261 log_verbose("Testing %s ......\n", testLocale);
3263 sscanf(rawData2[LCID][i], "%x", &lcid);
3264 length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3265 if (U_FAILURE(status)) {
3266 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
3267 status = U_ZERO_ERROR;
3271 if (length != uprv_strlen(temp2)) {
3272 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
3275 /* Compare language, country, script */
3276 length = uloc_getLanguage(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3277 if (U_FAILURE(status)) {
3278 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3279 status = U_ZERO_ERROR;
3281 else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
3282 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
3285 length = uloc_getScript(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3286 if (U_FAILURE(status)) {
3287 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3288 status = U_ZERO_ERROR;
3290 else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
3291 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
3294 length = uloc_getCountry(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3295 if (U_FAILURE(status)) {
3296 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3297 status = U_ZERO_ERROR;
3299 else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
3300 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
3306 const char* const basic_maximize_data[][2] = {
3351 "en_Latn_US_POSIX_1901"
3353 "en_Latn__POSIX_1901",
3354 "en_Latn_US_POSIX_1901"
3357 "en_Latn_US_POSIX_1901"
3360 "de_Latn_DE_POSIX_1901"
3365 "th@calendar=buddhist",
3366 "th_Thai_TH@calendar=buddhist"
3396 "de_Latn_DE_U_CO_PHONEBK"
3398 "de_Latn_u_co_phonebk",
3399 "de_Latn_DE_U_CO_PHONEBK"
3401 "de_Latn_DE_u_co_phonebk",
3402 "de_Latn_DE_U_CO_PHONEBK"
3406 const char* const basic_minimize_data[][2] = {
3411 "en_Latn_US_POSIX_1901",
3414 "EN_Latn_US_POSIX_1901",
3417 "en_Zzzz_US_POSIX_1901",
3420 "de_Latn_DE_POSIX_1901",
3426 "en_Latn_US@calendar=gregorian",
3427 "en@calendar=gregorian"
3431 const char* const full_data[][3] = {
3435 /* "REMOVE-LIKELY" */
4918 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
4919 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5501 "de@collation=phonebook",
5502 "de_Latn_DE@collation=phonebook",
5503 "de@collation=phonebook"
5507 typedef struct errorDataTag {
5509 const char* expected;
5514 const errorData maximizeErrors[] = {
5518 U_ILLEGAL_ARGUMENT_ERROR,
5522 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5524 U_ILLEGAL_ARGUMENT_ERROR,
5528 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5530 U_ILLEGAL_ARGUMENT_ERROR,
5534 "en_Latn_US_POSIX@currency=EURO",
5535 "en_Latn_US_POSIX@currency=EURO",
5536 U_BUFFER_OVERFLOW_ERROR,
5540 "en_Latn_US_POSIX@currency=EURO",
5541 "en_Latn_US_POSIX@currency=EURO",
5542 U_STRING_NOT_TERMINATED_WARNING,
5547 const errorData minimizeErrors[] = {
5551 U_ILLEGAL_ARGUMENT_ERROR,
5555 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5557 U_ILLEGAL_ARGUMENT_ERROR,
5561 "en_Latn_US_POSIX@currency=EURO",
5562 "en__POSIX@currency=EURO",
5563 U_BUFFER_OVERFLOW_ERROR,
5567 "en_Latn_US_POSIX@currency=EURO",
5568 "en__POSIX@currency=EURO",
5569 U_STRING_NOT_TERMINATED_WARNING,
5574 static int32_t getExpectedReturnValue(const errorData* data)
5576 if (data->uerror == U_BUFFER_OVERFLOW_ERROR ||
5577 data->uerror == U_STRING_NOT_TERMINATED_WARNING)
5579 return strlen(data->expected);
5587 static int32_t getBufferSize(const errorData* data, int32_t actualSize)
5589 if (data->expected == NULL)
5593 else if (data->bufferSize < 0)
5595 return strlen(data->expected) + 1;
5599 return data->bufferSize;
5603 static void TestLikelySubtags()
5605 char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1];
5608 for (; i < UPRV_LENGTHOF(basic_maximize_data); ++i)
5610 UErrorCode status = U_ZERO_ERROR;
5611 const char* const minimal = basic_maximize_data[i][0];
5612 const char* const maximal = basic_maximize_data[i][1];
5614 /* const int32_t length = */
5615 uloc_addLikelySubtags(
5620 if (U_FAILURE(status)) {
5621 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status));
5622 status = U_ZERO_ERROR;
5624 else if (uprv_strlen(maximal) == 0) {
5625 if (uprv_stricmp(minimal, buffer) != 0) {
5626 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5629 else if (uprv_stricmp(maximal, buffer) != 0) {
5630 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer);
5634 for (i = 0; i < UPRV_LENGTHOF(basic_minimize_data); ++i) {
5636 UErrorCode status = U_ZERO_ERROR;
5637 const char* const maximal = basic_minimize_data[i][0];
5638 const char* const minimal = basic_minimize_data[i][1];
5640 /* const int32_t length = */
5641 uloc_minimizeSubtags(
5647 if (U_FAILURE(status)) {
5648 log_err_status(status, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5649 status = U_ZERO_ERROR;
5651 else if (uprv_strlen(minimal) == 0) {
5652 if (uprv_stricmp(maximal, buffer) != 0) {
5653 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5656 else if (uprv_stricmp(minimal, buffer) != 0) {
5657 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5661 for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
5663 UErrorCode status = U_ZERO_ERROR;
5664 const char* const minimal = full_data[i][0];
5665 const char* const maximal = full_data[i][1];
5667 /* const int32_t length = */
5668 uloc_addLikelySubtags(
5673 if (U_FAILURE(status)) {
5674 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status));
5675 status = U_ZERO_ERROR;
5677 else if (uprv_strlen(maximal) == 0) {
5678 if (uprv_stricmp(minimal, buffer) != 0) {
5679 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5682 else if (uprv_stricmp(maximal, buffer) != 0) {
5683 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5687 for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
5689 UErrorCode status = U_ZERO_ERROR;
5690 const char* const maximal = full_data[i][1];
5691 const char* const minimal = full_data[i][2];
5693 if (strlen(maximal) > 0) {
5695 /* const int32_t length = */
5696 uloc_minimizeSubtags(
5702 if (U_FAILURE(status)) {
5703 log_err_status(status, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5704 status = U_ZERO_ERROR;
5706 else if (uprv_strlen(minimal) == 0) {
5707 if (uprv_stricmp(maximal, buffer) != 0) {
5708 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5711 else if (uprv_stricmp(minimal, buffer) != 0) {
5712 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5717 for (i = 0; i < UPRV_LENGTHOF(maximizeErrors); ++i) {
5719 UErrorCode status = U_ZERO_ERROR;
5720 const char* const minimal = maximizeErrors[i].tag;
5721 const char* const maximal = maximizeErrors[i].expected;
5722 const UErrorCode expectedStatus = maximizeErrors[i].uerror;
5723 const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]);
5724 const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer));
5726 const int32_t length =
5727 uloc_addLikelySubtags(
5733 if (status == U_ZERO_ERROR) {
5734 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus));
5735 status = U_ZERO_ERROR;
5737 else if (status != expectedStatus) {
5738 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));
5740 else if (length != expectedLength) {
5741 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length);
5743 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5744 if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) {
5745 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5746 maximal, minimal, (int)sizeof(buffer), buffer);
5751 for (i = 0; i < UPRV_LENGTHOF(minimizeErrors); ++i) {
5753 UErrorCode status = U_ZERO_ERROR;
5754 const char* const maximal = minimizeErrors[i].tag;
5755 const char* const minimal = minimizeErrors[i].expected;
5756 const UErrorCode expectedStatus = minimizeErrors[i].uerror;
5757 const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]);
5758 const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer));
5760 const int32_t length =
5761 uloc_minimizeSubtags(
5767 if (status == U_ZERO_ERROR) {
5768 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus));
5769 status = U_ZERO_ERROR;
5771 else if (status != expectedStatus) {
5772 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));
5774 else if (length != expectedLength) {
5775 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length);
5777 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5778 if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) {
5779 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5780 minimal, maximal, (int)sizeof(buffer), buffer);
5786 const char* const locale_to_langtag[][3] = {
5789 {"en_US", "en-US", "en-US"},
5790 {"iw_IL", "he-IL", "he-IL"},
5791 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5792 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5793 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5794 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL}, /* variant POSIX_VAR is processed as regular variant */
5795 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL}, /* variant VAR_POSIX is processed as regular variant */
5796 {"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 */
5797 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5798 {"und_555", "und-555", "und-555"},
5799 {"123", "und", NULL},
5800 {"%$#&", "und", NULL},
5801 {"_Latn", "und-Latn", "und-Latn"},
5802 {"_DE", "und-DE", "und-DE"},
5803 {"und_FR", "und-FR", "und-FR"},
5804 {"th_TH_TH", "th-TH-x-lvariant-th", NULL},
5805 {"bogus", "bogus", "bogus"},
5806 {"foooobarrr", "und", NULL},
5807 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5808 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL},
5809 {"en_US_1234", "en-US-1234", "en-US-1234"},
5810 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5811 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5812 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL},
5813 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL},
5814 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5815 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5816 {"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"},
5817 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5818 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5819 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL},
5820 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL},
5821 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5822 {"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"},
5823 {"@x=elmer", "x-elmer", "x-elmer"},
5824 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5825 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5826 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5828 {"en@a=bar;attribute=baz", "en-a-bar-u-baz", "en-a-bar-u-baz"},
5829 {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo", "en-a-bar-u-baz-x-u-foo"},
5830 {"en@attribute=baz", "en-u-baz", "en-u-baz"},
5831 {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"},
5832 {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo"},
5833 {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"},
5837 static void TestToLanguageTag(void) {
5843 const char *expected;
5845 for (i = 0; locale_to_langtag[i][0] != NULL; i++) {
5846 inloc = locale_to_langtag[i][0];
5848 /* testing non-strict mode */
5849 status = U_ZERO_ERROR;
5851 expected = locale_to_langtag[i][1];
5853 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status);
5854 (void)len; /* Suppress set but not used warning. */
5855 if (U_FAILURE(status)) {
5856 if (expected != NULL) {
5857 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5858 inloc, u_errorName(status));
5861 if (expected == NULL) {
5862 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5864 } else if (uprv_strcmp(langtag, expected) != 0) {
5865 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5866 langtag, inloc, expected);
5870 /* testing strict mode */
5871 status = U_ZERO_ERROR;
5873 expected = locale_to_langtag[i][2];
5875 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status);
5876 if (U_FAILURE(status)) {
5877 if (expected != NULL) {
5878 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5879 inloc, u_errorName(status));
5882 if (expected == NULL) {
5883 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5885 } else if (uprv_strcmp(langtag, expected) != 0) {
5886 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5887 langtag, inloc, expected);
5893 #define FULL_LENGTH -1
5894 static const struct {
5898 } langtag_to_locale[] = {
5899 {"en", "en", FULL_LENGTH},
5900 {"en-us", "en_US", FULL_LENGTH},
5901 {"und-US", "_US", FULL_LENGTH},
5902 {"und-latn", "_Latn", FULL_LENGTH},
5903 {"en-US-posix", "en_US_POSIX", FULL_LENGTH},
5904 {"de-de_euro", "de", 2},
5905 {"kok-IN", "kok_IN", FULL_LENGTH},
5908 {"en-latn-x", "en_Latn", 7},
5909 {"art-lojban", "jbo", FULL_LENGTH},
5910 {"zh-hakka", "hak", FULL_LENGTH},
5911 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH},
5912 {"xxx-yy", "xxx_YY", FULL_LENGTH},
5913 {"fr-234", "fr_234", FULL_LENGTH},
5914 {"i-default", "en@x=i-default", FULL_LENGTH},
5916 {"ja-jp-jp", "ja_JP", 5},
5917 {"bogus", "bogus", FULL_LENGTH},
5918 {"boguslang", "", 0},
5919 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH},
5920 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH},
5921 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5922 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH},
5923 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH},
5924 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH},
5925 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH},
5926 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH},
5927 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH},
5928 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH},
5929 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH},
5930 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH},
5931 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH},
5932 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH},
5933 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH},
5934 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH},
5935 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH},
5936 {"x-elmer", "@x=elmer", FULL_LENGTH},
5937 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH},
5938 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH},
5939 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH},
5940 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH},
5941 {"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},
5942 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5943 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
5945 {"en-a-bar-u-baz", "en@a=bar;attribute=baz", FULL_LENGTH},
5946 {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", FULL_LENGTH},
5947 {"en-u-baz", "en@attribute=baz", FULL_LENGTH},
5948 {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", FULL_LENGTH},
5949 {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", FULL_LENGTH},
5950 {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", FULL_LENGTH},
5954 static void TestForLanguageTag(void) {
5959 int32_t expParsedLen;
5961 for (i = 0; langtag_to_locale[i].bcpID != NULL; i++) {
5962 status = U_ZERO_ERROR;
5964 expParsedLen = langtag_to_locale[i].len;
5965 if (expParsedLen == FULL_LENGTH) {
5966 expParsedLen = uprv_strlen(langtag_to_locale[i].bcpID);
5968 uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status);
5969 if (U_FAILURE(status)) {
5970 log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5971 langtag_to_locale[i].bcpID, u_errorName(status));
5973 if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) {
5974 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5975 locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID);
5977 if (parsedLen != expParsedLen) {
5978 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5979 parsedLen, langtag_to_locale[i].bcpID, expParsedLen);
5985 static void TestToUnicodeLocaleKey(void)
5987 /* $IN specifies the result should be the input pointer itself */
5988 static const char* DATA[][2] = {
5990 {"CALEndar", "ca"}, /* difference casing */
5991 {"ca", "ca"}, /* bcp key itself */
5992 {"kv", "kv"}, /* no difference between legacy and bcp */
5993 {"foo", NULL}, /* unknown, bcp ill-formed */
5994 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
5999 for (i = 0; DATA[i][0] != NULL; i++) {
6000 const char* keyword = DATA[i][0];
6001 const char* expected = DATA[i][1];
6002 const char* bcpKey = NULL;
6004 bcpKey = uloc_toUnicodeLocaleKey(keyword);
6005 if (expected == NULL) {
6006 if (bcpKey != NULL) {
6007 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey);
6009 } else if (bcpKey == NULL) {
6010 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6011 } else if (uprv_strcmp(expected, "$IN") == 0) {
6012 if (bcpKey != keyword) {
6013 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword);
6015 } else if (uprv_strcmp(bcpKey, expected) != 0) {
6016 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected);
6021 static void TestToLegacyKey(void)
6023 /* $IN specifies the result should be the input pointer itself */
6024 static const char* DATA[][2] = {
6025 {"kb", "colbackwards"},
6026 {"kB", "colbackwards"}, /* different casing */
6027 {"Collation", "collation"}, /* keyword itself with different casing */
6028 {"kv", "kv"}, /* no difference between legacy and bcp */
6029 {"foo", "$IN"}, /* unknown, bcp ill-formed */
6030 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
6031 {"e=mc2", NULL}, /* unknown, bcp/legacy ill-formed */
6036 for (i = 0; DATA[i][0] != NULL; i++) {
6037 const char* keyword = DATA[i][0];
6038 const char* expected = DATA[i][1];
6039 const char* legacyKey = NULL;
6041 legacyKey = uloc_toLegacyKey(keyword);
6042 if (expected == NULL) {
6043 if (legacyKey != NULL) {
6044 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey);
6046 } else if (legacyKey == NULL) {
6047 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6048 } else if (uprv_strcmp(expected, "$IN") == 0) {
6049 if (legacyKey != keyword) {
6050 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword);
6052 } else if (uprv_strcmp(legacyKey, expected) != 0) {
6053 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected);
6058 static void TestToUnicodeLocaleType(void)
6060 /* $IN specifies the result should be the input pointer itself */
6061 static const char* DATA[][3] = {
6062 {"tz", "Asia/Kolkata", "inccu"},
6063 {"calendar", "gregorian", "gregory"},
6064 {"ca", "gregorian", "gregory"},
6065 {"ca", "Gregorian", "gregory"},
6066 {"ca", "buddhist", "buddhist"},
6067 {"Calendar", "Japanese", "japanese"},
6068 {"calendar", "Islamic-Civil", "islamic-civil"},
6069 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6070 {"colalternate", "NON-IGNORABLE", "noignore"},
6071 {"colcaselevel", "yes", "true"},
6072 {"rg", "GBzzzz", "$IN"},
6073 {"tz", "america/new_york", "usnyc"},
6074 {"tz", "Asia/Kolkata", "inccu"},
6075 {"timezone", "navajo", "usden"},
6076 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
6077 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6078 {"zz", "gregorian", NULL}, /* unknown key, ill-formed type */
6079 {"co", "foo-", NULL}, /* unknown type, ill-formed type */
6080 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6081 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6082 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6083 {"kr", "digit-spacepunct", NULL}, /* invalid (bcp ill-formed) reordercode type */
6088 for (i = 0; DATA[i][0] != NULL; i++) {
6089 const char* keyword = DATA[i][0];
6090 const char* value = DATA[i][1];
6091 const char* expected = DATA[i][2];
6092 const char* bcpType = NULL;
6094 bcpType = uloc_toUnicodeLocaleType(keyword, value);
6095 if (expected == NULL) {
6096 if (bcpType != NULL) {
6097 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType);
6099 } else if (bcpType == NULL) {
6100 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6101 } else if (uprv_strcmp(expected, "$IN") == 0) {
6102 if (bcpType != value) {
6103 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value);
6105 } else if (uprv_strcmp(bcpType, expected) != 0) {
6106 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected);
6111 static void TestToLegacyType(void)
6113 /* $IN specifies the result should be the input pointer itself */
6114 static const char* DATA[][3] = {
6115 {"calendar", "gregory", "gregorian"},
6116 {"ca", "gregory", "gregorian"},
6117 {"ca", "Gregory", "gregorian"},
6118 {"ca", "buddhist", "buddhist"},
6119 {"Calendar", "Japanese", "japanese"},
6120 {"calendar", "Islamic-Civil", "islamic-civil"},
6121 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6122 {"colalternate", "noignore", "non-ignorable"},
6123 {"colcaselevel", "true", "yes"},
6124 {"rg", "gbzzzz", "gbzzzz"},
6125 {"tz", "usnyc", "America/New_York"},
6126 {"tz", "inccu", "Asia/Calcutta"},
6127 {"timezone", "usden", "America/Denver"},
6128 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6129 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6130 {"ca", "aaaa", "$IN"}, /* unknown type */
6131 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6132 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6133 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6134 {"co", "e=mc2", NULL}, /* known key, ill-formed bcp/legacy type */
6135 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6136 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6137 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6138 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6143 for (i = 0; DATA[i][0] != NULL; i++) {
6144 const char* keyword = DATA[i][0];
6145 const char* value = DATA[i][1];
6146 const char* expected = DATA[i][2];
6147 const char* legacyType = NULL;
6149 legacyType = uloc_toLegacyType(keyword, value);
6150 if (expected == NULL) {
6151 if (legacyType != NULL) {
6152 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType);
6154 } else if (legacyType == NULL) {
6155 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6156 } else if (uprv_strcmp(expected, "$IN") == 0) {
6157 if (legacyType != value) {
6158 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value);
6160 } else if (uprv_strcmp(legacyType, expected) != 0) {
6161 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected);
6163 log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword, value, legacyType);
6170 static void test_unicode_define(const char *namech, char ch, const char *nameu, UChar uch)
6174 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech, ch,(int)ch, nameu, (int) uch);
6175 u_charsToUChars(&ch, asUch, 1);
6176 if(asUch[0] != uch) {
6177 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);
6179 log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]);
6183 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6185 static void TestUnicodeDefines(void) {
6186 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE);
6187 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
6188 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
6191 static void TestIsRightToLeft() {
6192 // API test only. More test cases in intltest/LocaleTest.
6193 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6194 log_err("uloc_isRightToLeft() failed");