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