1 /********************************************************************
3 * Copyright (c) 1997-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
10 * Modification History:
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
25 #include "unicode/putil.h"
26 #include "unicode/ubrk.h"
27 #include "unicode/uchar.h"
28 #include "unicode/ucol.h"
29 #include "unicode/udat.h"
30 #include "unicode/uloc.h"
31 #include "unicode/umsg.h"
32 #include "unicode/ures.h"
33 #include "unicode/uset.h"
34 #include "unicode/ustring.h"
35 #include "unicode/utypes.h"
36 #include "unicode/ulocdata.h"
37 #include "unicode/uldnames.h"
38 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
40 #include "unicode/ualoc.h" /* Apple-specific */
42 static void TestNullDefault(void);
43 static void TestNonexistentLanguageExemplars(void);
44 static void TestLocDataErrorCodeChaining(void);
45 static void TestLanguageExemplarsFallbacks(void);
46 static void TestDisplayNameBrackets(void);
48 static void TestUnicodeDefines(void);
50 static void TestIsRightToLeft(void);
52 static void TestGetLanguagesForRegion(void);
53 static void TestGetAppleParent(void);
54 static void TestAppleLocalizationsToUse(void);
56 void PrintDataTable();
58 /*---------------------------------------------------
60 --------------------------------------------------- */
62 #define LOCALE_INFO_SIZE 28
64 static const char* const rawData2
[LOCALE_INFO_SIZE
][LOCALE_SIZE
] = {
66 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
68 { "", "", "", "", "", "", "", "", "" },
70 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
72 { "", "", "", "", "NY", "", "", "", "" },
74 { "en_US", "fr_FR", "ca_ES",
75 "el_GR", "no_NO_NY", "zh_Hans_CN",
76 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
78 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
80 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
82 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
84 /* display language (English) */
85 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
86 /* display script code (English) */
87 { "", "", "", "", "", "Simplified Han", "", "", "" },
88 /* display country (English) */
89 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
90 /* display variant (English) */
91 { "", "", "", "", "NY", "", "", "", "" },
92 /* display name (English) */
93 { "English (United States)", "French (France)", "Catalan (Spain)",
94 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
95 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
97 /* display language (French) */
98 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
99 /* display script code (French) */
100 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" },
101 /* display country (French) */
102 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
103 /* display variant (French) */
104 { "", "", "", "", "NY", "", "", "", "" },
105 /* display name (French) */
106 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
107 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)",
108 "allemand (Allemagne, ordre de tri=ordre de l\\u2019annuaire)", "espagnol (ordre de tri=ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" },
110 /* display language (Catalan) */
111 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
112 /* display script code (Catalan) */
113 { "", "", "", "", "", "han simplificat", "", "", "" },
114 /* display country (Catalan) */
115 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
116 /* display variant (Catalan) */
117 { "", "", "", "", "NY", "", "", "", "" },
118 /* display name (Catalan) */
119 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
120 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
121 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
123 /* display language (Greek) */
125 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
126 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
127 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
128 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
129 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
130 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
131 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
132 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
133 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
135 /* display script code (Greek) */
137 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" },
138 /* display country (Greek) */
140 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
141 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
142 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
143 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
144 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
145 "\\u039A\\u03AF\\u03BD\\u03B1",
146 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
148 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
150 /* display variant (Greek) */
151 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
152 /* display name (Greek) */
154 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
155 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
156 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
157 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
158 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
159 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
160 "\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03af\\u03b1, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2 \\u03c4\\u03b7\\u03bb\\u03b5\\u03c6\\u03c9\\u03bd\\u03b9\\u03ba\\u03bf\\u03cd \\u03ba\\u03b1\\u03c4\\u03b1\\u03bb\\u03cc\\u03b3\\u03bf\\u03c5)",
161 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)",
162 "\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03af\\u03b1, \\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf)"
166 static UChar
*** dataTable
=0;
206 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
208 void addLocaleTest(TestNode
** root
);
210 void addLocaleTest(TestNode
** root
)
212 TESTCASE(TestObsoleteNames
); /* srl- move */
213 TESTCASE(TestBasicGetters
);
214 TESTCASE(TestNullDefault
);
215 TESTCASE(TestPrefixes
);
216 TESTCASE(TestSimpleResourceInfo
);
217 TESTCASE(TestDisplayNames
);
218 TESTCASE(TestGetAvailableLocales
);
219 TESTCASE(TestDataDirectory
);
220 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
221 TESTCASE(TestISOFunctions
);
223 TESTCASE(TestISO3Fallback
);
224 TESTCASE(TestUninstalledISO3Names
);
225 TESTCASE(TestSimpleDisplayNames
);
226 TESTCASE(TestVariantParsing
);
227 TESTCASE(TestKeywordVariants
);
228 TESTCASE(TestKeywordVariantParsing
);
229 TESTCASE(TestCanonicalization
);
230 TESTCASE(TestKeywordSet
);
231 TESTCASE(TestKeywordSetError
);
232 TESTCASE(TestDisplayKeywords
);
233 TESTCASE(TestDisplayKeywordValues
);
234 TESTCASE(TestGetBaseName
);
235 #if !UCONFIG_NO_FILE_IO
236 TESTCASE(TestGetLocale
);
238 TESTCASE(TestDisplayNameWarning
);
239 TESTCASE(TestNonexistentLanguageExemplars
);
240 TESTCASE(TestLocDataErrorCodeChaining
);
241 TESTCASE(TestLanguageExemplarsFallbacks
);
242 TESTCASE(TestCalendar
);
243 TESTCASE(TestDateFormat
);
244 TESTCASE(TestCollation
);
245 TESTCASE(TestULocale
);
246 TESTCASE(TestUResourceBundle
);
247 TESTCASE(TestDisplayName
);
248 TESTCASE(TestAcceptLanguage
);
249 TESTCASE(TestGetLocaleForLCID
);
250 TESTCASE(TestOrientation
);
251 TESTCASE(TestLikelySubtags
);
252 TESTCASE(TestToLanguageTag
);
253 TESTCASE(TestForLanguageTag
);
254 TESTCASE(TestTrailingNull
);
255 TESTCASE(TestUnicodeDefines
);
256 TESTCASE(TestEnglishExemplarCharacters
);
257 TESTCASE(TestDisplayNameBrackets
);
258 TESTCASE(TestIsRightToLeft
);
259 TESTCASE(TestToUnicodeLocaleKey
);
260 TESTCASE(TestToLegacyKey
);
261 TESTCASE(TestToUnicodeLocaleType
);
262 TESTCASE(TestToLegacyType
);
263 TESTCASE(TestGetLanguagesForRegion
);
264 TESTCASE(TestGetAppleParent
);
265 TESTCASE(TestAppleLocalizationsToUse
);
269 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
270 static void TestBasicGetters() {
273 UErrorCode status
= U_ZERO_ERROR
;
274 char *testLocale
= 0;
275 char *temp
= 0, *name
= 0;
276 log_verbose("Testing Basic Getters\n");
277 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
278 testLocale
=(char*)malloc(sizeof(char) * (strlen(rawData2
[NAME
][i
])+1));
279 strcpy(testLocale
,rawData2
[NAME
][i
]);
281 log_verbose("Testing %s .....\n", testLocale
);
282 cap
=uloc_getLanguage(testLocale
, NULL
, 0, &status
);
283 if(status
==U_BUFFER_OVERFLOW_ERROR
){
285 temp
=(char*)malloc(sizeof(char) * (cap
+1));
286 uloc_getLanguage(testLocale
, temp
, cap
+1, &status
);
288 if(U_FAILURE(status
)){
289 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status
));
291 if (0 !=strcmp(temp
,rawData2
[LANG
][i
])) {
292 log_err(" Language code mismatch: %s versus %s\n", temp
, rawData2
[LANG
][i
]);
296 cap
=uloc_getCountry(testLocale
, temp
, cap
, &status
);
297 if(status
==U_BUFFER_OVERFLOW_ERROR
){
299 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
300 uloc_getCountry(testLocale
, temp
, cap
+1, &status
);
302 if(U_FAILURE(status
)){
303 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status
));
305 if (0 != strcmp(temp
, rawData2
[CTRY
][i
])) {
306 log_err(" Country code mismatch: %s versus %s\n", temp
, rawData2
[CTRY
][i
]);
310 cap
=uloc_getVariant(testLocale
, temp
, cap
, &status
);
311 if(status
==U_BUFFER_OVERFLOW_ERROR
){
313 temp
=(char*)realloc(temp
, sizeof(char) * (cap
+1));
314 uloc_getVariant(testLocale
, temp
, cap
+1, &status
);
316 if(U_FAILURE(status
)){
317 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status
));
319 if (0 != strcmp(temp
, rawData2
[VAR
][i
])) {
320 log_err("Variant code mismatch: %s versus %s\n", temp
, rawData2
[VAR
][i
]);
323 cap
=uloc_getName(testLocale
, NULL
, 0, &status
);
324 if(status
==U_BUFFER_OVERFLOW_ERROR
){
326 name
=(char*)malloc(sizeof(char) * (cap
+1));
327 uloc_getName(testLocale
, name
, cap
+1, &status
);
328 } else if(status
==U_ZERO_ERROR
) {
329 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale
);
331 if(U_FAILURE(status
)){
332 log_err("ERROR: in uloc_getName %s\n", myErrorName(status
));
334 if (0 != strcmp(name
, rawData2
[NAME
][i
])){
335 log_err(" Mismatch in getName: %s versus %s\n", name
, rawData2
[NAME
][i
]);
345 static void TestNullDefault() {
346 UErrorCode status
= U_ZERO_ERROR
;
347 char original
[ULOC_FULLNAME_CAPACITY
];
349 uprv_strcpy(original
, uloc_getDefault());
350 uloc_setDefault("qq_BLA", &status
);
351 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
352 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
354 uloc_setDefault(NULL
, &status
);
355 if (uprv_strcmp(uloc_getDefault(), original
) != 0) {
356 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
360 /* Test that set & get of default locale work, and that
361 * default locales are cached and reused, and not overwritten.
365 const char *n2_en_US
;
367 status
= U_ZERO_ERROR
;
368 uloc_setDefault("en_US", &status
);
369 n_en_US
= uloc_getDefault();
370 if (strcmp(n_en_US
, "en_US") != 0) {
371 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
374 uloc_setDefault("fr_FR", &status
);
375 n_fr_FR
= uloc_getDefault();
376 if (strcmp(n_en_US
, "en_US") != 0) {
377 log_err("uloc_setDefault altered previously default string."
378 "Expected \"en_US\", got \"%s\"\n", n_en_US
);
380 if (strcmp(n_fr_FR
, "fr_FR") != 0) {
381 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR
);
384 uloc_setDefault("en_US", &status
);
385 n2_en_US
= uloc_getDefault();
386 if (strcmp(n2_en_US
, "en_US") != 0) {
387 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US
);
389 if (n2_en_US
!= n_en_US
) {
390 log_err("Default locale cache failed to reuse en_US locale.\n");
393 if (U_FAILURE(status
)) {
394 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status
));
400 /* Test the i- and x- and @ and . functionality
403 #define PREFIXBUFSIZ 128
405 static void TestPrefixes() {
408 const char *loc
, *expected
;
410 static const char * const testData
[][7] =
412 /* NULL canonicalize() column means "expect same as getName()" */
413 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL
},
414 {"en", "", "GB", "", "en-gb", "en_GB", NULL
},
415 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL
},
416 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL
},
417 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL
},
418 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL
},
420 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans@collation=pinyin"},
421 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", NULL
},
423 {"de", "", "", "1901", "de-1901", "de__1901", NULL
},
424 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
425 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
426 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
427 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
428 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
429 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
430 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
431 {"no", "", "", "NY", "no__ny", "no__NY", NULL
},
432 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
433 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL
},
434 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL
},
435 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
436 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL
},
437 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL
},
438 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL
}, /* total garbage */
440 {NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
}
443 static const char * const testTitles
[] = {
444 "uloc_getLanguage()",
450 "uloc_canonicalize()"
453 char buf
[PREFIXBUFSIZ
];
458 for(row
=0;testData
[row
][0] != NULL
;row
++) {
459 loc
= testData
[row
][NAME
];
460 log_verbose("Test #%d: %s\n", row
, loc
);
465 for(n
=0;n
<=(NAME
+2);n
++) {
466 if(n
==NAME
) continue;
468 for(len
=0;len
<PREFIXBUFSIZ
;len
++) {
469 buf
[len
] = '%'; /* Set a tripwire.. */
475 len
= uloc_getLanguage(loc
, buf
, PREFIXBUFSIZ
, &err
);
479 len
= uloc_getScript(loc
, buf
, PREFIXBUFSIZ
, &err
);
483 len
= uloc_getCountry(loc
, buf
, PREFIXBUFSIZ
, &err
);
487 len
= uloc_getVariant(loc
, buf
, PREFIXBUFSIZ
, &err
);
491 len
= uloc_getName(loc
, buf
, PREFIXBUFSIZ
, &err
);
495 len
= uloc_canonicalize(loc
, buf
, PREFIXBUFSIZ
, &err
);
504 log_err("#%d: %s on %s: err %s\n",
505 row
, testTitles
[n
], loc
, u_errorName(err
));
507 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
508 row
, testTitles
[n
], loc
, buf
, len
);
510 if(len
!= (int32_t)strlen(buf
)) {
511 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
512 row
, testTitles
[n
], loc
, buf
, len
, strlen(buf
)+1);
516 /* see if they smashed something */
517 if(buf
[len
+1] != '%') {
518 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
519 row
, testTitles
[n
], loc
, buf
, buf
[len
+1]);
522 expected
= testData
[row
][n
];
523 if (expected
== NULL
&& n
== (NAME
+2)) {
524 /* NULL expected canonicalize() means "expect same as getName()" */
525 expected
= testData
[row
][NAME
+1];
527 if(strcmp(buf
, expected
)) {
528 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
529 row
, testTitles
[n
], loc
, buf
, expected
);
538 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
539 static void TestSimpleResourceInfo() {
541 char* testLocale
= 0;
546 testLocale
=(char*)malloc(sizeof(char) * 1);
547 expected
=(UChar
*)malloc(sizeof(UChar
) * 1);
550 log_verbose("Testing getISO3Language and getISO3Country\n");
551 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
553 testLocale
=(char*)realloc(testLocale
, sizeof(char) * (u_strlen(dataTable
[NAME
][i
])+1));
554 u_austrcpy(testLocale
, dataTable
[NAME
][i
]);
556 log_verbose("Testing %s ......\n", testLocale
);
558 temp
=uloc_getISO3Language(testLocale
);
559 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
560 u_uastrcpy(expected
,temp
);
561 if (0 != u_strcmp(expected
, dataTable
[LANG3
][i
])) {
562 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected
),
563 austrdup(dataTable
[LANG3
][i
]));
566 temp
=uloc_getISO3Country(testLocale
);
567 expected
=(UChar
*)realloc(expected
, sizeof(UChar
) * (strlen(temp
) + 1));
568 u_uastrcpy(expected
,temp
);
569 if (0 != u_strcmp(expected
, dataTable
[CTRY3
][i
])) {
570 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected
),
571 austrdup(dataTable
[CTRY3
][i
]));
573 sprintf(temp2
, "%x", (int)uloc_getLCID(testLocale
));
574 if (strcmp(temp2
, rawData2
[LCID
][i
]) != 0) {
575 log_err("LCID mismatch: %s versus %s\n", temp2
, rawData2
[LCID
][i
]);
584 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
585 * if there's room but won't be included in result. result < 0 indicates an error.
586 * Returns the number of chars written (not those that would be written if there's enough room.*/
587 static int32_t UCharsToEscapedAscii(const UChar
* utext
, int32_t len
, char* resultChars
, int32_t buflen
) {
588 static const struct {
601 static const int32_t ESCAPE_MAP_LENGTH
= sizeof(ESCAPE_MAP
)/sizeof(ESCAPE_MAP
[0]);
602 static const char HEX_DIGITS
[] = {
603 '0', '1', '2', '3', '4', '5', '6', '7',
604 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
607 int32_t resultLen
= 0;
608 const int32_t limit
= len
<0 ? buflen
: len
; /* buflen is long enough to hit the buffer limit */
609 const int32_t escapeLimit1
= buflen
-2;
610 const int32_t escapeLimit2
= buflen
-6;
613 if(utext
==NULL
|| resultChars
==NULL
|| buflen
<0) {
617 for(i
=0;i
<limit
&& resultLen
<buflen
;++i
) {
623 for(j
=0;j
<ESCAPE_MAP_LENGTH
&& uc
!=ESCAPE_MAP
[j
].sourceVal
;j
++) {
625 if(j
<ESCAPE_MAP_LENGTH
) {
626 if(resultLen
>escapeLimit1
) {
629 resultChars
[resultLen
++]='\\';
630 resultChars
[resultLen
++]=ESCAPE_MAP
[j
].escapedChar
;
634 u_austrncpy(resultChars
+ resultLen
, &uc
, 1);
639 if(resultLen
>escapeLimit2
) {
643 /* have to escape the uchar */
644 resultChars
[resultLen
++]='\\';
645 resultChars
[resultLen
++]='u';
646 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>12)&0xff];
647 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>8)&0xff];
648 resultChars
[resultLen
++]=HEX_DIGITS
[(uc
>>4)&0xff];
649 resultChars
[resultLen
++]=HEX_DIGITS
[uc
&0xff];
652 if(resultLen
<buflen
) {
653 resultChars
[resultLen
] = 0;
660 * Jitterbug 2439 -- markus 20030425
662 * The lookup of display names must not fall back through the default
663 * locale because that yields useless results.
665 static void TestDisplayNames()
668 UErrorCode errorCode
=U_ZERO_ERROR
;
670 log_verbose("Testing getDisplayName for different locales\n");
672 log_verbose(" In locale = en_US...\n");
673 doTestDisplayNames("en_US", DLANG_EN
);
674 log_verbose(" In locale = fr_FR....\n");
675 doTestDisplayNames("fr_FR", DLANG_FR
);
676 log_verbose(" In locale = ca_ES...\n");
677 doTestDisplayNames("ca_ES", DLANG_CA
);
678 log_verbose(" In locale = gr_EL..\n");
679 doTestDisplayNames("el_GR", DLANG_EL
);
681 /* test that the default locale has a display name for its own language */
682 errorCode
=U_ZERO_ERROR
;
683 length
=uloc_getDisplayLanguage(NULL
, NULL
, buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
684 if(U_FAILURE(errorCode
) || (length
<=3 && buffer
[0]<=0x7f)) {
685 /* check <=3 to reject getting the language code as a display name */
686 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
));
689 /* test that we get the language code itself for an unknown language, and a default warning */
690 errorCode
=U_ZERO_ERROR
;
691 length
=uloc_getDisplayLanguage("qq", "rr", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
692 if(errorCode
!=U_USING_DEFAULT_WARNING
|| length
!=2 || buffer
[0]!=0x71 || buffer
[1]!=0x71) {
693 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode
));
696 /* test that we get a default warning for a display name where one component is unknown (4255) */
697 errorCode
=U_ZERO_ERROR
;
698 length
=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
699 if(errorCode
!=U_USING_DEFAULT_WARNING
) {
700 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode
));
705 static const char *aLocale
= "es@collation=traditional;calendar=japanese";
706 static const char *testL
[] = { "en_US",
710 static const char *expect
[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
711 "espagnol (calendrier=calendrier japonais, ordre de tri=ordre traditionnel)",
712 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)",
713 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)" };
716 for(i
=0;i
<UPRV_LENGTHOF(testL
);i
++) {
717 errorCode
= U_ZERO_ERROR
;
718 uloc_getDisplayName(aLocale
, testL
[i
], buffer
, UPRV_LENGTHOF(buffer
), &errorCode
);
719 if(U_FAILURE(errorCode
)) {
720 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale
, testL
[i
], u_errorName(errorCode
));
722 expectBuffer
= CharsToUChars(expect
[i
]);
723 if(u_strcmp(buffer
,expectBuffer
)) {
724 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
));
726 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale
, testL
[i
], expect
[i
]);
733 /* test that we properly preflight and return data when there's a non-default pattern,
737 static const char *locale
="az_Cyrl";
738 static const char *displayLocale
="ja";
739 static const char *expectedChars
=
740 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e "
741 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
742 UErrorCode ec
=U_ZERO_ERROR
;
745 int32_t preflightLen
=uloc_getDisplayName(locale
, displayLocale
, NULL
, 0, &ec
);
746 /* inconvenient semantics when preflighting, this condition is expected... */
747 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
750 len
=uloc_getDisplayName(locale
, displayLocale
, result
, UPRV_LENGTHOF(result
), &ec
);
752 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
753 locale
, displayLocale
, u_errorName(ec
));
755 UChar
*expected
=CharsToUChars(expectedChars
);
756 int32_t expectedLen
=u_strlen(expected
);
758 if(len
!=expectedLen
) {
759 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
760 locale
, displayLocale
, len
, expectedLen
);
761 } else if(preflightLen
!=expectedLen
) {
762 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
763 locale
, displayLocale
, preflightLen
, expectedLen
);
764 } else if(u_strncmp(result
, expected
, len
)) {
765 int32_t cap
=len
*6+1; /* worst case + space for trailing null */
766 char* resultChars
=(char*)malloc(cap
);
767 int32_t resultCharsLen
=UCharsToEscapedAscii(result
, len
, resultChars
, cap
);
768 if(resultCharsLen
<0 || resultCharsLen
<cap
-1) {
769 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale
, displayLocale
);
771 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
772 locale
, displayLocale
, resultChars
, expectedChars
);
777 /* test all buffer sizes */
778 for(i
=len
+1;i
>=0;--i
) {
779 len
=uloc_getDisplayName(locale
, displayLocale
, result
, i
, &ec
);
780 if(ec
==U_BUFFER_OVERFLOW_ERROR
) {
784 log_err("using buffer of length %d returned error %s", i
, u_errorName(ec
));
787 if(len
!=expectedLen
) {
788 log_err("with buffer of length %d, expected length %d but got %d", i
, expectedLen
, len
);
791 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
792 * we don't know that it's been filled, so no point in checking. */
802 /* test for uloc_getAvialable() and uloc_countAvilable()*/
803 static void TestGetAvailableLocales()
809 log_verbose("Testing the no of avialable locales\n");
810 locCount
=uloc_countAvailable();
812 log_data_err("countAvailable() returned an empty list!\n");
814 /* use something sensible w/o hardcoding the count */
815 else if(locCount
< 0){
816 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount
);
819 log_info("Number of locales returned = %d\n", locCount
);
821 for(i
=0;i
<locCount
;i
++){
822 locList
=uloc_getAvailable(i
);
824 log_verbose(" %s\n", locList
);
828 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
829 static void TestDataDirectory()
832 char oldDirectory
[512];
833 const char *temp
,*testValue1
,*testValue2
,*testValue3
;
834 const char path
[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING
; /*give the required path */
836 log_verbose("Testing getDataDirectory()\n");
837 temp
= u_getDataDirectory();
838 strcpy(oldDirectory
, temp
);
840 testValue1
=uloc_getISO3Language("en_US");
841 log_verbose("first fetch of language retrieved %s\n", testValue1
);
843 if (0 != strcmp(testValue1
,"eng")){
844 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1
);
847 /*defining the path for DataDirectory */
848 log_verbose("Testing setDataDirectory\n");
849 u_setDataDirectory( path
);
850 if(strcmp(path
, u_getDataDirectory())==0)
851 log_verbose("setDataDirectory working fine\n");
853 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path
);
855 testValue2
=uloc_getISO3Language("en_US");
856 log_verbose("second fetch of language retrieved %s \n", testValue2
);
858 u_setDataDirectory(oldDirectory
);
859 testValue3
=uloc_getISO3Language("en_US");
860 log_verbose("third fetch of language retrieved %s \n", testValue3
);
862 if (0 != strcmp(testValue3
,"eng")) {
863 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3
);
869 /*=========================================================== */
873 static void doTestDisplayNames(const char* displayLocale
, int32_t compareIndex
)
875 UErrorCode status
= U_ZERO_ERROR
;
877 int32_t maxresultsize
;
879 const char *testLocale
;
883 UChar
*testScript
= 0;
889 UChar
* expectedLang
= 0;
890 UChar
* expectedScript
= 0;
891 UChar
* expectedCtry
= 0;
892 UChar
* expectedVar
= 0;
893 UChar
* expectedName
= 0;
897 for(i
=0;i
<LOCALE_SIZE
; ++i
)
899 testLocale
=rawData2
[NAME
][i
];
901 log_verbose("Testing..... %s\n", testLocale
);
904 maxresultsize
=uloc_getDisplayLanguage(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
905 if(status
==U_BUFFER_OVERFLOW_ERROR
)
908 testLang
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
909 uloc_getDisplayLanguage(testLocale
, displayLocale
, testLang
, maxresultsize
+ 1, &status
);
915 if(U_FAILURE(status
)){
916 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status
));
920 maxresultsize
=uloc_getDisplayScript(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
921 if(status
==U_BUFFER_OVERFLOW_ERROR
)
924 testScript
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
925 uloc_getDisplayScript(testLocale
, displayLocale
, testScript
, maxresultsize
+ 1, &status
);
931 if(U_FAILURE(status
)){
932 log_err("Error in getDisplayScript() %s\n", myErrorName(status
));
936 maxresultsize
=uloc_getDisplayCountry(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
937 if(status
==U_BUFFER_OVERFLOW_ERROR
)
940 testCtry
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
941 uloc_getDisplayCountry(testLocale
, displayLocale
, testCtry
, maxresultsize
+ 1, &status
);
947 if(U_FAILURE(status
)){
948 log_err("Error in getDisplayCountry() %s\n", myErrorName(status
));
952 maxresultsize
=uloc_getDisplayVariant(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
953 if(status
==U_BUFFER_OVERFLOW_ERROR
)
956 testVar
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
957 uloc_getDisplayVariant(testLocale
, displayLocale
, testVar
, maxresultsize
+ 1, &status
);
963 if(U_FAILURE(status
)){
964 log_err("Error in getDisplayVariant() %s\n", myErrorName(status
));
968 maxresultsize
=uloc_getDisplayName(testLocale
, displayLocale
, NULL
, maxresultsize
, &status
);
969 if(status
==U_BUFFER_OVERFLOW_ERROR
)
972 testName
=(UChar
*)malloc(sizeof(UChar
) * (maxresultsize
+1));
973 uloc_getDisplayName(testLocale
, displayLocale
, testName
, maxresultsize
+ 1, &status
);
979 if(U_FAILURE(status
)){
980 log_err("Error in getDisplayName() %s\n", myErrorName(status
));
983 expectedLang
=dataTable
[compareIndex
][i
];
984 if(u_strlen(expectedLang
)== 0)
985 expectedLang
=dataTable
[DLANG_EN
][i
];
987 expectedScript
=dataTable
[compareIndex
+ 1][i
];
988 if(u_strlen(expectedScript
)== 0)
989 expectedScript
=dataTable
[DSCRIPT_EN
][i
];
991 expectedCtry
=dataTable
[compareIndex
+ 2][i
];
992 if(u_strlen(expectedCtry
)== 0)
993 expectedCtry
=dataTable
[DCTRY_EN
][i
];
995 expectedVar
=dataTable
[compareIndex
+ 3][i
];
996 if(u_strlen(expectedVar
)== 0)
997 expectedVar
=dataTable
[DVAR_EN
][i
];
999 expectedName
=dataTable
[compareIndex
+ 4][i
];
1000 if(u_strlen(expectedName
) == 0)
1001 expectedName
=dataTable
[DNAME_EN
][i
];
1003 if (0 !=u_strcmp(testLang
,expectedLang
)) {
1004 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang
), austrdup(expectedLang
), displayLocale
);
1007 if (0 != u_strcmp(testScript
,expectedScript
)) {
1008 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript
), austrdup(expectedScript
), displayLocale
);
1011 if (0 != u_strcmp(testCtry
,expectedCtry
)) {
1012 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry
), austrdup(expectedCtry
), displayLocale
);
1015 if (0 != u_strcmp(testVar
,expectedVar
)) {
1016 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar
), austrdup(expectedVar
), displayLocale
);
1019 if(0 != u_strcmp(testName
, expectedName
)) {
1020 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName
), austrdup(expectedName
), displayLocale
);
1023 if(testName
!=&_NUL
) {
1026 if(testLang
!=&_NUL
) {
1029 if(testScript
!=&_NUL
) {
1032 if(testCtry
!=&_NUL
) {
1035 if(testVar
!=&_NUL
) {
1042 /*------------------------------
1043 * TestDisplayNameBrackets
1047 const char * displayLocale
;
1048 const char * namedRegion
;
1049 const char * namedLocale
;
1050 const char * regionName
;
1051 const char * ulocLocaleName
;
1052 const char * uldnLocaleName
;
1053 } DisplayNameBracketsItem
;
1055 static const DisplayNameBracketsItem displayNameBracketsItems
[] = {
1056 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)", "English (Cocos [Keeling] Islands)" },
1057 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])", "Burmese (Myanmar)" },
1058 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])", "Burmese (Myanmar, Myanmar)" },
1059 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B",
1060 "\\u82F1\\u6587\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09",
1061 "\\u82F1\\u6587\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" },
1062 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09",
1063 "\\u6CD5\\u6587\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09",
1064 "\\u6CD5\\u6587\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" },
1065 { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}
1068 enum { kDisplayNameBracketsMax
= 128 };
1070 static void TestDisplayNameBrackets()
1072 const DisplayNameBracketsItem
* itemPtr
= displayNameBracketsItems
;
1073 for (; itemPtr
->displayLocale
!= NULL
; itemPtr
++) {
1074 ULocaleDisplayNames
* uldn
;
1076 UChar expectRegionName
[kDisplayNameBracketsMax
];
1077 UChar expectUlocLocaleName
[kDisplayNameBracketsMax
];
1078 UChar expectUldnLocaleName
[kDisplayNameBracketsMax
];
1079 UChar getName
[kDisplayNameBracketsMax
];
1082 (void) u_unescape(itemPtr
->regionName
, expectRegionName
, kDisplayNameBracketsMax
);
1083 (void) u_unescape(itemPtr
->ulocLocaleName
, expectUlocLocaleName
, kDisplayNameBracketsMax
);
1084 (void) u_unescape(itemPtr
->uldnLocaleName
, expectUldnLocaleName
, kDisplayNameBracketsMax
);
1086 status
= U_ZERO_ERROR
;
1087 ulen
= uloc_getDisplayCountry(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1088 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1089 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1092 status
= U_ZERO_ERROR
;
1093 ulen
= uloc_getDisplayName(itemPtr
->namedLocale
, itemPtr
->displayLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1094 if ( U_FAILURE(status
) || u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1095 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1097 if ( U_FAILURE(status
) ) {
1098 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1099 } else if ( u_strcmp(getName
, expectUlocLocaleName
) != 0 ) {
1101 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1102 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1105 #if !UCONFIG_NO_FORMATTING
1106 status
= U_ZERO_ERROR
;
1107 uldn
= uldn_open(itemPtr
->displayLocale
, ULDN_STANDARD_NAMES
, &status
);
1108 if (U_SUCCESS(status
)) {
1109 status
= U_ZERO_ERROR
;
1110 ulen
= uldn_regionDisplayName(uldn
, itemPtr
->namedRegion
, getName
, kDisplayNameBracketsMax
, &status
);
1111 if ( U_FAILURE(status
) || u_strcmp(getName
, expectRegionName
) != 0 ) {
1112 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr
->displayLocale
, itemPtr
->namedRegion
, myErrorName(status
));
1115 status
= U_ZERO_ERROR
;
1116 ulen
= uldn_localeDisplayName(uldn
, itemPtr
->namedLocale
, getName
, kDisplayNameBracketsMax
, &status
);
1117 if ( U_FAILURE(status
) ) {
1118 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected status %s\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, myErrorName(status
));
1119 } else if ( u_strcmp(getName
, expectUldnLocaleName
) != 0 ) {
1121 u_strToUTF8(bbuf
, 128, NULL
, getName
, ulen
, &status
);
1122 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %-10s returns unexpected name (len %d): \"%s\"\n", itemPtr
->displayLocale
, itemPtr
->namedLocale
, ulen
, bbuf
);
1127 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr
->displayLocale
, u_errorName(status
));
1130 (void)ulen
; /* Suppress variable not used warning */
1134 /*------------------------------
1138 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1139 /* test for uloc_getISOLanguages, uloc_getISOCountries */
1140 static void TestISOFunctions()
1142 const char* const* str
=uloc_getISOLanguages();
1143 const char* const* str1
=uloc_getISOCountries();
1145 const char *key
= NULL
;
1146 int32_t count
= 0, skipped
= 0;
1148 UResourceBundle
*res
;
1149 UResourceBundle
*subRes
;
1150 UErrorCode status
= U_ZERO_ERROR
;
1152 /* test getISOLanguages*/
1153 /*str=uloc_getISOLanguages(); */
1154 log_verbose("Testing ISO Languages: \n");
1156 /* use structLocale - this data is no longer in root */
1157 res
= ures_openDirect(loadTestData(&status
), "structLocale", &status
);
1158 subRes
= ures_getByKey(res
, "Languages", NULL
, &status
);
1159 if (U_FAILURE(status
)) {
1160 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status
));
1164 expect
= ures_getSize(subRes
);
1165 for(count
= 0; *(str
+count
) != 0; count
++)
1168 test
= *(str
+count
);
1169 status
= U_ZERO_ERROR
;
1172 /* Skip over language tags. This API only returns language codes. */
1173 skipped
+= (key
!= NULL
);
1174 ures_getNextString(subRes
, NULL
, &key
, &status
);
1176 while (key
!= NULL
&& strchr(key
, '_'));
1180 /* TODO: Consider removing sh, which is deprecated */
1181 if(strcmp(key
,"root") == 0 || strcmp(key
,"Fallback") == 0 || strcmp(key
,"sh") == 0) {
1182 ures_getNextString(subRes
, NULL
, &key
, &status
);
1185 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1186 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1187 if(strcmp(test
,key
)) {
1188 /* The first difference usually implies the place where things get out of sync */
1189 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1193 if(!strcmp(test
,"in"))
1194 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1195 if(!strcmp(test
,"iw"))
1196 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1197 if(!strcmp(test
,"ji"))
1198 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1199 if(!strcmp(test
,"jw"))
1200 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1201 if(!strcmp(test
,"sh"))
1202 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test
);
1205 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1208 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count
, expect
);
1211 subRes
= ures_getByKey(res
, "Countries", subRes
, &status
);
1212 log_verbose("Testing ISO Countries");
1214 expect
= ures_getSize(subRes
) - 1; /* Skip ZZ */
1215 for(count
= 0; *(str1
+count
) != 0; count
++)
1218 test
= *(str1
+count
);
1220 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1221 skipped
+= (key
!= NULL
);
1222 ures_getNextString(subRes
, NULL
, &key
, &status
);
1224 while (key
!= NULL
&& strlen(key
) != 2);
1228 /* TODO: Consider removing CS, which is deprecated */
1229 while(strcmp(key
,"QO") == 0 || strcmp(key
,"QU") == 0 || strcmp(key
,"CS") == 0) {
1230 ures_getNextString(subRes
, NULL
, &key
, &status
);
1233 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1234 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1235 if(strcmp(test
,key
)) {
1236 /* The first difference usually implies the place where things get out of sync */
1237 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count
, test
, key
);
1240 if(!strcmp(test
,"FX"))
1241 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1242 if(!strcmp(test
,"YU"))
1243 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1244 if(!strcmp(test
,"ZR"))
1245 log_err("FAIL getISOCountries() has obsolete country code %s\n", test
);
1248 ures_getNextString(subRes
, NULL
, &key
, &status
);
1249 if (strcmp(key
, "ZZ") != 0) {
1250 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key
);
1252 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1253 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1256 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1257 skipped
+= (key
!= NULL
);
1258 ures_getNextString(subRes
, NULL
, &key
, &status
);
1260 while (U_SUCCESS(status
) && key
!= NULL
&& strlen(key
) != 2);
1262 expect
-= skipped
; /* Ignore the skipped resources from structLocale */
1265 log_err("There is an error in getISOCountries, got %d, expected %d \n", count
, expect
);
1272 static void setUpDataTable()
1275 dataTable
= (UChar
***)(calloc(sizeof(UChar
**),LOCALE_INFO_SIZE
));
1277 for (i
= 0; i
< LOCALE_INFO_SIZE
; i
++) {
1278 dataTable
[i
] = (UChar
**)(calloc(sizeof(UChar
*),LOCALE_SIZE
));
1279 for (j
= 0; j
< LOCALE_SIZE
; j
++){
1280 dataTable
[i
][j
] = CharsToUChars(rawData2
[i
][j
]);
1285 static void cleanUpDataTable()
1288 if(dataTable
!= NULL
) {
1289 for (i
=0; i
<LOCALE_INFO_SIZE
; i
++) {
1290 for(j
= 0; j
< LOCALE_SIZE
; j
++) {
1291 free(dataTable
[i
][j
]);
1301 * @bug 4011756 4011380
1303 static void TestISO3Fallback()
1305 const char* test
="xx_YY";
1307 const char * result
;
1309 result
= uloc_getISO3Language(test
);
1311 /* Conform to C API usage */
1313 if (!result
|| (result
[0] != 0))
1314 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1316 result
= uloc_getISO3Country(test
);
1318 if (!result
|| (result
[0] != 0))
1319 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1325 static void TestSimpleDisplayNames()
1328 This test is different from TestDisplayNames because TestDisplayNames checks
1329 fallback behavior, combination of language and country names to form locale
1330 names, and other stuff like that. This test just checks specific language
1331 and country codes to make sure we have the correct names for them.
1333 char languageCodes
[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1334 const char* languageNames
[] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1336 const char* inLocale
[] = { "en_US", "zh_Hant"};
1337 UErrorCode status
=U_ZERO_ERROR
;
1340 int32_t localeIndex
= 0;
1341 for (i
= 0; i
< 7; i
++) {
1343 UChar
*expectedLang
=0;
1347 localeIndex
= 1; /* Use the second locale for the rest of the test. */
1350 size
=uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], NULL
, size
, &status
);
1351 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1352 status
=U_ZERO_ERROR
;
1353 testLang
=(UChar
*)malloc(sizeof(UChar
) * (size
+ 1));
1354 uloc_getDisplayLanguage(languageCodes
[i
], inLocale
[localeIndex
], testLang
, size
+ 1, &status
);
1356 expectedLang
=(UChar
*)malloc(sizeof(UChar
) * (strlen(languageNames
[i
])+1));
1357 u_uastrcpy(expectedLang
, languageNames
[i
]);
1358 if (u_strcmp(testLang
, expectedLang
) != 0)
1359 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1360 languageCodes
[i
], languageNames
[i
], austrdup(testLang
));
1370 static void TestUninstalledISO3Names()
1372 /* This test checks to make sure getISO3Language and getISO3Country work right
1373 even for locales that are not installed. */
1374 static const char iso2Languages
[][4] = { "am", "ba", "fy", "mr", "rn",
1376 static const char iso3Languages
[][5] = { "amh", "bak", "fry", "mar", "run",
1377 "ssw", "twi", "zul" };
1378 static const char iso2Countries
[][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1379 "ss_SB", "tw_TC", "zu_ZW" };
1380 static const char iso3Countries
[][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1381 "SLB", "TCA", "ZWE" };
1384 for (i
= 0; i
< 8; i
++) {
1385 UErrorCode err
= U_ZERO_ERROR
;
1387 test
= uloc_getISO3Language(iso2Languages
[i
]);
1388 if(strcmp(test
, iso3Languages
[i
]) !=0 || U_FAILURE(err
))
1389 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1390 iso2Languages
[i
], iso3Languages
[i
], test
, myErrorName(err
));
1392 for (i
= 0; i
< 8; i
++) {
1393 UErrorCode err
= U_ZERO_ERROR
;
1395 test
= uloc_getISO3Country(iso2Countries
[i
]);
1396 if(strcmp(test
, iso3Countries
[i
]) !=0 || U_FAILURE(err
))
1397 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1398 iso2Countries
[i
], iso3Countries
[i
], test
, myErrorName(err
));
1403 static void TestVariantParsing()
1405 static const char* en_US_custom
="en_US_De Anza_Cupertino_California_United States_Earth";
1406 static const char* dispName
="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1407 static const char* dispVar
="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1408 static const char* shortVariant
="fr_FR_foo";
1409 static const char* bogusVariant
="fr_FR__foo";
1410 static const char* bogusVariant2
="fr_FR_foo_";
1411 static const char* bogusVariant3
="fr_FR__foo_";
1414 UChar displayVar
[100];
1415 UChar displayName
[100];
1416 UErrorCode status
=U_ZERO_ERROR
;
1419 size
=uloc_getDisplayVariant(en_US_custom
, "en_US", NULL
, size
, &status
);
1420 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1421 status
=U_ZERO_ERROR
;
1422 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1423 uloc_getDisplayVariant(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1426 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1428 u_uastrcpy(displayVar
, dispVar
);
1429 if(u_strcmp(got
,displayVar
)!=0) {
1430 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar
, austrdup(got
));
1433 size
=uloc_getDisplayName(en_US_custom
, "en_US", NULL
, size
, &status
);
1434 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1435 status
=U_ZERO_ERROR
;
1436 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1437 uloc_getDisplayName(en_US_custom
, "en_US", got
, size
+ 1, &status
);
1440 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1442 u_uastrcpy(displayName
, dispName
);
1443 if(u_strcmp(got
,displayName
)!=0) {
1444 if (status
== U_USING_DEFAULT_WARNING
) {
1445 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status
));
1447 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName
, austrdup(got
));
1452 status
=U_ZERO_ERROR
;
1453 size
=uloc_getDisplayVariant(shortVariant
, NULL
, NULL
, size
, &status
);
1454 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1455 status
=U_ZERO_ERROR
;
1456 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1457 uloc_getDisplayVariant(shortVariant
, NULL
, got
, size
+ 1, &status
);
1460 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1462 if(strcmp(austrdup(got
),"FOO")!=0) {
1463 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got
));
1466 status
=U_ZERO_ERROR
;
1467 size
=uloc_getDisplayVariant(bogusVariant
, NULL
, NULL
, size
, &status
);
1468 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1469 status
=U_ZERO_ERROR
;
1470 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1471 uloc_getDisplayVariant(bogusVariant
, NULL
, got
, size
+ 1, &status
);
1474 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1476 if(strcmp(austrdup(got
),"_FOO")!=0) {
1477 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got
));
1480 status
=U_ZERO_ERROR
;
1481 size
=uloc_getDisplayVariant(bogusVariant2
, NULL
, NULL
, size
, &status
);
1482 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1483 status
=U_ZERO_ERROR
;
1484 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1485 uloc_getDisplayVariant(bogusVariant2
, NULL
, got
, size
+ 1, &status
);
1488 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1490 if(strcmp(austrdup(got
),"FOO_")!=0) {
1491 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got
));
1494 status
=U_ZERO_ERROR
;
1495 size
=uloc_getDisplayVariant(bogusVariant3
, NULL
, NULL
, size
, &status
);
1496 if(status
==U_BUFFER_OVERFLOW_ERROR
) {
1497 status
=U_ZERO_ERROR
;
1498 got
=(UChar
*)realloc(got
, sizeof(UChar
) * (size
+1));
1499 uloc_getDisplayVariant(bogusVariant3
, NULL
, got
, size
+ 1, &status
);
1502 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1504 if(strcmp(austrdup(got
),"_FOO_")!=0) {
1505 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got
));
1511 static void TestObsoleteNames(void)
1514 UErrorCode status
= U_ZERO_ERROR
;
1526 { "eng_USA", "eng", "en", "USA", "US" },
1527 { "kok", "kok", "kok", "", "" },
1528 { "in", "ind", "in", "", "" },
1529 { "id", "ind", "id", "", "" }, /* NO aliasing */
1530 { "sh", "srp", "sh", "", "" },
1531 { "zz_CS", "", "zz", "SCG", "CS" },
1532 { "zz_FX", "", "zz", "FXX", "FX" },
1533 { "zz_RO", "", "zz", "ROU", "RO" },
1534 { "zz_TP", "", "zz", "TMP", "TP" },
1535 { "zz_TL", "", "zz", "TLS", "TL" },
1536 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1537 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1538 { "zz_ROM", "", "zz", "ROU", "RO" },
1539 { "zz_ROU", "", "zz", "ROU", "RO" },
1540 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1541 { "zz_TMP", "", "zz", "TMP", "TP" },
1542 { "zz_TLS", "", "zz", "TLS", "TL" },
1543 { "zz_YUG", "", "zz", "YUG", "YU" },
1544 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1545 { "iw", "heb", "iw", "", "" },
1546 { "ji", "yid", "ji", "", "" },
1547 { "jw", "jaw", "jw", "", "" },
1548 { "sh", "srp", "sh", "", "" },
1549 { "", "", "", "", "" }
1552 for(i
=0;tests
[i
].locale
[0];i
++)
1556 locale
= tests
[i
].locale
;
1557 log_verbose("** %s:\n", locale
);
1559 status
= U_ZERO_ERROR
;
1560 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1562 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1563 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1567 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1568 uloc_getISO3Language(locale
) );
1571 status
= U_ZERO_ERROR
;
1572 uloc_getLanguage(locale
, buff
, 256, &status
);
1573 if(U_FAILURE(status
))
1575 log_err("FAIL: error getting language from %s\n", locale
);
1579 if(strcmp(buff
,tests
[i
].lang
))
1581 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1582 locale
, buff
, tests
[i
].lang
);
1586 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale
, buff
);
1589 if(strcmp(tests
[i
].lang3
,uloc_getISO3Language(locale
)))
1591 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1592 locale
, uloc_getISO3Language(locale
), tests
[i
].lang3
);
1596 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1597 uloc_getISO3Language(locale
) );
1600 if(strcmp(tests
[i
].ctry3
,uloc_getISO3Country(locale
)))
1602 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1603 locale
, uloc_getISO3Country(locale
), tests
[i
].ctry3
);
1607 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1608 uloc_getISO3Country(locale
) );
1611 status
= U_ZERO_ERROR
;
1612 uloc_getCountry(locale
, buff
, 256, &status
);
1613 if(U_FAILURE(status
))
1615 log_err("FAIL: error getting country from %s\n", locale
);
1619 if(strcmp(buff
,tests
[i
].ctry
))
1621 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1622 locale
, buff
, tests
[i
].ctry
);
1626 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale
, buff
);
1631 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1632 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1635 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1636 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1641 i
= uloc_getLanguage("kok",NULL
,0,&icu_err
);
1642 if(U_FAILURE(icu_err
))
1644 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err
));
1647 icu_err
= U_ZERO_ERROR
;
1648 uloc_getLanguage("kok",r1_buff
,12,&icu_err
);
1649 if(U_FAILURE(icu_err
))
1651 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err
));
1654 r1_addr
= (char *)uloc_getISO3Language("kok");
1656 icu_err
= U_ZERO_ERROR
;
1657 if (strcmp(r1_buff
,"kok") != 0)
1659 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff
);
1662 r1_addr
= (char *)uloc_getISO3Language("in");
1663 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1664 if (strcmp(r1_buff
,"id") != 0)
1666 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1669 r1_addr
= (char *)uloc_getISO3Language("sh");
1670 i
= uloc_getLanguage(r1_addr
,r1_buff
,12,&icu_err
);
1671 if (strcmp(r1_buff
,"sr") != 0)
1673 printf("uloc_getLanguage error (%s)\n",r1_buff
);
1677 r1_addr
= (char *)uloc_getISO3Country("zz_ZR");
1678 strcpy(p1_buff
,"zz_");
1679 strcat(p1_buff
,r1_addr
);
1680 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1681 if (strcmp(r1_buff
,"ZR") != 0)
1683 printf("uloc_getCountry error (%s)\n",r1_buff
);
1686 r1_addr
= (char *)uloc_getISO3Country("zz_FX");
1687 strcpy(p1_buff
,"zz_");
1688 strcat(p1_buff
,r1_addr
);
1689 i
= uloc_getCountry(p1_buff
,r1_buff
,12,&icu_err
);
1690 if (strcmp(r1_buff
,"FX") != 0)
1692 printf("uloc_getCountry error (%s)\n",r1_buff
);
1700 static void TestKeywordVariants(void)
1702 static const struct {
1703 const char *localeID
;
1704 const char *expectedLocaleID
;
1705 const char *expectedLocaleIDNoKeywords
;
1706 const char *expectedCanonicalID
;
1707 const char *expectedKeywords
[10];
1708 int32_t numKeywords
;
1709 UErrorCode expectedStatus
; /* from uloc_openKeywords */
1712 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1713 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1715 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1716 {"calendar", "collation", "currency"},
1724 "de_DE@currency=EUR",
1725 {"","","","","","",""},
1727 U_INVALID_FORMAT_ERROR
/* must have '=' after '@' */
1730 "de_DE@euro;collation=phonebook",
1731 "de_DE", /* error result; bad format */
1732 "de_DE", /* error result; bad format */
1733 "de_DE", /* error result; bad format */
1734 {"","","","","","",""},
1736 U_INVALID_FORMAT_ERROR
1739 UErrorCode status
= U_ZERO_ERROR
;
1741 int32_t i
= 0, j
= 0;
1742 int32_t resultLen
= 0;
1744 UEnumeration
*keywords
;
1745 int32_t keyCount
= 0;
1746 const char *keyword
= NULL
;
1747 int32_t keywordLen
= 0;
1749 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
1750 status
= U_ZERO_ERROR
;
1752 keywords
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
1754 if(status
!= testCases
[i
].expectedStatus
) {
1755 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1756 testCases
[i
].localeID
,
1757 u_errorName(testCases
[i
].expectedStatus
), u_errorName(status
));
1759 status
= U_ZERO_ERROR
;
1761 if((keyCount
= uenum_count(keywords
, &status
)) != testCases
[i
].numKeywords
) {
1762 log_err("Expected to get %i keywords, got %i\n", testCases
[i
].numKeywords
, keyCount
);
1766 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1767 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1768 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1773 uenum_reset(keywords
, &status
);
1774 while((keyword
= uenum_next(keywords
, &keywordLen
, &status
))) {
1775 if(strcmp(keyword
, testCases
[i
].expectedKeywords
[j
]) != 0) {
1776 log_err("Expected to get keyword value %s, got %s\n", testCases
[i
].expectedKeywords
[j
], keyword
);
1781 uenum_close(keywords
);
1783 resultLen
= uloc_getName(testCases
[i
].localeID
, buffer
, 256, &status
);
1784 (void)resultLen
; /* Suppress set but not used warning. */
1785 if (uprv_strcmp(testCases
[i
].expectedLocaleID
, buffer
) != 0) {
1786 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1787 testCases
[i
].localeID
, testCases
[i
].expectedLocaleID
, buffer
);
1789 resultLen
= uloc_canonicalize(testCases
[i
].localeID
, buffer
, 256, &status
);
1790 if (uprv_strcmp(testCases
[i
].expectedCanonicalID
, buffer
) != 0) {
1791 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1792 testCases
[i
].localeID
, testCases
[i
].expectedCanonicalID
, buffer
);
1798 static void TestKeywordVariantParsing(void)
1800 static const struct {
1801 const char *localeID
;
1802 const char *keyword
;
1803 const char *expectedValue
;
1805 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
1806 { "de_DE", "collation", ""},
1807 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1808 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1811 UErrorCode status
= U_ZERO_ERROR
;
1814 int32_t resultLen
= 0;
1817 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
1819 resultLen
= uloc_getKeywordValue(testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
, 256, &status
);
1820 (void)resultLen
; /* Suppress set but not used warning. */
1821 if(uprv_strcmp(testCases
[i
].expectedValue
, buffer
) != 0) {
1822 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1823 testCases
[i
].expectedValue
, testCases
[i
].localeID
, testCases
[i
].keyword
, buffer
);
1828 static const struct {
1829 const char *l
; /* locale */
1830 const char *k
; /* kw */
1831 const char *v
; /* value */
1832 const char *x
; /* expected */
1833 } kwSetTestCases
[] = {
1835 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1836 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1837 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1838 { "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 */
1839 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1840 { "de", "Currency", "CHF", "de@currency=CHF" },
1841 { "de", "Currency", "CHF", "de@currency=CHF" },
1843 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1844 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1845 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1846 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1847 { "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 */
1848 { "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 */
1849 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1850 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1853 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1854 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1855 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1856 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1857 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1858 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1859 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1860 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1861 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1865 /* 1. removal of item at end */
1866 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1867 { "de@collation=phonebook;currency=CHF", "currency", NULL
, "de@collation=phonebook" },
1868 /* 2. removal of item at beginning */
1869 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1870 { "de@collation=phonebook;currency=CHF", "collation", NULL
, "de@currency=CHF" },
1871 /* 3. removal of an item not there */
1872 { "de@collation=phonebook;currency=CHF", "calendar", NULL
, "de@collation=phonebook;currency=CHF" },
1873 /* 4. removal of only item */
1874 { "de@collation=phonebook", "collation", NULL
, "de" },
1876 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1880 static void TestKeywordSet(void)
1883 int32_t resultLen
= 0;
1888 for(i
= 0; i
< sizeof(kwSetTestCases
)/sizeof(kwSetTestCases
[0]); i
++) {
1889 UErrorCode status
= U_ZERO_ERROR
;
1890 memset(buffer
,'%',1023);
1891 strcpy(buffer
, kwSetTestCases
[i
].l
);
1893 uloc_canonicalize(kwSetTestCases
[i
].l
, cbuffer
, 1023, &status
);
1894 if(strcmp(buffer
,cbuffer
)) {
1895 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i
, cbuffer
, buffer
);
1897 /* sanity check test case results for canonicity */
1898 uloc_canonicalize(kwSetTestCases
[i
].x
, cbuffer
, 1023, &status
);
1899 if(strcmp(kwSetTestCases
[i
].x
,cbuffer
)) {
1900 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__
, __LINE__
, i
, kwSetTestCases
[i
].x
, cbuffer
);
1903 resultLen
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, 1023, &status
);
1904 if(U_FAILURE(status
)) {
1905 log_err("Err on test case %d: got error %s\n", i
, u_errorName(status
));
1908 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=resultLen
)) {
1909 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
1910 kwSetTestCases
[i
].v
, buffer
, resultLen
, kwSetTestCases
[i
].x
, strlen(buffer
));
1912 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,buffer
);
1917 static void TestKeywordSetError(void)
1925 /* 0-test whether an error condition modifies the buffer at all */
1928 memset(buffer
,'%',1023);
1929 status
= U_ZERO_ERROR
;
1930 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1931 if(status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1932 log_err("expected illegal err got %s\n", u_errorName(status
));
1935 /* if(res!=strlen(kwSetTestCases[i].x)) {
1936 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1939 if(buffer
[blen
]!='%') {
1940 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
1943 log_verbose("0-buffer modify OK\n");
1946 /* 1- test a short buffer with growing text */
1947 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
1948 memset(buffer
,'%',1023);
1949 strcpy(buffer
,kwSetTestCases
[i
].l
);
1950 status
= U_ZERO_ERROR
;
1951 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1952 if(status
!= U_BUFFER_OVERFLOW_ERROR
) {
1953 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
);
1956 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
1957 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
1960 if(buffer
[blen
]!='%') {
1961 log_err("Buffer byte %d was modified: now %c\n", blen
, buffer
[blen
]);
1964 log_verbose("1/%d-buffer modify OK\n",i
);
1968 /* 2- test a short buffer - text the same size or shrinking */
1969 blen
=(int32_t)strlen(kwSetTestCases
[i
].l
)+1;
1970 memset(buffer
,'%',1023);
1971 strcpy(buffer
,kwSetTestCases
[i
].l
);
1972 status
= U_ZERO_ERROR
;
1973 res
= uloc_setKeywordValue(kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
, buffer
, blen
, &status
);
1974 if(status
!= U_ZERO_ERROR
) {
1975 log_err("expected zero error got %s\n", u_errorName(status
));
1978 if(buffer
[blen
+1]!='%') {
1979 log_err("Buffer byte %d was modified: now %c\n", blen
+1, buffer
[blen
+1]);
1982 if(res
!=(int32_t)strlen(kwSetTestCases
[i
].x
)) {
1983 log_err("expected result %d got %d\n", strlen(kwSetTestCases
[i
].x
), res
);
1986 if(strcmp(buffer
,kwSetTestCases
[i
].x
) || ((int32_t)strlen(buffer
)!=res
)) {
1987 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
,
1988 kwSetTestCases
[i
].v
, buffer
, res
, kwSetTestCases
[i
].x
, strlen(buffer
));
1990 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i
, kwSetTestCases
[i
].l
, kwSetTestCases
[i
].k
, kwSetTestCases
[i
].v
,
1993 log_verbose("2/%d-buffer modify OK\n",i
);
1997 static int32_t _canonicalize(int32_t selector
, /* 0==getName, 1==canonicalize */
1998 const char* localeID
,
2000 int32_t resultCapacity
,
2002 /* YOU can change this to use function pointers if you like */
2005 return uloc_getName(localeID
, result
, resultCapacity
, ec
);
2007 return uloc_canonicalize(localeID
, result
, resultCapacity
, ec
);
2013 static void TestCanonicalization(void)
2015 static const struct {
2016 const char *localeID
; /* input */
2017 const char *getNameID
; /* expected getName() result */
2018 const char *canonicalID
; /* expected canonicalize() result */
2020 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2021 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2022 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2023 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
2024 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
2025 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
2026 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
2027 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
2028 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
2029 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
2030 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
2031 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
2032 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
2033 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
2034 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
2035 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
2036 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
2037 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
2038 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
2039 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
2040 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
2041 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
2042 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
2043 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
2044 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
2045 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
2046 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
2047 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
2048 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
2049 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
2050 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
2051 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2052 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2053 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
2054 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2055 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2056 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2057 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2058 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2059 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2060 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
2061 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2062 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2063 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2064 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
2065 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
2066 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
2067 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
2068 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
2069 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
2070 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
2072 /* posix behavior that used to be performed by getName */
2073 { "mr.utf8", "mr.utf8", "mr" },
2074 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2075 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2076 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2077 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2078 { "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 */
2080 /* fleshing out canonicalization */
2081 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2082 { "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" },
2083 /* already-canonical ids are not changed */
2084 { "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" },
2085 /* PRE_EURO and EURO conversions don't affect other keywords */
2086 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
2087 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
2088 /* currency keyword overrides PRE_EURO and EURO currency */
2089 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
2090 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
2091 /* norwegian is just too weird, if we handle things in their full generality */
2092 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2094 /* test cases reflecting internal resource bundle usage */
2095 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2096 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2097 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2098 { "ja_JP", "ja_JP", "ja_JP" },
2100 /* test case for "i-default" */
2101 { "i-default", "en@x=i-default", "en@x=i-default" }
2104 static const char* label
[] = { "getName", "canonicalize" };
2106 UErrorCode status
= U_ZERO_ERROR
;
2107 int32_t i
, j
, resultLen
= 0, origResultLen
;
2110 for (i
=0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2111 for (j
=0; j
<2; ++j
) {
2112 const char* expected
= (j
==0) ? testCases
[i
].getNameID
: testCases
[i
].canonicalID
;
2114 status
= U_ZERO_ERROR
;
2116 if (expected
== NULL
) {
2117 expected
= uloc_getDefault();
2120 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2121 origResultLen
= _canonicalize(j
, testCases
[i
].localeID
, NULL
, 0, &status
);
2122 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
2123 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2124 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2127 status
= U_ZERO_ERROR
;
2128 resultLen
= _canonicalize(j
, testCases
[i
].localeID
, buffer
, sizeof(buffer
), &status
);
2129 if (U_FAILURE(status
)) {
2130 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2131 label
[j
], testCases
[i
].localeID
, u_errorName(status
));
2134 if(uprv_strcmp(expected
, buffer
) != 0) {
2135 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2136 label
[j
], testCases
[i
].localeID
, buffer
, expected
);
2138 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2139 label
[j
], testCases
[i
].localeID
, buffer
);
2141 if (resultLen
!= (int32_t)strlen(buffer
)) {
2142 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2143 label
[j
], testCases
[i
].localeID
, resultLen
, strlen(buffer
));
2145 if (origResultLen
!= resultLen
) {
2146 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2147 label
[j
], testCases
[i
].localeID
, origResultLen
, resultLen
);
2153 static void TestDisplayKeywords(void)
2157 static const struct {
2158 const char *localeID
;
2159 const char *displayLocale
;
2160 UChar displayKeyword
[200];
2162 { "ca_ES@currency=ESP", "de_AT",
2163 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2165 { "ja_JP@calendar=japanese", "de",
2166 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2168 { "de_DE@collation=traditional", "de_DE",
2169 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2172 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2173 UErrorCode status
= U_ZERO_ERROR
;
2174 const char* keyword
=NULL
;
2175 int32_t keywordLen
= 0;
2176 int32_t keywordCount
= 0;
2177 UChar
*displayKeyword
=NULL
;
2178 int32_t displayKeywordLen
= 0;
2179 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2180 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2181 if(U_FAILURE(status
)){
2182 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases
[i
].localeID
, u_errorName(status
));
2185 /* the uenum_next returns NUL terminated string */
2186 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2187 /* fetch the displayKeyword */
2188 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2189 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2190 status
= U_ZERO_ERROR
;
2191 displayKeywordLen
++; /* for null termination */
2192 displayKeyword
= (UChar
*) malloc(displayKeywordLen
* U_SIZEOF_UCHAR
);
2193 displayKeywordLen
= uloc_getDisplayKeyword(keyword
, testCases
[i
].displayLocale
, displayKeyword
, displayKeywordLen
, &status
);
2194 if(U_FAILURE(status
)){
2195 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
));
2198 if(u_strncmp(displayKeyword
, testCases
[i
].displayKeyword
, displayKeywordLen
)!=0){
2199 if (status
== U_USING_DEFAULT_WARNING
) {
2200 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
));
2202 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
);
2207 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status
));
2210 free(displayKeyword
);
2213 uenum_close(keywordEnum
);
2217 static void TestDisplayKeywordValues(void){
2220 static const struct {
2221 const char *localeID
;
2222 const char *displayLocale
;
2223 UChar displayKeywordValue
[500];
2225 { "ca_ES@currency=ESP", "de_AT",
2226 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2228 { "de_AT@currency=ATS", "fr_FR",
2229 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2231 { "de_DE@currency=DEM", "it",
2232 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2234 { "el_GR@currency=GRD", "en",
2235 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2237 { "eu_ES@currency=ESP", "it_IT",
2238 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2240 { "de@collation=phonebook", "es",
2241 {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}
2244 { "de_DE@collation=phonebook", "es",
2245 {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}
2247 { "es_ES@collation=traditional","de",
2248 {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}
2250 { "ja_JP@calendar=japanese", "de",
2251 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2254 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2255 UErrorCode status
= U_ZERO_ERROR
;
2256 const char* keyword
=NULL
;
2257 int32_t keywordLen
= 0;
2258 int32_t keywordCount
= 0;
2259 UChar
*displayKeywordValue
= NULL
;
2260 int32_t displayKeywordValueLen
= 0;
2261 UEnumeration
* keywordEnum
= uloc_openKeywords(testCases
[i
].localeID
, &status
);
2262 for(keywordCount
= uenum_count(keywordEnum
, &status
); keywordCount
> 0 ; keywordCount
--){
2263 if(U_FAILURE(status
)){
2264 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
));
2267 /* the uenum_next returns NUL terminated string */
2268 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2270 /* fetch the displayKeywordValue */
2271 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2272 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2273 status
= U_ZERO_ERROR
;
2274 displayKeywordValueLen
++; /* for null termination */
2275 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2276 displayKeywordValueLen
= uloc_getDisplayKeywordValue(testCases
[i
].localeID
, keyword
, testCases
[i
].displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2277 if(U_FAILURE(status
)){
2278 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
));
2281 if(u_strncmp(displayKeywordValue
, testCases
[i
].displayKeywordValue
, displayKeywordValueLen
)!=0){
2282 if (status
== U_USING_DEFAULT_WARNING
) {
2283 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
));
2285 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
));
2290 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2292 free(displayKeywordValue
);
2294 uenum_close(keywordEnum
);
2297 /* test a multiple keywords */
2298 UErrorCode status
= U_ZERO_ERROR
;
2299 const char* keyword
=NULL
;
2300 int32_t keywordLen
= 0;
2301 int32_t keywordCount
= 0;
2302 const char* localeID
= "es@collation=phonebook;calendar=buddhist;currency=DEM";
2303 const char* displayLocale
= "de";
2304 static const UChar expected
[][50] = {
2305 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2307 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2308 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2311 UEnumeration
* keywordEnum
= uloc_openKeywords(localeID
, &status
);
2313 for(keywordCount
= 0; keywordCount
< uenum_count(keywordEnum
, &status
) ; keywordCount
++){
2314 UChar
*displayKeywordValue
= NULL
;
2315 int32_t displayKeywordValueLen
= 0;
2316 if(U_FAILURE(status
)){
2317 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID
, displayLocale
, u_errorName(status
));
2320 /* the uenum_next returns NUL terminated string */
2321 keyword
= uenum_next(keywordEnum
, &keywordLen
, &status
);
2323 /* fetch the displayKeywordValue */
2324 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2325 if(status
==U_BUFFER_OVERFLOW_ERROR
){
2326 status
= U_ZERO_ERROR
;
2327 displayKeywordValueLen
++; /* for null termination */
2328 displayKeywordValue
= (UChar
*)malloc(displayKeywordValueLen
* U_SIZEOF_UCHAR
);
2329 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, keyword
, displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2330 if(U_FAILURE(status
)){
2331 log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID
, keyword
, displayLocale
, u_errorName(status
));
2334 if(u_strncmp(displayKeywordValue
, expected
[keywordCount
], displayKeywordValueLen
)!=0){
2335 if (status
== U_USING_DEFAULT_WARNING
) {
2336 log_data_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s got error: %s. Perhaps you are missing data?\n", localeID
, keyword
, displayLocale
, u_errorName(status
));
2338 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID
, keyword
, displayLocale
);
2343 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status
));
2345 free(displayKeywordValue
);
2347 uenum_close(keywordEnum
);
2351 /* Test non existent keywords */
2352 UErrorCode status
= U_ZERO_ERROR
;
2353 const char* localeID
= "es";
2354 const char* displayLocale
= "de";
2355 UChar
*displayKeywordValue
= NULL
;
2356 int32_t displayKeywordValueLen
= 0;
2358 /* fetch the displayKeywordValue */
2359 displayKeywordValueLen
= uloc_getDisplayKeywordValue(localeID
, "calendar", displayLocale
, displayKeywordValue
, displayKeywordValueLen
, &status
);
2360 if(U_FAILURE(status
)) {
2361 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status
));
2362 } else if(displayKeywordValueLen
!= 0) {
2363 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen
);
2369 static void TestGetBaseName(void) {
2370 static const struct {
2371 const char *localeID
;
2372 const char *baseName
;
2374 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2375 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2376 { "ja@calendar = buddhist", "ja" }
2379 int32_t i
= 0, baseNameLen
= 0;
2381 UErrorCode status
= U_ZERO_ERROR
;
2383 for(i
= 0; i
< sizeof(testCases
)/sizeof(testCases
[0]); i
++) {
2384 baseNameLen
= uloc_getBaseName(testCases
[i
].localeID
, baseName
, 256, &status
);
2385 (void)baseNameLen
; /* Suppress set but not used warning. */
2386 if(strcmp(testCases
[i
].baseName
, baseName
)) {
2387 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2388 testCases
[i
].localeID
, testCases
[i
].baseName
, baseName
);
2394 static void TestTrailingNull(void) {
2395 const char* localeId
= "zh_Hans";
2396 UChar buffer
[128]; /* sufficient for this test */
2398 UErrorCode status
= U_ZERO_ERROR
;
2401 len
= uloc_getDisplayName(localeId
, localeId
, buffer
, 128, &status
);
2403 log_err("buffer too small");
2407 for (i
= 0; i
< len
; ++i
) {
2408 if (buffer
[i
] == 0) {
2409 log_err("name contained null");
2415 /* Jitterbug 4115 */
2416 static void TestDisplayNameWarning(void) {
2419 UErrorCode status
= U_ZERO_ERROR
;
2421 size
= uloc_getDisplayLanguage("qqq", "kl", name
, sizeof(name
)/sizeof(name
[0]), &status
);
2422 (void)size
; /* Suppress set but not used warning. */
2423 if (status
!= U_USING_DEFAULT_WARNING
) {
2424 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2425 u_errorName(status
));
2431 * Compare two locale IDs. If they are equal, return 0. If `string'
2432 * starts with `prefix' plus an additional element, that is, string ==
2433 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2435 static UBool
_loccmp(const char* string
, const char* prefix
) {
2436 int32_t slen
= (int32_t)uprv_strlen(string
),
2437 plen
= (int32_t)uprv_strlen(prefix
);
2438 int32_t c
= uprv_strncmp(string
, prefix
, plen
);
2439 /* 'root' is less than everything */
2440 if (uprv_strcmp(prefix
, "root") == 0) {
2441 return (uprv_strcmp(string
, "root") == 0) ? 0 : 1;
2443 if (c
) return -1; /* mismatch */
2444 if (slen
== plen
) return 0;
2445 if (string
[plen
] == '_') return 1;
2446 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2449 static void _checklocs(const char* label
,
2452 const char* actual
) {
2453 /* We want the valid to be strictly > the bogus requested locale,
2454 and the valid to be >= the actual. */
2455 if (_loccmp(req
, valid
) > 0 &&
2456 _loccmp(valid
, actual
) >= 0) {
2457 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2458 label
, req
, valid
, actual
);
2460 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2461 label
, req
, valid
, actual
);
2465 static void TestGetLocale(void) {
2466 UErrorCode ec
= U_ZERO_ERROR
;
2468 UChar EMPTY
[1] = {0};
2471 #if !UCONFIG_NO_FORMATTING
2474 const char *req
= "en_US_REDWOODSHORES", *valid
, *actual
;
2475 obj
= udat_open(UDAT_DEFAULT
, UDAT_DEFAULT
,
2479 if (U_FAILURE(ec
)) {
2480 log_data_err("udat_open failed.Error %s\n", u_errorName(ec
));
2483 valid
= udat_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2484 actual
= udat_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2485 if (U_FAILURE(ec
)) {
2486 log_err("udat_getLocaleByType() failed\n");
2489 _checklocs("udat", req
, valid
, actual
);
2495 #if !UCONFIG_NO_FORMATTING
2498 const char *req
= "fr_FR_PROVENCAL", *valid
, *actual
;
2499 obj
= ucal_open(NULL
, 0,
2503 if (U_FAILURE(ec
)) {
2504 log_err("ucal_open failed with error: %s\n", u_errorName(ec
));
2507 valid
= ucal_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2508 actual
= ucal_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2509 if (U_FAILURE(ec
)) {
2510 log_err("ucal_getLocaleByType() failed\n");
2513 _checklocs("ucal", req
, valid
, actual
);
2519 #if !UCONFIG_NO_FORMATTING
2522 const char *req
= "zh_Hant_TW_TAINAN", *valid
, *actual
;
2523 obj
= unum_open(UNUM_DECIMAL
,
2527 if (U_FAILURE(ec
)) {
2528 log_err("unum_open failed\n");
2531 valid
= unum_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2532 actual
= unum_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2533 if (U_FAILURE(ec
)) {
2534 log_err("unum_getLocaleByType() failed\n");
2537 _checklocs("unum", req
, valid
, actual
);
2544 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2545 #if !UCONFIG_NO_FORMATTING
2547 UMessageFormat
*obj
;
2548 const char *req
= "ja_JP_TAKAYAMA", *valid
, *actual
;
2550 obj
= umsg_open(EMPTY
, 0,
2553 if (U_FAILURE(ec
)) {
2554 log_err("umsg_open failed\n");
2557 valid
= umsg_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2558 actual
= umsg_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2559 if (U_FAILURE(ec
)) {
2560 log_err("umsg_getLocaleByType() failed\n");
2563 /* We want the valid to be strictly > the bogus requested locale,
2564 and the valid to be >= the actual. */
2565 /* TODO MessageFormat is currently just storing the locale it is given.
2566 As a result, it will return whatever it was given, even if the
2567 locale is invalid. */
2568 test
= (_cmpversion("3.2") <= 0) ?
2569 /* Here is the weakened test for 3.0: */
2570 (_loccmp(req
, valid
) >= 0) :
2571 /* Here is what the test line SHOULD be: */
2572 (_loccmp(req
, valid
) > 0);
2575 _loccmp(valid
, actual
) >= 0) {
2576 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2578 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req
, valid
, actual
);
2586 #if !UCONFIG_NO_BREAK_ITERATION
2588 UBreakIterator
*obj
;
2589 const char *req
= "ar_KW_ABDALI", *valid
, *actual
;
2590 obj
= ubrk_open(UBRK_WORD
,
2595 if (U_FAILURE(ec
)) {
2596 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec
));
2599 valid
= ubrk_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2600 actual
= ubrk_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2601 if (U_FAILURE(ec
)) {
2602 log_err("ubrk_getLocaleByType() failed\n");
2605 _checklocs("ubrk", req
, valid
, actual
);
2611 #if !UCONFIG_NO_COLLATION
2614 const char *req
= "es_AR_BUENOSAIRES", *valid
, *actual
;
2615 obj
= ucol_open(req
, &ec
);
2616 if (U_FAILURE(ec
)) {
2617 log_err("ucol_open failed - %s\n", u_errorName(ec
));
2620 valid
= ucol_getLocaleByType(obj
, ULOC_VALID_LOCALE
, &ec
);
2621 actual
= ucol_getLocaleByType(obj
, ULOC_ACTUAL_LOCALE
, &ec
);
2622 if (U_FAILURE(ec
)) {
2623 log_err("ucol_getLocaleByType() failed\n");
2626 _checklocs("ucol", req
, valid
, actual
);
2631 static void TestEnglishExemplarCharacters(void) {
2632 UErrorCode status
= U_ZERO_ERROR
;
2635 UChar testChars
[] = {
2636 0x61, /* standard */
2637 0xE1, /* auxiliary */
2639 0x2D /* punctuation */
2641 ULocaleData
*uld
= ulocdata_open("en", &status
);
2642 if (U_FAILURE(status
)) {
2643 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status
));
2647 for (i
= 0; i
< ULOCDATA_ES_COUNT
; i
++) {
2648 exSet
= ulocdata_getExemplarSet(uld
, exSet
, 0, (ULocaleDataExemplarSetType
)i
, &status
);
2649 if (U_FAILURE(status
)) {
2650 log_err_status(status
, "ulocdata_getExemplarSet() for type %d failed\n", i
);
2651 status
= U_ZERO_ERROR
;
2654 if (!uset_contains(exSet
, (UChar32
)testChars
[i
])) {
2655 log_err("Character U+%04X is not included in exemplar type %d\n", testChars
[i
], i
);
2660 ulocdata_close(uld
);
2663 static void TestNonexistentLanguageExemplars(void) {
2664 /* JB 4068 - Nonexistent language */
2665 UErrorCode ec
= U_ZERO_ERROR
;
2666 ULocaleData
*uld
= ulocdata_open("qqq",&ec
);
2667 if (ec
!= U_USING_DEFAULT_WARNING
) {
2668 log_err_status(ec
, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2671 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2672 ulocdata_close(uld
);
2675 static void TestLocDataErrorCodeChaining(void) {
2676 UErrorCode ec
= U_USELESS_COLLATOR_ERROR
;
2677 ulocdata_open(NULL
, &ec
);
2678 ulocdata_getExemplarSet(NULL
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
);
2679 ulocdata_getDelimiter(NULL
, ULOCDATA_DELIMITER_COUNT
, NULL
, -1, &ec
);
2680 ulocdata_getMeasurementSystem(NULL
, &ec
);
2681 ulocdata_getPaperSize(NULL
, NULL
, NULL
, &ec
);
2682 if (ec
!= U_USELESS_COLLATOR_ERROR
) {
2683 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec
));
2687 static void TestLanguageExemplarsFallbacks(void) {
2688 /* Test that en_US fallsback, but en doesn't fallback. */
2689 UErrorCode ec
= U_ZERO_ERROR
;
2690 ULocaleData
*uld
= ulocdata_open("en_US",&ec
);
2691 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2692 if (ec
!= U_USING_FALLBACK_WARNING
) {
2693 log_err_status(ec
, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2696 ulocdata_close(uld
);
2698 uld
= ulocdata_open("en",&ec
);
2699 uset_close(ulocdata_getExemplarSet(uld
, NULL
, 0, ULOCDATA_ES_STANDARD
, &ec
));
2700 if (ec
!= U_ZERO_ERROR
) {
2701 log_err_status(ec
, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2704 ulocdata_close(uld
);
2707 static const char *acceptResult(UAcceptResult uar
) {
2708 return udbg_enumName(UDBG_UAcceptResult
, uar
);
2711 static void TestAcceptLanguage(void) {
2712 UErrorCode status
= U_ZERO_ERROR
;
2713 UAcceptResult outResult
;
2714 UEnumeration
*available
;
2720 int32_t httpSet
; /**< Which of http[] should be used? */
2721 const char *icuSet
; /**< ? */
2722 const char *expect
; /**< The expected locale result */
2723 UAcceptResult res
; /**< The expected error code */
2725 /*0*/{ 0, NULL
, "mt_MT", ULOC_ACCEPT_VALID
},
2726 /*1*/{ 1, NULL
, "en", ULOC_ACCEPT_VALID
},
2727 /*2*/{ 2, NULL
, "en", ULOC_ACCEPT_FALLBACK
},
2728 /*3*/{ 3, NULL
, "", ULOC_ACCEPT_FAILED
},
2729 /*4*/{ 4, NULL
, "es", ULOC_ACCEPT_VALID
},
2731 /*5*/{ 5, NULL
, "en", ULOC_ACCEPT_VALID
}, /* XF */
2732 /*6*/{ 6, NULL
, "ja", ULOC_ACCEPT_FALLBACK
}, /* XF */
2733 /*7*/{ 7, NULL
, "zh", ULOC_ACCEPT_FALLBACK
}, /* XF */
2735 const int32_t numTests
= sizeof(tests
)/sizeof(tests
[0]);
2736 static const char *http
[] = {
2737 /*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",
2738 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2739 /*2*/ "en-wf, de-lx;q=0.8",
2740 /*3*/ "mga-ie;q=0.9, tlh",
2741 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2742 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2743 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2744 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2745 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2746 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2747 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2750 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2752 /*7*/ "zh-xx;q=0.9",
2755 for(i
=0;i
<numTests
;i
++) {
2757 status
=U_ZERO_ERROR
;
2758 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2759 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2761 available
= ures_openAvailableLocales(tests
[i
].icuSet
, &status
);
2763 rc
= uloc_acceptLanguageFromHTTP(tmp
, 199, &outResult
, http
[tests
[i
].httpSet
], available
, &status
);
2764 (void)rc
; /* Suppress set but not used warning. */
2765 uenum_close(available
);
2766 log_verbose(" got %s, %s [%s]\n", tmp
[0]?tmp
:"(EMPTY)", acceptResult(outResult
), u_errorName(status
));
2767 if(outResult
!= tests
[i
].res
) {
2768 log_err_status(status
, "FAIL: #%d: expected outResult of %s but got %s\n", i
,
2769 acceptResult( tests
[i
].res
),
2770 acceptResult( outResult
));
2771 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2772 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
,acceptResult(tests
[i
].res
));
2774 if((outResult
>0)&&uprv_strcmp(tmp
, tests
[i
].expect
)) {
2775 log_err_status(status
, "FAIL: #%d: expected %s but got %s\n", i
, tests
[i
].expect
, tmp
);
2776 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2777 i
, http
[tests
[i
].httpSet
], tests
[i
].icuSet
, tests
[i
].expect
, acceptResult(tests
[i
].res
));
2782 static const char* LOCALE_ALIAS
[][2] = {
2796 static UBool
isLocaleAvailable(UResourceBundle
* resIndex
, const char* loc
){
2797 UErrorCode status
= U_ZERO_ERROR
;
2799 ures_getStringByKey(resIndex
, loc
,&len
, &status
);
2800 if(U_FAILURE(status
)){
2806 static void TestCalendar() {
2807 #if !UCONFIG_NO_FORMATTING
2809 UErrorCode status
= U_ZERO_ERROR
;
2810 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2811 if(U_FAILURE(status
)){
2812 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2815 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2816 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2817 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2818 UCalendar
* c1
= NULL
;
2819 UCalendar
* c2
= NULL
;
2821 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2822 const char* l1
= ucal_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2823 const char* l2
= ucal_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2825 if(!isLocaleAvailable(resIndex
, newLoc
)){
2828 c1
= ucal_open(NULL
, -1, oldLoc
, UCAL_GREGORIAN
, &status
);
2829 c2
= ucal_open(NULL
, -1, newLoc
, UCAL_GREGORIAN
, &status
);
2831 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0 || status
!=U_ZERO_ERROR
) {
2832 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2834 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1
, l2
);
2838 ures_close(resIndex
);
2842 static void TestDateFormat() {
2843 #if !UCONFIG_NO_FORMATTING
2845 UErrorCode status
= U_ZERO_ERROR
;
2846 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2847 if(U_FAILURE(status
)){
2848 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2851 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2852 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2853 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2854 UDateFormat
* df1
= NULL
;
2855 UDateFormat
* df2
= NULL
;
2856 const char* l1
= NULL
;
2857 const char* l2
= NULL
;
2859 if(!isLocaleAvailable(resIndex
, newLoc
)){
2862 df1
= udat_open(UDAT_FULL
, UDAT_FULL
,oldLoc
, NULL
, 0, NULL
, -1, &status
);
2863 df2
= udat_open(UDAT_FULL
, UDAT_FULL
,newLoc
, NULL
, 0, NULL
, -1, &status
);
2864 if(U_FAILURE(status
)){
2865 log_err("Creation of date format failed %s\n", u_errorName(status
));
2868 /*Test function "getLocale"*/
2869 l1
= udat_getLocaleByType(df1
, ULOC_VALID_LOCALE
, &status
);
2870 l2
= udat_getLocaleByType(df2
, ULOC_VALID_LOCALE
, &status
);
2871 if(U_FAILURE(status
)){
2872 log_err("Fetching the locale by type failed. %s\n", u_errorName(status
));
2874 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
2875 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2877 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1
, l2
);
2881 ures_close(resIndex
);
2885 static void TestCollation() {
2886 #if !UCONFIG_NO_COLLATION
2888 UErrorCode status
= U_ZERO_ERROR
;
2889 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
2890 if(U_FAILURE(status
)){
2891 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
2894 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
2895 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
2896 const char* newLoc
= LOCALE_ALIAS
[i
][1];
2897 UCollator
* c1
= NULL
;
2898 UCollator
* c2
= NULL
;
2899 const char* l1
= NULL
;
2900 const char* l2
= NULL
;
2902 status
= U_ZERO_ERROR
;
2903 if(!isLocaleAvailable(resIndex
, newLoc
)){
2906 if(U_FAILURE(status
)){
2907 log_err("Creation of collators failed %s\n", u_errorName(status
));
2910 c1
= ucol_open(oldLoc
, &status
);
2911 c2
= ucol_open(newLoc
, &status
);
2912 l1
= ucol_getLocaleByType(c1
, ULOC_VALID_LOCALE
, &status
);
2913 l2
= ucol_getLocaleByType(c2
, ULOC_VALID_LOCALE
, &status
);
2914 if(U_FAILURE(status
)){
2915 log_err("Fetching the locale names failed failed %s\n", u_errorName(status
));
2917 if (strcmp(newLoc
,l1
)!=0 || strcmp(l1
,l2
)!=0) {
2918 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
2920 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1
, l2
);
2924 ures_close(resIndex
);
2928 typedef struct OrientationStructTag
{
2929 const char* localeId
;
2930 ULayoutType character
;
2932 } OrientationStruct
;
2934 static const char* ULayoutTypeToString(ULayoutType type
)
2938 case ULOC_LAYOUT_LTR
:
2939 return "ULOC_LAYOUT_LTR";
2941 case ULOC_LAYOUT_RTL
:
2942 return "ULOC_LAYOUT_RTL";
2944 case ULOC_LAYOUT_TTB
:
2945 return "ULOC_LAYOUT_TTB";
2947 case ULOC_LAYOUT_BTT
:
2948 return "ULOC_LAYOUT_BTT";
2950 case ULOC_LAYOUT_UNKNOWN
:
2954 return "Unknown enum value for ULayoutType!";
2957 static void TestOrientation()
2959 static const OrientationStruct toTest
[] = {
2960 { "ar", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2961 { "aR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2962 { "ar_Arab", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2963 { "fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2964 { "Fa", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2965 { "he", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2966 { "ps", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2967 { "ur", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2968 { "UR", ULOC_LAYOUT_RTL
, ULOC_LAYOUT_TTB
},
2969 { "en", ULOC_LAYOUT_LTR
, ULOC_LAYOUT_TTB
}
2973 for (; i
< sizeof(toTest
) / sizeof(toTest
[0]); ++i
) {
2974 UErrorCode statusCO
= U_ZERO_ERROR
;
2975 UErrorCode statusLO
= U_ZERO_ERROR
;
2976 const char* const localeId
= toTest
[i
].localeId
;
2977 const ULayoutType co
= uloc_getCharacterOrientation(localeId
, &statusCO
);
2978 const ULayoutType expectedCO
= toTest
[i
].character
;
2979 const ULayoutType lo
= uloc_getLineOrientation(localeId
, &statusLO
);
2980 const ULayoutType expectedLO
= toTest
[i
].line
;
2981 if (U_FAILURE(statusCO
)) {
2982 log_err_status(statusCO
,
2983 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
2985 u_errorName(statusCO
));
2987 else if (co
!= expectedCO
) {
2989 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2991 ULayoutTypeToString(expectedCO
),
2992 ULayoutTypeToString(co
));
2994 if (U_FAILURE(statusLO
)) {
2995 log_err_status(statusLO
,
2996 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
2998 u_errorName(statusLO
));
3000 else if (lo
!= expectedLO
) {
3002 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
3004 ULayoutTypeToString(expectedLO
),
3005 ULayoutTypeToString(lo
));
3010 static void TestULocale() {
3012 UErrorCode status
= U_ZERO_ERROR
;
3013 UResourceBundle
*resIndex
= ures_open(NULL
,"res_index", &status
);
3014 if(U_FAILURE(status
)){
3015 log_err_status(status
, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3018 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3019 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3020 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3021 UChar name1
[256], name2
[256];
3022 char names1
[256], names2
[256];
3023 int32_t capacity
= 256;
3025 status
= U_ZERO_ERROR
;
3026 if(!isLocaleAvailable(resIndex
, newLoc
)){
3029 uloc_getDisplayName(oldLoc
, ULOC_US
, name1
, capacity
, &status
);
3030 if(U_FAILURE(status
)){
3031 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc
, u_errorName(status
));
3034 uloc_getDisplayName(newLoc
, ULOC_US
, name2
, capacity
, &status
);
3035 if(U_FAILURE(status
)){
3036 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc
, u_errorName(status
));
3039 if (u_strcmp(name1
, name2
)!=0) {
3040 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3042 u_austrcpy(names1
, name1
);
3043 u_austrcpy(names2
, name2
);
3044 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1
, names2
);
3046 ures_close(resIndex
);
3050 static void TestUResourceBundle() {
3054 UResourceBundle
* rb1
= NULL
;
3055 UResourceBundle
* rb2
= NULL
;
3056 UErrorCode status
= U_ZERO_ERROR
;
3058 UResourceBundle
*resIndex
= NULL
;
3059 if(U_FAILURE(status
)){
3060 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status
));
3063 resIndex
= ures_open(NULL
,"res_index", &status
);
3064 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3066 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3067 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3068 if(!isLocaleAvailable(resIndex
, newLoc
)){
3071 rb1
= ures_open(NULL
, oldLoc
, &status
);
3072 if (U_FAILURE(status
)) {
3073 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3076 us1
= ures_getLocaleByType(rb1
, ULOC_ACTUAL_LOCALE
, &status
);
3078 status
= U_ZERO_ERROR
;
3079 rb2
= ures_open(NULL
, newLoc
, &status
);
3080 if (U_FAILURE(status
)) {
3081 log_err("ures_open(%s) failed %s\n", oldLoc
, u_errorName(status
));
3083 us2
= ures_getLocaleByType(rb2
, ULOC_ACTUAL_LOCALE
, &status
);
3085 if (strcmp(us1
,newLoc
)!=0 || strcmp(us1
,us2
)!=0 ) {
3086 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc
, newLoc
);
3089 log_verbose("ures_getStringByKey old:%s new:%s\n", us1
, us2
);
3095 ures_close(resIndex
);
3098 static void TestDisplayName() {
3100 UChar oldCountry
[256] = {'\0'};
3101 UChar newCountry
[256] = {'\0'};
3102 UChar oldLang
[256] = {'\0'};
3103 UChar newLang
[256] = {'\0'};
3104 char country
[256] ={'\0'};
3105 char language
[256] ={'\0'};
3106 int32_t capacity
= 256;
3109 for (i
=0; i
<UPRV_LENGTHOF(LOCALE_ALIAS
); i
++) {
3110 const char* oldLoc
= LOCALE_ALIAS
[i
][0];
3111 const char* newLoc
= LOCALE_ALIAS
[i
][1];
3112 UErrorCode status
= U_ZERO_ERROR
;
3113 int32_t available
= uloc_countAvailable();
3115 for(j
=0; j
<available
; j
++){
3117 const char* dispLoc
= uloc_getAvailable(j
);
3118 int32_t oldCountryLen
= uloc_getDisplayCountry(oldLoc
,dispLoc
, oldCountry
, capacity
, &status
);
3119 int32_t newCountryLen
= uloc_getDisplayCountry(newLoc
, dispLoc
, newCountry
, capacity
, &status
);
3120 int32_t oldLangLen
= uloc_getDisplayLanguage(oldLoc
, dispLoc
, oldLang
, capacity
, &status
);
3121 int32_t newLangLen
= uloc_getDisplayLanguage(newLoc
, dispLoc
, newLang
, capacity
, &status
);
3123 int32_t countryLen
= uloc_getCountry(newLoc
, country
, capacity
, &status
);
3124 int32_t langLen
= uloc_getLanguage(newLoc
, language
, capacity
, &status
);
3125 /* there is a display name for the current country ID */
3126 if(countryLen
!= newCountryLen
){
3127 if(u_strncmp(oldCountry
,newCountry
,oldCountryLen
)!=0){
3128 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc
, dispLoc
);
3131 /* there is a display name for the current lang ID */
3132 if(langLen
!=newLangLen
){
3133 if(u_strncmp(oldLang
,newLang
,oldLangLen
)){
3134 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc
, dispLoc
); }
3140 static void TestGetLocaleForLCID() {
3141 int32_t i
, length
, lengthPre
;
3142 const char* testLocale
= 0;
3143 UErrorCode status
= U_ZERO_ERROR
;
3144 char temp2
[40], temp3
[40];
3147 lcid
= uloc_getLCID("en_US");
3148 if (lcid
!= 0x0409) {
3149 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid
);
3152 lengthPre
= uloc_getLocaleForLCID(lcid
, temp2
, 4, &status
);
3153 if (status
!= U_BUFFER_OVERFLOW_ERROR
) {
3154 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status
));
3157 status
= U_ZERO_ERROR
;
3160 length
= uloc_getLocaleForLCID(lcid
, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3161 if (U_FAILURE(status
)) {
3162 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status
));
3163 status
= U_ZERO_ERROR
;
3166 if (length
!= lengthPre
) {
3167 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length
, lengthPre
);
3170 length
= uloc_getLocaleForLCID(0x12345, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3171 if (U_SUCCESS(status
)) {
3172 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2
, u_errorName(status
));
3174 status
= U_ZERO_ERROR
;
3176 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3177 for (i
= 0; i
< LOCALE_SIZE
; i
++) {
3179 testLocale
=rawData2
[NAME
][i
];
3181 log_verbose("Testing %s ......\n", testLocale
);
3183 sscanf(rawData2
[LCID
][i
], "%x", &lcid
);
3184 length
= uloc_getLocaleForLCID(lcid
, temp2
, sizeof(temp2
)/sizeof(char), &status
);
3185 if (U_FAILURE(status
)) {
3186 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid
, u_errorName(status
));
3187 status
= U_ZERO_ERROR
;
3191 if (length
!= uprv_strlen(temp2
)) {
3192 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length
, lcid
, uprv_strlen(temp2
));
3195 /* Compare language, country, script */
3196 length
= uloc_getLanguage(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3197 if (U_FAILURE(status
)) {
3198 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3199 status
= U_ZERO_ERROR
;
3201 else if (uprv_strcmp(temp3
, rawData2
[LANG
][i
]) && !(uprv_strcmp(temp3
, "nn") == 0 && uprv_strcmp(rawData2
[VAR
][i
], "NY") == 0)) {
3202 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[LANG
][i
], lcid
, temp2
);
3205 length
= uloc_getScript(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3206 if (U_FAILURE(status
)) {
3207 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3208 status
= U_ZERO_ERROR
;
3210 else if (uprv_strcmp(temp3
, rawData2
[SCRIPT
][i
])) {
3211 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[SCRIPT
][i
], lcid
, temp2
);
3214 length
= uloc_getCountry(temp2
, temp3
, sizeof(temp3
)/sizeof(char), &status
);
3215 if (U_FAILURE(status
)) {
3216 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid
, temp2
, u_errorName(status
));
3217 status
= U_ZERO_ERROR
;
3219 else if (uprv_strlen(rawData2
[CTRY
][i
]) && uprv_strcmp(temp3
, rawData2
[CTRY
][i
])) {
3220 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2
[CTRY
][i
], lcid
, temp2
);
3226 const char* const basic_maximize_data
[][2] = {
3271 "en_Latn_US_POSIX_1901"
3273 "en_Latn__POSIX_1901",
3274 "en_Latn_US_POSIX_1901"
3277 "en_Latn_US_POSIX_1901"
3280 "de_Latn_DE_POSIX_1901"
3285 "th@calendar=buddhist",
3286 "th_Thai_TH@calendar=buddhist"
3316 "de_Latn_DE_U_CO_PHONEBK"
3318 "de_Latn_u_co_phonebk",
3319 "de_Latn_DE_U_CO_PHONEBK"
3321 "de_Latn_DE_u_co_phonebk",
3322 "de_Latn_DE_U_CO_PHONEBK"
3326 const char* const basic_minimize_data
[][2] = {
3331 "en_Latn_US_POSIX_1901",
3334 "EN_Latn_US_POSIX_1901",
3337 "en_Zzzz_US_POSIX_1901",
3340 "de_Latn_DE_POSIX_1901",
3346 "en_Latn_US@calendar=gregorian",
3347 "en@calendar=gregorian"
3351 const char* const full_data
[][3] = {
3355 /* "REMOVE-LIKELY" */
4838 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */
4839 "zh_Hani", /* changed due to cldrbug 6204, may be an error */
5421 "de@collation=phonebook",
5422 "de_Latn_DE@collation=phonebook",
5423 "de@collation=phonebook"
5427 typedef struct errorDataTag
{
5429 const char* expected
;
5434 const errorData maximizeErrors
[] = {
5438 U_ILLEGAL_ARGUMENT_ERROR
,
5442 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5444 U_ILLEGAL_ARGUMENT_ERROR
,
5448 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5450 U_ILLEGAL_ARGUMENT_ERROR
,
5454 "en_Latn_US_POSIX@currency=EURO",
5455 "en_Latn_US_POSIX@currency=EURO",
5456 U_BUFFER_OVERFLOW_ERROR
,
5460 "en_Latn_US_POSIX@currency=EURO",
5461 "en_Latn_US_POSIX@currency=EURO",
5462 U_STRING_NOT_TERMINATED_WARNING
,
5467 const errorData minimizeErrors
[] = {
5471 U_ILLEGAL_ARGUMENT_ERROR
,
5475 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5477 U_ILLEGAL_ARGUMENT_ERROR
,
5481 "en_Latn_US_POSIX@currency=EURO",
5482 "en__POSIX@currency=EURO",
5483 U_BUFFER_OVERFLOW_ERROR
,
5487 "en_Latn_US_POSIX@currency=EURO",
5488 "en__POSIX@currency=EURO",
5489 U_STRING_NOT_TERMINATED_WARNING
,
5494 static int32_t getExpectedReturnValue(const errorData
* data
)
5496 if (data
->uerror
== U_BUFFER_OVERFLOW_ERROR
||
5497 data
->uerror
== U_STRING_NOT_TERMINATED_WARNING
)
5499 return strlen(data
->expected
);
5507 static int32_t getBufferSize(const errorData
* data
, int32_t actualSize
)
5509 if (data
->expected
== NULL
)
5513 else if (data
->bufferSize
< 0)
5515 return strlen(data
->expected
) + 1;
5519 return data
->bufferSize
;
5523 static void TestLikelySubtags()
5525 char buffer
[ULOC_FULLNAME_CAPACITY
+ ULOC_KEYWORD_AND_VALUES_CAPACITY
+ 1];
5528 for (; i
< sizeof(basic_maximize_data
) / sizeof(basic_maximize_data
[0]); ++i
)
5530 UErrorCode status
= U_ZERO_ERROR
;
5531 const char* const minimal
= basic_maximize_data
[i
][0];
5532 const char* const maximal
= basic_maximize_data
[i
][1];
5534 /* const int32_t length = */
5535 uloc_addLikelySubtags(
5540 if (U_FAILURE(status
)) {
5541 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal
, u_errorName(status
));
5542 status
= U_ZERO_ERROR
;
5544 else if (uprv_strlen(maximal
) == 0) {
5545 if (uprv_stricmp(minimal
, buffer
) != 0) {
5546 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5549 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5550 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal
, minimal
, buffer
);
5554 for (i
= 0; i
< sizeof(basic_minimize_data
) / sizeof(basic_minimize_data
[0]); ++i
) {
5556 UErrorCode status
= U_ZERO_ERROR
;
5557 const char* const maximal
= basic_minimize_data
[i
][0];
5558 const char* const minimal
= basic_minimize_data
[i
][1];
5560 /* const int32_t length = */
5561 uloc_minimizeSubtags(
5567 if (U_FAILURE(status
)) {
5568 log_err_status(status
, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5569 status
= U_ZERO_ERROR
;
5571 else if (uprv_strlen(minimal
) == 0) {
5572 if (uprv_stricmp(maximal
, buffer
) != 0) {
5573 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5576 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5577 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5581 for (i
= 0; i
< sizeof(full_data
) / sizeof(full_data
[0]); ++i
) {
5583 UErrorCode status
= U_ZERO_ERROR
;
5584 const char* const minimal
= full_data
[i
][0];
5585 const char* const maximal
= full_data
[i
][1];
5587 /* const int32_t length = */
5588 uloc_addLikelySubtags(
5593 if (U_FAILURE(status
)) {
5594 log_err_status(status
, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal
, u_errorName(status
));
5595 status
= U_ZERO_ERROR
;
5597 else if (uprv_strlen(maximal
) == 0) {
5598 if (uprv_stricmp(minimal
, buffer
) != 0) {
5599 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5602 else if (uprv_stricmp(maximal
, buffer
) != 0) {
5603 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal
, minimal
, buffer
);
5607 for (i
= 0; i
< sizeof(full_data
) / sizeof(full_data
[0]); ++i
) {
5609 UErrorCode status
= U_ZERO_ERROR
;
5610 const char* const maximal
= full_data
[i
][1];
5611 const char* const minimal
= full_data
[i
][2];
5613 if (strlen(maximal
) > 0) {
5615 /* const int32_t length = */
5616 uloc_minimizeSubtags(
5622 if (U_FAILURE(status
)) {
5623 log_err_status(status
, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal
, u_errorName(status
));
5624 status
= U_ZERO_ERROR
;
5626 else if (uprv_strlen(minimal
) == 0) {
5627 if (uprv_stricmp(maximal
, buffer
) != 0) {
5628 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal
, maximal
, buffer
);
5631 else if (uprv_stricmp(minimal
, buffer
) != 0) {
5632 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal
, maximal
, buffer
);
5637 for (i
= 0; i
< sizeof(maximizeErrors
) / sizeof(maximizeErrors
[0]); ++i
) {
5639 UErrorCode status
= U_ZERO_ERROR
;
5640 const char* const minimal
= maximizeErrors
[i
].tag
;
5641 const char* const maximal
= maximizeErrors
[i
].expected
;
5642 const UErrorCode expectedStatus
= maximizeErrors
[i
].uerror
;
5643 const int32_t expectedLength
= getExpectedReturnValue(&maximizeErrors
[i
]);
5644 const int32_t bufferSize
= getBufferSize(&maximizeErrors
[i
], sizeof(buffer
));
5646 const int32_t length
=
5647 uloc_addLikelySubtags(
5653 if (status
== U_ZERO_ERROR
) {
5654 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal
, u_errorName(expectedStatus
));
5655 status
= U_ZERO_ERROR
;
5657 else if (status
!= expectedStatus
) {
5658 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
));
5660 else if (length
!= expectedLength
) {
5661 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal
, expectedLength
, length
);
5663 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5664 if (uprv_strnicmp(maximal
, buffer
, bufferSize
) != 0) {
5665 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5666 maximal
, minimal
, (int)sizeof(buffer
), buffer
);
5671 for (i
= 0; i
< sizeof(minimizeErrors
) / sizeof(minimizeErrors
[0]); ++i
) {
5673 UErrorCode status
= U_ZERO_ERROR
;
5674 const char* const maximal
= minimizeErrors
[i
].tag
;
5675 const char* const minimal
= minimizeErrors
[i
].expected
;
5676 const UErrorCode expectedStatus
= minimizeErrors
[i
].uerror
;
5677 const int32_t expectedLength
= getExpectedReturnValue(&minimizeErrors
[i
]);
5678 const int32_t bufferSize
= getBufferSize(&minimizeErrors
[i
], sizeof(buffer
));
5680 const int32_t length
=
5681 uloc_minimizeSubtags(
5687 if (status
== U_ZERO_ERROR
) {
5688 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal
, u_errorName(expectedStatus
));
5689 status
= U_ZERO_ERROR
;
5691 else if (status
!= expectedStatus
) {
5692 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
));
5694 else if (length
!= expectedLength
) {
5695 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal
, expectedLength
, length
);
5697 else if (status
== U_BUFFER_OVERFLOW_ERROR
|| status
== U_STRING_NOT_TERMINATED_WARNING
) {
5698 if (uprv_strnicmp(minimal
, buffer
, bufferSize
) != 0) {
5699 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5700 minimal
, maximal
, (int)sizeof(buffer
), buffer
);
5706 const char* const locale_to_langtag
[][3] = {
5709 {"en_US", "en-US", "en-US"},
5710 {"iw_IL", "he-IL", "he-IL"},
5711 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5712 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5713 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5714 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL
}, /* variant POSIX_VAR is processed as regular variant */
5715 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL
}, /* variant VAR_POSIX is processed as regular variant */
5716 {"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 */
5717 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5718 {"und_555", "und-555", "und-555"},
5719 {"123", "und", NULL
},
5720 {"%$#&", "und", NULL
},
5721 {"_Latn", "und-Latn", "und-Latn"},
5722 {"_DE", "und-DE", "und-DE"},
5723 {"und_FR", "und-FR", "und-FR"},
5724 {"th_TH_TH", "th-TH-x-lvariant-th", NULL
},
5725 {"bogus", "bogus", "bogus"},
5726 {"foooobarrr", "und", NULL
},
5727 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5728 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL
},
5729 {"en_US_1234", "en-US-1234", "en-US-1234"},
5730 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5731 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5732 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL
},
5733 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL
},
5734 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5735 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5736 {"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"},
5737 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5738 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5739 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL
},
5740 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL
},
5741 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5742 {"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"},
5743 {"@x=elmer", "x-elmer", "x-elmer"},
5744 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5745 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5746 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5750 static void TestToLanguageTag(void) {
5756 const char *expected
;
5758 for (i
= 0; locale_to_langtag
[i
][0] != NULL
; i
++) {
5759 inloc
= locale_to_langtag
[i
][0];
5761 /* testing non-strict mode */
5762 status
= U_ZERO_ERROR
;
5764 expected
= locale_to_langtag
[i
][1];
5766 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), FALSE
, &status
);
5767 (void)len
; /* Suppress set but not used warning. */
5768 if (U_FAILURE(status
)) {
5769 if (expected
!= NULL
) {
5770 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5771 inloc
, u_errorName(status
));
5774 if (expected
== NULL
) {
5775 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5777 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5778 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5779 langtag
, inloc
, expected
);
5783 /* testing strict mode */
5784 status
= U_ZERO_ERROR
;
5786 expected
= locale_to_langtag
[i
][2];
5788 len
= uloc_toLanguageTag(inloc
, langtag
, sizeof(langtag
), TRUE
, &status
);
5789 if (U_FAILURE(status
)) {
5790 if (expected
!= NULL
) {
5791 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5792 inloc
, u_errorName(status
));
5795 if (expected
== NULL
) {
5796 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5798 } else if (uprv_strcmp(langtag
, expected
) != 0) {
5799 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5800 langtag
, inloc
, expected
);
5806 #define FULL_LENGTH -1
5807 static const struct {
5811 } langtag_to_locale
[] = {
5812 {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn", "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz", FULL_LENGTH
},
5813 {"en", "en", FULL_LENGTH
},
5814 {"en-us", "en_US", FULL_LENGTH
},
5815 {"und-US", "_US", FULL_LENGTH
},
5816 {"und-latn", "_Latn", FULL_LENGTH
},
5817 {"en-US-posix", "en_US_POSIX", FULL_LENGTH
},
5818 {"de-de_euro", "de", 2},
5819 {"kok-IN", "kok_IN", FULL_LENGTH
},
5822 {"en-latn-x", "en_Latn", 7},
5823 {"art-lojban", "jbo", FULL_LENGTH
},
5824 {"zh-hakka", "hak", FULL_LENGTH
},
5825 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH
},
5826 {"xxx-yy", "xxx_YY", FULL_LENGTH
},
5827 {"fr-234", "fr_234", FULL_LENGTH
},
5828 {"i-default", "en@x=i-default", FULL_LENGTH
},
5830 {"ja-jp-jp", "ja_JP", 5},
5831 {"bogus", "bogus", FULL_LENGTH
},
5832 {"boguslang", "", 0},
5833 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH
},
5834 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH
},
5835 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5836 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH
},
5837 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH
},
5838 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH
},
5839 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH
},
5840 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH
},
5841 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH
},
5842 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH
},
5843 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH
},
5844 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH
},
5845 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH
},
5846 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH
},
5847 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH
},
5848 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH
},
5849 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH
},
5850 {"x-elmer", "@x=elmer", FULL_LENGTH
},
5851 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH
},
5852 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH
},
5853 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH
},
5854 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH
},
5855 {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn", "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz", FULL_LENGTH
},
5857 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5858 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91},
5862 static void TestForLanguageTag(void) {
5867 int32_t expParsedLen
;
5869 for (i
= 0; langtag_to_locale
[i
].bcpID
!= NULL
; i
++) {
5870 status
= U_ZERO_ERROR
;
5872 expParsedLen
= langtag_to_locale
[i
].len
;
5873 if (expParsedLen
== FULL_LENGTH
) {
5874 expParsedLen
= uprv_strlen(langtag_to_locale
[i
].bcpID
);
5876 uloc_forLanguageTag(langtag_to_locale
[i
].bcpID
, locale
, sizeof(locale
), &parsedLen
, &status
);
5877 if (U_FAILURE(status
)) {
5878 log_err_status(status
, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5879 langtag_to_locale
[i
].bcpID
, u_errorName(status
));
5881 if (uprv_strcmp(langtag_to_locale
[i
].locID
, locale
) != 0) {
5882 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5883 locale
, langtag_to_locale
[i
].bcpID
, langtag_to_locale
[i
].locID
);
5885 if (parsedLen
!= expParsedLen
) {
5886 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5887 parsedLen
, langtag_to_locale
[i
].bcpID
, expParsedLen
);
5893 static void TestToUnicodeLocaleKey(void)
5895 /* $IN specifies the result should be the input pointer itself */
5896 static const char* DATA
[][2] = {
5898 {"CALEndar", "ca"}, /* difference casing */
5899 {"ca", "ca"}, /* bcp key itself */
5900 {"kv", "kv"}, /* no difference between legacy and bcp */
5901 {"foo", NULL
}, /* unknown, bcp ill-formed */
5902 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */
5907 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
5908 const char* keyword
= DATA
[i
][0];
5909 const char* expected
= DATA
[i
][1];
5910 const char* bcpKey
= NULL
;
5912 bcpKey
= uloc_toUnicodeLocaleKey(keyword
);
5913 if (expected
== NULL
) {
5914 if (bcpKey
!= NULL
) {
5915 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword
, bcpKey
);
5917 } else if (bcpKey
== NULL
) {
5918 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
5919 } else if (uprv_strcmp(expected
, "$IN") == 0) {
5920 if (bcpKey
!= keyword
) {
5921 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, bcpKey
, keyword
);
5923 } else if (uprv_strcmp(bcpKey
, expected
) != 0) {
5924 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword
, bcpKey
, expected
);
5929 static void TestToLegacyKey(void)
5931 /* $IN specifies the result should be the input pointer itself */
5932 static const char* DATA
[][2] = {
5933 {"kb", "colbackwards"},
5934 {"kB", "colbackwards"}, /* different casing */
5935 {"Collation", "collation"}, /* keyword itself with different casing */
5936 {"kv", "kv"}, /* no difference between legacy and bcp */
5937 {"foo", "$IN"}, /* unknown, bcp ill-formed */
5938 {"ZZ", "$IN"}, /* unknown, bcp well-formed */
5939 {"e=mc2", NULL
}, /* unknown, bcp/legacy ill-formed */
5944 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
5945 const char* keyword
= DATA
[i
][0];
5946 const char* expected
= DATA
[i
][1];
5947 const char* legacyKey
= NULL
;
5949 legacyKey
= uloc_toLegacyKey(keyword
);
5950 if (expected
== NULL
) {
5951 if (legacyKey
!= NULL
) {
5952 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword
, legacyKey
);
5954 } else if (legacyKey
== NULL
) {
5955 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword
, expected
);
5956 } else if (uprv_strcmp(expected
, "$IN") == 0) {
5957 if (legacyKey
!= keyword
) {
5958 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword
, legacyKey
, keyword
);
5960 } else if (uprv_strcmp(legacyKey
, expected
) != 0) {
5961 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword
, legacyKey
, expected
);
5966 static void TestToUnicodeLocaleType(void)
5968 /* $IN specifies the result should be the input pointer itself */
5969 static const char* DATA
[][3] = {
5970 {"tz", "Asia/Kolkata", "inccu"},
5971 {"calendar", "gregorian", "gregory"},
5972 {"ca", "gregorian", "gregory"},
5973 {"ca", "Gregorian", "gregory"},
5974 {"ca", "buddhist", "buddhist"},
5975 {"Calendar", "Japanese", "japanese"},
5976 {"calendar", "Islamic-Civil", "islamic-civil"},
5977 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
5978 {"colalternate", "NON-IGNORABLE", "noignore"},
5979 {"colcaselevel", "yes", "true"},
5980 {"tz", "america/new_york", "usnyc"},
5981 {"tz", "Asia/Kolkata", "inccu"},
5982 {"timezone", "navajo", "usden"},
5983 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */
5984 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
5985 {"zz", "gregorian", NULL
}, /* unknown key, ill-formed type */
5986 {"co", "foo-", NULL
}, /* unknown type, ill-formed type */
5987 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
5988 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
5989 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
5990 {"kr", "digit-spacepunct", NULL
}, /* invalid (bcp ill-formed) reordercode type */
5995 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
5996 const char* keyword
= DATA
[i
][0];
5997 const char* value
= DATA
[i
][1];
5998 const char* expected
= DATA
[i
][2];
5999 const char* bcpType
= NULL
;
6001 bcpType
= uloc_toUnicodeLocaleType(keyword
, value
);
6002 if (expected
== NULL
) {
6003 if (bcpType
!= NULL
) {
6004 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, bcpType
);
6006 } else if (bcpType
== NULL
) {
6007 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6008 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6009 if (bcpType
!= value
) {
6010 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, bcpType
, value
);
6012 } else if (uprv_strcmp(bcpType
, expected
) != 0) {
6013 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, bcpType
, expected
);
6018 static void TestToLegacyType(void)
6020 /* $IN specifies the result should be the input pointer itself */
6021 static const char* DATA
[][3] = {
6022 {"calendar", "gregory", "gregorian"},
6023 {"ca", "gregory", "gregorian"},
6024 {"ca", "Gregory", "gregorian"},
6025 {"ca", "buddhist", "buddhist"},
6026 {"Calendar", "Japanese", "japanese"},
6027 {"calendar", "Islamic-Civil", "islamic-civil"},
6028 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */
6029 {"colalternate", "noignore", "non-ignorable"},
6030 {"colcaselevel", "true", "yes"},
6031 {"tz", "usnyc", "America/New_York"},
6032 {"tz", "inccu", "Asia/Calcutta"},
6033 {"timezone", "usden", "America/Denver"},
6034 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */
6035 {"colstrength", "quarternary", "quaternary"}, /* type alias */
6036 {"ca", "aaaa", "$IN"}, /* unknown type */
6037 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */
6038 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */
6039 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */
6040 {"co", "e=mc2", NULL
}, /* known key, ill-formed bcp/legacy type */
6041 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */
6042 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */
6043 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */
6044 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */
6049 for (i
= 0; DATA
[i
][0] != NULL
; i
++) {
6050 const char* keyword
= DATA
[i
][0];
6051 const char* value
= DATA
[i
][1];
6052 const char* expected
= DATA
[i
][2];
6053 const char* legacyType
= NULL
;
6055 legacyType
= uloc_toLegacyType(keyword
, value
);
6056 if (expected
== NULL
) {
6057 if (legacyType
!= NULL
) {
6058 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword
, value
, legacyType
);
6060 } else if (legacyType
== NULL
) {
6061 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword
, value
, expected
);
6062 } else if (uprv_strcmp(expected
, "$IN") == 0) {
6063 if (legacyType
!= value
) {
6064 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword
, value
, legacyType
, value
);
6066 } else if (uprv_strcmp(legacyType
, expected
) != 0) {
6067 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword
, value
, legacyType
, expected
);
6074 static void test_unicode_define(const char *namech
, char ch
, const char *nameu
, UChar uch
)
6078 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech
, ch
,(int)ch
, nameu
, (int) uch
);
6079 u_charsToUChars(&ch
, asUch
, 1);
6080 if(asUch
[0] != uch
) {
6081 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
);
6083 log_verbose(" .. OK, == U+%04X\n", (int)asUch
[0]);
6087 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
6089 static void TestUnicodeDefines(void) {
6090 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR
, ULOC_KEYWORD_SEPARATOR_UNICODE
);
6091 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN
, ULOC_KEYWORD_ASSIGN_UNICODE
);
6092 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR
, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE
);
6095 static void TestIsRightToLeft() {
6096 // API test only. More test cases in intltest/LocaleTest.
6097 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
6098 log_err("uloc_isRightToLeft() failed");
6102 /* Apple-specific, test for Apple-specific function ualoc_getAppleParent */
6103 static const char* localesAndAppleParent
[] = {
6142 "zh_HK", "zh_Hant_HK",
6143 "zh-HK", "zh_Hant_HK",
6145 "zh-Hant-HK", "zh_Hant",
6146 "zh_Hant_HK", "zh_Hant",
6147 "zh-Hant-MO", "zh_Hant_HK",
6148 "zh-Hans-HK", "zh_Hans",
6151 "en-Latn-US", "en_Latn",
6152 "en_US_POSIX", "en_US",
6153 "en_Latn_US_POSIX", "en_Latn_US",
6154 "en-u-ca-hebrew", "root",
6155 "en@calendar=hebrew", "root",
6156 "en_@calendar=hebrew", "root",
6159 "Default@2x", "root",
6161 NULL
/* terminator */
6164 static void TestGetAppleParent() {
6165 const char **localesPtr
= localesAndAppleParent
;
6166 const char * locale
;
6167 while ((locale
= *localesPtr
++) != NULL
) {
6168 const char * expectParent
= *localesPtr
++;
6169 UErrorCode status
= U_ZERO_ERROR
;
6170 char getParent
[ULOC_FULLNAME_CAPACITY
];
6171 int32_t plen
= ualoc_getAppleParent(locale
, getParent
, ULOC_FULLNAME_CAPACITY
, &status
);
6172 if (U_FAILURE(status
)) {
6173 log_err("FAIL: ualoc_getAppleParent input \"%s\", status %s\n", locale
, u_errorName(status
));
6174 } else if (uprv_strcmp(expectParent
, getParent
) != 0) {
6175 log_err("FAIL: ualoc_getAppleParent input \"%s\", expected parent \"%s\", got parent \"%s\"\n", locale
, expectParent
, getParent
);
6180 /* Apple-specific, test for Apple-specific function ualoc_getLanguagesForRegion */
6181 enum { kUALanguageEntryMax
= 10 };
6183 static void TestGetLanguagesForRegion() {
6184 UALanguageEntry entries
[kUALanguageEntryMax
];
6187 const char * region
;
6189 status
= U_ZERO_ERROR
;
6191 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
6192 if (U_FAILURE(status
)) {
6193 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6195 // Expect approximately:
6196 // zh_Hans 0.90 UALANGSTATUS_OFFICIAL
6203 // ug_Arab 0.0055 Uighur UALANGSTATUS_REGIONAL_OFFICIAL
6204 // ...at least 4 more with fractions >= 0.001
6205 if (entryCount
< kUALanguageEntryMax
) {
6206 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6208 UALanguageEntry
* entryPtr
= entries
;
6209 if (uprv_strcmp(entryPtr
->languageCode
, "zh_Hans") != 0 || entryPtr
->userFraction
< 0.8 || entryPtr
->userFraction
> 1.0 || entryPtr
->status
!= UALANGSTATUS_OFFICIAL
) {
6210 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entryPtr
->languageCode
, entryPtr
->userFraction
, (int)entryPtr
->status
);
6212 for (entryPtr
++; entryPtr
< entries
+ kUALanguageEntryMax
&& uprv_strcmp(entryPtr
->languageCode
, "ug_Arab") != 0; entryPtr
++)
6214 if (entryPtr
< entries
+ kUALanguageEntryMax
) {
6215 // we found ug_Arab, make sure it has correct status
6216 if (entryPtr
->status
!= UALANGSTATUS_REGIONAL_OFFICIAL
) {
6217 log_err("FAIL: ualoc_getLanguagesForRegion %s, ug_Arab had incorrect status %d\n", (int)entryPtr
->status
);
6220 // did not find ug_Arab
6221 log_err("FAIL: ualoc_getLanguagesForRegion %s, entries did not include ug_Arab\n", region
);
6226 status
= U_ZERO_ERROR
;
6228 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, entries
, kUALanguageEntryMax
, &status
);
6229 if (U_FAILURE(status
)) {
6230 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6232 // Expect approximately:
6233 // en 0.85 UALANGSTATUS_OFFICIAL
6234 // fr 0.22 UALANGSTATUS_OFFICIAL
6236 if (entryCount
< 2) {
6237 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6239 if (uprv_strcmp(entries
[0].languageCode
, "en") != 0 || entries
[0].userFraction
< 0.7 || entries
[0].userFraction
> 1.0 || entries
[0].status
!= UALANGSTATUS_OFFICIAL
) {
6240 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region
, entries
[0].languageCode
, entries
[0].userFraction
, (int)entries
[0].status
);
6242 if (uprv_strcmp(entries
[1].languageCode
, "fr") != 0 || entries
[1].userFraction
< 0.1 || entries
[1].userFraction
> 1.0 || entries
[1].status
!= UALANGSTATUS_OFFICIAL
) {
6243 log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region
, entries
[1].languageCode
, entries
[1].userFraction
, (int)entries
[1].status
);
6248 status
= U_ZERO_ERROR
;
6250 entryCount
= ualoc_getLanguagesForRegion(region
, 0.001, NULL
, 0, &status
);
6251 if (U_FAILURE(status
)) {
6252 log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region
, u_errorName(status
));
6254 if (entryCount
< 40) {
6255 log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region
, entryCount
);
6260 /* data for TestAppleLocalizationsToUse */
6263 const char * const *locs
;
6265 } AppleLocsAndCount
;
6267 enum { kNumLocSets
= 6 };
6270 const char * language
;
6271 const char ** expLocsForSets
[kNumLocSets
];
6275 static const char * appleLocs1
[] = {
6309 static const char * appleLocs2
[] = {
6316 "en", "en_AU", "en_GB",
6340 "zh_CN", "zh_HK", "zh_TW",
6343 static const char * appleLocs3
[] = {
6350 "en", "en_AU", "en_CA", "en_GB",
6353 "fr", "fr_CA", "fr_FR",
6365 "pt", "pt_BR", "pt_PT",
6374 "zh_CN", "zh_HK", "zh_MO", "zh_TW",
6377 static const char * appleLocs4
[] = {
6378 "en", "en_AU", "en_CA", "en_GB", "en_IN", "en_US",
6379 "es", "es_419", "es_MX",
6380 "fr", "fr_CA", "fr_CH", "fr_FR",
6381 "nl", "nl_BE", "nl_NL",
6383 "ro", "ro_MD", "ro_RO",
6384 "zh_Hans", "zh_Hant", "zh_Hant_HK",
6387 static const char * appleLocs5
[] = {
6388 "en", "en_001", "en_AU", "en_GB",
6389 "es", "es_ES", "es_MX",
6390 "zh_CN", "zh_Hans", "zh_Hant", "zh_TW",
6400 static const char * appleLocs6
[] = {
6401 "en", "en_001", "en_150", "en_AU", "en_GB",
6402 "es", "es_419", "es_ES", "es_MX",
6403 "zh_CN", "zh_Hans", "zh_Hant", "zh_Hant_HK", "zh_HK", "zh_TW",
6410 static const AppleLocsAndCount locAndCountEntries
[kNumLocSets
] = {
6411 { appleLocs1
, UPRV_LENGTHOF(appleLocs1
) },
6412 { appleLocs2
, UPRV_LENGTHOF(appleLocs2
) },
6413 { appleLocs3
, UPRV_LENGTHOF(appleLocs3
) },
6414 { appleLocs4
, UPRV_LENGTHOF(appleLocs4
) },
6415 { appleLocs5
, UPRV_LENGTHOF(appleLocs5
) },
6416 { appleLocs6
, UPRV_LENGTHOF(appleLocs6
) },
6420 static const char* l1_ar
[] = { "ar", NULL
};
6421 static const char* l1_Ara
[] = { "Arabic", NULL
};
6422 static const char* l1_ca
[] = { "ca", NULL
};
6423 static const char* l1_cs
[] = { "cs", NULL
};
6424 static const char* l1_da
[] = { "da", NULL
};
6425 static const char* l1_Dan
[] = { "Danish", NULL
};
6426 static const char* l1_de
[] = { "de", NULL
};
6427 static const char* l1_Ger
[] = { "German", NULL
};
6428 static const char* l1_el
[] = { "el", NULL
};
6429 static const char* l1_en
[] = { "en", NULL
};
6430 static const char* l1_Eng
[] = { "English", NULL
};
6431 static const char* l2_en_001_
[] = { "en_001", "en", NULL
};
6432 static const char* l2_en_CA_
[] = { "en_CA", "en", NULL
};
6433 static const char* l2_en_GB_
[] = { "en_GB", "en", NULL
};
6434 static const char* l2_en_US_
[] = { "en_US", "en", NULL
};
6435 static const char* l2_en_GB_Eng
[] = { "en_GB", "English", NULL
};
6436 static const char* l3_en_GB001_
[] = { "en_GB", "en_001", "en", NULL
};
6437 static const char* l3_en_AUGB_
[] = { "en_AU", "en_GB", "en", NULL
};
6438 static const char* l3_en_INGB_
[] = { "en_IN", "en_GB", "en", NULL
};
6439 static const char* l4_en_150GB001_
[] = { "en_150", "en_GB", "en_001", "en", NULL
};
6440 static const char* l4_en_AUGB001_
[] = { "en_AU", "en_GB", "en_001", "en", NULL
};
6441 static const char* l1_es
[] = { "es", NULL
};
6442 static const char* l1_Spa
[] = { "Spanish", NULL
};
6443 static const char* l2_es_419_
[] = { "es_419", "es", NULL
};
6444 static const char* l2_es_ES_
[] = { "es_ES", "es", NULL
};
6445 static const char* l2_es_MX_
[] = { "es_MX", "es", NULL
};
6446 static const char* l2_es_MX_Spa
[] = { "es_MX", "Spanish", NULL
};
6447 static const char* l3_es_MX419_
[] = { "es_MX", "es_419", "es", NULL
};
6448 static const char* l1_fi
[] = { "fi", NULL
};
6449 static const char* l1_Fin
[] = { "Finnish", NULL
};
6450 static const char* l1_fil
[] = { "fil", NULL
};
6451 static const char* l1_tl
[] = { "tl", NULL
};
6452 static const char* l1_fr
[] = { "fr", NULL
};
6453 static const char* l1_Fre
[] = { "French", NULL
};
6454 static const char* l2_fr_CA_
[] = { "fr_CA", "fr", NULL
};
6455 static const char* l2_fr_CH_
[] = { "fr_CH", "fr", NULL
};
6456 static const char* l2_fr_FR_
[] = { "fr_FR", "fr", NULL
};
6457 static const char* l1_haw
[] = { "haw", NULL
};
6458 static const char* l1_he
[] = { "he", NULL
};
6459 static const char* l1_hr
[] = { "hr", NULL
};
6460 static const char* l1_hu
[] = { "hu", NULL
};
6461 static const char* l1_id
[] = { "id", NULL
};
6462 static const char* l1_in
[] = { "in", NULL
};
6463 static const char* l1_it
[] = { "it", NULL
};
6464 static const char* l1_Ita
[] = { "Italian", NULL
};
6465 static const char* l1_ja
[] = { "ja", NULL
};
6466 static const char* l1_Japn
[] = { "Japanese", NULL
};
6467 static const char* l1_ko
[] = { "ko", NULL
};
6468 static const char* l1_Kor
[] = { "Korean", NULL
};
6469 static const char* l1_ms
[] = { "ms", NULL
};
6470 static const char* l1_nb
[] = { "nb", NULL
};
6471 static const char* l1_no
[] = { "no", NULL
};
6472 static const char* l1_Nor
[] = { "Norwegian", NULL
};
6473 static const char* l1_nl
[] = { "nl", NULL
};
6474 static const char* l1_Dut
[] = { "Dutch", NULL
};
6475 static const char* l2_nl_BE_
[] = { "nl_BE", "nl", NULL
};
6476 static const char* l1_pl
[] = { "pl", NULL
};
6477 static const char* l1_Pol
[] = { "Polish", NULL
};
6478 static const char* l1_pt
[] = { "pt", NULL
};
6479 static const char* l1_pt_PT
[] = { "pt_PT", NULL
};
6480 static const char* l1_Port
[] = { "Portuguese", NULL
};
6481 static const char* l2_pt_BR_
[] = { "pt_BR", "pt", NULL
};
6482 static const char* l2_pt_PT_
[] = { "pt_PT", "pt", NULL
};
6483 static const char* l1_ro
[] = { "ro", NULL
};
6484 static const char* l2_ro_MD_
[] = { "ro_MD", "ro", NULL
};
6485 static const char* l1_mo
[] = { "mo", NULL
};
6486 static const char* l1_ru
[] = { "ru", NULL
};
6487 static const char* l1_Rus
[] = { "Russian", NULL
};
6488 static const char* l1_sk
[] = { "sk", NULL
};
6489 static const char* l1_sr
[] = { "sr", NULL
};
6490 static const char* l1_srLatn
[] = { "sr-Latn", NULL
};
6491 static const char* l1_sv
[] = { "sv", NULL
};
6492 static const char* l1_Swe
[] = { "Swedish", NULL
};
6493 static const char* l1_th
[] = { "th", NULL
};
6494 static const char* l1_Thai
[] = { "Thai", NULL
};
6495 static const char* l1_tlh
[] = { "tlh", NULL
};
6496 static const char* l1_tr
[] = { "tr", NULL
};
6497 static const char* l1_Tur
[] = { "Turkish", NULL
};
6498 static const char* l1_uk
[] = { "uk", NULL
};
6499 static const char* l1_vi
[] = { "vi", NULL
};
6500 static const char* l1_yi
[] = { "yi", NULL
};
6501 static const char* l1_iw
[] = { "iw", NULL
};
6502 static const char* l1_zh_CN
[] = { "zh_CN", NULL
};
6503 static const char* l1_zh_TW
[] = { "zh_TW", NULL
};
6504 static const char* l1_zh_Hans
[] = { "zh_Hans", NULL
};
6505 static const char* l1_zh_Hant
[] = { "zh_Hant", NULL
};
6506 static const char* l1_zhHant
[] = { "zh-Hant", NULL
};
6507 static const char* l2_zh_HKTW
[] = { "zh_HK", "zh_TW", NULL
};
6508 static const char* l2_zh_Hant_HK_
[] = { "zh_Hant_HK", "zh_Hant", NULL
};
6509 static const char* l2_zh_CN_Hans
[] = { "zh_CN", "zh_Hans", NULL
};
6510 static const char* l2_zh_TW_Hant
[] = { "zh_TW", "zh_Hant", NULL
};
6511 static const char* l3_zh_MOHKTW
[] = { "zh_MO", "zh_HK", "zh_TW", NULL
};
6512 static const char* l3_zh_HK_HantHK_Hant
[] = { "zh_HK", "zh_Hant_HK", "zh_Hant", NULL
};
6514 static const LangAndExpLocs appleLangAndLoc
[] = {
6515 // language\ result for appleLocs1 appleLocs2 appleLocs3 appleLocs4 appleLocs5 appleLocs6
6516 { "zh", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6517 { "zh-Hans", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6518 { "zh-Hant", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l1_zh_Hant
, l1_zh_Hant
} },
6519 { "zh-Hans-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
6520 { "zh-Hans-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6521 { "zh-Hant-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
6522 { "zh-Hant-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6523 { "zh-Hant-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6524 { "zh-Hans-HK", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6525 { "zh-CN", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l2_zh_CN_Hans
, l2_zh_CN_Hans
} },
6526 { "zh-SG", { l1_zh_CN
, l1_zh_CN
, l1_zh_CN
, l1_zh_Hans
, l1_zh_Hans
, l1_zh_Hans
} },
6527 { "zh-TW", { l1_zh_TW
, l1_zh_TW
, l1_zh_TW
, l1_zh_Hant
, l2_zh_TW_Hant
, l2_zh_TW_Hant
} },
6528 { "zh-HK", { l1_zh_TW
, l2_zh_HKTW
, l2_zh_HKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l3_zh_HK_HantHK_Hant
} },
6529 { "zh-MO", { l1_zh_TW
, l2_zh_HKTW
, l3_zh_MOHKTW
, l2_zh_Hant_HK_
, l1_zh_Hant
, l2_zh_Hant_HK_
} },
6530 { "en", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6531 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6532 { "en-AU", { l1_Eng
, l3_en_AUGB_
, l3_en_AUGB_
, l3_en_AUGB_
, l4_en_AUGB001_
, l4_en_AUGB001_
} },
6533 { "en-CA", { l1_Eng
, l1_en
, l2_en_CA_
, l2_en_CA_
, l2_en_001_
, l2_en_001_
} },
6534 { "en-GB", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l3_en_GB001_
} },
6535 { "en-IN", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l3_en_INGB_
, l3_en_GB001_
, l3_en_GB001_
} },
6536 { "en-US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6537 { "en_US", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6538 { "en-FR", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
6539 { "en-IL", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
6540 { "en-001", { l1_Eng
, l1_en
, l1_en
, l1_en
, l2_en_001_
, l2_en_001_
} },
6541 { "en-150", { l1_Eng
, l2_en_GB_
, l2_en_GB_
, l2_en_GB_
, l3_en_GB001_
, l4_en_150GB001_
} },
6542 { "en-Latn", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6543 { "en-Latn-US", { l1_Eng
, l1_en
, l1_en
, l1_en
,/*TODO*/ l1_en
, l1_en
} },
6544 { "en-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l2_en_US_
, l1_en
, l1_en
} },
6545 { "en-Latn-US-POSIX", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6546 { "en-u-ca-hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6547 { "en@calendar=hebrew", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6548 { "en-", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6549 { "en_", { l1_Eng
, l1_en
, l1_en
, l1_en
, l1_en
, l1_en
} },
6550 { "es", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6551 { "es-ES", { l1_Spa
, l1_es
, l1_es
, l1_es
, l2_es_ES_
, l2_es_ES_
} },
6552 { "es-419", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
6553 { "es-MX", { l1_Spa
, l2_es_MX_
, l2_es_419_
, l3_es_MX419_
, l2_es_MX_
, l3_es_MX419_
} },
6554 { "es-AR", { l1_Spa
, l1_es
, l2_es_419_
, l2_es_419_
, l1_es
, l2_es_419_
} },
6555 { "es-Latn", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6556 { "es-Latn-MX", { l1_Spa
, l1_es
, l1_es
, l1_es
, l1_es
, l1_es
} },
6557 { "pt", { l1_Port
, l1_pt
, l1_pt
, l1_pt
, NULL
, NULL
} },
6558 { "pt-BR", { l1_Port
, l1_pt
, l2_pt_BR_
, l2_pt_BR_
, NULL
, NULL
} },
6559 { "pt-PT", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6560 { "pt-MO", { l1_Port
, l2_pt_PT_
, l2_pt_PT_
, l1_pt
, NULL
, NULL
} },
6561 { "fr", { l1_Fre
, l1_fr
, l1_fr
, l1_fr
, NULL
, NULL
} },
6562 { "fr-FR", { l1_Fre
, l1_fr
, l2_fr_FR_
, l2_fr_FR_
, NULL
, NULL
} },
6563 { "fr-CA", { l1_Fre
, l2_fr_CA_
, l2_fr_CA_
, l2_fr_CA_
, NULL
, NULL
} },
6564 { "fr-CH", { l1_Fre
, l1_fr
, l1_fr
, l2_fr_CH_
, NULL
, NULL
} },
6565 { "ar", { l1_Ara
, l1_ar
, l1_ar
, NULL
, NULL
, NULL
} },
6566 { "da", { l1_Dan
, l1_da
, l1_da
, NULL
, NULL
, NULL
} },
6567 { "nl", { l1_Dut
, l1_nl
, l1_nl
, l1_nl
, NULL
, NULL
} },
6568 { "nl-BE", { l1_Dut
, l1_nl
, l1_nl
, l2_nl_BE_
, NULL
, NULL
} },
6569 { "fi", { l1_Fin
, l1_fi
, l1_fi
, NULL
, NULL
, NULL
} },
6570 { "de", { l1_Ger
, l1_de
, l1_de
, NULL
, NULL
, NULL
} },
6571 { "it", { l1_Ita
, l1_it
, l1_it
, NULL
, NULL
, NULL
} },
6572 { "ja", { l1_Japn
, l1_ja
, l1_ja
, NULL
, NULL
, NULL
} },
6573 { "ko", { l1_Kor
, l1_ko
, l1_ko
, NULL
, NULL
, NULL
} },
6574 { "nb", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
6575 { "no", { l1_Nor
, l1_no
, l1_nb
, NULL
, NULL
, NULL
} },
6576 { "pl", { l1_Pol
, l1_pl
, l1_pl
, NULL
, NULL
, NULL
} },
6577 { "ru", { l1_Rus
, l1_ru
, l1_ru
, NULL
, NULL
, NULL
} },
6578 { "sv", { l1_Swe
, l1_sv
, l1_sv
, NULL
, NULL
, NULL
} },
6579 { "th", { l1_Thai
, l1_th
, l1_th
, NULL
, NULL
, NULL
} },
6580 { "tr", { l1_Tur
, l1_tr
, l1_tr
, NULL
, NULL
, NULL
} },
6581 { "ca", { l1_ca
, l1_ca
, l1_ca
, NULL
, NULL
, NULL
} },
6582 { "cs", { l1_cs
, l1_cs
, l1_cs
, NULL
, NULL
, NULL
} },
6583 { "el", { l1_el
, l1_el
, l1_el
, NULL
, NULL
, NULL
} },
6584 { "he", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
6585 { "iw", { l1_he
, l1_he
, l1_he
, NULL
, NULL
, l1_iw
} },
6586 { "hr", { l1_hr
, l1_hr
, l1_hr
, NULL
, NULL
, NULL
} },
6587 { "hu", { l1_hu
, l1_hu
, l1_hu
, NULL
, NULL
, NULL
} },
6588 { "id", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
6589 { "in", { l1_id
, l1_id
, l1_id
, NULL
, NULL
, l1_in
} },
6590 { "ms", { l1_ms
, l1_ms
, l1_ms
, NULL
, NULL
, NULL
} },
6591 { "ro", { l1_ro
, l1_ro
, l1_ro
, l1_ro
, NULL
, NULL
} },
6592 { "mo", { l1_ro
, l1_ro
, l1_ro
, l2_ro_MD_
, NULL
, l1_mo
} },
6593 { "sk", { l1_sk
, l1_sk
, l1_sk
, NULL
, NULL
, NULL
} },
6594 { "uk", { l1_uk
, l1_uk
, l1_uk
, NULL
, NULL
, NULL
} },
6595 { "vi", { l1_vi
, l1_vi
, l1_vi
, NULL
, NULL
, NULL
} },
6596 { "yi", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
6597 { "ji", { NULL
, NULL
, NULL
, NULL
, l1_yi
, NULL
} },
6598 { "fil", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
6599 { "tl", { NULL
, NULL
, NULL
, NULL
, l1_fil
, l1_tl
} },
6600 { "haw", { NULL
, NULL
, NULL
, NULL
, l1_haw
, NULL
} },
6601 { "sr", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
6602 { "sr-Cyrl", { NULL
, NULL
, NULL
, NULL
, l1_sr
, NULL
} },
6603 { "sr-Latn", { NULL
, NULL
, NULL
, NULL
, l1_srLatn
, NULL
} },
6604 { "tlh", { NULL
, NULL
, NULL
, NULL
, l1_tlh
, NULL
} },
6605 { "Default@2x", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6606 { "default", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6607 { "root", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6608 { "", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6609 { "_US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6610 { "-US", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6611 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6612 { "-u-ca-hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6613 { "@calendar=hebrew", { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} },
6615 enum { kNumAppleLangAndLoc
= UPRV_LENGTHOF(appleLangAndLoc
) };
6617 /* tests from <rdar://problem/21518031> */
6619 static const char * appleLocsA1
[] = { "en", "fr", "de", "zh-Hant" };
6620 static const char * appleLocsA2
[] = { "en", "fr", "de", "zh_TW", "zh_CN", "zh-Hant" };
6621 static const char * appleLocsA3
[] = { "en", "en_IN", "en_GB", "fr", "de", "zh_TW" };
6622 static const char * appleLocsA4
[] = { "Spanish", "es_MX", "English", "en_GB" };
6623 static const char * appleLocsA5
[] = { "en", "fr", "de", "pt", "pt_PT" };
6624 static const char * appleLocsA6
[] = { "en", "pt_PT" };
6626 static const AppleLocsAndCount locAndCountEntriesA
[kNumLocSets
] = {
6627 { appleLocsA1
, UPRV_LENGTHOF(appleLocsA1
) },
6628 { appleLocsA2
, UPRV_LENGTHOF(appleLocsA2
) },
6629 { appleLocsA3
, UPRV_LENGTHOF(appleLocsA3
) },
6630 { appleLocsA4
, UPRV_LENGTHOF(appleLocsA4
) },
6631 { appleLocsA5
, UPRV_LENGTHOF(appleLocsA5
) },
6632 { appleLocsA6
, UPRV_LENGTHOF(appleLocsA6
) },
6635 static const LangAndExpLocs appleLangAndLocA
[] = {
6636 // language\ result for appleLocsA1 appleLocsA2 appleLocsA3 appleLocsA4 appleLocsA5 appleLocsA6
6637 { "zh-Hant", { l1_zhHant
,/*0*/ l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6638 { "zh_Hant", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6639 { "zh_HK", { l1_zhHant
, l1_zhHant
,/*zh_TW*/ l1_zh_TW
, NULL
, NULL
, NULL
} },
6640 { "en_IN", { l1_en
, l1_en
, l3_en_INGB_
, l2_en_GB_Eng
, l1_en
, l1_en
} },
6641 { "es_MX", { NULL
, NULL
, NULL
, l2_es_MX_Spa
, NULL
, NULL
} },
6642 { "pt_PT", { NULL
, NULL
, NULL
, NULL
, l2_pt_PT_
, l1_pt_PT
} },
6643 { "pt", { NULL
, NULL
, NULL
, NULL
, l1_pt
, l1_pt_PT
} },
6645 enum { kNumAppleLangAndLocA
= UPRV_LENGTHOF(appleLangAndLocA
) };
6647 /* tests from log attached to 21682790 */
6649 static const char * appleLocsB1
[] = {
6650 "ar", "Base", "ca", "cs",
6651 "da", "Dutch", "el", "English",
6652 "es_MX", "fi", "French", "German",
6653 "he", "hr", "hu", "id",
6654 "Italian", "Japanese", "ko", "ms",
6655 "no", "pl", "pt", "pt_PT",
6656 "ro", "ru", "sk", "Spanish",
6657 "sv", "th", "tr", "uk",
6658 "vi", "zh_CN", "zh_TW"
6661 static const char * appleLocsB2
[] = {
6663 "da", "Dutch", "el", "English",
6664 "es_MX", "fi", "French", "German",
6665 "he", "hr", "hu", "id",
6666 "Italian", "Japanese", "ko", "ms",
6667 "no", "pl", "pt", "pt_PT",
6668 "ro", "ru", "sk", "Spanish",
6669 "sv", "th", "tr", "uk",
6670 "vi", "zh_CN", "zh_TW"
6673 static const char * appleLocsB3
[] = {
6674 "ar", "ca", "cs", "da",
6675 "de", "el", "en", "es",
6676 "es_MX", "fi", "French", "he",
6677 "hr", "hu", "id", "Italian",
6678 "ja", "ko", "ms", "nl",
6679 "no", "pl", "pt", "pt_PT",
6680 "ro", "ru", "sk", "sv",
6681 "th", "tr", "uk", "vi",
6685 static const char * appleLocsB4
[] = {
6686 "ar", "ca", "cs", "da",
6687 "de", "el", "en", "es",
6688 "es_MX", "fi", "fr", "he",
6689 "hr", "hu", "id", "it",
6690 "ja", "ko", "ms", "nl",
6691 "no", "pl", "pt", "pt_PT",
6692 "ro", "ru", "sk", "sv",
6693 "th", "tr", "uk", "vi",
6697 static const char * appleLocsB5
[] = { "en" };
6699 static const char * appleLocsB6
[] = { "English" };
6701 static const AppleLocsAndCount locAndCountEntriesB
[kNumLocSets
] = {
6702 { appleLocsB1
, UPRV_LENGTHOF(appleLocsB1
) },
6703 { appleLocsB2
, UPRV_LENGTHOF(appleLocsB2
) },
6704 { appleLocsB3
, UPRV_LENGTHOF(appleLocsB3
) },
6705 { appleLocsB4
, UPRV_LENGTHOF(appleLocsB4
) },
6706 { appleLocsB5
, UPRV_LENGTHOF(appleLocsB5
) },
6707 { appleLocsB6
, UPRV_LENGTHOF(appleLocsB6
) },
6710 static const LangAndExpLocs appleLangAndLocB
[] = {
6711 // language\ result for appleLocsB1 appleLocsB2 appleLocsB3 appleLocsB4 appleLocsB5 appleLocsB6
6712 // Prefs 1, logged with sets B1-B3
6713 { "en", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
6714 { "es", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
6715 // Prefs 2, logged with sets B1-B6
6716 { "English", { l1_Eng
, l1_Eng
, l1_en
, l1_en
, l1_en
, l1_Eng
} },
6717 { "Spanish", { l1_Spa
, l1_Spa
, l1_es
, l1_es
, NULL
, NULL
} },
6719 enum { kNumAppleLangAndLocB
= UPRV_LENGTHOF(appleLangAndLocB
) };
6722 const AppleLocsAndCount
* locAndCountEntriesPtr
;
6723 const LangAndExpLocs
* appleLangAndLocPtr
;
6724 int32_t appleLangAndLocCount
;
6725 } AppleLocToUseTestSet
;
6727 static const AppleLocToUseTestSet altuTestSets
[] = {
6728 { locAndCountEntries
, appleLangAndLoc
, kNumAppleLangAndLoc
},
6729 { locAndCountEntriesA
, appleLangAndLocA
, kNumAppleLangAndLocA
},
6730 { locAndCountEntriesB
, appleLangAndLocB
, kNumAppleLangAndLocB
},
6734 /* tests for multiple prefs sets */
6736 static const char * appleLocsM
[] = { "en", "en_GB", "pt", "pt_PT", "zh_CN", "zh_Hant" };
6737 static const char * prefLangsM
[] = { "tlh", "zh_HK", "zh_SG", "zh_Hans", "pt_BR", "pt_PT", "en_IN", "en" };
6738 static const char * locsToUseM
[] = { "zh_Hant" };
6740 kNumAppleLocsM
= UPRV_LENGTHOF(appleLocsM
),
6741 kNumPrefLangsM
= UPRV_LENGTHOF(prefLangsM
),
6742 kNumLocsToUseM
= UPRV_LENGTHOF(locsToUseM
),
6747 enum { kMaxLocalizationsToUse
= 8, kPrintArrayBufSize
= 128 };
6749 // array, array of pointers to strings to print
6750 // count, count of array elements, may be -1 if array is terminated by a NULL entry
6751 // buf, buffer into which to put concatenated strings
6752 // bufSize, length of buf
6753 static void printStringArray(const char **array
, int32_t count
, char *buf
, int32_t bufSize
) {
6754 char * bufPtr
= buf
;
6755 const char * curEntry
;
6756 int32_t idx
, countMax
= bufSize
/16;
6757 if (count
< 0 || count
> countMax
) {
6760 for (idx
= 0; idx
< count
&& (curEntry
= *array
++) != NULL
; idx
++) {
6761 int32_t len
= sprintf(bufPtr
, "%s\"%.12s\"", (idx
> 0)? ", ": "", curEntry
);
6767 *bufPtr
= 0; /* ensure termination */
6770 static UBool
equalStringArrays(const char **array1
, int32_t count1
, const char **array2
, int32_t count2
) {
6771 const char ** array1Ptr
= array1
;
6772 const char ** array2Ptr
= array2
;
6775 while (*array1Ptr
++ != NULL
) {
6781 while (*array2Ptr
++ != NULL
) {
6785 if (count1
!= count2
) {
6789 for (idx
= 0; idx
< count1
; idx
++) {
6790 if (uprv_strcmp(array1
[idx
], array2
[idx
]) != 0) {
6797 static void TestAppleLocalizationsToUse() {
6798 const AppleLocToUseTestSet
* testSetPtr
;
6799 const char * locsToUse
[kMaxLocalizationsToUse
];
6800 int32_t numLocsToUse
;
6802 char printExpected
[kPrintArrayBufSize
];
6803 char printActual
[kPrintArrayBufSize
];
6805 for (testSetPtr
= altuTestSets
; testSetPtr
->locAndCountEntriesPtr
!= NULL
; testSetPtr
++) {
6806 int32_t iLocSet
, iLang
;
6808 for (iLocSet
= 0; iLocSet
< kNumLocSets
; iLocSet
++) {
6809 for (iLang
= 0; iLang
< testSetPtr
->appleLangAndLocCount
; iLang
++) {
6810 status
= U_ZERO_ERROR
;
6811 const char * language
= testSetPtr
->appleLangAndLocPtr
[iLang
].language
;
6812 const char ** expLocsForSet
= testSetPtr
->appleLangAndLocPtr
[iLang
].expLocsForSets
[iLocSet
];
6814 numLocsToUse
= ualoc_localizationsToUse(&language
, 1,
6815 testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locs
, testSetPtr
->locAndCountEntriesPtr
[iLocSet
].locCount
,
6816 locsToUse
, kMaxLocalizationsToUse
, &status
);
6817 if (U_FAILURE(status
)) {
6818 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, status %s\n",
6819 testSetPtr
-altuTestSets
, iLocSet
+1, language
, u_errorName(status
));
6820 } else if (numLocsToUse
== 0 && expLocsForSet
!= NULL
) {
6821 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
6822 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect {%s}, get no results\n",
6823 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
);
6824 } else if (numLocsToUse
> 0 && expLocsForSet
== NULL
) {
6825 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
6826 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect no results, get {%s}\n",
6827 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printActual
);
6828 } else if (numLocsToUse
> 0 && !equalStringArrays(expLocsForSet
, -1, locsToUse
, numLocsToUse
)) {
6829 printStringArray(expLocsForSet
, -1, printExpected
, kPrintArrayBufSize
);
6830 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
6831 log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s:\n expect {%s}\n get {%s}\n",
6832 testSetPtr
-altuTestSets
, iLocSet
+1, language
, printExpected
, printActual
);
6839 status
= U_ZERO_ERROR
;
6840 numLocsToUse
= ualoc_localizationsToUse(prefLangsM
, kNumPrefLangsM
, appleLocsM
, kNumAppleLocsM
, locsToUse
, kMaxLocalizationsToUse
, &status
);
6841 if (U_FAILURE(status
)) {
6842 log_err("FAIL: ualoc_localizationsToUse appleLocsM, langs prefLangsM, status %s\n", u_errorName(status
));
6843 } else if (!equalStringArrays(locsToUseM
, kNumLocsToUseM
, locsToUse
, numLocsToUse
)) {
6844 printStringArray(locsToUseM
, kNumLocsToUseM
, printExpected
, kPrintArrayBufSize
);
6845 printStringArray(locsToUse
, numLocsToUse
, printActual
, kPrintArrayBufSize
);
6846 log_err("FAIL: ualoc_localizationsToUse appleLocsM, langs prefLangsM:\n expect {%s}\n get {%s}\n",
6847 printExpected
, printActual
);