1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2011, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
7 *
8 * File CLOCTST.C
9 *
10 * Modification History:
11 * Name Description
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
14 */
15 #include "cloctst.h"
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include "cintltst.h"
20 #include "cstring.h"
21 #include "uparse.h"
22 #include "uresimp.h"
23
24 #include "unicode/putil.h"
25 #include "unicode/ubrk.h"
26 #include "unicode/uchar.h"
27 #include "unicode/ucol.h"
28 #include "unicode/udat.h"
29 #include "unicode/uloc.h"
30 #include "unicode/umsg.h"
31 #include "unicode/ures.h"
32 #include "unicode/uset.h"
33 #include "unicode/ustring.h"
34 #include "unicode/utypes.h"
35 #include "unicode/ulocdata.h"
36 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */
37 #include "udbgutil.h"
38 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
39
40 static void TestNullDefault(void);
41 static void TestNonexistentLanguageExemplars(void);
42 static void TestLocDataErrorCodeChaining(void);
43 static void TestLanguageExemplarsFallbacks(void);
44
45 static void TestUnicodeDefines(void);
46
47 void PrintDataTable();
48
49 /*---------------------------------------------------
50 table of valid data
51 --------------------------------------------------- */
52 #define LOCALE_SIZE 9
53 #define LOCALE_INFO_SIZE 28
54
55 static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
56 /* language code */
57 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
58 /* script code */
59 { "", "", "", "", "", "", "", "", "" },
60 /* country code */
61 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
62 /* variant code */
63 { "", "", "", "", "NY", "", "", "", "" },
64 /* full name */
65 { "en_US", "fr_FR", "ca_ES",
66 "el_GR", "no_NO_NY", "zh_Hans_CN",
67 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
68 /* ISO-3 language */
69 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
70 /* ISO-3 country */
71 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
72 /* LCID */
73 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
74
75 /* display language (English) */
76 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
77 /* display script code (English) */
78 { "", "", "", "", "", "Simplified", "", "", "" },
79 /* display country (English) */
80 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
81 /* display variant (English) */
82 { "", "", "", "", "NY", "", "", "", "" },
83 /* display name (English) */
84 { "English (United States)", "French (France)", "Catalan (Spain)",
85 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)",
86 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" },
87
88 /* display language (French) */
89 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
90 /* display script code (French) */
91 { "", "", "", "", "", "id\\u00e9ogrammes han simplifi\\u00e9s", "", "", "" },
92 /* display country (French) */
93 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
94 /* display variant (French) */
95 { "", "", "", "", "NY", "", "", "", "" },
96 /* display name (French) */
97 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
98 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (id\\u00e9ogrammes han simplifi\\u00e9s, Chine)",
99 "allemand (Allemagne, Ordonnancement=Ordre de l\\u2019annuaire)", "espagnol (Ordonnancement=Ordre traditionnel)", "japonais (Japon, Calendrier=Calendrier japonais)" },
100
101 /* display language (Catalan) */
102 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" },
103 /* display script code (Catalan) */
104 { "", "", "", "", "", "simplificat", "", "", "" },
105 /* display country (Catalan) */
106 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
107 /* display variant (Catalan) */
108 { "", "", "", "", "NY", "", "", "", "" },
109 /* display name (Catalan) */
110 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
111 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)",
112 "alemany (Alemanya, ordre alfab\\u00e8tic=ordre de la guia telef\\u00F2nica)", "espanyol (ordre alfab\\u00e8tic=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" },
113
114 /* display language (Greek) */
115 {
116 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
117 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
118 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
119 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
120 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
121 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
122 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
123 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
124 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
125 },
126 /* display script code (Greek) */
127
128 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc", "", "", "" },
129 /* display country (Greek) */
130 {
131 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2 \\u03C4\\u03B7\\u03C2 \\u0391\\u03BC\\u03B5\\u03C1\\u03B9\\u03BA\\u03AE\\u03C2",
132 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
133 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
134 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
135 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
136 "\\u039A\\u03AF\\u03BD\\u03B1",
137 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
138 "",
139 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
140 },
141 /* display variant (Greek) */
142 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
143 /* display name (Greek) */
144 {
145 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2 \\u03C4\\u03B7\\u03C2 \\u0391\\u03BC\\u03B5\\u03C1\\u03B9\\u03BA\\u03AE\\u03C2)",
146 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
147 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
148 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
149 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
150 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc, \\u039A\\u03AF\\u03BD\\u03B1)",
151 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1, \\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A3\\u03B5\\u03B9\\u03C1\\u03AC \\u03C4\\u03B1\\u03BE\\u03B9\\u03BD\\u03CC\\u03BC\\u03B7\\u03C3\\u03B7\\u03C2 \\u03C4\\u03B7\\u03BB\\u03B5\\u03C6\\u03C9\\u03BD\\u03B9\\u03BA\\u03BF\\u03CD \\u03BA\\u03B1\\u03C4\\u03B1\\u03BB\\u03CC\\u03B3\\u03BF\\u03C5)",
152 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03C3\\u03B5\\u03B9\\u03C1\\u03AC \\u03C4\\u03B1\\u03BE\\u03B9\\u03BD\\u03CC\\u03BC\\u03B7\\u03C3\\u03B7\\u03C2)",
153 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC (\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1, \\u03B7\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u03B7\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF)"
154 }
155 };
156
157 static UChar*** dataTable=0;
158 enum {
159 ENGLISH = 0,
160 FRENCH = 1,
161 CATALAN = 2,
162 GREEK = 3,
163 NORWEGIAN = 4
164 };
165
166 enum {
167 LANG = 0,
168 SCRIPT = 1,
169 CTRY = 2,
170 VAR = 3,
171 NAME = 4,
172 LANG3 = 5,
173 CTRY3 = 6,
174 LCID = 7,
175 DLANG_EN = 8,
176 DSCRIPT_EN = 9,
177 DCTRY_EN = 10,
178 DVAR_EN = 11,
179 DNAME_EN = 12,
180 DLANG_FR = 13,
181 DSCRIPT_FR = 14,
182 DCTRY_FR = 15,
183 DVAR_FR = 16,
184 DNAME_FR = 17,
185 DLANG_CA = 18,
186 DSCRIPT_CA = 19,
187 DCTRY_CA = 20,
188 DVAR_CA = 21,
189 DNAME_CA = 22,
190 DLANG_EL = 23,
191 DSCRIPT_EL = 24,
192 DCTRY_EL = 25,
193 DVAR_EL = 26,
194 DNAME_EL = 27
195 };
196
197 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
198
199 void addLocaleTest(TestNode** root);
200
addLocaleTest(TestNode ** root)201 void addLocaleTest(TestNode** root)
202 {
203 TESTCASE(TestObsoleteNames); /* srl- move */
204 TESTCASE(TestBasicGetters);
205 TESTCASE(TestNullDefault);
206 TESTCASE(TestPrefixes);
207 TESTCASE(TestSimpleResourceInfo);
208 TESTCASE(TestDisplayNames);
209 TESTCASE(TestGetAvailableLocales);
210 TESTCASE(TestDataDirectory);
211 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
212 TESTCASE(TestISOFunctions);
213 #endif
214 TESTCASE(TestISO3Fallback);
215 TESTCASE(TestUninstalledISO3Names);
216 TESTCASE(TestSimpleDisplayNames);
217 TESTCASE(TestVariantParsing);
218 TESTCASE(TestKeywordVariants);
219 TESTCASE(TestKeywordVariantParsing);
220 TESTCASE(TestCanonicalization);
221 TESTCASE(TestKeywordSet);
222 TESTCASE(TestKeywordSetError);
223 TESTCASE(TestDisplayKeywords);
224 TESTCASE(TestDisplayKeywordValues);
225 TESTCASE(TestGetBaseName);
226 #if !UCONFIG_NO_FILE_IO
227 TESTCASE(TestGetLocale);
228 #endif
229 TESTCASE(TestDisplayNameWarning);
230 TESTCASE(TestNonexistentLanguageExemplars);
231 TESTCASE(TestLocDataErrorCodeChaining);
232 TESTCASE(TestLanguageExemplarsFallbacks);
233 TESTCASE(TestCalendar);
234 TESTCASE(TestDateFormat);
235 TESTCASE(TestCollation);
236 TESTCASE(TestULocale);
237 TESTCASE(TestUResourceBundle);
238 TESTCASE(TestDisplayName);
239 TESTCASE(TestAcceptLanguage);
240 TESTCASE(TestGetLocaleForLCID);
241 TESTCASE(TestOrientation);
242 TESTCASE(TestLikelySubtags);
243 TESTCASE(TestToLanguageTag);
244 TESTCASE(TestForLanguageTag);
245 TESTCASE(TestTrailingNull);
246 TESTCASE(TestUnicodeDefines);
247 }
248
249
250 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
TestBasicGetters()251 static void TestBasicGetters() {
252 int32_t i;
253 int32_t cap;
254 UErrorCode status = U_ZERO_ERROR;
255 char *testLocale = 0;
256 char *temp = 0, *name = 0;
257 log_verbose("Testing Basic Getters\n");
258 for (i = 0; i < LOCALE_SIZE; i++) {
259 testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
260 strcpy(testLocale,rawData2[NAME][i]);
261
262 log_verbose("Testing %s .....\n", testLocale);
263 cap=uloc_getLanguage(testLocale, NULL, 0, &status);
264 if(status==U_BUFFER_OVERFLOW_ERROR){
265 status=U_ZERO_ERROR;
266 temp=(char*)malloc(sizeof(char) * (cap+1));
267 uloc_getLanguage(testLocale, temp, cap+1, &status);
268 }
269 if(U_FAILURE(status)){
270 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status));
271 }
272 if (0 !=strcmp(temp,rawData2[LANG][i])) {
273 log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]);
274 }
275
276
277 cap=uloc_getCountry(testLocale, temp, cap, &status);
278 if(status==U_BUFFER_OVERFLOW_ERROR){
279 status=U_ZERO_ERROR;
280 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
281 uloc_getCountry(testLocale, temp, cap+1, &status);
282 }
283 if(U_FAILURE(status)){
284 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status));
285 }
286 if (0 != strcmp(temp, rawData2[CTRY][i])) {
287 log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]);
288
289 }
290
291 cap=uloc_getVariant(testLocale, temp, cap, &status);
292 if(status==U_BUFFER_OVERFLOW_ERROR){
293 status=U_ZERO_ERROR;
294 temp=(char*)realloc(temp, sizeof(char) * (cap+1));
295 uloc_getVariant(testLocale, temp, cap+1, &status);
296 }
297 if(U_FAILURE(status)){
298 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status));
299 }
300 if (0 != strcmp(temp, rawData2[VAR][i])) {
301 log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]);
302 }
303
304 cap=uloc_getName(testLocale, NULL, 0, &status);
305 if(status==U_BUFFER_OVERFLOW_ERROR){
306 status=U_ZERO_ERROR;
307 name=(char*)malloc(sizeof(char) * (cap+1));
308 uloc_getName(testLocale, name, cap+1, &status);
309 } else if(status==U_ZERO_ERROR) {
310 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale);
311 }
312 if(U_FAILURE(status)){
313 log_err("ERROR: in uloc_getName %s\n", myErrorName(status));
314 }
315 if (0 != strcmp(name, rawData2[NAME][i])){
316 log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]);
317 }
318
319 free(temp);
320 free(name);
321
322 free(testLocale);
323 }
324 }
325
TestNullDefault()326 static void TestNullDefault() {
327 UErrorCode status = U_ZERO_ERROR;
328 char original[ULOC_FULLNAME_CAPACITY];
329
330 uprv_strcpy(original, uloc_getDefault());
331 uloc_setDefault("qq_BLA", &status);
332 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
333 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
334 }
335 uloc_setDefault(NULL, &status);
336 if (uprv_strcmp(uloc_getDefault(), original) != 0) {
337 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
338 }
339
340 {
341 /* Test that set & get of default locale work, and that
342 * default locales are cached and reused, and not overwritten.
343 */
344 const char *n_en_US;
345 const char *n_fr_FR;
346 const char *n2_en_US;
347
348 status = U_ZERO_ERROR;
349 uloc_setDefault("en_US", &status);
350 n_en_US = uloc_getDefault();
351 if (strcmp(n_en_US, "en_US") != 0) {
352 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
353 }
354
355 uloc_setDefault("fr_FR", &status);
356 n_fr_FR = uloc_getDefault();
357 if (strcmp(n_en_US, "en_US") != 0) {
358 log_err("uloc_setDefault altered previously default string."
359 "Expected \"en_US\", got \"%s\"\n", n_en_US);
360 }
361 if (strcmp(n_fr_FR, "fr_FR") != 0) {
362 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR);
363 }
364
365 uloc_setDefault("en_US", &status);
366 n2_en_US = uloc_getDefault();
367 if (strcmp(n2_en_US, "en_US") != 0) {
368 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
369 }
370 if (n2_en_US != n_en_US) {
371 log_err("Default locale cache failed to reuse en_US locale.\n");
372 }
373
374 if (U_FAILURE(status)) {
375 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status));
376 }
377
378 }
379
380 }
381 /* Test the i- and x- and @ and . functionality
382 */
383
384 #define PREFIXBUFSIZ 128
385
TestPrefixes()386 static void TestPrefixes() {
387 int row = 0;
388 int n;
389 const char *loc, *expected;
390
391 static const char * const testData[][7] =
392 {
393 /* NULL canonicalize() column means "expect same as getName()" */
394 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL},
395 {"en", "", "GB", "", "en-gb", "en_GB", NULL},
396 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL},
397 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL},
398 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL},
399 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL},
400
401 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans_PINYIN", "zh_Hans@collation=pinyin"},
402 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy_AREVMDA", NULL},
403
404 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
405 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
406 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
407 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
408 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
409 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
410 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
411 {"no", "", "", "NY", "no__ny", "no__NY", NULL},
412 {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
413 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL},
414 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL},
415 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"},
416 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL},
417 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL},
418 {"12", "3456", "78", "90", "12_3456_78_90", "12_3456_78_90", NULL}, /* total garbage */
419
420 {NULL,NULL,NULL,NULL,NULL,NULL,NULL}
421 };
422
423 static const char * const testTitles[] = {
424 "uloc_getLanguage()",
425 "uloc_getScript()",
426 "uloc_getCountry()",
427 "uloc_getVariant()",
428 "name",
429 "uloc_getName()",
430 "uloc_canonicalize()"
431 };
432
433 char buf[PREFIXBUFSIZ];
434 int32_t len;
435 UErrorCode err;
436
437
438 for(row=0;testData[row][0] != NULL;row++) {
439 loc = testData[row][NAME];
440 log_verbose("Test #%d: %s\n", row, loc);
441
442 err = U_ZERO_ERROR;
443 len=0;
444 buf[0]=0;
445 for(n=0;n<=(NAME+2);n++) {
446 if(n==NAME) continue;
447
448 for(len=0;len<PREFIXBUFSIZ;len++) {
449 buf[len] = '%'; /* Set a tripwire.. */
450 }
451 len = 0;
452
453 switch(n) {
454 case LANG:
455 len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err);
456 break;
457
458 case SCRIPT:
459 len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err);
460 break;
461
462 case CTRY:
463 len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err);
464 break;
465
466 case VAR:
467 len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err);
468 break;
469
470 case NAME+1:
471 len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err);
472 break;
473
474 case NAME+2:
475 len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err);
476 break;
477
478 default:
479 strcpy(buf, "**??");
480 len=4;
481 }
482
483 if(U_FAILURE(err)) {
484 log_err("#%d: %s on %s: err %s\n",
485 row, testTitles[n], loc, u_errorName(err));
486 } else {
487 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
488 row, testTitles[n], loc, buf, len);
489
490 if(len != (int32_t)strlen(buf)) {
491 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
492 row, testTitles[n], loc, buf, len, strlen(buf)+1);
493
494 }
495
496 /* see if they smashed something */
497 if(buf[len+1] != '%') {
498 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
499 row, testTitles[n], loc, buf, buf[len+1]);
500 }
501
502 expected = testData[row][n];
503 if (expected == NULL && n == (NAME+2)) {
504 /* NULL expected canonicalize() means "expect same as getName()" */
505 expected = testData[row][NAME+1];
506 }
507 if(strcmp(buf, expected)) {
508 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
509 row, testTitles[n], loc, buf, expected);
510
511 }
512 }
513 }
514 }
515 }
516
517
518 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */
TestSimpleResourceInfo()519 static void TestSimpleResourceInfo() {
520 int32_t i;
521 char* testLocale = 0;
522 UChar* expected = 0;
523
524 const char* temp;
525 char temp2[20];
526 testLocale=(char*)malloc(sizeof(char) * 1);
527 expected=(UChar*)malloc(sizeof(UChar) * 1);
528
529 setUpDataTable();
530 log_verbose("Testing getISO3Language and getISO3Country\n");
531 for (i = 0; i < LOCALE_SIZE; i++) {
532
533 testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
534 u_austrcpy(testLocale, dataTable[NAME][i]);
535
536 log_verbose("Testing %s ......\n", testLocale);
537
538 temp=uloc_getISO3Language(testLocale);
539 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
540 u_uastrcpy(expected,temp);
541 if (0 != u_strcmp(expected, dataTable[LANG3][i])) {
542 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected),
543 austrdup(dataTable[LANG3][i]));
544 }
545
546 temp=uloc_getISO3Country(testLocale);
547 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
548 u_uastrcpy(expected,temp);
549 if (0 != u_strcmp(expected, dataTable[CTRY3][i])) {
550 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected),
551 austrdup(dataTable[CTRY3][i]));
552 }
553 sprintf(temp2, "%x", (int)uloc_getLCID(testLocale));
554 if (strcmp(temp2, rawData2[LCID][i]) != 0) {
555 log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]);
556 }
557 }
558
559 free(expected);
560 free(testLocale);
561 cleanUpDataTable();
562 }
563
564 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null
565 * if there's room but won't be included in result. result < 0 indicates an error.
566 * Returns the number of chars written (not those that would be written if there's enough room.*/
UCharsToEscapedAscii(const UChar * utext,int32_t len,char * resultChars,int32_t buflen)567 static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) {
568 static const struct {
569 char escapedChar;
570 UChar sourceVal;
571 } ESCAPE_MAP[] = {
572 /*a*/ {'a', 0x07},
573 /*b*/ {'b', 0x08},
574 /*e*/ {'e', 0x1b},
575 /*f*/ {'f', 0x0c},
576 /*n*/ {'n', 0x0a},
577 /*r*/ {'r', 0x0d},
578 /*t*/ {'t', 0x09},
579 /*v*/ {'v', 0x0b}
580 };
581 static const int32_t ESCAPE_MAP_LENGTH = sizeof(ESCAPE_MAP)/sizeof(ESCAPE_MAP[0]);
582 static const char HEX_DIGITS[] = {
583 '0', '1', '2', '3', '4', '5', '6', '7',
584 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
585 };
586 int32_t i, j;
587 int32_t resultLen = 0;
588 const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */
589 const int32_t escapeLimit1 = buflen-2;
590 const int32_t escapeLimit2 = buflen-6;
591 UChar uc;
592
593 if(utext==NULL || resultChars==NULL || buflen<0) {
594 return -1;
595 }
596
597 for(i=0;i<limit && resultLen<buflen;++i) {
598 uc=utext[i];
599 if(len<0 && uc==0) {
600 break;
601 }
602 if(uc<0x20) {
603 for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) {
604 }
605 if(j<ESCAPE_MAP_LENGTH) {
606 if(resultLen>escapeLimit1) {
607 break;
608 }
609 resultChars[resultLen++]='\\';
610 resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar;
611 continue;
612 }
613 } else if(uc<0x7f) {
614 u_austrncpy(resultChars + resultLen, &uc, 1);
615 resultLen++;
616 continue;
617 }
618
619 if(resultLen>escapeLimit2) {
620 break;
621 }
622
623 /* have to escape the uchar */
624 resultChars[resultLen++]='\\';
625 resultChars[resultLen++]='u';
626 resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff];
627 resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff];
628 resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff];
629 resultChars[resultLen++]=HEX_DIGITS[uc&0xff];
630 }
631
632 if(resultLen<buflen) {
633 resultChars[resultLen] = 0;
634 }
635
636 return resultLen;
637 }
638
639 /*
640 * Jitterbug 2439 -- markus 20030425
641 *
642 * The lookup of display names must not fall back through the default
643 * locale because that yields useless results.
644 */
TestDisplayNames()645 static void TestDisplayNames()
646 {
647 UChar buffer[100];
648 UErrorCode errorCode=U_ZERO_ERROR;
649 int32_t length;
650 log_verbose("Testing getDisplayName for different locales\n");
651
652 log_verbose(" In locale = en_US...\n");
653 doTestDisplayNames("en_US", DLANG_EN);
654 log_verbose(" In locale = fr_FR....\n");
655 doTestDisplayNames("fr_FR", DLANG_FR);
656 log_verbose(" In locale = ca_ES...\n");
657 doTestDisplayNames("ca_ES", DLANG_CA);
658 log_verbose(" In locale = gr_EL..\n");
659 doTestDisplayNames("el_GR", DLANG_EL);
660
661 /* test that the default locale has a display name for its own language */
662 errorCode=U_ZERO_ERROR;
663 length=uloc_getDisplayLanguage(NULL, NULL, buffer, LENGTHOF(buffer), &errorCode);
664 if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) {
665 /* check <=3 to reject getting the language code as a display name */
666 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));
667 }
668
669 /* test that we get the language code itself for an unknown language, and a default warning */
670 errorCode=U_ZERO_ERROR;
671 length=uloc_getDisplayLanguage("qq", "rr", buffer, LENGTHOF(buffer), &errorCode);
672 if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
673 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
674 }
675
676 /* test that we get a default warning for a display name where one component is unknown (4255) */
677 errorCode=U_ZERO_ERROR;
678 length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, LENGTHOF(buffer), &errorCode);
679 if(errorCode!=U_USING_DEFAULT_WARNING) {
680 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode));
681 }
682
683 {
684 int32_t i;
685 static const char *aLocale = "es@collation=traditional;calendar=japanese";
686 static const char *testL[] = { "en_US",
687 "fr_FR",
688 "ca_ES",
689 "el_GR" };
690 static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */
691 "espagnol (Calendrier=Calendrier japonais, Ordonnancement=Ordre traditionnel)",
692 "espanyol (calendari=calendari japon\\u00e8s, ordre alfab\\u00e8tic=ordre tradicional)",
693 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03B7\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u03B7\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF, \\u03C4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03C3\\u03B5\\u03B9\\u03C1\\u03AC \\u03C4\\u03B1\\u03BE\\u03B9\\u03BD\\u03CC\\u03BC\\u03B7\\u03C3\\u03B7\\u03C2)" };
694 UChar *expectBuffer;
695
696 for(i=0;i<LENGTHOF(testL);i++) {
697 errorCode = U_ZERO_ERROR;
698 uloc_getDisplayName(aLocale, testL[i], buffer, LENGTHOF(buffer), &errorCode);
699 if(U_FAILURE(errorCode)) {
700 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode));
701 } else {
702 expectBuffer = CharsToUChars(expect[i]);
703 if(u_strcmp(buffer,expectBuffer)) {
704 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));
705 } else {
706 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]);
707 }
708 free(expectBuffer);
709 }
710 }
711 }
712
713 /* test that we properly preflight and return data when there's a non-default pattern,
714 see ticket #8262. */
715 {
716 int32_t i;
717 static const char *locale="az_Cyrl";
718 static const char *displayLocale="ja";
719 static const char *expectedChars =
720 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e"
721 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)";
722 UErrorCode ec=U_ZERO_ERROR;
723 UChar result[256];
724 int32_t len;
725 int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec);
726 /* inconvenient semantics when preflighting, this condition is expected... */
727 if(ec==U_BUFFER_OVERFLOW_ERROR) {
728 ec=U_ZERO_ERROR;
729 }
730 len=uloc_getDisplayName(locale, displayLocale, result, LENGTHOF(result), &ec);
731 if(U_FAILURE(ec)) {
732 log_err("uloc_getDisplayName(%s, %s...) returned error: %s",
733 locale, displayLocale, u_errorName(ec));
734 } else {
735 UChar *expected=CharsToUChars(expectedChars);
736 int32_t expectedLen=u_strlen(expected);
737
738 if(len!=expectedLen) {
739 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d",
740 locale, displayLocale, len, expectedLen);
741 } else if(preflightLen!=expectedLen) {
742 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d",
743 locale, displayLocale, preflightLen, expectedLen);
744 } else if(u_strncmp(result, expected, len)) {
745 int32_t cap=len*6+1; /* worst case + space for trailing null */
746 char* resultChars=(char*)malloc(cap);
747 int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap);
748 if(resultCharsLen<0 || resultCharsLen<cap-1) {
749 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale);
750 } else {
751 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'",
752 locale, displayLocale, resultChars, expectedChars);
753 }
754 free(resultChars);
755 resultChars=NULL;
756 } else {
757 /* test all buffer sizes */
758 for(i=len+1;i>=0;--i) {
759 len=uloc_getDisplayName(locale, displayLocale, result, i, &ec);
760 if(ec==U_BUFFER_OVERFLOW_ERROR) {
761 ec=U_ZERO_ERROR;
762 }
763 if(U_FAILURE(ec)) {
764 log_err("using buffer of length %d returned error %s", i, u_errorName(ec));
765 break;
766 }
767 if(len!=expectedLen) {
768 log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len);
769 break;
770 }
771 /* There's no guarantee about what's in the buffer if we've overflowed, in particular,
772 * we don't know that it's been filled, so no point in checking. */
773 }
774 }
775
776 free(expected);
777 }
778 }
779 }
780
781
782 /* test for uloc_getAvialable() and uloc_countAvilable()*/
TestGetAvailableLocales()783 static void TestGetAvailableLocales()
784 {
785
786 const char *locList;
787 int32_t locCount,i;
788
789 log_verbose("Testing the no of avialable locales\n");
790 locCount=uloc_countAvailable();
791 if (locCount == 0)
792 log_data_err("countAvailable() returned an empty list!\n");
793
794 /* use something sensible w/o hardcoding the count */
795 else if(locCount < 0){
796 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount);
797 }
798 else{
799 log_info("Number of locales returned = %d\n", locCount);
800 }
801 for(i=0;i<locCount;i++){
802 locList=uloc_getAvailable(i);
803
804 log_verbose(" %s\n", locList);
805 }
806 }
807
808 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
TestDataDirectory()809 static void TestDataDirectory()
810 {
811
812 char oldDirectory[512];
813 const char *temp,*testValue1,*testValue2,*testValue3;
814 const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */
815
816 log_verbose("Testing getDataDirectory()\n");
817 temp = u_getDataDirectory();
818 strcpy(oldDirectory, temp);
819
820 testValue1=uloc_getISO3Language("en_US");
821 log_verbose("first fetch of language retrieved %s\n", testValue1);
822
823 if (0 != strcmp(testValue1,"eng")){
824 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1);
825 }
826
827 /*defining the path for DataDirectory */
828 log_verbose("Testing setDataDirectory\n");
829 u_setDataDirectory( path );
830 if(strcmp(path, u_getDataDirectory())==0)
831 log_verbose("setDataDirectory working fine\n");
832 else
833 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path);
834
835 testValue2=uloc_getISO3Language("en_US");
836 log_verbose("second fetch of language retrieved %s \n", testValue2);
837
838 u_setDataDirectory(oldDirectory);
839 testValue3=uloc_getISO3Language("en_US");
840 log_verbose("third fetch of language retrieved %s \n", testValue3);
841
842 if (0 != strcmp(testValue3,"eng")) {
843 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3);
844 }
845 }
846
847
848
849 /*=========================================================== */
850
851 static UChar _NUL=0;
852
doTestDisplayNames(const char * displayLocale,int32_t compareIndex)853 static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
854 {
855 UErrorCode status = U_ZERO_ERROR;
856 int32_t i;
857 int32_t maxresultsize;
858
859 const char *testLocale;
860
861
862 UChar *testLang = 0;
863 UChar *testScript = 0;
864 UChar *testCtry = 0;
865 UChar *testVar = 0;
866 UChar *testName = 0;
867
868
869 UChar* expectedLang = 0;
870 UChar* expectedScript = 0;
871 UChar* expectedCtry = 0;
872 UChar* expectedVar = 0;
873 UChar* expectedName = 0;
874
875 setUpDataTable();
876
877 for(i=0;i<LOCALE_SIZE; ++i)
878 {
879 testLocale=rawData2[NAME][i];
880
881 log_verbose("Testing..... %s\n", testLocale);
882
883 maxresultsize=0;
884 maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
885 if(status==U_BUFFER_OVERFLOW_ERROR)
886 {
887 status=U_ZERO_ERROR;
888 testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
889 uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
890 }
891 else
892 {
893 testLang=&_NUL;
894 }
895 if(U_FAILURE(status)){
896 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
897 }
898
899 maxresultsize=0;
900 maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status);
901 if(status==U_BUFFER_OVERFLOW_ERROR)
902 {
903 status=U_ZERO_ERROR;
904 testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
905 uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status);
906 }
907 else
908 {
909 testScript=&_NUL;
910 }
911 if(U_FAILURE(status)){
912 log_err("Error in getDisplayScript() %s\n", myErrorName(status));
913 }
914
915 maxresultsize=0;
916 maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
917 if(status==U_BUFFER_OVERFLOW_ERROR)
918 {
919 status=U_ZERO_ERROR;
920 testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
921 uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
922 }
923 else
924 {
925 testCtry=&_NUL;
926 }
927 if(U_FAILURE(status)){
928 log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
929 }
930
931 maxresultsize=0;
932 maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
933 if(status==U_BUFFER_OVERFLOW_ERROR)
934 {
935 status=U_ZERO_ERROR;
936 testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
937 uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
938 }
939 else
940 {
941 testVar=&_NUL;
942 }
943 if(U_FAILURE(status)){
944 log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
945 }
946
947 maxresultsize=0;
948 maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
949 if(status==U_BUFFER_OVERFLOW_ERROR)
950 {
951 status=U_ZERO_ERROR;
952 testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
953 uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
954 }
955 else
956 {
957 testName=&_NUL;
958 }
959 if(U_FAILURE(status)){
960 log_err("Error in getDisplayName() %s\n", myErrorName(status));
961 }
962
963 expectedLang=dataTable[compareIndex][i];
964 if(u_strlen(expectedLang)== 0)
965 expectedLang=dataTable[DLANG_EN][i];
966
967 expectedScript=dataTable[compareIndex + 1][i];
968 if(u_strlen(expectedScript)== 0)
969 expectedScript=dataTable[DSCRIPT_EN][i];
970
971 expectedCtry=dataTable[compareIndex + 2][i];
972 if(u_strlen(expectedCtry)== 0)
973 expectedCtry=dataTable[DCTRY_EN][i];
974
975 expectedVar=dataTable[compareIndex + 3][i];
976 if(u_strlen(expectedVar)== 0)
977 expectedVar=dataTable[DVAR_EN][i];
978
979 expectedName=dataTable[compareIndex + 4][i];
980 if(u_strlen(expectedName) == 0)
981 expectedName=dataTable[DNAME_EN][i];
982
983 if (0 !=u_strcmp(testLang,expectedLang)) {
984 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
985 }
986
987 if (0 != u_strcmp(testScript,expectedScript)) {
988 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale);
989 }
990
991 if (0 != u_strcmp(testCtry,expectedCtry)) {
992 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
993 }
994
995 if (0 != u_strcmp(testVar,expectedVar)) {
996 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
997 }
998
999 if(0 != u_strcmp(testName, expectedName)) {
1000 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale);
1001 }
1002
1003 if(testName!=&_NUL) {
1004 free(testName);
1005 }
1006 if(testLang!=&_NUL) {
1007 free(testLang);
1008 }
1009 if(testScript!=&_NUL) {
1010 free(testScript);
1011 }
1012 if(testCtry!=&_NUL) {
1013 free(testCtry);
1014 }
1015 if(testVar!=&_NUL) {
1016 free(testVar);
1017 }
1018 }
1019 cleanUpDataTable();
1020 }
1021
1022 /* test for uloc_getISOLanguages, uloc_getISOCountries */
TestISOFunctions()1023 static void TestISOFunctions()
1024 {
1025 const char* const* str=uloc_getISOLanguages();
1026 const char* const* str1=uloc_getISOCountries();
1027 const char* test;
1028 const char *key = NULL;
1029 int32_t count = 0, skipped = 0;
1030 int32_t expect;
1031 UResourceBundle *res;
1032 UResourceBundle *subRes;
1033 UErrorCode status = U_ZERO_ERROR;
1034
1035 /* test getISOLanguages*/
1036 /*str=uloc_getISOLanguages(); */
1037 log_verbose("Testing ISO Languages: \n");
1038
1039 /* use structLocale - this data is no longer in root */
1040 res = ures_openDirect(loadTestData(&status), "structLocale", &status);
1041 subRes = ures_getByKey(res, "Languages", NULL, &status);
1042 if (U_FAILURE(status)) {
1043 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status));
1044 return;
1045 }
1046
1047 expect = ures_getSize(subRes);
1048 for(count = 0; *(str+count) != 0; count++)
1049 {
1050 key = NULL;
1051 test = *(str+count);
1052 status = U_ZERO_ERROR;
1053
1054 do {
1055 /* Skip over language tags. This API only returns language codes. */
1056 skipped += (key != NULL);
1057 ures_getNextString(subRes, NULL, &key, &status);
1058 }
1059 while (key != NULL && strchr(key, '_'));
1060
1061 if(key == NULL)
1062 break;
1063 /* TODO: Consider removing sh, which is deprecated */
1064 if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) {
1065 ures_getNextString(subRes, NULL, &key, &status);
1066 skipped++;
1067 }
1068 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1069 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1070 if(strcmp(test,key)) {
1071 /* The first difference usually implies the place where things get out of sync */
1072 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1073 }
1074 #endif
1075
1076 if(!strcmp(test,"in"))
1077 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1078 if(!strcmp(test,"iw"))
1079 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1080 if(!strcmp(test,"ji"))
1081 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1082 if(!strcmp(test,"jw"))
1083 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1084 if(!strcmp(test,"sh"))
1085 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
1086 }
1087
1088 expect -= skipped; /* Ignore the skipped resources from structLocale */
1089
1090 if(count!=expect) {
1091 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect);
1092 }
1093
1094 subRes = ures_getByKey(res, "Countries", subRes, &status);
1095 log_verbose("Testing ISO Countries");
1096 skipped = 0;
1097 expect = ures_getSize(subRes) - 1; /* Skip ZZ */
1098 for(count = 0; *(str1+count) != 0; count++)
1099 {
1100 key = NULL;
1101 test = *(str1+count);
1102 do {
1103 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
1104 skipped += (key != NULL);
1105 ures_getNextString(subRes, NULL, &key, &status);
1106 }
1107 while (key != NULL && strlen(key) != 2);
1108
1109 if(key == NULL)
1110 break;
1111 /* TODO: Consider removing CS, which is deprecated */
1112 while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) {
1113 ures_getNextString(subRes, NULL, &key, &status);
1114 skipped++;
1115 }
1116 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
1117 /* This code only works on ASCII machines where the keys are stored in ASCII order */
1118 if(strcmp(test,key)) {
1119 /* The first difference usually implies the place where things get out of sync */
1120 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
1121 }
1122 #endif
1123 if(!strcmp(test,"FX"))
1124 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1125 if(!strcmp(test,"YU"))
1126 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1127 if(!strcmp(test,"ZR"))
1128 log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
1129 }
1130
1131 ures_getNextString(subRes, NULL, &key, &status);
1132 if (strcmp(key, "ZZ") != 0) {
1133 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key);
1134 }
1135 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
1136 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
1137 key = NULL;
1138 do {
1139 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
1140 skipped += (key != NULL);
1141 ures_getNextString(subRes, NULL, &key, &status);
1142 }
1143 while (U_SUCCESS(status) && key != NULL && strlen(key) != 2);
1144 #endif
1145 expect -= skipped; /* Ignore the skipped resources from structLocale */
1146 if(count!=expect)
1147 {
1148 log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect);
1149 }
1150 ures_close(subRes);
1151 ures_close(res);
1152 }
1153
setUpDataTable()1154 static void setUpDataTable()
1155 {
1156 int32_t i,j;
1157 dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE));
1158
1159 for (i = 0; i < LOCALE_INFO_SIZE; i++) {
1160 dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE));
1161 for (j = 0; j < LOCALE_SIZE; j++){
1162 dataTable[i][j] = CharsToUChars(rawData2[i][j]);
1163 }
1164 }
1165 }
1166
cleanUpDataTable()1167 static void cleanUpDataTable()
1168 {
1169 int32_t i,j;
1170 if(dataTable != NULL) {
1171 for (i=0; i<LOCALE_INFO_SIZE; i++) {
1172 for(j = 0; j < LOCALE_SIZE; j++) {
1173 free(dataTable[i][j]);
1174 }
1175 free(dataTable[i]);
1176 }
1177 free(dataTable);
1178 }
1179 dataTable = NULL;
1180 }
1181
1182 /**
1183 * @bug 4011756 4011380
1184 */
TestISO3Fallback()1185 static void TestISO3Fallback()
1186 {
1187 const char* test="xx_YY";
1188
1189 const char * result;
1190
1191 result = uloc_getISO3Language(test);
1192
1193 /* Conform to C API usage */
1194
1195 if (!result || (result[0] != 0))
1196 log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
1197
1198 result = uloc_getISO3Country(test);
1199
1200 if (!result || (result[0] != 0))
1201 log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
1202 }
1203
1204 /**
1205 * @bug 4118587
1206 */
TestSimpleDisplayNames()1207 static void TestSimpleDisplayNames()
1208 {
1209 /*
1210 This test is different from TestDisplayNames because TestDisplayNames checks
1211 fallback behavior, combination of language and country names to form locale
1212 names, and other stuff like that. This test just checks specific language
1213 and country codes to make sure we have the correct names for them.
1214 */
1215 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" };
1216 const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish",
1217 "Zhuang", "419" };
1218 const char* inLocale [] = { "en_US", "zh_Hant"};
1219 UErrorCode status=U_ZERO_ERROR;
1220
1221 int32_t i;
1222 int32_t localeIndex = 0;
1223 for (i = 0; i < 7; i++) {
1224 UChar *testLang=0;
1225 UChar *expectedLang=0;
1226 int size=0;
1227
1228 if (i == 6) {
1229 localeIndex = 1; /* Use the second locale for the rest of the test. */
1230 }
1231
1232 size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status);
1233 if(status==U_BUFFER_OVERFLOW_ERROR) {
1234 status=U_ZERO_ERROR;
1235 testLang=(UChar*)malloc(sizeof(UChar) * (size + 1));
1236 uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status);
1237 }
1238 expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1));
1239 u_uastrcpy(expectedLang, languageNames[i]);
1240 if (u_strcmp(testLang, expectedLang) != 0)
1241 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
1242 languageCodes[i], languageNames[i], austrdup(testLang));
1243 free(testLang);
1244 free(expectedLang);
1245 }
1246
1247 }
1248
1249 /**
1250 * @bug 4118595
1251 */
TestUninstalledISO3Names()1252 static void TestUninstalledISO3Names()
1253 {
1254 /* This test checks to make sure getISO3Language and getISO3Country work right
1255 even for locales that are not installed. */
1256 static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
1257 "ss", "tw", "zu" };
1258 static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
1259 "ssw", "twi", "zul" };
1260 static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
1261 "ss_SB", "tw_TC", "zu_ZW" };
1262 static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1263 "SLB", "TCA", "ZWE" };
1264 int32_t i;
1265
1266 for (i = 0; i < 8; i++) {
1267 UErrorCode err = U_ZERO_ERROR;
1268 const char *test;
1269 test = uloc_getISO3Language(iso2Languages[i]);
1270 if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err))
1271 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1272 iso2Languages[i], iso3Languages[i], test, myErrorName(err));
1273 }
1274 for (i = 0; i < 8; i++) {
1275 UErrorCode err = U_ZERO_ERROR;
1276 const char *test;
1277 test = uloc_getISO3Country(iso2Countries[i]);
1278 if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err))
1279 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
1280 iso2Countries[i], iso3Countries[i], test, myErrorName(err));
1281 }
1282 }
1283
1284
TestVariantParsing()1285 static void TestVariantParsing()
1286 {
1287 static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth";
1288 static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
1289 static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
1290 static const char* shortVariant="fr_FR_foo";
1291 static const char* bogusVariant="fr_FR__foo";
1292 static const char* bogusVariant2="fr_FR_foo_";
1293 static const char* bogusVariant3="fr_FR__foo_";
1294
1295
1296 UChar displayVar[100];
1297 UChar displayName[100];
1298 UErrorCode status=U_ZERO_ERROR;
1299 UChar* got=0;
1300 int32_t size=0;
1301 size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status);
1302 if(status==U_BUFFER_OVERFLOW_ERROR) {
1303 status=U_ZERO_ERROR;
1304 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1305 uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status);
1306 }
1307 else {
1308 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1309 }
1310 u_uastrcpy(displayVar, dispVar);
1311 if(u_strcmp(got,displayVar)!=0) {
1312 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got));
1313 }
1314 size=0;
1315 size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status);
1316 if(status==U_BUFFER_OVERFLOW_ERROR) {
1317 status=U_ZERO_ERROR;
1318 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1319 uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status);
1320 }
1321 else {
1322 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1323 }
1324 u_uastrcpy(displayName, dispName);
1325 if(u_strcmp(got,displayName)!=0) {
1326 if (status == U_USING_DEFAULT_WARNING) {
1327 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status));
1328 } else {
1329 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got));
1330 }
1331 }
1332
1333 size=0;
1334 status=U_ZERO_ERROR;
1335 size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status);
1336 if(status==U_BUFFER_OVERFLOW_ERROR) {
1337 status=U_ZERO_ERROR;
1338 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1339 uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status);
1340 }
1341 else {
1342 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1343 }
1344 if(strcmp(austrdup(got),"FOO")!=0) {
1345 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got));
1346 }
1347 size=0;
1348 status=U_ZERO_ERROR;
1349 size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status);
1350 if(status==U_BUFFER_OVERFLOW_ERROR) {
1351 status=U_ZERO_ERROR;
1352 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1353 uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status);
1354 }
1355 else {
1356 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1357 }
1358 if(strcmp(austrdup(got),"_FOO")!=0) {
1359 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got));
1360 }
1361 size=0;
1362 status=U_ZERO_ERROR;
1363 size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status);
1364 if(status==U_BUFFER_OVERFLOW_ERROR) {
1365 status=U_ZERO_ERROR;
1366 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1367 uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status);
1368 }
1369 else {
1370 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1371 }
1372 if(strcmp(austrdup(got),"FOO_")!=0) {
1373 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got));
1374 }
1375 size=0;
1376 status=U_ZERO_ERROR;
1377 size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status);
1378 if(status==U_BUFFER_OVERFLOW_ERROR) {
1379 status=U_ZERO_ERROR;
1380 got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
1381 uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status);
1382 }
1383 else {
1384 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
1385 }
1386 if(strcmp(austrdup(got),"_FOO_")!=0) {
1387 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got));
1388 }
1389 free(got);
1390 }
1391
1392
TestObsoleteNames(void)1393 static void TestObsoleteNames(void)
1394 {
1395 int32_t i;
1396 UErrorCode status = U_ZERO_ERROR;
1397 char buff[256];
1398
1399 static const struct
1400 {
1401 char locale[9];
1402 char lang3[4];
1403 char lang[4];
1404 char ctry3[4];
1405 char ctry[4];
1406 } tests[] =
1407 {
1408 { "eng_USA", "eng", "en", "USA", "US" },
1409 { "kok", "kok", "kok", "", "" },
1410 { "in", "ind", "in", "", "" },
1411 { "id", "ind", "id", "", "" }, /* NO aliasing */
1412 { "sh", "srp", "sh", "", "" },
1413 { "zz_CS", "", "zz", "SCG", "CS" },
1414 { "zz_FX", "", "zz", "FXX", "FX" },
1415 { "zz_RO", "", "zz", "ROU", "RO" },
1416 { "zz_TP", "", "zz", "TMP", "TP" },
1417 { "zz_TL", "", "zz", "TLS", "TL" },
1418 { "zz_ZR", "", "zz", "ZAR", "ZR" },
1419 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
1420 { "zz_ROM", "", "zz", "ROU", "RO" },
1421 { "zz_ROU", "", "zz", "ROU", "RO" },
1422 { "zz_ZAR", "", "zz", "ZAR", "ZR" },
1423 { "zz_TMP", "", "zz", "TMP", "TP" },
1424 { "zz_TLS", "", "zz", "TLS", "TL" },
1425 { "zz_YUG", "", "zz", "YUG", "YU" },
1426 { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
1427 { "iw", "heb", "iw", "", "" },
1428 { "ji", "yid", "ji", "", "" },
1429 { "jw", "jaw", "jw", "", "" },
1430 { "sh", "srp", "sh", "", "" },
1431 { "", "", "", "", "" }
1432 };
1433
1434 for(i=0;tests[i].locale[0];i++)
1435 {
1436 const char *locale;
1437
1438 locale = tests[i].locale;
1439 log_verbose("** %s:\n", locale);
1440
1441 status = U_ZERO_ERROR;
1442 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1443 {
1444 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1445 locale, uloc_getISO3Language(locale), tests[i].lang3);
1446 }
1447 else
1448 {
1449 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1450 uloc_getISO3Language(locale) );
1451 }
1452
1453 status = U_ZERO_ERROR;
1454 uloc_getLanguage(locale, buff, 256, &status);
1455 if(U_FAILURE(status))
1456 {
1457 log_err("FAIL: error getting language from %s\n", locale);
1458 }
1459 else
1460 {
1461 if(strcmp(buff,tests[i].lang))
1462 {
1463 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
1464 locale, buff, tests[i].lang);
1465 }
1466 else
1467 {
1468 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff);
1469 }
1470 }
1471 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
1472 {
1473 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
1474 locale, uloc_getISO3Language(locale), tests[i].lang3);
1475 }
1476 else
1477 {
1478 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
1479 uloc_getISO3Language(locale) );
1480 }
1481
1482 if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale)))
1483 {
1484 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
1485 locale, uloc_getISO3Country(locale), tests[i].ctry3);
1486 }
1487 else
1488 {
1489 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
1490 uloc_getISO3Country(locale) );
1491 }
1492
1493 status = U_ZERO_ERROR;
1494 uloc_getCountry(locale, buff, 256, &status);
1495 if(U_FAILURE(status))
1496 {
1497 log_err("FAIL: error getting country from %s\n", locale);
1498 }
1499 else
1500 {
1501 if(strcmp(buff,tests[i].ctry))
1502 {
1503 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
1504 locale, buff, tests[i].ctry);
1505 }
1506 else
1507 {
1508 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff);
1509 }
1510 }
1511 }
1512
1513 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
1514 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
1515 }
1516
1517 if (uloc_getLCID("iw") != uloc_getLCID("he")) {
1518 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
1519 }
1520
1521 #if 0
1522
1523 i = uloc_getLanguage("kok",NULL,0,&icu_err);
1524 if(U_FAILURE(icu_err))
1525 {
1526 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err));
1527 }
1528
1529 icu_err = U_ZERO_ERROR;
1530 uloc_getLanguage("kok",r1_buff,12,&icu_err);
1531 if(U_FAILURE(icu_err))
1532 {
1533 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err));
1534 }
1535
1536 r1_addr = (char *)uloc_getISO3Language("kok");
1537
1538 icu_err = U_ZERO_ERROR;
1539 if (strcmp(r1_buff,"kok") != 0)
1540 {
1541 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff);
1542 line--;
1543 }
1544 r1_addr = (char *)uloc_getISO3Language("in");
1545 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1546 if (strcmp(r1_buff,"id") != 0)
1547 {
1548 printf("uloc_getLanguage error (%s)\n",r1_buff);
1549 line--;
1550 }
1551 r1_addr = (char *)uloc_getISO3Language("sh");
1552 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
1553 if (strcmp(r1_buff,"sr") != 0)
1554 {
1555 printf("uloc_getLanguage error (%s)\n",r1_buff);
1556 line--;
1557 }
1558
1559 r1_addr = (char *)uloc_getISO3Country("zz_ZR");
1560 strcpy(p1_buff,"zz_");
1561 strcat(p1_buff,r1_addr);
1562 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1563 if (strcmp(r1_buff,"ZR") != 0)
1564 {
1565 printf("uloc_getCountry error (%s)\n",r1_buff);
1566 line--;
1567 }
1568 r1_addr = (char *)uloc_getISO3Country("zz_FX");
1569 strcpy(p1_buff,"zz_");
1570 strcat(p1_buff,r1_addr);
1571 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
1572 if (strcmp(r1_buff,"FX") != 0)
1573 {
1574 printf("uloc_getCountry error (%s)\n",r1_buff);
1575 line--;
1576 }
1577
1578 #endif
1579
1580 }
1581
TestKeywordVariants(void)1582 static void TestKeywordVariants(void)
1583 {
1584 static const struct {
1585 const char *localeID;
1586 const char *expectedLocaleID;
1587 const char *expectedLocaleIDNoKeywords;
1588 const char *expectedCanonicalID;
1589 const char *expectedKeywords[10];
1590 int32_t numKeywords;
1591 UErrorCode expectedStatus; /* from uloc_openKeywords */
1592 } testCases[] = {
1593 {
1594 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1595 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1596 "de_DE",
1597 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1598 {"calendar", "collation", "currency"},
1599 3,
1600 U_ZERO_ERROR
1601 },
1602 {
1603 "de_DE@euro",
1604 "de_DE@euro",
1605 "de_DE",
1606 "de_DE@currency=EUR",
1607 {"","","","","","",""},
1608 0,
1609 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1610 },
1611 {
1612 "de_DE@euro;collation=phonebook",
1613 "de_DE", /* error result; bad format */
1614 "de_DE", /* error result; bad format */
1615 "de_DE", /* error result; bad format */
1616 {"","","","","","",""},
1617 0,
1618 U_INVALID_FORMAT_ERROR
1619 }
1620 };
1621 UErrorCode status = U_ZERO_ERROR;
1622
1623 int32_t i = 0, j = 0;
1624 int32_t resultLen = 0;
1625 char buffer[256];
1626 UEnumeration *keywords;
1627 int32_t keyCount = 0;
1628 const char *keyword = NULL;
1629 int32_t keywordLen = 0;
1630
1631 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
1632 status = U_ZERO_ERROR;
1633 *buffer = 0;
1634 keywords = uloc_openKeywords(testCases[i].localeID, &status);
1635
1636 if(status != testCases[i].expectedStatus) {
1637 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
1638 testCases[i].localeID,
1639 u_errorName(testCases[i].expectedStatus), u_errorName(status));
1640 }
1641 status = U_ZERO_ERROR;
1642 if(keywords) {
1643 if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
1644 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1645 }
1646 if(keyCount) {
1647 j = 0;
1648 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1649 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1650 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1651 }
1652 j++;
1653 }
1654 j = 0;
1655 uenum_reset(keywords, &status);
1656 while((keyword = uenum_next(keywords, &keywordLen, &status))) {
1657 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1658 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1659 }
1660 j++;
1661 }
1662 }
1663 uenum_close(keywords);
1664 }
1665 resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
1666 if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
1667 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
1668 testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
1669 }
1670 resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
1671 if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
1672 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
1673 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
1674 }
1675 }
1676
1677 }
1678
TestKeywordVariantParsing(void)1679 static void TestKeywordVariantParsing(void)
1680 {
1681 static const struct {
1682 const char *localeID;
1683 const char *keyword;
1684 const char *expectedValue;
1685 } testCases[] = {
1686 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
1687 { "de_DE", "collation", ""},
1688 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
1689 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
1690 };
1691
1692 UErrorCode status = U_ZERO_ERROR;
1693
1694 int32_t i = 0;
1695 int32_t resultLen = 0;
1696 char buffer[256];
1697
1698 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
1699 *buffer = 0;
1700 resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
1701 if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
1702 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1703 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
1704 }
1705 }
1706 }
1707
1708 static const struct {
1709 const char *l; /* locale */
1710 const char *k; /* kw */
1711 const char *v; /* value */
1712 const char *x; /* expected */
1713 } kwSetTestCases[] = {
1714 #if 1
1715 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
1716 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
1717 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
1718 { "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 */
1719 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
1720 { "de", "Currency", "CHF", "de@currency=CHF" },
1721 { "de", "Currency", "CHF", "de@currency=CHF" },
1722
1723 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1724 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
1725 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1726 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1727 { "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 */
1728 { "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 */
1729 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
1730 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
1731 #endif
1732 #if 1
1733 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
1734 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
1735 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
1736 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
1737 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
1738 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
1739 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
1740 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
1741 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
1742 #endif
1743 #if 1
1744 /* removal tests */
1745 /* 1. removal of item at end */
1746 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
1747 { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
1748 /* 2. removal of item at beginning */
1749 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
1750 { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
1751 /* 3. removal of an item not there */
1752 { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
1753 /* 4. removal of only item */
1754 { "de@collation=phonebook", "collation", NULL, "de" },
1755 #endif
1756 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
1757 };
1758
1759
TestKeywordSet(void)1760 static void TestKeywordSet(void)
1761 {
1762 int32_t i = 0;
1763 int32_t resultLen = 0;
1764 char buffer[1024];
1765
1766 char cbuffer[1024];
1767
1768 for(i = 0; i < sizeof(kwSetTestCases)/sizeof(kwSetTestCases[0]); i++) {
1769 UErrorCode status = U_ZERO_ERROR;
1770 memset(buffer,'%',1023);
1771 strcpy(buffer, kwSetTestCases[i].l);
1772
1773 uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
1774 if(strcmp(buffer,cbuffer)) {
1775 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
1776 }
1777 /* sanity check test case results for canonicity */
1778 uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
1779 if(strcmp(kwSetTestCases[i].x,cbuffer)) {
1780 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
1781 }
1782
1783 resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
1784 if(U_FAILURE(status)) {
1785 log_err("Err on test case %d: got error %s\n", i, u_errorName(status));
1786 continue;
1787 }
1788 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
1789 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1790 kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
1791 } else {
1792 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
1793 }
1794 }
1795 }
1796
TestKeywordSetError(void)1797 static void TestKeywordSetError(void)
1798 {
1799 char buffer[1024];
1800 UErrorCode status;
1801 int32_t res;
1802 int32_t i;
1803 int32_t blen;
1804
1805 /* 0-test whether an error condition modifies the buffer at all */
1806 blen=0;
1807 i=0;
1808 memset(buffer,'%',1023);
1809 status = U_ZERO_ERROR;
1810 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1811 if(status != U_ILLEGAL_ARGUMENT_ERROR) {
1812 log_err("expected illegal err got %s\n", u_errorName(status));
1813 return;
1814 }
1815 /* if(res!=strlen(kwSetTestCases[i].x)) {
1816 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1817 return;
1818 } */
1819 if(buffer[blen]!='%') {
1820 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1821 return;
1822 }
1823 log_verbose("0-buffer modify OK\n");
1824
1825 for(i=0;i<=2;i++) {
1826 /* 1- test a short buffer with growing text */
1827 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1828 memset(buffer,'%',1023);
1829 strcpy(buffer,kwSetTestCases[i].l);
1830 status = U_ZERO_ERROR;
1831 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1832 if(status != U_BUFFER_OVERFLOW_ERROR) {
1833 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);
1834 return;
1835 }
1836 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
1837 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1838 return;
1839 }
1840 if(buffer[blen]!='%') {
1841 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
1842 return;
1843 }
1844 log_verbose("1/%d-buffer modify OK\n",i);
1845 }
1846
1847 for(i=3;i<=4;i++) {
1848 /* 2- test a short buffer - text the same size or shrinking */
1849 blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
1850 memset(buffer,'%',1023);
1851 strcpy(buffer,kwSetTestCases[i].l);
1852 status = U_ZERO_ERROR;
1853 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
1854 if(status != U_ZERO_ERROR) {
1855 log_err("expected zero error got %s\n", u_errorName(status));
1856 return;
1857 }
1858 if(buffer[blen+1]!='%') {
1859 log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
1860 return;
1861 }
1862 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
1863 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
1864 return;
1865 }
1866 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
1867 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
1868 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
1869 } else {
1870 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
1871 buffer);
1872 }
1873 log_verbose("2/%d-buffer modify OK\n",i);
1874 }
1875 }
1876
_canonicalize(int32_t selector,const char * localeID,char * result,int32_t resultCapacity,UErrorCode * ec)1877 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
1878 const char* localeID,
1879 char* result,
1880 int32_t resultCapacity,
1881 UErrorCode* ec) {
1882 /* YOU can change this to use function pointers if you like */
1883 switch (selector) {
1884 case 0:
1885 return uloc_getName(localeID, result, resultCapacity, ec);
1886 case 1:
1887 return uloc_canonicalize(localeID, result, resultCapacity, ec);
1888 default:
1889 return -1;
1890 }
1891 }
1892
TestCanonicalization(void)1893 static void TestCanonicalization(void)
1894 {
1895 static const struct {
1896 const char *localeID; /* input */
1897 const char *getNameID; /* expected getName() result */
1898 const char *canonicalID; /* expected canonicalize() result */
1899 } testCases[] = {
1900 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
1901 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
1902 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
1903 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
1904 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
1905 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
1906 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
1907 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
1908 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
1909 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
1910 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
1911 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
1912 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
1913 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
1914 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
1915 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
1916 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
1917 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
1918 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
1919 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
1920 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
1921 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
1922 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
1923 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
1924 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
1925 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
1926 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
1927 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
1928 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
1929 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" },
1930 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
1931 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
1932 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
1933 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" },
1934 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
1935 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
1936 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
1937 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
1938 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
1939 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
1940 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
1941 { "en-BOONT", "en_BOONT", "en__BOONT" }, /* registered name */
1942 { "de-1901", "de_1901", "de__1901" }, /* registered name */
1943 { "de-1906", "de_1906", "de__1906" }, /* registered name */
1944 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */
1945 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */
1946 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */
1947 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
1948 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
1949 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
1950 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
1951
1952 /* posix behavior that used to be performed by getName */
1953 { "mr.utf8", "mr.utf8", "mr" },
1954 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
1955 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
1956 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
1957 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
1958 { "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 */
1959
1960 /* fleshing out canonicalization */
1961 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
1962 { "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" },
1963 /* already-canonical ids are not changed */
1964 { "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" },
1965 /* PRE_EURO and EURO conversions don't affect other keywords */
1966 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
1967 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
1968 /* currency keyword overrides PRE_EURO and EURO currency */
1969 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
1970 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
1971 /* norwegian is just too weird, if we handle things in their full generality */
1972 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
1973
1974 /* test cases reflecting internal resource bundle usage */
1975 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
1976 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
1977 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
1978 { "ja_JP", "ja_JP", "ja_JP" },
1979
1980 /* test case for "i-default" */
1981 { "i-default", "en@x=i-default", "en@x=i-default" }
1982 };
1983
1984 static const char* label[] = { "getName", "canonicalize" };
1985
1986 UErrorCode status = U_ZERO_ERROR;
1987 int32_t i, j, resultLen = 0, origResultLen;
1988 char buffer[256];
1989
1990 for (i=0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
1991 for (j=0; j<2; ++j) {
1992 const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
1993 *buffer = 0;
1994 status = U_ZERO_ERROR;
1995
1996 if (expected == NULL) {
1997 expected = uloc_getDefault();
1998 }
1999
2000 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
2001 origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
2002 if (status != U_BUFFER_OVERFLOW_ERROR) {
2003 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
2004 label[j], testCases[i].localeID, u_errorName(status));
2005 continue;
2006 }
2007 status = U_ZERO_ERROR;
2008 resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
2009 if (U_FAILURE(status)) {
2010 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
2011 label[j], testCases[i].localeID, u_errorName(status));
2012 continue;
2013 }
2014 if(uprv_strcmp(expected, buffer) != 0) {
2015 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
2016 label[j], testCases[i].localeID, buffer, expected);
2017 } else {
2018 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
2019 label[j], testCases[i].localeID, buffer);
2020 }
2021 if (resultLen != (int32_t)strlen(buffer)) {
2022 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
2023 label[j], testCases[i].localeID, resultLen, strlen(buffer));
2024 }
2025 if (origResultLen != resultLen) {
2026 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
2027 label[j], testCases[i].localeID, origResultLen, resultLen);
2028 }
2029 }
2030 }
2031 }
2032
TestDisplayKeywords(void)2033 static void TestDisplayKeywords(void)
2034 {
2035 int32_t i;
2036
2037 static const struct {
2038 const char *localeID;
2039 const char *displayLocale;
2040 UChar displayKeyword[200];
2041 } testCases[] = {
2042 { "ca_ES@currency=ESP", "de_AT",
2043 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
2044 },
2045 { "ja_JP@calendar=japanese", "de",
2046 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2047 },
2048 { "de_DE@collation=traditional", "de_DE",
2049 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
2050 },
2051 };
2052 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2053 UErrorCode status = U_ZERO_ERROR;
2054 const char* keyword =NULL;
2055 int32_t keywordLen = 0;
2056 int32_t keywordCount = 0;
2057 UChar *displayKeyword=NULL;
2058 int32_t displayKeywordLen = 0;
2059 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2060 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2061 if(U_FAILURE(status)){
2062 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
2063 break;
2064 }
2065 /* the uenum_next returns NUL terminated string */
2066 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2067 /* fetch the displayKeyword */
2068 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2069 if(status==U_BUFFER_OVERFLOW_ERROR){
2070 status = U_ZERO_ERROR;
2071 displayKeywordLen++; /* for null termination */
2072 displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
2073 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
2074 if(U_FAILURE(status)){
2075 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));
2076 break;
2077 }
2078 if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
2079 if (status == U_USING_DEFAULT_WARNING) {
2080 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));
2081 } else {
2082 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);
2083 }
2084 break;
2085 }
2086 }else{
2087 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
2088 }
2089
2090 free(displayKeyword);
2091
2092 }
2093 uenum_close(keywordEnum);
2094 }
2095 }
2096
TestDisplayKeywordValues(void)2097 static void TestDisplayKeywordValues(void){
2098 int32_t i;
2099
2100 static const struct {
2101 const char *localeID;
2102 const char *displayLocale;
2103 UChar displayKeywordValue[500];
2104 } testCases[] = {
2105 { "ca_ES@currency=ESP", "de_AT",
2106 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000}
2107 },
2108 { "de_AT@currency=ATS", "fr_FR",
2109 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
2110 },
2111 { "de_DE@currency=DEM", "it",
2112 {0x004d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0054, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
2113 },
2114 { "el_GR@currency=GRD", "en",
2115 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
2116 },
2117 { "eu_ES@currency=ESP", "it_IT",
2118 {0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0053, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
2119 },
2120 { "de@collation=phonebook", "es",
2121 {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}
2122 },
2123
2124 { "de_DE@collation=phonebook", "es",
2125 {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}
2126 },
2127 { "es_ES@collation=traditional","de",
2128 {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}
2129 },
2130 { "ja_JP@calendar=japanese", "de",
2131 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
2132 },
2133 };
2134 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2135 UErrorCode status = U_ZERO_ERROR;
2136 const char* keyword =NULL;
2137 int32_t keywordLen = 0;
2138 int32_t keywordCount = 0;
2139 UChar *displayKeywordValue = NULL;
2140 int32_t displayKeywordValueLen = 0;
2141 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
2142 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
2143 if(U_FAILURE(status)){
2144 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));
2145 break;
2146 }
2147 /* the uenum_next returns NUL terminated string */
2148 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2149
2150 /* fetch the displayKeywordValue */
2151 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2152 if(status==U_BUFFER_OVERFLOW_ERROR){
2153 status = U_ZERO_ERROR;
2154 displayKeywordValueLen++; /* for null termination */
2155 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2156 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2157 if(U_FAILURE(status)){
2158 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));
2159 break;
2160 }
2161 if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
2162 if (status == U_USING_DEFAULT_WARNING) {
2163 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));
2164 } else {
2165 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));
2166 }
2167 break;
2168 }
2169 }else{
2170 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2171 }
2172 free(displayKeywordValue);
2173 }
2174 uenum_close(keywordEnum);
2175 }
2176 {
2177 /* test a multiple keywords */
2178 UErrorCode status = U_ZERO_ERROR;
2179 const char* keyword =NULL;
2180 int32_t keywordLen = 0;
2181 int32_t keywordCount = 0;
2182 const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
2183 const char* displayLocale = "de";
2184 static const UChar expected[][50] = {
2185 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
2186
2187 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000},
2188 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
2189 };
2190
2191 UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
2192
2193 for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
2194 UChar *displayKeywordValue = NULL;
2195 int32_t displayKeywordValueLen = 0;
2196 if(U_FAILURE(status)){
2197 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
2198 break;
2199 }
2200 /* the uenum_next returns NUL terminated string */
2201 keyword = uenum_next(keywordEnum, &keywordLen, &status);
2202
2203 /* fetch the displayKeywordValue */
2204 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2205 if(status==U_BUFFER_OVERFLOW_ERROR){
2206 status = U_ZERO_ERROR;
2207 displayKeywordValueLen++; /* for null termination */
2208 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
2209 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2210 if(U_FAILURE(status)){
2211 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));
2212 break;
2213 }
2214 if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
2215 if (status == U_USING_DEFAULT_WARNING) {
2216 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));
2217 } else {
2218 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
2219 }
2220 break;
2221 }
2222 }else{
2223 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
2224 }
2225 free(displayKeywordValue);
2226 }
2227 uenum_close(keywordEnum);
2228
2229 }
2230 {
2231 /* Test non existent keywords */
2232 UErrorCode status = U_ZERO_ERROR;
2233 const char* localeID = "es";
2234 const char* displayLocale = "de";
2235 UChar *displayKeywordValue = NULL;
2236 int32_t displayKeywordValueLen = 0;
2237
2238 /* fetch the displayKeywordValue */
2239 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
2240 if(U_FAILURE(status)) {
2241 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
2242 } else if(displayKeywordValueLen != 0) {
2243 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
2244 }
2245 }
2246 }
2247
2248
TestGetBaseName(void)2249 static void TestGetBaseName(void) {
2250 static const struct {
2251 const char *localeID;
2252 const char *baseName;
2253 } testCases[] = {
2254 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2255 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2256 { "ja@calendar = buddhist", "ja" }
2257 };
2258
2259 int32_t i = 0, baseNameLen = 0;
2260 char baseName[256];
2261 UErrorCode status = U_ZERO_ERROR;
2262
2263 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
2264 baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
2265 if(strcmp(testCases[i].baseName, baseName)) {
2266 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
2267 testCases[i].localeID, testCases[i].baseName, baseName);
2268 return;
2269 }
2270 }
2271 }
2272
TestTrailingNull(void)2273 static void TestTrailingNull(void) {
2274 const char* localeId = "zh_Hans";
2275 UChar buffer[128]; /* sufficient for this test */
2276 int32_t len;
2277 UErrorCode status = U_ZERO_ERROR;
2278 int i;
2279
2280 len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status);
2281 if (len > 128) {
2282 log_err("buffer too small");
2283 return;
2284 }
2285
2286 for (i = 0; i < len; ++i) {
2287 if (buffer[i] == 0) {
2288 log_err("name contained null");
2289 return;
2290 }
2291 }
2292 }
2293
2294 /* Jitterbug 4115 */
TestDisplayNameWarning(void)2295 static void TestDisplayNameWarning(void) {
2296 UChar name[256];
2297 int32_t size;
2298 UErrorCode status = U_ZERO_ERROR;
2299
2300 size = uloc_getDisplayLanguage("qqq", "kl", name, sizeof(name)/sizeof(name[0]), &status);
2301 if (status != U_USING_DEFAULT_WARNING) {
2302 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2303 u_errorName(status));
2304 }
2305 }
2306
2307
2308 /**
2309 * Compare two locale IDs. If they are equal, return 0. If `string'
2310 * starts with `prefix' plus an additional element, that is, string ==
2311 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2312 */
_loccmp(const char * string,const char * prefix)2313 static UBool _loccmp(const char* string, const char* prefix) {
2314 int32_t slen = (int32_t)uprv_strlen(string),
2315 plen = (int32_t)uprv_strlen(prefix);
2316 int32_t c = uprv_strncmp(string, prefix, plen);
2317 /* 'root' is less than everything */
2318 if (uprv_strcmp(prefix, "root") == 0) {
2319 return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
2320 }
2321 if (c) return -1; /* mismatch */
2322 if (slen == plen) return 0;
2323 if (string[plen] == '_') return 1;
2324 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2325 }
2326
_checklocs(const char * label,const char * req,const char * valid,const char * actual)2327 static void _checklocs(const char* label,
2328 const char* req,
2329 const char* valid,
2330 const char* actual) {
2331 /* We want the valid to be strictly > the bogus requested locale,
2332 and the valid to be >= the actual. */
2333 if (_loccmp(req, valid) > 0 &&
2334 _loccmp(valid, actual) >= 0) {
2335 log_verbose("%s; req=%s, valid=%s, actual=%s\n",
2336 label, req, valid, actual);
2337 } else {
2338 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
2339 label, req, valid, actual);
2340 }
2341 }
2342
TestGetLocale(void)2343 static void TestGetLocale(void) {
2344 UErrorCode ec = U_ZERO_ERROR;
2345 UParseError pe;
2346 UChar EMPTY[1] = {0};
2347
2348 /* === udat === */
2349 #if !UCONFIG_NO_FORMATTING
2350 {
2351 UDateFormat *obj;
2352 const char *req = "en_US_REDWOODSHORES", *valid, *actual;
2353 obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
2354 req,
2355 NULL, 0,
2356 NULL, 0, &ec);
2357 if (U_FAILURE(ec)) {
2358 log_data_err("udat_open failed.Error %s\n", u_errorName(ec));
2359 return;
2360 }
2361 valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2362 actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2363 if (U_FAILURE(ec)) {
2364 log_err("udat_getLocaleByType() failed\n");
2365 return;
2366 }
2367 _checklocs("udat", req, valid, actual);
2368 udat_close(obj);
2369 }
2370 #endif
2371
2372 /* === ucal === */
2373 #if !UCONFIG_NO_FORMATTING
2374 {
2375 UCalendar *obj;
2376 const char *req = "fr_FR_PROVENCAL", *valid, *actual;
2377 obj = ucal_open(NULL, 0,
2378 req,
2379 UCAL_GREGORIAN,
2380 &ec);
2381 if (U_FAILURE(ec)) {
2382 log_err("ucal_open failed with error: %s\n", u_errorName(ec));
2383 return;
2384 }
2385 valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2386 actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2387 if (U_FAILURE(ec)) {
2388 log_err("ucal_getLocaleByType() failed\n");
2389 return;
2390 }
2391 _checklocs("ucal", req, valid, actual);
2392 ucal_close(obj);
2393 }
2394 #endif
2395
2396 /* === unum === */
2397 #if !UCONFIG_NO_FORMATTING
2398 {
2399 UNumberFormat *obj;
2400 const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
2401 obj = unum_open(UNUM_DECIMAL,
2402 NULL, 0,
2403 req,
2404 &pe, &ec);
2405 if (U_FAILURE(ec)) {
2406 log_err("unum_open failed\n");
2407 return;
2408 }
2409 valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2410 actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2411 if (U_FAILURE(ec)) {
2412 log_err("unum_getLocaleByType() failed\n");
2413 return;
2414 }
2415 _checklocs("unum", req, valid, actual);
2416 unum_close(obj);
2417 }
2418 #endif
2419
2420 /* === umsg === */
2421 #if 0
2422 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
2423 #if !UCONFIG_NO_FORMATTING
2424 {
2425 UMessageFormat *obj;
2426 const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
2427 UBool test;
2428 obj = umsg_open(EMPTY, 0,
2429 req,
2430 &pe, &ec);
2431 if (U_FAILURE(ec)) {
2432 log_err("umsg_open failed\n");
2433 return;
2434 }
2435 valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2436 actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2437 if (U_FAILURE(ec)) {
2438 log_err("umsg_getLocaleByType() failed\n");
2439 return;
2440 }
2441 /* We want the valid to be strictly > the bogus requested locale,
2442 and the valid to be >= the actual. */
2443 /* TODO MessageFormat is currently just storing the locale it is given.
2444 As a result, it will return whatever it was given, even if the
2445 locale is invalid. */
2446 test = (_cmpversion("3.2") <= 0) ?
2447 /* Here is the weakened test for 3.0: */
2448 (_loccmp(req, valid) >= 0) :
2449 /* Here is what the test line SHOULD be: */
2450 (_loccmp(req, valid) > 0);
2451
2452 if (test &&
2453 _loccmp(valid, actual) >= 0) {
2454 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2455 } else {
2456 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
2457 }
2458 umsg_close(obj);
2459 }
2460 #endif
2461 #endif
2462
2463 /* === ubrk === */
2464 #if !UCONFIG_NO_BREAK_ITERATION
2465 {
2466 UBreakIterator *obj;
2467 const char *req = "ar_KW_ABDALI", *valid, *actual;
2468 obj = ubrk_open(UBRK_WORD,
2469 req,
2470 EMPTY,
2471 0,
2472 &ec);
2473 if (U_FAILURE(ec)) {
2474 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
2475 return;
2476 }
2477 valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2478 actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2479 if (U_FAILURE(ec)) {
2480 log_err("ubrk_getLocaleByType() failed\n");
2481 return;
2482 }
2483 _checklocs("ubrk", req, valid, actual);
2484 ubrk_close(obj);
2485 }
2486 #endif
2487
2488 /* === ucol === */
2489 #if !UCONFIG_NO_COLLATION
2490 {
2491 UCollator *obj;
2492 const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
2493 obj = ucol_open(req, &ec);
2494 if (U_FAILURE(ec)) {
2495 log_err("ucol_open failed - %s\n", u_errorName(ec));
2496 return;
2497 }
2498 valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
2499 actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
2500 if (U_FAILURE(ec)) {
2501 log_err("ucol_getLocaleByType() failed\n");
2502 return;
2503 }
2504 _checklocs("ucol", req, valid, actual);
2505 ucol_close(obj);
2506 }
2507 #endif
2508 }
2509
TestNonexistentLanguageExemplars(void)2510 static void TestNonexistentLanguageExemplars(void) {
2511 /* JB 4068 - Nonexistent language */
2512 UErrorCode ec = U_ZERO_ERROR;
2513 ULocaleData *uld = ulocdata_open("qqq",&ec);
2514 if (ec != U_USING_DEFAULT_WARNING) {
2515 log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
2516 u_errorName(ec));
2517 }
2518 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2519 ulocdata_close(uld);
2520 }
2521
TestLocDataErrorCodeChaining(void)2522 static void TestLocDataErrorCodeChaining(void) {
2523 UErrorCode ec = U_USELESS_COLLATOR_ERROR;
2524 ulocdata_open(NULL, &ec);
2525 ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
2526 ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
2527 ulocdata_getMeasurementSystem(NULL, &ec);
2528 ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
2529 if (ec != U_USELESS_COLLATOR_ERROR) {
2530 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
2531 }
2532 }
2533
TestLanguageExemplarsFallbacks(void)2534 static void TestLanguageExemplarsFallbacks(void) {
2535 /* Test that en_US fallsback, but en doesn't fallback. */
2536 UErrorCode ec = U_ZERO_ERROR;
2537 ULocaleData *uld = ulocdata_open("en_US",&ec);
2538 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2539 if (ec != U_USING_FALLBACK_WARNING) {
2540 log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
2541 u_errorName(ec));
2542 }
2543 ulocdata_close(uld);
2544 ec = U_ZERO_ERROR;
2545 uld = ulocdata_open("en",&ec);
2546 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
2547 if (ec != U_ZERO_ERROR) {
2548 log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
2549 u_errorName(ec));
2550 }
2551 ulocdata_close(uld);
2552 }
2553
acceptResult(UAcceptResult uar)2554 static const char *acceptResult(UAcceptResult uar) {
2555 return udbg_enumName(UDBG_UAcceptResult, uar);
2556 }
2557
TestAcceptLanguage(void)2558 static void TestAcceptLanguage(void) {
2559 UErrorCode status = U_ZERO_ERROR;
2560 UAcceptResult outResult;
2561 UEnumeration *available;
2562 char tmp[200];
2563 int i;
2564 int32_t rc = 0;
2565
2566 struct {
2567 int32_t httpSet; /**< Which of http[] should be used? */
2568 const char *icuSet; /**< ? */
2569 const char *expect; /**< The expected locale result */
2570 UAcceptResult res; /**< The expected error code */
2571 } tests[] = {
2572 /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID },
2573 /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID },
2574 /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK },
2575 /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED },
2576 /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID },
2577
2578 /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID }, /* XF */
2579 /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK }, /* XF */
2580 /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK }, /* XF */
2581 };
2582 const int32_t numTests = sizeof(tests)/sizeof(tests[0]);
2583 static const char *http[] = {
2584 /*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",
2585 /*1*/ "ja;q=0.5, en;q=0.8, tlh",
2586 /*2*/ "en-wf, de-lx;q=0.8",
2587 /*3*/ "mga-ie;q=0.9, tlh",
2588 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2589 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2590 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2591 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2592 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2593 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
2594 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
2595 "es",
2596
2597 /*5*/ "zh-xx;q=0.9, en;q=0.6",
2598 /*6*/ "ja-JA",
2599 /*7*/ "zh-xx;q=0.9",
2600 };
2601
2602 for(i=0;i<numTests;i++) {
2603 outResult = -3;
2604 status=U_ZERO_ERROR;
2605 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2606 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2607
2608 available = ures_openAvailableLocales(tests[i].icuSet, &status);
2609 tmp[0]=0;
2610 rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status);
2611 uenum_close(available);
2612 log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
2613 if(outResult != tests[i].res) {
2614 log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
2615 acceptResult( tests[i].res),
2616 acceptResult( outResult));
2617 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2618 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res));
2619 }
2620 if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
2621 log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
2622 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
2623 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
2624 }
2625 }
2626 }
2627
2628 static const char* LOCALE_ALIAS[][2] = {
2629 {"in", "id"},
2630 {"in_ID", "id_ID"},
2631 {"iw", "he"},
2632 {"iw_IL", "he_IL"},
2633 {"ji", "yi"},
2634 {"en_BU", "en_MM"},
2635 {"en_DY", "en_BJ"},
2636 {"en_HV", "en_BF"},
2637 {"en_NH", "en_VU"},
2638 {"en_RH", "en_ZW"},
2639 {"en_TP", "en_TL"},
2640 {"en_ZR", "en_CD"}
2641 };
isLocaleAvailable(UResourceBundle * resIndex,const char * loc)2642 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
2643 UErrorCode status = U_ZERO_ERROR;
2644 int32_t len = 0;
2645 ures_getStringByKey(resIndex, loc,&len, &status);
2646 if(U_FAILURE(status)){
2647 return FALSE;
2648 }
2649 return TRUE;
2650 }
2651
TestCalendar()2652 static void TestCalendar() {
2653 #if !UCONFIG_NO_FORMATTING
2654 int i;
2655 UErrorCode status = U_ZERO_ERROR;
2656 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2657 if(U_FAILURE(status)){
2658 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2659 return;
2660 }
2661 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2662 const char* oldLoc = LOCALE_ALIAS[i][0];
2663 const char* newLoc = LOCALE_ALIAS[i][1];
2664 UCalendar* c1 = NULL;
2665 UCalendar* c2 = NULL;
2666
2667 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
2668 const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2669 const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2670
2671 if(!isLocaleAvailable(resIndex, newLoc)){
2672 continue;
2673 }
2674 c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
2675 c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
2676
2677 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
2678 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2679 }
2680 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2);
2681 ucal_close(c1);
2682 ucal_close(c2);
2683 }
2684 ures_close(resIndex);
2685 #endif
2686 }
2687
TestDateFormat()2688 static void TestDateFormat() {
2689 #if !UCONFIG_NO_FORMATTING
2690 int i;
2691 UErrorCode status = U_ZERO_ERROR;
2692 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2693 if(U_FAILURE(status)){
2694 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2695 return;
2696 }
2697 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2698 const char* oldLoc = LOCALE_ALIAS[i][0];
2699 const char* newLoc = LOCALE_ALIAS[i][1];
2700 UDateFormat* df1 = NULL;
2701 UDateFormat* df2 = NULL;
2702 const char* l1 = NULL;
2703 const char* l2 = NULL;
2704
2705 if(!isLocaleAvailable(resIndex, newLoc)){
2706 continue;
2707 }
2708 df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
2709 df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
2710 if(U_FAILURE(status)){
2711 log_err("Creation of date format failed %s\n", u_errorName(status));
2712 return;
2713 }
2714 /*Test function "getLocale"*/
2715 l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
2716 l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
2717 if(U_FAILURE(status)){
2718 log_err("Fetching the locale by type failed. %s\n", u_errorName(status));
2719 }
2720 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2721 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2722 }
2723 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2);
2724 udat_close(df1);
2725 udat_close(df2);
2726 }
2727 ures_close(resIndex);
2728 #endif
2729 }
2730
TestCollation()2731 static void TestCollation() {
2732 #if !UCONFIG_NO_COLLATION
2733 int i;
2734 UErrorCode status = U_ZERO_ERROR;
2735 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2736 if(U_FAILURE(status)){
2737 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2738 return;
2739 }
2740 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2741 const char* oldLoc = LOCALE_ALIAS[i][0];
2742 const char* newLoc = LOCALE_ALIAS[i][1];
2743 UCollator* c1 = NULL;
2744 UCollator* c2 = NULL;
2745 const char* l1 = NULL;
2746 const char* l2 = NULL;
2747
2748 status = U_ZERO_ERROR;
2749 if(!isLocaleAvailable(resIndex, newLoc)){
2750 continue;
2751 }
2752 if(U_FAILURE(status)){
2753 log_err("Creation of collators failed %s\n", u_errorName(status));
2754 return;
2755 }
2756 c1 = ucol_open(oldLoc, &status);
2757 c2 = ucol_open(newLoc, &status);
2758 l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
2759 l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
2760 if(U_FAILURE(status)){
2761 log_err("Fetching the locale names failed failed %s\n", u_errorName(status));
2762 }
2763 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
2764 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2765 }
2766 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2);
2767 ucol_close(c1);
2768 ucol_close(c2);
2769 }
2770 ures_close(resIndex);
2771 #endif
2772 }
2773
2774 typedef struct OrientationStructTag {
2775 const char* localeId;
2776 ULayoutType character;
2777 ULayoutType line;
2778 } OrientationStruct;
2779
ULayoutTypeToString(ULayoutType type)2780 static const char* ULayoutTypeToString(ULayoutType type)
2781 {
2782 switch(type)
2783 {
2784 case ULOC_LAYOUT_LTR:
2785 return "ULOC_LAYOUT_LTR";
2786 break;
2787 case ULOC_LAYOUT_RTL:
2788 return "ULOC_LAYOUT_RTL";
2789 break;
2790 case ULOC_LAYOUT_TTB:
2791 return "ULOC_LAYOUT_TTB";
2792 break;
2793 case ULOC_LAYOUT_BTT:
2794 return "ULOC_LAYOUT_BTT";
2795 break;
2796 case ULOC_LAYOUT_UNKNOWN:
2797 break;
2798 }
2799
2800 return "Unknown enum value for ULayoutType!";
2801 }
2802
TestOrientation()2803 static void TestOrientation()
2804 {
2805 static const OrientationStruct toTest [] = {
2806 { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2807 { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2808 { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2809 { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2810 { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2811 { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2812 { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2813 { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2814 { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB },
2815 { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB }
2816 };
2817
2818 size_t i = 0;
2819 for (; i < sizeof(toTest) / sizeof(toTest[0]); ++i) {
2820 UErrorCode statusCO = U_ZERO_ERROR;
2821 UErrorCode statusLO = U_ZERO_ERROR;
2822 const char* const localeId = toTest[i].localeId;
2823 const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO);
2824 const ULayoutType expectedCO = toTest[i].character;
2825 const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO);
2826 const ULayoutType expectedLO = toTest[i].line;
2827 if (U_FAILURE(statusCO)) {
2828 log_err_status(statusCO,
2829 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n",
2830 localeId,
2831 u_errorName(statusCO));
2832 }
2833 else if (co != expectedCO) {
2834 log_err(
2835 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2836 localeId,
2837 ULayoutTypeToString(expectedCO),
2838 ULayoutTypeToString(co));
2839 }
2840 if (U_FAILURE(statusLO)) {
2841 log_err_status(statusLO,
2842 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n",
2843 localeId,
2844 u_errorName(statusLO));
2845 }
2846 else if (lo != expectedLO) {
2847 log_err(
2848 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n",
2849 localeId,
2850 ULayoutTypeToString(expectedLO),
2851 ULayoutTypeToString(lo));
2852 }
2853 }
2854 }
2855
TestULocale()2856 static void TestULocale() {
2857 int i;
2858 UErrorCode status = U_ZERO_ERROR;
2859 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
2860 if(U_FAILURE(status)){
2861 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2862 return;
2863 }
2864 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2865 const char* oldLoc = LOCALE_ALIAS[i][0];
2866 const char* newLoc = LOCALE_ALIAS[i][1];
2867 UChar name1[256], name2[256];
2868 char names1[256], names2[256];
2869 int32_t capacity = 256;
2870
2871 status = U_ZERO_ERROR;
2872 if(!isLocaleAvailable(resIndex, newLoc)){
2873 continue;
2874 }
2875 uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
2876 if(U_FAILURE(status)){
2877 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
2878 }
2879
2880 uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
2881 if(U_FAILURE(status)){
2882 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
2883 }
2884
2885 if (u_strcmp(name1, name2)!=0) {
2886 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2887 }
2888 u_austrcpy(names1, name1);
2889 u_austrcpy(names2, name2);
2890 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2);
2891 }
2892 ures_close(resIndex);
2893
2894 }
2895
TestUResourceBundle()2896 static void TestUResourceBundle() {
2897 const char* us1;
2898 const char* us2;
2899
2900 UResourceBundle* rb1 = NULL;
2901 UResourceBundle* rb2 = NULL;
2902 UErrorCode status = U_ZERO_ERROR;
2903 int i;
2904 UResourceBundle *resIndex = NULL;
2905 if(U_FAILURE(status)){
2906 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
2907 return;
2908 }
2909 resIndex = ures_open(NULL,"res_index", &status);
2910 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2911
2912 const char* oldLoc = LOCALE_ALIAS[i][0];
2913 const char* newLoc = LOCALE_ALIAS[i][1];
2914 if(!isLocaleAvailable(resIndex, newLoc)){
2915 continue;
2916 }
2917 rb1 = ures_open(NULL, oldLoc, &status);
2918 if (U_FAILURE(status)) {
2919 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
2920 }
2921
2922 us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status);
2923
2924 status = U_ZERO_ERROR;
2925 rb2 = ures_open(NULL, newLoc, &status);
2926 if (U_FAILURE(status)) {
2927 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
2928 }
2929 us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status);
2930
2931 if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
2932 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
2933 }
2934
2935 log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2);
2936 ures_close(rb1);
2937 rb1 = NULL;
2938 ures_close(rb2);
2939 rb2 = NULL;
2940 }
2941 ures_close(resIndex);
2942 }
2943
TestDisplayName()2944 static void TestDisplayName() {
2945
2946 UChar oldCountry[256] = {'\0'};
2947 UChar newCountry[256] = {'\0'};
2948 UChar oldLang[256] = {'\0'};
2949 UChar newLang[256] = {'\0'};
2950 char country[256] ={'\0'};
2951 char language[256] ={'\0'};
2952 int32_t capacity = 256;
2953 int i =0;
2954 int j=0;
2955 for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
2956 const char* oldLoc = LOCALE_ALIAS[i][0];
2957 const char* newLoc = LOCALE_ALIAS[i][1];
2958 UErrorCode status = U_ZERO_ERROR;
2959 int32_t available = uloc_countAvailable();
2960
2961 for(j=0; j<available; j++){
2962
2963 const char* dispLoc = uloc_getAvailable(j);
2964 int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
2965 int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
2966 int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
2967 int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
2968
2969 int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
2970 int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status);
2971 /* there is a display name for the current country ID */
2972 if(countryLen != newCountryLen ){
2973 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
2974 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
2975 }
2976 }
2977 /* there is a display name for the current lang ID */
2978 if(langLen!=newLangLen){
2979 if(u_strncmp(oldLang,newLang,oldLangLen)){
2980 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); }
2981 }
2982 }
2983 }
2984 }
2985
TestGetLocaleForLCID()2986 static void TestGetLocaleForLCID() {
2987 int32_t i, length, lengthPre;
2988 const char* testLocale = 0;
2989 UErrorCode status = U_ZERO_ERROR;
2990 char temp2[40], temp3[40];
2991 uint32_t lcid;
2992
2993 lcid = uloc_getLCID("en_US");
2994 if (lcid != 0x0409) {
2995 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
2996 }
2997
2998 lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
2999 if (status != U_BUFFER_OVERFLOW_ERROR) {
3000 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
3001 }
3002 else {
3003 status = U_ZERO_ERROR;
3004 }
3005
3006 length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
3007 if (U_FAILURE(status)) {
3008 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
3009 status = U_ZERO_ERROR;
3010 }
3011
3012 if (length != lengthPre) {
3013 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
3014 }
3015
3016 length = uloc_getLocaleForLCID(0x12345, temp2, sizeof(temp2)/sizeof(char), &status);
3017 if (U_SUCCESS(status)) {
3018 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
3019 }
3020 status = U_ZERO_ERROR;
3021
3022 log_verbose("Testing getLocaleForLCID vs. locale data\n");
3023 for (i = 0; i < LOCALE_SIZE; i++) {
3024
3025 testLocale=rawData2[NAME][i];
3026
3027 log_verbose("Testing %s ......\n", testLocale);
3028
3029 sscanf(rawData2[LCID][i], "%x", &lcid);
3030 length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
3031 if (U_FAILURE(status)) {
3032 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
3033 status = U_ZERO_ERROR;
3034 continue;
3035 }
3036
3037 if (length != uprv_strlen(temp2)) {
3038 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
3039 }
3040
3041 /* Compare language, country, script */
3042 length = uloc_getLanguage(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3043 if (U_FAILURE(status)) {
3044 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3045 status = U_ZERO_ERROR;
3046 }
3047 else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
3048 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
3049 }
3050
3051 length = uloc_getScript(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3052 if (U_FAILURE(status)) {
3053 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3054 status = U_ZERO_ERROR;
3055 }
3056 else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
3057 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
3058 }
3059
3060 length = uloc_getCountry(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
3061 if (U_FAILURE(status)) {
3062 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
3063 status = U_ZERO_ERROR;
3064 }
3065 else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
3066 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
3067 }
3068 }
3069
3070 }
3071
3072 const char* const basic_maximize_data[][2] = {
3073 {
3074 "zu_Zzzz_Zz",
3075 "zu_Latn_ZA",
3076 }, {
3077 "ZU_Zz",
3078 "zu_Latn_ZA"
3079 }, {
3080 "zu_LATN",
3081 "zu_Latn_ZA"
3082 }, {
3083 "en_Zz",
3084 "en_Latn_US"
3085 }, {
3086 "en_us",
3087 "en_Latn_US"
3088 }, {
3089 "en_Kore",
3090 "en_Kore_US"
3091 }, {
3092 "en_Kore_Zz",
3093 "en_Kore_US"
3094 }, {
3095 "en_Kore_ZA",
3096 "en_Kore_ZA"
3097 }, {
3098 "en_Kore_ZA_POSIX",
3099 "en_Kore_ZA_POSIX"
3100 }, {
3101 "en_Gujr",
3102 "en_Gujr_US"
3103 }, {
3104 "en_ZA",
3105 "en_Latn_ZA"
3106 }, {
3107 "en_Gujr_Zz",
3108 "en_Gujr_US"
3109 }, {
3110 "en_Gujr_ZA",
3111 "en_Gujr_ZA"
3112 }, {
3113 "en_Gujr_ZA_POSIX",
3114 "en_Gujr_ZA_POSIX"
3115 }, {
3116 "en_US_POSIX_1901",
3117 "en_Latn_US_POSIX_1901"
3118 }, {
3119 "en_Latn__POSIX_1901",
3120 "en_Latn_US_POSIX_1901"
3121 }, {
3122 "en__POSIX_1901",
3123 "en_Latn_US_POSIX_1901"
3124 }, {
3125 "de__POSIX_1901",
3126 "de_Latn_DE_POSIX_1901"
3127 }, {
3128 "en_US_BOSTON",
3129 "en_Latn_US_BOSTON"
3130 }, {
3131 "th@calendar=buddhist",
3132 "th_Thai_TH@calendar=buddhist"
3133 }, {
3134 "ar_ZZ",
3135 "ar_Arab_EG"
3136 }, {
3137 "zh",
3138 "zh_Hans_CN"
3139 }, {
3140 "zh_TW",
3141 "zh_Hant_TW"
3142 }, {
3143 "zh_HK",
3144 "zh_Hant_HK"
3145 }, {
3146 "zh_Hant",
3147 "zh_Hant_TW"
3148 }, {
3149 "zh_Zzzz_CN",
3150 "zh_Hans_CN"
3151 }, {
3152 "und_US",
3153 "en_Latn_US"
3154 }, {
3155 "und_HK",
3156 "zh_Hant_HK"
3157 }, {
3158 "zzz",
3159 ""
3160 }, {
3161 "de_u_co_phonebk",
3162 "de_Latn_DE_U_CO_PHONEBK"
3163 }, {
3164 "de_Latn_u_co_phonebk",
3165 "de_Latn_DE_U_CO_PHONEBK"
3166 }, {
3167 "de_Latn_DE_u_co_phonebk",
3168 "de_Latn_DE_U_CO_PHONEBK"
3169 }
3170 };
3171
3172 const char* const basic_minimize_data[][2] = {
3173 {
3174 "en_Latn_US",
3175 "en"
3176 }, {
3177 "en_Latn_US_POSIX_1901",
3178 "en__POSIX_1901"
3179 }, {
3180 "EN_Latn_US_POSIX_1901",
3181 "en__POSIX_1901"
3182 }, {
3183 "en_Zzzz_US_POSIX_1901",
3184 "en__POSIX_1901"
3185 }, {
3186 "de_Latn_DE_POSIX_1901",
3187 "de__POSIX_1901"
3188 }, {
3189 "und",
3190 ""
3191 }, {
3192 "en_Latn_US@calendar=gregorian",
3193 "en@calendar=gregorian"
3194 }
3195 };
3196
3197 const char* const full_data[][3] = {
3198 {
3199 /* "FROM", */
3200 /* "ADD-LIKELY", */
3201 /* "REMOVE-LIKELY" */
3202 /* }, { */
3203 "aa",
3204 "aa_Latn_ET",
3205 "aa"
3206 }, {
3207 "af",
3208 "af_Latn_ZA",
3209 "af"
3210 }, {
3211 "ak",
3212 "ak_Latn_GH",
3213 "ak"
3214 }, {
3215 "am",
3216 "am_Ethi_ET",
3217 "am"
3218 }, {
3219 "ar",
3220 "ar_Arab_EG",
3221 "ar"
3222 }, {
3223 "as",
3224 "as_Beng_IN",
3225 "as"
3226 }, {
3227 "az",
3228 "az_Latn_AZ",
3229 "az"
3230 }, {
3231 "be",
3232 "be_Cyrl_BY",
3233 "be"
3234 }, {
3235 "bg",
3236 "bg_Cyrl_BG",
3237 "bg"
3238 }, {
3239 "bn",
3240 "bn_Beng_BD",
3241 "bn"
3242 }, {
3243 "bo",
3244 "bo_Tibt_CN",
3245 "bo"
3246 }, {
3247 "bs",
3248 "bs_Latn_BA",
3249 "bs"
3250 }, {
3251 "ca",
3252 "ca_Latn_ES",
3253 "ca"
3254 }, {
3255 "ch",
3256 "ch_Latn_GU",
3257 "ch"
3258 }, {
3259 "chk",
3260 "chk_Latn_FM",
3261 "chk"
3262 }, {
3263 "cs",
3264 "cs_Latn_CZ",
3265 "cs"
3266 }, {
3267 "cy",
3268 "cy_Latn_GB",
3269 "cy"
3270 }, {
3271 "da",
3272 "da_Latn_DK",
3273 "da"
3274 }, {
3275 "de",
3276 "de_Latn_DE",
3277 "de"
3278 }, {
3279 "dv",
3280 "dv_Thaa_MV",
3281 "dv"
3282 }, {
3283 "dz",
3284 "dz_Tibt_BT",
3285 "dz"
3286 }, {
3287 "ee",
3288 "ee_Latn_GH",
3289 "ee"
3290 }, {
3291 "el",
3292 "el_Grek_GR",
3293 "el"
3294 }, {
3295 "en",
3296 "en_Latn_US",
3297 "en"
3298 }, {
3299 "es",
3300 "es_Latn_ES",
3301 "es"
3302 }, {
3303 "et",
3304 "et_Latn_EE",
3305 "et"
3306 }, {
3307 "eu",
3308 "eu_Latn_ES",
3309 "eu"
3310 }, {
3311 "fa",
3312 "fa_Arab_IR",
3313 "fa"
3314 }, {
3315 "fi",
3316 "fi_Latn_FI",
3317 "fi"
3318 }, {
3319 "fil",
3320 "fil_Latn_PH",
3321 "fil"
3322 }, {
3323 "fo",
3324 "fo_Latn_FO",
3325 "fo"
3326 }, {
3327 "fr",
3328 "fr_Latn_FR",
3329 "fr"
3330 }, {
3331 "fur",
3332 "fur_Latn_IT",
3333 "fur"
3334 }, {
3335 "ga",
3336 "ga_Latn_IE",
3337 "ga"
3338 }, {
3339 "gaa",
3340 "gaa_Latn_GH",
3341 "gaa"
3342 }, {
3343 "gl",
3344 "gl_Latn_ES",
3345 "gl"
3346 }, {
3347 "gn",
3348 "gn_Latn_PY",
3349 "gn"
3350 }, {
3351 "gu",
3352 "gu_Gujr_IN",
3353 "gu"
3354 }, {
3355 "ha",
3356 "ha_Latn_NG",
3357 "ha"
3358 }, {
3359 "haw",
3360 "haw_Latn_US",
3361 "haw"
3362 }, {
3363 "he",
3364 "he_Hebr_IL",
3365 "he"
3366 }, {
3367 "hi",
3368 "hi_Deva_IN",
3369 "hi"
3370 }, {
3371 "hr",
3372 "hr_Latn_HR",
3373 "hr"
3374 }, {
3375 "ht",
3376 "ht_Latn_HT",
3377 "ht"
3378 }, {
3379 "hu",
3380 "hu_Latn_HU",
3381 "hu"
3382 }, {
3383 "hy",
3384 "hy_Armn_AM",
3385 "hy"
3386 }, {
3387 "id",
3388 "id_Latn_ID",
3389 "id"
3390 }, {
3391 "ig",
3392 "ig_Latn_NG",
3393 "ig"
3394 }, {
3395 "ii",
3396 "ii_Yiii_CN",
3397 "ii"
3398 }, {
3399 "is",
3400 "is_Latn_IS",
3401 "is"
3402 }, {
3403 "it",
3404 "it_Latn_IT",
3405 "it"
3406 }, {
3407 "ja",
3408 "ja_Jpan_JP",
3409 "ja"
3410 }, {
3411 "ka",
3412 "ka_Geor_GE",
3413 "ka"
3414 }, {
3415 "kaj",
3416 "kaj_Latn_NG",
3417 "kaj"
3418 }, {
3419 "kam",
3420 "kam_Latn_KE",
3421 "kam"
3422 }, {
3423 "kk",
3424 "kk_Cyrl_KZ",
3425 "kk"
3426 }, {
3427 "kl",
3428 "kl_Latn_GL",
3429 "kl"
3430 }, {
3431 "km",
3432 "km_Khmr_KH",
3433 "km"
3434 }, {
3435 "kn",
3436 "kn_Knda_IN",
3437 "kn"
3438 }, {
3439 "ko",
3440 "ko_Kore_KR",
3441 "ko"
3442 }, {
3443 "kok",
3444 "kok_Deva_IN",
3445 "kok"
3446 }, {
3447 "kpe",
3448 "kpe_Latn_LR",
3449 "kpe"
3450 }, {
3451 "ku",
3452 "ku_Arab_IQ",
3453 "ku"
3454 }, {
3455 "ky",
3456 "ky_Cyrl_KG",
3457 "ky"
3458 }, {
3459 "la",
3460 "la_Latn_VA",
3461 "la"
3462 }, {
3463 "ln",
3464 "ln_Latn_CD",
3465 "ln"
3466 }, {
3467 "lo",
3468 "lo_Laoo_LA",
3469 "lo"
3470 }, {
3471 "lt",
3472 "lt_Latn_LT",
3473 "lt"
3474 }, {
3475 "lv",
3476 "lv_Latn_LV",
3477 "lv"
3478 }, {
3479 "mg",
3480 "mg_Latn_MG",
3481 "mg"
3482 }, {
3483 "mh",
3484 "mh_Latn_MH",
3485 "mh"
3486 }, {
3487 "mk",
3488 "mk_Cyrl_MK",
3489 "mk"
3490 }, {
3491 "ml",
3492 "ml_Mlym_IN",
3493 "ml"
3494 }, {
3495 "mn",
3496 "mn_Cyrl_MN",
3497 "mn"
3498 }, {
3499 "mr",
3500 "mr_Deva_IN",
3501 "mr"
3502 }, {
3503 "ms",
3504 "ms_Latn_MY",
3505 "ms"
3506 }, {
3507 "mt",
3508 "mt_Latn_MT",
3509 "mt"
3510 }, {
3511 "my",
3512 "my_Mymr_MM",
3513 "my"
3514 }, {
3515 "na",
3516 "na_Latn_NR",
3517 "na"
3518 }, {
3519 "ne",
3520 "ne_Deva_NP",
3521 "ne"
3522 }, {
3523 "niu",
3524 "niu_Latn_NU",
3525 "niu"
3526 }, {
3527 "nl",
3528 "nl_Latn_NL",
3529 "nl"
3530 }, {
3531 "nn",
3532 "nn_Latn_NO",
3533 "nn"
3534 }, {
3535 "nr",
3536 "nr_Latn_ZA",
3537 "nr"
3538 }, {
3539 "nso",
3540 "nso_Latn_ZA",
3541 "nso"
3542 }, {
3543 "ny",
3544 "ny_Latn_MW",
3545 "ny"
3546 }, {
3547 "om",
3548 "om_Latn_ET",
3549 "om"
3550 }, {
3551 "or",
3552 "or_Orya_IN",
3553 "or"
3554 }, {
3555 "pa",
3556 "pa_Guru_IN",
3557 "pa"
3558 }, {
3559 "pa_Arab",
3560 "pa_Arab_PK",
3561 "pa_PK"
3562 }, {
3563 "pa_PK",
3564 "pa_Arab_PK",
3565 "pa_PK"
3566 }, {
3567 "pap",
3568 "pap_Latn_AN",
3569 "pap"
3570 }, {
3571 "pau",
3572 "pau_Latn_PW",
3573 "pau"
3574 }, {
3575 "pl",
3576 "pl_Latn_PL",
3577 "pl"
3578 }, {
3579 "ps",
3580 "ps_Arab_AF",
3581 "ps"
3582 }, {
3583 "pt",
3584 "pt_Latn_BR",
3585 "pt"
3586 }, {
3587 "rn",
3588 "rn_Latn_BI",
3589 "rn"
3590 }, {
3591 "ro",
3592 "ro_Latn_RO",
3593 "ro"
3594 }, {
3595 "ru",
3596 "ru_Cyrl_RU",
3597 "ru"
3598 }, {
3599 "rw",
3600 "rw_Latn_RW",
3601 "rw"
3602 }, {
3603 "sa",
3604 "sa_Deva_IN",
3605 "sa"
3606 }, {
3607 "se",
3608 "se_Latn_NO",
3609 "se"
3610 }, {
3611 "sg",
3612 "sg_Latn_CF",
3613 "sg"
3614 }, {
3615 "si",
3616 "si_Sinh_LK",
3617 "si"
3618 }, {
3619 "sid",
3620 "sid_Latn_ET",
3621 "sid"
3622 }, {
3623 "sk",
3624 "sk_Latn_SK",
3625 "sk"
3626 }, {
3627 "sl",
3628 "sl_Latn_SI",
3629 "sl"
3630 }, {
3631 "sm",
3632 "sm_Latn_WS",
3633 "sm"
3634 }, {
3635 "so",
3636 "so_Latn_SO",
3637 "so"
3638 }, {
3639 "sq",
3640 "sq_Latn_AL",
3641 "sq"
3642 }, {
3643 "sr",
3644 "sr_Cyrl_RS",
3645 "sr"
3646 }, {
3647 "ss",
3648 "ss_Latn_ZA",
3649 "ss"
3650 }, {
3651 "st",
3652 "st_Latn_ZA",
3653 "st"
3654 }, {
3655 "sv",
3656 "sv_Latn_SE",
3657 "sv"
3658 }, {
3659 "sw",
3660 "sw_Latn_TZ",
3661 "sw"
3662 }, {
3663 "ta",
3664 "ta_Taml_IN",
3665 "ta"
3666 }, {
3667 "te",
3668 "te_Telu_IN",
3669 "te"
3670 }, {
3671 "tet",
3672 "tet_Latn_TL",
3673 "tet"
3674 }, {
3675 "tg",
3676 "tg_Cyrl_TJ",
3677 "tg"
3678 }, {
3679 "th",
3680 "th_Thai_TH",
3681 "th"
3682 }, {
3683 "ti",
3684 "ti_Ethi_ET",
3685 "ti"
3686 }, {
3687 "tig",
3688 "tig_Ethi_ER",
3689 "tig"
3690 }, {
3691 "tk",
3692 "tk_Latn_TM",
3693 "tk"
3694 }, {
3695 "tkl",
3696 "tkl_Latn_TK",
3697 "tkl"
3698 }, {
3699 "tn",
3700 "tn_Latn_ZA",
3701 "tn"
3702 }, {
3703 "to",
3704 "to_Latn_TO",
3705 "to"
3706 }, {
3707 "tpi",
3708 "tpi_Latn_PG",
3709 "tpi"
3710 }, {
3711 "tr",
3712 "tr_Latn_TR",
3713 "tr"
3714 }, {
3715 "ts",
3716 "ts_Latn_ZA",
3717 "ts"
3718 }, {
3719 "tt",
3720 "tt_Cyrl_RU",
3721 "tt"
3722 }, {
3723 "tvl",
3724 "tvl_Latn_TV",
3725 "tvl"
3726 }, {
3727 "ty",
3728 "ty_Latn_PF",
3729 "ty"
3730 }, {
3731 "uk",
3732 "uk_Cyrl_UA",
3733 "uk"
3734 }, {
3735 "und",
3736 "en_Latn_US",
3737 "en"
3738 }, {
3739 "und_AD",
3740 "ca_Latn_AD",
3741 "ca_AD"
3742 }, {
3743 "und_AE",
3744 "ar_Arab_AE",
3745 "ar_AE"
3746 }, {
3747 "und_AF",
3748 "fa_Arab_AF",
3749 "fa_AF"
3750 }, {
3751 "und_AL",
3752 "sq_Latn_AL",
3753 "sq"
3754 }, {
3755 "und_AM",
3756 "hy_Armn_AM",
3757 "hy"
3758 }, {
3759 "und_AN",
3760 "pap_Latn_AN",
3761 "pap"
3762 }, {
3763 "und_AO",
3764 "pt_Latn_AO",
3765 "pt_AO"
3766 }, {
3767 "und_AR",
3768 "es_Latn_AR",
3769 "es_AR"
3770 }, {
3771 "und_AS",
3772 "sm_Latn_AS",
3773 "sm_AS"
3774 }, {
3775 "und_AT",
3776 "de_Latn_AT",
3777 "de_AT"
3778 }, {
3779 "und_AW",
3780 "nl_Latn_AW",
3781 "nl_AW"
3782 }, {
3783 "und_AX",
3784 "sv_Latn_AX",
3785 "sv_AX"
3786 }, {
3787 "und_AZ",
3788 "az_Latn_AZ",
3789 "az"
3790 }, {
3791 "und_Arab",
3792 "ar_Arab_EG",
3793 "ar"
3794 }, {
3795 "und_Arab_IN",
3796 "ur_Arab_IN",
3797 "ur_IN"
3798 }, {
3799 "und_Arab_PK",
3800 "ur_Arab_PK",
3801 "ur"
3802 }, {
3803 "und_Arab_SN",
3804 "ar_Arab_SN",
3805 "ar_SN"
3806 }, {
3807 "und_Armn",
3808 "hy_Armn_AM",
3809 "hy"
3810 }, {
3811 "und_BA",
3812 "bs_Latn_BA",
3813 "bs"
3814 }, {
3815 "und_BD",
3816 "bn_Beng_BD",
3817 "bn"
3818 }, {
3819 "und_BE",
3820 "nl_Latn_BE",
3821 "nl_BE"
3822 }, {
3823 "und_BF",
3824 "fr_Latn_BF",
3825 "fr_BF"
3826 }, {
3827 "und_BG",
3828 "bg_Cyrl_BG",
3829 "bg"
3830 }, {
3831 "und_BH",
3832 "ar_Arab_BH",
3833 "ar_BH"
3834 }, {
3835 "und_BI",
3836 "rn_Latn_BI",
3837 "rn"
3838 }, {
3839 "und_BJ",
3840 "fr_Latn_BJ",
3841 "fr_BJ"
3842 }, {
3843 "und_BN",
3844 "ms_Latn_BN",
3845 "ms_BN"
3846 }, {
3847 "und_BO",
3848 "es_Latn_BO",
3849 "es_BO"
3850 }, {
3851 "und_BR",
3852 "pt_Latn_BR",
3853 "pt"
3854 }, {
3855 "und_BT",
3856 "dz_Tibt_BT",
3857 "dz"
3858 }, {
3859 "und_BY",
3860 "be_Cyrl_BY",
3861 "be"
3862 }, {
3863 "und_Beng",
3864 "bn_Beng_BD",
3865 "bn"
3866 }, {
3867 "und_Beng_IN",
3868 "bn_Beng_IN",
3869 "bn_IN"
3870 }, {
3871 "und_CD",
3872 "sw_Latn_CD",
3873 "sw_CD"
3874 }, {
3875 "und_CF",
3876 "fr_Latn_CF",
3877 "fr_CF"
3878 }, {
3879 "und_CG",
3880 "fr_Latn_CG",
3881 "fr_CG"
3882 }, {
3883 "und_CH",
3884 "de_Latn_CH",
3885 "de_CH"
3886 }, {
3887 "und_CI",
3888 "fr_Latn_CI",
3889 "fr_CI"
3890 }, {
3891 "und_CL",
3892 "es_Latn_CL",
3893 "es_CL"
3894 }, {
3895 "und_CM",
3896 "fr_Latn_CM",
3897 "fr_CM"
3898 }, {
3899 "und_CN",
3900 "zh_Hans_CN",
3901 "zh"
3902 }, {
3903 "und_CO",
3904 "es_Latn_CO",
3905 "es_CO"
3906 }, {
3907 "und_CR",
3908 "es_Latn_CR",
3909 "es_CR"
3910 }, {
3911 "und_CU",
3912 "es_Latn_CU",
3913 "es_CU"
3914 }, {
3915 "und_CV",
3916 "pt_Latn_CV",
3917 "pt_CV"
3918 }, {
3919 "und_CY",
3920 "el_Grek_CY",
3921 "el_CY"
3922 }, {
3923 "und_CZ",
3924 "cs_Latn_CZ",
3925 "cs"
3926 }, {
3927 "und_Cher",
3928 "chr_Cher_US",
3929 "chr"
3930 }, {
3931 "und_Cyrl",
3932 "ru_Cyrl_RU",
3933 "ru"
3934 }, {
3935 "und_Cyrl_KZ",
3936 "ru_Cyrl_KZ",
3937 "ru_KZ"
3938 }, {
3939 "und_DE",
3940 "de_Latn_DE",
3941 "de"
3942 }, {
3943 "und_DJ",
3944 "aa_Latn_DJ",
3945 "aa_DJ"
3946 }, {
3947 "und_DK",
3948 "da_Latn_DK",
3949 "da"
3950 }, {
3951 "und_DO",
3952 "es_Latn_DO",
3953 "es_DO"
3954 }, {
3955 "und_DZ",
3956 "ar_Arab_DZ",
3957 "ar_DZ"
3958 }, {
3959 "und_Deva",
3960 "hi_Deva_IN",
3961 "hi"
3962 }, {
3963 "und_EC",
3964 "es_Latn_EC",
3965 "es_EC"
3966 }, {
3967 "und_EE",
3968 "et_Latn_EE",
3969 "et"
3970 }, {
3971 "und_EG",
3972 "ar_Arab_EG",
3973 "ar"
3974 }, {
3975 "und_EH",
3976 "ar_Arab_EH",
3977 "ar_EH"
3978 }, {
3979 "und_ER",
3980 "ti_Ethi_ER",
3981 "ti_ER"
3982 }, {
3983 "und_ES",
3984 "es_Latn_ES",
3985 "es"
3986 }, {
3987 "und_ET",
3988 "en_Latn_ET",
3989 "en_ET"
3990 }, {
3991 "und_Ethi",
3992 "am_Ethi_ET",
3993 "am"
3994 }, {
3995 "und_Ethi_ER",
3996 "am_Ethi_ER",
3997 "am_ER"
3998 }, {
3999 "und_FI",
4000 "fi_Latn_FI",
4001 "fi"
4002 }, {
4003 "und_FM",
4004 "chk_Latn_FM",
4005 "chk"
4006 }, {
4007 "und_FO",
4008 "fo_Latn_FO",
4009 "fo"
4010 }, {
4011 "und_FR",
4012 "fr_Latn_FR",
4013 "fr"
4014 }, {
4015 "und_GA",
4016 "fr_Latn_GA",
4017 "fr_GA"
4018 }, {
4019 "und_GE",
4020 "ka_Geor_GE",
4021 "ka"
4022 }, {
4023 "und_GF",
4024 "fr_Latn_GF",
4025 "fr_GF"
4026 }, {
4027 "und_GL",
4028 "kl_Latn_GL",
4029 "kl"
4030 }, {
4031 "und_GN",
4032 "fr_Latn_GN",
4033 "fr_GN"
4034 }, {
4035 "und_GP",
4036 "fr_Latn_GP",
4037 "fr_GP"
4038 }, {
4039 "und_GQ",
4040 "es_Latn_GQ",
4041 "es_GQ"
4042 }, {
4043 "und_GR",
4044 "el_Grek_GR",
4045 "el"
4046 }, {
4047 "und_GT",
4048 "es_Latn_GT",
4049 "es_GT"
4050 }, {
4051 "und_GU",
4052 "en_Latn_GU",
4053 "en_GU"
4054 }, {
4055 "und_GW",
4056 "pt_Latn_GW",
4057 "pt_GW"
4058 }, {
4059 "und_Geor",
4060 "ka_Geor_GE",
4061 "ka"
4062 }, {
4063 "und_Grek",
4064 "el_Grek_GR",
4065 "el"
4066 }, {
4067 "und_Gujr",
4068 "gu_Gujr_IN",
4069 "gu"
4070 }, {
4071 "und_Guru",
4072 "pa_Guru_IN",
4073 "pa"
4074 }, {
4075 "und_HK",
4076 "zh_Hant_HK",
4077 "zh_HK"
4078 }, {
4079 "und_HN",
4080 "es_Latn_HN",
4081 "es_HN"
4082 }, {
4083 "und_HR",
4084 "hr_Latn_HR",
4085 "hr"
4086 }, {
4087 "und_HT",
4088 "ht_Latn_HT",
4089 "ht"
4090 }, {
4091 "und_HU",
4092 "hu_Latn_HU",
4093 "hu"
4094 }, {
4095 "und_Hani",
4096 "zh_Hans_CN",
4097 "zh"
4098 }, {
4099 "und_Hans",
4100 "zh_Hans_CN",
4101 "zh"
4102 }, {
4103 "und_Hant",
4104 "zh_Hant_TW",
4105 "zh_TW"
4106 }, {
4107 "und_Hebr",
4108 "he_Hebr_IL",
4109 "he"
4110 }, {
4111 "und_IL",
4112 "he_Hebr_IL",
4113 "he"
4114 }, {
4115 "und_IN",
4116 "hi_Deva_IN",
4117 "hi"
4118 }, {
4119 "und_IQ",
4120 "ar_Arab_IQ",
4121 "ar_IQ"
4122 }, {
4123 "und_IR",
4124 "fa_Arab_IR",
4125 "fa"
4126 }, {
4127 "und_IS",
4128 "is_Latn_IS",
4129 "is"
4130 }, {
4131 "und_IT",
4132 "it_Latn_IT",
4133 "it"
4134 }, {
4135 "und_JO",
4136 "ar_Arab_JO",
4137 "ar_JO"
4138 }, {
4139 "und_JP",
4140 "ja_Jpan_JP",
4141 "ja"
4142 }, {
4143 "und_Jpan",
4144 "ja_Jpan_JP",
4145 "ja"
4146 }, {
4147 "und_KG",
4148 "ky_Cyrl_KG",
4149 "ky"
4150 }, {
4151 "und_KH",
4152 "km_Khmr_KH",
4153 "km"
4154 }, {
4155 "und_KM",
4156 "ar_Arab_KM",
4157 "ar_KM"
4158 }, {
4159 "und_KP",
4160 "ko_Kore_KP",
4161 "ko_KP"
4162 }, {
4163 "und_KR",
4164 "ko_Kore_KR",
4165 "ko"
4166 }, {
4167 "und_KW",
4168 "ar_Arab_KW",
4169 "ar_KW"
4170 }, {
4171 "und_KZ",
4172 "ru_Cyrl_KZ",
4173 "ru_KZ"
4174 }, {
4175 "und_Khmr",
4176 "km_Khmr_KH",
4177 "km"
4178 }, {
4179 "und_Knda",
4180 "kn_Knda_IN",
4181 "kn"
4182 }, {
4183 "und_Kore",
4184 "ko_Kore_KR",
4185 "ko"
4186 }, {
4187 "und_LA",
4188 "lo_Laoo_LA",
4189 "lo"
4190 }, {
4191 "und_LB",
4192 "ar_Arab_LB",
4193 "ar_LB"
4194 }, {
4195 "und_LI",
4196 "de_Latn_LI",
4197 "de_LI"
4198 }, {
4199 "und_LK",
4200 "si_Sinh_LK",
4201 "si"
4202 }, {
4203 "und_LS",
4204 "st_Latn_LS",
4205 "st_LS"
4206 }, {
4207 "und_LT",
4208 "lt_Latn_LT",
4209 "lt"
4210 }, {
4211 "und_LU",
4212 "fr_Latn_LU",
4213 "fr_LU"
4214 }, {
4215 "und_LV",
4216 "lv_Latn_LV",
4217 "lv"
4218 }, {
4219 "und_LY",
4220 "ar_Arab_LY",
4221 "ar_LY"
4222 }, {
4223 "und_Laoo",
4224 "lo_Laoo_LA",
4225 "lo"
4226 }, {
4227 "und_Latn_ES",
4228 "es_Latn_ES",
4229 "es"
4230 }, {
4231 "und_Latn_ET",
4232 "en_Latn_ET",
4233 "en_ET"
4234 }, {
4235 "und_Latn_GB",
4236 "en_Latn_GB",
4237 "en_GB"
4238 }, {
4239 "und_Latn_GH",
4240 "ak_Latn_GH",
4241 "ak"
4242 }, {
4243 "und_Latn_ID",
4244 "id_Latn_ID",
4245 "id"
4246 }, {
4247 "und_Latn_IT",
4248 "it_Latn_IT",
4249 "it"
4250 }, {
4251 "und_Latn_NG",
4252 "en_Latn_NG",
4253 "en_NG"
4254 }, {
4255 "und_Latn_TR",
4256 "tr_Latn_TR",
4257 "tr"
4258 }, {
4259 "und_Latn_ZA",
4260 "en_Latn_ZA",
4261 "en_ZA"
4262 }, {
4263 "und_MA",
4264 "ar_Arab_MA",
4265 "ar_MA"
4266 }, {
4267 "und_MC",
4268 "fr_Latn_MC",
4269 "fr_MC"
4270 }, {
4271 "und_MD",
4272 "ro_Latn_MD",
4273 "ro_MD"
4274 }, {
4275 "und_ME",
4276 "sr_Latn_ME",
4277 "sr_ME"
4278 }, {
4279 "und_MG",
4280 "mg_Latn_MG",
4281 "mg"
4282 }, {
4283 "und_MH",
4284 "en_Latn_MH",
4285 "en_MH"
4286 }, {
4287 "und_MK",
4288 "mk_Cyrl_MK",
4289 "mk"
4290 }, {
4291 "und_ML",
4292 "bm_Latn_ML",
4293 "bm"
4294 }, {
4295 "und_MM",
4296 "my_Mymr_MM",
4297 "my"
4298 }, {
4299 "und_MN",
4300 "mn_Cyrl_MN",
4301 "mn"
4302 }, {
4303 "und_MO",
4304 "zh_Hant_MO",
4305 "zh_MO"
4306 }, {
4307 "und_MQ",
4308 "fr_Latn_MQ",
4309 "fr_MQ"
4310 }, {
4311 "und_MR",
4312 "ar_Arab_MR",
4313 "ar_MR"
4314 }, {
4315 "und_MT",
4316 "mt_Latn_MT",
4317 "mt"
4318 }, {
4319 "und_MV",
4320 "dv_Thaa_MV",
4321 "dv"
4322 }, {
4323 "und_MW",
4324 "en_Latn_MW",
4325 "en_MW"
4326 }, {
4327 "und_MX",
4328 "es_Latn_MX",
4329 "es_MX"
4330 }, {
4331 "und_MY",
4332 "ms_Latn_MY",
4333 "ms"
4334 }, {
4335 "und_MZ",
4336 "pt_Latn_MZ",
4337 "pt_MZ"
4338 }, {
4339 "und_Mlym",
4340 "ml_Mlym_IN",
4341 "ml"
4342 }, {
4343 "und_Mymr",
4344 "my_Mymr_MM",
4345 "my"
4346 }, {
4347 "und_NC",
4348 "fr_Latn_NC",
4349 "fr_NC"
4350 }, {
4351 "und_NE",
4352 "ha_Latn_NE",
4353 "ha_NE"
4354 }, {
4355 "und_NG",
4356 "en_Latn_NG",
4357 "en_NG"
4358 }, {
4359 "und_NI",
4360 "es_Latn_NI",
4361 "es_NI"
4362 }, {
4363 "und_NL",
4364 "nl_Latn_NL",
4365 "nl"
4366 }, {
4367 "und_NO",
4368 "nb_Latn_NO",
4369 "nb"
4370 }, {
4371 "und_NP",
4372 "ne_Deva_NP",
4373 "ne"
4374 }, {
4375 "und_NR",
4376 "en_Latn_NR",
4377 "en_NR"
4378 }, {
4379 "und_NU",
4380 "en_Latn_NU",
4381 "en_NU"
4382 }, {
4383 "und_OM",
4384 "ar_Arab_OM",
4385 "ar_OM"
4386 }, {
4387 "und_Orya",
4388 "or_Orya_IN",
4389 "or"
4390 }, {
4391 "und_PA",
4392 "es_Latn_PA",
4393 "es_PA"
4394 }, {
4395 "und_PE",
4396 "es_Latn_PE",
4397 "es_PE"
4398 }, {
4399 "und_PF",
4400 "fr_Latn_PF",
4401 "fr_PF"
4402 }, {
4403 "und_PG",
4404 "tpi_Latn_PG",
4405 "tpi"
4406 }, {
4407 "und_PH",
4408 "fil_Latn_PH",
4409 "fil"
4410 }, {
4411 "und_PL",
4412 "pl_Latn_PL",
4413 "pl"
4414 }, {
4415 "und_PM",
4416 "fr_Latn_PM",
4417 "fr_PM"
4418 }, {
4419 "und_PR",
4420 "es_Latn_PR",
4421 "es_PR"
4422 }, {
4423 "und_PS",
4424 "ar_Arab_PS",
4425 "ar_PS"
4426 }, {
4427 "und_PT",
4428 "pt_Latn_PT",
4429 "pt_PT"
4430 }, {
4431 "und_PW",
4432 "pau_Latn_PW",
4433 "pau"
4434 }, {
4435 "und_PY",
4436 "gn_Latn_PY",
4437 "gn"
4438 }, {
4439 "und_QA",
4440 "ar_Arab_QA",
4441 "ar_QA"
4442 }, {
4443 "und_RE",
4444 "fr_Latn_RE",
4445 "fr_RE"
4446 }, {
4447 "und_RO",
4448 "ro_Latn_RO",
4449 "ro"
4450 }, {
4451 "und_RS",
4452 "sr_Cyrl_RS",
4453 "sr"
4454 }, {
4455 "und_RU",
4456 "ru_Cyrl_RU",
4457 "ru"
4458 }, {
4459 "und_RW",
4460 "rw_Latn_RW",
4461 "rw"
4462 }, {
4463 "und_SA",
4464 "ar_Arab_SA",
4465 "ar_SA"
4466 }, {
4467 "und_SD",
4468 "ar_Arab_SD",
4469 "ar_SD"
4470 }, {
4471 "und_SE",
4472 "sv_Latn_SE",
4473 "sv"
4474 }, {
4475 "und_SG",
4476 "en_Latn_SG",
4477 "en_SG"
4478 }, {
4479 "und_SI",
4480 "sl_Latn_SI",
4481 "sl"
4482 }, {
4483 "und_SJ",
4484 "nb_Latn_SJ",
4485 "nb_SJ"
4486 }, {
4487 "und_SK",
4488 "sk_Latn_SK",
4489 "sk"
4490 }, {
4491 "und_SM",
4492 "it_Latn_SM",
4493 "it_SM"
4494 }, {
4495 "und_SN",
4496 "fr_Latn_SN",
4497 "fr_SN"
4498 }, {
4499 "und_SO",
4500 "so_Latn_SO",
4501 "so"
4502 }, {
4503 "und_SR",
4504 "nl_Latn_SR",
4505 "nl_SR"
4506 }, {
4507 "und_ST",
4508 "pt_Latn_ST",
4509 "pt_ST"
4510 }, {
4511 "und_SV",
4512 "es_Latn_SV",
4513 "es_SV"
4514 }, {
4515 "und_SY",
4516 "ar_Arab_SY",
4517 "ar_SY"
4518 }, {
4519 "und_Sinh",
4520 "si_Sinh_LK",
4521 "si"
4522 }, {
4523 "und_TD",
4524 "fr_Latn_TD",
4525 "fr_TD"
4526 }, {
4527 "und_TG",
4528 "fr_Latn_TG",
4529 "fr_TG"
4530 }, {
4531 "und_TH",
4532 "th_Thai_TH",
4533 "th"
4534 }, {
4535 "und_TJ",
4536 "tg_Cyrl_TJ",
4537 "tg"
4538 }, {
4539 "und_TK",
4540 "tkl_Latn_TK",
4541 "tkl"
4542 }, {
4543 "und_TL",
4544 "pt_Latn_TL",
4545 "pt_TL"
4546 }, {
4547 "und_TM",
4548 "tk_Latn_TM",
4549 "tk"
4550 }, {
4551 "und_TN",
4552 "ar_Arab_TN",
4553 "ar_TN"
4554 }, {
4555 "und_TO",
4556 "to_Latn_TO",
4557 "to"
4558 }, {
4559 "und_TR",
4560 "tr_Latn_TR",
4561 "tr"
4562 }, {
4563 "und_TV",
4564 "tvl_Latn_TV",
4565 "tvl"
4566 }, {
4567 "und_TW",
4568 "zh_Hant_TW",
4569 "zh_TW"
4570 }, {
4571 "und_Taml",
4572 "ta_Taml_IN",
4573 "ta"
4574 }, {
4575 "und_Telu",
4576 "te_Telu_IN",
4577 "te"
4578 }, {
4579 "und_Thaa",
4580 "dv_Thaa_MV",
4581 "dv"
4582 }, {
4583 "und_Thai",
4584 "th_Thai_TH",
4585 "th"
4586 }, {
4587 "und_Tibt",
4588 "bo_Tibt_CN",
4589 "bo"
4590 }, {
4591 "und_UA",
4592 "uk_Cyrl_UA",
4593 "uk"
4594 }, {
4595 "und_UY",
4596 "es_Latn_UY",
4597 "es_UY"
4598 }, {
4599 "und_UZ",
4600 "uz_Cyrl_UZ",
4601 "uz"
4602 }, {
4603 "und_VA",
4604 "la_Latn_VA",
4605 "la"
4606 }, {
4607 "und_VE",
4608 "es_Latn_VE",
4609 "es_VE"
4610 }, {
4611 "und_VN",
4612 "vi_Latn_VN",
4613 "vi"
4614 }, {
4615 "und_VU",
4616 "bi_Latn_VU",
4617 "bi"
4618 }, {
4619 "und_WF",
4620 "fr_Latn_WF",
4621 "fr_WF"
4622 }, {
4623 "und_WS",
4624 "sm_Latn_WS",
4625 "sm"
4626 }, {
4627 "und_YE",
4628 "ar_Arab_YE",
4629 "ar_YE"
4630 }, {
4631 "und_YT",
4632 "fr_Latn_YT",
4633 "fr_YT"
4634 }, {
4635 "und_Yiii",
4636 "ii_Yiii_CN",
4637 "ii"
4638 }, {
4639 "ur",
4640 "ur_Arab_PK",
4641 "ur"
4642 }, {
4643 "uz",
4644 "uz_Cyrl_UZ",
4645 "uz"
4646 }, {
4647 "uz_AF",
4648 "uz_Arab_AF",
4649 "uz_AF"
4650 }, {
4651 "uz_Arab",
4652 "uz_Arab_AF",
4653 "uz_AF"
4654 }, {
4655 "ve",
4656 "ve_Latn_ZA",
4657 "ve"
4658 }, {
4659 "vi",
4660 "vi_Latn_VN",
4661 "vi"
4662 }, {
4663 "wal",
4664 "wal_Ethi_ET",
4665 "wal"
4666 }, {
4667 "wo",
4668 "wo_Latn_SN",
4669 "wo"
4670 }, {
4671 "xh",
4672 "xh_Latn_ZA",
4673 "xh"
4674 }, {
4675 "yo",
4676 "yo_Latn_NG",
4677 "yo"
4678 }, {
4679 "zh",
4680 "zh_Hans_CN",
4681 "zh"
4682 }, {
4683 "zh_HK",
4684 "zh_Hant_HK",
4685 "zh_HK"
4686 }, {
4687 "zh_Hani",
4688 "zh_Hans_CN",
4689 "zh"
4690 }, {
4691 "zh_Hant",
4692 "zh_Hant_TW",
4693 "zh_TW"
4694 }, {
4695 "zh_MO",
4696 "zh_Hant_MO",
4697 "zh_MO"
4698 }, {
4699 "zh_TW",
4700 "zh_Hant_TW",
4701 "zh_TW"
4702 }, {
4703 "zu",
4704 "zu_Latn_ZA",
4705 "zu"
4706 }, {
4707 "und",
4708 "en_Latn_US",
4709 "en"
4710 }, {
4711 "und_ZZ",
4712 "en_Latn_US",
4713 "en"
4714 }, {
4715 "und_CN",
4716 "zh_Hans_CN",
4717 "zh"
4718 }, {
4719 "und_TW",
4720 "zh_Hant_TW",
4721 "zh_TW"
4722 }, {
4723 "und_HK",
4724 "zh_Hant_HK",
4725 "zh_HK"
4726 }, {
4727 "und_AQ",
4728 "en_Latn_AQ",
4729 "en_AQ"
4730 }, {
4731 "und_Zzzz",
4732 "en_Latn_US",
4733 "en"
4734 }, {
4735 "und_Zzzz_ZZ",
4736 "en_Latn_US",
4737 "en"
4738 }, {
4739 "und_Zzzz_CN",
4740 "zh_Hans_CN",
4741 "zh"
4742 }, {
4743 "und_Zzzz_TW",
4744 "zh_Hant_TW",
4745 "zh_TW"
4746 }, {
4747 "und_Zzzz_HK",
4748 "zh_Hant_HK",
4749 "zh_HK"
4750 }, {
4751 "und_Zzzz_AQ",
4752 "en_Latn_AQ",
4753 "en_AQ"
4754 }, {
4755 "und_Latn",
4756 "en_Latn_US",
4757 "en"
4758 }, {
4759 "und_Latn_ZZ",
4760 "en_Latn_US",
4761 "en"
4762 }, {
4763 "und_Latn_CN",
4764 "za_Latn_CN",
4765 "za"
4766 }, {
4767 "und_Latn_TW",
4768 "zh_Latn_TW",
4769 "zh_Latn_TW"
4770 }, {
4771 "und_Latn_HK",
4772 "zh_Latn_HK",
4773 "zh_Latn_HK"
4774 }, {
4775 "und_Latn_AQ",
4776 "en_Latn_AQ",
4777 "en_AQ"
4778 }, {
4779 "und_Hans",
4780 "zh_Hans_CN",
4781 "zh"
4782 }, {
4783 "und_Hans_ZZ",
4784 "zh_Hans_CN",
4785 "zh"
4786 }, {
4787 "und_Hans_CN",
4788 "zh_Hans_CN",
4789 "zh"
4790 }, {
4791 "und_Hans_TW",
4792 "zh_Hans_TW",
4793 "zh_Hans_TW"
4794 }, {
4795 "und_Hans_HK",
4796 "zh_Hans_HK",
4797 "zh_Hans_HK"
4798 }, {
4799 "und_Hans_AQ",
4800 "zh_Hans_AQ",
4801 "zh_AQ"
4802 }, {
4803 "und_Hant",
4804 "zh_Hant_TW",
4805 "zh_TW"
4806 }, {
4807 "und_Hant_ZZ",
4808 "zh_Hant_TW",
4809 "zh_TW"
4810 }, {
4811 "und_Hant_CN",
4812 "zh_Hant_CN",
4813 "zh_Hant_CN"
4814 }, {
4815 "und_Hant_TW",
4816 "zh_Hant_TW",
4817 "zh_TW"
4818 }, {
4819 "und_Hant_HK",
4820 "zh_Hant_HK",
4821 "zh_HK"
4822 }, {
4823 "und_Hant_AQ",
4824 "zh_Hant_AQ",
4825 "zh_Hant_AQ"
4826 }, {
4827 "und_Moon",
4828 "en_Moon_US",
4829 "en_Moon"
4830 }, {
4831 "und_Moon_ZZ",
4832 "en_Moon_US",
4833 "en_Moon"
4834 }, {
4835 "und_Moon_CN",
4836 "zh_Moon_CN",
4837 "zh_Moon"
4838 }, {
4839 "und_Moon_TW",
4840 "zh_Moon_TW",
4841 "zh_Moon_TW"
4842 }, {
4843 "und_Moon_HK",
4844 "zh_Moon_HK",
4845 "zh_Moon_HK"
4846 }, {
4847 "und_Moon_AQ",
4848 "en_Moon_AQ",
4849 "en_Moon_AQ"
4850 }, {
4851 "es",
4852 "es_Latn_ES",
4853 "es"
4854 }, {
4855 "es_ZZ",
4856 "es_Latn_ES",
4857 "es"
4858 }, {
4859 "es_CN",
4860 "es_Latn_CN",
4861 "es_CN"
4862 }, {
4863 "es_TW",
4864 "es_Latn_TW",
4865 "es_TW"
4866 }, {
4867 "es_HK",
4868 "es_Latn_HK",
4869 "es_HK"
4870 }, {
4871 "es_AQ",
4872 "es_Latn_AQ",
4873 "es_AQ"
4874 }, {
4875 "es_Zzzz",
4876 "es_Latn_ES",
4877 "es"
4878 }, {
4879 "es_Zzzz_ZZ",
4880 "es_Latn_ES",
4881 "es"
4882 }, {
4883 "es_Zzzz_CN",
4884 "es_Latn_CN",
4885 "es_CN"
4886 }, {
4887 "es_Zzzz_TW",
4888 "es_Latn_TW",
4889 "es_TW"
4890 }, {
4891 "es_Zzzz_HK",
4892 "es_Latn_HK",
4893 "es_HK"
4894 }, {
4895 "es_Zzzz_AQ",
4896 "es_Latn_AQ",
4897 "es_AQ"
4898 }, {
4899 "es_Latn",
4900 "es_Latn_ES",
4901 "es"
4902 }, {
4903 "es_Latn_ZZ",
4904 "es_Latn_ES",
4905 "es"
4906 }, {
4907 "es_Latn_CN",
4908 "es_Latn_CN",
4909 "es_CN"
4910 }, {
4911 "es_Latn_TW",
4912 "es_Latn_TW",
4913 "es_TW"
4914 }, {
4915 "es_Latn_HK",
4916 "es_Latn_HK",
4917 "es_HK"
4918 }, {
4919 "es_Latn_AQ",
4920 "es_Latn_AQ",
4921 "es_AQ"
4922 }, {
4923 "es_Hans",
4924 "es_Hans_ES",
4925 "es_Hans"
4926 }, {
4927 "es_Hans_ZZ",
4928 "es_Hans_ES",
4929 "es_Hans"
4930 }, {
4931 "es_Hans_CN",
4932 "es_Hans_CN",
4933 "es_Hans_CN"
4934 }, {
4935 "es_Hans_TW",
4936 "es_Hans_TW",
4937 "es_Hans_TW"
4938 }, {
4939 "es_Hans_HK",
4940 "es_Hans_HK",
4941 "es_Hans_HK"
4942 }, {
4943 "es_Hans_AQ",
4944 "es_Hans_AQ",
4945 "es_Hans_AQ"
4946 }, {
4947 "es_Hant",
4948 "es_Hant_ES",
4949 "es_Hant"
4950 }, {
4951 "es_Hant_ZZ",
4952 "es_Hant_ES",
4953 "es_Hant"
4954 }, {
4955 "es_Hant_CN",
4956 "es_Hant_CN",
4957 "es_Hant_CN"
4958 }, {
4959 "es_Hant_TW",
4960 "es_Hant_TW",
4961 "es_Hant_TW"
4962 }, {
4963 "es_Hant_HK",
4964 "es_Hant_HK",
4965 "es_Hant_HK"
4966 }, {
4967 "es_Hant_AQ",
4968 "es_Hant_AQ",
4969 "es_Hant_AQ"
4970 }, {
4971 "es_Moon",
4972 "es_Moon_ES",
4973 "es_Moon"
4974 }, {
4975 "es_Moon_ZZ",
4976 "es_Moon_ES",
4977 "es_Moon"
4978 }, {
4979 "es_Moon_CN",
4980 "es_Moon_CN",
4981 "es_Moon_CN"
4982 }, {
4983 "es_Moon_TW",
4984 "es_Moon_TW",
4985 "es_Moon_TW"
4986 }, {
4987 "es_Moon_HK",
4988 "es_Moon_HK",
4989 "es_Moon_HK"
4990 }, {
4991 "es_Moon_AQ",
4992 "es_Moon_AQ",
4993 "es_Moon_AQ"
4994 }, {
4995 "zh",
4996 "zh_Hans_CN",
4997 "zh"
4998 }, {
4999 "zh_ZZ",
5000 "zh_Hans_CN",
5001 "zh"
5002 }, {
5003 "zh_CN",
5004 "zh_Hans_CN",
5005 "zh"
5006 }, {
5007 "zh_TW",
5008 "zh_Hant_TW",
5009 "zh_TW"
5010 }, {
5011 "zh_HK",
5012 "zh_Hant_HK",
5013 "zh_HK"
5014 }, {
5015 "zh_AQ",
5016 "zh_Hans_AQ",
5017 "zh_AQ"
5018 }, {
5019 "zh_Zzzz",
5020 "zh_Hans_CN",
5021 "zh"
5022 }, {
5023 "zh_Zzzz_ZZ",
5024 "zh_Hans_CN",
5025 "zh"
5026 }, {
5027 "zh_Zzzz_CN",
5028 "zh_Hans_CN",
5029 "zh"
5030 }, {
5031 "zh_Zzzz_TW",
5032 "zh_Hant_TW",
5033 "zh_TW"
5034 }, {
5035 "zh_Zzzz_HK",
5036 "zh_Hant_HK",
5037 "zh_HK"
5038 }, {
5039 "zh_Zzzz_AQ",
5040 "zh_Hans_AQ",
5041 "zh_AQ"
5042 }, {
5043 "zh_Latn",
5044 "zh_Latn_CN",
5045 "zh_Latn"
5046 }, {
5047 "zh_Latn_ZZ",
5048 "zh_Latn_CN",
5049 "zh_Latn"
5050 }, {
5051 "zh_Latn_CN",
5052 "zh_Latn_CN",
5053 "zh_Latn"
5054 }, {
5055 "zh_Latn_TW",
5056 "zh_Latn_TW",
5057 "zh_Latn_TW"
5058 }, {
5059 "zh_Latn_HK",
5060 "zh_Latn_HK",
5061 "zh_Latn_HK"
5062 }, {
5063 "zh_Latn_AQ",
5064 "zh_Latn_AQ",
5065 "zh_Latn_AQ"
5066 }, {
5067 "zh_Hans",
5068 "zh_Hans_CN",
5069 "zh"
5070 }, {
5071 "zh_Hans_ZZ",
5072 "zh_Hans_CN",
5073 "zh"
5074 }, {
5075 "zh_Hans_TW",
5076 "zh_Hans_TW",
5077 "zh_Hans_TW"
5078 }, {
5079 "zh_Hans_HK",
5080 "zh_Hans_HK",
5081 "zh_Hans_HK"
5082 }, {
5083 "zh_Hans_AQ",
5084 "zh_Hans_AQ",
5085 "zh_AQ"
5086 }, {
5087 "zh_Hant",
5088 "zh_Hant_TW",
5089 "zh_TW"
5090 }, {
5091 "zh_Hant_ZZ",
5092 "zh_Hant_TW",
5093 "zh_TW"
5094 }, {
5095 "zh_Hant_CN",
5096 "zh_Hant_CN",
5097 "zh_Hant_CN"
5098 }, {
5099 "zh_Hant_AQ",
5100 "zh_Hant_AQ",
5101 "zh_Hant_AQ"
5102 }, {
5103 "zh_Moon",
5104 "zh_Moon_CN",
5105 "zh_Moon"
5106 }, {
5107 "zh_Moon_ZZ",
5108 "zh_Moon_CN",
5109 "zh_Moon"
5110 }, {
5111 "zh_Moon_CN",
5112 "zh_Moon_CN",
5113 "zh_Moon"
5114 }, {
5115 "zh_Moon_TW",
5116 "zh_Moon_TW",
5117 "zh_Moon_TW"
5118 }, {
5119 "zh_Moon_HK",
5120 "zh_Moon_HK",
5121 "zh_Moon_HK"
5122 }, {
5123 "zh_Moon_AQ",
5124 "zh_Moon_AQ",
5125 "zh_Moon_AQ"
5126 }, {
5127 "art",
5128 "",
5129 ""
5130 }, {
5131 "art_ZZ",
5132 "",
5133 ""
5134 }, {
5135 "art_CN",
5136 "",
5137 ""
5138 }, {
5139 "art_TW",
5140 "",
5141 ""
5142 }, {
5143 "art_HK",
5144 "",
5145 ""
5146 }, {
5147 "art_AQ",
5148 "",
5149 ""
5150 }, {
5151 "art_Zzzz",
5152 "",
5153 ""
5154 }, {
5155 "art_Zzzz_ZZ",
5156 "",
5157 ""
5158 }, {
5159 "art_Zzzz_CN",
5160 "",
5161 ""
5162 }, {
5163 "art_Zzzz_TW",
5164 "",
5165 ""
5166 }, {
5167 "art_Zzzz_HK",
5168 "",
5169 ""
5170 }, {
5171 "art_Zzzz_AQ",
5172 "",
5173 ""
5174 }, {
5175 "art_Latn",
5176 "",
5177 ""
5178 }, {
5179 "art_Latn_ZZ",
5180 "",
5181 ""
5182 }, {
5183 "art_Latn_CN",
5184 "",
5185 ""
5186 }, {
5187 "art_Latn_TW",
5188 "",
5189 ""
5190 }, {
5191 "art_Latn_HK",
5192 "",
5193 ""
5194 }, {
5195 "art_Latn_AQ",
5196 "",
5197 ""
5198 }, {
5199 "art_Hans",
5200 "",
5201 ""
5202 }, {
5203 "art_Hans_ZZ",
5204 "",
5205 ""
5206 }, {
5207 "art_Hans_CN",
5208 "",
5209 ""
5210 }, {
5211 "art_Hans_TW",
5212 "",
5213 ""
5214 }, {
5215 "art_Hans_HK",
5216 "",
5217 ""
5218 }, {
5219 "art_Hans_AQ",
5220 "",
5221 ""
5222 }, {
5223 "art_Hant",
5224 "",
5225 ""
5226 }, {
5227 "art_Hant_ZZ",
5228 "",
5229 ""
5230 }, {
5231 "art_Hant_CN",
5232 "",
5233 ""
5234 }, {
5235 "art_Hant_TW",
5236 "",
5237 ""
5238 }, {
5239 "art_Hant_HK",
5240 "",
5241 ""
5242 }, {
5243 "art_Hant_AQ",
5244 "",
5245 ""
5246 }, {
5247 "art_Moon",
5248 "",
5249 ""
5250 }, {
5251 "art_Moon_ZZ",
5252 "",
5253 ""
5254 }, {
5255 "art_Moon_CN",
5256 "",
5257 ""
5258 }, {
5259 "art_Moon_TW",
5260 "",
5261 ""
5262 }, {
5263 "art_Moon_HK",
5264 "",
5265 ""
5266 }, {
5267 "art_Moon_AQ",
5268 "",
5269 ""
5270 }, {
5271 "de@collation=phonebook",
5272 "de_Latn_DE@collation=phonebook",
5273 "de@collation=phonebook"
5274 }
5275 };
5276
5277 typedef struct errorDataTag {
5278 const char* tag;
5279 const char* expected;
5280 UErrorCode uerror;
5281 int32_t bufferSize;
5282 } errorData;
5283
5284 const errorData maximizeErrors[] = {
5285 {
5286 "enfueiujhytdf",
5287 NULL,
5288 U_ILLEGAL_ARGUMENT_ERROR,
5289 -1
5290 },
5291 {
5292 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5293 NULL,
5294 U_ILLEGAL_ARGUMENT_ERROR,
5295 -1
5296 },
5297 {
5298 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5299 NULL,
5300 U_ILLEGAL_ARGUMENT_ERROR,
5301 -1
5302 },
5303 {
5304 "en_Latn_US_POSIX@currency=EURO",
5305 "en_Latn_US_POSIX@currency=EURO",
5306 U_BUFFER_OVERFLOW_ERROR,
5307 29
5308 },
5309 {
5310 "en_Latn_US_POSIX@currency=EURO",
5311 "en_Latn_US_POSIX@currency=EURO",
5312 U_STRING_NOT_TERMINATED_WARNING,
5313 30
5314 }
5315 };
5316
5317 const errorData minimizeErrors[] = {
5318 {
5319 "enfueiujhytdf",
5320 NULL,
5321 U_ILLEGAL_ARGUMENT_ERROR,
5322 -1
5323 },
5324 {
5325 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
5326 NULL,
5327 U_ILLEGAL_ARGUMENT_ERROR,
5328 -1
5329 },
5330 {
5331 "en_Latn_US_POSIX@currency=EURO",
5332 "en__POSIX@currency=EURO",
5333 U_BUFFER_OVERFLOW_ERROR,
5334 22
5335 },
5336 {
5337 "en_Latn_US_POSIX@currency=EURO",
5338 "en__POSIX@currency=EURO",
5339 U_STRING_NOT_TERMINATED_WARNING,
5340 23
5341 }
5342 };
5343
getExpectedReturnValue(const errorData * data)5344 static int32_t getExpectedReturnValue(const errorData* data)
5345 {
5346 if (data->uerror == U_BUFFER_OVERFLOW_ERROR ||
5347 data->uerror == U_STRING_NOT_TERMINATED_WARNING)
5348 {
5349 return strlen(data->expected);
5350 }
5351 else
5352 {
5353 return -1;
5354 }
5355 }
5356
getBufferSize(const errorData * data,int32_t actualSize)5357 static int32_t getBufferSize(const errorData* data, int32_t actualSize)
5358 {
5359 if (data->expected == NULL)
5360 {
5361 return actualSize;
5362 }
5363 else if (data->bufferSize < 0)
5364 {
5365 return strlen(data->expected) + 1;
5366 }
5367 else
5368 {
5369 return data->bufferSize;
5370 }
5371 }
5372
TestLikelySubtags()5373 static void TestLikelySubtags()
5374 {
5375 char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1];
5376 int32_t i = 0;
5377
5378 for (; i < sizeof(basic_maximize_data) / sizeof(basic_maximize_data[0]); ++i)
5379 {
5380 UErrorCode status = U_ZERO_ERROR;
5381 const char* const minimal = basic_maximize_data[i][0];
5382 const char* const maximal = basic_maximize_data[i][1];
5383
5384 /* const int32_t length = */
5385 uloc_addLikelySubtags(
5386 minimal,
5387 buffer,
5388 sizeof(buffer),
5389 &status);
5390 if (U_FAILURE(status)) {
5391 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status));
5392 status = U_ZERO_ERROR;
5393 }
5394 else if (uprv_strlen(maximal) == 0) {
5395 if (uprv_stricmp(minimal, buffer) != 0) {
5396 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5397 }
5398 }
5399 else if (uprv_stricmp(maximal, buffer) != 0) {
5400 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer);
5401 }
5402 }
5403
5404 for (i = 0; i < sizeof(basic_minimize_data) / sizeof(basic_minimize_data[0]); ++i) {
5405
5406 UErrorCode status = U_ZERO_ERROR;
5407 const char* const maximal = basic_minimize_data[i][0];
5408 const char* const minimal = basic_minimize_data[i][1];
5409
5410 /* const int32_t length = */
5411 uloc_minimizeSubtags(
5412 maximal,
5413 buffer,
5414 sizeof(buffer),
5415 &status);
5416
5417 if (U_FAILURE(status)) {
5418 log_err_status(status, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5419 status = U_ZERO_ERROR;
5420 }
5421 else if (uprv_strlen(minimal) == 0) {
5422 if (uprv_stricmp(maximal, buffer) != 0) {
5423 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5424 }
5425 }
5426 else if (uprv_stricmp(minimal, buffer) != 0) {
5427 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5428 }
5429 }
5430
5431 for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) {
5432
5433 UErrorCode status = U_ZERO_ERROR;
5434 const char* const minimal = full_data[i][0];
5435 const char* const maximal = full_data[i][1];
5436
5437 /* const int32_t length = */
5438 uloc_addLikelySubtags(
5439 minimal,
5440 buffer,
5441 sizeof(buffer),
5442 &status);
5443 if (U_FAILURE(status)) {
5444 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status));
5445 status = U_ZERO_ERROR;
5446 }
5447 else if (uprv_strlen(maximal) == 0) {
5448 if (uprv_stricmp(minimal, buffer) != 0) {
5449 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5450 }
5451 }
5452 else if (uprv_stricmp(maximal, buffer) != 0) {
5453 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer);
5454 }
5455 }
5456
5457 for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) {
5458
5459 UErrorCode status = U_ZERO_ERROR;
5460 const char* const maximal = full_data[i][1];
5461 const char* const minimal = full_data[i][2];
5462
5463 if (strlen(maximal) > 0) {
5464
5465 /* const int32_t length = */
5466 uloc_minimizeSubtags(
5467 maximal,
5468 buffer,
5469 sizeof(buffer),
5470 &status);
5471
5472 if (U_FAILURE(status)) {
5473 log_err_status(status, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status));
5474 status = U_ZERO_ERROR;
5475 }
5476 else if (uprv_strlen(minimal) == 0) {
5477 if (uprv_stricmp(maximal, buffer) != 0) {
5478 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer);
5479 }
5480 }
5481 else if (uprv_stricmp(minimal, buffer) != 0) {
5482 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer);
5483 }
5484 }
5485 }
5486
5487 for (i = 0; i < sizeof(maximizeErrors) / sizeof(maximizeErrors[0]); ++i) {
5488
5489 UErrorCode status = U_ZERO_ERROR;
5490 const char* const minimal = maximizeErrors[i].tag;
5491 const char* const maximal = maximizeErrors[i].expected;
5492 const UErrorCode expectedStatus = maximizeErrors[i].uerror;
5493 const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]);
5494 const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer));
5495
5496 const int32_t length =
5497 uloc_addLikelySubtags(
5498 minimal,
5499 buffer,
5500 bufferSize,
5501 &status);
5502
5503 if (status == U_ZERO_ERROR) {
5504 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus));
5505 status = U_ZERO_ERROR;
5506 }
5507 else if (status != expectedStatus) {
5508 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));
5509 }
5510 else if (length != expectedLength) {
5511 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length);
5512 }
5513 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5514 if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) {
5515 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n",
5516 maximal, minimal, (int)sizeof(buffer), buffer);
5517 }
5518 }
5519 }
5520
5521 for (i = 0; i < sizeof(minimizeErrors) / sizeof(minimizeErrors[0]); ++i) {
5522
5523 UErrorCode status = U_ZERO_ERROR;
5524 const char* const maximal = minimizeErrors[i].tag;
5525 const char* const minimal = minimizeErrors[i].expected;
5526 const UErrorCode expectedStatus = minimizeErrors[i].uerror;
5527 const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]);
5528 const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer));
5529
5530 const int32_t length =
5531 uloc_minimizeSubtags(
5532 maximal,
5533 buffer,
5534 bufferSize,
5535 &status);
5536
5537 if (status == U_ZERO_ERROR) {
5538 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus));
5539 status = U_ZERO_ERROR;
5540 }
5541 else if (status != expectedStatus) {
5542 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));
5543 }
5544 else if (length != expectedLength) {
5545 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length);
5546 }
5547 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
5548 if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) {
5549 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n",
5550 minimal, maximal, (int)sizeof(buffer), buffer);
5551 }
5552 }
5553 }
5554 }
5555
5556 const char* const locale_to_langtag[][3] = {
5557 {"@x=elmer", "x-elmer", "x-elmer"},
5558 {"", "und", "und"},
5559 {"en", "en", "en"},
5560 {"en_US", "en-US", "en-US"},
5561 {"iw_IL", "he-IL", "he-IL"},
5562 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"},
5563 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"},
5564 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"},
5565 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL}, /* variant POSIX_VAR is processed as regular variant */
5566 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL}, /* variant VAR_POSIX is processed as regular variant */
5567 {"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 */
5568 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"},
5569 {"und_555", "und-555", "und-555"},
5570 {"123", "und", NULL},
5571 {"%$#&", "und", NULL},
5572 {"_Latn", "und-Latn", "und-Latn"},
5573 {"_DE", "und-DE", "und-DE"},
5574 {"und_FR", "und-FR", "und-FR"},
5575 {"th_TH_TH", "th-TH-x-lvariant-th", NULL},
5576 {"bogus", "bogus", "bogus"},
5577 {"foooobarrr", "und", NULL},
5578 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"},
5579 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL},
5580 {"en_US_1234", "en-US-1234", "en-US-1234"},
5581 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"},
5582 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"},
5583 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL},
5584 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL},
5585 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"},
5586 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"},
5587 {"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"},
5588 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"},
5589 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"},
5590 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL},
5591 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-ks-identic", NULL},
5592 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"},
5593 {"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"},
5594 {"@x=elmer", "x-elmer", "x-elmer"},
5595 {"en@x=elmer", "en-x-elmer", "en-x-elmer"},
5596 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"},
5597 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"},
5598 {NULL, NULL, NULL}
5599 };
5600
TestToLanguageTag(void)5601 static void TestToLanguageTag(void) {
5602 char langtag[256];
5603 int32_t i;
5604 UErrorCode status;
5605 int32_t len;
5606 const char *inloc;
5607 const char *expected;
5608
5609 for (i = 0; locale_to_langtag[i][0] != NULL; i++) {
5610 inloc = locale_to_langtag[i][0];
5611
5612 /* testing non-strict mode */
5613 status = U_ZERO_ERROR;
5614 langtag[0] = 0;
5615 expected = locale_to_langtag[i][1];
5616
5617 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status);
5618 if (U_FAILURE(status)) {
5619 if (expected != NULL) {
5620 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n",
5621 inloc, u_errorName(status));
5622 }
5623 } else {
5624 if (expected == NULL) {
5625 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n",
5626 inloc, langtag);
5627 } else if (uprv_strcmp(langtag, expected) != 0) {
5628 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n",
5629 langtag, inloc, expected);
5630 }
5631 }
5632
5633 /* testing strict mode */
5634 status = U_ZERO_ERROR;
5635 langtag[0] = 0;
5636 expected = locale_to_langtag[i][2];
5637
5638 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status);
5639 if (U_FAILURE(status)) {
5640 if (expected != NULL) {
5641 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n",
5642 inloc, u_errorName(status));
5643 }
5644 } else {
5645 if (expected == NULL) {
5646 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n",
5647 inloc, langtag);
5648 } else if (uprv_strcmp(langtag, expected) != 0) {
5649 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n",
5650 langtag, inloc, expected);
5651 }
5652 }
5653 }
5654 }
5655
5656 static const struct {
5657 const char *bcpID;
5658 const char *locID;
5659 int32_t len;
5660 } langtag_to_locale[] = {
5661 {"en", "en", 2},
5662 {"en-us", "en_US", 5},
5663 {"und-US", "_US", 6},
5664 {"und-latn", "_Latn", 8},
5665 {"en-US-posix", "en_US_POSIX", 11},
5666 {"de-de_euro", "de", 2},
5667 {"kok-IN", "kok_IN", 6},
5668 {"123", "", 0},
5669 {"en_us", "", 0},
5670 {"en-latn-x", "en_Latn", 7},
5671 {"art-lojban", "jbo", 3},
5672 {"zh-hakka", "hak", 3},
5673 {"zh-cmn-CH", "cmn_CH", 9},
5674 {"xxx-yy", "xxx_YY", 6},
5675 {"fr-234", "fr_234", 6},
5676 {"i-default", "en@x=i-default", 14},
5677 {"i-test", "", 0},
5678 {"ja-jp-jp", "ja_JP", 5},
5679 {"bogus", "bogus", 5},
5680 {"boguslang", "", 0},
5681 {"EN-lATN-us", "en_Latn_US", 10},
5682 {"und-variant-1234", "__VARIANT_1234", 16},
5683 {"und-varzero-var1-vartwo", "__VARZERO", 11},
5684 {"en-u-ca-gregory", "en@calendar=gregorian", 15},
5685 {"en-U-cu-USD", "en@currency=usd", 11},
5686 {"en-US-u-va-posix", "en_US_POSIX", 16},
5687 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", 27},
5688 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", 22},
5689 {"en-us-u-va-posix2", "en_US@va=posix2", 17},
5690 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", 22},
5691 {"ar-x-1-2-3", "ar@x=1-2-3", 10},
5692 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", 19},
5693 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", 30},
5694 {"ja-u-cu-jpy-ca-jp", "ja@currency=jpy", 11},
5695 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", 16},
5696 {"und-a-abc-def", "und@a=abc-def", 13},
5697 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", 30},
5698 {"x-elmer", "@x=elmer", 7},
5699 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", 30},
5700 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer",
5701 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that", 88},
5702 {NULL, NULL, 0}
5703 };
5704
TestForLanguageTag(void)5705 static void TestForLanguageTag(void) {
5706 char locale[256];
5707 int32_t i;
5708 UErrorCode status;
5709 int32_t parsedLen;
5710
5711 for (i = 0; langtag_to_locale[i].bcpID != NULL; i++) {
5712 status = U_ZERO_ERROR;
5713 locale[0] = 0;
5714 uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status);
5715 if (U_FAILURE(status)) {
5716 log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n",
5717 langtag_to_locale[i].bcpID, u_errorName(status));
5718 } else {
5719 if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) {
5720 log_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n",
5721 locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID);
5722 }
5723 if (parsedLen != langtag_to_locale[i].len) {
5724 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n",
5725 parsedLen, langtag_to_locale[i].bcpID, langtag_to_locale[i].len);
5726 }
5727 }
5728 }
5729 }
5730
test_unicode_define(const char * namech,char ch,const char * nameu,UChar uch)5731 static void test_unicode_define(const char *namech, char ch, const char *nameu, UChar uch)
5732 {
5733 UChar asUch[1];
5734 asUch[0]=0;
5735 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech, ch,(int)ch, nameu, (int) uch);
5736 u_charsToUChars(&ch, asUch, 1);
5737 if(asUch[0] != uch) {
5738 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);
5739 } else {
5740 log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]);
5741 }
5742 }
5743
5744 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y))
5745
TestUnicodeDefines(void)5746 static void TestUnicodeDefines(void) {
5747 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE);
5748 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
5749 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
5750 }
5751