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