1 /********************************************************************
3 * Copyright (c) 1997-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
10 * Modification History:
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
24 #include "unicode/putil.h"
25 #include "unicode/ubrk.h"
26 #include "unicode/uchar.h"
27 #include "unicode/ucol.h"
28 #include "unicode/udat.h"
29 #include "unicode/uloc.h"
30 #include "unicode/umsg.h"
31 #include "unicode/ures.h"
32 #include "unicode/uset.h"
33 #include "unicode/ustring.h"
34 #include "unicode/utypes.h"
35 #include "unicode/ulocdata.h"
36 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
38 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
40 static void TestNullDefault(void);
41 static void TestNonexistentLanguageExemplars(void);
42 static void TestLocDataErrorCodeChaining(void);
43 static void TestLanguageExemplarsFallbacks(void);
45 static void TestUnicodeDefines(void);
47 void PrintDataTable();
49 /*---------------------------------------------------
51 --------------------------------------------------- */
53 #define LOCALE_INFO_SIZE 28
55 static const char* const rawData2
[LOCALE_INFO_SIZE
][LOCALE_SIZE
] = {
57 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
59 { "", "", "", "", "", "", "", "", "" },
61 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
63 { "", "", "", "", "NY", "", "", "", "" },
65 { "en_US", "fr_FR", "ca_ES",
66 "el_GR", "no_NO_NY", "zh_Hans_CN",
67 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
69 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
71 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
73 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
75 /* display language (English) */
76 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
77 /* display script code (English) */
78 { "", "", "", "", "", "Simplified Han", "", "", "" },
79 /* display country (English) */
80 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
81 /* display variant (English) */
82 { "", "", "", "", "NY", "", "", "", "" },
83 /* display name (English) */
84 { "English (United States)", "French (France)", "Catalan (Spain)",
85 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
86 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
88 /* display language (French) */
89 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
90 /* display script code (French) */
91 { "", "", "", "", "", "chinois simplifi\\u00e9", "", "", "" },
92 /* display country (French) */
93 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
94 /* display variant (French) */
95 { "", "", "", "", "NY", "", "", "", "" },
96 /* display name (French) */
97 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
98 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (id\\u00e9ogrammes han simplifi\\u00e9s, Chine)",
99 "allemand (Allemagne, Ordonnancement=Ordre de l\\u2019annuaire)", "espagnol (Ordonnancement=Ordre traditionnel)", "japonais (Japon, Calendrier=Calendrier japonais)" },
101 /* display language (Catalan) */
102 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
103 /* display script code (Catalan) */
104 { "", "", "", "", "", "xin\\u00E8s simplificat", "", "", "" },
105 /* display country (Catalan) */
106 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
107 /* display variant (Catalan) */
108 { "", "", "", "", "NY", "", "", "", "" },
109 /* display name (Catalan) */
110 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
111 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
112 "alemany (Alemanya, ordre alfab\\u00e8tic=ordre de la guia telef\\u00F2nica)", "espanyol (ordre alfab\\u00e8tic=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
114 /* display language (Greek) */
116 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
117 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
118 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
119 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
120 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
121 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
122 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
123 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
124 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
126 /* display script code (Greek) */
128 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03b1 \\u03a7\\u03b1\\u03bd", "", "", "" },
129 /* display country (Greek) */
131 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2 \\u03C4\\u03B7\\u03C2 \\u0391\\u03BC\\u03B5\\u03C1\\u03B9\\u03BA\\u03AE\\u03C2",
132 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
133 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
134 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
135 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
136 "\\u039A\\u03AF\\u03BD\\u03B1",
137 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
139 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
141 /* display variant (Greek) */
142 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
143 /* display name (Greek) */
145 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2 \\u03C4\\u03B7\\u03C2 \\u0391\\u03BC\\u03B5\\u03C1\\u03B9\\u03BA\\u03AE\\u03C2)",
146 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
147 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
148 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
149 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
150 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc, \\u039A\\u03AF\\u03BD\\u03B1)",
151 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1, \\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\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)",
152 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\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)",
153 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC (\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1, \\u03B7\\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)"
157 static UChar
*** dataTable
=0;
197 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
199 void addLocaleTest(TestNode
** root
);
201 void addLocaleTest(TestNode
** root
)
203 TESTCASE(TestObsoleteNames
); /* srl- move */
204 TESTCASE(TestBasicGetters
);
205 TESTCASE(TestNullDefault
);
206 TESTCASE(TestPrefixes
);
207 TESTCASE(TestSimpleResourceInfo
);
208 TESTCASE(TestDisplayNames
);
209 TESTCASE(TestGetAvailableLocales
);
210 TESTCASE(TestDataDirectory
);
211 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
212 TESTCASE(TestISOFunctions
);
214 TESTCASE(TestISO3Fallback
);
215 TESTCASE(TestUninstalledISO3Names
);
216 TESTCASE(TestSimpleDisplayNames
);
217 TESTCASE(TestVariantParsing
);
218 TESTCASE(TestKeywordVariants
);
219 TESTCASE(TestKeywordVariantParsing
);
220 TESTCASE(TestCanonicalization
);
221 TESTCASE(TestKeywordSet
);
222 TESTCASE(TestKeywordSetError
);
223 TESTCASE(TestDisplayKeywords
);
224 TESTCASE(TestDisplayKeywordValues
);
225 TESTCASE(TestGetBaseName
);
226 #if !UCONFIG_NO_FILE_IO
227 TESTCASE(TestGetLocale
);
229 TESTCASE(TestDisplayNameWarning
);
230 TESTCASE(TestNonexistentLanguageExemplars
);
231 TESTCASE(TestLocDataErrorCodeChaining
);
232 TESTCASE(TestLanguageExemplarsFallbacks
);
233 TESTCASE(TestCalendar
);
234 TESTCASE(TestDateFormat
);
235 TESTCASE(TestCollation
);
236 TESTCASE(TestULocale
);
237 TESTCASE(TestUResourceBundle
);
238 TESTCASE(TestDisplayName
);
239 TESTCASE(TestAcceptLanguage
);
240 TESTCASE(TestGetLocaleForLCID
);
241 TESTCASE(TestOrientation
);
242 TESTCASE(TestLikelySubtags
);
243 TESTCASE(TestToLanguageTag
);
244 TESTCASE(TestForLanguageTag
);
245 TESTCASE(TestTrailingNull
);
246 TESTCASE(TestUnicodeDefines
);
250 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
251 static void TestBasicGetters() {
254 UErrorCode status
= U_ZERO_ERROR
;
255 char *testLocale
= 0;
256 char *temp
= 0, *name
= 0;
257 log_verbose("Testing Basic Getters\n");
258 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
259 testLocale
=(char*)malloc(sizeof(char) * (strlen(rawData2
[NAME
][i
])+1));
260 strcpy(testLocale
,rawData2
[NAME
][i
]);
262 log_verbose("Testing %s .....\n", testLocale
);
263 cap
=uloc_getLanguage(testLocale
, NULL
, 0, &status
);
264 if(status
==U_BUFFER_OVERFLOW_ERROR
){
266 temp
=(char*)malloc(sizeof(char) * (cap
+1));
267 uloc_getLanguage(testLocale
, temp
, cap
+1, &status
);
269 if(U_FAILURE(status
)){
270 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status
));
272 if (0 !=strcmp(temp
,rawData2
[LANG
][i
])) {
273 log_err(" Language code mismatch: %s versus %s\n", temp
, rawData2
[LANG
][i
]);
277 cap
=uloc_getCountry(testLocale
, temp
, cap
, &status
);
278 if(status
==U_BUFFER_OVERFLOW_ERROR
){
280 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
281 uloc_getCountry(testLocale
, temp
, cap
+1, &status
);
283 if(U_FAILURE(status
)){
284 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status
));
286 if (0 != strcmp(temp
, rawData2
[CTRY
][i
])) {
287 log_err(" Country code mismatch: %s versus %s\n", temp
, rawData2
[CTRY
][i
]);
291 cap
=uloc_getVariant(testLocale
, temp
, cap
, &status
);
292 if(status
==U_BUFFER_OVERFLOW_ERROR
){
294 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
295 uloc_getVariant(testLocale
, temp
, cap
+1, &status
);
297 if(U_FAILURE(status
)){
298 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status
));
300 if (0 != strcmp(temp
, rawData2
[VAR
][i
])) {
301 log_err("Variant code mismatch: %s versus %s\n", temp
, rawData2
[VAR
][i
]);
304 cap
=uloc_getName(testLocale
, NULL
, 0, &status
);
305 if(status
==U_BUFFER_OVERFLOW_ERROR
){
307 name
=(char*)malloc(sizeof(char) * (cap
+1));
308 uloc_getName(testLocale
, name
, cap
+1, &status
);
309 } else if(status
==U_ZERO_ERROR
) {
310 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale
);
312 if(U_FAILURE(status
)){
313 log_err("ERROR: in uloc_getName %s\n", myErrorName(status
));
315 if (0 != strcmp(name
, rawData2
[NAME
][i
])){
316 log_err(" Mismatch in getName: %s versus %s\n", name
, rawData2
[NAME
][i
]);
326 static void TestNullDefault() {
327 UErrorCode status
= U_ZERO_ERROR
;
328 char original
[ULOC_FULLNAME_CAPACITY
];
330 uprv_strcpy(original
, uloc_getDefault());
331 uloc_setDefault("qq_BLA", &status
);
332 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
333 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
335 uloc_setDefault(NULL
, &status
);
336 if (uprv_strcmp(uloc_getDefault(), original
) != 0) {
337 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
341 /* Test that set & get of default locale work, and that
342 * default locales are cached and reused, and not overwritten.
346 const char *n2_en_US
;
348 status
= U_ZERO_ERROR
;
349 uloc_setDefault("en_US", &status
);
350 n_en_US
= uloc_getDefault();
351 if (strcmp(n_en_US
, "en_US") != 0) {
352 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
355 uloc_setDefault("fr_FR", &status
);
356 n_fr_FR
= uloc_getDefault();
357 if (strcmp(n_en_US
, "en_US") != 0) {
358 log_err("uloc_setDefault altered previously default string."
359 "Expected \"en_US\", got \"%s\"\n", n_en_US
);
361 if (strcmp(n_fr_FR
, "fr_FR") != 0) {
362 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR
);
365 uloc_setDefault("en_US", &status
);
366 n2_en_US
= uloc_getDefault();
367 if (strcmp(n2_en_US
, "en_US") != 0) {
368 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
370 if (n2_en_US
!= n_en_US
) {
371 log_err("Default locale cache failed to reuse en_US locale.\n");
374 if (U_FAILURE(status
)) {
375 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status
));
381 /* Test the i- and x- and @ and . functionality
384 #define PREFIXBUFSIZ 128
386 static void TestPrefixes() {
389 const char *loc
, *expected
;
391 static const char * const testData
[][7] =
393 /* NULL canonicalize() column means "expect same as getName()" */
394 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL
},
395 {"en", "", "GB", "", "en-gb", "en_GB", NULL
},
396 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL
},
397 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL
},
398 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL
},
399 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL
},
401 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans_PINYIN", "zh_Hans@collation=pinyin"},
402 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy_AREVMDA", NULL
},
404 {"de", "", "", "1901", "de-1901", "de_1901", NULL
},
405 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
406 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
407 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
408 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
409 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
410 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
411 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
412 {"no", "", "", "NY", "no__ny", "no__NY", NULL
},
413 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
414 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL
},
415 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL
},
416 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
417 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL
},
418 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL
},
419 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL
}, /* total garbage */
421 {NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
}
424 static const char * const testTitles
[] = {
425 "uloc_getLanguage()",
431 "uloc_canonicalize()"
434 char buf
[PREFIXBUFSIZ
];
439 for(row
=0;testData
[row
][0] != NULL
;row
++) {
440 loc
= testData
[row
][NAME
];
441 log_verbose("Test #%d: %s\n", row
, loc
);
446 for(n
=0;n
<=(NAME
+2);n
++) {
447 if(n
==NAME
) continue;
449 for(len
=0;len
<PREFIXBUFSIZ
;len
++) {
450 buf
[len
] = '%'; /* Set a tripwire.. */
456 len
= uloc_getLanguage(loc
, buf
, PREFIXBUFSIZ
, &err
);
460 len
= uloc_getScript(loc
, buf
, PREFIXBUFSIZ
, &err
);
464 len
= uloc_getCountry(loc
, buf
, PREFIXBUFSIZ
, &err
);
468 len
= uloc_getVariant(loc
, buf
, PREFIXBUFSIZ
, &err
);
472 len
= uloc_getName(loc
, buf
, PREFIXBUFSIZ
, &err
);
476 len
= uloc_canonicalize(loc
, buf
, PREFIXBUFSIZ
, &err
);
485 log_err("#%d: %s on %s: err %s\n",
486 row
, testTitles
[n
], loc
, u_errorName(err
));
488 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
489 row
, testTitles
[n
], loc
, buf
, len
);
491 if(len
!= (int32_t)strlen(buf
)) {
492 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
493 row
, testTitles
[n
], loc
, buf
, len
, strlen(buf
)+1);
497 /* see if they smashed something */
498 if(buf
[len
+1] != '%') {
499 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
500 row
, testTitles
[n
], loc
, buf
, buf
[len
+1]);
503 expected
= testData
[row
][n
];
504 if (expected
== NULL
&& n
== (NAME
+2)) {
505 /* NULL expected canonicalize() means "expect same as getName()" */
506 expected
= testData
[row
][NAME
+1];
508 if(strcmp(buf
, expected
)) {
509 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
510 row
, testTitles
[n
], loc
, buf
, expected
);
519 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
520 static void TestSimpleResourceInfo() {
522 char* testLocale
= 0;
527 testLocale
=(char*)malloc(sizeof(char) * 1);
528 expected
=(UChar
*)malloc(sizeof(UChar
) * 1);
531 log_verbose("Testing getISO3Language and getISO3Country\n");
532 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
534 testLocale
=(char*)realloc(testLocale
, sizeof(char) * (u_strlen(dataTable
[NAME
][i
])+1));
535 u_austrcpy(testLocale
, dataTable
[NAME
][i
]);
537 log_verbose("Testing %s ......\n", testLocale
);
539 temp
=uloc_getISO3Language(testLocale
);
540 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
541 u_uastrcpy(expected
,temp
);
542 if (0 != u_strcmp(expected
, dataTable
[LANG3
][i
])) {
543 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected
),
544 austrdup(dataTable
[LANG3
][i
]));
547 temp
=uloc_getISO3Country(testLocale
);
548 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
549 u_uastrcpy(expected
,temp
);
550 if (0 != u_strcmp(expected
, dataTable
[CTRY3
][i
])) {
551 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected
),
552 austrdup(dataTable
[CTRY3
][i
]));
554 sprintf(temp2
, "%x", (int)uloc_getLCID(testLocale
));
555 if (strcmp(temp2
, rawData2
[LCID
][i
]) != 0) {
556 log_err("LCID mismatch: %s versus %s\n", temp2
, rawData2
[LCID
][i
]);
565 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
566 * if there's room but won't be included in result. result < 0 indicates an error.
567 * Returns the number of chars written (not those that would be written if there's enough room.*/
568 static int32_t UCharsToEscapedAscii(const UChar
* utext
, int32_t len
, char* resultChars
, int32_t buflen
) {
569 static const struct {
582 static const int32_t ESCAPE_MAP_LENGTH
= sizeof(ESCAPE_MAP
)/sizeof(ESCAPE_MAP
[0]);
583 static const char HEX_DIGITS
[] = {
584 '0', '1', '2', '3', '4', '5', '6', '7',
585 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
588 int32_t resultLen
= 0;
589 const int32_t limit
= len
<0 ? buflen
: len
; /* buflen is long enough to hit the buffer limit */
590 const int32_t escapeLimit1
= buflen
-2;
591 const int32_t escapeLimit2
= buflen
-6;
594 if(utext
==NULL
|| resultChars
==NULL
|| buflen
<0) {
598 for(i
=0;i
<limit
&& resultLen
<buflen
;++i
) {
604 for(j
=0;j
<ESCAPE_MAP_LENGTH
&& uc
!=ESCAPE_MAP
[j
].sourceVal
;j
++) {
606 if(j
<ESCAPE_MAP_LENGTH
) {
607 if(resultLen
>escapeLimit1
) {
610 resultChars
[resultLen
++]='\\';
611 resultChars
[resultLen
++]=ESCAPE_MAP
[j
].escapedChar
;
615 u_austrncpy(resultChars
+ resultLen
, &uc
, 1);
620 if(resultLen
>escapeLimit2
) {
624 /* have to escape the uchar */
625 resultChars
[resultLen
++]='\\';
626 resultChars
[resultLen
++]='u';
627 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>12)&0xff];
628 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>8)&0xff];
629 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>4)&0xff];
630 resultChars
[resultLen
++]=HEX_DIGITS
[uc
&0xff];
633 if(resultLen
<buflen
) {
634 resultChars
[resultLen
] = 0;
641 * Jitterbug 2439 -- markus 20030425
643 * The lookup of display names must not fall back through the default
644 * locale because that yields useless results.
646 static void TestDisplayNames()
649 UErrorCode errorCode
=U_ZERO_ERROR
;
651 log_verbose("Testing getDisplayName for different locales\n");
653 log_verbose(" In locale = en_US...\n");
654 doTestDisplayNames("en_US", DLANG_EN
);
655 log_verbose(" In locale = fr_FR....\n");
656 doTestDisplayNames("fr_FR", DLANG_FR
);
657 log_verbose(" In locale = ca_ES...\n");
658 doTestDisplayNames("ca_ES", DLANG_CA
);
659 log_verbose(" In locale = gr_EL..\n");
660 doTestDisplayNames("el_GR", DLANG_EL
);
662 /* test that the default locale has a display name for its own language */
663 errorCode
=U_ZERO_ERROR
;
664 length
=uloc_getDisplayLanguage(NULL
, NULL
, buffer
, LENGTHOF(buffer
), &errorCode
);
665 if(U_FAILURE(errorCode
) || (length
<=3 && buffer
[0]<=0x7f)) {
666 /* check <=3 to reject getting the language code as a display name */
667 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
));
670 /* test that we get the language code itself for an unknown language, and a default warning */
671 errorCode
=U_ZERO_ERROR
;
672 length
=uloc_getDisplayLanguage("qq", "rr", buffer
, LENGTHOF(buffer
), &errorCode
);
673 if(errorCode
!=U_USING_DEFAULT_WARNING
|| length
!=2 || buffer
[0]!=0x71 || buffer
[1]!=0x71) {
674 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode
));
677 /* test that we get a default warning for a display name where one component is unknown (4255) */
678 errorCode
=U_ZERO_ERROR
;
679 length
=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer
, LENGTHOF(buffer
), &errorCode
);
680 if(errorCode
!=U_USING_DEFAULT_WARNING
) {
681 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode
));
686 static const char *aLocale
= "es@collation=traditional;calendar=japanese";
687 static const char *testL
[] = { "en_US",
691 static const char *expect
[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
692 "espagnol (Calendrier=Calendrier japonais, Ordonnancement=Ordre traditionnel)",
693 "espanyol (calendari=calendari japon\\u00e8s, ordre alfab\\u00e8tic=ordre tradicional)",
694 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03B7\\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, \\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\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)" };
697 for(i
=0;i
<LENGTHOF(testL
);i
++) {
698 errorCode
= U_ZERO_ERROR
;
699 uloc_getDisplayName(aLocale
, testL
[i
], buffer
, LENGTHOF(buffer
), &errorCode
);
700 if(U_FAILURE(errorCode
)) {
701 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale
, testL
[i
], u_errorName(errorCode
));
703 expectBuffer
= CharsToUChars(expect
[i
]);
704 if(u_strcmp(buffer
,expectBuffer
)) {
705 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
));
707 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale
, testL
[i
], expect
[i
]);
714 /* test that we properly preflight and return data when there's a non-default pattern,
718 static const char *locale
="az_Cyrl";
719 static const char *displayLocale
="ja";
720 static const char *expectedChars
=
721 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e"
722 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
723 UErrorCode ec
=U_ZERO_ERROR
;
726 int32_t preflightLen
=uloc_getDisplayName(locale
, displayLocale
, NULL
, 0, &ec
);
727 /* inconvenient semantics when preflighting, this condition is expected... */
728 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
731 len
=uloc_getDisplayName(locale
, displayLocale
, result
, LENGTHOF(result
), &ec
);
733 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
734 locale
, displayLocale
, u_errorName(ec
));
736 UChar
*expected
=CharsToUChars(expectedChars
);
737 int32_t expectedLen
=u_strlen(expected
);
739 if(len
!=expectedLen
) {
740 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
741 locale
, displayLocale
, len
, expectedLen
);
742 } else if(preflightLen
!=expectedLen
) {
743 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
744 locale
, displayLocale
, preflightLen
, expectedLen
);
745 } else if(u_strncmp(result
, expected
, len
)) {
746 int32_t cap
=len
*6+1; /* worst case + space for trailing null */
747 char* resultChars
=(char*)malloc(cap
);
748 int32_t resultCharsLen
=UCharsToEscapedAscii(result
, len
, resultChars
, cap
);
749 if(resultCharsLen
<0 || resultCharsLen
<cap
-1) {
750 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale
, displayLocale
);
752 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
753 locale
, displayLocale
, resultChars
, expectedChars
);
758 /* test all buffer sizes */
759 for(i
=len
+1;i
>=0;--i
) {
760 len
=uloc_getDisplayName(locale
, displayLocale
, result
, i
, &ec
);
761 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
765 log_err("using buffer of length %d returned error %s", i
, u_errorName(ec
));
768 if(len
!=expectedLen
) {
769 log_err("with buffer of length %d, expected length %d but got %d", i
, expectedLen
, len
);
772 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
773 * we don't know that it's been filled, so no point in checking. */
783 /* test for uloc_getAvialable() and uloc_countAvilable()*/
784 static void TestGetAvailableLocales()
790 log_verbose("Testing the no of avialable locales\n");
791 locCount
=uloc_countAvailable();
793 log_data_err("countAvailable() returned an empty list!\n");
795 /* use something sensible w/o hardcoding the count */
796 else if(locCount
< 0){
797 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount
);
800 log_info("Number of locales returned = %d\n", locCount
);
802 for(i
=0;i
<locCount
;i
++){
803 locList
=uloc_getAvailable(i
);
805 log_verbose(" %s\n", locList
);
809 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
810 static void TestDataDirectory()
813 char oldDirectory
[512];
814 const char *temp
,*testValue1
,*testValue2
,*testValue3
;
815 const char path
[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING
; /*give the required path */
817 log_verbose("Testing getDataDirectory()\n");
818 temp
= u_getDataDirectory();
819 strcpy(oldDirectory
, temp
);
821 testValue1
=uloc_getISO3Language("en_US");
822 log_verbose("first fetch of language retrieved %s\n", testValue1
);
824 if (0 != strcmp(testValue1
,"eng")){
825 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1
);
828 /*defining the path for DataDirectory */
829 log_verbose("Testing setDataDirectory\n");
830 u_setDataDirectory( path
);
831 if(strcmp(path
, u_getDataDirectory())==0)
832 log_verbose("setDataDirectory working fine\n");
834 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path
);
836 testValue2
=uloc_getISO3Language("en_US");
837 log_verbose("second fetch of language retrieved %s \n", testValue2
);
839 u_setDataDirectory(oldDirectory
);
840 testValue3
=uloc_getISO3Language("en_US");
841 log_verbose("third fetch of language retrieved %s \n", testValue3
);
843 if (0 != strcmp(testValue3
,"eng")) {
844 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3
);
850 /*=========================================================== */
854 static void doTestDisplayNames(const char* displayLocale
, int32_t compareIndex
)
856 UErrorCode status
= U_ZERO_ERROR
;
858 int32_t maxresultsize
;
860 const char *testLocale
;
864 UChar
*testScript
= 0;
870 UChar
* expectedLang
= 0;
871 UChar
* expectedScript
= 0;
872 UChar
* expectedCtry
= 0;
873 UChar
* expectedVar
= 0;
874 UChar
* expectedName
= 0;
878 for(i
=0;i
<LOCALE_SIZE
; ++i
)
880 testLocale
=rawData2
[NAME
][i
];
882 log_verbose("Testing..... %s\n", testLocale
);
885 maxresultsize
=uloc_getDisplayLanguage(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
886 if(status
==U_BUFFER_OVERFLOW_ERROR
)
889 testLang
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
890 uloc_getDisplayLanguage(testLocale
, displayLocale
, testLang
, maxresultsize
+ 1, &status
);
896 if(U_FAILURE(status
)){
897 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status
));
901 maxresultsize
=uloc_getDisplayScript(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
902 if(status
==U_BUFFER_OVERFLOW_ERROR
)
905 testScript
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
906 uloc_getDisplayScript(testLocale
, displayLocale
, testScript
, maxresultsize
+ 1, &status
);
912 if(U_FAILURE(status
)){
913 log_err("Error in getDisplayScript() %s\n", myErrorName(status
));
917 maxresultsize
=uloc_getDisplayCountry(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
918 if(status
==U_BUFFER_OVERFLOW_ERROR
)
921 testCtry
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
922 uloc_getDisplayCountry(testLocale
, displayLocale
, testCtry
, maxresultsize
+ 1, &status
);
928 if(U_FAILURE(status
)){
929 log_err("Error in getDisplayCountry() %s\n", myErrorName(status
));
933 maxresultsize
=uloc_getDisplayVariant(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
934 if(status
==U_BUFFER_OVERFLOW_ERROR
)
937 testVar
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
938 uloc_getDisplayVariant(testLocale
, displayLocale
, testVar
, maxresultsize
+ 1, &status
);
944 if(U_FAILURE(status
)){
945 log_err("Error in getDisplayVariant() %s\n", myErrorName(status
));
949 maxresultsize
=uloc_getDisplayName(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
950 if(status
==U_BUFFER_OVERFLOW_ERROR
)
953 testName
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
954 uloc_getDisplayName(testLocale
, displayLocale
, testName
, maxresultsize
+ 1, &status
);
960 if(U_FAILURE(status
)){
961 log_err("Error in getDisplayName() %s\n", myErrorName(status
));
964 expectedLang
=dataTable
[compareIndex
][i
];
965 if(u_strlen(expectedLang
)== 0)
966 expectedLang
=dataTable
[DLANG_EN
][i
];
968 expectedScript
=dataTable
[compareIndex
+ 1][i
];
969 if(u_strlen(expectedScript
)== 0)
970 expectedScript
=dataTable
[DSCRIPT_EN
][i
];
972 expectedCtry
=dataTable
[compareIndex
+ 2][i
];
973 if(u_strlen(expectedCtry
)== 0)
974 expectedCtry
=dataTable
[DCTRY_EN
][i
];
976 expectedVar
=dataTable
[compareIndex
+ 3][i
];
977 if(u_strlen(expectedVar
)== 0)
978 expectedVar
=dataTable
[DVAR_EN
][i
];
980 expectedName
=dataTable
[compareIndex
+ 4][i
];
981 if(u_strlen(expectedName
) == 0)
982 expectedName
=dataTable
[DNAME_EN
][i
];
984 if (0 !=u_strcmp(testLang
,expectedLang
)) {
985 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang
), austrdup(expectedLang
), displayLocale
);
988 if (0 != u_strcmp(testScript
,expectedScript
)) {
989 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript
), austrdup(expectedScript
), displayLocale
);
992 if (0 != u_strcmp(testCtry
,expectedCtry
)) {
993 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry
), austrdup(expectedCtry
), displayLocale
);
996 if (0 != u_strcmp(testVar
,expectedVar
)) {
997 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar
), austrdup(expectedVar
), displayLocale
);
1000 if(0 != u_strcmp(testName
, expectedName
)) {
1001 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName
), austrdup(expectedName
), displayLocale
);
1004 if(testName
!=&_NUL
) {
1007 if(testLang
!=&_NUL
) {
1010 if(testScript
!=&_NUL
) {
1013 if(testCtry
!=&_NUL
) {
1016 if(testVar
!=&_NUL
) {
1023 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1024 static void TestISOFunctions()
1026 const char* const* str
=uloc_getISOLanguages();
1027 const char* const* str1
=uloc_getISOCountries();
1029 const char *key
= NULL
;
1030 int32_t count
= 0, skipped
= 0;
1032 UResourceBundle
*res
;
1033 UResourceBundle
*subRes
;
1034 UErrorCode status
= U_ZERO_ERROR
;
1036 /* test getISOLanguages*/
1037 /*str=uloc_getISOLanguages(); */
1038 log_verbose("Testing ISO Languages: \n");
1040 /* use structLocale - this data is no longer in root */
1041 res
= ures_openDirect(loadTestData(&status
), "structLocale", &status
);
1042 subRes
= ures_getByKey(res
, "Languages", NULL
, &status
);
1043 if (U_FAILURE(status
)) {
1044 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status
));
1048 expect
= ures_getSize(subRes
);
1049 for(count
= 0; *(str
+count
) != 0; count
++)
1052 test
= *(str
+count
);
1053 status
= U_ZERO_ERROR
;
1056 /* Skip over language tags. This API only returns language codes. */
1057 skipped
+= (key
!= NULL
);
1058 ures_getNextString(subRes
, NULL
, &key
, &status
);
1060 while (key
!= NULL
&& strchr(key
, '_'));
1064 /* TODO: Consider removing sh, which is deprecated */
1065 if(strcmp(key
,"root") == 0 || strcmp(key
,"Fallback") == 0 || strcmp(key
,"sh") == 0) {
1066 ures_getNextString(subRes
, NULL
, &key
, &status
);
1069 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1070 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1071 if(strcmp(test
,key
)) {
1072 /* The first difference usually implies the place where things get out of sync */
1073 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1077 if(!strcmp(test
,"in"))
1078 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1079 if(!strcmp(test
,"iw"))
1080 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1081 if(!strcmp(test
,"ji"))
1082 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1083 if(!strcmp(test
,"jw"))
1084 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1085 if(!strcmp(test
,"sh"))
1086 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1089 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1092 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count
, expect
);
1095 subRes
= ures_getByKey(res
, "Countries", subRes
, &status
);
1096 log_verbose("Testing ISO Countries");
1098 expect
= ures_getSize(subRes
) - 1; /* Skip ZZ */
1099 for(count
= 0; *(str1
+count
) != 0; count
++)
1102 test
= *(str1
+count
);
1104 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1105 skipped
+= (key
!= NULL
);
1106 ures_getNextString(subRes
, NULL
, &key
, &status
);
1108 while (key
!= NULL
&& strlen(key
) != 2);
1112 /* TODO: Consider removing CS, which is deprecated */
1113 while(strcmp(key
,"QO") == 0 || strcmp(key
,"QU") == 0 || strcmp(key
,"CS") == 0) {
1114 ures_getNextString(subRes
, NULL
, &key
, &status
);
1117 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1118 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1119 if(strcmp(test
,key
)) {
1120 /* The first difference usually implies the place where things get out of sync */
1121 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1124 if(!strcmp(test
,"FX"))
1125 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1126 if(!strcmp(test
,"YU"))
1127 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1128 if(!strcmp(test
,"ZR"))
1129 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1132 ures_getNextString(subRes
, NULL
, &key
, &status
);
1133 if (strcmp(key
, "ZZ") != 0) {
1134 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key
);
1136 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1137 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1140 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1141 skipped
+= (key
!= NULL
);
1142 ures_getNextString(subRes
, NULL
, &key
, &status
);
1144 while (U_SUCCESS(status
) && key
!= NULL
&& strlen(key
) != 2);
1146 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1149 log_err("There is an error in getISOCountries, got %d, expected %d \n", count
, expect
);
1155 static void setUpDataTable()
1158 dataTable
= (UChar
***)(calloc(sizeof(UChar
**),LOCALE_INFO_SIZE
));
1160 for (i
= 0; i
< LOCALE_INFO_SIZE
; i
++) {
1161 dataTable
[i
] = (UChar
**)(calloc(sizeof(UChar
*),LOCALE_SIZE
));
1162 for (j
= 0; j
< LOCALE_SIZE
; j
++){
1163 dataTable
[i
][j
] = CharsToUChars(rawData2
[i
][j
]);
1168 static void cleanUpDataTable()
1171 if(dataTable
!= NULL
) {
1172 for (i
=0; i
<LOCALE_INFO_SIZE
; i
++) {
1173 for(j
= 0; j
< LOCALE_SIZE
; j
++) {
1174 free(dataTable
[i
][j
]);
1184 * @bug 4011756 4011380
1186 static void TestISO3Fallback()
1188 const char* test
="xx_YY";
1190 const char * result
;
1192 result
= uloc_getISO3Language(test
);
1194 /* Conform to C API usage */
1196 if (!result
|| (result
[0] != 0))
1197 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1199 result
= uloc_getISO3Country(test
);
1201 if (!result
|| (result
[0] != 0))
1202 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1208 static void TestSimpleDisplayNames()
1211 This test is different from TestDisplayNames because TestDisplayNames checks
1212 fallback behavior, combination of language and country names to form locale
1213 names, and other stuff like that. This test just checks specific language
1214 and country codes to make sure we have the correct names for them.
1216 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1217 const char* languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish",
1219 const char* inLocale
[] = { "en_US", "zh_Hant"};
1220 UErrorCode status
=U_ZERO_ERROR
;
1223 int32_t localeIndex
= 0;
1224 for (i
= 0; i
< 7; i
++) {
1226 UChar
*expectedLang
=0;
1230 localeIndex
= 1; /* Use the second locale for the rest of the test. */
1233 size
=uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], NULL
, size
, &status
);
1234 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1235 status
=U_ZERO_ERROR
;
1236 testLang
=(UChar
*)malloc(sizeof(UChar
) * (size
+ 1));
1237 uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], testLang
, size
+ 1, &status
);
1239 expectedLang
=(UChar
*)malloc(sizeof(UChar
) * (strlen(languageNames
[i
])+1));
1240 u_uastrcpy(expectedLang
, languageNames
[i
]);
1241 if (u_strcmp(testLang
, expectedLang
) != 0)
1242 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1243 languageCodes
[i
], languageNames
[i
], austrdup(testLang
));
1253 static void TestUninstalledISO3Names()
1255 /* This test checks to make sure getISO3Language and getISO3Country work right
1256 even for locales that are not installed. */
1257 static const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
1259 static const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
1260 "ssw", "twi", "zul" };
1261 static const char iso2Countries
[][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1262 "ss_SB", "tw_TC", "zu_ZW" };
1263 static const char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1264 "SLB", "TCA", "ZWE" };
1267 for (i
= 0; i
< 8; i
++) {
1268 UErrorCode err
= U_ZERO_ERROR
;
1270 test
= uloc_getISO3Language(iso2Languages
[i
]);
1271 if(strcmp(test
, iso3Languages
[i
]) !=0 || U_FAILURE(err
))
1272 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1273 iso2Languages
[i
], iso3Languages
[i
], test
, myErrorName(err
));
1275 for (i
= 0; i
< 8; i
++) {
1276 UErrorCode err
= U_ZERO_ERROR
;
1278 test
= uloc_getISO3Country(iso2Countries
[i
]);
1279 if(strcmp(test
, iso3Countries
[i
]) !=0 || U_FAILURE(err
))
1280 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1281 iso2Countries
[i
], iso3Countries
[i
], test
, myErrorName(err
));
1286 static void TestVariantParsing()
1288 static const char* en_US_custom
="en_US_De Anza_Cupertino_California_United States_Earth";
1289 static const char* dispName
="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1290 static const char* dispVar
="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1291 static const char* shortVariant
="fr_FR_foo";
1292 static const char* bogusVariant
="fr_FR__foo";
1293 static const char* bogusVariant2
="fr_FR_foo_";
1294 static const char* bogusVariant3
="fr_FR__foo_";
1297 UChar displayVar
[100];
1298 UChar displayName
[100];
1299 UErrorCode status
=U_ZERO_ERROR
;
1302 size
=uloc_getDisplayVariant(en_US_custom
, "en_US", NULL
, size
, &status
);
1303 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1304 status
=U_ZERO_ERROR
;
1305 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1306 uloc_getDisplayVariant(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1309 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1311 u_uastrcpy(displayVar
, dispVar
);
1312 if(u_strcmp(got
,displayVar
)!=0) {
1313 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar
, austrdup(got
));
1316 size
=uloc_getDisplayName(en_US_custom
, "en_US", NULL
, size
, &status
);
1317 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1318 status
=U_ZERO_ERROR
;
1319 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1320 uloc_getDisplayName(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1323 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1325 u_uastrcpy(displayName
, dispName
);
1326 if(u_strcmp(got
,displayName
)!=0) {
1327 if (status
== U_USING_DEFAULT_WARNING
) {
1328 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status
));
1330 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName
, austrdup(got
));
1335 status
=U_ZERO_ERROR
;
1336 size
=uloc_getDisplayVariant(shortVariant
, NULL
, NULL
, size
, &status
);
1337 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1338 status
=U_ZERO_ERROR
;
1339 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1340 uloc_getDisplayVariant(shortVariant
, NULL
, got
, size
+ 1, &status
);
1343 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1345 if(strcmp(austrdup(got
),"FOO")!=0) {
1346 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got
));
1349 status
=U_ZERO_ERROR
;
1350 size
=uloc_getDisplayVariant(bogusVariant
, NULL
, NULL
, size
, &status
);
1351 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1352 status
=U_ZERO_ERROR
;
1353 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1354 uloc_getDisplayVariant(bogusVariant
, NULL
, got
, size
+ 1, &status
);
1357 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1359 if(strcmp(austrdup(got
),"_FOO")!=0) {
1360 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got
));
1363 status
=U_ZERO_ERROR
;
1364 size
=uloc_getDisplayVariant(bogusVariant2
, NULL
, NULL
, size
, &status
);
1365 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1366 status
=U_ZERO_ERROR
;
1367 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1368 uloc_getDisplayVariant(bogusVariant2
, NULL
, got
, size
+ 1, &status
);
1371 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1373 if(strcmp(austrdup(got
),"FOO_")!=0) {
1374 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got
));
1377 status
=U_ZERO_ERROR
;
1378 size
=uloc_getDisplayVariant(bogusVariant3
, NULL
, NULL
, size
, &status
);
1379 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1380 status
=U_ZERO_ERROR
;
1381 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1382 uloc_getDisplayVariant(bogusVariant3
, NULL
, got
, size
+ 1, &status
);
1385 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1387 if(strcmp(austrdup(got
),"_FOO_")!=0) {
1388 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got
));
1394 static void TestObsoleteNames(void)
1397 UErrorCode status
= U_ZERO_ERROR
;
1409 { "eng_USA", "eng", "en", "USA", "US" },
1410 { "kok", "kok", "kok", "", "" },
1411 { "in", "ind", "in", "", "" },
1412 { "id", "ind", "id", "", "" }, /* NO aliasing */
1413 { "sh", "srp", "sh", "", "" },
1414 { "zz_CS", "", "zz", "SCG", "CS" },
1415 { "zz_FX", "", "zz", "FXX", "FX" },
1416 { "zz_RO", "", "zz", "ROU", "RO" },
1417 { "zz_TP", "", "zz", "TMP", "TP" },
1418 { "zz_TL", "", "zz", "TLS", "TL" },
1419 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1420 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1421 { "zz_ROM", "", "zz", "ROU", "RO" },
1422 { "zz_ROU", "", "zz", "ROU", "RO" },
1423 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1424 { "zz_TMP", "", "zz", "TMP", "TP" },
1425 { "zz_TLS", "", "zz", "TLS", "TL" },
1426 { "zz_YUG", "", "zz", "YUG", "YU" },
1427 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1428 { "iw", "heb", "iw", "", "" },
1429 { "ji", "yid", "ji", "", "" },
1430 { "jw", "jaw", "jw", "", "" },
1431 { "sh", "srp", "sh", "", "" },
1432 { "", "", "", "", "" }
1435 for(i
=0;tests
[i
].locale
[0];i
++)
1439 locale
= tests
[i
].locale
;
1440 log_verbose("** %s:\n", locale
);
1442 status
= U_ZERO_ERROR
;
1443 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1445 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1446 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1450 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1451 uloc_getISO3Language(locale
) );
1454 status
= U_ZERO_ERROR
;
1455 uloc_getLanguage(locale
, buff
, 256, &status
);
1456 if(U_FAILURE(status
))
1458 log_err("FAIL: error getting language from %s\n", locale
);
1462 if(strcmp(buff
,tests
[i
].lang
))
1464 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1465 locale
, buff
, tests
[i
].lang
);
1469 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale
, buff
);
1472 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1474 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1475 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1479 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1480 uloc_getISO3Language(locale
) );
1483 if(strcmp(tests
[i
].ctry3
,uloc_getISO3Country(locale
)))
1485 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1486 locale
, uloc_getISO3Country(locale
), tests
[i
].ctry3
);
1490 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1491 uloc_getISO3Country(locale
) );
1494 status
= U_ZERO_ERROR
;
1495 uloc_getCountry(locale
, buff
, 256, &status
);
1496 if(U_FAILURE(status
))
1498 log_err("FAIL: error getting country from %s\n", locale
);
1502 if(strcmp(buff
,tests
[i
].ctry
))
1504 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1505 locale
, buff
, tests
[i
].ctry
);
1509 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale
, buff
);
1514 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1515 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1518 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1519 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1524 i
= uloc_getLanguage("kok",NULL
,0,&icu_err
);
1525 if(U_FAILURE(icu_err
))
1527 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err
));
1530 icu_err
= U_ZERO_ERROR
;
1531 uloc_getLanguage("kok",r1_buff
,12,&icu_err
);
1532 if(U_FAILURE(icu_err
))
1534 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err
));
1537 r1_addr
= (char *)uloc_getISO3Language("kok");
1539 icu_err
= U_ZERO_ERROR
;
1540 if (strcmp(r1_buff
,"kok") != 0)
1542 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff
);
1545 r1_addr
= (char *)uloc_getISO3Language("in");
1546 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1547 if (strcmp(r1_buff
,"id") != 0)
1549 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1552 r1_addr
= (char *)uloc_getISO3Language("sh");
1553 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1554 if (strcmp(r1_buff
,"sr") != 0)
1556 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1560 r1_addr
= (char *)uloc_getISO3Country("zz_ZR");
1561 strcpy(p1_buff
,"zz_");
1562 strcat(p1_buff
,r1_addr
);
1563 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1564 if (strcmp(r1_buff
,"ZR") != 0)
1566 printf("uloc_getCountry error (%s)\n",r1_buff
);
1569 r1_addr
= (char *)uloc_getISO3Country("zz_FX");
1570 strcpy(p1_buff
,"zz_");
1571 strcat(p1_buff
,r1_addr
);
1572 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1573 if (strcmp(r1_buff
,"FX") != 0)
1575 printf("uloc_getCountry error (%s)\n",r1_buff
);
1583 static void TestKeywordVariants(void)
1585 static const struct {
1586 const char *localeID
;
1587 const char *expectedLocaleID
;
1588 const char *expectedLocaleIDNoKeywords
;
1589 const char *expectedCanonicalID
;
1590 const char *expectedKeywords
[10];
1591 int32_t numKeywords
;
1592 UErrorCode expectedStatus
; /* from uloc_openKeywords */
1595 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1596 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1598 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1599 {"calendar", "collation", "currency"},
1607 "de_DE@currency=EUR",
1608 {"","","","","","",""},
1610 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1613 "de_DE@euro;collation=phonebook",
1614 "de_DE", /* error result; bad format */
1615 "de_DE", /* error result; bad format */
1616 "de_DE", /* error result; bad format */
1617 {"","","","","","",""},
1619 U_INVALID_FORMAT_ERROR
1622 UErrorCode status
= U_ZERO_ERROR
;
1624 int32_t i
= 0, j
= 0;
1625 int32_t resultLen
= 0;
1627 UEnumeration
*keywords
;
1628 int32_t keyCount
= 0;
1629 const char *keyword
= NULL
;
1630 int32_t keywordLen
= 0;
1632 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
1633 status
= U_ZERO_ERROR
;
1635 keywords
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
1637 if(status
!= testCases
[i
].expectedStatus
) {
1638 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1639 testCases
[i
].localeID
,
1640 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1642 status
= U_ZERO_ERROR
;
1644 if((keyCount
= uenum_count(keywords
, &status
)) != testCases
[i
].numKeywords
) {
1645 log_err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1649 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1650 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1651 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1656 uenum_reset(keywords
, &status
);
1657 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1658 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1659 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1664 uenum_close(keywords
);
1666 resultLen
= uloc_getName(testCases
[i
].localeID
, buffer
, 256, &status
);
1667 if (uprv_strcmp(testCases
[i
].expectedLocaleID
, buffer
) != 0) {
1668 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1669 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
);
1671 resultLen
= uloc_canonicalize(testCases
[i
].localeID
, buffer
, 256, &status
);
1672 if (uprv_strcmp(testCases
[i
].expectedCanonicalID
, buffer
) != 0) {
1673 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1674 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
);
1680 static void TestKeywordVariantParsing(void)
1682 static const struct {
1683 const char *localeID
;
1684 const char *keyword
;
1685 const char *expectedValue
;
1687 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
1688 { "de_DE", "collation", ""},
1689 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1690 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1693 UErrorCode status
= U_ZERO_ERROR
;
1696 int32_t resultLen
= 0;
1699 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
1701 resultLen
= uloc_getKeywordValue(testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
, 256, &status
);
1702 if(uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1703 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1704 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1709 static const struct {
1710 const char *l
; /* locale */
1711 const char *k
; /* kw */
1712 const char *v
; /* value */
1713 const char *x
; /* expected */
1714 } kwSetTestCases
[] = {
1716 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1717 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1718 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1719 { "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 */
1720 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1721 { "de", "Currency", "CHF", "de@currency=CHF" },
1722 { "de", "Currency", "CHF", "de@currency=CHF" },
1724 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1725 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1726 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1727 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1728 { "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 */
1729 { "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 */
1730 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1731 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1734 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1735 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1736 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1737 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1738 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1739 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1740 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1741 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1742 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1746 /* 1. removal of item at end */
1747 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1748 { "de@collation=phonebook;currency=CHF", "currency", NULL
, "de@collation=phonebook" },
1749 /* 2. removal of item at beginning */
1750 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1751 { "de@collation=phonebook;currency=CHF", "collation", NULL
, "de@currency=CHF" },
1752 /* 3. removal of an item not there */
1753 { "de@collation=phonebook;currency=CHF", "calendar", NULL
, "de@collation=phonebook;currency=CHF" },
1754 /* 4. removal of only item */
1755 { "de@collation=phonebook", "collation", NULL
, "de" },
1757 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1761 static void TestKeywordSet(void)
1764 int32_t resultLen
= 0;
1769 for(i
= 0; i
< sizeof(kwSetTestCases
)/sizeof(kwSetTestCases
[0]); i
++) {
1770 UErrorCode status
= U_ZERO_ERROR
;
1771 memset(buffer
,'%',1023);
1772 strcpy(buffer
, kwSetTestCases
[i
].l
);
1774 uloc_canonicalize(kwSetTestCases
[i
].l
, cbuffer
, 1023, &status
);
1775 if(strcmp(buffer
,cbuffer
)) {
1776 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i
, cbuffer
, buffer
);
1778 /* sanity check test case results for canonicity */
1779 uloc_canonicalize(kwSetTestCases
[i
].x
, cbuffer
, 1023, &status
);
1780 if(strcmp(kwSetTestCases
[i
].x
,cbuffer
)) {
1781 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__
, __LINE__
, i
, kwSetTestCases
[i
].x
, cbuffer
);
1784 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
1785 if(U_FAILURE(status
)) {
1786 log_err("Err on test case %d: got error %s\n", i
, u_errorName(status
));
1789 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=resultLen
)) {
1790 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
1791 kwSetTestCases
[i
].v
, buffer
, resultLen
, kwSetTestCases
[i
].x
, strlen(buffer
));
1793 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,buffer
);
1798 static void TestKeywordSetError(void)
1806 /* 0-test whether an error condition modifies the buffer at all */
1809 memset(buffer
,'%',1023);
1810 status
= U_ZERO_ERROR
;
1811 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1812 if(status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1813 log_err("expected illegal err got %s\n", u_errorName(status
));
1816 /* if(res!=strlen(kwSetTestCases[i].x)) {
1817 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1820 if(buffer
[blen
]!='%') {
1821 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
1824 log_verbose("0-buffer modify OK\n");
1827 /* 1- test a short buffer with growing text */
1828 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
1829 memset(buffer
,'%',1023);
1830 strcpy(buffer
,kwSetTestCases
[i
].l
);
1831 status
= U_ZERO_ERROR
;
1832 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1833 if(status
!= U_BUFFER_OVERFLOW_ERROR
) {
1834 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
);
1837 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
1838 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
1841 if(buffer
[blen
]!='%') {
1842 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
1845 log_verbose("1/%d-buffer modify OK\n",i
);
1849 /* 2- test a short buffer - text the same size or shrinking */
1850 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
1851 memset(buffer
,'%',1023);
1852 strcpy(buffer
,kwSetTestCases
[i
].l
);
1853 status
= U_ZERO_ERROR
;
1854 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1855 if(status
!= U_ZERO_ERROR
) {
1856 log_err("expected zero error got %s\n", u_errorName(status
));
1859 if(buffer
[blen
+1]!='%') {
1860 log_err("Buffer byte %d was modified: now %c\n", blen
+1, buffer
[blen
+1]);
1863 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
1864 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
1867 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=res
)) {
1868 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
1869 kwSetTestCases
[i
].v
, buffer
, res
, kwSetTestCases
[i
].x
, strlen(buffer
));
1871 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,
1874 log_verbose("2/%d-buffer modify OK\n",i
);
1878 static int32_t _canonicalize(int32_t selector
, /* 0==getName, 1==canonicalize */
1879 const char* localeID
,
1881 int32_t resultCapacity
,
1883 /* YOU can change this to use function pointers if you like */
1886 return uloc_getName(localeID
, result
, resultCapacity
, ec
);
1888 return uloc_canonicalize(localeID
, result
, resultCapacity
, ec
);
1894 static void TestCanonicalization(void)
1896 static const struct {
1897 const char *localeID
; /* input */
1898 const char *getNameID
; /* expected getName() result */
1899 const char *canonicalID
; /* expected canonicalize() result */
1901 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
1902 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
1903 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
1904 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
1905 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
1906 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
1907 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
1908 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
1909 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
1910 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
1911 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
1912 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
1913 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
1914 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
1915 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
1916 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
1917 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
1918 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
1919 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
1920 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
1921 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
1922 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
1923 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
1924 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
1925 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
1926 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
1927 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
1928 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
1929 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
1930 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
1931 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
1932 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
1933 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
1934 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
1935 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
1936 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
1937 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
1938 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
1939 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
1940 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
1941 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
1942 { "en-BOONT", "en_BOONT", "en_BOONT" }, /* registered name */
1943 { "de-1901", "de_1901", "de_1901" }, /* registered name */
1944 { "de-1906", "de_1906", "de_1906" }, /* registered name */
1945 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
1946 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
1947 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
1948 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
1949 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
1950 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
1951 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
1953 /* posix behavior that used to be performed by getName */
1954 { "mr.utf8", "mr.utf8", "mr" },
1955 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
1956 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
1957 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
1958 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
1959 { "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 */
1961 /* fleshing out canonicalization */
1962 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
1963 { "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" },
1964 /* already-canonical ids are not changed */
1965 { "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" },
1966 /* PRE_EURO and EURO conversions don't affect other keywords */
1967 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
1968 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
1969 /* currency keyword overrides PRE_EURO and EURO currency */
1970 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
1971 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
1972 /* norwegian is just too weird, if we handle things in their full generality */
1973 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
1975 /* test cases reflecting internal resource bundle usage */
1976 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
1977 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
1978 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
1979 { "ja_JP", "ja_JP", "ja_JP" },
1981 /* test case for "i-default" */
1982 { "i-default", "en@x=i-default", "en@x=i-default" }
1985 static const char* label
[] = { "getName", "canonicalize" };
1987 UErrorCode status
= U_ZERO_ERROR
;
1988 int32_t i
, j
, resultLen
= 0, origResultLen
;
1991 for (i
=0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
1992 for (j
=0; j
<2; ++j
) {
1993 const char* expected
= (j
==0) ? testCases
[i
].getNameID
: testCases
[i
].canonicalID
;
1995 status
= U_ZERO_ERROR
;
1997 if (expected
== NULL
) {
1998 expected
= uloc_getDefault();
2001 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2002 origResultLen
= _canonicalize(j
, testCases
[i
].localeID
, NULL
, 0, &status
);
2003 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
2004 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2005 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2008 status
= U_ZERO_ERROR
;
2009 resultLen
= _canonicalize(j
, testCases
[i
].localeID
, buffer
, sizeof(buffer
), &status
);
2010 if (U_FAILURE(status
)) {
2011 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2012 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2015 if(uprv_strcmp(expected
, buffer
) != 0) {
2016 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2017 label
[j
], testCases
[i
].localeID
, buffer
, expected
);
2019 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2020 label
[j
], testCases
[i
].localeID
, buffer
);
2022 if (resultLen
!= (int32_t)strlen(buffer
)) {
2023 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2024 label
[j
], testCases
[i
].localeID
, resultLen
, strlen(buffer
));
2026 if (origResultLen
!= resultLen
) {
2027 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2028 label
[j
], testCases
[i
].localeID
, origResultLen
, resultLen
);
2034 static void TestDisplayKeywords(void)
2038 static const struct {
2039 const char *localeID
;
2040 const char *displayLocale
;
2041 UChar displayKeyword
[200];
2043 { "ca_ES@currency=ESP", "de_AT",
2044 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2046 { "ja_JP@calendar=japanese", "de",
2047 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2049 { "de_DE@collation=traditional", "de_DE",
2050 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2053 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2054 UErrorCode status
= U_ZERO_ERROR
;
2055 const char* keyword
=NULL
;
2056 int32_t keywordLen
= 0;
2057 int32_t keywordCount
= 0;
2058 UChar
*displayKeyword
=NULL
;
2059 int32_t displayKeywordLen
= 0;
2060 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2061 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2062 if(U_FAILURE(status
)){
2063 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases
[i
].localeID
, u_errorName(status
));
2066 /* the uenum_next returns NUL terminated string */
2067 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2068 /* fetch the displayKeyword */
2069 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2070 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2071 status
= U_ZERO_ERROR
;
2072 displayKeywordLen
++; /* for null termination */
2073 displayKeyword
= (UChar
*) malloc(displayKeywordLen
* U_SIZEOF_UCHAR
);
2074 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2075 if(U_FAILURE(status
)){
2076 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
));
2079 if(u_strncmp(displayKeyword
, testCases
[i
].displayKeyword
, displayKeywordLen
)!=0){
2080 if (status
== U_USING_DEFAULT_WARNING
) {
2081 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
));
2083 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
);
2088 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status
));
2091 free(displayKeyword
);
2094 uenum_close(keywordEnum
);
2098 static void TestDisplayKeywordValues(void){
2101 static const struct {
2102 const char *localeID
;
2103 const char *displayLocale
;
2104 UChar displayKeywordValue
[500];
2106 { "ca_ES@currency=ESP", "de_AT",
2107 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2109 { "de_AT@currency=ATS", "fr_FR",
2110 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2112 { "de_DE@currency=DEM", "it",
2113 {0x004d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0054, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2115 { "el_GR@currency=GRD", "en",
2116 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2118 { "eu_ES@currency=ESP", "it_IT",
2119 {0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0053, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2121 { "de@collation=phonebook", "es",
2122 {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}
2125 { "de_DE@collation=phonebook", "es",
2126 {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}
2128 { "es_ES@collation=traditional","de",
2129 {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}
2131 { "ja_JP@calendar=japanese", "de",
2132 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2135 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2136 UErrorCode status
= U_ZERO_ERROR
;
2137 const char* keyword
=NULL
;
2138 int32_t keywordLen
= 0;
2139 int32_t keywordCount
= 0;
2140 UChar
*displayKeywordValue
= NULL
;
2141 int32_t displayKeywordValueLen
= 0;
2142 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2143 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2144 if(U_FAILURE(status
)){
2145 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
));
2148 /* the uenum_next returns NUL terminated string */
2149 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2151 /* fetch the displayKeywordValue */
2152 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2153 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2154 status
= U_ZERO_ERROR
;
2155 displayKeywordValueLen
++; /* for null termination */
2156 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2157 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2158 if(U_FAILURE(status
)){
2159 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
));
2162 if(u_strncmp(displayKeywordValue
, testCases
[i
].displayKeywordValue
, displayKeywordValueLen
)!=0){
2163 if (status
== U_USING_DEFAULT_WARNING
) {
2164 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
));
2166 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
));
2171 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2173 free(displayKeywordValue
);
2175 uenum_close(keywordEnum
);
2178 /* test a multiple keywords */
2179 UErrorCode status
= U_ZERO_ERROR
;
2180 const char* keyword
=NULL
;
2181 int32_t keywordLen
= 0;
2182 int32_t keywordCount
= 0;
2183 const char* localeID
= "es@collation=phonebook;calendar=buddhist;currency=DEM";
2184 const char* displayLocale
= "de";
2185 static const UChar expected
[][50] = {
2186 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2188 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000},
2189 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2192 UEnumeration
* keywordEnum
= uloc_openKeywords(localeID
, &status
);
2194 for(keywordCount
= 0; keywordCount
< uenum_count(keywordEnum
, &status
) ; keywordCount
++){
2195 UChar
*displayKeywordValue
= NULL
;
2196 int32_t displayKeywordValueLen
= 0;
2197 if(U_FAILURE(status
)){
2198 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID
, displayLocale
, u_errorName(status
));
2201 /* the uenum_next returns NUL terminated string */
2202 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2204 /* fetch the displayKeywordValue */
2205 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2206 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2207 status
= U_ZERO_ERROR
;
2208 displayKeywordValueLen
++; /* for null termination */
2209 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2210 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2211 if(U_FAILURE(status
)){
2212 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
));
2215 if(u_strncmp(displayKeywordValue
, expected
[keywordCount
], displayKeywordValueLen
)!=0){
2216 if (status
== U_USING_DEFAULT_WARNING
) {
2217 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
));
2219 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID
, keyword
, displayLocale
);
2224 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2226 free(displayKeywordValue
);
2228 uenum_close(keywordEnum
);
2232 /* Test non existent keywords */
2233 UErrorCode status
= U_ZERO_ERROR
;
2234 const char* localeID
= "es";
2235 const char* displayLocale
= "de";
2236 UChar
*displayKeywordValue
= NULL
;
2237 int32_t displayKeywordValueLen
= 0;
2239 /* fetch the displayKeywordValue */
2240 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, "calendar", displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2241 if(U_FAILURE(status
)) {
2242 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status
));
2243 } else if(displayKeywordValueLen
!= 0) {
2244 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen
);
2250 static void TestGetBaseName(void) {
2251 static const struct {
2252 const char *localeID
;
2253 const char *baseName
;
2255 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2256 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2257 { "ja@calendar = buddhist", "ja" }
2260 int32_t i
= 0, baseNameLen
= 0;
2262 UErrorCode status
= U_ZERO_ERROR
;
2264 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2265 baseNameLen
= uloc_getBaseName(testCases
[i
].localeID
, baseName
, 256, &status
);
2266 if(strcmp(testCases
[i
].baseName
, baseName
)) {
2267 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2268 testCases
[i
].localeID
, testCases
[i
].baseName
, baseName
);
2274 static void TestTrailingNull(void) {
2275 const char* localeId
= "zh_Hans";
2276 UChar buffer
[128]; /* sufficient for this test */
2278 UErrorCode status
= U_ZERO_ERROR
;
2281 len
= uloc_getDisplayName(localeId
, localeId
, buffer
, 128, &status
);
2283 log_err("buffer too small");
2287 for (i
= 0; i
< len
; ++i
) {
2288 if (buffer
[i
] == 0) {
2289 log_err("name contained null");
2295 /* Jitterbug 4115 */
2296 static void TestDisplayNameWarning(void) {
2299 UErrorCode status
= U_ZERO_ERROR
;
2301 size
= uloc_getDisplayLanguage("qqq", "kl", name
, sizeof(name
)/sizeof(name
[0]), &status
);
2302 if (status
!= U_USING_DEFAULT_WARNING
) {
2303 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2304 u_errorName(status
));
2310 * Compare two locale IDs. If they are equal, return 0. If `string'
2311 * starts with `prefix' plus an additional element, that is, string ==
2312 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2314 static UBool
_loccmp(const char* string
, const char* prefix
) {
2315 int32_t slen
= (int32_t)uprv_strlen(string
),
2316 plen
= (int32_t)uprv_strlen(prefix
);
2317 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
2318 /* 'root' is less than everything */
2319 if (uprv_strcmp(prefix
, "root") == 0) {
2320 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
2322 if (c
) return -1; /* mismatch */
2323 if (slen
== plen
) return 0;
2324 if (string
[plen
] == '_') return 1;
2325 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2328 static void _checklocs(const char* label
,
2331 const char* actual
) {
2332 /* We want the valid to be strictly > the bogus requested locale,
2333 and the valid to be >= the actual. */
2334 if (_loccmp(req
, valid
) > 0 &&
2335 _loccmp(valid
, actual
) >= 0) {
2336 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2337 label
, req
, valid
, actual
);
2339 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2340 label
, req
, valid
, actual
);
2344 static void TestGetLocale(void) {
2345 UErrorCode ec
= U_ZERO_ERROR
;
2347 UChar EMPTY
[1] = {0};
2350 #if !UCONFIG_NO_FORMATTING
2353 const char *req
= "en_US_REDWOODSHORES", *valid
, *actual
;
2354 obj
= udat_open(UDAT_DEFAULT
, UDAT_DEFAULT
,
2358 if (U_FAILURE(ec
)) {
2359 log_data_err("udat_open failed.Error %s\n", u_errorName(ec
));
2362 valid
= udat_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2363 actual
= udat_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2364 if (U_FAILURE(ec
)) {
2365 log_err("udat_getLocaleByType() failed\n");
2368 _checklocs("udat", req
, valid
, actual
);
2374 #if !UCONFIG_NO_FORMATTING
2377 const char *req
= "fr_FR_PROVENCAL", *valid
, *actual
;
2378 obj
= ucal_open(NULL
, 0,
2382 if (U_FAILURE(ec
)) {
2383 log_err("ucal_open failed with error: %s\n", u_errorName(ec
));
2386 valid
= ucal_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2387 actual
= ucal_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2388 if (U_FAILURE(ec
)) {
2389 log_err("ucal_getLocaleByType() failed\n");
2392 _checklocs("ucal", req
, valid
, actual
);
2398 #if !UCONFIG_NO_FORMATTING
2401 const char *req
= "zh_Hant_TW_TAINAN", *valid
, *actual
;
2402 obj
= unum_open(UNUM_DECIMAL
,
2406 if (U_FAILURE(ec
)) {
2407 log_err("unum_open failed\n");
2410 valid
= unum_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2411 actual
= unum_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2412 if (U_FAILURE(ec
)) {
2413 log_err("unum_getLocaleByType() failed\n");
2416 _checklocs("unum", req
, valid
, actual
);
2423 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2424 #if !UCONFIG_NO_FORMATTING
2426 UMessageFormat
*obj
;
2427 const char *req
= "ja_JP_TAKAYAMA", *valid
, *actual
;
2429 obj
= umsg_open(EMPTY
, 0,
2432 if (U_FAILURE(ec
)) {
2433 log_err("umsg_open failed\n");
2436 valid
= umsg_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2437 actual
= umsg_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2438 if (U_FAILURE(ec
)) {
2439 log_err("umsg_getLocaleByType() failed\n");
2442 /* We want the valid to be strictly > the bogus requested locale,
2443 and the valid to be >= the actual. */
2444 /* TODO MessageFormat is currently just storing the locale it is given.
2445 As a result, it will return whatever it was given, even if the
2446 locale is invalid. */
2447 test
= (_cmpversion("3.2") <= 0) ?
2448 /* Here is the weakened test for 3.0: */
2449 (_loccmp(req
, valid
) >= 0) :
2450 /* Here is what the test line SHOULD be: */
2451 (_loccmp(req
, valid
) > 0);
2454 _loccmp(valid
, actual
) >= 0) {
2455 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2457 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2465 #if !UCONFIG_NO_BREAK_ITERATION
2467 UBreakIterator
*obj
;
2468 const char *req
= "ar_KW_ABDALI", *valid
, *actual
;
2469 obj
= ubrk_open(UBRK_WORD
,
2474 if (U_FAILURE(ec
)) {
2475 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec
));
2478 valid
= ubrk_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2479 actual
= ubrk_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2480 if (U_FAILURE(ec
)) {
2481 log_err("ubrk_getLocaleByType() failed\n");
2484 _checklocs("ubrk", req
, valid
, actual
);
2490 #if !UCONFIG_NO_COLLATION
2493 const char *req
= "es_AR_BUENOSAIRES", *valid
, *actual
;
2494 obj
= ucol_open(req
, &ec
);
2495 if (U_FAILURE(ec
)) {
2496 log_err("ucol_open failed - %s\n", u_errorName(ec
));
2499 valid
= ucol_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2500 actual
= ucol_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2501 if (U_FAILURE(ec
)) {
2502 log_err("ucol_getLocaleByType() failed\n");
2505 _checklocs("ucol", req
, valid
, actual
);
2511 static void TestNonexistentLanguageExemplars(void) {
2512 /* JB 4068 - Nonexistent language */
2513 UErrorCode ec
= U_ZERO_ERROR
;
2514 ULocaleData
*uld
= ulocdata_open("qqq",&ec
);
2515 if (ec
!= U_USING_DEFAULT_WARNING
) {
2516 log_err_status(ec
, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2519 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2520 ulocdata_close(uld
);
2523 static void TestLocDataErrorCodeChaining(void) {
2524 UErrorCode ec
= U_USELESS_COLLATOR_ERROR
;
2525 ulocdata_open(NULL
, &ec
);
2526 ulocdata_getExemplarSet(NULL
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
);
2527 ulocdata_getDelimiter(NULL
, ULOCDATA_DELIMITER_COUNT
, NULL
, -1, &ec
);
2528 ulocdata_getMeasurementSystem(NULL
, &ec
);
2529 ulocdata_getPaperSize(NULL
, NULL
, NULL
, &ec
);
2530 if (ec
!= U_USELESS_COLLATOR_ERROR
) {
2531 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec
));
2535 static void TestLanguageExemplarsFallbacks(void) {
2536 /* Test that en_US fallsback, but en doesn't fallback. */
2537 UErrorCode ec
= U_ZERO_ERROR
;
2538 ULocaleData
*uld
= ulocdata_open("en_US",&ec
);
2539 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2540 if (ec
!= U_USING_FALLBACK_WARNING
) {
2541 log_err_status(ec
, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2544 ulocdata_close(uld
);
2546 uld
= ulocdata_open("en",&ec
);
2547 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2548 if (ec
!= U_ZERO_ERROR
) {
2549 log_err_status(ec
, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2552 ulocdata_close(uld
);
2555 static const char *acceptResult(UAcceptResult uar
) {
2556 return udbg_enumName(UDBG_UAcceptResult
, uar
);
2559 static void TestAcceptLanguage(void) {
2560 UErrorCode status
= U_ZERO_ERROR
;
2561 UAcceptResult outResult
;
2562 UEnumeration
*available
;
2568 int32_t httpSet
; /**< Which of http[] should be used? */
2569 const char *icuSet
; /**< ? */
2570 const char *expect
; /**< The expected locale result */
2571 UAcceptResult res
; /**< The expected error code */
2573 /*0*/{ 0, NULL
, "mt_MT", ULOC_ACCEPT_VALID
},
2574 /*1*/{ 1, NULL
, "en", ULOC_ACCEPT_VALID
},
2575 /*2*/{ 2, NULL
, "en", ULOC_ACCEPT_FALLBACK
},
2576 /*3*/{ 3, NULL
, "", ULOC_ACCEPT_FAILED
},
2577 /*4*/{ 4, NULL
, "es", ULOC_ACCEPT_VALID
},
2579 /*5*/{ 5, NULL
, "en", ULOC_ACCEPT_VALID
}, /* XF */
2580 /*6*/{ 6, NULL
, "ja", ULOC_ACCEPT_FALLBACK
}, /* XF */
2581 /*7*/{ 7, NULL
, "zh", ULOC_ACCEPT_FALLBACK
}, /* XF */
2583 const int32_t numTests
= sizeof(tests
)/sizeof(tests
[0]);
2584 static const char *http
[] = {
2585 /*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",
2586 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2587 /*2*/ "en-wf, de-lx;q=0.8",
2588 /*3*/ "mga-ie;q=0.9, tlh",
2589 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2590 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2591 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2592 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2593 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2594 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2595 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2598 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2600 /*7*/ "zh-xx;q=0.9",
2603 for(i
=0;i
<numTests
;i
++) {
2605 status
=U_ZERO_ERROR
;
2606 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2607 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2609 available
= ures_openAvailableLocales(tests
[i
].icuSet
, &status
);
2611 rc
= uloc_acceptLanguageFromHTTP(tmp
, 199, &outResult
, http
[tests
[i
].httpSet
], available
, &status
);
2612 uenum_close(available
);
2613 log_verbose(" got %s, %s [%s]\n", tmp
[0]?tmp
:"(EMPTY)", acceptResult(outResult
), u_errorName(status
));
2614 if(outResult
!= tests
[i
].res
) {
2615 log_err_status(status
, "FAIL: #%d: expected outResult of %s but got %s\n", i
,
2616 acceptResult( tests
[i
].res
),
2617 acceptResult( outResult
));
2618 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2619 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
,acceptResult(tests
[i
].res
));
2621 if((outResult
>0)&&uprv_strcmp(tmp
, tests
[i
].expect
)) {
2622 log_err_status(status
, "FAIL: #%d: expected %s but got %s\n", i
, tests
[i
].expect
, tmp
);
2623 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2624 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2629 static const char* LOCALE_ALIAS
[][2] = {
2643 static UBool
isLocaleAvailable(UResourceBundle
* resIndex
, const char* loc
){
2644 UErrorCode status
= U_ZERO_ERROR
;
2646 ures_getStringByKey(resIndex
, loc
,&len
, &status
);
2647 if(U_FAILURE(status
)){
2653 static void TestCalendar() {
2654 #if !UCONFIG_NO_FORMATTING
2656 UErrorCode status
= U_ZERO_ERROR
;
2657 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2658 if(U_FAILURE(status
)){
2659 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2662 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2663 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2664 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2665 UCalendar
* c1
= NULL
;
2666 UCalendar
* c2
= NULL
;
2668 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2669 const char* l1
= ucal_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2670 const char* l2
= ucal_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2672 if(!isLocaleAvailable(resIndex
, newLoc
)){
2675 c1
= ucal_open(NULL
, -1, oldLoc
, UCAL_GREGORIAN
, &status
);
2676 c2
= ucal_open(NULL
, -1, newLoc
, UCAL_GREGORIAN
, &status
);
2678 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0 || status
!=U_ZERO_ERROR
) {
2679 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2681 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1
, l2
);
2685 ures_close(resIndex
);
2689 static void TestDateFormat() {
2690 #if !UCONFIG_NO_FORMATTING
2692 UErrorCode status
= U_ZERO_ERROR
;
2693 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2694 if(U_FAILURE(status
)){
2695 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2698 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2699 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2700 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2701 UDateFormat
* df1
= NULL
;
2702 UDateFormat
* df2
= NULL
;
2703 const char* l1
= NULL
;
2704 const char* l2
= NULL
;
2706 if(!isLocaleAvailable(resIndex
, newLoc
)){
2709 df1
= udat_open(UDAT_FULL
, UDAT_FULL
,oldLoc
, NULL
, 0, NULL
, -1, &status
);
2710 df2
= udat_open(UDAT_FULL
, UDAT_FULL
,newLoc
, NULL
, 0, NULL
, -1, &status
);
2711 if(U_FAILURE(status
)){
2712 log_err("Creation of date format failed %s\n", u_errorName(status
));
2715 /*Test function "getLocale"*/
2716 l1
= udat_getLocaleByType(df1
, ULOC_VALID_LOCALE
, &status
);
2717 l2
= udat_getLocaleByType(df2
, ULOC_VALID_LOCALE
, &status
);
2718 if(U_FAILURE(status
)){
2719 log_err("Fetching the locale by type failed. %s\n", u_errorName(status
));
2721 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
2722 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2724 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1
, l2
);
2728 ures_close(resIndex
);
2732 static void TestCollation() {
2733 #if !UCONFIG_NO_COLLATION
2735 UErrorCode status
= U_ZERO_ERROR
;
2736 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2737 if(U_FAILURE(status
)){
2738 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2741 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2742 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2743 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2744 UCollator
* c1
= NULL
;
2745 UCollator
* c2
= NULL
;
2746 const char* l1
= NULL
;
2747 const char* l2
= NULL
;
2749 status
= U_ZERO_ERROR
;
2750 if(!isLocaleAvailable(resIndex
, newLoc
)){
2753 if(U_FAILURE(status
)){
2754 log_err("Creation of collators failed %s\n", u_errorName(status
));
2757 c1
= ucol_open(oldLoc
, &status
);
2758 c2
= ucol_open(newLoc
, &status
);
2759 l1
= ucol_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2760 l2
= ucol_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2761 if(U_FAILURE(status
)){
2762 log_err("Fetching the locale names failed failed %s\n", u_errorName(status
));
2764 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
2765 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2767 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1
, l2
);
2771 ures_close(resIndex
);
2775 typedef struct OrientationStructTag
{
2776 const char* localeId
;
2777 ULayoutType character
;
2779 } OrientationStruct
;
2781 static const char* ULayoutTypeToString(ULayoutType type
)
2785 case ULOC_LAYOUT_LTR
:
2786 return "ULOC_LAYOUT_LTR";
2788 case ULOC_LAYOUT_RTL
:
2789 return "ULOC_LAYOUT_RTL";
2791 case ULOC_LAYOUT_TTB
:
2792 return "ULOC_LAYOUT_TTB";
2794 case ULOC_LAYOUT_BTT
:
2795 return "ULOC_LAYOUT_BTT";
2797 case ULOC_LAYOUT_UNKNOWN
:
2801 return "Unknown enum value for ULayoutType!";
2804 static void TestOrientation()
2806 static const OrientationStruct toTest
[] = {
2807 { "ar", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2808 { "aR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2809 { "ar_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2810 { "fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2811 { "Fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2812 { "he", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2813 { "ps", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2814 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2815 { "UR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2816 { "en", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
}
2820 for (; i
< sizeof(toTest
) / sizeof(toTest
[0]); ++i
) {
2821 UErrorCode statusCO
= U_ZERO_ERROR
;
2822 UErrorCode statusLO
= U_ZERO_ERROR
;
2823 const char* const localeId
= toTest
[i
].localeId
;
2824 const ULayoutType co
= uloc_getCharacterOrientation(localeId
, &statusCO
);
2825 const ULayoutType expectedCO
= toTest
[i
].character
;
2826 const ULayoutType lo
= uloc_getLineOrientation(localeId
, &statusLO
);
2827 const ULayoutType expectedLO
= toTest
[i
].line
;
2828 if (U_FAILURE(statusCO
)) {
2829 log_err_status(statusCO
,
2830 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
2832 u_errorName(statusCO
));
2834 else if (co
!= expectedCO
) {
2836 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2838 ULayoutTypeToString(expectedCO
),
2839 ULayoutTypeToString(co
));
2841 if (U_FAILURE(statusLO
)) {
2842 log_err_status(statusLO
,
2843 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
2845 u_errorName(statusLO
));
2847 else if (lo
!= expectedLO
) {
2849 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2851 ULayoutTypeToString(expectedLO
),
2852 ULayoutTypeToString(lo
));
2857 static void TestULocale() {
2859 UErrorCode status
= U_ZERO_ERROR
;
2860 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2861 if(U_FAILURE(status
)){
2862 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2865 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2866 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2867 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2868 UChar name1
[256], name2
[256];
2869 char names1
[256], names2
[256];
2870 int32_t capacity
= 256;
2872 status
= U_ZERO_ERROR
;
2873 if(!isLocaleAvailable(resIndex
, newLoc
)){
2876 uloc_getDisplayName(oldLoc
, ULOC_US
, name1
, capacity
, &status
);
2877 if(U_FAILURE(status
)){
2878 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc
, u_errorName(status
));
2881 uloc_getDisplayName(newLoc
, ULOC_US
, name2
, capacity
, &status
);
2882 if(U_FAILURE(status
)){
2883 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc
, u_errorName(status
));
2886 if (u_strcmp(name1
, name2
)!=0) {
2887 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2889 u_austrcpy(names1
, name1
);
2890 u_austrcpy(names2
, name2
);
2891 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1
, names2
);
2893 ures_close(resIndex
);
2897 static void TestUResourceBundle() {
2901 UResourceBundle
* rb1
= NULL
;
2902 UResourceBundle
* rb2
= NULL
;
2903 UErrorCode status
= U_ZERO_ERROR
;
2905 UResourceBundle
*resIndex
= NULL
;
2906 if(U_FAILURE(status
)){
2907 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2910 resIndex
= ures_open(NULL
,"res_index", &status
);
2911 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2913 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2914 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2915 if(!isLocaleAvailable(resIndex
, newLoc
)){
2918 rb1
= ures_open(NULL
, oldLoc
, &status
);
2919 if (U_FAILURE(status
)) {
2920 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
2923 us1
= ures_getLocaleByType(rb1
, ULOC_ACTUAL_LOCALE
, &status
);
2925 status
= U_ZERO_ERROR
;
2926 rb2
= ures_open(NULL
, newLoc
, &status
);
2927 if (U_FAILURE(status
)) {
2928 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
2930 us2
= ures_getLocaleByType(rb2
, ULOC_ACTUAL_LOCALE
, &status
);
2932 if (strcmp(us1
,newLoc
)!=0 || strcmp(us1
,us2
)!=0 ) {
2933 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2936 log_verbose("ures_getStringByKey old:%s new:%s\n", us1
, us2
);
2942 ures_close(resIndex
);
2945 static void TestDisplayName() {
2947 UChar oldCountry
[256] = {'\0'};
2948 UChar newCountry
[256] = {'\0'};
2949 UChar oldLang
[256] = {'\0'};
2950 UChar newLang
[256] = {'\0'};
2951 char country
[256] ={'\0'};
2952 char language
[256] ={'\0'};
2953 int32_t capacity
= 256;
2956 for (i
=0; i
<LENGTHOF(LOCALE_ALIAS
); i
++) {
2957 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2958 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2959 UErrorCode status
= U_ZERO_ERROR
;
2960 int32_t available
= uloc_countAvailable();
2962 for(j
=0; j
<available
; j
++){
2964 const char* dispLoc
= uloc_getAvailable(j
);
2965 int32_t oldCountryLen
= uloc_getDisplayCountry(oldLoc
,dispLoc
, oldCountry
, capacity
, &status
);
2966 int32_t newCountryLen
= uloc_getDisplayCountry(newLoc
, dispLoc
, newCountry
, capacity
, &status
);
2967 int32_t oldLangLen
= uloc_getDisplayLanguage(oldLoc
, dispLoc
, oldLang
, capacity
, &status
);
2968 int32_t newLangLen
= uloc_getDisplayLanguage(newLoc
, dispLoc
, newLang
, capacity
, &status
);
2970 int32_t countryLen
= uloc_getCountry(newLoc
, country
, capacity
, &status
);
2971 int32_t langLen
= uloc_getLanguage(newLoc
, language
, capacity
, &status
);
2972 /* there is a display name for the current country ID */
2973 if(countryLen
!= newCountryLen
){
2974 if(u_strncmp(oldCountry
,newCountry
,oldCountryLen
)!=0){
2975 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc
, dispLoc
);
2978 /* there is a display name for the current lang ID */
2979 if(langLen
!=newLangLen
){
2980 if(u_strncmp(oldLang
,newLang
,oldLangLen
)){
2981 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc
, dispLoc
); }
2987 static void TestGetLocaleForLCID() {
2988 int32_t i
, length
, lengthPre
;
2989 const char* testLocale
= 0;
2990 UErrorCode status
= U_ZERO_ERROR
;
2991 char temp2
[40], temp3
[40];
2994 lcid
= uloc_getLCID("en_US");
2995 if (lcid
!= 0x0409) {
2996 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid
);
2999 lengthPre
= uloc_getLocaleForLCID(lcid
, temp2
, 4, &status
);
3000 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
3001 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status
));
3004 status
= U_ZERO_ERROR
;
3007 length
= uloc_getLocaleForLCID(lcid
, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3008 if (U_FAILURE(status
)) {
3009 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status
));
3010 status
= U_ZERO_ERROR
;
3013 if (length
!= lengthPre
) {
3014 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length
, lengthPre
);
3017 length
= uloc_getLocaleForLCID(0x12345, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3018 if (U_SUCCESS(status
)) {
3019 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2
, u_errorName(status
));
3021 status
= U_ZERO_ERROR
;
3023 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3024 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
3026 testLocale
=rawData2
[NAME
][i
];
3028 log_verbose("Testing %s ......\n", testLocale
);
3030 sscanf(rawData2
[LCID
][i
], "%x", &lcid
);
3031 length
= uloc_getLocaleForLCID(lcid
, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3032 if (U_FAILURE(status
)) {
3033 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid
, u_errorName(status
));
3034 status
= U_ZERO_ERROR
;
3038 if (length
!= uprv_strlen(temp2
)) {
3039 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length
, lcid
, uprv_strlen(temp2
));
3042 /* Compare language, country, script */
3043 length
= uloc_getLanguage(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3044 if (U_FAILURE(status
)) {
3045 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3046 status
= U_ZERO_ERROR
;
3048 else if (uprv_strcmp(temp3
, rawData2
[LANG
][i
]) && !(uprv_strcmp(temp3
, "nn") == 0 && uprv_strcmp(rawData2
[VAR
][i
], "NY") == 0)) {
3049 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[LANG
][i
], lcid
, temp2
);
3052 length
= uloc_getScript(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3053 if (U_FAILURE(status
)) {
3054 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3055 status
= U_ZERO_ERROR
;
3057 else if (uprv_strcmp(temp3
, rawData2
[SCRIPT
][i
])) {
3058 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[SCRIPT
][i
], lcid
, temp2
);
3061 length
= uloc_getCountry(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3062 if (U_FAILURE(status
)) {
3063 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3064 status
= U_ZERO_ERROR
;
3066 else if (uprv_strlen(rawData2
[CTRY
][i
]) && uprv_strcmp(temp3
, rawData2
[CTRY
][i
])) {
3067 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[CTRY
][i
], lcid
, temp2
);
3073 const char* const basic_maximize_data
[][2] = {
3118 "en_Latn_US_POSIX_1901"
3120 "en_Latn__POSIX_1901",
3121 "en_Latn_US_POSIX_1901"
3124 "en_Latn_US_POSIX_1901"
3127 "de_Latn_DE_POSIX_1901"
3132 "th@calendar=buddhist",
3133 "th_Thai_TH@calendar=buddhist"
3163 "de_Latn_DE_U_CO_PHONEBK"
3165 "de_Latn_u_co_phonebk",
3166 "de_Latn_DE_U_CO_PHONEBK"
3168 "de_Latn_DE_u_co_phonebk",
3169 "de_Latn_DE_U_CO_PHONEBK"
3173 const char* const basic_minimize_data
[][2] = {
3178 "en_Latn_US_POSIX_1901",
3181 "EN_Latn_US_POSIX_1901",
3184 "en_Zzzz_US_POSIX_1901",
3187 "de_Latn_DE_POSIX_1901",
3193 "en_Latn_US@calendar=gregorian",
3194 "en@calendar=gregorian"
3198 const char* const full_data
[][3] = {
3202 /* "REMOVE-LIKELY" */
5272 "de@collation=phonebook",
5273 "de_Latn_DE@collation=phonebook",
5274 "de@collation=phonebook"
5278 typedef struct errorDataTag
{
5280 const char* expected
;
5285 const errorData maximizeErrors
[] = {
5289 U_ILLEGAL_ARGUMENT_ERROR
,
5293 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5295 U_ILLEGAL_ARGUMENT_ERROR
,
5299 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5301 U_ILLEGAL_ARGUMENT_ERROR
,
5305 "en_Latn_US_POSIX@currency=EURO",
5306 "en_Latn_US_POSIX@currency=EURO",
5307 U_BUFFER_OVERFLOW_ERROR
,
5311 "en_Latn_US_POSIX@currency=EURO",
5312 "en_Latn_US_POSIX@currency=EURO",
5313 U_STRING_NOT_TERMINATED_WARNING
,
5318 const errorData minimizeErrors
[] = {
5322 U_ILLEGAL_ARGUMENT_ERROR
,
5326 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5328 U_ILLEGAL_ARGUMENT_ERROR
,
5332 "en_Latn_US_POSIX@currency=EURO",
5333 "en__POSIX@currency=EURO",
5334 U_BUFFER_OVERFLOW_ERROR
,
5338 "en_Latn_US_POSIX@currency=EURO",
5339 "en__POSIX@currency=EURO",
5340 U_STRING_NOT_TERMINATED_WARNING
,
5345 static int32_t getExpectedReturnValue(const errorData
* data
)
5347 if (data
->uerror
== U_BUFFER_OVERFLOW_ERROR
||
5348 data
->uerror
== U_STRING_NOT_TERMINATED_WARNING
)
5350 return strlen(data
->expected
);
5358 static int32_t getBufferSize(const errorData
* data
, int32_t actualSize
)
5360 if (data
->expected
== NULL
)
5364 else if (data
->bufferSize
< 0)
5366 return strlen(data
->expected
) + 1;
5370 return data
->bufferSize
;
5374 static void TestLikelySubtags()
5376 char buffer
[ULOC_FULLNAME_CAPACITY
+ ULOC_KEYWORD_AND_VALUES_CAPACITY
+ 1];
5379 for (; i
< sizeof(basic_maximize_data
) / sizeof(basic_maximize_data
[0]); ++i
)
5381 UErrorCode status
= U_ZERO_ERROR
;
5382 const char* const minimal
= basic_maximize_data
[i
][0];
5383 const char* const maximal
= basic_maximize_data
[i
][1];
5385 /* const int32_t length = */
5386 uloc_addLikelySubtags(
5391 if (U_FAILURE(status
)) {
5392 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal
, u_errorName(status
));
5393 status
= U_ZERO_ERROR
;
5395 else if (uprv_strlen(maximal
) == 0) {
5396 if (uprv_stricmp(minimal
, buffer
) != 0) {
5397 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5400 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5401 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal
, minimal
, buffer
);
5405 for (i
= 0; i
< sizeof(basic_minimize_data
) / sizeof(basic_minimize_data
[0]); ++i
) {
5407 UErrorCode status
= U_ZERO_ERROR
;
5408 const char* const maximal
= basic_minimize_data
[i
][0];
5409 const char* const minimal
= basic_minimize_data
[i
][1];
5411 /* const int32_t length = */
5412 uloc_minimizeSubtags(
5418 if (U_FAILURE(status
)) {
5419 log_err_status(status
, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5420 status
= U_ZERO_ERROR
;
5422 else if (uprv_strlen(minimal
) == 0) {
5423 if (uprv_stricmp(maximal
, buffer
) != 0) {
5424 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5427 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5428 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5432 for (i
= 0; i
< sizeof(full_data
) / sizeof(full_data
[0]); ++i
) {
5434 UErrorCode status
= U_ZERO_ERROR
;
5435 const char* const minimal
= full_data
[i
][0];
5436 const char* const maximal
= full_data
[i
][1];
5438 /* const int32_t length = */
5439 uloc_addLikelySubtags(
5444 if (U_FAILURE(status
)) {
5445 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal
, u_errorName(status
));
5446 status
= U_ZERO_ERROR
;
5448 else if (uprv_strlen(maximal
) == 0) {
5449 if (uprv_stricmp(minimal
, buffer
) != 0) {
5450 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5453 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5454 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5458 for (i
= 0; i
< sizeof(full_data
) / sizeof(full_data
[0]); ++i
) {
5460 UErrorCode status
= U_ZERO_ERROR
;
5461 const char* const maximal
= full_data
[i
][1];
5462 const char* const minimal
= full_data
[i
][2];
5464 if (strlen(maximal
) > 0) {
5466 /* const int32_t length = */
5467 uloc_minimizeSubtags(
5473 if (U_FAILURE(status
)) {
5474 log_err_status(status
, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5475 status
= U_ZERO_ERROR
;
5477 else if (uprv_strlen(minimal
) == 0) {
5478 if (uprv_stricmp(maximal
, buffer
) != 0) {
5479 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5482 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5483 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5488 for (i
= 0; i
< sizeof(maximizeErrors
) / sizeof(maximizeErrors
[0]); ++i
) {
5490 UErrorCode status
= U_ZERO_ERROR
;
5491 const char* const minimal
= maximizeErrors
[i
].tag
;
5492 const char* const maximal
= maximizeErrors
[i
].expected
;
5493 const UErrorCode expectedStatus
= maximizeErrors
[i
].uerror
;
5494 const int32_t expectedLength
= getExpectedReturnValue(&maximizeErrors
[i
]);
5495 const int32_t bufferSize
= getBufferSize(&maximizeErrors
[i
], sizeof(buffer
));
5497 const int32_t length
=
5498 uloc_addLikelySubtags(
5504 if (status
== U_ZERO_ERROR
) {
5505 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal
, u_errorName(expectedStatus
));
5506 status
= U_ZERO_ERROR
;
5508 else if (status
!= expectedStatus
) {
5509 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
));
5511 else if (length
!= expectedLength
) {
5512 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal
, expectedLength
, length
);
5514 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5515 if (uprv_strnicmp(maximal
, buffer
, bufferSize
) != 0) {
5516 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5517 maximal
, minimal
, (int)sizeof(buffer
), buffer
);
5522 for (i
= 0; i
< sizeof(minimizeErrors
) / sizeof(minimizeErrors
[0]); ++i
) {
5524 UErrorCode status
= U_ZERO_ERROR
;
5525 const char* const maximal
= minimizeErrors
[i
].tag
;
5526 const char* const minimal
= minimizeErrors
[i
].expected
;
5527 const UErrorCode expectedStatus
= minimizeErrors
[i
].uerror
;
5528 const int32_t expectedLength
= getExpectedReturnValue(&minimizeErrors
[i
]);
5529 const int32_t bufferSize
= getBufferSize(&minimizeErrors
[i
], sizeof(buffer
));
5531 const int32_t length
=
5532 uloc_minimizeSubtags(
5538 if (status
== U_ZERO_ERROR
) {
5539 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal
, u_errorName(expectedStatus
));
5540 status
= U_ZERO_ERROR
;
5542 else if (status
!= expectedStatus
) {
5543 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
));
5545 else if (length
!= expectedLength
) {
5546 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal
, expectedLength
, length
);
5548 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5549 if (uprv_strnicmp(minimal
, buffer
, bufferSize
) != 0) {
5550 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5551 minimal
, maximal
, (int)sizeof(buffer
), buffer
);
5557 const char* const locale_to_langtag
[][3] = {
5558 {"@x=elmer", "x-elmer", "x-elmer"},
5561 {"en_US", "en-US", "en-US"},
5562 {"iw_IL", "he-IL", "he-IL"},
5563 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5564 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5565 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5566 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL
}, /* variant POSIX_VAR is processed as regular variant */
5567 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL
}, /* variant VAR_POSIX is processed as regular variant */
5568 {"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 */
5569 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5570 {"und_555", "und-555", "und-555"},
5571 {"123", "und", NULL
},
5572 {"%$#&", "und", NULL
},
5573 {"_Latn", "und-Latn", "und-Latn"},
5574 {"_DE", "und-DE", "und-DE"},
5575 {"und_FR", "und-FR", "und-FR"},
5576 {"th_TH_TH", "th-TH-x-lvariant-th", NULL
},
5577 {"bogus", "bogus", "bogus"},
5578 {"foooobarrr", "und", NULL
},
5579 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5580 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL
},
5581 {"en_US_1234", "en-US-1234", "en-US-1234"},
5582 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5583 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5584 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL
},
5585 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL
},
5586 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5587 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5588 {"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"},
5589 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5590 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5591 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL
},
5592 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-ks-identic", NULL
},
5593 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5594 {"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"},
5595 {"@x=elmer", "x-elmer", "x-elmer"},
5596 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5597 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5598 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5602 static void TestToLanguageTag(void) {
5608 const char *expected
;
5610 for (i
= 0; locale_to_langtag
[i
][0] != NULL
; i
++) {
5611 inloc
= locale_to_langtag
[i
][0];
5613 /* testing non-strict mode */
5614 status
= U_ZERO_ERROR
;
5616 expected
= locale_to_langtag
[i
][1];
5618 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), FALSE
, &status
);
5619 if (U_FAILURE(status
)) {
5620 if (expected
!= NULL
) {
5621 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5622 inloc
, u_errorName(status
));
5625 if (expected
== NULL
) {
5626 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5628 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5629 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5630 langtag
, inloc
, expected
);
5634 /* testing strict mode */
5635 status
= U_ZERO_ERROR
;
5637 expected
= locale_to_langtag
[i
][2];
5639 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), TRUE
, &status
);
5640 if (U_FAILURE(status
)) {
5641 if (expected
!= NULL
) {
5642 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5643 inloc
, u_errorName(status
));
5646 if (expected
== NULL
) {
5647 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5649 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5650 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5651 langtag
, inloc
, expected
);
5657 static const struct {
5661 } langtag_to_locale
[] = {
5663 {"en-us", "en_US", 5},
5664 {"und-US", "_US", 6},
5665 {"und-latn", "_Latn", 8},
5666 {"en-US-posix", "en_US_POSIX", 11},
5667 {"de-de_euro", "de", 2},
5668 {"kok-IN", "kok_IN", 6},
5671 {"en-latn-x", "en_Latn", 7},
5672 {"art-lojban", "jbo", 3},
5673 {"zh-hakka", "hak", 3},
5674 {"zh-cmn-CH", "cmn_CH", 9},
5675 {"xxx-yy", "xxx_YY", 6},
5676 {"fr-234", "fr_234", 6},
5677 {"i-default", "en@x=i-default", 14},
5679 {"ja-jp-jp", "ja_JP", 5},
5680 {"bogus", "bogus", 5},
5681 {"boguslang", "", 0},
5682 {"EN-lATN-us", "en_Latn_US", 10},
5683 {"und-variant-1234", "__VARIANT_1234", 16},
5684 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5685 {"en-u-ca-gregory", "en@calendar=gregorian", 15},
5686 {"en-U-cu-USD", "en@currency=usd", 11},
5687 {"en-US-u-va-posix", "en_US_POSIX", 16},
5688 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", 27},
5689 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", 22},
5690 {"en-us-u-va-posix2", "en_US@va=posix2", 17},
5691 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", 22},
5692 {"ar-x-1-2-3", "ar@x=1-2-3", 10},
5693 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", 19},
5694 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", 30},
5695 {"ja-u-cu-jpy-ca-jp", "ja@currency=jpy", 11},
5696 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", 16},
5697 {"und-a-abc-def", "und@a=abc-def", 13},
5698 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", 30},
5699 {"x-elmer", "@x=elmer", 7},
5700 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", 30},
5701 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5702 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that", 88},
5706 static void TestForLanguageTag(void) {
5712 for (i
= 0; langtag_to_locale
[i
].bcpID
!= NULL
; i
++) {
5713 status
= U_ZERO_ERROR
;
5715 uloc_forLanguageTag(langtag_to_locale
[i
].bcpID
, locale
, sizeof(locale
), &parsedLen
, &status
);
5716 if (U_FAILURE(status
)) {
5717 log_err_status(status
, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5718 langtag_to_locale
[i
].bcpID
, u_errorName(status
));
5720 if (uprv_strcmp(langtag_to_locale
[i
].locID
, locale
) != 0) {
5721 log_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5722 locale
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].locID
);
5724 if (parsedLen
!= langtag_to_locale
[i
].len
) {
5725 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5726 parsedLen
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].len
);
5732 static void test_unicode_define(const char *namech
, char ch
, const char *nameu
, UChar uch
)
5736 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech
, ch
,(int)ch
, nameu
, (int) uch
);
5737 u_charsToUChars(&ch
, asUch
, 1);
5738 if(asUch
[0] != uch
) {
5739 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
);
5741 log_verbose(" .. OK, == U+%04X\n", (int)asUch
[0]);
5745 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
5747 static void TestUnicodeDefines(void) {
5748 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR
, ULOC_KEYWORD_SEPARATOR_UNICODE
);
5749 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN
, ULOC_KEYWORD_ASSIGN_UNICODE
);
5750 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR
, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE
);