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