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