1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /*****************************************************************************
12 * Modification History:
14 * Madhu Katragadda Ported for C API
15 ******************************************************************************
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);
53 static void TestBadLocaleIDs(void);
55 void PrintDataTable();
57 /*---------------------------------------------------
59 --------------------------------------------------- */
61 #define LOCALE_INFO_SIZE 28
63 static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
65 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
67 { "", "", "", "", "", "", "", "", "" },
69 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
71 { "", "", "", "", "NY", "", "", "", "" },
73 { "en_US", "fr_FR", "ca_ES",
74 "el_GR", "no_NO_NY", "zh_Hans_CN",
75 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
77 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
79 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
81 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
83 /* display language (English) */
84 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
85 /* display script code (English) */
86 { "", "", "", "", "", "Simplified Han", "", "", "" },
87 /* display country (English) */
88 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
89 /* display variant (English) */
90 { "", "", "", "", "NY", "", "", "", "" },
91 /* display name (English) */
92 { "English (United States)", "French (France)", "Catalan (Spain)",
93 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
94 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
96 /* display language (French) */
97 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
98 /* display script code (French) */
99 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
100 /* display country (French) */
101 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
102 /* display variant (French) */
103 { "", "", "", "", "NY", "", "", "", "" },
104 /* display name (French) */
105 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
106 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)",
107 "allemand (Allemagne, ordre de tri=Ordre de l\\u2019annuaire)", "espagnol (ordre de tri=Ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
109 /* display language (Catalan) */
110 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
111 /* display script code (Catalan) */
112 { "", "", "", "", "", "han simplificat", "", "", "" },
113 /* display country (Catalan) */
114 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
115 /* display variant (Catalan) */
116 { "", "", "", "", "NY", "", "", "", "" },
117 /* display name (Catalan) */
118 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
119 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
120 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
122 /* display language (Greek) */
124 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
125 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
126 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
127 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
128 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
129 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
130 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
131 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
132 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
134 /* display script code (Greek) */
136 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
137 /* display country (Greek) */
139 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
140 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
141 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
142 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
143 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
144 "\\u039A\\u03AF\\u03BD\\u03B1",
145 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
147 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
149 /* display variant (Greek) */
150 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
151 /* display name (Greek) */
153 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
154 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
155 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
156 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
157 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
158 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
159 "\\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)",
160 "\\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)",
161 "\\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)"
165 static UChar*** dataTable=0;
205 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
207 void addLocaleTest(TestNode** root);
209 void addLocaleTest(TestNode** root)
211 TESTCASE(TestObsoleteNames); /* srl- move */
212 TESTCASE(TestBasicGetters);
213 TESTCASE(TestNullDefault);
214 TESTCASE(TestPrefixes);
215 TESTCASE(TestSimpleResourceInfo);
216 TESTCASE(TestDisplayNames);
217 TESTCASE(TestGetAvailableLocales);
218 TESTCASE(TestDataDirectory);
219 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
220 TESTCASE(TestISOFunctions);
222 TESTCASE(TestISO3Fallback);
223 TESTCASE(TestUninstalledISO3Names);
224 TESTCASE(TestSimpleDisplayNames);
225 TESTCASE(TestVariantParsing);
226 TESTCASE(TestKeywordVariants);
227 TESTCASE(TestKeywordVariantParsing);
228 TESTCASE(TestCanonicalization);
229 TESTCASE(TestKeywordSet);
230 TESTCASE(TestKeywordSetError);
231 TESTCASE(TestDisplayKeywords);
232 TESTCASE(TestDisplayKeywordValues);
233 TESTCASE(TestGetBaseName);
234 #if !UCONFIG_NO_FILE_IO
235 TESTCASE(TestGetLocale);
237 TESTCASE(TestDisplayNameWarning);
238 TESTCASE(TestNonexistentLanguageExemplars);
239 TESTCASE(TestLocDataErrorCodeChaining);
240 TESTCASE(TestLocDataWithRgTag);
241 TESTCASE(TestLanguageExemplarsFallbacks);
242 TESTCASE(TestCalendar);
243 TESTCASE(TestDateFormat);
244 TESTCASE(TestCollation);
245 TESTCASE(TestULocale);
246 TESTCASE(TestUResourceBundle);
247 TESTCASE(TestDisplayName);
248 TESTCASE(TestAcceptLanguage);
249 TESTCASE(TestGetLocaleForLCID);
250 TESTCASE(TestOrientation);
251 TESTCASE(TestLikelySubtags);
252 TESTCASE(TestToLanguageTag);
253 TESTCASE(TestForLanguageTag);
254 TESTCASE(TestTrailingNull);
255 TESTCASE(TestUnicodeDefines);
256 TESTCASE(TestEnglishExemplarCharacters);
257 TESTCASE(TestDisplayNameBrackets);
258 TESTCASE(TestIsRightToLeft);
259 TESTCASE(TestToUnicodeLocaleKey);
260 TESTCASE(TestToLegacyKey);
261 TESTCASE(TestToUnicodeLocaleType);
262 TESTCASE(TestToLegacyType);
263 TESTCASE(TestBadLocaleIDs);
267 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
268 static void TestBasicGetters() {
271 UErrorCode status = U_ZERO_ERROR;
272 char *testLocale = 0;
273 char *temp = 0, *name = 0;
274 log_verbose("Testing Basic Getters\n");
275 for (i = 0; i < LOCALE_SIZE; i++) {
276 testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
277 strcpy(testLocale,rawData2[NAME][i]);
279 log_verbose("Testing %s .....\n", testLocale);
280 cap=uloc_getLanguage(testLocale, NULL, 0, &status);
281 if(status==U_BUFFER_OVERFLOW_ERROR){
283 temp=(char*)malloc(sizeof(char) * (cap+1));
284 uloc_getLanguage(testLocale, temp, cap+1, &status);
286 if(U_FAILURE(status)){
287 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status));
289 if (0 !=strcmp(temp,rawData2[LANG][i])) {
290 log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]);
294 cap=uloc_getCountry(testLocale, temp, cap, &status);
295 if(status==U_BUFFER_OVERFLOW_ERROR){
297 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
298 uloc_getCountry(testLocale, temp, cap+1, &status);
300 if(U_FAILURE(status)){
301 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status));
303 if (0 != strcmp(temp, rawData2[CTRY][i])) {
304 log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]);
308 cap=uloc_getVariant(testLocale, temp, cap, &status);
309 if(status==U_BUFFER_OVERFLOW_ERROR){
311 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
312 uloc_getVariant(testLocale, temp, cap+1, &status);
314 if(U_FAILURE(status)){
315 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status));
317 if (0 != strcmp(temp, rawData2[VAR][i])) {
318 log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]);
321 cap=uloc_getName(testLocale, NULL, 0, &status);
322 if(status==U_BUFFER_OVERFLOW_ERROR){
324 name=(char*)malloc(sizeof(char) * (cap+1));
325 uloc_getName(testLocale, name, cap+1, &status);
326 } else if(status==U_ZERO_ERROR) {
327 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale);
329 if(U_FAILURE(status)){
330 log_err("ERROR: in uloc_getName %s\n", myErrorName(status));
332 if (0 != strcmp(name, rawData2[NAME][i])){
333 log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]);
343 static void TestNullDefault() {
344 UErrorCode status = U_ZERO_ERROR;
345 char original[ULOC_FULLNAME_CAPACITY];
347 uprv_strcpy(original, uloc_getDefault());
348 uloc_setDefault("qq_BLA", &status);
349 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
350 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
352 uloc_setDefault(NULL, &status);
353 if (uprv_strcmp(uloc_getDefault(), original) != 0) {
354 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
358 /* Test that set & get of default locale work, and that
359 * default locales are cached and reused, and not overwritten.
363 const char *n2_en_US;
365 status = U_ZERO_ERROR;
366 uloc_setDefault("en_US", &status);
367 n_en_US = uloc_getDefault();
368 if (strcmp(n_en_US, "en_US") != 0) {
369 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
372 uloc_setDefault("fr_FR", &status);
373 n_fr_FR = uloc_getDefault();
374 if (strcmp(n_en_US, "en_US") != 0) {
375 log_err("uloc_setDefault altered previously default string."
376 "Expected \"en_US\", got \"%s\"\n", n_en_US);
378 if (strcmp(n_fr_FR, "fr_FR") != 0) {
379 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR);
382 uloc_setDefault("en_US", &status);
383 n2_en_US = uloc_getDefault();
384 if (strcmp(n2_en_US, "en_US") != 0) {
385 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
387 if (n2_en_US != n_en_US) {
388 log_err("Default locale cache failed to reuse en_US locale.\n");
391 if (U_FAILURE(status)) {
392 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status));
398 /* Test the i- and x- and @ and . functionality
401 #define PREFIXBUFSIZ 128
403 static void TestPrefixes() {
406 const char *loc, *expected;
408 static const char * const testData[][7] =
410 /* NULL canonicalize() column means "expect same as getName()" */
411 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL},
412 {"en", "", "GB", "", "en-gb", "en_GB", NULL},
413 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL},
414 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL},
415 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL},
416 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL},
418 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans@collation=pinyin"},
419 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", NULL},
421 {"de", "", "", "1901", "de-1901", "de__1901", NULL},
422 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
423 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
424 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
425 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
426 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
427 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
428 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
429 {"no", "", "", "NY", "no__ny", "no__NY", NULL},
430 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
431 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL},
432 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL},
433 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
434 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL},
435 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL},
436 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL}, /* total garbage */
438 {NULL,NULL,NULL,NULL,NULL,NULL,NULL}
441 static const char * const testTitles[] = {
442 "uloc_getLanguage()",
448 "uloc_canonicalize()"
451 char buf[PREFIXBUFSIZ];
456 for(row=0;testData[row][0] != NULL;row++) {
457 loc = testData[row][NAME];
458 log_verbose("Test #%d: %s\n", row, loc);
463 for(n=0;n<=(NAME+2);n++) {
464 if(n==NAME) continue;
466 for(len=0;len<PREFIXBUFSIZ;len++) {
467 buf[len] = '%'; /* Set a tripwire.. */
473 len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err);
477 len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err);
481 len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err);
485 len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err);
489 len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err);
493 len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err);
502 log_err("#%d: %s on %s: err %s\n",
503 row, testTitles[n], loc, u_errorName(err));
505 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
506 row, testTitles[n], loc, buf, len);
508 if(len != (int32_t)strlen(buf)) {
509 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
510 row, testTitles[n], loc, buf, len, strlen(buf)+1);
514 /* see if they smashed something */
515 if(buf[len+1] != '%') {
516 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
517 row, testTitles[n], loc, buf, buf[len+1]);
520 expected = testData[row][n];
521 if (expected == NULL && n == (NAME+2)) {
522 /* NULL expected canonicalize() means "expect same as getName()" */
523 expected = testData[row][NAME+1];
525 if(strcmp(buf, expected)) {
526 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
527 row, testTitles[n], loc, buf, expected);
536 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
537 static void TestSimpleResourceInfo() {
539 char* testLocale = 0;
544 testLocale=(char*)malloc(sizeof(char) * 1);
545 expected=(UChar*)malloc(sizeof(UChar) * 1);
548 log_verbose("Testing getISO3Language and getISO3Country\n");
549 for (i = 0; i < LOCALE_SIZE; i++) {
551 testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
552 u_austrcpy(testLocale, dataTable[NAME][i]);
554 log_verbose("Testing %s ......\n", testLocale);
556 temp=uloc_getISO3Language(testLocale);
557 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
558 u_uastrcpy(expected,temp);
559 if (0 != u_strcmp(expected, dataTable[LANG3][i])) {
560 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected),
561 austrdup(dataTable[LANG3][i]));
564 temp=uloc_getISO3Country(testLocale);
565 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
566 u_uastrcpy(expected,temp);
567 if (0 != u_strcmp(expected, dataTable[CTRY3][i])) {
568 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected),
569 austrdup(dataTable[CTRY3][i]));
571 sprintf(temp2, "%x", (int)uloc_getLCID(testLocale));
572 if (strcmp(temp2, rawData2[LCID][i]) != 0) {
573 log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]);
582 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
583 * if there's room but won't be included in result. result < 0 indicates an error.
584 * Returns the number of chars written (not those that would be written if there's enough room.*/
585 static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) {
586 static const struct {
599 static const int32_t ESCAPE_MAP_LENGTH = UPRV_LENGTHOF(ESCAPE_MAP);
600 static const char HEX_DIGITS[] = {
601 '0', '1', '2', '3', '4', '5', '6', '7',
602 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
605 int32_t resultLen = 0;
606 const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */
607 const int32_t escapeLimit1 = buflen-2;
608 const int32_t escapeLimit2 = buflen-6;
611 if(utext==NULL || resultChars==NULL || buflen<0) {
615 for(i=0;i<limit && resultLen<buflen;++i) {
621 for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) {
623 if(j<ESCAPE_MAP_LENGTH) {
624 if(resultLen>escapeLimit1) {
627 resultChars[resultLen++]='\\';
628 resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar;
632 u_austrncpy(resultChars + resultLen, &uc, 1);
637 if(resultLen>escapeLimit2) {
641 /* have to escape the uchar */
642 resultChars[resultLen++]='\\';
643 resultChars[resultLen++]='u';
644 resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff];
645 resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff];
646 resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff];
647 resultChars[resultLen++]=HEX_DIGITS[uc&0xff];
650 if(resultLen<buflen) {
651 resultChars[resultLen] = 0;
658 * Jitterbug 2439 -- markus 20030425
660 * The lookup of display names must not fall back through the default
661 * locale because that yields useless results.
663 static void TestDisplayNames()
666 UErrorCode errorCode=U_ZERO_ERROR;
668 log_verbose("Testing getDisplayName for different locales\n");
670 log_verbose(" In locale = en_US...\n");
671 doTestDisplayNames("en_US", DLANG_EN);
672 log_verbose(" In locale = fr_FR....\n");
673 doTestDisplayNames("fr_FR", DLANG_FR);
674 log_verbose(" In locale = ca_ES...\n");
675 doTestDisplayNames("ca_ES", DLANG_CA);
676 log_verbose(" In locale = gr_EL..\n");
677 doTestDisplayNames("el_GR", DLANG_EL);
679 /* test that the default locale has a display name for its own language */
680 errorCode=U_ZERO_ERROR;
681 length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode);
682 if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) {
683 /* check <=3 to reject getting the language code as a display name */
684 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));
687 /* test that we get the language code itself for an unknown language, and a default warning */
688 errorCode=U_ZERO_ERROR;
689 length=uloc_getDisplayLanguage("qq", "rr", buffer, UPRV_LENGTHOF(buffer), &errorCode);
690 if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
691 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
694 /* test that we get a default warning for a display name where one component is unknown (4255) */
695 errorCode=U_ZERO_ERROR;
696 length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, UPRV_LENGTHOF(buffer), &errorCode);
697 if(errorCode!=U_USING_DEFAULT_WARNING) {
698 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode));
703 static const char *aLocale = "es@collation=traditional;calendar=japanese";
704 static const char *testL[] = { "en_US",
708 static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
709 "espagnol (calendrier=calendrier japonais, ordre de tri=Ordre traditionnel)",
710 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
711 "\\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)" };
714 for(i=0;i<UPRV_LENGTHOF(testL);i++) {
715 errorCode = U_ZERO_ERROR;
716 uloc_getDisplayName(aLocale, testL[i], buffer, UPRV_LENGTHOF(buffer), &errorCode);
717 if(U_FAILURE(errorCode)) {
718 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode));
720 expectBuffer = CharsToUChars(expect[i]);
721 if(u_strcmp(buffer,expectBuffer)) {
722 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));
724 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]);
731 /* test that we properly preflight and return data when there's a non-default pattern,
735 static const char *locale="az_Cyrl";
736 static const char *displayLocale="ja";
737 static const char *expectedChars =
738 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e "
739 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
740 UErrorCode ec=U_ZERO_ERROR;
743 int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec);
744 /* inconvenient semantics when preflighting, this condition is expected... */
745 if(ec==U_BUFFER_OVERFLOW_ERROR) {
748 len=uloc_getDisplayName(locale, displayLocale, result, UPRV_LENGTHOF(result), &ec);
750 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
751 locale, displayLocale, u_errorName(ec));
753 UChar *expected=CharsToUChars(expectedChars);
754 int32_t expectedLen=u_strlen(expected);
756 if(len!=expectedLen) {
757 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
758 locale, displayLocale, len, expectedLen);
759 } else if(preflightLen!=expectedLen) {
760 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
761 locale, displayLocale, preflightLen, expectedLen);
762 } else if(u_strncmp(result, expected, len)) {
763 int32_t cap=len*6+1; /* worst case + space for trailing null */
764 char* resultChars=(char*)malloc(cap);
765 int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap);
766 if(resultCharsLen<0 || resultCharsLen<cap-1) {
767 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale);
769 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
770 locale, displayLocale, resultChars, expectedChars);
775 /* test all buffer sizes */
776 for(i=len+1;i>=0;--i) {
777 len=uloc_getDisplayName(locale, displayLocale, result, i, &ec);
778 if(ec==U_BUFFER_OVERFLOW_ERROR) {
782 log_err("using buffer of length %d returned error %s", i, u_errorName(ec));
785 if(len!=expectedLen) {
786 log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len);
789 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
790 * we don't know that it's been filled, so no point in checking. */
800 /* test for uloc_getAvialable() and uloc_countAvilable()*/
801 static void TestGetAvailableLocales()
807 log_verbose("Testing the no of avialable locales\n");
808 locCount=uloc_countAvailable();
810 log_data_err("countAvailable() returned an empty list!\n");
812 /* use something sensible w/o hardcoding the count */
813 else if(locCount < 0){
814 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount);
817 log_info("Number of locales returned = %d\n", locCount);
819 for(i=0;i<locCount;i++){
820 locList=uloc_getAvailable(i);
822 log_verbose(" %s\n", locList);
826 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
827 static void TestDataDirectory()
830 char oldDirectory[512];
831 const char *temp,*testValue1,*testValue2,*testValue3;
832 const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */
834 log_verbose("Testing getDataDirectory()\n");
835 temp = u_getDataDirectory();
836 strcpy(oldDirectory, temp);
838 testValue1=uloc_getISO3Language("en_US");
839 log_verbose("first fetch of language retrieved %s\n", testValue1);
841 if (0 != strcmp(testValue1,"eng")){
842 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1);
845 /*defining the path for DataDirectory */
846 log_verbose("Testing setDataDirectory\n");
847 u_setDataDirectory( path );
848 if(strcmp(path, u_getDataDirectory())==0)
849 log_verbose("setDataDirectory working fine\n");
851 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path);
853 testValue2=uloc_getISO3Language("en_US");
854 log_verbose("second fetch of language retrieved %s \n", testValue2);
856 u_setDataDirectory(oldDirectory);
857 testValue3=uloc_getISO3Language("en_US");
858 log_verbose("third fetch of language retrieved %s \n", testValue3);
860 if (0 != strcmp(testValue3,"eng")) {
861 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3);
867 /*=========================================================== */
871 static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
873 UErrorCode status = U_ZERO_ERROR;
875 int32_t maxresultsize;
877 const char *testLocale;
881 UChar *testScript = 0;
887 UChar* expectedLang = 0;
888 UChar* expectedScript = 0;
889 UChar* expectedCtry = 0;
890 UChar* expectedVar = 0;
891 UChar* expectedName = 0;
895 for(i=0;i<LOCALE_SIZE; ++i)
897 testLocale=rawData2[NAME][i];
899 log_verbose("Testing..... %s\n", testLocale);
902 maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
903 if(status==U_BUFFER_OVERFLOW_ERROR)
906 testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
907 uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
913 if(U_FAILURE(status)){
914 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
918 maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status);
919 if(status==U_BUFFER_OVERFLOW_ERROR)
922 testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
923 uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status);
929 if(U_FAILURE(status)){
930 log_err("Error in getDisplayScript() %s\n", myErrorName(status));
934 maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
935 if(status==U_BUFFER_OVERFLOW_ERROR)
938 testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
939 uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
945 if(U_FAILURE(status)){
946 log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
950 maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
951 if(status==U_BUFFER_OVERFLOW_ERROR)
954 testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
955 uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
961 if(U_FAILURE(status)){
962 log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
966 maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
967 if(status==U_BUFFER_OVERFLOW_ERROR)
970 testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
971 uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
977 if(U_FAILURE(status)){
978 log_err("Error in getDisplayName() %s\n", myErrorName(status));
981 expectedLang=dataTable[compareIndex][i];
982 if(u_strlen(expectedLang)== 0)
983 expectedLang=dataTable[DLANG_EN][i];
985 expectedScript=dataTable[compareIndex + 1][i];
986 if(u_strlen(expectedScript)== 0)
987 expectedScript=dataTable[DSCRIPT_EN][i];
989 expectedCtry=dataTable[compareIndex + 2][i];
990 if(u_strlen(expectedCtry)== 0)
991 expectedCtry=dataTable[DCTRY_EN][i];
993 expectedVar=dataTable[compareIndex + 3][i];
994 if(u_strlen(expectedVar)== 0)
995 expectedVar=dataTable[DVAR_EN][i];
997 expectedName=dataTable[compareIndex + 4][i];
998 if(u_strlen(expectedName) == 0)
999 expectedName=dataTable[DNAME_EN][i];
1001 if (0 !=u_strcmp(testLang,expectedLang)) {
1002 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
1005 if (0 != u_strcmp(testScript,expectedScript)) {
1006 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale);
1009 if (0 != u_strcmp(testCtry,expectedCtry)) {
1010 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
1013 if (0 != u_strcmp(testVar,expectedVar)) {
1014 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
1017 if(0 != u_strcmp(testName, expectedName)) {
1018 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale);
1021 if(testName!=&_NUL) {
1024 if(testLang!=&_NUL) {
1027 if(testScript!=&_NUL) {
1030 if(testCtry!=&_NUL) {
1033 if(testVar!=&_NUL) {
1040 /*------------------------------
1041 * TestDisplayNameBrackets
1045 const char * displayLocale;
1046 const char * namedRegion;
1047 const char * namedLocale;
1048 const char * regionName;
1049 const char * localeName;
1050 } DisplayNameBracketsItem;
1052 static const DisplayNameBracketsItem displayNameBracketsItems[] = {
1053 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" },
1054 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" },
1055 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" },
1056 { "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" },
1057 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1058 { NULL, NULL, NULL, NULL, NULL }
1061 enum { kDisplayNameBracketsMax = 128 };
1063 static void TestDisplayNameBrackets()
1065 const DisplayNameBracketsItem * itemPtr = displayNameBracketsItems;
1066 for (; itemPtr->displayLocale != NULL; itemPtr++) {
1067 ULocaleDisplayNames * uldn;
1069 UChar expectRegionName[kDisplayNameBracketsMax];
1070 UChar expectLocaleName[kDisplayNameBracketsMax];
1071 UChar getName[kDisplayNameBracketsMax];
1074 (void) u_unescape(itemPtr->regionName, expectRegionName, kDisplayNameBracketsMax);
1075 (void) u_unescape(itemPtr->localeName, expectLocaleName, kDisplayNameBracketsMax);
1077 status = U_ZERO_ERROR;
1078 ulen = uloc_getDisplayCountry(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1079 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1080 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1083 status = U_ZERO_ERROR;
1084 ulen = uloc_getDisplayName(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status);
1085 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1086 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1089 #if !UCONFIG_NO_FORMATTING
1090 status = U_ZERO_ERROR;
1091 uldn = uldn_open(itemPtr->displayLocale, ULDN_STANDARD_NAMES, &status);
1092 if (U_SUCCESS(status)) {
1093 status = U_ZERO_ERROR;
1094 ulen = uldn_regionDisplayName(uldn, itemPtr->namedRegion, getName, kDisplayNameBracketsMax, &status);
1095 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) {
1096 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedRegion, myErrorName(status));
1099 status = U_ZERO_ERROR;
1100 ulen = uldn_localeDisplayName(uldn, itemPtr->namedLocale, getName, kDisplayNameBracketsMax, &status);
1101 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) {
1102 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status));
1107 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr->displayLocale, u_errorName(status));
1110 (void)ulen; /* Suppress variable not used warning */
1114 /*------------------------------
1118 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1119 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1120 static void TestISOFunctions()
1122 const char* const* str=uloc_getISOLanguages();
1123 const char* const* str1=uloc_getISOCountries();
1125 const char *key = NULL;
1126 int32_t count = 0, skipped = 0;
1128 UResourceBundle *res;
1129 UResourceBundle *subRes;
1130 UErrorCode status = U_ZERO_ERROR;
1132 /* test getISOLanguages*/
1133 /*str=uloc_getISOLanguages(); */
1134 log_verbose("Testing ISO Languages: \n");
1136 /* use structLocale - this data is no longer in root */
1137 res = ures_openDirect(loadTestData(&status), "structLocale", &status);
1138 subRes = ures_getByKey(res, "Languages", NULL, &status);
1139 if (U_FAILURE(status)) {
1140 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status));
1144 expect = ures_getSize(subRes);
1145 for(count = 0; *(str+count) != 0; count++)
1148 test = *(str+count);
1149 status = U_ZERO_ERROR;
1152 /* Skip over language tags. This API only returns language codes. */
1153 skipped += (key != NULL);
1154 ures_getNextString(subRes, NULL, &key, &status);
1156 while (key != NULL && strchr(key, '_'));
1160 /* TODO: Consider removing sh, which is deprecated */
1161 if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) {
1162 ures_getNextString(subRes, NULL, &key, &status);
1165 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1166 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1167 if(strcmp(test,key)) {
1168 /* The first difference usually implies the place where things get out of sync */
1169 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1173 if(!strcmp(test,"in"))
1174 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1175 if(!strcmp(test,"iw"))
1176 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1177 if(!strcmp(test,"ji"))
1178 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1179 if(!strcmp(test,"jw"))
1180 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1181 if(!strcmp(test,"sh"))
1182 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1185 expect -= skipped; /* Ignore the skipped resources from structLocale */
1188 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect);
1191 subRes = ures_getByKey(res, "Countries", subRes, &status);
1192 log_verbose("Testing ISO Countries");
1194 expect = ures_getSize(subRes) - 1; /* Skip ZZ */
1195 for(count = 0; *(str1+count) != 0; count++)
1198 test = *(str1+count);
1200 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1201 skipped += (key != NULL);
1202 ures_getNextString(subRes, NULL, &key, &status);
1204 while (key != NULL && strlen(key) != 2);
1208 /* TODO: Consider removing CS, which is deprecated */
1209 while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) {
1210 ures_getNextString(subRes, NULL, &key, &status);
1213 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1214 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1215 if(strcmp(test,key)) {
1216 /* The first difference usually implies the place where things get out of sync */
1217 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1220 if(!strcmp(test,"FX"))
1221 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1222 if(!strcmp(test,"YU"))
1223 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1224 if(!strcmp(test,"ZR"))
1225 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1228 ures_getNextString(subRes, NULL, &key, &status);
1229 if (strcmp(key, "ZZ") != 0) {
1230 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key);
1232 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1233 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1236 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1237 skipped += (key != NULL);
1238 ures_getNextString(subRes, NULL, &key, &status);
1240 while (U_SUCCESS(status) && key != NULL && strlen(key) != 2);
1242 expect -= skipped; /* Ignore the skipped resources from structLocale */
1245 log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect);
1252 static void setUpDataTable()
1255 dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE));
1257 for (i = 0; i < LOCALE_INFO_SIZE; i++) {
1258 dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE));
1259 for (j = 0; j < LOCALE_SIZE; j++){
1260 dataTable[i][j] = CharsToUChars(rawData2[i][j]);
1265 static void cleanUpDataTable()
1268 if(dataTable != NULL) {
1269 for (i=0; i<LOCALE_INFO_SIZE; i++) {
1270 for(j = 0; j < LOCALE_SIZE; j++) {
1271 free(dataTable[i][j]);
1281 * @bug 4011756 4011380
1283 static void TestISO3Fallback()
1285 const char* test="xx_YY";
1287 const char * result;
1289 result = uloc_getISO3Language(test);
1291 /* Conform to C API usage */
1293 if (!result || (result[0] != 0))
1294 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1296 result = uloc_getISO3Country(test);
1298 if (!result || (result[0] != 0))
1299 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1305 static void TestSimpleDisplayNames()
1308 This test is different from TestDisplayNames because TestDisplayNames checks
1309 fallback behavior, combination of language and country names to form locale
1310 names, and other stuff like that. This test just checks specific language
1311 and country codes to make sure we have the correct names for them.
1313 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1314 const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1316 const char* inLocale [] = { "en_US", "zh_Hant"};
1317 UErrorCode status=U_ZERO_ERROR;
1320 int32_t localeIndex = 0;
1321 for (i = 0; i < 7; i++) {
1323 UChar *expectedLang=0;
1327 localeIndex = 1; /* Use the second locale for the rest of the test. */
1330 size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status);
1331 if(status==U_BUFFER_OVERFLOW_ERROR) {
1332 status=U_ZERO_ERROR;
1333 testLang=(UChar*)malloc(sizeof(UChar) * (size + 1));
1334 uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status);
1336 expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1));
1337 u_uastrcpy(expectedLang, languageNames[i]);
1338 if (u_strcmp(testLang, expectedLang) != 0)
1339 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1340 languageCodes[i], languageNames[i], austrdup(testLang));
1350 static void TestUninstalledISO3Names()
1352 /* This test checks to make sure getISO3Language and getISO3Country work right
1353 even for locales that are not installed. */
1354 static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
1356 static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
1357 "ssw", "twi", "zul" };
1358 static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1359 "ss_SB", "tw_TC", "zu_ZW" };
1360 static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1361 "SLB", "TCA", "ZWE" };
1364 for (i = 0; i < 8; i++) {
1365 UErrorCode err = U_ZERO_ERROR;
1367 test = uloc_getISO3Language(iso2Languages[i]);
1368 if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err))
1369 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1370 iso2Languages[i], iso3Languages[i], test, myErrorName(err));
1372 for (i = 0; i < 8; i++) {
1373 UErrorCode err = U_ZERO_ERROR;
1375 test = uloc_getISO3Country(iso2Countries[i]);
1376 if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err))
1377 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1378 iso2Countries[i], iso3Countries[i], test, myErrorName(err));
1383 static void TestVariantParsing()
1385 static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth";
1386 static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1387 static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1388 static const char* shortVariant="fr_FR_foo";
1389 static const char* bogusVariant="fr_FR__foo";
1390 static const char* bogusVariant2="fr_FR_foo_";
1391 static const char* bogusVariant3="fr_FR__foo_";
1394 UChar displayVar[100];
1395 UChar displayName[100];
1396 UErrorCode status=U_ZERO_ERROR;
1399 size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status);
1400 if(status==U_BUFFER_OVERFLOW_ERROR) {
1401 status=U_ZERO_ERROR;
1402 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1403 uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status);
1406 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1408 u_uastrcpy(displayVar, dispVar);
1409 if(u_strcmp(got,displayVar)!=0) {
1410 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got));
1413 size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status);
1414 if(status==U_BUFFER_OVERFLOW_ERROR) {
1415 status=U_ZERO_ERROR;
1416 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1417 uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status);
1420 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1422 u_uastrcpy(displayName, dispName);
1423 if(u_strcmp(got,displayName)!=0) {
1424 if (status == U_USING_DEFAULT_WARNING) {
1425 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status));
1427 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got));
1432 status=U_ZERO_ERROR;
1433 size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status);
1434 if(status==U_BUFFER_OVERFLOW_ERROR) {
1435 status=U_ZERO_ERROR;
1436 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1437 uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status);
1440 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1442 if(strcmp(austrdup(got),"FOO")!=0) {
1443 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got));
1446 status=U_ZERO_ERROR;
1447 size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status);
1448 if(status==U_BUFFER_OVERFLOW_ERROR) {
1449 status=U_ZERO_ERROR;
1450 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1451 uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status);
1454 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1456 if(strcmp(austrdup(got),"_FOO")!=0) {
1457 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got));
1460 status=U_ZERO_ERROR;
1461 size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status);
1462 if(status==U_BUFFER_OVERFLOW_ERROR) {
1463 status=U_ZERO_ERROR;
1464 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1465 uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status);
1468 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1470 if(strcmp(austrdup(got),"FOO_")!=0) {
1471 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got));
1474 status=U_ZERO_ERROR;
1475 size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status);
1476 if(status==U_BUFFER_OVERFLOW_ERROR) {
1477 status=U_ZERO_ERROR;
1478 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1479 uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status);
1482 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1484 if(strcmp(austrdup(got),"_FOO_")!=0) {
1485 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got));
1491 static void TestObsoleteNames(void)
1494 UErrorCode status = U_ZERO_ERROR;
1506 { "eng_USA", "eng", "en", "USA", "US" },
1507 { "kok", "kok", "kok", "", "" },
1508 { "in", "ind", "in", "", "" },
1509 { "id", "ind", "id", "", "" }, /* NO aliasing */
1510 { "sh", "srp", "sh", "", "" },
1511 { "zz_CS", "", "zz", "SCG", "CS" },
1512 { "zz_FX", "", "zz", "FXX", "FX" },
1513 { "zz_RO", "", "zz", "ROU", "RO" },
1514 { "zz_TP", "", "zz", "TMP", "TP" },
1515 { "zz_TL", "", "zz", "TLS", "TL" },
1516 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1517 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1518 { "zz_ROM", "", "zz", "ROU", "RO" },
1519 { "zz_ROU", "", "zz", "ROU", "RO" },
1520 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1521 { "zz_TMP", "", "zz", "TMP", "TP" },
1522 { "zz_TLS", "", "zz", "TLS", "TL" },
1523 { "zz_YUG", "", "zz", "YUG", "YU" },
1524 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1525 { "iw", "heb", "iw", "", "" },
1526 { "ji", "yid", "ji", "", "" },
1527 { "jw", "jaw", "jw", "", "" },
1528 { "sh", "srp", "sh", "", "" },
1529 { "", "", "", "", "" }
1532 for(i=0;tests[i].locale[0];i++)
1536 locale = tests[i].locale;
1537 log_verbose("** %s:\n", locale);
1539 status = U_ZERO_ERROR;
1540 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1542 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1543 locale, uloc_getISO3Language(locale), tests[i].lang3);
1547 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1548 uloc_getISO3Language(locale) );
1551 status = U_ZERO_ERROR;
1552 uloc_getLanguage(locale, buff, 256, &status);
1553 if(U_FAILURE(status))
1555 log_err("FAIL: error getting language from %s\n", locale);
1559 if(strcmp(buff,tests[i].lang))
1561 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1562 locale, buff, tests[i].lang);
1566 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff);
1569 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1571 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1572 locale, uloc_getISO3Language(locale), tests[i].lang3);
1576 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1577 uloc_getISO3Language(locale) );
1580 if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale)))
1582 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1583 locale, uloc_getISO3Country(locale), tests[i].ctry3);
1587 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1588 uloc_getISO3Country(locale) );
1591 status = U_ZERO_ERROR;
1592 uloc_getCountry(locale, buff, 256, &status);
1593 if(U_FAILURE(status))
1595 log_err("FAIL: error getting country from %s\n", locale);
1599 if(strcmp(buff,tests[i].ctry))
1601 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1602 locale, buff, tests[i].ctry);
1606 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff);
1611 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1612 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1615 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1616 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1621 i = uloc_getLanguage("kok",NULL,0,&icu_err);
1622 if(U_FAILURE(icu_err))
1624 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err));
1627 icu_err = U_ZERO_ERROR;
1628 uloc_getLanguage("kok",r1_buff,12,&icu_err);
1629 if(U_FAILURE(icu_err))
1631 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err));
1634 r1_addr = (char *)uloc_getISO3Language("kok");
1636 icu_err = U_ZERO_ERROR;
1637 if (strcmp(r1_buff,"kok") != 0)
1639 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff);
1642 r1_addr = (char *)uloc_getISO3Language("in");
1643 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1644 if (strcmp(r1_buff,"id") != 0)
1646 printf("uloc_getLanguage error (%s)\n",r1_buff);
1649 r1_addr = (char *)uloc_getISO3Language("sh");
1650 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1651 if (strcmp(r1_buff,"sr") != 0)
1653 printf("uloc_getLanguage error (%s)\n",r1_buff);
1657 r1_addr = (char *)uloc_getISO3Country("zz_ZR");
1658 strcpy(p1_buff,"zz_");
1659 strcat(p1_buff,r1_addr);
1660 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1661 if (strcmp(r1_buff,"ZR") != 0)
1663 printf("uloc_getCountry error (%s)\n",r1_buff);
1666 r1_addr = (char *)uloc_getISO3Country("zz_FX");
1667 strcpy(p1_buff,"zz_");
1668 strcat(p1_buff,r1_addr);
1669 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1670 if (strcmp(r1_buff,"FX") != 0)
1672 printf("uloc_getCountry error (%s)\n",r1_buff);
1680 static void TestKeywordVariants(void)
1682 static const struct {
1683 const char *localeID;
1684 const char *expectedLocaleID; /* uloc_getName */
1685 const char *expectedLocaleIDNoKeywords; /* uloc_getBaseName */
1686 const char *expectedCanonicalID; /* uloc_canonicalize */
1687 const char *expectedKeywords[10];
1688 int32_t numKeywords;
1689 UErrorCode expectedStatus; /* from uloc_openKeywords */
1692 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1693 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1695 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1696 {"calendar", "collation", "currency"},
1703 "de_DE@euro", /* we probably should strip off the POSIX style variant @euro see #11690 */
1704 "de_DE@currency=EUR",
1705 {"","","","","","",""},
1707 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1710 "de_DE@euro;collation=phonebook", /* The POSIX style variant @euro cannot be combined with key=value? */
1711 "de_DE", /* getName returns de_DE - should be INVALID_FORMAT_ERROR? */
1712 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1713 "de_DE", /* canonicalize returns de_DE - should be INVALID_FORMAT_ERROR? */
1714 {"","","","","","",""},
1716 U_INVALID_FORMAT_ERROR
1720 0, /* expected getName to fail */
1721 "de_DE", /* getBaseName returns de_DE - should be INVALID_FORMAT_ERROR? see #11690 */
1722 0, /* expected canonicalize to fail */
1723 {"","","","","","",""},
1725 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1728 UErrorCode status = U_ZERO_ERROR;
1730 int32_t i = 0, j = 0;
1731 int32_t resultLen = 0;
1733 UEnumeration *keywords;
1734 int32_t keyCount = 0;
1735 const char *keyword = NULL;
1736 int32_t keywordLen = 0;
1738 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1739 status = U_ZERO_ERROR;
1741 keywords = uloc_openKeywords(testCases[i].localeID, &status);
1743 if(status != testCases[i].expectedStatus) {
1744 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1745 testCases[i].localeID,
1746 u_errorName(testCases[i].expectedStatus), u_errorName(status));
1748 status = U_ZERO_ERROR;
1750 if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
1751 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1755 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1756 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1757 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1762 uenum_reset(keywords, &status);
1763 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1764 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1765 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1770 uenum_close(keywords);
1773 status = U_ZERO_ERROR;
1774 resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
1775 if (U_SUCCESS(status)) {
1776 if (testCases[i].expectedLocaleID == 0) {
1777 log_err("Expected uloc_getName(\"%s\") to fail; got \"%s\"\n",
1778 testCases[i].localeID, buffer);
1779 } else if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
1780 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1781 testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
1784 if (testCases[i].expectedLocaleID != 0) {
1785 log_err("Expected uloc_getName(\"%s\") => \"%s\"; but returned error: %s\n",
1786 testCases[i].localeID, testCases[i].expectedLocaleID, buffer, u_errorName(status));
1790 status = U_ZERO_ERROR;
1791 resultLen = uloc_getBaseName(testCases[i].localeID, buffer, 256, &status);
1792 if (U_SUCCESS(status)) {
1793 if (testCases[i].expectedLocaleIDNoKeywords == 0) {
1794 log_err("Expected uloc_getBaseName(\"%s\") to fail; got \"%s\"\n",
1795 testCases[i].localeID, buffer);
1796 } else if (uprv_strcmp(testCases[i].expectedLocaleIDNoKeywords, buffer) != 0) {
1797 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; got \"%s\"\n",
1798 testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer);
1801 if (testCases[i].expectedLocaleIDNoKeywords != 0) {
1802 log_err("Expected uloc_getBaseName(\"%s\") => \"%s\"; but returned error: %s\n",
1803 testCases[i].localeID, testCases[i].expectedLocaleIDNoKeywords, buffer, u_errorName(status));
1807 status = U_ZERO_ERROR;
1808 resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
1809 if (U_SUCCESS(status)) {
1810 if (testCases[i].expectedCanonicalID == 0) {
1811 log_err("Expected uloc_canonicalize(\"%s\") to fail; got \"%s\"\n",
1812 testCases[i].localeID, buffer);
1813 } else if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
1814 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1815 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
1818 if (testCases[i].expectedCanonicalID != 0) {
1819 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; but returned error: %s\n",
1820 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer, u_errorName(status));
1826 static void TestKeywordVariantParsing(void)
1828 static const struct {
1829 const char *localeID;
1830 const char *keyword;
1831 const char *expectedValue; /* NULL if failure is expected */
1833 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", NULL }, /* malformed key name */
1834 { "de_DE", "collation", ""},
1835 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1836 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1841 int32_t resultLen = 0;
1844 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1846 status = U_ZERO_ERROR;
1847 resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
1848 (void)resultLen; /* Suppress set but not used warning. */
1849 if (testCases[i].expectedValue) {
1850 /* expect success */
1851 if (U_FAILURE(status)) {
1852 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got status %s\n",
1853 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, u_errorName(status));
1854 } else if (uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
1855 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Instead got \"%s\"\n",
1856 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
1858 } else if (U_SUCCESS(status)) {
1859 /* expect failure */
1860 log_err("Expected failure but got success from \"%s\" for keyword \"%s\". Got \"%s\"\n",
1861 testCases[i].localeID, testCases[i].keyword, buffer);
1867 static const struct {
1868 const char *l; /* locale */
1869 const char *k; /* kw */
1870 const char *v; /* value */
1871 const char *x; /* expected */
1872 } kwSetTestCases[] = {
1874 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1875 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1876 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1877 { "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 */
1878 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1879 { "de", "Currency", "CHF", "de@currency=CHF" },
1880 { "de", "Currency", "CHF", "de@currency=CHF" },
1882 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1883 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1884 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1885 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1886 { "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 */
1887 { "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 */
1888 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1889 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1892 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1893 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1894 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1895 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1896 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1897 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1898 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1899 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1900 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1904 /* 1. removal of item at end */
1905 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1906 { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
1907 /* 2. removal of item at beginning */
1908 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1909 { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
1910 /* 3. removal of an item not there */
1911 { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
1912 /* 4. removal of only item */
1913 { "de@collation=phonebook", "collation", NULL, "de" },
1915 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1916 /* cases with legal extra spacing */
1917 /*31*/{ "en_US@ calendar = islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1918 /*32*/{ "en_US@ calendar = gregorian ; collation = phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1919 /*33*/{ "en_US@ calendar = islamic", "currency", "CHF", "en_US@calendar=islamic;currency=CHF" },
1920 /*34*/{ "en_US@ currency = CHF", "calendar", "japanese", "en_US@calendar=japanese;currency=CHF" },
1921 /* cases in which setKeywordValue expected to fail (implied by NULL for expected); locale need not be canonical */
1922 /*35*/{ "en_US@calendar=gregorian;", "calendar", "japanese", NULL },
1923 /*36*/{ "en_US@calendar=gregorian;=", "calendar", "japanese", NULL },
1924 /*37*/{ "en_US@calendar=gregorian;currency=", "calendar", "japanese", NULL },
1925 /*38*/{ "en_US@=", "calendar", "japanese", NULL },
1926 /*39*/{ "en_US@=;", "calendar", "japanese", NULL },
1927 /*40*/{ "en_US@= ", "calendar", "japanese", NULL },
1928 /*41*/{ "en_US@ =", "calendar", "japanese", NULL },
1929 /*42*/{ "en_US@ = ", "calendar", "japanese", NULL },
1930 /*43*/{ "en_US@=;calendar=gregorian", "calendar", "japanese", NULL },
1931 /*44*/{ "en_US@= calen dar = gregorian", "calendar", "japanese", NULL },
1932 /*45*/{ "en_US@= calendar = greg orian", "calendar", "japanese", NULL },
1933 /*46*/{ "en_US@=;cal...endar=gregorian", "calendar", "japanese", NULL },
1934 /*47*/{ "en_US@=;calendar=greg...orian", "calendar", "japanese", NULL },
1935 /*48*/{ "en_US@calendar=gregorian", "cale ndar", "japanese", NULL },
1936 /*49*/{ "en_US@calendar=gregorian", "calendar", "japa..nese", NULL },
1937 /* cases in which getKeywordValue and setKeyword expected to fail (implied by NULL for value and expected) */
1938 /*50*/{ "en_US@=", "calendar", NULL, NULL },
1939 /*51*/{ "en_US@=;", "calendar", NULL, NULL },
1940 /*52*/{ "en_US@= ", "calendar", NULL, NULL },
1941 /*53*/{ "en_US@ =", "calendar", NULL, NULL },
1942 /*54*/{ "en_US@ = ", "calendar", NULL, NULL },
1943 /*55*/{ "en_US@=;calendar=gregorian", "calendar", NULL, NULL },
1944 /*56*/{ "en_US@= calen dar = gregorian", "calendar", NULL, NULL },
1945 /*57*/{ "en_US@= calendar = greg orian", "calendar", NULL, NULL },
1946 /*58*/{ "en_US@=;cal...endar=gregorian", "calendar", NULL, NULL },
1947 /*59*/{ "en_US@=;calendar=greg...orian", "calendar", NULL, NULL },
1948 /*60*/{ "en_US@calendar=gregorian", "cale ndar", NULL, NULL },
1952 static void TestKeywordSet(void)
1955 int32_t resultLen = 0;
1960 for(i = 0; i < UPRV_LENGTHOF(kwSetTestCases); i++) {
1961 UErrorCode status = U_ZERO_ERROR;
1962 memset(buffer,'%',1023);
1963 strcpy(buffer, kwSetTestCases[i].l);
1965 if (kwSetTestCases[i].x != NULL) {
1966 uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
1967 if(strcmp(buffer,cbuffer)) {
1968 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
1970 /* sanity check test case results for canonicity */
1971 uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
1972 if(strcmp(kwSetTestCases[i].x,cbuffer)) {
1973 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
1976 status = U_ZERO_ERROR;
1977 resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
1978 if(U_FAILURE(status)) {
1979 log_err("Err on test case %d for setKeywordValue: got error %s\n", i, u_errorName(status));
1980 } else if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
1981 log_err("FAIL: #%d setKeywordValue: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1982 kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
1984 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
1987 if (kwSetTestCases[i].v != NULL && kwSetTestCases[i].v[0] != 0) {
1988 status = U_ZERO_ERROR;
1989 resultLen = uloc_getKeywordValue(kwSetTestCases[i].x, kwSetTestCases[i].k, buffer, 1023, &status);
1990 if(U_FAILURE(status)) {
1991 log_err("Err on test case %d for getKeywordValue: got error %s\n", i, u_errorName(status));
1992 } else if (resultLen != uprv_strlen(kwSetTestCases[i].v) || uprv_strcmp(buffer, kwSetTestCases[i].v) != 0) {
1993 log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i, buffer, resultLen,
1994 kwSetTestCases[i].v, uprv_strlen(kwSetTestCases[i].v));
1998 /* test cases expected to result in error */
1999 status = U_ZERO_ERROR;
2000 resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
2001 if(U_SUCCESS(status)) {
2002 log_err("Err on test case %d for setKeywordValue: expected to fail but succeeded, got %s (%d)\n", i, buffer, resultLen);
2005 if (kwSetTestCases[i].v == NULL) {
2006 status = U_ZERO_ERROR;
2007 strcpy(cbuffer, kwSetTestCases[i].l);
2008 resultLen = uloc_getKeywordValue(cbuffer, kwSetTestCases[i].k, buffer, 1023, &status);
2009 if(U_SUCCESS(status)) {
2010 log_err("Err on test case %d for getKeywordValue: expected to fail but succeeded\n", i);
2017 static void TestKeywordSetError(void)
2025 /* 0-test whether an error condition modifies the buffer at all */
2028 memset(buffer,'%',1023);
2029 status = U_ZERO_ERROR;
2030 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2031 if(status != U_ILLEGAL_ARGUMENT_ERROR) {
2032 log_err("expected illegal err got %s\n", u_errorName(status));
2035 /* if(res!=strlen(kwSetTestCases[i].x)) {
2036 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2039 if(buffer[blen]!='%') {
2040 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
2043 log_verbose("0-buffer modify OK\n");
2046 /* 1- test a short buffer with growing text */
2047 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
2048 memset(buffer,'%',1023);
2049 strcpy(buffer,kwSetTestCases[i].l);
2050 status = U_ZERO_ERROR;
2051 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2052 if(status != U_BUFFER_OVERFLOW_ERROR) {
2053 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);
2056 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
2057 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2060 if(buffer[blen]!='%') {
2061 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
2064 log_verbose("1/%d-buffer modify OK\n",i);
2068 /* 2- test a short buffer - text the same size or shrinking */
2069 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
2070 memset(buffer,'%',1023);
2071 strcpy(buffer,kwSetTestCases[i].l);
2072 status = U_ZERO_ERROR;
2073 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
2074 if(status != U_ZERO_ERROR) {
2075 log_err("expected zero error got %s\n", u_errorName(status));
2078 if(buffer[blen+1]!='%') {
2079 log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
2082 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
2083 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
2086 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
2087 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
2088 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
2090 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
2093 log_verbose("2/%d-buffer modify OK\n",i);
2097 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
2098 const char* localeID,
2100 int32_t resultCapacity,
2102 /* YOU can change this to use function pointers if you like */
2105 return uloc_getName(localeID, result, resultCapacity, ec);
2107 return uloc_canonicalize(localeID, result, resultCapacity, ec);
2113 static void TestCanonicalization(void)
2115 static const struct {
2116 const char *localeID; /* input */
2117 const char *getNameID; /* expected getName() result */
2118 const char *canonicalID; /* expected canonicalize() result */
2120 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2121 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2122 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2123 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
2124 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
2125 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
2126 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2127 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2128 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2129 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2130 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2131 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2132 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2133 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2134 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2135 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2136 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2137 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2138 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2139 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2140 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2141 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2142 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2143 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2144 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2145 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2146 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2147 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2148 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2149 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2150 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2151 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2152 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2153 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
2154 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2155 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2156 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2157 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2158 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2159 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2160 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2161 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2162 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2163 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2164 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2165 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2166 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2167 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2168 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2169 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2170 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2172 /* posix behavior that used to be performed by getName */
2173 { "mr.utf8", "mr.utf8", "mr" },
2174 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2175 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2176 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2177 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2178 { "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 */
2180 /* fleshing out canonicalization */
2181 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2182 { "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" },
2183 /* already-canonical ids are not changed */
2184 { "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" },
2185 /* PRE_EURO and EURO conversions don't affect other keywords */
2186 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2187 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2188 /* currency keyword overrides PRE_EURO and EURO currency */
2189 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2190 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2191 /* norwegian is just too weird, if we handle things in their full generality */
2192 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2194 /* test cases reflecting internal resource bundle usage */
2195 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2196 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2197 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2198 { "ja_JP", "ja_JP", "ja_JP" },
2200 /* test case for "i-default" */
2201 { "i-default", "en@x=i-default", "en@x=i-default" }
2204 static const char* label[] = { "getName", "canonicalize" };
2206 UErrorCode status = U_ZERO_ERROR;
2207 int32_t i, j, resultLen = 0, origResultLen;
2210 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
2211 for (j=0; j<2; ++j) {
2212 const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
2214 status = U_ZERO_ERROR;
2216 if (expected == NULL) {
2217 expected = uloc_getDefault();
2220 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2221 origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
2222 if (status != U_BUFFER_OVERFLOW_ERROR) {
2223 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2224 label[j], testCases[i].localeID, u_errorName(status));
2227 status = U_ZERO_ERROR;
2228 resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
2229 if (U_FAILURE(status)) {
2230 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2231 label[j], testCases[i].localeID, u_errorName(status));
2234 if(uprv_strcmp(expected, buffer) != 0) {
2235 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2236 label[j], testCases[i].localeID, buffer, expected);
2238 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2239 label[j], testCases[i].localeID, buffer);
2241 if (resultLen != (int32_t)strlen(buffer)) {
2242 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2243 label[j], testCases[i].localeID, resultLen, strlen(buffer));
2245 if (origResultLen != resultLen) {
2246 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2247 label[j], testCases[i].localeID, origResultLen, resultLen);
2253 static void TestDisplayKeywords(void)
2257 static const struct {
2258 const char *localeID;
2259 const char *displayLocale;
2260 UChar displayKeyword[200];
2262 { "ca_ES@currency=ESP", "de_AT",
2263 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2265 { "ja_JP@calendar=japanese", "de",
2266 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2268 { "de_DE@collation=traditional", "de_DE",
2269 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2272 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2273 UErrorCode status = U_ZERO_ERROR;
2274 const char* keyword =NULL;
2275 int32_t keywordLen = 0;
2276 int32_t keywordCount = 0;
2277 UChar *displayKeyword=NULL;
2278 int32_t displayKeywordLen = 0;
2279 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2280 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2281 if(U_FAILURE(status)){
2282 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
2285 /* the uenum_next returns NUL terminated string */
2286 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2287 /* fetch the displayKeyword */
2288 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2289 if(status==U_BUFFER_OVERFLOW_ERROR){
2290 status = U_ZERO_ERROR;
2291 displayKeywordLen++; /* for null termination */
2292 displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
2293 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2294 if(U_FAILURE(status)){
2295 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));
2298 if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
2299 if (status == U_USING_DEFAULT_WARNING) {
2300 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));
2302 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);
2307 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
2310 free(displayKeyword);
2313 uenum_close(keywordEnum);
2317 static void TestDisplayKeywordValues(void){
2320 static const struct {
2321 const char *localeID;
2322 const char *displayLocale;
2323 UChar displayKeywordValue[500];
2325 { "ca_ES@currency=ESP", "de_AT",
2326 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2328 { "de_AT@currency=ATS", "fr_FR",
2329 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2331 { "de_DE@currency=DEM", "it",
2332 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2334 { "el_GR@currency=GRD", "en",
2335 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2337 { "eu_ES@currency=ESP", "it_IT",
2338 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2340 { "de@collation=phonebook", "es",
2341 {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}
2344 { "de_DE@collation=phonebook", "es",
2345 {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}
2347 { "es_ES@collation=traditional","de",
2348 {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}
2350 { "ja_JP@calendar=japanese", "de",
2351 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2354 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2355 UErrorCode status = U_ZERO_ERROR;
2356 const char* keyword =NULL;
2357 int32_t keywordLen = 0;
2358 int32_t keywordCount = 0;
2359 UChar *displayKeywordValue = NULL;
2360 int32_t displayKeywordValueLen = 0;
2361 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2362 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2363 if(U_FAILURE(status)){
2364 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));
2367 /* the uenum_next returns NUL terminated string */
2368 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2370 /* fetch the displayKeywordValue */
2371 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2372 if(status==U_BUFFER_OVERFLOW_ERROR){
2373 status = U_ZERO_ERROR;
2374 displayKeywordValueLen++; /* for null termination */
2375 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2376 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2377 if(U_FAILURE(status)){
2378 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));
2381 if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
2382 if (status == U_USING_DEFAULT_WARNING) {
2383 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));
2385 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));
2390 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2392 free(displayKeywordValue);
2394 uenum_close(keywordEnum);
2397 /* test a multiple keywords */
2398 UErrorCode status = U_ZERO_ERROR;
2399 const char* keyword =NULL;
2400 int32_t keywordLen = 0;
2401 int32_t keywordCount = 0;
2402 const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
2403 const char* displayLocale = "de";
2404 static const UChar expected[][50] = {
2405 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2407 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2408 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2411 UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
2413 for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
2414 UChar *displayKeywordValue = NULL;
2415 int32_t displayKeywordValueLen = 0;
2416 if(U_FAILURE(status)){
2417 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
2420 /* the uenum_next returns NUL terminated string */
2421 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2423 /* fetch the displayKeywordValue */
2424 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2425 if(status==U_BUFFER_OVERFLOW_ERROR){
2426 status = U_ZERO_ERROR;
2427 displayKeywordValueLen++; /* for null termination */
2428 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2429 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2430 if(U_FAILURE(status)){
2431 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));
2434 if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
2435 if (status == U_USING_DEFAULT_WARNING) {
2436 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));
2438 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
2443 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2445 free(displayKeywordValue);
2447 uenum_close(keywordEnum);
2451 /* Test non existent keywords */
2452 UErrorCode status = U_ZERO_ERROR;
2453 const char* localeID = "es";
2454 const char* displayLocale = "de";
2455 UChar *displayKeywordValue = NULL;
2456 int32_t displayKeywordValueLen = 0;
2458 /* fetch the displayKeywordValue */
2459 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2460 if(U_FAILURE(status)) {
2461 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
2462 } else if(displayKeywordValueLen != 0) {
2463 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
2469 static void TestGetBaseName(void) {
2470 static const struct {
2471 const char *localeID;
2472 const char *baseName;
2474 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2475 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2476 { "ja@calendar = buddhist", "ja" }
2479 int32_t i = 0, baseNameLen = 0;
2481 UErrorCode status = U_ZERO_ERROR;
2483 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2484 baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
2485 (void)baseNameLen; /* Suppress set but not used warning. */
2486 if(strcmp(testCases[i].baseName, baseName)) {
2487 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2488 testCases[i].localeID, testCases[i].baseName, baseName);
2494 static void TestTrailingNull(void) {
2495 const char* localeId = "zh_Hans";
2496 UChar buffer[128]; /* sufficient for this test */
2498 UErrorCode status = U_ZERO_ERROR;
2501 len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status);
2503 log_err("buffer too small");
2507 for (i = 0; i < len; ++i) {
2508 if (buffer[i] == 0) {
2509 log_err("name contained null");
2515 /* Jitterbug 4115 */
2516 static void TestDisplayNameWarning(void) {
2519 UErrorCode status = U_ZERO_ERROR;
2521 size = uloc_getDisplayLanguage("qqq", "kl", name, UPRV_LENGTHOF(name), &status);
2522 (void)size; /* Suppress set but not used warning. */
2523 if (status != U_USING_DEFAULT_WARNING) {
2524 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2525 u_errorName(status));
2531 * Compare two locale IDs. If they are equal, return 0. If `string'
2532 * starts with `prefix' plus an additional element, that is, string ==
2533 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2535 static UBool _loccmp(const char* string, const char* prefix) {
2536 int32_t slen = (int32_t)uprv_strlen(string),
2537 plen = (int32_t)uprv_strlen(prefix);
2538 int32_t c = uprv_strncmp(string, prefix, plen);
2539 /* 'root' is less than everything */
2540 if (uprv_strcmp(prefix, "root") == 0) {
2541 return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
2543 if (c) return -1; /* mismatch */
2544 if (slen == plen) return 0;
2545 if (string[plen] == '_') return 1;
2546 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2549 static void _checklocs(const char* label,
2552 const char* actual) {
2553 /* We want the valid to be strictly > the bogus requested locale,
2554 and the valid to be >= the actual. */
2555 if (_loccmp(req, valid) > 0 &&
2556 _loccmp(valid, actual) >= 0) {
2557 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2558 label, req, valid, actual);
2560 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2561 label, req, valid, actual);
2565 static void TestGetLocale(void) {
2566 UErrorCode ec = U_ZERO_ERROR;
2568 UChar EMPTY[1] = {0};
2571 #if !UCONFIG_NO_FORMATTING
2574 const char *req = "en_US_REDWOODSHORES", *valid, *actual;
2575 obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
2579 if (U_FAILURE(ec)) {
2580 log_data_err("udat_open failed.Error %s\n", u_errorName(ec));
2583 valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2584 actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2585 if (U_FAILURE(ec)) {
2586 log_err("udat_getLocaleByType() failed\n");
2589 _checklocs("udat", req, valid, actual);
2595 #if !UCONFIG_NO_FORMATTING
2598 const char *req = "fr_FR_PROVENCAL", *valid, *actual;
2599 obj = ucal_open(NULL, 0,
2603 if (U_FAILURE(ec)) {
2604 log_err("ucal_open failed with error: %s\n", u_errorName(ec));
2607 valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2608 actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2609 if (U_FAILURE(ec)) {
2610 log_err("ucal_getLocaleByType() failed\n");
2613 _checklocs("ucal", req, valid, actual);
2619 #if !UCONFIG_NO_FORMATTING
2622 const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
2623 obj = unum_open(UNUM_DECIMAL,
2627 if (U_FAILURE(ec)) {
2628 log_err("unum_open failed\n");
2631 valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2632 actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2633 if (U_FAILURE(ec)) {
2634 log_err("unum_getLocaleByType() failed\n");
2637 _checklocs("unum", req, valid, actual);
2644 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2645 #if !UCONFIG_NO_FORMATTING
2647 UMessageFormat *obj;
2648 const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
2650 obj = umsg_open(EMPTY, 0,
2653 if (U_FAILURE(ec)) {
2654 log_err("umsg_open failed\n");
2657 valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2658 actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2659 if (U_FAILURE(ec)) {
2660 log_err("umsg_getLocaleByType() failed\n");
2663 /* We want the valid to be strictly > the bogus requested locale,
2664 and the valid to be >= the actual. */
2665 /* TODO MessageFormat is currently just storing the locale it is given.
2666 As a result, it will return whatever it was given, even if the
2667 locale is invalid. */
2668 test = (_cmpversion("3.2") <= 0) ?
2669 /* Here is the weakened test for 3.0: */
2670 (_loccmp(req, valid) >= 0) :
2671 /* Here is what the test line SHOULD be: */
2672 (_loccmp(req, valid) > 0);
2675 _loccmp(valid, actual) >= 0) {
2676 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2678 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2686 #if !UCONFIG_NO_BREAK_ITERATION
2688 UBreakIterator *obj;
2689 const char *req = "ar_KW_ABDALI", *valid, *actual;
2690 obj = ubrk_open(UBRK_WORD,
2695 if (U_FAILURE(ec)) {
2696 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
2699 valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2700 actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2701 if (U_FAILURE(ec)) {
2702 log_err("ubrk_getLocaleByType() failed\n");
2705 _checklocs("ubrk", req, valid, actual);
2711 #if !UCONFIG_NO_COLLATION
2714 const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
2715 obj = ucol_open(req, &ec);
2716 if (U_FAILURE(ec)) {
2717 log_err("ucol_open failed - %s\n", u_errorName(ec));
2720 valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2721 actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2722 if (U_FAILURE(ec)) {
2723 log_err("ucol_getLocaleByType() failed\n");
2726 _checklocs("ucol", req, valid, actual);
2731 static void TestEnglishExemplarCharacters(void) {
2732 UErrorCode status = U_ZERO_ERROR;
2735 UChar testChars[] = {
2736 0x61, /* standard */
2737 0xE1, /* auxiliary */
2739 0x2D /* punctuation */
2741 ULocaleData *uld = ulocdata_open("en", &status);
2742 if (U_FAILURE(status)) {
2743 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status));
2747 for (i = 0; i < ULOCDATA_ES_COUNT; i++) {
2748 exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status);
2749 if (U_FAILURE(status)) {
2750 log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i);
2751 status = U_ZERO_ERROR;
2754 if (!uset_contains(exSet, (UChar32)testChars[i])) {
2755 log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i);
2760 ulocdata_close(uld);
2763 static void TestNonexistentLanguageExemplars(void) {
2764 /* JB 4068 - Nonexistent language */
2765 UErrorCode ec = U_ZERO_ERROR;
2766 ULocaleData *uld = ulocdata_open("qqq",&ec);
2767 if (ec != U_USING_DEFAULT_WARNING) {
2768 log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2771 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2772 ulocdata_close(uld);
2775 static void TestLocDataErrorCodeChaining(void) {
2776 UErrorCode ec = U_USELESS_COLLATOR_ERROR;
2777 ulocdata_open(NULL, &ec);
2778 ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
2779 ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
2780 ulocdata_getMeasurementSystem(NULL, &ec);
2781 ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
2782 if (ec != U_USELESS_COLLATOR_ERROR) {
2783 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
2789 UMeasurementSystem measureSys;
2792 static const LocToMeasureSys locToMeasures[] = {
2793 { "fr_FR", UMS_SI },
2795 { "en_GB", UMS_UK },
2796 { "fr_FR@rg=GBZZZZ", UMS_UK },
2797 { "en@rg=frzzzz", UMS_SI },
2798 { "en_GB@rg=USZZZZ", UMS_US },
2799 { NULL, (UMeasurementSystem)0 } /* terminator */
2802 static void TestLocDataWithRgTag(void) {
2803 const LocToMeasureSys* locToMeasurePtr = locToMeasures;
2804 for (; locToMeasurePtr->locale != NULL; locToMeasurePtr++) {
2805 UErrorCode status = U_ZERO_ERROR;
2806 UMeasurementSystem measureSys = ulocdata_getMeasurementSystem(locToMeasurePtr->locale, &status);
2807 if (U_FAILURE(status)) {
2808 log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
2809 locToMeasurePtr->locale, u_errorName(status));
2810 } else if (measureSys != locToMeasurePtr->measureSys) {
2811 log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
2812 locToMeasurePtr->locale, (int) locToMeasurePtr->measureSys, (int)measureSys);
2817 static void TestLanguageExemplarsFallbacks(void) {
2818 /* Test that en_US fallsback, but en doesn't fallback. */
2819 UErrorCode ec = U_ZERO_ERROR;
2820 ULocaleData *uld = ulocdata_open("en_US",&ec);
2821 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2822 if (ec != U_USING_FALLBACK_WARNING) {
2823 log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2826 ulocdata_close(uld);
2828 uld = ulocdata_open("en",&ec);
2829 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2830 if (ec != U_ZERO_ERROR) {
2831 log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2834 ulocdata_close(uld);
2837 static const char *acceptResult(UAcceptResult uar) {
2838 return udbg_enumName(UDBG_UAcceptResult, uar);
2841 static void TestAcceptLanguage(void) {
2842 UErrorCode status = U_ZERO_ERROR;
2843 UAcceptResult outResult;
2844 UEnumeration *available;
2850 int32_t httpSet; /**< Which of http[] should be used? */
2851 const char *icuSet; /**< ? */
2852 const char *expect; /**< The expected locale result */
2853 UAcceptResult res; /**< The expected error code */
2854 UErrorCode expectStatus; /**< expected status */
2856 /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2857 /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2858 /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},
2859 /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR},
2860 /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
2861 /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, /* XF */
2862 /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
2863 /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
2864 /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
2865 /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
2866 /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
2867 /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
2869 const int32_t numTests = UPRV_LENGTHOF(tests);
2870 static const char *http[] = {
2871 /*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",
2872 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2873 /*2*/ "en-wf, de-lx;q=0.8",
2874 /*3*/ "mga-ie;q=0.9, tlh",
2875 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2876 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2877 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2878 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2879 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2880 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2881 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2883 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2885 /*7*/ "zh-xx;q=0.9",
2886 /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2887 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2888 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2889 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
2890 /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2891 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2892 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2893 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
2894 /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2895 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2896 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2897 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
2898 /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2899 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2900 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2901 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
2904 for(i=0;i<numTests;i++) {
2906 status=U_ZERO_ERROR;
2907 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2908 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2910 available = ures_openAvailableLocales(tests[i].icuSet, &status);
2912 rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status);
2913 (void)rc; /* Suppress set but not used warning. */
2914 uenum_close(available);
2915 log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
2916 if(status != tests[i].expectStatus) {
2917 log_err_status(status, "FAIL: expected status %s but got %s\n", u_errorName(tests[i].expectStatus), u_errorName(status));
2918 } else if(U_SUCCESS(tests[i].expectStatus)) {
2919 /* don't check content if expected failure */
2920 if(outResult != tests[i].res) {
2921 log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
2922 acceptResult( tests[i].res),
2923 acceptResult( outResult));
2924 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2925 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res));
2927 if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
2928 log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
2929 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2930 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2936 static const char* LOCALE_ALIAS[][2] = {
2950 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
2951 UErrorCode status = U_ZERO_ERROR;
2953 ures_getStringByKey(resIndex, loc,&len, &status);
2954 if(U_FAILURE(status)){
2960 static void TestCalendar() {
2961 #if !UCONFIG_NO_FORMATTING
2963 UErrorCode status = U_ZERO_ERROR;
2964 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2965 if(U_FAILURE(status)){
2966 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2969 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
2970 const char* oldLoc = LOCALE_ALIAS[i][0];
2971 const char* newLoc = LOCALE_ALIAS[i][1];
2972 UCalendar* c1 = NULL;
2973 UCalendar* c2 = NULL;
2975 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2976 const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2977 const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2979 if(!isLocaleAvailable(resIndex, newLoc)){
2982 c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
2983 c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
2985 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
2986 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2988 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2);
2992 ures_close(resIndex);
2996 static void TestDateFormat() {
2997 #if !UCONFIG_NO_FORMATTING
2999 UErrorCode status = U_ZERO_ERROR;
3000 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3001 if(U_FAILURE(status)){
3002 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3005 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3006 const char* oldLoc = LOCALE_ALIAS[i][0];
3007 const char* newLoc = LOCALE_ALIAS[i][1];
3008 UDateFormat* df1 = NULL;
3009 UDateFormat* df2 = NULL;
3010 const char* l1 = NULL;
3011 const char* l2 = NULL;
3013 if(!isLocaleAvailable(resIndex, newLoc)){
3016 df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
3017 df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
3018 if(U_FAILURE(status)){
3019 log_err("Creation of date format failed %s\n", u_errorName(status));
3022 /*Test function "getLocale"*/
3023 l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
3024 l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
3025 if(U_FAILURE(status)){
3026 log_err("Fetching the locale by type failed. %s\n", u_errorName(status));
3028 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
3029 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3031 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2);
3035 ures_close(resIndex);
3039 static void TestCollation() {
3040 #if !UCONFIG_NO_COLLATION
3042 UErrorCode status = U_ZERO_ERROR;
3043 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3044 if(U_FAILURE(status)){
3045 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3048 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3049 const char* oldLoc = LOCALE_ALIAS[i][0];
3050 const char* newLoc = LOCALE_ALIAS[i][1];
3051 UCollator* c1 = NULL;
3052 UCollator* c2 = NULL;
3053 const char* l1 = NULL;
3054 const char* l2 = NULL;
3056 status = U_ZERO_ERROR;
3057 if(!isLocaleAvailable(resIndex, newLoc)){
3060 if(U_FAILURE(status)){
3061 log_err("Creation of collators failed %s\n", u_errorName(status));
3064 c1 = ucol_open(oldLoc, &status);
3065 c2 = ucol_open(newLoc, &status);
3066 l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
3067 l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
3068 if(U_FAILURE(status)){
3069 log_err("Fetching the locale names failed failed %s\n", u_errorName(status));
3071 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
3072 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3074 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2);
3078 ures_close(resIndex);
3082 typedef struct OrientationStructTag {
3083 const char* localeId;
3084 ULayoutType character;
3086 } OrientationStruct;
3088 static const char* ULayoutTypeToString(ULayoutType type)
3092 case ULOC_LAYOUT_LTR:
3093 return "ULOC_LAYOUT_LTR";
3095 case ULOC_LAYOUT_RTL:
3096 return "ULOC_LAYOUT_RTL";
3098 case ULOC_LAYOUT_TTB:
3099 return "ULOC_LAYOUT_TTB";
3101 case ULOC_LAYOUT_BTT:
3102 return "ULOC_LAYOUT_BTT";
3104 case ULOC_LAYOUT_UNKNOWN:
3108 return "Unknown enum value for ULayoutType!";
3111 static void TestOrientation()
3113 static const OrientationStruct toTest [] = {
3114 { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3115 { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3116 { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3117 { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3118 { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3119 { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3120 { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3121 { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3122 { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
3123 { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB }
3127 for (; i < UPRV_LENGTHOF(toTest); ++i) {
3128 UErrorCode statusCO = U_ZERO_ERROR;
3129 UErrorCode statusLO = U_ZERO_ERROR;
3130 const char* const localeId = toTest[i].localeId;
3131 const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO);
3132 const ULayoutType expectedCO = toTest[i].character;
3133 const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO);
3134 const ULayoutType expectedLO = toTest[i].line;
3135 if (U_FAILURE(statusCO)) {
3136 log_err_status(statusCO,
3137 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
3139 u_errorName(statusCO));
3141 else if (co != expectedCO) {
3143 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3145 ULayoutTypeToString(expectedCO),
3146 ULayoutTypeToString(co));
3148 if (U_FAILURE(statusLO)) {
3149 log_err_status(statusLO,
3150 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
3152 u_errorName(statusLO));
3154 else if (lo != expectedLO) {
3156 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3158 ULayoutTypeToString(expectedLO),
3159 ULayoutTypeToString(lo));
3164 static void TestULocale() {
3166 UErrorCode status = U_ZERO_ERROR;
3167 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
3168 if(U_FAILURE(status)){
3169 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3172 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3173 const char* oldLoc = LOCALE_ALIAS[i][0];
3174 const char* newLoc = LOCALE_ALIAS[i][1];
3175 UChar name1[256], name2[256];
3176 char names1[256], names2[256];
3177 int32_t capacity = 256;
3179 status = U_ZERO_ERROR;
3180 if(!isLocaleAvailable(resIndex, newLoc)){
3183 uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
3184 if(U_FAILURE(status)){
3185 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
3188 uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
3189 if(U_FAILURE(status)){
3190 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
3193 if (u_strcmp(name1, name2)!=0) {
3194 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3196 u_austrcpy(names1, name1);
3197 u_austrcpy(names2, name2);
3198 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2);
3200 ures_close(resIndex);
3204 static void TestUResourceBundle() {
3208 UResourceBundle* rb1 = NULL;
3209 UResourceBundle* rb2 = NULL;
3210 UErrorCode status = U_ZERO_ERROR;
3212 UResourceBundle *resIndex = NULL;
3213 if(U_FAILURE(status)){
3214 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
3217 resIndex = ures_open(NULL,"res_index", &status);
3218 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3220 const char* oldLoc = LOCALE_ALIAS[i][0];
3221 const char* newLoc = LOCALE_ALIAS[i][1];
3222 if(!isLocaleAvailable(resIndex, newLoc)){
3225 rb1 = ures_open(NULL, oldLoc, &status);
3226 if (U_FAILURE(status)) {
3227 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3230 us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status);
3232 status = U_ZERO_ERROR;
3233 rb2 = ures_open(NULL, newLoc, &status);
3234 if (U_FAILURE(status)) {
3235 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
3237 us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status);
3239 if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
3240 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
3243 log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2);
3249 ures_close(resIndex);
3252 static void TestDisplayName() {
3254 UChar oldCountry[256] = {'\0'};
3255 UChar newCountry[256] = {'\0'};
3256 UChar oldLang[256] = {'\0'};
3257 UChar newLang[256] = {'\0'};
3258 char country[256] ={'\0'};
3259 char language[256] ={'\0'};
3260 int32_t capacity = 256;
3263 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) {
3264 const char* oldLoc = LOCALE_ALIAS[i][0];
3265 const char* newLoc = LOCALE_ALIAS[i][1];
3266 UErrorCode status = U_ZERO_ERROR;
3267 int32_t available = uloc_countAvailable();
3269 for(j=0; j<available; j++){
3271 const char* dispLoc = uloc_getAvailable(j);
3272 int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
3273 int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
3274 int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
3275 int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
3277 int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
3278 int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status);
3279 /* there is a display name for the current country ID */
3280 if(countryLen != newCountryLen ){
3281 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
3282 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
3285 /* there is a display name for the current lang ID */
3286 if(langLen!=newLangLen){
3287 if(u_strncmp(oldLang,newLang,oldLangLen)){
3288 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); }
3294 static void TestGetLocaleForLCID() {
3295 int32_t i, length, lengthPre;
3296 const char* testLocale = 0;
3297 UErrorCode status = U_ZERO_ERROR;
3298 char temp2[40], temp3[40];
3301 lcid = uloc_getLCID("en_US");
3302 if (lcid != 0x0409) {
3303 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
3306 lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
3307 if (status != U_BUFFER_OVERFLOW_ERROR) {
3308 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
3311 status = U_ZERO_ERROR;
3314 length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3315 if (U_FAILURE(status)) {
3316 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
3317 status = U_ZERO_ERROR;
3320 if (length != lengthPre) {
3321 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
3324 length = uloc_getLocaleForLCID(0x12345, temp2, UPRV_LENGTHOF(temp2), &status);
3325 if (U_SUCCESS(status)) {
3326 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
3328 status = U_ZERO_ERROR;
3330 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3331 for (i = 0; i < LOCALE_SIZE; i++) {
3333 testLocale=rawData2[NAME][i];
3335 log_verbose("Testing %s ......\n", testLocale);
3337 sscanf(rawData2[LCID][i], "%x", &lcid);
3338 length = uloc_getLocaleForLCID(lcid, temp2, UPRV_LENGTHOF(temp2), &status);
3339 if (U_FAILURE(status)) {
3340 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
3341 status = U_ZERO_ERROR;
3345 if (length != uprv_strlen(temp2)) {
3346 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
3349 /* Compare language, country, script */
3350 length = uloc_getLanguage(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3351 if (U_FAILURE(status)) {
3352 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3353 status = U_ZERO_ERROR;
3355 else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
3356 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
3359 length = uloc_getScript(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3360 if (U_FAILURE(status)) {
3361 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3362 status = U_ZERO_ERROR;
3364 else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
3365 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
3368 length = uloc_getCountry(temp2, temp3, UPRV_LENGTHOF(temp3), &status);
3369 if (U_FAILURE(status)) {
3370 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3371 status = U_ZERO_ERROR;
3373 else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
3374 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
3380 const char* const basic_maximize_data[][2] = {
3425 "en_Latn_US_POSIX_1901"
3427 "en_Latn__POSIX_1901",
3428 "en_Latn_US_POSIX_1901"
3431 "en_Latn_US_POSIX_1901"
3434 "de_Latn_DE_POSIX_1901"
3439 "th@calendar=buddhist",
3440 "th_Thai_TH@calendar=buddhist"
3470 "de_Latn_DE_U_CO_PHONEBK"
3472 "de_Latn_u_co_phonebk",
3473 "de_Latn_DE_U_CO_PHONEBK"
3475 "de_Latn_DE_u_co_phonebk",
3476 "de_Latn_DE_U_CO_PHONEBK"
3480 const char* const basic_minimize_data[][2] = {
3485 "en_Latn_US_POSIX_1901",
3488 "EN_Latn_US_POSIX_1901",
3491 "en_Zzzz_US_POSIX_1901",
3494 "de_Latn_DE_POSIX_1901",
3500 "en_Latn_US@calendar=gregorian",
3501 "en@calendar=gregorian"
3505 const char* const full_data[][3] = {
3509 /* "REMOVE-LIKELY" */
4992 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
4993 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5575 "de@collation=phonebook",
5576 "de_Latn_DE@collation=phonebook",
5577 "de@collation=phonebook"
5581 typedef struct errorDataTag {
5583 const char* expected;
5588 const errorData maximizeErrors[] = {
5592 U_ILLEGAL_ARGUMENT_ERROR,
5596 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5598 U_ILLEGAL_ARGUMENT_ERROR,
5602 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5604 U_ILLEGAL_ARGUMENT_ERROR,
5608 "en_Latn_US_POSIX@currency=EURO",
5609 "en_Latn_US_POSIX@currency=EURO",
5610 U_BUFFER_OVERFLOW_ERROR,
5614 "en_Latn_US_POSIX@currency=EURO",
5615 "en_Latn_US_POSIX@currency=EURO",
5616 U_STRING_NOT_TERMINATED_WARNING,
5621 const errorData minimizeErrors[] = {
5625 U_ILLEGAL_ARGUMENT_ERROR,
5629 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5631 U_ILLEGAL_ARGUMENT_ERROR,
5635 "en_Latn_US_POSIX@currency=EURO",
5636 "en__POSIX@currency=EURO",
5637 U_BUFFER_OVERFLOW_ERROR,
5641 "en_Latn_US_POSIX@currency=EURO",
5642 "en__POSIX@currency=EURO",
5643 U_STRING_NOT_TERMINATED_WARNING,
5648 static int32_t getExpectedReturnValue(const errorData* data)
5650 if (data->uerror == U_BUFFER_OVERFLOW_ERROR ||
5651 data->uerror == U_STRING_NOT_TERMINATED_WARNING)
5653 return strlen(data->expected);
5661 static int32_t getBufferSize(const errorData* data, int32_t actualSize)
5663 if (data->expected == NULL)
5667 else if (data->bufferSize < 0)
5669 return strlen(data->expected) + 1;
5673 return data->bufferSize;
5677 static void TestLikelySubtags()
5679 char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1];
5682 for (; i < UPRV_LENGTHOF(basic_maximize_data); ++i)
5684 UErrorCode status = U_ZERO_ERROR;
5685 const char* const minimal = basic_maximize_data[i][0];
5686 const char* const maximal = basic_maximize_data[i][1];
5688 /* const int32_t length = */
5689 uloc_addLikelySubtags(
5694 if (U_FAILURE(status)) {
5695 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status));
5696 status = U_ZERO_ERROR;
5698 else if (uprv_strlen(maximal) == 0) {
5699 if (uprv_stricmp(minimal, buffer) != 0) {
5700 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5703 else if (uprv_stricmp(maximal, buffer) != 0) {
5704 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer);
5708 for (i = 0; i < UPRV_LENGTHOF(basic_minimize_data); ++i) {
5710 UErrorCode status = U_ZERO_ERROR;
5711 const char* const maximal = basic_minimize_data[i][0];
5712 const char* const minimal = basic_minimize_data[i][1];
5714 /* const int32_t length = */
5715 uloc_minimizeSubtags(
5721 if (U_FAILURE(status)) {
5722 log_err_status(status, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5723 status = U_ZERO_ERROR;
5725 else if (uprv_strlen(minimal) == 0) {
5726 if (uprv_stricmp(maximal, buffer) != 0) {
5727 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5730 else if (uprv_stricmp(minimal, buffer) != 0) {
5731 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5735 for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
5737 UErrorCode status = U_ZERO_ERROR;
5738 const char* const minimal = full_data[i][0];
5739 const char* const maximal = full_data[i][1];
5741 /* const int32_t length = */
5742 uloc_addLikelySubtags(
5747 if (U_FAILURE(status)) {
5748 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status));
5749 status = U_ZERO_ERROR;
5751 else if (uprv_strlen(maximal) == 0) {
5752 if (uprv_stricmp(minimal, buffer) != 0) {
5753 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5756 else if (uprv_stricmp(maximal, buffer) != 0) {
5757 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5761 for (i = 0; i < UPRV_LENGTHOF(full_data); ++i) {
5763 UErrorCode status = U_ZERO_ERROR;
5764 const char* const maximal = full_data[i][1];
5765 const char* const minimal = full_data[i][2];
5767 if (strlen(maximal) > 0) {
5769 /* const int32_t length = */
5770 uloc_minimizeSubtags(
5776 if (U_FAILURE(status)) {
5777 log_err_status(status, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5778 status = U_ZERO_ERROR;
5780 else if (uprv_strlen(minimal) == 0) {
5781 if (uprv_stricmp(maximal, buffer) != 0) {
5782 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5785 else if (uprv_stricmp(minimal, buffer) != 0) {
5786 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5791 for (i = 0; i < UPRV_LENGTHOF(maximizeErrors); ++i) {
5793 UErrorCode status = U_ZERO_ERROR;
5794 const char* const minimal = maximizeErrors[i].tag;
5795 const char* const maximal = maximizeErrors[i].expected;
5796 const UErrorCode expectedStatus = maximizeErrors[i].uerror;
5797 const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]);
5798 const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer));
5800 const int32_t length =
5801 uloc_addLikelySubtags(
5807 if (status == U_ZERO_ERROR) {
5808 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus));
5809 status = U_ZERO_ERROR;
5811 else if (status != expectedStatus) {
5812 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));
5814 else if (length != expectedLength) {
5815 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length);
5817 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5818 if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) {
5819 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5820 maximal, minimal, (int)sizeof(buffer), buffer);
5825 for (i = 0; i < UPRV_LENGTHOF(minimizeErrors); ++i) {
5827 UErrorCode status = U_ZERO_ERROR;
5828 const char* const maximal = minimizeErrors[i].tag;
5829 const char* const minimal = minimizeErrors[i].expected;
5830 const UErrorCode expectedStatus = minimizeErrors[i].uerror;
5831 const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]);
5832 const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer));
5834 const int32_t length =
5835 uloc_minimizeSubtags(
5841 if (status == U_ZERO_ERROR) {
5842 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus));
5843 status = U_ZERO_ERROR;
5845 else if (status != expectedStatus) {
5846 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));
5848 else if (length != expectedLength) {
5849 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length);
5851 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5852 if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) {
5853 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5854 minimal, maximal, (int)sizeof(buffer), buffer);
5860 const char* const locale_to_langtag[][3] = {
5863 {"en_US", "en-US", "en-US"},
5864 {"iw_IL", "he-IL", "he-IL"},
5865 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5866 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5867 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5868 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL}, /* variant POSIX_VAR is processed as regular variant */
5869 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL}, /* variant VAR_POSIX is processed as regular variant */
5870 {"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 */
5871 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5872 {"und_555", "und-555", "und-555"},
5873 {"123", "und", NULL},
5874 {"%$#&", "und", NULL},
5875 {"_Latn", "und-Latn", "und-Latn"},
5876 {"_DE", "und-DE", "und-DE"},
5877 {"und_FR", "und-FR", "und-FR"},
5878 {"th_TH_TH", "th-TH-x-lvariant-th", NULL},
5879 {"bogus", "bogus", "bogus"},
5880 {"foooobarrr", "und", NULL},
5881 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5882 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL},
5883 {"en_US_1234", "en-US-1234", "en-US-1234"},
5884 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5885 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5886 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL},
5887 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL},
5888 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5889 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5890 {"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"},
5891 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5892 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5893 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL},
5894 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL},
5895 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5896 {"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"},
5897 {"@x=elmer", "x-elmer", "x-elmer"},
5898 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5899 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5900 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5902 {"en@a=bar;attribute=baz", "en-a-bar-u-baz", "en-a-bar-u-baz"},
5903 {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo", "en-a-bar-u-baz-x-u-foo"},
5904 {"en@attribute=baz", "en-u-baz", "en-u-baz"},
5905 {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil", "en-u-baz-ca-islamic-civil"},
5906 {"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"},
5907 {"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"},
5911 static void TestToLanguageTag(void) {
5917 const char *expected;
5919 for (i = 0; locale_to_langtag[i][0] != NULL; i++) {
5920 inloc = locale_to_langtag[i][0];
5922 /* testing non-strict mode */
5923 status = U_ZERO_ERROR;
5925 expected = locale_to_langtag[i][1];
5927 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status);
5928 (void)len; /* Suppress set but not used warning. */
5929 if (U_FAILURE(status)) {
5930 if (expected != NULL) {
5931 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5932 inloc, u_errorName(status));
5935 if (expected == NULL) {
5936 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5938 } else if (uprv_strcmp(langtag, expected) != 0) {
5939 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5940 langtag, inloc, expected);
5944 /* testing strict mode */
5945 status = U_ZERO_ERROR;
5947 expected = locale_to_langtag[i][2];
5949 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status);
5950 if (U_FAILURE(status)) {
5951 if (expected != NULL) {
5952 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5953 inloc, u_errorName(status));
5956 if (expected == NULL) {
5957 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5959 } else if (uprv_strcmp(langtag, expected) != 0) {
5960 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5961 langtag, inloc, expected);
5967 #define FULL_LENGTH -1
5968 static const struct {
5972 } langtag_to_locale[] = {
5973 {"en", "en", FULL_LENGTH},
5974 {"en-us", "en_US", FULL_LENGTH},
5975 {"und-US", "_US", FULL_LENGTH},
5976 {"und-latn", "_Latn", FULL_LENGTH},
5977 {"en-US-posix", "en_US_POSIX", FULL_LENGTH},
5978 {"de-de_euro", "de", 2},
5979 {"kok-IN", "kok_IN", FULL_LENGTH},
5982 {"en-latn-x", "en_Latn", 7},
5983 {"art-lojban", "jbo", FULL_LENGTH},
5984 {"zh-hakka", "hak", FULL_LENGTH},
5985 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH},
5986 {"xxx-yy", "xxx_YY", FULL_LENGTH},
5987 {"fr-234", "fr_234", FULL_LENGTH},
5988 {"i-default", "en@x=i-default", FULL_LENGTH},
5990 {"ja-jp-jp", "ja_JP", 5},
5991 {"bogus", "bogus", FULL_LENGTH},
5992 {"boguslang", "", 0},
5993 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH},
5994 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH},
5995 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5996 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH},
5997 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH},
5998 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH},
5999 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH},
6000 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH},
6001 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH},
6002 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH},
6003 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH},
6004 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH},
6005 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH},
6006 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH},
6007 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH},
6008 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH},
6009 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH},
6010 {"x-elmer", "@x=elmer", FULL_LENGTH},
6011 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH},
6012 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH},
6013 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH},
6014 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH},
6015 {"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},
6016 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
6017 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
6019 {"en-a-bar-u-baz", "en@a=bar;attribute=baz", FULL_LENGTH},
6020 {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", FULL_LENGTH},
6021 {"en-u-baz", "en@attribute=baz", FULL_LENGTH},
6022 {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", FULL_LENGTH},
6023 {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", FULL_LENGTH},
6024 {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", FULL_LENGTH},
6028 static void TestForLanguageTag(void) {
6033 int32_t expParsedLen;
6035 for (i = 0; langtag_to_locale[i].bcpID != NULL; i++) {
6036 status = U_ZERO_ERROR;
6038 expParsedLen = langtag_to_locale[i].len;
6039 if (expParsedLen == FULL_LENGTH) {
6040 expParsedLen = uprv_strlen(langtag_to_locale[i].bcpID);
6042 uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status);
6043 if (U_FAILURE(status)) {
6044 log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
6045 langtag_to_locale[i].bcpID, u_errorName(status));
6047 if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) {
6048 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
6049 locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID);
6051 if (parsedLen != expParsedLen) {
6052 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
6053 parsedLen, langtag_to_locale[i].bcpID, expParsedLen);
6059 static void TestToUnicodeLocaleKey(void)
6061 /* $IN specifies the result should be the input pointer itself */
6062 static const char* DATA[][2] = {
6064 {"CALEndar", "ca"}, /* difference casing */
6065 {"ca", "ca"}, /* bcp key itself */
6066 {"kv", "kv"}, /* no difference between legacy and bcp */
6067 {"foo", NULL}, /* unknown, bcp ill-formed */
6068 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
6073 for (i = 0; DATA[i][0] != NULL; i++) {
6074 const char* keyword = DATA[i][0];
6075 const char* expected = DATA[i][1];
6076 const char* bcpKey = NULL;
6078 bcpKey = uloc_toUnicodeLocaleKey(keyword);
6079 if (expected == NULL) {
6080 if (bcpKey != NULL) {
6081 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey);
6083 } else if (bcpKey == NULL) {
6084 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6085 } else if (uprv_strcmp(expected, "$IN") == 0) {
6086 if (bcpKey != keyword) {
6087 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword);
6089 } else if (uprv_strcmp(bcpKey, expected) != 0) {
6090 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected);
6095 static void TestToLegacyKey(void)
6097 /* $IN specifies the result should be the input pointer itself */
6098 static const char* DATA[][2] = {
6099 {"kb", "colbackwards"},
6100 {"kB", "colbackwards"}, /* different casing */
6101 {"Collation", "collation"}, /* keyword itself with different casing */
6102 {"kv", "kv"}, /* no difference between legacy and bcp */
6103 {"foo", "$IN"}, /* unknown, bcp ill-formed */
6104 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
6105 {"e=mc2", NULL}, /* unknown, bcp/legacy ill-formed */
6110 for (i = 0; DATA[i][0] != NULL; i++) {
6111 const char* keyword = DATA[i][0];
6112 const char* expected = DATA[i][1];
6113 const char* legacyKey = NULL;
6115 legacyKey = uloc_toLegacyKey(keyword);
6116 if (expected == NULL) {
6117 if (legacyKey != NULL) {
6118 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey);
6120 } else if (legacyKey == NULL) {
6121 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected);
6122 } else if (uprv_strcmp(expected, "$IN") == 0) {
6123 if (legacyKey != keyword) {
6124 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword);
6126 } else if (uprv_strcmp(legacyKey, expected) != 0) {
6127 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected);
6132 static void TestToUnicodeLocaleType(void)
6134 /* $IN specifies the result should be the input pointer itself */
6135 static const char* DATA[][3] = {
6136 {"tz", "Asia/Kolkata", "inccu"},
6137 {"calendar", "gregorian", "gregory"},
6138 {"ca", "gregorian", "gregory"},
6139 {"ca", "Gregorian", "gregory"},
6140 {"ca", "buddhist", "buddhist"},
6141 {"Calendar", "Japanese", "japanese"},
6142 {"calendar", "Islamic-Civil", "islamic-civil"},
6143 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6144 {"colalternate", "NON-IGNORABLE", "noignore"},
6145 {"colcaselevel", "yes", "true"},
6146 {"rg", "GBzzzz", "$IN"},
6147 {"tz", "america/new_york", "usnyc"},
6148 {"tz", "Asia/Kolkata", "inccu"},
6149 {"timezone", "navajo", "usden"},
6150 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
6151 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6152 {"zz", "gregorian", NULL}, /* unknown key, ill-formed type */
6153 {"co", "foo-", NULL}, /* unknown type, ill-formed type */
6154 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6155 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6156 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6157 {"kr", "digit-spacepunct", NULL}, /* invalid (bcp ill-formed) reordercode type */
6162 for (i = 0; DATA[i][0] != NULL; i++) {
6163 const char* keyword = DATA[i][0];
6164 const char* value = DATA[i][1];
6165 const char* expected = DATA[i][2];
6166 const char* bcpType = NULL;
6168 bcpType = uloc_toUnicodeLocaleType(keyword, value);
6169 if (expected == NULL) {
6170 if (bcpType != NULL) {
6171 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType);
6173 } else if (bcpType == NULL) {
6174 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6175 } else if (uprv_strcmp(expected, "$IN") == 0) {
6176 if (bcpType != value) {
6177 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value);
6179 } else if (uprv_strcmp(bcpType, expected) != 0) {
6180 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected);
6185 static void TestToLegacyType(void)
6187 /* $IN specifies the result should be the input pointer itself */
6188 static const char* DATA[][3] = {
6189 {"calendar", "gregory", "gregorian"},
6190 {"ca", "gregory", "gregorian"},
6191 {"ca", "Gregory", "gregorian"},
6192 {"ca", "buddhist", "buddhist"},
6193 {"Calendar", "Japanese", "japanese"},
6194 {"calendar", "Islamic-Civil", "islamic-civil"},
6195 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6196 {"colalternate", "noignore", "non-ignorable"},
6197 {"colcaselevel", "true", "yes"},
6198 {"rg", "gbzzzz", "gbzzzz"},
6199 {"tz", "usnyc", "America/New_York"},
6200 {"tz", "inccu", "Asia/Calcutta"},
6201 {"timezone", "usden", "America/Denver"},
6202 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6203 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6204 {"ca", "aaaa", "$IN"}, /* unknown type */
6205 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6206 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6207 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6208 {"co", "e=mc2", NULL}, /* known key, ill-formed bcp/legacy type */
6209 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6210 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6211 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6212 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6217 for (i = 0; DATA[i][0] != NULL; i++) {
6218 const char* keyword = DATA[i][0];
6219 const char* value = DATA[i][1];
6220 const char* expected = DATA[i][2];
6221 const char* legacyType = NULL;
6223 legacyType = uloc_toLegacyType(keyword, value);
6224 if (expected == NULL) {
6225 if (legacyType != NULL) {
6226 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType);
6228 } else if (legacyType == NULL) {
6229 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected);
6230 } else if (uprv_strcmp(expected, "$IN") == 0) {
6231 if (legacyType != value) {
6232 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value);
6234 } else if (uprv_strcmp(legacyType, expected) != 0) {
6235 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected);
6237 log_verbose("toLegacyType: keyword=%s, value=%s => %s\n", keyword, value, legacyType);
6244 static void test_unicode_define(const char *namech, char ch, const char *nameu, UChar uch)
6248 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech, ch,(int)ch, nameu, (int) uch);
6249 u_charsToUChars(&ch, asUch, 1);
6250 if(asUch[0] != uch) {
6251 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);
6253 log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]);
6257 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6259 static void TestUnicodeDefines(void) {
6260 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE);
6261 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
6262 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
6265 static void TestIsRightToLeft() {
6266 // API test only. More test cases in intltest/LocaleTest.
6267 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6268 log_err("uloc_isRightToLeft() failed");
6273 const char * badLocaleID;
6274 const char * displayLocale;
6275 const char * expectedName;
6276 UErrorCode expectedStatus;
6279 static const BadLocaleItem badLocaleItems[] = {
6280 { "-9223372036854775808", "en", "9223372036854775808", U_USING_DEFAULT_WARNING },
6281 /* add more in the future */
6282 { NULL, NULL, NULL, U_ZERO_ERROR } /* terminator */
6285 enum { kUBufDispNameMax = 128, kBBufDispNameMax = 256 };
6287 static void TestBadLocaleIDs() {
6288 const BadLocaleItem* itemPtr;
6289 for (itemPtr = badLocaleItems; itemPtr->badLocaleID != NULL; itemPtr++) {
6290 UChar ubufExpect[kUBufDispNameMax], ubufGet[kUBufDispNameMax];
6291 UErrorCode status = U_ZERO_ERROR;
6292 int32_t ulenExpect = u_unescape(itemPtr->expectedName, ubufExpect, kUBufDispNameMax);
6293 int32_t ulenGet = uloc_getDisplayName(itemPtr->badLocaleID, itemPtr->displayLocale, ubufGet, kUBufDispNameMax, &status);
6294 if (status != itemPtr->expectedStatus ||
6295 (U_SUCCESS(status) && (ulenGet != ulenExpect || u_strncmp(ubufGet, ubufExpect, ulenExpect) != 0))) {
6296 char bbufExpect[kBBufDispNameMax], bbufGet[kBBufDispNameMax];
6297 u_austrncpy(bbufExpect, ubufExpect, ulenExpect);
6298 u_austrncpy(bbufGet, ubufGet, ulenGet);
6299 log_err("FAIL: For localeID %s, displayLocale %s, calling uloc_getDisplayName:\n"
6300 " expected status %-26s, name (len %2d): %s\n"
6301 " got status %-26s, name (len %2d): %s\n",
6302 itemPtr->badLocaleID, itemPtr->displayLocale,
6303 u_errorName(itemPtr->expectedStatus), ulenExpect, bbufExpect,
6304 u_errorName(status), ulenGet, bbufGet );