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