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