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