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