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