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