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