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