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