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 #include <functional>
10 #include <iterator>
11 #include <set>
12 #include <utility>
13
14 #include "loctest.h"
15 #include "unicode/localebuilder.h"
16 #include "unicode/localpointer.h"
17 #include "unicode/decimfmt.h"
18 #include "unicode/ucurr.h"
19 #include "unicode/smpdtfmt.h"
20 #include "unicode/strenum.h"
21 #include "unicode/dtfmtsym.h"
22 #include "unicode/brkiter.h"
23 #include "unicode/coll.h"
24 #include "unicode/ustring.h"
25 #include "unicode/std_string.h"
26 #include "charstr.h"
27 #include "cmemory.h"
28 #include "cstring.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include "putilimp.h"
32 #include "hash.h"
33 #include "locmap.h"
34
35 static const char* const rawData[33][8] = {
36
37 // language code
38 { "en", "fr", "ca", "el", "no", "it", "xx", "zh" },
39 // script code
40 { "", "", "", "", "", "", "", "Hans" },
41 // country code
42 { "US", "FR", "ES", "GR", "NO", "", "YY", "CN" },
43 // variant code
44 { "", "", "", "", "NY", "", "", "" },
45 // full name
46 { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "it", "xx_YY", "zh_Hans_CN" },
47 // ISO-3 language
48 { "eng", "fra", "cat", "ell", "nor", "ita", "", "zho" },
49 // ISO-3 country
50 { "USA", "FRA", "ESP", "GRC", "NOR", "", "", "CHN" },
51 // LCID
52 { "409", "40c", "403", "408", "814", "10", "0", "804" },
53
54 // display language (English)
55 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "Chinese" },
56 // display script (English)
57 { "", "", "", "", "", "", "", "Simplified Han" },
58 // display country (English)
59 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "China" },
60 // display variant (English)
61 { "", "", "", "", "NY", "", "", ""},
62 // display name (English)
63 // Updated no_NO_NY English display name for new pattern-based algorithm
64 // (part of Euro support).
65 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China)" },
66
67 // display language (French)
68 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" },
69 // display script (French)
70 { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" },
71 // display country (French)
72 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine" },
73 // display variant (French)
74 { "", "", "", "", "NY", "", "", "" },
75 // display name (French)
76 //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" },
77 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine)" },
78
79
80 /* display language (Catalan) */
81 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" },
82 /* display script (Catalan) */
83 { "", "", "", "", "", "", "", "han simplificat" },
84 /* display country (Catalan) */
85 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina" },
86 /* display variant (Catalan) */
87 { "", "", "", "", "NY", "", "" },
88 /* display name (Catalan) */
89 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina)" },
90
91 // display language (Greek)[actual values listed below]
92 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
93 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
94 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
95 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
96 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
97 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
98 "",
99 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC"
100 },
101 // display script (Greek)
102 { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" },
103 // display country (Greek)[actual values listed below]
104 { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
105 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
106 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
107 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
108 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
109 "",
110 "",
111 "\\u039A\\u03AF\\u03BD\\u03B1"
112 },
113 // display variant (Greek)
114 { "", "", "", "", "NY", "", "" },
115 // display name (Greek)[actual values listed below]
116 { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)",
117 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
118 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
119 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
120 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
121 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
122 "",
123 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)"
124 },
125
126 // display language (<root>)
127 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "" },
128 // display script (<root>)
129 { "", "", "", "", "", "", "", ""},
130 // display country (<root>)
131 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "" },
132 // display variant (<root>)
133 { "", "", "", "", "Nynorsk", "", "", ""},
134 // display name (<root>)
135 //{ "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
136 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,NY)", "Italian", "xx (YY)", "" }
137 };
138
139
140 /*
141 Usage:
142 test_assert( Test (should be TRUE) )
143
144 Example:
145 test_assert(i==3);
146
147 the macro is ugly but makes the tests pretty.
148 */
149
150 #define test_assert(test) UPRV_BLOCK_MACRO_BEGIN { \
151 if(!(test)) \
152 errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \
153 else \
154 logln("PASS: asserted " #test); \
155 } UPRV_BLOCK_MACRO_END
156
157 /*
158 Usage:
159 test_assert_print( Test (should be TRUE), printable )
160
161 Example:
162 test_assert(i==3, toString(i));
163
164 the macro is ugly but makes the tests pretty.
165 */
166
167 #define test_assert_print(test,print) UPRV_BLOCK_MACRO_BEGIN { \
168 if(!(test)) \
169 errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \
170 else \
171 logln("PASS: asserted " #test "-> " + UnicodeString(print)); \
172 } UPRV_BLOCK_MACRO_END
173
174
175 #define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \
176 logln(#l " = " + UnicodeString(l.getName(), "")); \
177 } UPRV_BLOCK_MACRO_END
178
LocaleTest()179 LocaleTest::LocaleTest()
180 : dataTable(NULL)
181 {
182 setUpDataTable();
183 }
184
~LocaleTest()185 LocaleTest::~LocaleTest()
186 {
187 if (dataTable != 0) {
188 for (int32_t i = 0; i < 33; i++) {
189 delete []dataTable[i];
190 }
191 delete []dataTable;
192 dataTable = 0;
193 }
194 }
195
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)196 void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
197 {
198 TESTCASE_AUTO_BEGIN;
199 TESTCASE_AUTO(TestBug11421); // Must run early in list to trigger failure.
200 TESTCASE_AUTO(TestBasicGetters);
201 TESTCASE_AUTO(TestSimpleResourceInfo);
202 TESTCASE_AUTO(TestDisplayNames);
203 TESTCASE_AUTO(TestSimpleObjectStuff);
204 TESTCASE_AUTO(TestPOSIXParsing);
205 TESTCASE_AUTO(TestGetAvailableLocales);
206 TESTCASE_AUTO(TestDataDirectory);
207 TESTCASE_AUTO(TestISO3Fallback);
208 TESTCASE_AUTO(TestGetLangsAndCountries);
209 TESTCASE_AUTO(TestSimpleDisplayNames);
210 TESTCASE_AUTO(TestUninstalledISO3Names);
211 TESTCASE_AUTO(TestAtypicalLocales);
212 #if !UCONFIG_NO_FORMATTING
213 TESTCASE_AUTO(TestThaiCurrencyFormat);
214 TESTCASE_AUTO(TestEuroSupport);
215 #endif
216 TESTCASE_AUTO(TestToString);
217 #if !UCONFIG_NO_FORMATTING
218 TESTCASE_AUTO(Test4139940);
219 TESTCASE_AUTO(Test4143951);
220 #endif
221 TESTCASE_AUTO(Test4147315);
222 TESTCASE_AUTO(Test4147317);
223 TESTCASE_AUTO(Test4147552);
224 TESTCASE_AUTO(TestVariantParsing);
225 TESTCASE_AUTO(Test20639_DeprecatesISO3Language);
226 #if !UCONFIG_NO_FORMATTING
227 TESTCASE_AUTO(Test4105828);
228 #endif
229 TESTCASE_AUTO(TestSetIsBogus);
230 TESTCASE_AUTO(TestParallelAPIValues);
231 TESTCASE_AUTO(TestAddLikelySubtags);
232 TESTCASE_AUTO(TestMinimizeSubtags);
233 TESTCASE_AUTO(TestAddLikelyAndMinimizeSubtags);
234 TESTCASE_AUTO(TestKeywordVariants);
235 TESTCASE_AUTO(TestCreateUnicodeKeywords);
236 TESTCASE_AUTO(TestKeywordVariantParsing);
237 TESTCASE_AUTO(TestCreateKeywordSet);
238 TESTCASE_AUTO(TestCreateKeywordSetEmpty);
239 TESTCASE_AUTO(TestCreateUnicodeKeywordSet);
240 TESTCASE_AUTO(TestCreateUnicodeKeywordSetEmpty);
241 TESTCASE_AUTO(TestGetKeywordValueStdString);
242 TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString);
243 TESTCASE_AUTO(TestSetKeywordValue);
244 TESTCASE_AUTO(TestSetKeywordValueStringPiece);
245 TESTCASE_AUTO(TestSetUnicodeKeywordValueStringPiece);
246 TESTCASE_AUTO(TestGetBaseName);
247 #if !UCONFIG_NO_FILE_IO
248 TESTCASE_AUTO(TestGetLocale);
249 #endif
250 TESTCASE_AUTO(TestVariantWithOutCountry);
251 TESTCASE_AUTO(TestCanonicalization);
252 TESTCASE_AUTO(TestCurrencyByDate);
253 TESTCASE_AUTO(TestGetVariantWithKeywords);
254 TESTCASE_AUTO(TestIsRightToLeft);
255 TESTCASE_AUTO(TestBug13277);
256 TESTCASE_AUTO(TestBug13554);
257 TESTCASE_AUTO(TestBug20410);
258 TESTCASE_AUTO(TestConstructorAcceptsBCP47);
259 TESTCASE_AUTO(TestForLanguageTag);
260 TESTCASE_AUTO(TestToLanguageTag);
261 TESTCASE_AUTO(TestMoveAssign);
262 TESTCASE_AUTO(TestMoveCtor);
263 TESTCASE_AUTO(TestBug20407iVariantPreferredValue);
264 TESTCASE_AUTO(TestBug13417VeryLongLanguageTag);
265 TESTCASE_AUTO(TestBug11053UnderlineTimeZone);
266 TESTCASE_AUTO(TestUnd);
267 TESTCASE_AUTO(TestUndScript);
268 TESTCASE_AUTO(TestUndRegion);
269 TESTCASE_AUTO(TestUndCAPI);
270 TESTCASE_AUTO(TestRangeIterator);
271 TESTCASE_AUTO(TestPointerConvertingIterator);
272 TESTCASE_AUTO(TestTagConvertingIterator);
273 TESTCASE_AUTO(TestCapturingTagConvertingIterator);
274 TESTCASE_AUTO(TestSetUnicodeKeywordValueInLongLocale);
275 TESTCASE_AUTO(TestSetUnicodeKeywordValueNullInLongLocale);
276 TESTCASE_AUTO_END;
277 }
278
TestBasicGetters()279 void LocaleTest::TestBasicGetters() {
280 UnicodeString temp;
281
282 int32_t i;
283 for (i = 0; i <= MAX_LOCALES; i++) {
284 Locale testLocale("");
285 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
286 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
287 }
288 else {
289 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
290 }
291 logln("Testing " + (UnicodeString)testLocale.getName() + "...");
292
293 if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
294 errln(" Language code mismatch: " + temp + " versus "
295 + dataTable[LANG][i]);
296 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
297 errln(" Script code mismatch: " + temp + " versus "
298 + dataTable[SCRIPT][i]);
299 if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
300 errln(" Country code mismatch: " + temp + " versus "
301 + dataTable[CTRY][i]);
302 if ( (temp=testLocale.getVariant()) != (dataTable[VAR][i]))
303 errln(" Variant code mismatch: " + temp + " versus "
304 + dataTable[VAR][i]);
305 if ( (temp=testLocale.getName()) != (dataTable[NAME][i]))
306 errln(" Locale name mismatch: " + temp + " versus "
307 + dataTable[NAME][i]);
308 }
309
310 logln("Same thing without variant codes...");
311 for (i = 0; i <= MAX_LOCALES; i++) {
312 Locale testLocale("");
313 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
314 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i]);
315 }
316 else {
317 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i]);
318 }
319 logln("Testing " + (temp=testLocale.getName()) + "...");
320
321 if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
322 errln("Language code mismatch: " + temp + " versus "
323 + dataTable[LANG][i]);
324 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
325 errln("Script code mismatch: " + temp + " versus "
326 + dataTable[SCRIPT][i]);
327 if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
328 errln("Country code mismatch: " + temp + " versus "
329 + dataTable[CTRY][i]);
330 if (testLocale.getVariant()[0] != 0)
331 errln("Variant code mismatch: something versus \"\"");
332 }
333
334 logln("Testing long language names and getters");
335 Locale test8 = Locale::createFromName("x-klingon-latn-zx.utf32be@special");
336
337 temp = test8.getLanguage();
338 if (temp != UnicodeString("x-klingon") )
339 errln("Language code mismatch: " + temp + " versus \"x-klingon\"");
340
341 temp = test8.getScript();
342 if (temp != UnicodeString("Latn") )
343 errln("Script code mismatch: " + temp + " versus \"Latn\"");
344
345 temp = test8.getCountry();
346 if (temp != UnicodeString("ZX") )
347 errln("Country code mismatch: " + temp + " versus \"ZX\"");
348
349 temp = test8.getVariant();
350 //if (temp != UnicodeString("SPECIAL") )
351 // errln("Variant code mismatch: " + temp + " versus \"SPECIAL\"");
352 // As of 3.0, the "@special" will *not* be parsed by uloc_getName()
353 if (temp != UnicodeString("") )
354 errln("Variant code mismatch: " + temp + " versus \"\"");
355
356 if (Locale::getDefault() != Locale::createFromName(NULL))
357 errln("Locale::getDefault() == Locale::createFromName(NULL)");
358
359 /*----------*/
360 // NOTE: There used to be a special test for locale names that had language or
361 // country codes that were longer than two letters. The new version of Locale
362 // doesn't support anything that isn't an officially recognized language or
363 // country code, so we no longer support this feature.
364
365 Locale bogusLang("THISISABOGUSLANGUAGE"); // Jitterbug 2864: language code too long
366 if(!bogusLang.isBogus()) {
367 errln("Locale(\"THISISABOGUSLANGUAGE\").isBogus()==FALSE");
368 }
369
370 bogusLang=Locale("eo");
371 if( bogusLang.isBogus() ||
372 strcmp(bogusLang.getLanguage(), "eo")!=0 ||
373 *bogusLang.getCountry()!=0 ||
374 *bogusLang.getVariant()!=0 ||
375 strcmp(bogusLang.getName(), "eo")!=0
376 ) {
377 errln("assignment to bogus Locale does not unbogus it or sets bad data");
378 }
379
380 Locale a("eo_DE@currency=DEM");
381 Locale *pb=a.clone();
382 if(pb==&a || *pb!=a) {
383 errln("Locale.clone() failed");
384 }
385 delete pb;
386 }
387
TestParallelAPIValues()388 void LocaleTest::TestParallelAPIValues() {
389 logln("Test synchronization between C and C++ API");
390 if (strcmp(Locale::getChinese().getName(), ULOC_CHINESE) != 0) {
391 errln("Differences for ULOC_CHINESE Locale");
392 }
393 if (strcmp(Locale::getEnglish().getName(), ULOC_ENGLISH) != 0) {
394 errln("Differences for ULOC_ENGLISH Locale");
395 }
396 if (strcmp(Locale::getFrench().getName(), ULOC_FRENCH) != 0) {
397 errln("Differences for ULOC_FRENCH Locale");
398 }
399 if (strcmp(Locale::getGerman().getName(), ULOC_GERMAN) != 0) {
400 errln("Differences for ULOC_GERMAN Locale");
401 }
402 if (strcmp(Locale::getItalian().getName(), ULOC_ITALIAN) != 0) {
403 errln("Differences for ULOC_ITALIAN Locale");
404 }
405 if (strcmp(Locale::getJapanese().getName(), ULOC_JAPANESE) != 0) {
406 errln("Differences for ULOC_JAPANESE Locale");
407 }
408 if (strcmp(Locale::getKorean().getName(), ULOC_KOREAN) != 0) {
409 errln("Differences for ULOC_KOREAN Locale");
410 }
411 if (strcmp(Locale::getSimplifiedChinese().getName(), ULOC_SIMPLIFIED_CHINESE) != 0) {
412 errln("Differences for ULOC_SIMPLIFIED_CHINESE Locale");
413 }
414 if (strcmp(Locale::getTraditionalChinese().getName(), ULOC_TRADITIONAL_CHINESE) != 0) {
415 errln("Differences for ULOC_TRADITIONAL_CHINESE Locale");
416 }
417
418
419 if (strcmp(Locale::getCanada().getName(), ULOC_CANADA) != 0) {
420 errln("Differences for ULOC_CANADA Locale");
421 }
422 if (strcmp(Locale::getCanadaFrench().getName(), ULOC_CANADA_FRENCH) != 0) {
423 errln("Differences for ULOC_CANADA_FRENCH Locale");
424 }
425 if (strcmp(Locale::getChina().getName(), ULOC_CHINA) != 0) {
426 errln("Differences for ULOC_CHINA Locale");
427 }
428 if (strcmp(Locale::getPRC().getName(), ULOC_PRC) != 0) {
429 errln("Differences for ULOC_PRC Locale");
430 }
431 if (strcmp(Locale::getFrance().getName(), ULOC_FRANCE) != 0) {
432 errln("Differences for ULOC_FRANCE Locale");
433 }
434 if (strcmp(Locale::getGermany().getName(), ULOC_GERMANY) != 0) {
435 errln("Differences for ULOC_GERMANY Locale");
436 }
437 if (strcmp(Locale::getItaly().getName(), ULOC_ITALY) != 0) {
438 errln("Differences for ULOC_ITALY Locale");
439 }
440 if (strcmp(Locale::getJapan().getName(), ULOC_JAPAN) != 0) {
441 errln("Differences for ULOC_JAPAN Locale");
442 }
443 if (strcmp(Locale::getKorea().getName(), ULOC_KOREA) != 0) {
444 errln("Differences for ULOC_KOREA Locale");
445 }
446 if (strcmp(Locale::getTaiwan().getName(), ULOC_TAIWAN) != 0) {
447 errln("Differences for ULOC_TAIWAN Locale");
448 }
449 if (strcmp(Locale::getUK().getName(), ULOC_UK) != 0) {
450 errln("Differences for ULOC_UK Locale");
451 }
452 if (strcmp(Locale::getUS().getName(), ULOC_US) != 0) {
453 errln("Differences for ULOC_US Locale");
454 }
455 }
456
457
TestSimpleResourceInfo()458 void LocaleTest::TestSimpleResourceInfo() {
459 UnicodeString temp;
460 char temp2[20];
461 UErrorCode err = U_ZERO_ERROR;
462 int32_t i = 0;
463
464 for (i = 0; i <= MAX_LOCALES; i++) {
465 Locale testLocale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
466 logln("Testing " + (temp=testLocale.getName()) + "...");
467
468 if ( (temp=testLocale.getISO3Language()) != (dataTable[LANG3][i]))
469 errln(" ISO-3 language code mismatch: " + temp
470 + " versus " + dataTable[LANG3][i]);
471 if ( (temp=testLocale.getISO3Country()) != (dataTable[CTRY3][i]))
472 errln(" ISO-3 country code mismatch: " + temp
473 + " versus " + dataTable[CTRY3][i]);
474
475 sprintf(temp2, "%x", (int)testLocale.getLCID());
476 if (UnicodeString(temp2) != dataTable[LCID][i])
477 errln((UnicodeString)" LCID mismatch: " + temp2 + " versus "
478 + dataTable[LCID][i]);
479
480 if(U_FAILURE(err))
481 {
482 errln((UnicodeString)"Some error on number " + i + u_errorName(err));
483 }
484 err = U_ZERO_ERROR;
485 }
486
487 Locale locale("en");
488 if(strcmp(locale.getName(), "en") != 0||
489 strcmp(locale.getLanguage(), "en") != 0) {
490 errln("construction of Locale(en) failed\n");
491 }
492 /*-----*/
493
494 }
495
496 /*
497 * Jitterbug 2439 -- markus 20030425
498 *
499 * The lookup of display names must not fall back through the default
500 * locale because that yields useless results.
501 */
502 void
TestDisplayNames()503 LocaleTest::TestDisplayNames()
504 {
505 Locale english("en", "US");
506 Locale french("fr", "FR");
507 Locale croatian("ca", "ES");
508 Locale greek("el", "GR");
509
510 logln(" In locale = en_US...");
511 doTestDisplayNames(english, DLANG_EN);
512 logln(" In locale = fr_FR...");
513 doTestDisplayNames(french, DLANG_FR);
514 logln(" In locale = ca_ES...");
515 doTestDisplayNames(croatian, DLANG_CA);
516 logln(" In locale = el_GR...");
517 doTestDisplayNames(greek, DLANG_EL);
518
519 UnicodeString s;
520 UErrorCode status = U_ZERO_ERROR;
521
522 #if !UCONFIG_NO_FORMATTING
523 DecimalFormatSymbols symb(status);
524 /* Check to see if ICU supports this locale */
525 if (symb.getLocale(ULOC_VALID_LOCALE, status) != Locale("root")) {
526 /* test that the default locale has a display name for its own language */
527 /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */
528 if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) {
529 Locale().getDisplayLanguage(Locale(), s);
530 if(s.length()<=3 && s.charAt(0)<=0x7f) {
531 /* check <=3 to reject getting the language code as a display name */
532 dataerrln("unable to get a display string for the language of the default locale: " + s);
533 }
534
535 /*
536 * API coverage improvements: call
537 * Locale::getDisplayLanguage(UnicodeString &) and
538 * Locale::getDisplayCountry(UnicodeString &)
539 */
540 s.remove();
541 Locale().getDisplayLanguage(s);
542 if(s.length()<=3 && s.charAt(0)<=0x7f) {
543 dataerrln("unable to get a display string for the language of the default locale [2]: " + s);
544 }
545 }
546 }
547 else {
548 logln("Default locale %s is unsupported by ICU\n", Locale().getName());
549 }
550 s.remove();
551 #endif
552
553 french.getDisplayCountry(s);
554 if(s.isEmpty()) {
555 errln("unable to get any default-locale display string for the country of fr_FR\n");
556 }
557 s.remove();
558 Locale("zh", "Hant").getDisplayScript(s);
559 if(s.isEmpty()) {
560 errln("unable to get any default-locale display string for the country of zh_Hant\n");
561 }
562 }
563
TestSimpleObjectStuff()564 void LocaleTest::TestSimpleObjectStuff() {
565 Locale test1("aa", "AA");
566 Locale test2("aa", "AA");
567 Locale test3(test1);
568 Locale test4("zz", "ZZ");
569 Locale test5("aa", "AA", "");
570 Locale test6("aa", "AA", "ANTARES");
571 Locale test7("aa", "AA", "JUPITER");
572 Locale test8 = Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that
573
574 // now list them all for debugging usage.
575 test_dumpLocale(test1);
576 test_dumpLocale(test2);
577 test_dumpLocale(test3);
578 test_dumpLocale(test4);
579 test_dumpLocale(test5);
580 test_dumpLocale(test6);
581 test_dumpLocale(test7);
582 test_dumpLocale(test8);
583
584 // Make sure things compare to themselves!
585 test_assert(test1 == test1);
586 test_assert(test2 == test2);
587 test_assert(test3 == test3);
588 test_assert(test4 == test4);
589 test_assert(test5 == test5);
590 test_assert(test6 == test6);
591 test_assert(test7 == test7);
592 test_assert(test8 == test8);
593
594 // make sure things are not equal to themselves.
595 test_assert(!(test1 != test1));
596 test_assert(!(test2 != test2));
597 test_assert(!(test3 != test3));
598 test_assert(!(test4 != test4));
599 test_assert(!(test5 != test5));
600 test_assert(!(test6 != test6));
601 test_assert(!(test7 != test7));
602 test_assert(!(test8 != test8));
603
604 // make sure things that are equal to each other don't show up as unequal.
605 test_assert(!(test1 != test2));
606 test_assert(!(test2 != test1));
607 test_assert(!(test1 != test3));
608 test_assert(!(test2 != test3));
609 test_assert(test5 == test1);
610 test_assert(test6 != test2);
611 test_assert(test6 != test5);
612
613 test_assert(test6 != test7);
614
615 // test for things that shouldn't compare equal.
616 test_assert(!(test1 == test4));
617 test_assert(!(test2 == test4));
618 test_assert(!(test3 == test4));
619
620 test_assert(test7 == test8);
621
622 // test for hash codes to be the same.
623 int32_t hash1 = test1.hashCode();
624 int32_t hash2 = test2.hashCode();
625 int32_t hash3 = test3.hashCode();
626
627 test_assert(hash1 == hash2);
628 test_assert(hash1 == hash3);
629 test_assert(hash2 == hash3);
630
631 // test that the assignment operator works.
632 test4 = test1;
633 logln("test4=test1;");
634 test_dumpLocale(test4);
635 test_assert(test4 == test4);
636
637 test_assert(!(test1 != test4));
638 test_assert(!(test2 != test4));
639 test_assert(!(test3 != test4));
640 test_assert(test1 == test4);
641 test_assert(test4 == test1);
642
643 // test assignments with a variant
644 logln("test7 = test6");
645 test7 = test6;
646 test_dumpLocale(test7);
647 test_assert(test7 == test7);
648 test_assert(test7 == test6);
649 test_assert(test7 != test5);
650
651 logln("test6 = test1");
652 test6=test1;
653 test_dumpLocale(test6);
654 test_assert(test6 != test7);
655 test_assert(test6 == test1);
656 test_assert(test6 == test6);
657 }
658
659 // A class which exposes constructors that are implemented in terms of the POSIX parsing code.
660 class POSIXLocale : public Locale
661 {
662 public:
POSIXLocale(const UnicodeString & l)663 POSIXLocale(const UnicodeString& l)
664 :Locale()
665 {
666 char *ch;
667 ch = new char[l.length() + 1];
668 ch[l.extract(0, 0x7fffffff, ch, "")] = 0;
669 setFromPOSIXID(ch);
670 delete [] ch;
671 }
POSIXLocale(const char * l)672 POSIXLocale(const char *l)
673 :Locale()
674 {
675 setFromPOSIXID(l);
676 }
677 };
678
TestPOSIXParsing()679 void LocaleTest::TestPOSIXParsing()
680 {
681 POSIXLocale test1("ab_AB");
682 POSIXLocale test2(UnicodeString("ab_AB"));
683 Locale test3("ab","AB");
684
685 POSIXLocale test4("ab_AB_Antares");
686 POSIXLocale test5(UnicodeString("ab_AB_Antares"));
687 Locale test6("ab", "AB", "Antares");
688
689 test_dumpLocale(test1);
690 test_dumpLocale(test2);
691 test_dumpLocale(test3);
692 test_dumpLocale(test4);
693 test_dumpLocale(test5);
694 test_dumpLocale(test6);
695
696 test_assert(test1 == test1);
697
698 test_assert(test1 == test2);
699 test_assert(test2 == test3);
700 test_assert(test3 == test1);
701
702 test_assert(test4 == test5);
703 test_assert(test5 == test6);
704 test_assert(test6 == test4);
705
706 test_assert(test1 != test4);
707 test_assert(test5 != test3);
708 test_assert(test5 != test2);
709
710 int32_t hash1 = test1.hashCode();
711 int32_t hash2 = test2.hashCode();
712 int32_t hash3 = test3.hashCode();
713
714 test_assert(hash1 == hash2);
715 test_assert(hash2 == hash3);
716 test_assert(hash3 == hash1);
717 }
718
TestGetAvailableLocales()719 void LocaleTest::TestGetAvailableLocales()
720 {
721 int32_t locCount = 0;
722 const Locale* locList = Locale::getAvailableLocales(locCount);
723
724 if (locCount == 0)
725 dataerrln("getAvailableLocales() returned an empty list!");
726 else {
727 logln(UnicodeString("Number of locales returned = ") + locCount);
728 UnicodeString temp;
729 for(int32_t i = 0; i < locCount; ++i)
730 logln(locList[i].getName());
731 }
732 // I have no idea how to test this function...
733 }
734
735 // This test isn't applicable anymore - getISO3Language is
736 // independent of the data directory
TestDataDirectory()737 void LocaleTest::TestDataDirectory()
738 {
739 /*
740 char oldDirectory[80];
741 const char* temp;
742 UErrorCode err = U_ZERO_ERROR;
743 UnicodeString testValue;
744
745 temp = Locale::getDataDirectory();
746 strcpy(oldDirectory, temp);
747 logln(UnicodeString("oldDirectory = ") + oldDirectory);
748
749 Locale test(Locale::US);
750 test.getISO3Language(testValue);
751 logln("first fetch of language retrieved " + testValue);
752 if (testValue != "eng")
753 errln("Initial check of ISO3 language failed: expected \"eng\", got \"" + testValue + "\"");
754
755 {
756 char *path;
757 path=IntlTest::getTestDirectory();
758 Locale::setDataDirectory( path );
759 }
760
761 test.getISO3Language(testValue);
762 logln("second fetch of language retrieved " + testValue);
763 if (testValue != "xxx")
764 errln("setDataDirectory() failed: expected \"xxx\", got \"" + testValue + "\"");
765
766 Locale::setDataDirectory(oldDirectory);
767 test.getISO3Language(testValue);
768 logln("third fetch of language retrieved " + testValue);
769 if (testValue != "eng")
770 errln("get/setDataDirectory() failed: expected \"eng\", got \"" + testValue + "\"");
771 */
772 }
773
774 //===========================================================
775
doTestDisplayNames(Locale & displayLocale,int32_t compareIndex)776 void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) {
777 UnicodeString temp;
778
779 for (int32_t i = 0; i <= MAX_LOCALES; i++) {
780 Locale testLocale("");
781 if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) {
782 testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]);
783 }
784 else {
785 testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]);
786 }
787 logln(" Testing " + (temp=testLocale.getName()) + "...");
788
789 UnicodeString testLang;
790 UnicodeString testScript;
791 UnicodeString testCtry;
792 UnicodeString testVar;
793 UnicodeString testName;
794
795 testLocale.getDisplayLanguage(displayLocale, testLang);
796 testLocale.getDisplayScript(displayLocale, testScript);
797 testLocale.getDisplayCountry(displayLocale, testCtry);
798 testLocale.getDisplayVariant(displayLocale, testVar);
799 testLocale.getDisplayName(displayLocale, testName);
800
801 UnicodeString expectedLang;
802 UnicodeString expectedScript;
803 UnicodeString expectedCtry;
804 UnicodeString expectedVar;
805 UnicodeString expectedName;
806
807 expectedLang = dataTable[compareIndex][i];
808 if (expectedLang.length() == 0)
809 expectedLang = dataTable[DLANG_EN][i];
810
811 expectedScript = dataTable[compareIndex + 1][i];
812 if (expectedScript.length() == 0)
813 expectedScript = dataTable[DSCRIPT_EN][i];
814
815 expectedCtry = dataTable[compareIndex + 2][i];
816 if (expectedCtry.length() == 0)
817 expectedCtry = dataTable[DCTRY_EN][i];
818
819 expectedVar = dataTable[compareIndex + 3][i];
820 if (expectedVar.length() == 0)
821 expectedVar = dataTable[DVAR_EN][i];
822
823 expectedName = dataTable[compareIndex + 4][i];
824 if (expectedName.length() == 0)
825 expectedName = dataTable[DNAME_EN][i];
826
827 if (testLang != expectedLang)
828 dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang);
829 if (testScript != expectedScript)
830 dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript);
831 if (testCtry != expectedCtry)
832 dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry);
833 if (testVar != expectedVar)
834 dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar);
835 if (testName != expectedName)
836 dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName);
837 }
838 }
839
840 //---------------------------------------------------
841 // table of valid data
842 //---------------------------------------------------
843
844
845
setUpDataTable()846 void LocaleTest::setUpDataTable()
847 {
848 if (dataTable == 0) {
849 dataTable = new UnicodeString*[33];
850
851 for (int32_t i = 0; i < 33; i++) {
852 dataTable[i] = new UnicodeString[8];
853 for (int32_t j = 0; j < 8; j++) {
854 dataTable[i][j] = CharsToUnicodeString(rawData[i][j]);
855 }
856 }
857 }
858 }
859
860 // ====================
861
862
863 /**
864 * @bug 4011756 4011380
865 */
866 void
TestISO3Fallback()867 LocaleTest::TestISO3Fallback()
868 {
869 Locale test("xx", "YY");
870
871 const char * result;
872
873 result = test.getISO3Language();
874
875 // Conform to C API usage
876
877 if (!result || (result[0] != 0))
878 errln("getISO3Language() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
879
880 result = test.getISO3Country();
881
882 if (!result || (result[0] != 0))
883 errln("getISO3Country() on xx_YY returned " + UnicodeString(result) + " instead of \"\"");
884 }
885
886 /**
887 * @bug 4106155 4118587
888 */
889 void
TestGetLangsAndCountries()890 LocaleTest::TestGetLangsAndCountries()
891 {
892 // It didn't seem right to just do an exhaustive test of everything here, so I check
893 // for the following things:
894 // 1) Does each list have the right total number of entries?
895 // 2) Does each list contain certain language and country codes we think are important
896 // (the G7 countries, plus a couple others)?
897 // 3) Does each list have every entry formatted correctly? (i.e., two characters,
898 // all lower case for the language codes, all upper case for the country codes)
899 // 4) Is each list in sorted order?
900 int32_t testCount = 0;
901 const char * const * test = Locale::getISOLanguages();
902 const char spotCheck1[ ][4] = { "en", "es", "fr", "de", "it",
903 "ja", "ko", "zh", "th", "he",
904 "id", "iu", "ug", "yi", "za" };
905
906 int32_t i;
907
908 for(testCount = 0;test[testCount];testCount++)
909 ;
910
911 /* TODO: Change this test to be more like the cloctst version? */
912 if (testCount != 596)
913 errln("Expected getISOLanguages() to return 596 languages; it returned %d", testCount);
914 else {
915 for (i = 0; i < 15; i++) {
916 int32_t j;
917 for (j = 0; j < testCount; j++)
918 if (uprv_strcmp(test[j],spotCheck1[i])== 0)
919 break;
920 if (j == testCount || (uprv_strcmp(test[j],spotCheck1[i])!=0))
921 errln("Couldn't find " + (UnicodeString)spotCheck1[i] + " in language list.");
922 }
923 }
924 for (i = 0; i < testCount; i++) {
925 UnicodeString testee(test[i],"");
926 UnicodeString lc(test[i],"");
927 if (testee != lc.toLower())
928 errln(lc + " is not all lower case.");
929 if ( (testee.length() != 2) && (testee.length() != 3))
930 errln(testee + " is not two or three characters long.");
931 if (i > 0 && testee.compare(test[i - 1]) <= 0)
932 errln(testee + " appears in an out-of-order position in the list.");
933 }
934
935 test = Locale::getISOCountries();
936 UnicodeString spotCheck2 [] = { "US", "CA", "GB", "FR", "DE",
937 "IT", "JP", "KR", "CN", "TW",
938 "TH" };
939 int32_t spot2Len = 11;
940 for(testCount=0;test[testCount];testCount++)
941 ;
942
943 if (testCount != 249){
944 errln("Expected getISOCountries to return 249 countries; it returned %d", testCount);
945 }else {
946 for (i = 0; i < spot2Len; i++) {
947 int32_t j;
948 for (j = 0; j < testCount; j++)
949 {
950 UnicodeString testee(test[j],"");
951
952 if (testee == spotCheck2[i])
953 break;
954 }
955 UnicodeString testee(test[j],"");
956 if (j == testCount || testee != spotCheck2[i])
957 errln("Couldn't find " + spotCheck2[i] + " in country list.");
958 }
959 }
960 for (i = 0; i < testCount; i++) {
961 UnicodeString testee(test[i],"");
962 UnicodeString uc(test[i],"");
963 if (testee != uc.toUpper())
964 errln(testee + " is not all upper case.");
965 if (testee.length() != 2)
966 errln(testee + " is not two characters long.");
967 if (i > 0 && testee.compare(test[i - 1]) <= 0)
968 errln(testee + " appears in an out-of-order position in the list.");
969 }
970
971 // This getAvailableLocales and getISO3Language
972 {
973 int32_t numOfLocales;
974 Locale enLoc ("en");
975 const Locale *pLocales = Locale::getAvailableLocales(numOfLocales);
976
977 for (int i = 0; i < numOfLocales; i++) {
978 const Locale &loc(pLocales[i]);
979 UnicodeString name;
980 char szName[200];
981
982 loc.getDisplayName (enLoc, name);
983 name.extract (0, 200, szName, sizeof(szName));
984
985 if (strlen(loc.getISO3Language()) == 0) {
986 errln("getISO3Language() returned an empty string for: " + name);
987 }
988 }
989 }
990 }
991
992 /**
993 * @bug 4118587
994 */
995 void
TestSimpleDisplayNames()996 LocaleTest::TestSimpleDisplayNames()
997 {
998 // This test is different from TestDisplayNames because TestDisplayNames checks
999 // fallback behavior, combination of language and country names to form locale
1000 // names, and other stuff like that. This test just checks specific language
1001 // and country codes to make sure we have the correct names for them.
1002 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" };
1003 UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
1004 "Zhuang" };
1005
1006 for (int32_t i = 0; i < 6; i++) {
1007 UnicodeString test;
1008 Locale l(languageCodes[i], "", "");
1009 l.getDisplayLanguage(Locale::getUS(), test);
1010 if (test != languageNames[i])
1011 dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" +
1012 languageNames[i] + "\", got \"" + test + "\".");
1013 }
1014 }
1015
1016 /**
1017 * @bug 4118595
1018 */
1019 void
TestUninstalledISO3Names()1020 LocaleTest::TestUninstalledISO3Names()
1021 {
1022 // This test checks to make sure getISO3Language and getISO3Country work right
1023 // even for locales that are not installed.
1024 const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
1025 "ss", "tw", "zu" };
1026 const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
1027 "ssw", "twi", "zul" };
1028
1029 int32_t i;
1030
1031 for (i = 0; i < 8; i++) {
1032 UErrorCode err = U_ZERO_ERROR;
1033
1034 UnicodeString test;
1035 Locale l(iso2Languages[i], "", "");
1036 test = l.getISO3Language();
1037 if((test != iso3Languages[i]) || U_FAILURE(err))
1038 errln("Got wrong ISO3 code for " + UnicodeString(iso2Languages[i]) + ": Expected \"" +
1039 iso3Languages[i] + "\", got \"" + test + "\"." + UnicodeString(u_errorName(err)));
1040 }
1041
1042 char iso2Countries [][4] = { "AF", "BW", "KZ", "MO", "MN",
1043 "SB", "TC", "ZW" };
1044 char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
1045 "SLB", "TCA", "ZWE" };
1046
1047 for (i = 0; i < 8; i++) {
1048 UErrorCode err = U_ZERO_ERROR;
1049 Locale l("", iso2Countries[i], "");
1050 UnicodeString test(l.getISO3Country(), "");
1051 if (test != iso3Countries[i])
1052 errln("Got wrong ISO3 code for " + UnicodeString(iso2Countries[i]) + ": Expected \"" +
1053 UnicodeString(iso3Countries[i]) + "\", got \"" + test + "\"." + u_errorName(err));
1054 }
1055 }
1056
1057 /**
1058 * @bug 4092475
1059 * I could not reproduce this bug. I'm pretty convinced it was fixed with the
1060 * big locale-data reorg of 10/28/97. The lookup logic for language and country
1061 * display names was also changed at that time in that check-in. --rtg 3/20/98
1062 */
1063 void
TestAtypicalLocales()1064 LocaleTest::TestAtypicalLocales()
1065 {
1066 Locale localesToTest [] = { Locale("de", "CA"),
1067 Locale("ja", "ZA"),
1068 Locale("ru", "MX"),
1069 Locale("en", "FR"),
1070 Locale("es", "DE"),
1071 Locale("", "HR"),
1072 Locale("", "SE"),
1073 Locale("", "DO"),
1074 Locale("", "BE") };
1075
1076 UnicodeString englishDisplayNames [] = { "German (Canada)",
1077 "Japanese (South Africa)",
1078 "Russian (Mexico)",
1079 "English (France)",
1080 "Spanish (Germany)",
1081 "Unknown language (Croatia)",
1082 "Unknown language (Sweden)",
1083 "Unknown language (Dominican Republic)",
1084 "Unknown language (Belgium)" };
1085 UnicodeString frenchDisplayNames []= { "allemand (Canada)",
1086 "japonais (Afrique du Sud)",
1087 "russe (Mexique)",
1088 "anglais (France)",
1089 "espagnol (Allemagne)",
1090 u"langue indéterminée (Croatie)",
1091 u"langue indéterminée (Suède)",
1092 u"langue indéterminée (République dominicaine)",
1093 u"langue indéterminée (Belgique)" };
1094 UnicodeString spanishDisplayNames [] = {
1095 u"alemán (Canadá)",
1096 u"japonés (Sudáfrica)",
1097 u"ruso (México)",
1098 u"inglés (Francia)",
1099 u"español (Alemania)",
1100 "lengua desconocida (Croacia)",
1101 "lengua desconocida (Suecia)",
1102 u"lengua desconocida (República Dominicana)",
1103 u"lengua desconocida (Bélgica)" };
1104 // De-Anglicizing root required the change from
1105 // English display names to ISO Codes - ram 2003/09/26
1106 UnicodeString invDisplayNames [] = { "German (Canada)",
1107 "Japanese (South Africa)",
1108 "Russian (Mexico)",
1109 "English (France)",
1110 "Spanish (Germany)",
1111 "Unknown language (Croatia)",
1112 "Unknown language (Sweden)",
1113 "Unknown language (Dominican Republic)",
1114 "Unknown language (Belgium)" };
1115
1116 int32_t i;
1117 UErrorCode status = U_ZERO_ERROR;
1118 Locale saveLocale;
1119 Locale::setDefault(Locale::getUS(), status);
1120 for (i = 0; i < 9; ++i) {
1121 UnicodeString name;
1122 localesToTest[i].getDisplayName(Locale::getUS(), name);
1123 logln(name);
1124 if (name != englishDisplayNames[i])
1125 {
1126 dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i]
1127 + "\", got \"" + name + "\"");
1128 logln("Locale name was-> " + (name=localesToTest[i].getName()));
1129 }
1130 }
1131
1132 for (i = 0; i < 9; i++) {
1133 UnicodeString name;
1134 localesToTest[i].getDisplayName(Locale("es", "ES"), name);
1135 logln(name);
1136 if (name != spanishDisplayNames[i])
1137 dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
1138 + "\", got \"" + name + "\"");
1139 }
1140
1141 for (i = 0; i < 9; i++) {
1142 UnicodeString name;
1143 localesToTest[i].getDisplayName(Locale::getFrance(), name);
1144 logln(name);
1145 if (name != frenchDisplayNames[i])
1146 dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
1147 + "\", got \"" + name + "\"");
1148 }
1149
1150 for (i = 0; i < 9; i++) {
1151 UnicodeString name;
1152 localesToTest[i].getDisplayName(Locale("inv", "IN"), name);
1153 logln(name + " Locale fallback to be, and data fallback to root");
1154 if (name != invDisplayNames[i])
1155 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
1156 + "\", got \"" + prettify(name) + "\"");
1157 localesToTest[i].getDisplayName(Locale("inv", "BD"), name);
1158 logln(name + " Data fallback to root");
1159 if (name != invDisplayNames[i])
1160 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
1161 + "\", got \"" + prettify(name )+ "\"");
1162 }
1163 Locale::setDefault(saveLocale, status);
1164 }
1165
1166 #if !UCONFIG_NO_FORMATTING
1167
1168 /**
1169 * @bug 4135752
1170 * This would be better tested by the LocaleDataTest. Will move it when I
1171 * get the LocaleDataTest working again.
1172 */
1173 void
TestThaiCurrencyFormat()1174 LocaleTest::TestThaiCurrencyFormat()
1175 {
1176 UErrorCode status = U_ZERO_ERROR;
1177 DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance(
1178 Locale("th", "TH"), status);
1179 UnicodeString posPrefix(u"\u0E3F");
1180 UnicodeString temp;
1181
1182 if(U_FAILURE(status) || !thaiCurrency)
1183 {
1184 dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status)));
1185 return;
1186 }
1187 if (thaiCurrency->getPositivePrefix(temp) != posPrefix)
1188 errln("Thai currency prefix wrong: expected Baht sign, got \"" +
1189 thaiCurrency->getPositivePrefix(temp) + "\"");
1190 if (thaiCurrency->getPositiveSuffix(temp) != "")
1191 errln("Thai currency suffix wrong: expected \"\", got \"" +
1192 thaiCurrency->getPositiveSuffix(temp) + "\"");
1193
1194 delete thaiCurrency;
1195 }
1196
1197 /**
1198 * @bug 4122371
1199 * Confirm that Euro support works. This test is pretty rudimentary; all it does
1200 * is check that any locales with the EURO variant format a number using the
1201 * Euro currency symbol.
1202 *
1203 * ASSUME: All locales encode the Euro character "\u20AC".
1204 * If this is changed to use the single-character Euro symbol, this
1205 * test must be updated.
1206 *
1207 */
1208 void
TestEuroSupport()1209 LocaleTest::TestEuroSupport()
1210 {
1211 UChar euro = 0x20ac;
1212 const UnicodeString EURO_CURRENCY(&euro, 1, 1); // Look for this UnicodeString in formatted Euro currency
1213 const char* localeArr[] = {
1214 "ca_ES",
1215 "de_AT",
1216 "de_DE",
1217 "de_LU",
1218 "el_GR",
1219 "en_BE",
1220 "en_IE",
1221 "en_GB@currency=EUR",
1222 "en_US@currency=EUR",
1223 "es_ES",
1224 "eu_ES",
1225 "fi_FI",
1226 "fr_BE",
1227 "fr_FR",
1228 "fr_LU",
1229 "ga_IE",
1230 "gl_ES",
1231 "it_IT",
1232 "nl_BE",
1233 "nl_NL",
1234 "pt_PT",
1235 NULL
1236 };
1237 const char** locales = localeArr;
1238
1239 UErrorCode status = U_ZERO_ERROR;
1240
1241 UnicodeString temp;
1242
1243 for (;*locales!=NULL;locales++) {
1244 Locale loc (*locales);
1245 UnicodeString temp;
1246 NumberFormat *nf = NumberFormat::createCurrencyInstance(loc, status);
1247 UnicodeString pos;
1248
1249 if (U_FAILURE(status)) {
1250 dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales);
1251 continue;
1252 }
1253
1254 nf->format(271828.182845, pos);
1255 UnicodeString neg;
1256 nf->format(-271828.182845, neg);
1257 if (pos.indexOf(EURO_CURRENCY) >= 0 &&
1258 neg.indexOf(EURO_CURRENCY) >= 0) {
1259 logln("Ok: " + (temp=loc.getName()) +
1260 ": " + pos + " / " + neg);
1261 }
1262 else {
1263 errln("Fail: " + (temp=loc.getName()) +
1264 " formats without " + EURO_CURRENCY +
1265 ": " + pos + " / " + neg +
1266 "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
1267 }
1268
1269 delete nf;
1270 }
1271
1272 UnicodeString dollarStr("USD", ""), euroStr("EUR", ""), genericStr((UChar)0x00a4), resultStr;
1273 UChar tmp[4];
1274 status = U_ZERO_ERROR;
1275
1276 ucurr_forLocale("en_US", tmp, 4, &status);
1277 resultStr.setTo(tmp);
1278 if (dollarStr != resultStr) {
1279 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
1280 }
1281 ucurr_forLocale("en_US@currency=EUR", tmp, 4, &status);
1282 resultStr.setTo(tmp);
1283 if (euroStr != resultStr) {
1284 errcheckln(status, "Fail: en_US@currency=EUR didn't return EUR - %s", u_errorName(status));
1285 }
1286 ucurr_forLocale("en_GB@currency=EUR", tmp, 4, &status);
1287 resultStr.setTo(tmp);
1288 if (euroStr != resultStr) {
1289 errcheckln(status, "Fail: en_GB@currency=EUR didn't return EUR - %s", u_errorName(status));
1290 }
1291 ucurr_forLocale("en_US_Q", tmp, 4, &status);
1292 resultStr.setTo(tmp);
1293 if (dollarStr != resultStr) {
1294 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
1295 }
1296 int32_t invalidLen = ucurr_forLocale("en_QQ", tmp, 4, &status);
1297 if (invalidLen || U_SUCCESS(status)) {
1298 errln("Fail: en_QQ didn't return NULL");
1299 }
1300
1301 // The currency keyword value is as long as the destination buffer.
1302 // It should detect the overflow internally, and default to the locale's currency.
1303 tmp[0] = u'¤';
1304 status = U_ZERO_ERROR;
1305 int32_t length = ucurr_forLocale("en_US@currency=euro", tmp, 4, &status);
1306 if (U_FAILURE(status) || dollarStr != UnicodeString(tmp, length)) {
1307 if (U_SUCCESS(status) && tmp[0] == u'¤') {
1308 errln("Fail: ucurr_forLocale(en_US@currency=euro) succeeded without writing output");
1309 } else {
1310 errln("Fail: ucurr_forLocale(en_US@currency=euro) != USD - %s", u_errorName(status));
1311 }
1312 }
1313 }
1314
1315 #endif
1316
1317 /**
1318 * @bug 4139504
1319 * toString() doesn't work with language_VARIANT.
1320 */
1321 void
TestToString()1322 LocaleTest::TestToString() {
1323 Locale DATA [] = {
1324 Locale("xx", "", ""),
1325 Locale("", "YY", ""),
1326 Locale("", "", "ZZ"),
1327 Locale("xx", "YY", ""),
1328 Locale("xx", "", "ZZ"),
1329 Locale("", "YY", "ZZ"),
1330 Locale("xx", "YY", "ZZ"),
1331 };
1332
1333 const char DATA_S [][20] = {
1334 "xx",
1335 "_YY",
1336 "__ZZ",
1337 "xx_YY",
1338 "xx__ZZ",
1339 "_YY_ZZ",
1340 "xx_YY_ZZ",
1341 };
1342
1343 for (int32_t i=0; i < 7; ++i) {
1344 const char *name;
1345 name = DATA[i].getName();
1346
1347 if (strcmp(name, DATA_S[i]) != 0)
1348 {
1349 errln("Fail: Locale.getName(), got:" + UnicodeString(name) + ", expected: " + DATA_S[i]);
1350 }
1351 else
1352 logln("Pass: Locale.getName(), got:" + UnicodeString(name) );
1353 }
1354 }
1355
1356 #if !UCONFIG_NO_FORMATTING
1357
1358 /**
1359 * @bug 4139940
1360 * Couldn't reproduce this bug -- probably was fixed earlier.
1361 *
1362 * ORIGINAL BUG REPORT:
1363 * -- basically, hungarian for monday shouldn't have an \u00f4
1364 * (o circumflex)in it instead it should be an o with 2 inclined
1365 * (right) lines over it..
1366 *
1367 * You may wonder -- why do all this -- why not just add a line to
1368 * LocaleData? Well, I could see by inspection that the locale file had the
1369 * right character in it, so I wanted to check the rest of the pipeline -- a
1370 * very remote possibility, but I wanted to be sure. The other possibility
1371 * is that something is wrong with the font mapping subsystem, but we can't
1372 * test that here.
1373 */
1374 void
Test4139940()1375 LocaleTest::Test4139940()
1376 {
1377 Locale mylocale("hu", "", "");
1378 UDate mydate = date(98,3,13); // A Monday
1379 UErrorCode status = U_ZERO_ERROR;
1380 SimpleDateFormat df_full("EEEE", mylocale, status);
1381 if(U_FAILURE(status)){
1382 dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status)));
1383 return;
1384 }
1385 UnicodeString str;
1386 FieldPosition pos(FieldPosition::DONT_CARE);
1387 df_full.format(mydate, str, pos);
1388 // Make sure that o circumflex (\u00F4) is NOT there, and
1389 // o double acute (\u0151) IS.
1390 UChar ocf = 0x00f4;
1391 UChar oda = 0x0151;
1392 if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) {
1393 /* If the default locale is "th" this test will fail because of the buddhist calendar. */
1394 if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) {
1395 errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d",
1396 str.indexOf(oda), str.indexOf(ocf));
1397 } else {
1398 logln(UnicodeString("An error is produce in buddhist calendar."));
1399 }
1400 logln(UnicodeString("String is: ") + str );
1401 }
1402 }
1403
1404 UDate
date(int32_t y,int32_t m,int32_t d,int32_t hr,int32_t min,int32_t sec)1405 LocaleTest::date(int32_t y, int32_t m, int32_t d, int32_t hr, int32_t min, int32_t sec)
1406 {
1407 UErrorCode status = U_ZERO_ERROR;
1408 Calendar *cal = Calendar::createInstance(status);
1409 if (cal == 0)
1410 return 0.0;
1411 cal->clear();
1412 cal->set(1900 + y, m, d, hr, min, sec); // Add 1900 to follow java.util.Date protocol
1413 UDate dt = cal->getTime(status);
1414 if (U_FAILURE(status))
1415 return 0.0;
1416
1417 delete cal;
1418 return dt;
1419 }
1420
1421 /**
1422 * @bug 4143951
1423 * Russian first day of week should be Monday. Confirmed.
1424 */
1425 void
Test4143951()1426 LocaleTest::Test4143951()
1427 {
1428 UErrorCode status = U_ZERO_ERROR;
1429 Calendar *cal = Calendar::createInstance(Locale("ru", "", ""), status);
1430 if(U_SUCCESS(status)) {
1431 if (cal->getFirstDayOfWeek(status) != UCAL_MONDAY) {
1432 dataerrln("Fail: First day of week in Russia should be Monday");
1433 }
1434 }
1435 delete cal;
1436 }
1437
1438 #endif
1439
1440 /**
1441 * @bug 4147315
1442 * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
1443 * Should throw an exception for unknown locales
1444 */
1445 void
Test4147315()1446 LocaleTest::Test4147315()
1447 {
1448 UnicodeString temp;
1449 // Try with codes that are the wrong length but happen to match text
1450 // at a valid offset in the mapping table
1451 Locale locale("xxx", "CCC");
1452
1453 const char *result = locale.getISO3Country();
1454
1455 // Change to conform to C api usage
1456 if((result==NULL)||(result[0] != 0))
1457 errln("ERROR: getISO3Country() returns: " + UnicodeString(result,"") +
1458 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
1459 }
1460
1461 /**
1462 * @bug 4147317
1463 * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes.
1464 * Should throw an exception for unknown locales
1465 */
1466 void
Test4147317()1467 LocaleTest::Test4147317()
1468 {
1469 UnicodeString temp;
1470 // Try with codes that are the wrong length but happen to match text
1471 // at a valid offset in the mapping table
1472 Locale locale("xxx", "CCC");
1473
1474 const char *result = locale.getISO3Language();
1475
1476 // Change to conform to C api usage
1477 if((result==NULL)||(result[0] != 0))
1478 errln("ERROR: getISO3Language() returns: " + UnicodeString(result,"") +
1479 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
1480 }
1481
1482 /*
1483 * @bug 4147552
1484 */
1485 void
Test4147552()1486 LocaleTest::Test4147552()
1487 {
1488 Locale locales [] = { Locale("no", "NO"),
1489 Locale("no", "NO", "B"),
1490 Locale("no", "NO", "NY")
1491 };
1492
1493 UnicodeString edn("Norwegian (Norway, B)");
1494 UnicodeString englishDisplayNames [] = {
1495 "Norwegian (Norway)",
1496 edn,
1497 // "Norwegian (Norway,B)",
1498 //"Norwegian (Norway,NY)"
1499 "Norwegian (Norway, NY)"
1500 };
1501 UnicodeString ndn("norsk (Norge, B");
1502 UnicodeString norwegianDisplayNames [] = {
1503 "norsk (Norge)",
1504 "norsk (Norge, B)",
1505 //ndn,
1506 "norsk (Noreg, NY)"
1507 //"Norsk (Noreg, Nynorsk)"
1508 };
1509 UErrorCode status = U_ZERO_ERROR;
1510
1511 Locale saveLocale;
1512 Locale::setDefault(Locale::getEnglish(), status);
1513 for (int32_t i = 0; i < 3; ++i) {
1514 Locale loc = locales[i];
1515 UnicodeString temp;
1516 if (loc.getDisplayName(temp) != englishDisplayNames[i])
1517 dataerrln("English display-name mismatch: expected " +
1518 englishDisplayNames[i] + ", got " + loc.getDisplayName(temp));
1519 if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i])
1520 dataerrln("Norwegian display-name mismatch: expected " +
1521 norwegianDisplayNames[i] + ", got " +
1522 loc.getDisplayName(loc, temp));
1523 }
1524 Locale::setDefault(saveLocale, status);
1525 }
1526
1527 void
TestVariantParsing()1528 LocaleTest::TestVariantParsing()
1529 {
1530 Locale en_US_custom("en", "US", "De Anza_Cupertino_California_United States_Earth");
1531
1532 UnicodeString dispName("English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)");
1533 UnicodeString dispVar("DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH");
1534
1535 UnicodeString got;
1536
1537 en_US_custom.getDisplayVariant(Locale::getUS(), got);
1538 if(got != dispVar) {
1539 errln("FAIL: getDisplayVariant()");
1540 errln("Wanted: " + dispVar);
1541 errln("Got : " + got);
1542 }
1543
1544 en_US_custom.getDisplayName(Locale::getUS(), got);
1545 if(got != dispName) {
1546 dataerrln("FAIL: getDisplayName()");
1547 dataerrln("Wanted: " + dispName);
1548 dataerrln("Got : " + got);
1549 }
1550
1551 Locale shortVariant("fr", "FR", "foo");
1552 shortVariant.getDisplayVariant(got);
1553
1554 if(got != "FOO") {
1555 errln("FAIL: getDisplayVariant()");
1556 errln("Wanted: foo");
1557 errln("Got : " + got);
1558 }
1559
1560 Locale bogusVariant("fr", "FR", "_foo");
1561 bogusVariant.getDisplayVariant(got);
1562
1563 if(got != "FOO") {
1564 errln("FAIL: getDisplayVariant()");
1565 errln("Wanted: foo");
1566 errln("Got : " + got);
1567 }
1568
1569 Locale bogusVariant2("fr", "FR", "foo_");
1570 bogusVariant2.getDisplayVariant(got);
1571
1572 if(got != "FOO") {
1573 errln("FAIL: getDisplayVariant()");
1574 errln("Wanted: foo");
1575 errln("Got : " + got);
1576 }
1577
1578 Locale bogusVariant3("fr", "FR", "_foo_");
1579 bogusVariant3.getDisplayVariant(got);
1580
1581 if(got != "FOO") {
1582 errln("FAIL: getDisplayVariant()");
1583 errln("Wanted: foo");
1584 errln("Got : " + got);
1585 }
1586 }
1587
Test20639_DeprecatesISO3Language()1588 void LocaleTest::Test20639_DeprecatesISO3Language() {
1589 IcuTestErrorCode status(*this, "Test20639_DeprecatesISO3Language");
1590
1591 const struct TestCase {
1592 const char* localeName;
1593 const char* expectedISO3Language;
1594 } cases[] = {
1595 {"nb", "nob"},
1596 {"no", "nor"}, // why not nob?
1597 {"he", "heb"},
1598 {"iw", "heb"},
1599 {"ro", "ron"},
1600 {"mo", "mol"},
1601 };
1602 for (auto& cas : cases) {
1603 Locale loc(cas.localeName);
1604 const char* actual = loc.getISO3Language();
1605 assertEquals(cas.localeName, cas.expectedISO3Language, actual);
1606 }
1607 }
1608
1609 #if !UCONFIG_NO_FORMATTING
1610
1611 /**
1612 * @bug 4105828
1613 * Currency symbol in zh is wrong. We will test this at the NumberFormat
1614 * end to test the whole pipe.
1615 */
1616 void
Test4105828()1617 LocaleTest::Test4105828()
1618 {
1619 Locale LOC [] = { Locale::getChinese(), Locale("zh", "CN", ""),
1620 Locale("zh", "TW", ""), Locale("zh", "HK", "") };
1621 UErrorCode status = U_ZERO_ERROR;
1622 for (int32_t i = 0; i < 4; ++i) {
1623 NumberFormat *fmt = NumberFormat::createPercentInstance(LOC[i], status);
1624 if(U_FAILURE(status)) {
1625 dataerrln("Couldn't create NumberFormat - %s", u_errorName(status));
1626 return;
1627 }
1628 UnicodeString result;
1629 FieldPosition pos(FieldPosition::DONT_CARE);
1630 fmt->format((int32_t)1, result, pos);
1631 UnicodeString temp;
1632 if(result != "100%") {
1633 errln(UnicodeString("Percent for ") + LOC[i].getDisplayName(temp) + " should be 100%, got " + result);
1634 }
1635 delete fmt;
1636 }
1637 }
1638
1639 #endif
1640
1641 // Tests setBogus and isBogus APIs for Locale
1642 // Jitterbug 1735
1643 void
TestSetIsBogus()1644 LocaleTest::TestSetIsBogus() {
1645 Locale l("en_US");
1646 l.setToBogus();
1647 if(l.isBogus() != TRUE) {
1648 errln("After setting bogus, didn't return TRUE");
1649 }
1650 l = "en_US"; // This should reset bogus
1651 if(l.isBogus() != FALSE) {
1652 errln("After resetting bogus, didn't return FALSE");
1653 }
1654 }
1655
1656
1657 void
TestAddLikelySubtags()1658 LocaleTest::TestAddLikelySubtags() {
1659 IcuTestErrorCode status(*this, "TestAddLikelySubtags()");
1660
1661 static const Locale min("sv");
1662 static const Locale max("sv_Latn_SE");
1663
1664 Locale result(min);
1665 result.addLikelySubtags(status);
1666 status.errIfFailureAndReset("\"%s\"", min.getName());
1667 assertEquals("addLikelySubtags", max.getName(), result.getName());
1668 }
1669
1670
1671 void
TestMinimizeSubtags()1672 LocaleTest::TestMinimizeSubtags() {
1673 IcuTestErrorCode status(*this, "TestMinimizeSubtags()");
1674
1675 static const Locale max("zh_Hant_TW");
1676 static const Locale min("zh_TW");
1677
1678 Locale result(max);
1679 result.minimizeSubtags(status);
1680 status.errIfFailureAndReset("\"%s\"", max.getName());
1681 assertEquals("minimizeSubtags", min.getName(), result.getName());
1682 }
1683
1684
1685 void
TestAddLikelyAndMinimizeSubtags()1686 LocaleTest::TestAddLikelyAndMinimizeSubtags() {
1687 IcuTestErrorCode status(*this, "TestAddLikelyAndMinimizeSubtags()");
1688
1689 static const struct {
1690 const char* const from;
1691 const char* const add;
1692 const char* const remove;
1693 } full_data[] = {
1694 {
1695 "und_AQ",
1696 "_Latn_AQ",
1697 "_AQ"
1698 }, {
1699 "und_Zzzz_AQ",
1700 "_Latn_AQ",
1701 "_AQ"
1702 }, {
1703 "und_Latn_AQ",
1704 "_Latn_AQ",
1705 "_AQ"
1706 }, {
1707 "und_Moon_AQ",
1708 "_Moon_AQ",
1709 "_Moon_AQ"
1710 },
1711 };
1712
1713 for (const auto& item : full_data) {
1714 const char* const org = item.from;
1715 const char* const exp = item.add;
1716 Locale res(org);
1717 res.addLikelySubtags(status);
1718 status.errIfFailureAndReset("\"%s\"", org);
1719 assertEquals("addLikelySubtags", exp, res.getName());
1720 }
1721
1722 for (const auto& item : full_data) {
1723 const char* const org = item.from;
1724 const char* const exp = item.remove;
1725 Locale res(org);
1726 res.minimizeSubtags(status);
1727 status.errIfFailureAndReset("\"%s\"", org);
1728 assertEquals("minimizeSubtags", exp, res.getName());
1729 }
1730 }
1731
1732
1733 void
TestKeywordVariants(void)1734 LocaleTest::TestKeywordVariants(void) {
1735 static const struct {
1736 const char *localeID;
1737 const char *expectedLocaleID;
1738 //const char *expectedLocaleIDNoKeywords;
1739 //const char *expectedCanonicalID;
1740 const char *expectedKeywords[10];
1741 int32_t numKeywords;
1742 UErrorCode expectedStatus;
1743 } testCases[] = {
1744 {
1745 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
1746 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1747 //"de_DE",
1748 //"de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
1749 {"calendar", "collation", "currency"},
1750 3,
1751 U_ZERO_ERROR
1752 },
1753 {
1754 "de_DE@euro",
1755 "de_DE@euro",
1756 //"de_DE",
1757 //"de_DE@currency=EUR",
1758 {"","","","","","",""},
1759 0,
1760 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
1761 }
1762 };
1763 UErrorCode status = U_ZERO_ERROR;
1764
1765 int32_t i = 0, j = 0;
1766 const char *result = NULL;
1767 StringEnumeration *keywords;
1768 int32_t keyCount = 0;
1769 const char *keyword = NULL;
1770 const UnicodeString *keywordString;
1771 int32_t keywordLen = 0;
1772
1773 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1774 status = U_ZERO_ERROR;
1775 Locale l(testCases[i].localeID);
1776 keywords = l.createKeywords(status);
1777
1778 if(status != testCases[i].expectedStatus) {
1779 err("Expected to get status %s. Got %s instead\n",
1780 u_errorName(testCases[i].expectedStatus), u_errorName(status));
1781 }
1782 status = U_ZERO_ERROR;
1783 if(keywords) {
1784 if((keyCount = keywords->count(status)) != testCases[i].numKeywords) {
1785 err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
1786 }
1787 if(keyCount) {
1788 for(j = 0;;) {
1789 if((j&1)==0) {
1790 if((keyword = keywords->next(&keywordLen, status)) == NULL) {
1791 break;
1792 }
1793 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1794 err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1795 }
1796 } else {
1797 if((keywordString = keywords->snext(status)) == NULL) {
1798 break;
1799 }
1800 if(*keywordString != UnicodeString(testCases[i].expectedKeywords[j], "")) {
1801 err("Expected to get keyword UnicodeString %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1802 }
1803 }
1804 j++;
1805
1806 if(j == keyCount / 2) {
1807 // replace keywords with a clone of itself
1808 StringEnumeration *k2 = keywords->clone();
1809 if(k2 == NULL || keyCount != k2->count(status)) {
1810 errln("KeywordEnumeration.clone() failed");
1811 } else {
1812 delete keywords;
1813 keywords = k2;
1814 }
1815 }
1816 }
1817 keywords->reset(status); // Make sure that reset works.
1818 for(j = 0;;) {
1819 if((keyword = keywords->next(&keywordLen, status)) == NULL) {
1820 break;
1821 }
1822 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
1823 err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
1824 }
1825 j++;
1826 }
1827 }
1828 delete keywords;
1829 }
1830 result = l.getName();
1831 if(uprv_strcmp(testCases[i].expectedLocaleID, result) != 0) {
1832 err("Expected to get \"%s\" from \"%s\". Got \"%s\" instead\n",
1833 testCases[i].expectedLocaleID, testCases[i].localeID, result);
1834 }
1835
1836 }
1837
1838 }
1839
1840
1841 void
TestCreateUnicodeKeywords(void)1842 LocaleTest::TestCreateUnicodeKeywords(void) {
1843 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywords()");
1844
1845 static const Locale l("de@calendar=buddhist;collation=phonebook");
1846
1847 LocalPointer<StringEnumeration> keys(l.createUnicodeKeywords(status));
1848 status.errIfFailureAndReset("\"%s\"", l.getName());
1849
1850 const char* key;
1851 int32_t resultLength;
1852
1853 key = keys->next(&resultLength, status);
1854 status.errIfFailureAndReset("key #1");
1855 assertEquals("resultLength", 2, resultLength);
1856 assertTrue("key != nullptr", key != nullptr);
1857 if (key != nullptr) {
1858 assertEquals("calendar", "ca", key);
1859 }
1860
1861 key = keys->next(&resultLength, status);
1862 status.errIfFailureAndReset("key #2");
1863 assertEquals("resultLength", 2, resultLength);
1864 assertTrue("key != nullptr", key != nullptr);
1865 if (key != nullptr) {
1866 assertEquals("collation", "co", key);
1867 }
1868
1869 key = keys->next(&resultLength, status);
1870 status.errIfFailureAndReset("end of keys");
1871 assertEquals("resultLength", 0, resultLength);
1872 assertTrue("key == nullptr", key == nullptr);
1873
1874 const UnicodeString* skey;
1875 keys->reset(status); // KeywordEnumeration::reset() never touches status.
1876
1877 skey = keys->snext(status);
1878 status.errIfFailureAndReset("skey #1");
1879 assertTrue("skey != nullptr", skey != nullptr);
1880 if (skey != nullptr) {
1881 assertEquals("calendar", "ca", *skey);
1882 }
1883
1884 skey = keys->snext(status);
1885 status.errIfFailureAndReset("skey #2");
1886 assertTrue("skey != nullptr", skey != nullptr);
1887 if (skey != nullptr) {
1888 assertEquals("collation", "co", *skey);
1889 }
1890
1891 skey = keys->snext(status);
1892 status.errIfFailureAndReset("end of keys");
1893 assertTrue("skey == nullptr", skey == nullptr);
1894 }
1895
1896
1897 void
TestKeywordVariantParsing(void)1898 LocaleTest::TestKeywordVariantParsing(void) {
1899 static const struct {
1900 const char *localeID;
1901 const char *keyword;
1902 const char *expectedValue;
1903 } testCases[] = {
1904 { "de_DE@ C o ll A t i o n = Phonebook ", "collation", "Phonebook" },
1905 { "de_DE", "collation", ""},
1906 { "de_DE@collation= PHONEBOOK", "collation", "PHONEBOOK" },
1907 { "de_DE@ currency = euro ; CoLLaTion = PHONEBOOk ", "collation", "PHONEBOOk" },
1908 };
1909
1910 UErrorCode status = U_ZERO_ERROR;
1911
1912 int32_t i = 0;
1913 int32_t resultLen = 0;
1914 char buffer[256];
1915
1916 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
1917 *buffer = 0;
1918 Locale l(testCases[i].localeID);
1919 resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
1920 (void)resultLen; // Suppress unused variable warning.
1921 if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
1922 err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
1923 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
1924 }
1925 }
1926 }
1927
1928 void
TestCreateKeywordSet(void)1929 LocaleTest::TestCreateKeywordSet(void) {
1930 IcuTestErrorCode status(*this, "TestCreateKeywordSet()");
1931
1932 static const Locale l("de@calendar=buddhist;collation=phonebook");
1933
1934 std::set<std::string> result;
1935 l.getKeywords<std::string>(
1936 std::insert_iterator<decltype(result)>(result, result.begin()),
1937 status);
1938 status.errIfFailureAndReset("\"%s\"", l.getName());
1939
1940 assertEquals("set::size()", 2, static_cast<int32_t>(result.size()));
1941 assertTrue("set::find(\"calendar\")",
1942 result.find("calendar") != result.end());
1943 assertTrue("set::find(\"collation\")",
1944 result.find("collation") != result.end());
1945 }
1946
1947 void
TestCreateKeywordSetEmpty(void)1948 LocaleTest::TestCreateKeywordSetEmpty(void) {
1949 IcuTestErrorCode status(*this, "TestCreateKeywordSetEmpty()");
1950
1951 static const Locale l("de");
1952
1953 std::set<std::string> result;
1954 l.getKeywords<std::string>(
1955 std::insert_iterator<decltype(result)>(result, result.begin()),
1956 status);
1957 status.errIfFailureAndReset("\"%s\"", l.getName());
1958
1959 assertEquals("set::size()", 0, static_cast<int32_t>(result.size()));
1960 }
1961
1962 void
TestCreateUnicodeKeywordSet(void)1963 LocaleTest::TestCreateUnicodeKeywordSet(void) {
1964 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSet()");
1965
1966 static const Locale l("de@calendar=buddhist;collation=phonebook");
1967
1968 std::set<std::string> result;
1969 l.getUnicodeKeywords<std::string>(
1970 std::insert_iterator<decltype(result)>(result, result.begin()),
1971 status);
1972 status.errIfFailureAndReset("\"%s\"", l.getName());
1973
1974 assertEquals("set::size()", 2, static_cast<int32_t>(result.size()));
1975 assertTrue("set::find(\"ca\")",
1976 result.find("ca") != result.end());
1977 assertTrue("set::find(\"co\")",
1978 result.find("co") != result.end());
1979 }
1980
1981 void
TestCreateUnicodeKeywordSetEmpty(void)1982 LocaleTest::TestCreateUnicodeKeywordSetEmpty(void) {
1983 IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetEmpty()");
1984
1985 static const Locale l("de");
1986
1987 std::set<std::string> result;
1988 l.getUnicodeKeywords<std::string>(
1989 std::insert_iterator<decltype(result)>(result, result.begin()),
1990 status);
1991 status.errIfFailureAndReset("\"%s\"", l.getName());
1992
1993 assertEquals("set::size()", 0, static_cast<int32_t>(result.size()));
1994 }
1995
1996 void
TestGetKeywordValueStdString(void)1997 LocaleTest::TestGetKeywordValueStdString(void) {
1998 IcuTestErrorCode status(*this, "TestGetKeywordValueStdString()");
1999
2000 static const char tag[] = "fa-u-nu-latn";
2001 static const char keyword[] = "numbers";
2002 static const char expected[] = "latn";
2003
2004 Locale l = Locale::forLanguageTag(tag, status);
2005 status.errIfFailureAndReset("\"%s\"", tag);
2006
2007 std::string result = l.getKeywordValue<std::string>(keyword, status);
2008 status.errIfFailureAndReset("\"%s\"", keyword);
2009 assertEquals(keyword, expected, result.c_str());
2010 }
2011
2012 void
TestGetUnicodeKeywordValueStdString(void)2013 LocaleTest::TestGetUnicodeKeywordValueStdString(void) {
2014 IcuTestErrorCode status(*this, "TestGetUnicodeKeywordValueStdString()");
2015
2016 static const char keyword[] = "co";
2017 static const char expected[] = "phonebk";
2018
2019 static const Locale l("de@calendar=buddhist;collation=phonebook");
2020
2021 std::string result = l.getUnicodeKeywordValue<std::string>(keyword, status);
2022 status.errIfFailureAndReset("\"%s\"", keyword);
2023 assertEquals(keyword, expected, result.c_str());
2024 }
2025
2026 void
TestSetKeywordValue(void)2027 LocaleTest::TestSetKeywordValue(void) {
2028 static const struct {
2029 const char *keyword;
2030 const char *value;
2031 } testCases[] = {
2032 { "collation", "phonebook" },
2033 { "currency", "euro" },
2034 { "calendar", "buddhist" }
2035 };
2036
2037 UErrorCode status = U_ZERO_ERROR;
2038
2039 int32_t i = 0;
2040 int32_t resultLen = 0;
2041 char buffer[256];
2042
2043 Locale l(Locale::getGerman());
2044
2045 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2046 l.setKeywordValue(testCases[i].keyword, testCases[i].value, status);
2047 if(U_FAILURE(status)) {
2048 err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status));
2049 }
2050
2051 *buffer = 0;
2052 resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
2053 (void)resultLen; // Suppress unused variable warning.
2054 if(uprv_strcmp(testCases[i].value, buffer) != 0) {
2055 err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
2056 testCases[i].value, testCases[i].keyword, buffer);
2057 }
2058 }
2059 }
2060
2061 void
TestSetKeywordValueStringPiece(void)2062 LocaleTest::TestSetKeywordValueStringPiece(void) {
2063 IcuTestErrorCode status(*this, "TestSetKeywordValueStringPiece()");
2064 Locale l(Locale::getGerman());
2065
2066 l.setKeywordValue(StringPiece("collation"), StringPiece("phonebook"), status);
2067 l.setKeywordValue(StringPiece("calendarxxx", 8), StringPiece("buddhistxxx", 8), status);
2068
2069 static const char expected[] = "de@calendar=buddhist;collation=phonebook";
2070 assertEquals("", expected, l.getName());
2071 }
2072
2073 void
TestSetUnicodeKeywordValueStringPiece(void)2074 LocaleTest::TestSetUnicodeKeywordValueStringPiece(void) {
2075 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueStringPiece()");
2076 Locale l(Locale::getGerman());
2077
2078 l.setUnicodeKeywordValue(StringPiece("co"), StringPiece("phonebk"), status);
2079 status.errIfFailureAndReset();
2080
2081 l.setUnicodeKeywordValue(StringPiece("caxxx", 2), StringPiece("buddhistxxx", 8), status);
2082 status.errIfFailureAndReset();
2083
2084 static const char expected[] = "de@calendar=buddhist;collation=phonebook";
2085 assertEquals("", expected, l.getName());
2086
2087 l.setUnicodeKeywordValue("cu", nullptr, status);
2088 status.errIfFailureAndReset();
2089 assertEquals("", expected, l.getName());
2090
2091 l.setUnicodeKeywordValue("!!", nullptr, status);
2092 assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
2093 assertEquals("", expected, l.getName());
2094
2095 l.setUnicodeKeywordValue("co", "!!", status);
2096 assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
2097 assertEquals("", expected, l.getName());
2098
2099 l.setUnicodeKeywordValue("co", nullptr, status);
2100 status.errIfFailureAndReset();
2101
2102 l.setUnicodeKeywordValue("ca", "", status);
2103 status.errIfFailureAndReset();
2104
2105 assertEquals("", Locale::getGerman().getName(), l.getName());
2106 }
2107
2108 void
TestGetBaseName(void)2109 LocaleTest::TestGetBaseName(void) {
2110 static const struct {
2111 const char *localeID;
2112 const char *baseName;
2113 } testCases[] = {
2114 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
2115 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
2116 { "ja@calendar = buddhist", "ja" },
2117 { "de-u-co-phonebk", "de"}
2118 };
2119
2120 int32_t i = 0;
2121
2122 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
2123 Locale loc(testCases[i].localeID);
2124 if(strcmp(testCases[i].baseName, loc.getBaseName())) {
2125 errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"",
2126 testCases[i].localeID, testCases[i].baseName, loc.getBaseName());
2127 return;
2128 }
2129 }
2130
2131 // Verify that adding a keyword to an existing Locale doesn't change the base name.
2132 UErrorCode status = U_ZERO_ERROR;
2133 Locale loc2("en-US");
2134 if (strcmp("en_US", loc2.getBaseName())) {
2135 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
2136 }
2137 loc2.setKeywordValue("key", "value", status);
2138 if (strcmp("en_US@key=value", loc2.getName())) {
2139 errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__, __LINE__, loc2.getName());
2140 }
2141 if (strcmp("en_US", loc2.getBaseName())) {
2142 errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName());
2143 }
2144 }
2145
2146 /**
2147 * Compare two locale IDs. If they are equal, return 0. If `string'
2148 * starts with `prefix' plus an additional element, that is, string ==
2149 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
2150 */
_loccmp(const char * string,const char * prefix)2151 static UBool _loccmp(const char* string, const char* prefix) {
2152 int32_t slen = (int32_t)strlen(string),
2153 plen = (int32_t)strlen(prefix);
2154 int32_t c = uprv_strncmp(string, prefix, plen);
2155 /* 'root' is "less than" everything */
2156 if (prefix[0] == '\0') {
2157 return string[0] != '\0';
2158 }
2159 if (c) return -1; /* mismatch */
2160 if (slen == plen) return 0;
2161 if (string[plen] == '_') return 1;
2162 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
2163 }
2164
2165 /**
2166 * Check the relationship between requested locales, and report problems.
2167 * The caller specifies the expected relationships between requested
2168 * and valid (expReqValid) and between valid and actual (expValidActual).
2169 * Possible values are:
2170 * "gt" strictly greater than, e.g., en_US > en
2171 * "ge" greater or equal, e.g., en >= en
2172 * "eq" equal, e.g., en == en
2173 */
_checklocs(const char * label,const char * req,const Locale & validLoc,const Locale & actualLoc,const char * expReqValid,const char * expValidActual)2174 void LocaleTest::_checklocs(const char* label,
2175 const char* req,
2176 const Locale& validLoc,
2177 const Locale& actualLoc,
2178 const char* expReqValid,
2179 const char* expValidActual) {
2180 const char* valid = validLoc.getName();
2181 const char* actual = actualLoc.getName();
2182 int32_t reqValid = _loccmp(req, valid);
2183 int32_t validActual = _loccmp(valid, actual);
2184 if (((0 == uprv_strcmp(expReqValid, "gt") && reqValid > 0) ||
2185 (0 == uprv_strcmp(expReqValid, "ge") && reqValid >= 0) ||
2186 (0 == uprv_strcmp(expReqValid, "eq") && reqValid == 0)) &&
2187 ((0 == uprv_strcmp(expValidActual, "gt") && validActual > 0) ||
2188 (0 == uprv_strcmp(expValidActual, "ge") && validActual >= 0) ||
2189 (0 == uprv_strcmp(expValidActual, "eq") && validActual == 0))) {
2190 logln("%s; req=%s, valid=%s, actual=%s",
2191 label, req, valid, actual);
2192 } else {
2193 dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)",
2194 label, req, valid, actual,
2195 expReqValid, expValidActual);
2196 }
2197 }
2198
TestGetLocale(void)2199 void LocaleTest::TestGetLocale(void) {
2200 #if !UCONFIG_NO_SERVICE
2201 const char *req;
2202 Locale valid, actual, reqLoc;
2203
2204 // Calendar
2205 #if !UCONFIG_NO_FORMATTING
2206 {
2207 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
2208 req = "en_US_BROOKLYN";
2209 Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec);
2210 if (U_FAILURE(ec)) {
2211 dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec));
2212 } else {
2213 valid = cal->getLocale(ULOC_VALID_LOCALE, ec);
2214 actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec);
2215 if (U_FAILURE(ec)) {
2216 errln("FAIL: Calendar::getLocale() failed");
2217 } else {
2218 _checklocs("Calendar", req, valid, actual);
2219 }
2220 /* Make sure that it fails correctly */
2221 ec = U_FILE_ACCESS_ERROR;
2222 if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) {
2223 errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\"");
2224 }
2225 ec = U_ZERO_ERROR;
2226 }
2227 delete cal;
2228 }
2229 #endif
2230
2231 // DecimalFormat, DecimalFormatSymbols
2232 #if !UCONFIG_NO_FORMATTING
2233 {
2234 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
2235 req = "fr_FR_NICE";
2236 NumberFormat* nf = NumberFormat::createInstance(Locale::createFromName(req), ec);
2237 if (U_FAILURE(ec)) {
2238 dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec));
2239 } else {
2240 DecimalFormat* dec = dynamic_cast<DecimalFormat*>(nf);
2241 if (dec == NULL) {
2242 errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat");
2243 return;
2244 }
2245 valid = dec->getLocale(ULOC_VALID_LOCALE, ec);
2246 actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec);
2247 if (U_FAILURE(ec)) {
2248 errln("FAIL: DecimalFormat::getLocale() failed");
2249 } else {
2250 _checklocs("DecimalFormat", req, valid, actual);
2251 }
2252
2253 const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols();
2254 if (sym == NULL) {
2255 errln("FAIL: getDecimalFormatSymbols returned NULL");
2256 return;
2257 }
2258 valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
2259 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
2260 if (U_FAILURE(ec)) {
2261 errln("FAIL: DecimalFormatSymbols::getLocale() failed");
2262 } else {
2263 _checklocs("DecimalFormatSymbols", req, valid, actual);
2264 }
2265 }
2266 delete nf;
2267 }
2268 #endif
2269
2270 // DateFormat, DateFormatSymbols
2271 #if !UCONFIG_NO_FORMATTING
2272 {
2273 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
2274 req = "de_CH_LUCERNE";
2275 DateFormat* df =
2276 DateFormat::createDateInstance(DateFormat::kDefault,
2277 Locale::createFromName(req));
2278 if (df == 0){
2279 dataerrln("Error calling DateFormat::createDateInstance()");
2280 } else {
2281 SimpleDateFormat* dat = dynamic_cast<SimpleDateFormat*>(df);
2282 if (dat == NULL) {
2283 errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat");
2284 return;
2285 }
2286 valid = dat->getLocale(ULOC_VALID_LOCALE, ec);
2287 actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec);
2288 if (U_FAILURE(ec)) {
2289 errln("FAIL: SimpleDateFormat::getLocale() failed");
2290 } else {
2291 _checklocs("SimpleDateFormat", req, valid, actual);
2292 }
2293
2294 const DateFormatSymbols* sym = dat->getDateFormatSymbols();
2295 if (sym == NULL) {
2296 errln("FAIL: getDateFormatSymbols returned NULL");
2297 return;
2298 }
2299 valid = sym->getLocale(ULOC_VALID_LOCALE, ec);
2300 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec);
2301 if (U_FAILURE(ec)) {
2302 errln("FAIL: DateFormatSymbols::getLocale() failed");
2303 } else {
2304 _checklocs("DateFormatSymbols", req, valid, actual);
2305 }
2306 }
2307 delete df;
2308 }
2309 #endif
2310
2311 // BreakIterator
2312 #if !UCONFIG_NO_BREAK_ITERATION
2313 {
2314 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
2315 req = "es_ES_BARCELONA";
2316 reqLoc = Locale::createFromName(req);
2317 BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec);
2318 if (U_FAILURE(ec)) {
2319 dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec));
2320 } else {
2321 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
2322 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
2323 if (U_FAILURE(ec)) {
2324 errln("FAIL: BreakIterator::getLocale() failed");
2325 } else {
2326 _checklocs("BreakIterator", req, valid, actual);
2327 }
2328
2329 // After registering something, the behavior should be different
2330 URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec);
2331 brk = 0; // registerInstance adopts
2332 if (U_FAILURE(ec)) {
2333 errln("FAIL: BreakIterator::registerInstance() failed");
2334 } else {
2335 brk = BreakIterator::createWordInstance(reqLoc, ec);
2336 if (U_FAILURE(ec)) {
2337 errln("FAIL: BreakIterator::createWordInstance failed");
2338 } else {
2339 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
2340 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
2341 if (U_FAILURE(ec)) {
2342 errln("FAIL: BreakIterator::getLocale() failed");
2343 } else {
2344 // N.B.: now expect valid==actual==req
2345 _checklocs("BreakIterator(registered)",
2346 req, valid, actual, "eq", "eq");
2347 }
2348 }
2349 // No matter what, unregister
2350 BreakIterator::unregister(key, ec);
2351 if (U_FAILURE(ec)) {
2352 errln("FAIL: BreakIterator::unregister() failed");
2353 }
2354 delete brk;
2355 brk = 0;
2356 }
2357
2358 // After unregistering, should behave normally again
2359 brk = BreakIterator::createWordInstance(reqLoc, ec);
2360 if (U_FAILURE(ec)) {
2361 errln("FAIL: BreakIterator::createWordInstance failed");
2362 } else {
2363 valid = brk->getLocale(ULOC_VALID_LOCALE, ec);
2364 actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec);
2365 if (U_FAILURE(ec)) {
2366 errln("FAIL: BreakIterator::getLocale() failed");
2367 } else {
2368 _checklocs("BreakIterator(unregistered)", req, valid, actual);
2369 }
2370 }
2371 }
2372 delete brk;
2373 }
2374 #endif
2375
2376 // Collator
2377 #if !UCONFIG_NO_COLLATION
2378 {
2379 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
2380
2381 checkRegisteredCollators(NULL); // Don't expect any extras
2382
2383 req = "hi_IN_BHOPAL";
2384 reqLoc = Locale::createFromName(req);
2385 Collator* coll = Collator::createInstance(reqLoc, ec);
2386 if (U_FAILURE(ec)) {
2387 dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec));
2388 } else {
2389 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
2390 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
2391 if (U_FAILURE(ec)) {
2392 errln("FAIL: Collator::getLocale() failed");
2393 } else {
2394 _checklocs("Collator", req, valid, actual);
2395 }
2396
2397 // After registering something, the behavior should be different
2398 URegistryKey key = Collator::registerInstance(coll, reqLoc, ec);
2399 coll = 0; // registerInstance adopts
2400 if (U_FAILURE(ec)) {
2401 errln("FAIL: Collator::registerInstance() failed");
2402 } else {
2403 coll = Collator::createInstance(reqLoc, ec);
2404 if (U_FAILURE(ec)) {
2405 errln("FAIL: Collator::createWordInstance failed");
2406 } else {
2407 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
2408 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
2409 if (U_FAILURE(ec)) {
2410 errln("FAIL: Collator::getLocale() failed");
2411 } else {
2412 // N.B.: now expect valid==actual==req
2413 _checklocs("Collator(registered)",
2414 req, valid, actual, "eq", "eq");
2415 }
2416 }
2417 checkRegisteredCollators(req); // include hi_IN_BHOPAL
2418
2419 // No matter what, unregister
2420 Collator::unregister(key, ec);
2421 if (U_FAILURE(ec)) {
2422 errln("FAIL: Collator::unregister() failed");
2423 }
2424 delete coll;
2425 coll = 0;
2426 }
2427
2428 // After unregistering, should behave normally again
2429 coll = Collator::createInstance(reqLoc, ec);
2430 if (U_FAILURE(ec)) {
2431 errln("FAIL: Collator::createInstance failed");
2432 } else {
2433 valid = coll->getLocale(ULOC_VALID_LOCALE, ec);
2434 actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec);
2435 if (U_FAILURE(ec)) {
2436 errln("FAIL: Collator::getLocale() failed");
2437 } else {
2438 _checklocs("Collator(unregistered)", req, valid, actual);
2439 }
2440 }
2441 }
2442 delete coll;
2443
2444 checkRegisteredCollators(NULL); // extra should be gone again
2445 }
2446 #endif
2447 #endif
2448 }
2449
2450 #if !UCONFIG_NO_COLLATION
2451 /**
2452 * Compare Collator::getAvailableLocales(int) [ "old", returning an array ]
2453 * with Collator::getAvailableLocales() [ "new", returning a StringEnumeration ]
2454 * These should be identical (check their API docs) EXCEPT that
2455 * if expectExtra is non-NULL, it will be in the "new" array but not "old".
2456 * Does not return any status but calls errln on error.
2457 * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL.
2458 */
checkRegisteredCollators(const char * expectExtra)2459 void LocaleTest::checkRegisteredCollators(const char *expectExtra) {
2460 UErrorCode status = U_ZERO_ERROR;
2461 int32_t count1=0,count2=0;
2462 Hashtable oldHash(status);
2463 Hashtable newHash(status);
2464 assertSuccess(WHERE, status);
2465
2466 UnicodeString expectStr(expectExtra?expectExtra:"n/a", "");
2467
2468 // the 'old' list (non enumeration)
2469 const Locale* oldList = Collator::getAvailableLocales(count1);
2470 if(oldList == NULL) {
2471 dataerrln("Error: Collator::getAvailableLocales(count) returned NULL");
2472 return;
2473 }
2474
2475 // the 'new' list (enumeration)
2476 LocalPointer<StringEnumeration> newEnum(Collator::getAvailableLocales());
2477 if(newEnum.isNull()) {
2478 errln("Error: collator::getAvailableLocales() returned NULL");
2479 return;
2480 }
2481
2482 // OK. Let's add all of the OLD
2483 // then check for any in the NEW not in OLD
2484 // then check for any in OLD not in NEW.
2485
2486 // 1. add all of OLD
2487 for(int32_t i=0;i<count1;i++) {
2488 const UnicodeString key(oldList[i].getName(), "");
2489 int32_t oldI = oldHash.puti(key, 1, status);
2490 if( oldI == 1 ){
2491 errln("Error: duplicate key %s in Collator::getAvailableLocales(count) list.\n",
2492 oldList[i].getName());
2493 return;
2494 }
2495 if(expectExtra != NULL && !strcmp(expectExtra, oldList[i].getName())) {
2496 errln("Inexplicably, Collator::getAvailableCollators(count) had registered collator %s. This shouldn't happen, so I am going to consider it an error.\n", expectExtra);
2497 }
2498 }
2499
2500 // 2. add all of NEW
2501 const UnicodeString *locStr;
2502 UBool foundExpected = FALSE;
2503 while((locStr = newEnum->snext(status)) && U_SUCCESS(status)) {
2504 count2++;
2505
2506 if(expectExtra != NULL && expectStr == *locStr) {
2507 foundExpected = TRUE;
2508 logln(UnicodeString("Found expected registered collator: ","") + expectStr);
2509 }
2510 (void)foundExpected; // Hush unused variable compiler warning.
2511
2512 if( oldHash.geti(*locStr) == 0 ) {
2513 if(expectExtra != NULL && expectStr==*locStr) {
2514 logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr);
2515 } else {
2516 errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","")
2517 + *locStr);
2518 }
2519 }
2520 newHash.puti(*locStr, 1, status);
2521 }
2522
2523 // 3. check all of OLD again
2524 for(int32_t i=0;i<count1;i++) {
2525 const UnicodeString key(oldList[i].getName(), "");
2526 int32_t newI = newHash.geti(key);
2527 if(newI == 0) {
2528 errln(UnicodeString("Error: Collator::getAvailableLocales() is missing: ","")
2529 + key);
2530 }
2531 }
2532
2533 int32_t expectCount2 = count1;
2534 if(expectExtra != NULL) {
2535 expectCount2 ++; // if an extra item registered, bump the expect count
2536 }
2537
2538 assertEquals("Collator::getAvail() count", expectCount2, count2);
2539 }
2540 #endif
2541
2542
2543
TestVariantWithOutCountry(void)2544 void LocaleTest::TestVariantWithOutCountry(void) {
2545 Locale loc("en","","POSIX");
2546 if (0 != strcmp(loc.getVariant(), "POSIX")) {
2547 errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc.getName(), "POSIX", loc.getVariant());
2548 }
2549 Locale loc2("en","","FOUR");
2550 if (0 != strcmp(loc2.getVariant(), "FOUR")) {
2551 errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2.getName(), "FOUR", loc2.getVariant());
2552 }
2553 Locale loc3("en","Latn","","FOUR");
2554 if (0 != strcmp(loc3.getVariant(), "FOUR")) {
2555 errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3.getName(), "FOUR", loc3.getVariant());
2556 }
2557 Locale loc4("","Latn","","FOUR");
2558 if (0 != strcmp(loc4.getVariant(), "FOUR")) {
2559 errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4.getName(), "FOUR", loc4.getVariant());
2560 }
2561 Locale loc5("","Latn","US","FOUR");
2562 if (0 != strcmp(loc5.getVariant(), "FOUR")) {
2563 errln("FAIL: _Latn_US_FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc5.getName(), "FOUR", loc5.getVariant());
2564 }
2565 Locale loc6("de-1901");
2566 if (0 != strcmp(loc6.getVariant(), "1901")) {
2567 errln("FAIL: de-1901 didn't get parsed correctly - name is %s - expected %s got %s", loc6.getName(), "1901", loc6.getVariant());
2568 }
2569 }
2570
_canonicalize(int32_t selector,const char * localeID)2571 static Locale _canonicalize(int32_t selector, /* 0==createFromName, 1==createCanonical, 2==Locale ct */
2572 const char* localeID) {
2573 switch (selector) {
2574 case 0:
2575 return Locale::createFromName(localeID);
2576 case 1:
2577 return Locale::createCanonical(localeID);
2578 case 2:
2579 return Locale(localeID);
2580 default:
2581 return Locale("");
2582 }
2583 }
2584
TestCanonicalization(void)2585 void LocaleTest::TestCanonicalization(void)
2586 {
2587 static const struct {
2588 const char *localeID; /* input */
2589 const char *getNameID; /* expected getName() result */
2590 const char *canonicalID; /* expected canonicalize() result */
2591 } testCases[] = {
2592 { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
2593 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
2594 "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
2595 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
2596 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
2597 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
2598 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
2599 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
2600 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
2601 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
2602 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
2603 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
2604 // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS
2605 // TODO: unify this behavior
2606 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */
2607 { "de-1901", "de__1901", "de__1901" }, /* registered name */
2608 { "de-1906", "de__1906", "de__1906" }, /* registered name */
2609
2610 /* posix behavior that used to be performed by getName */
2611 { "mr.utf8", "mr.utf8", "mr" },
2612 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
2613 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
2614 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
2615 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
2616 { "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 */
2617
2618 /* fleshing out canonicalization */
2619 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
2620 { "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" },
2621 /* already-canonical ids are not changed */
2622 { "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" },
2623 /* norwegian is just too weird, if we handle things in their full generality */
2624 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
2625
2626 /* test cases reflecting internal resource bundle usage */
2627 { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
2628 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
2629 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
2630
2631 // Before ICU 64, ICU locale canonicalization had some additional mappings.
2632 // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants".
2633 // The following now use standard canonicalization.
2634 { "", "", "" },
2635 { "C", "c", "c" },
2636 { "POSIX", "posix", "posix" },
2637 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
2638 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
2639 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
2640 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
2641 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
2642 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
2643 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
2644 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
2645 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
2646 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
2647 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
2648 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
2649 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
2650 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
2651 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
2652 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
2653 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
2654 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
2655 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
2656 { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
2657 { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
2658 { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
2659 { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
2660 { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
2661 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
2662 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
2663 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
2664 { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
2665 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
2666 { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
2667 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */
2668 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
2669 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
2670 { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
2671 { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
2672 /* PRE_EURO and EURO conversions don't affect other keywords */
2673 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
2674 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
2675 /* currency keyword overrides PRE_EURO and EURO currency */
2676 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
2677 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
2678 };
2679
2680 static const char* label[] = { "createFromName", "createCanonical", "Locale" };
2681
2682 int32_t i, j;
2683
2684 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
2685 for (j=0; j<3; ++j) {
2686 const char* expected = (j==1) ? testCases[i].canonicalID : testCases[i].getNameID;
2687 Locale loc = _canonicalize(j, testCases[i].localeID);
2688 const char* getName = loc.isBogus() ? "BOGUS" : loc.getName();
2689 if(uprv_strcmp(expected, getName) != 0) {
2690 errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"",
2691 label[j], testCases[i].localeID, getName, expected);
2692 } else {
2693 logln("Ok: %s(%s) => \"%s\"",
2694 label[j], testCases[i].localeID, getName);
2695 }
2696 }
2697 }
2698 }
2699
TestCurrencyByDate(void)2700 void LocaleTest::TestCurrencyByDate(void)
2701 {
2702 #if !UCONFIG_NO_FORMATTING
2703 UErrorCode status = U_ZERO_ERROR;
2704 UDate date = uprv_getUTCtime();
2705 UChar TMP[4] = {0, 0, 0, 0};
2706 int32_t index = 0;
2707 int32_t resLen = 0;
2708 UnicodeString tempStr, resultStr;
2709
2710 // Cycle through historical currencies
2711 date = (UDate)-630720000000.0; // pre 1961 - no currency defined
2712 index = ucurr_countCurrencies("eo_AM", date, &status);
2713 if (index != 0)
2714 {
2715 errcheckln(status, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status));
2716 }
2717 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2718 if (resLen != 0) {
2719 errcheckln(status, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status));
2720 }
2721 status = U_ZERO_ERROR;
2722
2723 date = (UDate)0.0; // 1970 - one currency defined
2724 index = ucurr_countCurrencies("eo_AM", date, &status);
2725 if (index != 1)
2726 {
2727 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
2728 }
2729 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2730 tempStr.setTo(TMP);
2731 resultStr.setTo("SUR");
2732 if (resultStr != tempStr) {
2733 errcheckln(status, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status));
2734 }
2735
2736 date = (UDate)693792000000.0; // 1992 - one currency defined
2737 index = ucurr_countCurrencies("eo_AM", date, &status);
2738 if (index != 1)
2739 {
2740 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
2741 }
2742 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2743 tempStr.setTo(TMP);
2744 resultStr.setTo("RUR");
2745 if (resultStr != tempStr) {
2746 errcheckln(status, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status));
2747 }
2748
2749 date = (UDate)977616000000.0; // post 1993 - one currency defined
2750 index = ucurr_countCurrencies("eo_AM", date, &status);
2751 if (index != 1)
2752 {
2753 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
2754 }
2755 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2756 tempStr.setTo(TMP);
2757 resultStr.setTo("AMD");
2758 if (resultStr != tempStr) {
2759 errcheckln(status, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status));
2760 }
2761
2762 // Locale AD has multiple currencies at once
2763 date = (UDate)977616000000.0; // year 2001
2764 index = ucurr_countCurrencies("eo_AD", date, &status);
2765 if (index != 4)
2766 {
2767 errcheckln(status, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status));
2768 }
2769 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2770 tempStr.setTo(TMP);
2771 resultStr.setTo("EUR");
2772 if (resultStr != tempStr) {
2773 errcheckln(status, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status));
2774 }
2775 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2776 tempStr.setTo(TMP);
2777 resultStr.setTo("ESP");
2778 if (resultStr != tempStr) {
2779 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
2780 }
2781 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
2782 tempStr.setTo(TMP);
2783 resultStr.setTo("FRF");
2784 if (resultStr != tempStr) {
2785 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
2786 }
2787 resLen = ucurr_forLocaleAndDate("eo_AD", date, 4, TMP, 4, &status);
2788 tempStr.setTo(TMP);
2789 resultStr.setTo("ADP");
2790 if (resultStr != tempStr) {
2791 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
2792 }
2793
2794 date = (UDate)0.0; // year 1970
2795 index = ucurr_countCurrencies("eo_AD", date, &status);
2796 if (index != 3)
2797 {
2798 errcheckln(status, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status));
2799 }
2800 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2801 tempStr.setTo(TMP);
2802 resultStr.setTo("ESP");
2803 if (resultStr != tempStr) {
2804 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
2805 }
2806 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2807 tempStr.setTo(TMP);
2808 resultStr.setTo("FRF");
2809 if (resultStr != tempStr) {
2810 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
2811 }
2812 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
2813 tempStr.setTo(TMP);
2814 resultStr.setTo("ADP");
2815 if (resultStr != tempStr) {
2816 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
2817 }
2818
2819 date = (UDate)-630720000000.0; // year 1950
2820 index = ucurr_countCurrencies("eo_AD", date, &status);
2821 if (index != 2)
2822 {
2823 errcheckln(status, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status));
2824 }
2825 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2826 tempStr.setTo(TMP);
2827 resultStr.setTo("ESP");
2828 if (resultStr != tempStr) {
2829 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
2830 }
2831 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2832 tempStr.setTo(TMP);
2833 resultStr.setTo("ADP");
2834 if (resultStr != tempStr) {
2835 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
2836 }
2837
2838 date = (UDate)-2207520000000.0; // year 1900
2839 index = ucurr_countCurrencies("eo_AD", date, &status);
2840 if (index != 1)
2841 {
2842 errcheckln(status, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status));
2843 }
2844 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2845 tempStr.setTo(TMP);
2846 resultStr.setTo("ESP");
2847 if (resultStr != tempStr) {
2848 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
2849 }
2850
2851 // Locale UA has gap between years 1994 - 1996
2852 date = (UDate)788400000000.0;
2853 index = ucurr_countCurrencies("eo_UA", date, &status);
2854 if (index != 0)
2855 {
2856 errcheckln(status, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status));
2857 }
2858 resLen = ucurr_forLocaleAndDate("eo_UA", date, index, TMP, 4, &status);
2859 if (resLen != 0) {
2860 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
2861 }
2862 status = U_ZERO_ERROR;
2863
2864 // Test index bounds
2865 resLen = ucurr_forLocaleAndDate("eo_UA", date, 100, TMP, 4, &status);
2866 if (resLen != 0) {
2867 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
2868 }
2869 status = U_ZERO_ERROR;
2870
2871 resLen = ucurr_forLocaleAndDate("eo_UA", date, 0, TMP, 4, &status);
2872 if (resLen != 0) {
2873 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
2874 }
2875 status = U_ZERO_ERROR;
2876
2877 // Test for bogus locale
2878 index = ucurr_countCurrencies("eo_QQ", date, &status);
2879 if (index != 0)
2880 {
2881 errcheckln(status, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status));
2882 }
2883 status = U_ZERO_ERROR;
2884 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 1, TMP, 4, &status);
2885 if (resLen != 0) {
2886 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
2887 }
2888 status = U_ZERO_ERROR;
2889 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 0, TMP, 4, &status);
2890 if (resLen != 0) {
2891 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
2892 }
2893 status = U_ZERO_ERROR;
2894
2895 // Cycle through histrocial currencies
2896 date = (UDate)977616000000.0; // 2001 - one currency
2897 index = ucurr_countCurrencies("eo_AO", date, &status);
2898 if (index != 1)
2899 {
2900 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
2901 }
2902 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2903 tempStr.setTo(TMP);
2904 resultStr.setTo("AOA");
2905 if (resultStr != tempStr) {
2906 errcheckln(status, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status));
2907 }
2908
2909 date = (UDate)819936000000.0; // 1996 - 2 currencies
2910 index = ucurr_countCurrencies("eo_AO", date, &status);
2911 if (index != 2)
2912 {
2913 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
2914 }
2915 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2916 tempStr.setTo(TMP);
2917 resultStr.setTo("AOR");
2918 if (resultStr != tempStr) {
2919 errcheckln(status, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status));
2920 }
2921 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
2922 tempStr.setTo(TMP);
2923 resultStr.setTo("AON");
2924 if (resultStr != tempStr) {
2925 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
2926 }
2927
2928 date = (UDate)662256000000.0; // 1991 - 2 currencies
2929 index = ucurr_countCurrencies("eo_AO", date, &status);
2930 if (index != 2)
2931 {
2932 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
2933 }
2934 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2935 tempStr.setTo(TMP);
2936 resultStr.setTo("AON");
2937 if (resultStr != tempStr) {
2938 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
2939 }
2940 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
2941 tempStr.setTo(TMP);
2942 resultStr.setTo("AOK");
2943 if (resultStr != tempStr) {
2944 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
2945 }
2946
2947 date = (UDate)315360000000.0; // 1980 - one currency
2948 index = ucurr_countCurrencies("eo_AO", date, &status);
2949 if (index != 1)
2950 {
2951 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
2952 }
2953 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2954 tempStr.setTo(TMP);
2955 resultStr.setTo("AOK");
2956 if (resultStr != tempStr) {
2957 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
2958 }
2959
2960 date = (UDate)0.0; // 1970 - no currencies
2961 index = ucurr_countCurrencies("eo_AO", date, &status);
2962 if (index != 0)
2963 {
2964 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
2965 }
2966 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2967 if (resLen != 0) {
2968 errcheckln(status, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status));
2969 }
2970 status = U_ZERO_ERROR;
2971
2972 // Test with currency keyword override
2973 date = (UDate)977616000000.0; // 2001 - two currencies
2974 index = ucurr_countCurrencies("eo_DE@currency=DEM", date, &status);
2975 if (index != 2)
2976 {
2977 errcheckln(status, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status));
2978 }
2979 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 1, TMP, 4, &status);
2980 tempStr.setTo(TMP);
2981 resultStr.setTo("EUR");
2982 if (resultStr != tempStr) {
2983 errcheckln(status, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status));
2984 }
2985 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 2, TMP, 4, &status);
2986 tempStr.setTo(TMP);
2987 resultStr.setTo("DEM");
2988 if (resultStr != tempStr) {
2989 errcheckln(status, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status));
2990 }
2991
2992 // Test Euro Support
2993 status = U_ZERO_ERROR; // reset
2994 date = uprv_getUTCtime();
2995
2996 UChar USD[4];
2997 ucurr_forLocaleAndDate("en_US", date, 1, USD, 4, &status);
2998
2999 UChar YEN[4];
3000 ucurr_forLocaleAndDate("ja_JP", date, 1, YEN, 4, &status);
3001
3002 ucurr_forLocaleAndDate("en_US", date, 1, TMP, 4, &status);
3003 if (u_strcmp(USD, TMP) != 0) {
3004 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
3005 }
3006 ucurr_forLocaleAndDate("en_US_Q", date, 1, TMP, 4, &status);
3007 if (u_strcmp(USD, TMP) != 0) {
3008 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
3009 }
3010 status = U_ZERO_ERROR; // reset
3011 #endif
3012 }
3013
TestGetVariantWithKeywords(void)3014 void LocaleTest::TestGetVariantWithKeywords(void)
3015 {
3016 Locale l("en_US_VALLEY@foo=value");
3017 const char *variant = l.getVariant();
3018 logln(variant);
3019 test_assert(strcmp("VALLEY", variant) == 0);
3020
3021 UErrorCode status = U_ZERO_ERROR;
3022 char buffer[50];
3023 int32_t len = l.getKeywordValue("foo", buffer, 50, status);
3024 buffer[len] = '\0';
3025 test_assert(strcmp("value", buffer) == 0);
3026 }
3027
TestIsRightToLeft()3028 void LocaleTest::TestIsRightToLeft() {
3029 assertFalse("root LTR", Locale::getRoot().isRightToLeft());
3030 assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
3031 assertTrue("ar RTL", Locale("ar").isRightToLeft());
3032 assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), FALSE, TRUE);
3033 assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
3034 assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
3035 assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), FALSE, TRUE); // Sorani Kurdish
3036 assertFalse("fil LTR", Locale("fil").isRightToLeft());
3037 assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
3038 }
3039
TestBug11421()3040 void LocaleTest::TestBug11421() {
3041 Locale::getDefault().getBaseName();
3042 int32_t numLocales;
3043 const Locale *localeList = Locale::getAvailableLocales(numLocales);
3044 for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) {
3045 const Locale &loc = localeList[localeIndex];
3046 if (strncmp(loc.getName(), loc.getBaseName(), strlen(loc.getBaseName()))) {
3047 errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"",
3048 __FILE__, __LINE__, loc.getName(), loc.getBaseName());
3049 break;
3050 }
3051 }
3052 }
3053
3054 // TestBug13277. The failure manifests as valgrind errors.
3055 // See the trac ticket for details.
3056 //
3057
TestBug13277()3058 void LocaleTest::TestBug13277() {
3059 UErrorCode status = U_ZERO_ERROR;
3060 CharString name("en-us-x-foo", -1, status);
3061 while (name.length() < 152) {
3062 name.append("-x-foo", -1, status);
3063 }
3064
3065 while (name.length() < 160) {
3066 name.append('z', status);
3067 Locale loc(name.data(), nullptr, nullptr, nullptr);
3068 }
3069 }
3070
3071 // TestBug13554 Check for read past end of array in getPosixID().
3072 // The bug shows as an Address Sanitizer failure.
3073
TestBug13554()3074 void LocaleTest::TestBug13554() {
3075 UErrorCode status = U_ZERO_ERROR;
3076 const int BUFFER_SIZE = 100;
3077 char posixID[BUFFER_SIZE];
3078
3079 for (uint32_t hostid = 0; hostid < 0x500; ++hostid) {
3080 status = U_ZERO_ERROR;
3081 uprv_convertToPosix(hostid, posixID, BUFFER_SIZE, &status);
3082 }
3083 }
3084
TestBug20410()3085 void LocaleTest::TestBug20410() {
3086 IcuTestErrorCode status(*this, "TestBug20410()");
3087
3088 static const char tag1[] = "art-lojban-x-0";
3089 static const Locale expected1("jbo@x=0");
3090 Locale result1 = Locale::forLanguageTag(tag1, status);
3091 status.errIfFailureAndReset("\"%s\"", tag1);
3092 assertEquals(tag1, expected1.getName(), result1.getName());
3093
3094 static const char tag2[] = "zh-xiang-u-nu-thai-x-0";
3095 static const Locale expected2("hsn@numbers=thai;x=0");
3096 Locale result2 = Locale::forLanguageTag(tag2, status);
3097 status.errIfFailureAndReset("\"%s\"", tag2);
3098 assertEquals(tag2, expected2.getName(), result2.getName());
3099
3100 static const char locid3[] = "art__lojban@x=0";
3101 Locale result3 = Locale::createCanonical(locid3);
3102 static const Locale expected3("art__LOJBAN@x=0");
3103 assertEquals(locid3, expected3.getName(), result3.getName());
3104
3105 static const char locid4[] = "art-lojban-x-0";
3106 Locale result4 = Locale::createCanonical(locid4);
3107 static const Locale expected4("jbo@x=0");
3108 assertEquals(locid4, expected4.getName(), result4.getName());
3109 }
3110
TestConstructorAcceptsBCP47()3111 void LocaleTest::TestConstructorAcceptsBCP47() {
3112 IcuTestErrorCode status(*this, "TestConstructorAcceptsBCP47");
3113
3114 Locale loc1("ar-EG-u-nu-latn");
3115 Locale loc2("ar-EG@numbers=latn");
3116 Locale loc3("ar-EG");
3117 std::string val;
3118
3119 // Check getKeywordValue "numbers"
3120 val = loc1.getKeywordValue<std::string>("numbers", status);
3121 assertEquals("BCP47 syntax has ICU keyword value", "latn", val.c_str());
3122
3123 val = loc2.getKeywordValue<std::string>("numbers", status);
3124 assertEquals("ICU syntax has ICU keyword value", "latn", val.c_str());
3125
3126 val = loc3.getKeywordValue<std::string>("numbers", status);
3127 assertEquals("Default, ICU keyword", "", val.c_str());
3128
3129 // Check getUnicodeKeywordValue "nu"
3130 val = loc1.getUnicodeKeywordValue<std::string>("nu", status);
3131 assertEquals("BCP47 syntax has short unicode keyword value", "latn", val.c_str());
3132
3133 val = loc2.getUnicodeKeywordValue<std::string>("nu", status);
3134 assertEquals("ICU syntax has short unicode keyword value", "latn", val.c_str());
3135
3136 val = loc3.getUnicodeKeywordValue<std::string>("nu", status);
3137 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, short unicode keyword");
3138
3139 // Check getUnicodeKeywordValue "numbers"
3140 val = loc1.getUnicodeKeywordValue<std::string>("numbers", status);
3141 assertEquals("BCP47 syntax has long unicode keyword value", "latn", val.c_str());
3142
3143 val = loc2.getUnicodeKeywordValue<std::string>("numbers", status);
3144 assertEquals("ICU syntax has long unicode keyword value", "latn", val.c_str());
3145
3146 val = loc3.getUnicodeKeywordValue<std::string>("numbers", status);
3147 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, long unicode keyword");
3148 }
3149
TestForLanguageTag()3150 void LocaleTest::TestForLanguageTag() {
3151 IcuTestErrorCode status(*this, "TestForLanguageTag()");
3152
3153 static const char tag_en[] = "en-US";
3154 static const char tag_oed[] = "en-GB-oed";
3155 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
3156 static const char tag_ill[] = "!";
3157 static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' };
3158 static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz";
3159
3160 static const Locale loc_en("en_US");
3161 static const Locale loc_oed("en_GB_OXENDICT");
3162 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
3163 static const Locale loc_null("");
3164 static const Locale loc_gb("en_GB");
3165 static const Locale loc_ext("en_GB@1=abc-efg;a=xyz");
3166
3167 Locale result_en = Locale::forLanguageTag(tag_en, status);
3168 status.errIfFailureAndReset("\"%s\"", tag_en);
3169 assertEquals(tag_en, loc_en.getName(), result_en.getName());
3170
3171 Locale result_oed = Locale::forLanguageTag(tag_oed, status);
3172 status.errIfFailureAndReset("\"%s\"", tag_oed);
3173 assertEquals(tag_oed, loc_oed.getName(), result_oed.getName());
3174
3175 Locale result_af = Locale::forLanguageTag(tag_af, status);
3176 status.errIfFailureAndReset("\"%s\"", tag_af);
3177 assertEquals(tag_af, loc_af.getName(), result_af.getName());
3178
3179 Locale result_ill = Locale::forLanguageTag(tag_ill, status);
3180 assertEquals(tag_ill, U_ILLEGAL_ARGUMENT_ERROR, status.reset());
3181 assertTrue(result_ill.getName(), result_ill.isBogus());
3182
3183 Locale result_null = Locale::forLanguageTag(nullptr, status);
3184 status.errIfFailureAndReset("nullptr");
3185 assertEquals("nullptr", loc_null.getName(), result_null.getName());
3186
3187 StringPiece sp_substr(tag_oed, 5); // "en-GB", no NUL.
3188 Locale result_substr = Locale::forLanguageTag(sp_substr, status);
3189 status.errIfFailureAndReset("\"%.*s\"", sp_substr.size(), sp_substr.data());
3190 assertEquals(CharString(sp_substr, status).data(),
3191 loc_gb.getName(), result_substr.getName());
3192
3193 StringPiece sp_no_nul(tag_no_nul, sizeof tag_no_nul); // "en-GB", no NUL.
3194 Locale result_no_nul = Locale::forLanguageTag(sp_no_nul, status);
3195 status.errIfFailureAndReset("\"%.*s\"", sp_no_nul.size(), sp_no_nul.data());
3196 assertEquals(CharString(sp_no_nul, status).data(),
3197 loc_gb.getName(), result_no_nul.getName());
3198
3199 Locale result_ext = Locale::forLanguageTag(tag_ext, status);
3200 status.errIfFailureAndReset("\"%s\"", tag_ext);
3201 assertEquals(tag_ext, loc_ext.getName(), result_ext.getName());
3202 }
3203
TestToLanguageTag()3204 void LocaleTest::TestToLanguageTag() {
3205 IcuTestErrorCode status(*this, "TestToLanguageTag()");
3206
3207 static const Locale loc_c("en_US_POSIX");
3208 static const Locale loc_en("en_US");
3209 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
3210 static const Locale loc_ext("en@0=abc;a=xyz");
3211 static const Locale loc_empty("");
3212 static const Locale loc_ill("!");
3213
3214 static const char tag_c[] = "en-US-u-va-posix";
3215 static const char tag_en[] = "en-US";
3216 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
3217 static const char tag_ext[] = "en-0-abc-a-xyz";
3218 static const char tag_und[] = "und";
3219
3220 std::string result;
3221 StringByteSink<std::string> sink(&result);
3222 loc_c.toLanguageTag(sink, status);
3223 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
3224 assertEquals(loc_c.getName(), tag_c, result.c_str());
3225
3226 std::string result_c = loc_c.toLanguageTag<std::string>(status);
3227 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
3228 assertEquals(loc_c.getName(), tag_c, result_c.c_str());
3229
3230 std::string result_en = loc_en.toLanguageTag<std::string>(status);
3231 status.errIfFailureAndReset("\"%s\"", loc_en.getName());
3232 assertEquals(loc_en.getName(), tag_en, result_en.c_str());
3233
3234 std::string result_af = loc_af.toLanguageTag<std::string>(status);
3235 status.errIfFailureAndReset("\"%s\"", loc_af.getName());
3236 assertEquals(loc_af.getName(), tag_af, result_af.c_str());
3237
3238 std::string result_ext = loc_ext.toLanguageTag<std::string>(status);
3239 status.errIfFailureAndReset("\"%s\"", loc_ext.getName());
3240 assertEquals(loc_ext.getName(), tag_ext, result_ext.c_str());
3241
3242 std::string result_empty = loc_empty.toLanguageTag<std::string>(status);
3243 status.errIfFailureAndReset("\"%s\"", loc_empty.getName());
3244 assertEquals(loc_empty.getName(), tag_und, result_empty.c_str());
3245
3246 std::string result_ill = loc_ill.toLanguageTag<std::string>(status);
3247 status.errIfFailureAndReset("\"%s\"", loc_ill.getName());
3248 assertEquals(loc_ill.getName(), tag_und, result_ill.c_str());
3249
3250 Locale loc_bogus;
3251 loc_bogus.setToBogus();
3252 std::string result_bogus = loc_bogus.toLanguageTag<std::string>(status);
3253 assertEquals("bogus", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
3254 assertTrue(result_bogus.c_str(), result_bogus.empty());
3255 }
3256
TestMoveAssign()3257 void LocaleTest::TestMoveAssign() {
3258 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
3259 Locale l1("de@collation=phonebook;x="
3260 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3261 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3262 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3263 "aaaaabbbbbzz");
3264
3265 Locale l2;
3266 {
3267 Locale l3(l1);
3268 assertTrue("l1 == l3", l1 == l3);
3269 l2 = std::move(l3);
3270 assertTrue("l1 == l2", l1 == l2);
3271 assertTrue("l2 != l3", l2.getName() != l3.getName());
3272 }
3273
3274 // This should remain true also after l3 has been destructed.
3275 assertTrue("l1 == l2, again", l1 == l2);
3276
3277 Locale l4("de@collation=phonebook");
3278
3279 Locale l5;
3280 {
3281 Locale l6(l4);
3282 assertTrue("l4 == l6", l4 == l6);
3283 l5 = std::move(l6);
3284 assertTrue("l4 == l5", l4 == l5);
3285 assertTrue("l5 != l6", l5.getName() != l6.getName());
3286 }
3287
3288 // This should remain true also after l6 has been destructed.
3289 assertTrue("l4 == l5, again", l4 == l5);
3290
3291 Locale l7("vo_Cyrl_AQ_EURO");
3292
3293 Locale l8;
3294 {
3295 Locale l9(l7);
3296 assertTrue("l7 == l9", l7 == l9);
3297 l8 = std::move(l9);
3298 assertTrue("l7 == l8", l7 == l8);
3299 assertTrue("l8 != l9", l8.getName() != l9.getName());
3300 }
3301
3302 // This should remain true also after l9 has been destructed.
3303 assertTrue("l7 == l8, again", l7 == l8);
3304
3305 assertEquals("language", l7.getLanguage(), l8.getLanguage());
3306 assertEquals("script", l7.getScript(), l8.getScript());
3307 assertEquals("country", l7.getCountry(), l8.getCountry());
3308 assertEquals("variant", l7.getVariant(), l8.getVariant());
3309 assertEquals("bogus", l7.isBogus(), l8.isBogus());
3310 }
3311
TestMoveCtor()3312 void LocaleTest::TestMoveCtor() {
3313 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
3314 Locale l1("de@collation=phonebook;x="
3315 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3316 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3317 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3318 "aaaaabbbbbzz");
3319
3320 Locale l3(l1);
3321 assertTrue("l1 == l3", l1 == l3);
3322 Locale l2(std::move(l3));
3323 assertTrue("l1 == l2", l1 == l2);
3324 assertTrue("l2 != l3", l2.getName() != l3.getName());
3325
3326 Locale l4("de@collation=phonebook");
3327
3328 Locale l6(l4);
3329 assertTrue("l4 == l6", l4 == l6);
3330 Locale l5(std::move(l6));
3331 assertTrue("l4 == l5", l4 == l5);
3332 assertTrue("l5 != l6", l5.getName() != l6.getName());
3333
3334 Locale l7("vo_Cyrl_AQ_EURO");
3335
3336 Locale l9(l7);
3337 assertTrue("l7 == l9", l7 == l9);
3338 Locale l8(std::move(l9));
3339 assertTrue("l7 == l8", l7 == l8);
3340 assertTrue("l8 != l9", l8.getName() != l9.getName());
3341
3342 assertEquals("language", l7.getLanguage(), l8.getLanguage());
3343 assertEquals("script", l7.getScript(), l8.getScript());
3344 assertEquals("country", l7.getCountry(), l8.getCountry());
3345 assertEquals("variant", l7.getVariant(), l8.getVariant());
3346 assertEquals("bogus", l7.isBogus(), l8.isBogus());
3347 }
3348
TestBug20407iVariantPreferredValue()3349 void LocaleTest::TestBug20407iVariantPreferredValue() {
3350 IcuTestErrorCode status(*this, "TestBug20407iVariantPreferredValue()");
3351
3352 Locale l = Locale::forLanguageTag("hy-arevela", status);
3353 status.errIfFailureAndReset("hy-arevela fail");
3354 assertTrue("!l.isBogus()", !l.isBogus());
3355
3356 std::string result = l.toLanguageTag<std::string>(status);
3357 assertEquals(l.getName(), "hy", result.c_str());
3358
3359 l = Locale::forLanguageTag("hy-arevmda", status);
3360 status.errIfFailureAndReset("hy-arevmda");
3361 assertTrue("!l.isBogus()", !l.isBogus());
3362
3363 result = l.toLanguageTag<std::string>(status);
3364 assertEquals(l.getName(), "hyw", result.c_str());
3365 }
3366
TestBug13417VeryLongLanguageTag()3367 void LocaleTest::TestBug13417VeryLongLanguageTag() {
3368 IcuTestErrorCode status(*this, "TestBug13417VeryLongLanguageTag()");
3369
3370 static const char tag[] =
3371 "zh-x"
3372 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3373 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3374 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3375 "-foo-bar-baz-fxx"
3376 ;
3377
3378 Locale l = Locale::forLanguageTag(tag, status);
3379 status.errIfFailureAndReset("\"%s\"", tag);
3380 assertTrue("!l.isBogus()", !l.isBogus());
3381
3382 std::string result = l.toLanguageTag<std::string>(status);
3383 status.errIfFailureAndReset("\"%s\"", l.getName());
3384 assertEquals("equals", tag, result.c_str());
3385 }
3386
TestBug11053UnderlineTimeZone()3387 void LocaleTest::TestBug11053UnderlineTimeZone() {
3388 static const char* const tz_in_ext[] = {
3389 "etadd",
3390 "tzdar",
3391 "eheai",
3392 "sttms",
3393 "arirj",
3394 "arrgl",
3395 "aruaq",
3396 "arluq",
3397 "mxpvr",
3398 "brbvb",
3399 "arbue",
3400 "caycb",
3401 "brcgr",
3402 "cayzs",
3403 "crsjo",
3404 "caydq",
3405 "svsal",
3406 "cafne",
3407 "caglb",
3408 "cagoo",
3409 "tcgdt",
3410 "ustel",
3411 "bolpb",
3412 "uslax",
3413 "sxphi",
3414 "mxmex",
3415 "usnyc",
3416 "usxul",
3417 "usndcnt",
3418 "usndnsl",
3419 "ttpos",
3420 "brpvh",
3421 "prsju",
3422 "clpuq",
3423 "caffs",
3424 "cayek",
3425 "brrbr",
3426 "mxstis",
3427 "dosdq",
3428 "brsao",
3429 "gpsbh",
3430 "casjf",
3431 "knbas",
3432 "lccas",
3433 "vistt",
3434 "vcsvd",
3435 "cayyn",
3436 "cathu",
3437 "hkhkg",
3438 "mykul",
3439 "khpnh",
3440 "cvrai",
3441 "gsgrv",
3442 "shshn",
3443 "aubhq",
3444 "auldh",
3445 "imdgs",
3446 "smsai",
3447 "asppg",
3448 "pgpom",
3449 };
3450 static const char* const tzname_with_underline[] = {
3451 "America/Buenos_Aires",
3452 "America/Coral_Harbour",
3453 "America/Los_Angeles",
3454 "America/Mexico_City",
3455 "America/New_York",
3456 "America/Rio_Branco",
3457 "America/Sao_Paulo",
3458 "America/St_Johns",
3459 "America/St_Thomas",
3460 "Australia/Broken_Hill",
3461 "Australia/Lord_Howe",
3462 "Pacific/Pago_Pago",
3463 };
3464 std::string locale_str;
3465 for (int32_t i = 0; i < UPRV_LENGTHOF(tz_in_ext); i++) {
3466 locale_str = "en-u-tz-";
3467 locale_str += tz_in_ext[i];
3468 Locale l(locale_str.c_str());
3469 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
3470 }
3471 for (int32_t i = 0; i < UPRV_LENGTHOF(tzname_with_underline); i++) {
3472 locale_str = "en@timezone=";
3473 locale_str += tzname_with_underline[i];
3474 Locale l(locale_str.c_str());
3475 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
3476 }
3477 locale_str = "en_US@timezone=America/Coral_Harbour";
3478 Locale l2(locale_str.c_str());
3479 assertTrue((locale_str + " !l2.isBogus()").c_str(), !l2.isBogus());
3480 locale_str = "en_Latn@timezone=America/New_York";
3481 Locale l3(locale_str.c_str());
3482 assertTrue((locale_str + " !l3.isBogus()").c_str(), !l3.isBogus());
3483 locale_str = "en_Latn_US@timezone=Australia/Broken_Hill";
3484 Locale l4(locale_str.c_str());
3485 assertTrue((locale_str + " !l4.isBogus()").c_str(), !l4.isBogus());
3486 locale_str = "en-u-tz-ciabj";
3487 Locale l5(locale_str.c_str());
3488 assertTrue((locale_str + " !l5.isBogus()").c_str(), !l5.isBogus());
3489 locale_str = "en-US-u-tz-asppg";
3490 Locale l6(locale_str.c_str());
3491 assertTrue((locale_str + " !l6.isBogus()").c_str(), !l6.isBogus());
3492 locale_str = "fil-Latn-u-tz-cvrai";
3493 Locale l7(locale_str.c_str());
3494 assertTrue((locale_str + " !l7.isBogus()").c_str(), !l7.isBogus());
3495 locale_str = "fil-Latn-PH-u-tz-gsgrv";
3496 Locale l8(locale_str.c_str());
3497 assertTrue((locale_str + " !l8.isBogus()").c_str(), !l8.isBogus());
3498 }
3499
TestUnd()3500 void LocaleTest::TestUnd() {
3501 IcuTestErrorCode status(*this, "TestUnd()");
3502
3503 static const char empty[] = "";
3504 static const char root[] = "root";
3505 static const char und[] = "und";
3506
3507 Locale empty_ctor(empty);
3508 Locale empty_tag = Locale::forLanguageTag(empty, status);
3509 status.errIfFailureAndReset("\"%s\"", empty);
3510
3511 Locale root_ctor(root);
3512 Locale root_tag = Locale::forLanguageTag(root, status);
3513 Locale root_build = LocaleBuilder().setLanguageTag(root).build(status);
3514 status.errIfFailureAndReset("\"%s\"", root);
3515
3516 Locale und_ctor(und);
3517 Locale und_tag = Locale::forLanguageTag(und, status);
3518 Locale und_build = LocaleBuilder().setLanguageTag(und).build(status);
3519 status.errIfFailureAndReset("\"%s\"", und);
3520
3521 assertEquals("getName()", empty, empty_ctor.getName());
3522 assertEquals("getName()", empty, root_ctor.getName());
3523 assertEquals("getName()", empty, und_ctor.getName());
3524
3525 assertEquals("getName()", empty, empty_tag.getName());
3526 assertEquals("getName()", empty, root_tag.getName());
3527 assertEquals("getName()", empty, und_tag.getName());
3528
3529 assertEquals("getName()", empty, root_build.getName());
3530 assertEquals("getName()", empty, und_build.getName());
3531
3532 assertEquals("toLanguageTag()", und, empty_ctor.toLanguageTag<std::string>(status).c_str());
3533 assertEquals("toLanguageTag()", und, root_ctor.toLanguageTag<std::string>(status).c_str());
3534 assertEquals("toLanguageTag()", und, und_ctor.toLanguageTag<std::string>(status).c_str());
3535 status.errIfFailureAndReset();
3536
3537 assertEquals("toLanguageTag()", und, empty_tag.toLanguageTag<std::string>(status).c_str());
3538 assertEquals("toLanguageTag()", und, root_tag.toLanguageTag<std::string>(status).c_str());
3539 assertEquals("toLanguageTag()", und, und_tag.toLanguageTag<std::string>(status).c_str());
3540 status.errIfFailureAndReset();
3541
3542 assertEquals("toLanguageTag()", und, root_build.toLanguageTag<std::string>(status).c_str());
3543 assertEquals("toLanguageTag()", und, und_build.toLanguageTag<std::string>(status).c_str());
3544 status.errIfFailureAndReset();
3545
3546 assertTrue("empty_ctor == empty_tag", empty_ctor == empty_tag);
3547
3548 assertTrue("root_ctor == root_tag", root_ctor == root_tag);
3549 assertTrue("root_ctor == root_build", root_ctor == root_build);
3550 assertTrue("root_tag == root_build", root_tag == root_build);
3551
3552 assertTrue("und_ctor == und_tag", und_ctor == und_tag);
3553 assertTrue("und_ctor == und_build", und_ctor == und_build);
3554 assertTrue("und_tag == und_build", und_tag == und_build);
3555
3556 assertTrue("empty_ctor == root_ctor", empty_ctor == root_ctor);
3557 assertTrue("empty_ctor == und_ctor", empty_ctor == und_ctor);
3558 assertTrue("root_ctor == und_ctor", root_ctor == und_ctor);
3559
3560 assertTrue("empty_tag == root_tag", empty_tag == root_tag);
3561 assertTrue("empty_tag == und_tag", empty_tag == und_tag);
3562 assertTrue("root_tag == und_tag", root_tag == und_tag);
3563
3564 assertTrue("root_build == und_build", root_build == und_build);
3565
3566 static const Locale& displayLocale = Locale::getEnglish();
3567 static const UnicodeString displayName("Unknown language");
3568 UnicodeString tmp;
3569
3570 assertEquals("getDisplayName()", displayName, empty_ctor.getDisplayName(displayLocale, tmp));
3571 assertEquals("getDisplayName()", displayName, root_ctor.getDisplayName(displayLocale, tmp));
3572 assertEquals("getDisplayName()", displayName, und_ctor.getDisplayName(displayLocale, tmp));
3573
3574 assertEquals("getDisplayName()", displayName, empty_tag.getDisplayName(displayLocale, tmp));
3575 assertEquals("getDisplayName()", displayName, root_tag.getDisplayName(displayLocale, tmp));
3576 assertEquals("getDisplayName()", displayName, und_tag.getDisplayName(displayLocale, tmp));
3577
3578 assertEquals("getDisplayName()", displayName, root_build.getDisplayName(displayLocale, tmp));
3579 assertEquals("getDisplayName()", displayName, und_build.getDisplayName(displayLocale, tmp));
3580 }
3581
TestUndScript()3582 void LocaleTest::TestUndScript() {
3583 IcuTestErrorCode status(*this, "TestUndScript()");
3584
3585 static const char id[] = "_Cyrl";
3586 static const char tag[] = "und-Cyrl";
3587 static const char script[] = "Cyrl";
3588
3589 Locale locale_ctor(id);
3590 Locale locale_legacy(tag);
3591 Locale locale_tag = Locale::forLanguageTag(tag, status);
3592 Locale locale_build = LocaleBuilder().setScript(script).build(status);
3593 status.errIfFailureAndReset("\"%s\"", tag);
3594
3595 assertEquals("getName()", id, locale_ctor.getName());
3596 assertEquals("getName()", id, locale_legacy.getName());
3597 assertEquals("getName()", id, locale_tag.getName());
3598 assertEquals("getName()", id, locale_build.getName());
3599
3600 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
3601 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
3602 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
3603 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
3604 status.errIfFailureAndReset();
3605
3606 static const Locale& displayLocale = Locale::getEnglish();
3607 static const UnicodeString displayName("Unknown language (Cyrillic)");
3608 UnicodeString tmp;
3609
3610 assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp));
3611 assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
3612 assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp));
3613 assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp));
3614 }
3615
TestUndRegion()3616 void LocaleTest::TestUndRegion() {
3617 IcuTestErrorCode status(*this, "TestUndRegion()");
3618
3619 static const char id[] = "_AQ";
3620 static const char tag[] = "und-AQ";
3621 static const char region[] = "AQ";
3622
3623 Locale locale_ctor(id);
3624 Locale locale_legacy(tag);
3625 Locale locale_tag = Locale::forLanguageTag(tag, status);
3626 Locale locale_build = LocaleBuilder().setRegion(region).build(status);
3627 status.errIfFailureAndReset("\"%s\"", tag);
3628
3629 assertEquals("getName()", id, locale_ctor.getName());
3630 assertEquals("getName()", id, locale_legacy.getName());
3631 assertEquals("getName()", id, locale_tag.getName());
3632 assertEquals("getName()", id, locale_build.getName());
3633
3634 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
3635 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
3636 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
3637 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
3638 status.errIfFailureAndReset();
3639
3640 static const Locale& displayLocale = Locale::getEnglish();
3641 static const UnicodeString displayName("Unknown language (Antarctica)");
3642 UnicodeString tmp;
3643
3644 assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp));
3645 assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
3646 assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp));
3647 assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp));
3648 }
3649
TestUndCAPI()3650 void LocaleTest::TestUndCAPI() {
3651 IcuTestErrorCode status(*this, "TestUndCAPI()");
3652
3653 static const char empty[] = "";
3654 static const char root[] = "root";
3655 static const char und[] = "und";
3656
3657 static const char empty_script[] = "_Cyrl";
3658 static const char empty_region[] = "_AQ";
3659
3660 static const char und_script[] = "und_Cyrl";
3661 static const char und_region[] = "und_AQ";
3662
3663 char tmp[ULOC_FULLNAME_CAPACITY];
3664 int32_t reslen;
3665
3666 // uloc_getName()
3667
3668 uprv_memset(tmp, '!', sizeof tmp);
3669 reslen = uloc_getName(empty, tmp, sizeof tmp, status);
3670 status.errIfFailureAndReset("\"%s\"", empty);
3671 assertTrue("reslen >= 0", reslen >= 0);
3672 assertEquals("uloc_getName()", empty, tmp);
3673
3674 uprv_memset(tmp, '!', sizeof tmp);
3675 reslen = uloc_getName(root, tmp, sizeof tmp, status);
3676 status.errIfFailureAndReset("\"%s\"", root);
3677 assertTrue("reslen >= 0", reslen >= 0);
3678 assertEquals("uloc_getName()", empty, tmp);
3679
3680 uprv_memset(tmp, '!', sizeof tmp);
3681 reslen = uloc_getName(und, tmp, sizeof tmp, status);
3682 status.errIfFailureAndReset("\"%s\"", und);
3683 assertTrue("reslen >= 0", reslen >= 0);
3684 assertEquals("uloc_getName()", empty, tmp);
3685
3686 uprv_memset(tmp, '!', sizeof tmp);
3687 reslen = uloc_getName(empty_script, tmp, sizeof tmp, status);
3688 status.errIfFailureAndReset("\"%s\"", empty_script);
3689 assertTrue("reslen >= 0", reslen >= 0);
3690 assertEquals("uloc_getName()", empty_script, tmp);
3691
3692 uprv_memset(tmp, '!', sizeof tmp);
3693 reslen = uloc_getName(empty_region, tmp, sizeof tmp, status);
3694 status.errIfFailureAndReset("\"%s\"", empty_region);
3695 assertTrue("reslen >= 0", reslen >= 0);
3696 assertEquals("uloc_getName()", empty_region, tmp);
3697
3698 uprv_memset(tmp, '!', sizeof tmp);
3699 reslen = uloc_getName(und_script, tmp, sizeof tmp, status);
3700 status.errIfFailureAndReset("\"%s\"", und_script);
3701 assertTrue("reslen >= 0", reslen >= 0);
3702 assertEquals("uloc_getName()", empty_script, tmp);
3703
3704 uprv_memset(tmp, '!', sizeof tmp);
3705 reslen = uloc_getName(und_region, tmp, sizeof tmp, status);
3706 status.errIfFailureAndReset("\"%s\"", und_region);
3707 assertTrue("reslen >= 0", reslen >= 0);
3708 assertEquals("uloc_getName()", empty_region, tmp);
3709
3710 // uloc_getBaseName()
3711
3712 uprv_memset(tmp, '!', sizeof tmp);
3713 reslen = uloc_getBaseName(empty, tmp, sizeof tmp, status);
3714 status.errIfFailureAndReset("\"%s\"", empty);
3715 assertTrue("reslen >= 0", reslen >= 0);
3716 assertEquals("uloc_getBaseName()", empty, tmp);
3717
3718 uprv_memset(tmp, '!', sizeof tmp);
3719 reslen = uloc_getBaseName(root, tmp, sizeof tmp, status);
3720 status.errIfFailureAndReset("\"%s\"", root);
3721 assertTrue("reslen >= 0", reslen >= 0);
3722 assertEquals("uloc_getBaseName()", empty, tmp);
3723
3724 uprv_memset(tmp, '!', sizeof tmp);
3725 reslen = uloc_getBaseName(und, tmp, sizeof tmp, status);
3726 status.errIfFailureAndReset("\"%s\"", und);
3727 assertTrue("reslen >= 0", reslen >= 0);
3728 assertEquals("uloc_getBaseName()", empty, tmp);
3729
3730 uprv_memset(tmp, '!', sizeof tmp);
3731 reslen = uloc_getBaseName(empty_script, tmp, sizeof tmp, status);
3732 status.errIfFailureAndReset("\"%s\"", empty_script);
3733 assertTrue("reslen >= 0", reslen >= 0);
3734 assertEquals("uloc_getBaseName()", empty_script, tmp);
3735
3736 uprv_memset(tmp, '!', sizeof tmp);
3737 reslen = uloc_getBaseName(empty_region, tmp, sizeof tmp, status);
3738 status.errIfFailureAndReset("\"%s\"", empty_region);
3739 assertTrue("reslen >= 0", reslen >= 0);
3740 assertEquals("uloc_getBaseName()", empty_region, tmp);
3741
3742 uprv_memset(tmp, '!', sizeof tmp);
3743 reslen = uloc_getBaseName(und_script, tmp, sizeof tmp, status);
3744 status.errIfFailureAndReset("\"%s\"", und_script);
3745 assertTrue("reslen >= 0", reslen >= 0);
3746 assertEquals("uloc_getBaseName()", empty_script, tmp);
3747
3748 uprv_memset(tmp, '!', sizeof tmp);
3749 reslen = uloc_getBaseName(und_region, tmp, sizeof tmp, status);
3750 status.errIfFailureAndReset("\"%s\"", und_region);
3751 assertTrue("reslen >= 0", reslen >= 0);
3752 assertEquals("uloc_getBaseName()", empty_region, tmp);
3753
3754 // uloc_getParent()
3755
3756 uprv_memset(tmp, '!', sizeof tmp);
3757 reslen = uloc_getParent(empty, tmp, sizeof tmp, status);
3758 status.errIfFailureAndReset("\"%s\"", empty);
3759 assertTrue("reslen >= 0", reslen >= 0);
3760 assertEquals("uloc_getParent()", empty, tmp);
3761
3762 uprv_memset(tmp, '!', sizeof tmp);
3763 reslen = uloc_getParent(root, tmp, sizeof tmp, status);
3764 status.errIfFailureAndReset("\"%s\"", root);
3765 assertTrue("reslen >= 0", reslen >= 0);
3766 assertEquals("uloc_getParent()", empty, tmp);
3767
3768 uprv_memset(tmp, '!', sizeof tmp);
3769 reslen = uloc_getParent(und, tmp, sizeof tmp, status);
3770 status.errIfFailureAndReset("\"%s\"", und);
3771 assertTrue("reslen >= 0", reslen >= 0);
3772 assertEquals("uloc_getParent()", empty, tmp);
3773
3774 uprv_memset(tmp, '!', sizeof tmp);
3775 reslen = uloc_getParent(empty_script, tmp, sizeof tmp, status);
3776 status.errIfFailureAndReset("\"%s\"", empty_script);
3777 assertTrue("reslen >= 0", reslen >= 0);
3778 assertEquals("uloc_getParent()", empty, tmp);
3779
3780 uprv_memset(tmp, '!', sizeof tmp);
3781 reslen = uloc_getParent(empty_region, tmp, sizeof tmp, status);
3782 status.errIfFailureAndReset("\"%s\"", empty_region);
3783 assertTrue("reslen >= 0", reslen >= 0);
3784 assertEquals("uloc_getParent()", empty, tmp);
3785
3786 uprv_memset(tmp, '!', sizeof tmp);
3787 reslen = uloc_getParent(und_script, tmp, sizeof tmp, status);
3788 status.errIfFailureAndReset("\"%s\"", und_script);
3789 assertTrue("reslen >= 0", reslen >= 0);
3790 assertEquals("uloc_getParent()", empty, tmp);
3791
3792 uprv_memset(tmp, '!', sizeof tmp);
3793 reslen = uloc_getParent(und_region, tmp, sizeof tmp, status);
3794 status.errIfFailureAndReset("\"%s\"", und_region);
3795 assertTrue("reslen >= 0", reslen >= 0);
3796 assertEquals("uloc_getParent()", empty, tmp);
3797
3798 // uloc_getLanguage()
3799
3800 uprv_memset(tmp, '!', sizeof tmp);
3801 reslen = uloc_getLanguage(empty, tmp, sizeof tmp, status);
3802 status.errIfFailureAndReset("\"%s\"", empty);
3803 assertTrue("reslen >= 0", reslen >= 0);
3804 assertEquals("uloc_getLanguage()", empty, tmp);
3805
3806 uprv_memset(tmp, '!', sizeof tmp);
3807 reslen = uloc_getLanguage(root, tmp, sizeof tmp, status);
3808 status.errIfFailureAndReset("\"%s\"", root);
3809 assertTrue("reslen >= 0", reslen >= 0);
3810 assertEquals("uloc_getLanguage()", empty, tmp);
3811
3812 uprv_memset(tmp, '!', sizeof tmp);
3813 reslen = uloc_getLanguage(und, tmp, sizeof tmp, status);
3814 status.errIfFailureAndReset("\"%s\"", und);
3815 assertTrue("reslen >= 0", reslen >= 0);
3816 assertEquals("uloc_getLanguage()", empty, tmp);
3817
3818 uprv_memset(tmp, '!', sizeof tmp);
3819 reslen = uloc_getLanguage(empty_script, tmp, sizeof tmp, status);
3820 status.errIfFailureAndReset("\"%s\"", empty_script);
3821 assertTrue("reslen >= 0", reslen >= 0);
3822 assertEquals("uloc_getLanguage()", empty, tmp);
3823
3824 uprv_memset(tmp, '!', sizeof tmp);
3825 reslen = uloc_getLanguage(empty_region, tmp, sizeof tmp, status);
3826 status.errIfFailureAndReset("\"%s\"", empty_region);
3827 assertTrue("reslen >= 0", reslen >= 0);
3828 assertEquals("uloc_getLanguage()", empty, tmp);
3829
3830 uprv_memset(tmp, '!', sizeof tmp);
3831 reslen = uloc_getLanguage(und_script, tmp, sizeof tmp, status);
3832 status.errIfFailureAndReset("\"%s\"", und_script);
3833 assertTrue("reslen >= 0", reslen >= 0);
3834 assertEquals("uloc_getLanguage()", empty, tmp);
3835
3836 uprv_memset(tmp, '!', sizeof tmp);
3837 reslen = uloc_getLanguage(und_region, tmp, sizeof tmp, status);
3838 status.errIfFailureAndReset("\"%s\"", und_region);
3839 assertTrue("reslen >= 0", reslen >= 0);
3840 assertEquals("uloc_getLanguage()", empty, tmp);
3841 }
3842
3843 #define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array))
3844
TestRangeIterator()3845 void LocaleTest::TestRangeIterator() {
3846 IcuTestErrorCode status(*this, "TestRangeIterator");
3847 Locale locales[] = { "fr", "en_GB", "en" };
3848 Locale::RangeIterator<Locale *> iter(ARRAY_RANGE(locales));
3849
3850 assertTrue("0.hasNext()", iter.hasNext());
3851 const Locale &l0 = iter.next();
3852 assertEquals("0.next()", "fr", l0.getName());
3853 assertTrue("&0.next()", &l0 == &locales[0]);
3854
3855 assertTrue("1.hasNext()", iter.hasNext());
3856 const Locale &l1 = iter.next();
3857 assertEquals("1.next()", "en_GB", l1.getName());
3858 assertTrue("&1.next()", &l1 == &locales[1]);
3859
3860 assertTrue("2.hasNext()", iter.hasNext());
3861 const Locale &l2 = iter.next();
3862 assertEquals("2.next()", "en", l2.getName());
3863 assertTrue("&2.next()", &l2 == &locales[2]);
3864
3865 assertFalse("3.hasNext()", iter.hasNext());
3866 }
3867
TestPointerConvertingIterator()3868 void LocaleTest::TestPointerConvertingIterator() {
3869 IcuTestErrorCode status(*this, "TestPointerConvertingIterator");
3870 Locale locales[] = { "fr", "en_GB", "en" };
3871 Locale *pointers[] = { locales, locales + 1, locales + 2 };
3872 // Lambda with explicit reference return type to prevent copy-constructing a temporary
3873 // which would be destructed right away.
3874 Locale::ConvertingIterator<Locale **, std::function<const Locale &(const Locale *)>> iter(
3875 ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; });
3876
3877 assertTrue("0.hasNext()", iter.hasNext());
3878 const Locale &l0 = iter.next();
3879 assertEquals("0.next()", "fr", l0.getName());
3880 assertTrue("&0.next()", &l0 == pointers[0]);
3881
3882 assertTrue("1.hasNext()", iter.hasNext());
3883 const Locale &l1 = iter.next();
3884 assertEquals("1.next()", "en_GB", l1.getName());
3885 assertTrue("&1.next()", &l1 == pointers[1]);
3886
3887 assertTrue("2.hasNext()", iter.hasNext());
3888 const Locale &l2 = iter.next();
3889 assertEquals("2.next()", "en", l2.getName());
3890 assertTrue("&2.next()", &l2 == pointers[2]);
3891
3892 assertFalse("3.hasNext()", iter.hasNext());
3893 }
3894
3895 namespace {
3896
3897 class LocaleFromTag {
3898 public:
LocaleFromTag()3899 LocaleFromTag() : locale(Locale::getRoot()) {}
operator ()(const char * tag)3900 const Locale &operator()(const char *tag) { return locale = Locale(tag); }
3901
3902 private:
3903 // Store the locale in the converter, rather than return a reference to a temporary,
3904 // or a value which could go out of scope with the caller's reference to it.
3905 Locale locale;
3906 };
3907
3908 } // namespace
3909
TestTagConvertingIterator()3910 void LocaleTest::TestTagConvertingIterator() {
3911 IcuTestErrorCode status(*this, "TestTagConvertingIterator");
3912 const char *tags[] = { "fr", "en_GB", "en" };
3913 LocaleFromTag converter;
3914 Locale::ConvertingIterator<const char **, LocaleFromTag> iter(ARRAY_RANGE(tags), converter);
3915
3916 assertTrue("0.hasNext()", iter.hasNext());
3917 const Locale &l0 = iter.next();
3918 assertEquals("0.next()", "fr", l0.getName());
3919
3920 assertTrue("1.hasNext()", iter.hasNext());
3921 const Locale &l1 = iter.next();
3922 assertEquals("1.next()", "en_GB", l1.getName());
3923
3924 assertTrue("2.hasNext()", iter.hasNext());
3925 const Locale &l2 = iter.next();
3926 assertEquals("2.next()", "en", l2.getName());
3927
3928 assertFalse("3.hasNext()", iter.hasNext());
3929 }
3930
TestCapturingTagConvertingIterator()3931 void LocaleTest::TestCapturingTagConvertingIterator() {
3932 IcuTestErrorCode status(*this, "TestCapturingTagConvertingIterator");
3933 const char *tags[] = { "fr", "en_GB", "en" };
3934 // Store the converted locale in a locale variable,
3935 // rather than return a reference to a temporary,
3936 // or a value which could go out of scope with the caller's reference to it.
3937 Locale locale;
3938 // Lambda with explicit reference return type to prevent copy-constructing a temporary
3939 // which would be destructed right away.
3940 Locale::ConvertingIterator<const char **, std::function<const Locale &(const char *)>> iter(
3941 ARRAY_RANGE(tags), [&](const char *tag) -> const Locale & { return locale = Locale(tag); });
3942
3943 assertTrue("0.hasNext()", iter.hasNext());
3944 const Locale &l0 = iter.next();
3945 assertEquals("0.next()", "fr", l0.getName());
3946
3947 assertTrue("1.hasNext()", iter.hasNext());
3948 const Locale &l1 = iter.next();
3949 assertEquals("1.next()", "en_GB", l1.getName());
3950
3951 assertTrue("2.hasNext()", iter.hasNext());
3952 const Locale &l2 = iter.next();
3953 assertEquals("2.next()", "en", l2.getName());
3954
3955 assertFalse("3.hasNext()", iter.hasNext());
3956 }
3957
TestSetUnicodeKeywordValueInLongLocale()3958 void LocaleTest::TestSetUnicodeKeywordValueInLongLocale() {
3959 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueInLongLocale");
3960 const char* value = "efghijkl";
3961 icu::Locale l("de");
3962 char keyword[3];
3963 CharString expected("de-u", status);
3964 keyword[2] = '\0';
3965 for (char i = 'a'; i < 's'; i++) {
3966 keyword[0] = keyword[1] = i;
3967 expected.append("-", status);
3968 expected.append(keyword, status);
3969 expected.append("-", status);
3970 expected.append(value, status);
3971 l.setUnicodeKeywordValue(keyword, value, status);
3972 if (status.errIfFailureAndReset(
3973 "setUnicodeKeywordValue(\"%s\", \"%s\") fail while locale is \"%s\"",
3974 keyword, value, l.getName())) {
3975 return;
3976 }
3977 std::string tag = l.toLanguageTag<std::string>(status);
3978 if (status.errIfFailureAndReset(
3979 "toLanguageTag fail on \"%s\"", l.getName())) {
3980 return;
3981 }
3982 if (tag != expected.data()) {
3983 errln("Expected to get \"%s\" bug got \"%s\"", tag.c_str(),
3984 expected.data());
3985 return;
3986 }
3987 }
3988 }
3989
TestSetUnicodeKeywordValueNullInLongLocale()3990 void LocaleTest::TestSetUnicodeKeywordValueNullInLongLocale() {
3991 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueNullInLongLocale");
3992 const char *exts[] = {"cf", "cu", "em", "kk", "kr", "ks", "kv", "lb", "lw",
3993 "ms", "nu", "rg", "sd", "ss", "tz"};
3994 for (int32_t i = 0; i < UPRV_LENGTHOF(exts); i++) {
3995 CharString tag("de-u", status);
3996 for (int32_t j = 0; j <= i; j++) {
3997 tag.append("-", status).append(exts[j], status);
3998 }
3999 if (status.errIfFailureAndReset(
4000 "Cannot create tag \"%s\"", tag.data())) {
4001 continue;
4002 }
4003 Locale l = Locale::forLanguageTag(tag.data(), status);
4004 if (status.errIfFailureAndReset(
4005 "Locale::forLanguageTag(\"%s\") failed", tag.data())) {
4006 continue;
4007 }
4008 for (int32_t j = 0; j <= i; j++) {
4009 l.setUnicodeKeywordValue(exts[j], nullptr, status);
4010 if (status.errIfFailureAndReset(
4011 "Locale(\"%s\").setUnicodeKeywordValue(\"%s\", nullptr) failed",
4012 tag.data(), exts[j])) {
4013 continue;
4014 }
4015 }
4016 if (strcmp("de", l.getName()) != 0) {
4017 errln("setUnicodeKeywordValue should remove all extensions from "
4018 "\"%s\" and only have \"de\", but is \"%s\" instead.",
4019 tag.data(), l.getName());
4020 }
4021 }
4022 }
4023