]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/loctest.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / loctest.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
b75a7d8f 3/********************************************************************
374ca955 4 * COPYRIGHT:
2ca993e8 5 * Copyright (c) 1997-2016, International Business Machines Corporation and
b75a7d8f
A
6 * others. All Rights Reserved.
7 ********************************************************************/
8
340931cb 9#include <functional>
3d1f044b
A
10#include <iterator>
11#include <set>
12#include <utility>
13
b75a7d8f 14#include "loctest.h"
3d1f044b
A
15#include "unicode/localebuilder.h"
16#include "unicode/localpointer.h"
b75a7d8f 17#include "unicode/decimfmt.h"
374ca955 18#include "unicode/ucurr.h"
b75a7d8f 19#include "unicode/smpdtfmt.h"
0f5d89e8 20#include "unicode/strenum.h"
374ca955
A
21#include "unicode/dtfmtsym.h"
22#include "unicode/brkiter.h"
23#include "unicode/coll.h"
0f5d89e8 24#include "unicode/ustring.h"
3d1f044b 25#include "unicode/std_string.h"
0f5d89e8 26#include "charstr.h"
2ca993e8 27#include "cmemory.h"
374ca955 28#include "cstring.h"
73c04bcf 29#include <stdio.h>
4388f060 30#include <string.h>
46f4442e 31#include "putilimp.h"
b331163b 32#include "hash.h"
0f5d89e8 33#include "locmap.h"
b75a7d8f 34
46f4442e 35static const char* const rawData[33][8] = {
b75a7d8f
A
36
37 // language code
374ca955
A
38 { "en", "fr", "ca", "el", "no", "it", "xx", "zh" },
39 // script code
40 { "", "", "", "", "", "", "", "Hans" },
b75a7d8f 41 // country code
374ca955 42 { "US", "FR", "ES", "GR", "NO", "", "YY", "CN" },
b75a7d8f 43 // variant code
374ca955 44 { "", "", "", "", "NY", "", "", "" },
b75a7d8f 45 // full name
374ca955 46 { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "it", "xx_YY", "zh_Hans_CN" },
b75a7d8f 47 // ISO-3 language
374ca955 48 { "eng", "fra", "cat", "ell", "nor", "ita", "", "zho" },
b75a7d8f 49 // ISO-3 country
374ca955
A
50 { "USA", "FRA", "ESP", "GRC", "NOR", "", "", "CHN" },
51 // LCID
52 { "409", "40c", "403", "408", "814", "10", "0", "804" },
b75a7d8f 53
3d1f044b 54 // display language (English)
374ca955
A
55 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "Chinese" },
56 // display script (English)
57 { "", "", "", "", "", "", "", "Simplified Han" },
b75a7d8f 58 // display country (English)
4f1e1a09 59 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "China mainland" },
b75a7d8f 60 // display variant (English)
374ca955 61 { "", "", "", "", "NY", "", "", ""},
b75a7d8f
A
62 // display name (English)
63 // Updated no_NO_NY English display name for new pattern-based algorithm
64 // (part of Euro support).
3d1f044b 65 { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese, Simplified (China mainland)" },
b75a7d8f 66
3d1f044b 67 // display language (French)
374ca955
A
68 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" },
69 // display script (French)
57a6839d 70 { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" },
b75a7d8f 71 // display country (French)
4f1e1a09 72 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine continentale" },
b75a7d8f 73 // display variant (French)
374ca955 74 { "", "", "", "", "NY", "", "", "" },
b75a7d8f 75 // display name (French)
374ca955 76 //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" },
3d1f044b 77 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois simplifi\\u00E9 (Chine continentale)" },
374ca955
A
78
79
80 /* display language (Catalan) */
46f4442e 81 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" },
374ca955 82 /* display script (Catalan) */
57a6839d 83 { "", "", "", "", "", "", "", "han simplificat" },
374ca955 84 /* display country (Catalan) */
4f1e1a09 85 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina continental" },
374ca955
A
86 /* display variant (Catalan) */
87 { "", "", "", "", "NY", "", "" },
88 /* display name (Catalan) */
3d1f044b 89 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s simplificat (Xina continental)" },
b75a7d8f 90
3d1f044b 91 // display language (Greek)[actual values listed below]
374ca955
A
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)
57a6839d 102 { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" },
b75a7d8f 103 // display country (Greek)[actual values listed below]
57a6839d 104 { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2",
374ca955
A
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 "",
4f1e1a09 111 "\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE"
374ca955 112 },
b75a7d8f 113 // display variant (Greek)
374ca955 114 { "", "", "", "", "NY", "", "" },
b75a7d8f 115 // display name (Greek)[actual values listed below]
57a6839d 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)",
374ca955
A
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)",
57a6839d 120 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
374ca955
A
121 "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac",
122 "",
3d1f044b 123 "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03b1 \\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u039A\\u03AF\\u03BD\\u03B1 \\u03B7\\u03C0\\u03B5\\u03B9\\u03C1\\u03C9\\u03C4\\u03B9\\u03BA\\u03AE)"
374ca955 124 },
b75a7d8f 125
3d1f044b 126 // display language (<root>)
374ca955
A
127 { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "" },
128 // display script (<root>)
129 { "", "", "", "", "", "", "", ""},
b75a7d8f 130 // display country (<root>)
374ca955 131 { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "" },
b75a7d8f 132 // display variant (<root>)
374ca955 133 { "", "", "", "", "Nynorsk", "", "", ""},
b75a7d8f 134 // display name (<root>)
374ca955
A
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)", "" }
b75a7d8f
A
137};
138
73c04bcf 139
b75a7d8f
A
140/*
141 Usage:
73c04bcf 142 test_assert( Test (should be TRUE) )
b75a7d8f
A
143
144 Example:
73c04bcf 145 test_assert(i==3);
b75a7d8f 146
73c04bcf 147 the macro is ugly but makes the tests pretty.
b75a7d8f
A
148*/
149
340931cb
A
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
b75a7d8f 156
b75a7d8f
A
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
340931cb
A
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
b75a7d8f
A
173
174
340931cb
A
175#define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \
176 logln(#l " = " + UnicodeString(l.getName(), "")); \
177} UPRV_BLOCK_MACRO_END
b75a7d8f
A
178
179LocaleTest::LocaleTest()
180: dataTable(NULL)
181{
182 setUpDataTable();
183}
184
185LocaleTest::~LocaleTest()
186{
187 if (dataTable != 0) {
374ca955 188 for (int32_t i = 0; i < 33; i++) {
b75a7d8f
A
189 delete []dataTable[i];
190 }
191 delete []dataTable;
192 dataTable = 0;
193 }
194}
195
b75a7d8f
A
196void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
197{
b331163b
A
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);
b75a7d8f 212#if !UCONFIG_NO_FORMATTING
b331163b
A
213 TESTCASE_AUTO(TestThaiCurrencyFormat);
214 TESTCASE_AUTO(TestEuroSupport);
b75a7d8f 215#endif
b331163b 216 TESTCASE_AUTO(TestToString);
b75a7d8f 217#if !UCONFIG_NO_FORMATTING
b331163b
A
218 TESTCASE_AUTO(Test4139940);
219 TESTCASE_AUTO(Test4143951);
b75a7d8f 220#endif
b331163b
A
221 TESTCASE_AUTO(Test4147315);
222 TESTCASE_AUTO(Test4147317);
223 TESTCASE_AUTO(Test4147552);
224 TESTCASE_AUTO(TestVariantParsing);
340931cb 225 TESTCASE_AUTO(Test20639_DeprecatesISO3Language);
b75a7d8f 226#if !UCONFIG_NO_FORMATTING
b331163b 227 TESTCASE_AUTO(Test4105828);
b75a7d8f 228#endif
b331163b
A
229 TESTCASE_AUTO(TestSetIsBogus);
230 TESTCASE_AUTO(TestParallelAPIValues);
3d1f044b
A
231 TESTCASE_AUTO(TestAddLikelySubtags);
232 TESTCASE_AUTO(TestMinimizeSubtags);
233 TESTCASE_AUTO(TestAddLikelyAndMinimizeSubtags);
b331163b 234 TESTCASE_AUTO(TestKeywordVariants);
3d1f044b 235 TESTCASE_AUTO(TestCreateUnicodeKeywords);
b331163b 236 TESTCASE_AUTO(TestKeywordVariantParsing);
3d1f044b 237 TESTCASE_AUTO(TestCreateKeywordSet);
340931cb 238 TESTCASE_AUTO(TestCreateKeywordSetEmpty);
3d1f044b 239 TESTCASE_AUTO(TestCreateUnicodeKeywordSet);
340931cb 240 TESTCASE_AUTO(TestCreateUnicodeKeywordSetEmpty);
3d1f044b
A
241 TESTCASE_AUTO(TestGetKeywordValueStdString);
242 TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString);
b331163b 243 TESTCASE_AUTO(TestSetKeywordValue);
3d1f044b
A
244 TESTCASE_AUTO(TestSetKeywordValueStringPiece);
245 TESTCASE_AUTO(TestSetUnicodeKeywordValueStringPiece);
b331163b 246 TESTCASE_AUTO(TestGetBaseName);
729e4ab9 247#if !UCONFIG_NO_FILE_IO
b331163b 248 TESTCASE_AUTO(TestGetLocale);
729e4ab9 249#endif
b331163b
A
250 TESTCASE_AUTO(TestVariantWithOutCountry);
251 TESTCASE_AUTO(TestCanonicalization);
252 TESTCASE_AUTO(TestCurrencyByDate);
253 TESTCASE_AUTO(TestGetVariantWithKeywords);
254 TESTCASE_AUTO(TestIsRightToLeft);
0f5d89e8
A
255 TESTCASE_AUTO(TestBug13277);
256 TESTCASE_AUTO(TestBug13554);
3d1f044b 257 TESTCASE_AUTO(TestBug20410);
340931cb 258 TESTCASE_AUTO(TestConstructorAcceptsBCP47);
3d1f044b
A
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);
340931cb
A
270 TESTCASE_AUTO(TestRangeIterator);
271 TESTCASE_AUTO(TestPointerConvertingIterator);
272 TESTCASE_AUTO(TestTagConvertingIterator);
273 TESTCASE_AUTO(TestCapturingTagConvertingIterator);
274 TESTCASE_AUTO(TestSetUnicodeKeywordValueInLongLocale);
275 TESTCASE_AUTO(TestSetUnicodeKeywordValueNullInLongLocale);
b331163b 276 TESTCASE_AUTO_END;
b75a7d8f
A
277}
278
279void LocaleTest::TestBasicGetters() {
280 UnicodeString temp;
281
282 int32_t i;
283 for (i = 0; i <= MAX_LOCALES; i++) {
374ca955
A
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 }
b75a7d8f
A
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]);
374ca955
A
296 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
297 errln(" Script code mismatch: " + temp + " versus "
298 + dataTable[SCRIPT][i]);
b75a7d8f
A
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++) {
374ca955
A
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 }
b75a7d8f
A
319 logln("Testing " + (temp=testLocale.getName()) + "...");
320
321 if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i]))
374ca955 322 errln("Language code mismatch: " + temp + " versus "
b75a7d8f 323 + dataTable[LANG][i]);
374ca955
A
324 if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i]))
325 errln("Script code mismatch: " + temp + " versus "
326 + dataTable[SCRIPT][i]);
b75a7d8f 327 if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i]))
374ca955 328 errln("Country code mismatch: " + temp + " versus "
b75a7d8f
A
329 + dataTable[CTRY][i]);
330 if (testLocale.getVariant()[0] != 0)
374ca955 331 errln("Variant code mismatch: something versus \"\"");
b75a7d8f
A
332 }
333
334 logln("Testing long language names and getters");
374ca955 335 Locale test8 = Locale::createFromName("x-klingon-latn-zx.utf32be@special");
b75a7d8f
A
336
337 temp = test8.getLanguage();
338 if (temp != UnicodeString("x-klingon") )
374ca955
A
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\"");
b75a7d8f
A
344
345 temp = test8.getCountry();
346 if (temp != UnicodeString("ZX") )
374ca955 347 errln("Country code mismatch: " + temp + " versus \"ZX\"");
b75a7d8f
A
348
349 temp = test8.getVariant();
374ca955
A
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 \"\"");
b75a7d8f
A
355
356 if (Locale::getDefault() != Locale::createFromName(NULL))
374ca955 357 errln("Locale::getDefault() == Locale::createFromName(NULL)");
b75a7d8f
A
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 }
374ca955
A
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;
b75a7d8f
A
386}
387
388void 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
458void LocaleTest::TestSimpleResourceInfo() {
374ca955
A
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]);
b75a7d8f 479
374ca955
A
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 /*-----*/
b75a7d8f
A
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 */
374ca955
A
502void
503LocaleTest::TestDisplayNames()
b75a7d8f
A
504{
505 Locale english("en", "US");
506 Locale french("fr", "FR");
374ca955 507 Locale croatian("ca", "ES");
b75a7d8f
A
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);
374ca955
A
514 logln(" In locale = ca_ES...");
515 doTestDisplayNames(croatian, DLANG_CA);
b75a7d8f
A
516 logln(" In locale = el_GR...");
517 doTestDisplayNames(greek, DLANG_EL);
518
b75a7d8f 519 UnicodeString s;
46f4442e 520 UErrorCode status = U_ZERO_ERROR;
b75a7d8f 521
46f4442e
A
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 */
729e4ab9
A
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 }
46f4442e 534
729e4ab9
A
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 }
46f4442e
A
545 }
546 }
547 else {
548 logln("Default locale %s is unsupported by ICU\n", Locale().getName());
b75a7d8f
A
549 }
550 s.remove();
46f4442e
A
551#endif
552
b75a7d8f
A
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 }
73c04bcf
A
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");
b75a7d8f 561 }
73c04bcf 562}
b75a7d8f
A
563
564void LocaleTest::TestSimpleObjectStuff() {
565 Locale test1("aa", "AA");
566 Locale test2("aa", "AA");
567 Locale test3(test1);
568 Locale test4("zz", "ZZ");
374ca955
A
569 Locale test5("aa", "AA", "");
570 Locale test6("aa", "AA", "ANTARES");
b75a7d8f 571 Locale test7("aa", "AA", "JUPITER");
374ca955 572 Locale test8 = Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that
b75a7d8f
A
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);
374ca955 642
b75a7d8f
A
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.
660class POSIXLocale : public Locale
661{
662public:
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 }
672 POSIXLocale(const char *l)
673 :Locale()
674 {
675 setFromPOSIXID(l);
676 }
677};
678
679void 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"));
374ca955 687 Locale test6("ab", "AB", "Antares");
b75a7d8f
A
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
719void LocaleTest::TestGetAvailableLocales()
720{
721 int32_t locCount = 0;
722 const Locale* locList = Locale::getAvailableLocales(locCount);
723
724 if (locCount == 0)
729e4ab9 725 dataerrln("getAvailableLocales() returned an empty list!");
b75a7d8f
A
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
737void 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 + "\"");
374ca955 765
b75a7d8f
A
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
776void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) {
777 UnicodeString temp;
374ca955 778
b75a7d8f 779 for (int32_t i = 0; i <= MAX_LOCALES; i++) {
374ca955
A
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 }
b75a7d8f
A
787 logln(" Testing " + (temp=testLocale.getName()) + "...");
788
789 UnicodeString testLang;
374ca955 790 UnicodeString testScript;
b75a7d8f
A
791 UnicodeString testCtry;
792 UnicodeString testVar;
793 UnicodeString testName;
794
795 testLocale.getDisplayLanguage(displayLocale, testLang);
374ca955 796 testLocale.getDisplayScript(displayLocale, testScript);
b75a7d8f
A
797 testLocale.getDisplayCountry(displayLocale, testCtry);
798 testLocale.getDisplayVariant(displayLocale, testVar);
799 testLocale.getDisplayName(displayLocale, testName);
800
801 UnicodeString expectedLang;
374ca955 802 UnicodeString expectedScript;
b75a7d8f
A
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
374ca955
A
811 expectedScript = dataTable[compareIndex + 1][i];
812 if (expectedScript.length() == 0)
813 expectedScript = dataTable[DSCRIPT_EN][i];
814
815 expectedCtry = dataTable[compareIndex + 2][i];
b75a7d8f
A
816 if (expectedCtry.length() == 0)
817 expectedCtry = dataTable[DCTRY_EN][i];
818
374ca955 819 expectedVar = dataTable[compareIndex + 3][i];
b75a7d8f
A
820 if (expectedVar.length() == 0)
821 expectedVar = dataTable[DVAR_EN][i];
822
374ca955 823 expectedName = dataTable[compareIndex + 4][i];
b75a7d8f
A
824 if (expectedName.length() == 0)
825 expectedName = dataTable[DNAME_EN][i];
826
827 if (testLang != expectedLang)
729e4ab9 828 dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang);
374ca955 829 if (testScript != expectedScript)
729e4ab9 830 dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript);
b75a7d8f 831 if (testCtry != expectedCtry)
729e4ab9 832 dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry);
b75a7d8f 833 if (testVar != expectedVar)
729e4ab9 834 dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar);
b75a7d8f 835 if (testName != expectedName)
729e4ab9 836 dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName);
b75a7d8f
A
837 }
838}
839
840//---------------------------------------------------
841// table of valid data
842//---------------------------------------------------
843
844
374ca955 845
b75a7d8f
A
846void LocaleTest::setUpDataTable()
847{
848 if (dataTable == 0) {
374ca955 849 dataTable = new UnicodeString*[33];
b75a7d8f 850
374ca955
A
851 for (int32_t i = 0; i < 33; i++) {
852 dataTable[i] = new UnicodeString[8];
853 for (int32_t j = 0; j < 8; j++) {
b75a7d8f
A
854 dataTable[i][j] = CharsToUnicodeString(rawData[i][j]);
855 }
856 }
b75a7d8f
A
857 }
858}
859
860// ====================
861
862
863/**
864 * @bug 4011756 4011380
865 */
374ca955
A
866void
867LocaleTest::TestISO3Fallback()
b75a7d8f
A
868{
869 Locale test("xx", "YY");
870
871 const char * result;
872
873 result = test.getISO3Language();
874
374ca955 875 // Conform to C API usage
b75a7d8f
A
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 */
374ca955
A
889void
890LocaleTest::TestGetLangsAndCountries()
b75a7d8f
A
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();
374ca955
A
902 const char spotCheck1[ ][4] = { "en", "es", "fr", "de", "it",
903 "ja", "ko", "zh", "th", "he",
b75a7d8f
A
904 "id", "iu", "ug", "yi", "za" };
905
906 int32_t i;
374ca955 907
b75a7d8f
A
908 for(testCount = 0;test[testCount];testCount++)
909 ;
910
374ca955 911 /* TODO: Change this test to be more like the cloctst version? */
340931cb
A
912 if (testCount != 596)
913 errln("Expected getISOLanguages() to return 596 languages; it returned %d", testCount);
b75a7d8f
A
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();
374ca955
A
936 UnicodeString spotCheck2 [] = { "US", "CA", "GB", "FR", "DE",
937 "IT", "JP", "KR", "CN", "TW",
b75a7d8f
A
938 "TH" };
939 int32_t spot2Len = 11;
940 for(testCount=0;test[testCount];testCount++)
941 ;
942
2ca993e8
A
943 if (testCount != 256){
944 errln("Expected getISOCountries to return 256 countries; it returned %d", testCount);
73c04bcf 945 }else {
b75a7d8f
A
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 }
4388f060
A
960 for (i = 0; i < testCount; i++) {
961 UnicodeString testee(test[i],"");
b75a7d8f
A
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 }
4388f060
A
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 }
b75a7d8f
A
990}
991
992/**
993 * @bug 4118587
994 */
374ca955
A
995void
996LocaleTest::TestSimpleDisplayNames()
b75a7d8f
A
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" };
51004dcb 1003 UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
b75a7d8f
A
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])
729e4ab9 1011 dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" +
b75a7d8f
A
1012 languageNames[i] + "\", got \"" + test + "\".");
1013 }
1014}
1015
1016/**
1017 * @bug 4118595
1018 */
374ca955
A
1019void
1020LocaleTest::TestUninstalledISO3Names()
b75a7d8f
A
1021{
1022 // This test checks to make sure getISO3Language and getISO3Country work right
1023 // even for locales that are not installed.
374ca955 1024 const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
b75a7d8f 1025 "ss", "tw", "zu" };
374ca955 1026 const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
b75a7d8f
A
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
374ca955 1042 char iso2Countries [][4] = { "AF", "BW", "KZ", "MO", "MN",
b75a7d8f 1043 "SB", "TC", "ZW" };
374ca955 1044 char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
b75a7d8f
A
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 */
374ca955
A
1063void
1064LocaleTest::TestAtypicalLocales()
b75a7d8f
A
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 "Croatia",
1082 "Sweden",
1083 "Dominican Republic",
1084 "Belgium" };
1085 UnicodeString frenchDisplayNames []= { "allemand (Canada)",
3d1f044b
A
1086 "japonais (Afrique du Sud)",
1087 "russe (Mexique)",
b75a7d8f
A
1088 "anglais (France)",
1089 "espagnol (Allemagne)",
3d1f044b
A
1090 u"Croatie",
1091 u"Suède",
1092 u"République dominicaine",
1093 u"Belgique" };
b75a7d8f 1094 UnicodeString spanishDisplayNames [] = {
3d1f044b
A
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)",
b75a7d8f
A
1100 "Croacia",
1101 "Suecia",
3d1f044b
A
1102 u"República Dominicana",
1103 u"Bélgica" };
374ca955
A
1104 // De-Anglicizing root required the change from
1105 // English display names to ISO Codes - ram 2003/09/26
73c04bcf
A
1106 UnicodeString invDisplayNames [] = { "German (Canada)",
1107 "Japanese (South Africa)",
1108 "Russian (Mexico)",
1109 "English (France)",
1110 "Spanish (Germany)",
1111 "Croatia",
1112 "Sweden",
1113 "Dominican Republic",
1114 "Belgium" };
b75a7d8f
A
1115
1116 int32_t i;
1117 UErrorCode status = U_ZERO_ERROR;
73c04bcf 1118 Locale saveLocale;
b75a7d8f
A
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 {
729e4ab9 1126 dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i]
b75a7d8f
A
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])
729e4ab9 1137 dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
b75a7d8f
A
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])
729e4ab9 1146 dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
b75a7d8f
A
1147 + "\", got \"" + name + "\"");
1148 }
1149
1150 for (i = 0; i < 9; i++) {
1151 UnicodeString name;
73c04bcf 1152 localesToTest[i].getDisplayName(Locale("inv", "IN"), name);
374ca955 1153 logln(name + " Locale fallback to be, and data fallback to root");
73c04bcf 1154 if (name != invDisplayNames[i])
729e4ab9 1155 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
73c04bcf
A
1156 + "\", got \"" + prettify(name) + "\"");
1157 localesToTest[i].getDisplayName(Locale("inv", "BD"), name);
b75a7d8f 1158 logln(name + " Data fallback to root");
73c04bcf 1159 if (name != invDisplayNames[i])
729e4ab9 1160 dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i])
73c04bcf 1161 + "\", got \"" + prettify(name )+ "\"");
b75a7d8f 1162 }
73c04bcf 1163 Locale::setDefault(saveLocale, status);
b75a7d8f
A
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 */
374ca955
A
1173void
1174LocaleTest::TestThaiCurrencyFormat()
b75a7d8f
A
1175{
1176 UErrorCode status = U_ZERO_ERROR;
1177 DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance(
1178 Locale("th", "TH"), status);
3d1f044b 1179 UnicodeString posPrefix(u"\u0E3F");
b75a7d8f
A
1180 UnicodeString temp;
1181
1182 if(U_FAILURE(status) || !thaiCurrency)
1183 {
729e4ab9 1184 dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status)));
b75a7d8f
A
1185 return;
1186 }
b331163b 1187 if (thaiCurrency->getPositivePrefix(temp) != posPrefix)
3d1f044b 1188 errln("Thai currency prefix wrong: expected Baht sign, got \"" +
b75a7d8f
A
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 */
374ca955
A
1208void
1209LocaleTest::TestEuroSupport()
b75a7d8f
A
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",
3d1f044b
A
1221 "en_GB@currency=EUR",
1222 "en_US@currency=EUR",
b75a7d8f
A
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;
374ca955
A
1246 NumberFormat *nf = NumberFormat::createCurrencyInstance(loc, status);
1247 UnicodeString pos;
73c04bcf
A
1248
1249 if (U_FAILURE(status)) {
1250 dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales);
1251 continue;
1252 }
1253
374ca955
A
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) {
729e4ab9 1279 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
374ca955 1280 }
3d1f044b 1281 ucurr_forLocale("en_US@currency=EUR", tmp, 4, &status);
374ca955
A
1282 resultStr.setTo(tmp);
1283 if (euroStr != resultStr) {
3d1f044b 1284 errcheckln(status, "Fail: en_US@currency=EUR didn't return EUR - %s", u_errorName(status));
374ca955 1285 }
3d1f044b 1286 ucurr_forLocale("en_GB@currency=EUR", tmp, 4, &status);
374ca955
A
1287 resultStr.setTo(tmp);
1288 if (euroStr != resultStr) {
3d1f044b 1289 errcheckln(status, "Fail: en_GB@currency=EUR didn't return EUR - %s", u_errorName(status));
374ca955
A
1290 }
1291 ucurr_forLocale("en_US_Q", tmp, 4, &status);
1292 resultStr.setTo(tmp);
1293 if (dollarStr != resultStr) {
729e4ab9 1294 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
374ca955
A
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");
b75a7d8f 1299 }
0f5d89e8
A
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 }
b75a7d8f
A
1313}
1314
1315#endif
1316
1317/**
1318 * @bug 4139504
1319 * toString() doesn't work with language_VARIANT.
1320 */
374ca955 1321void
b75a7d8f
A
1322LocaleTest::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 };
374ca955 1342
b75a7d8f
A
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:
374ca955
A
1363 * -- basically, hungarian for monday shouldn't have an \u00f4
1364 * (o circumflex)in it instead it should be an o with 2 inclined
b75a7d8f
A
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 */
374ca955
A
1374void
1375LocaleTest::Test4139940()
b75a7d8f 1376{
374ca955 1377 Locale mylocale("hu", "", "");
b75a7d8f
A
1378 UDate mydate = date(98,3,13); // A Monday
1379 UErrorCode status = U_ZERO_ERROR;
1380 SimpleDateFormat df_full("EEEE", mylocale, status);
73c04bcf 1381 if(U_FAILURE(status)){
729e4ab9 1382 dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status)));
73c04bcf
A
1383 return;
1384 }
b75a7d8f
A
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;
374ca955 1392 if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) {
729e4ab9
A
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 }
374ca955
A
1400 logln(UnicodeString("String is: ") + str );
1401 }
b75a7d8f
A
1402}
1403
1404UDate
1405LocaleTest::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);
374ca955 1409 if (cal == 0)
b75a7d8f
A
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;
374ca955 1416
b75a7d8f
A
1417 delete cal;
1418 return dt;
1419}
1420
1421/**
1422 * @bug 4143951
1423 * Russian first day of week should be Monday. Confirmed.
1424 */
374ca955
A
1425void
1426LocaleTest::Test4143951()
b75a7d8f
A
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) {
729e4ab9 1432 dataerrln("Fail: First day of week in Russia should be Monday");
b75a7d8f
A
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 */
374ca955
A
1445void
1446LocaleTest::Test4147315()
b75a7d8f
A
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
51004dcb 1451 Locale locale("xxx", "CCC");
374ca955 1452
b75a7d8f
A
1453 const char *result = locale.getISO3Country();
1454
1455 // Change to conform to C api usage
1456 if((result==NULL)||(result[0] != 0))
374ca955 1457 errln("ERROR: getISO3Country() returns: " + UnicodeString(result,"") +
b75a7d8f
A
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 */
374ca955
A
1466void
1467LocaleTest::Test4147317()
b75a7d8f
A
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
51004dcb 1472 Locale locale("xxx", "CCC");
374ca955 1473
b75a7d8f
A
1474 const char *result = locale.getISO3Language();
1475
1476 // Change to conform to C api usage
1477 if((result==NULL)||(result[0] != 0))
374ca955 1478 errln("ERROR: getISO3Language() returns: " + UnicodeString(result,"") +
b75a7d8f
A
1479 " for locale '" + (temp=locale.getName()) + "' rather than exception" );
1480}
1481
1482/*
1483 * @bug 4147552
1484 */
374ca955
A
1485void
1486LocaleTest::Test4147552()
b75a7d8f 1487{
374ca955 1488 Locale locales [] = { Locale("no", "NO"),
b75a7d8f 1489 Locale("no", "NO", "B"),
374ca955 1490 Locale("no", "NO", "NY")
b75a7d8f 1491 };
374ca955
A
1492
1493 UnicodeString edn("Norwegian (Norway, B)");
1494 UnicodeString englishDisplayNames [] = {
b75a7d8f
A
1495 "Norwegian (Norway)",
1496 edn,
1497 // "Norwegian (Norway,B)",
374ca955
A
1498 //"Norwegian (Norway,NY)"
1499 "Norwegian (Norway, NY)"
b75a7d8f 1500 };
374ca955
A
1501 UnicodeString ndn("norsk (Norge, B");
1502 UnicodeString norwegianDisplayNames [] = {
b75a7d8f 1503 "norsk (Norge)",
374ca955
A
1504 "norsk (Norge, B)",
1505 //ndn,
1506 "norsk (Noreg, NY)"
1507 //"Norsk (Noreg, Nynorsk)"
b75a7d8f 1508 };
73c04bcf 1509 UErrorCode status = U_ZERO_ERROR;
b75a7d8f 1510
73c04bcf
A
1511 Locale saveLocale;
1512 Locale::setDefault(Locale::getEnglish(), status);
b75a7d8f
A
1513 for (int32_t i = 0; i < 3; ++i) {
1514 Locale loc = locales[i];
1515 UnicodeString temp;
1516 if (loc.getDisplayName(temp) != englishDisplayNames[i])
729e4ab9 1517 dataerrln("English display-name mismatch: expected " +
b75a7d8f
A
1518 englishDisplayNames[i] + ", got " + loc.getDisplayName(temp));
1519 if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i])
729e4ab9 1520 dataerrln("Norwegian display-name mismatch: expected " +
b75a7d8f
A
1521 norwegianDisplayNames[i] + ", got " +
1522 loc.getDisplayName(loc, temp));
1523 }
73c04bcf 1524 Locale::setDefault(saveLocale, status);
b75a7d8f
A
1525}
1526
1527void
1528LocaleTest::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");
374ca955 1534
b75a7d8f 1535 UnicodeString got;
374ca955 1536
b75a7d8f
A
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) {
729e4ab9
A
1546 dataerrln("FAIL: getDisplayName()");
1547 dataerrln("Wanted: " + dispName);
1548 dataerrln("Got : " + got);
b75a7d8f
A
1549 }
1550
1551 Locale shortVariant("fr", "FR", "foo");
1552 shortVariant.getDisplayVariant(got);
374ca955 1553
b75a7d8f
A
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);
374ca955 1562
b75a7d8f
A
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);
374ca955 1571
b75a7d8f
A
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);
374ca955 1580
b75a7d8f
A
1581 if(got != "FOO") {
1582 errln("FAIL: getDisplayVariant()");
1583 errln("Wanted: foo");
1584 errln("Got : " + got);
1585 }
1586}
1587
340931cb
A
1588void 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
b75a7d8f
A
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 */
374ca955
A
1616void
1617LocaleTest::Test4105828()
b75a7d8f
A
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)) {
729e4ab9 1625 dataerrln("Couldn't create NumberFormat - %s", u_errorName(status));
b75a7d8f
A
1626 return;
1627 }
1628 UnicodeString result;
f3c0d7a5 1629 FieldPosition pos(FieldPosition::DONT_CARE);
b75a7d8f
A
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
1643void
1644LocaleTest::TestSetIsBogus() {
374ca955
A
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 }
b75a7d8f
A
1654}
1655
374ca955 1656
3d1f044b
A
1657void
1658LocaleTest::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
1671void
1672LocaleTest::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
1685void
1686LocaleTest::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 "und_Latn_AQ",
1697 "und_AQ"
1698 }, {
1699 "und_Zzzz_AQ",
1700 "und_Latn_AQ",
1701 "und_AQ"
1702 }, {
1703 "und_Latn_AQ",
1704 "und_Latn_AQ",
1705 "und_AQ"
1706 }, {
1707 "und_Moon_AQ",
1708 "und_Moon_AQ",
1709 "und_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
374ca955
A
1733void
1734LocaleTest::TestKeywordVariants(void) {
46f4442e 1735 static const struct {
374ca955
A
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
2ca993e8 1773 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
374ca955
A
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 }
73c04bcf
A
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 }
374ca955
A
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
3d1f044b
A
1840
1841void
1842LocaleTest::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
374ca955
A
1897void
1898LocaleTest::TestKeywordVariantParsing(void) {
46f4442e 1899 static const struct {
374ca955
A
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
2ca993e8 1916 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
374ca955
A
1917 *buffer = 0;
1918 Locale l(testCases[i].localeID);
1919 resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status);
57a6839d 1920 (void)resultLen; // Suppress unused variable warning.
374ca955
A
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
3d1f044b
A
1928void
1929LocaleTest::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
340931cb
A
1947void
1948LocaleTest::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
3d1f044b
A
1962void
1963LocaleTest::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
340931cb
A
1981void
1982LocaleTest::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
3d1f044b
A
1996void
1997LocaleTest::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
2012void
2013LocaleTest::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
729e4ab9
A
2026void
2027LocaleTest::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
2ca993e8 2045 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
729e4ab9
A
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);
57a6839d 2053 (void)resultLen; // Suppress unused variable warning.
729e4ab9
A
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
3d1f044b
A
2061void
2062LocaleTest::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
2073void
2074LocaleTest::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
374ca955
A
2108void
2109LocaleTest::TestGetBaseName(void) {
46f4442e 2110 static const struct {
374ca955
A
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" },
b331163b
A
2116 { "ja@calendar = buddhist", "ja" },
2117 { "de-u-co-phonebk", "de"}
374ca955
A
2118 };
2119
2120 int32_t i = 0;
2121
b331163b 2122 for(i = 0; i < UPRV_LENGTHOF(testCases); i++) {
374ca955
A
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 }
b331163b
A
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 }
374ca955
A
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 */
2151static 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 */
3d1f044b
A
2156 if (prefix[0] == '\0') {
2157 return string[0] != '\0';
374ca955
A
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 */
2174void 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 {
729e4ab9 2193 dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)",
374ca955
A
2194 label, req, valid, actual,
2195 expReqValid, expValidActual);
2196 }
2197}
2198
2199void LocaleTest::TestGetLocale(void) {
2200#if !UCONFIG_NO_SERVICE
374ca955
A
2201 const char *req;
2202 Locale valid, actual, reqLoc;
2203
2204 // Calendar
2205#if !UCONFIG_NO_FORMATTING
b331163b
A
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);
374ca955 2210 if (U_FAILURE(ec)) {
b331163b 2211 dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec));
374ca955 2212 } else {
b331163b
A
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;
73c04bcf 2226 }
b331163b 2227 delete cal;
374ca955 2228 }
374ca955
A
2229#endif
2230
2231 // DecimalFormat, DecimalFormatSymbols
2232#if !UCONFIG_NO_FORMATTING
b331163b
A
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);
374ca955 2237 if (U_FAILURE(ec)) {
b331163b 2238 dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec));
374ca955 2239 } else {
b331163b
A
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 }
374ca955 2252
b331163b
A
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 }
73c04bcf 2265 }
b331163b 2266 delete nf;
374ca955 2267 }
374ca955
A
2268#endif
2269
2270 // DateFormat, DateFormatSymbols
2271#if !UCONFIG_NO_FORMATTING
b331163b
A
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()");
73c04bcf 2280 } else {
b331163b
A
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 }
374ca955 2293
b331163b
A
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 }
73c04bcf 2306 }
b331163b 2307 delete df;
73c04bcf 2308 }
374ca955
A
2309#endif
2310
2311 // BreakIterator
2312#if !UCONFIG_NO_BREAK_ITERATION
b331163b
A
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);
374ca955 2318 if (U_FAILURE(ec)) {
b331163b 2319 dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec));
374ca955 2320 } else {
b331163b
A
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 }
374ca955 2328
b331163b
A
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
374ca955
A
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 {
b331163b 2368 _checklocs("BreakIterator(unregistered)", req, valid, actual);
374ca955
A
2369 }
2370 }
374ca955 2371 }
b331163b 2372 delete brk;
374ca955 2373 }
374ca955
A
2374#endif
2375
2376 // Collator
2377#if !UCONFIG_NO_COLLATION
b331163b
A
2378 {
2379 UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code
374ca955 2380
b331163b
A
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);
374ca955 2386 if (U_FAILURE(ec)) {
b331163b 2387 dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec));
374ca955 2388 } else {
b331163b
A
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
374ca955
A
2429 coll = Collator::createInstance(reqLoc, ec);
2430 if (U_FAILURE(ec)) {
b331163b 2431 errln("FAIL: Collator::createInstance failed");
374ca955
A
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 {
b331163b 2438 _checklocs("Collator(unregistered)", req, valid, actual);
374ca955
A
2439 }
2440 }
374ca955 2441 }
b331163b 2442 delete coll;
374ca955 2443
b331163b
A
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 */
2459void 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);
3d1f044b 2464 assertSuccess(WHERE, status);
b331163b
A
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);
374ca955 2515 } else {
b331163b
A
2516 errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","")
2517 + *locStr);
374ca955
A
2518 }
2519 }
b331163b 2520 newHash.puti(*locStr, 1, status);
374ca955 2521 }
b331163b
A
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);
374ca955 2539}
b331163b
A
2540#endif
2541
2542
374ca955
A
2543
2544void LocaleTest::TestVariantWithOutCountry(void) {
2545 Locale loc("en","","POSIX");
2546 if (0 != strcmp(loc.getVariant(), "POSIX")) {
4388f060 2547 errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc.getName(), "POSIX", loc.getVariant());
374ca955
A
2548 }
2549 Locale loc2("en","","FOUR");
2550 if (0 != strcmp(loc2.getVariant(), "FOUR")) {
4388f060 2551 errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2.getName(), "FOUR", loc2.getVariant());
374ca955
A
2552 }
2553 Locale loc3("en","Latn","","FOUR");
2554 if (0 != strcmp(loc3.getVariant(), "FOUR")) {
4388f060 2555 errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3.getName(), "FOUR", loc3.getVariant());
374ca955
A
2556 }
2557 Locale loc4("","Latn","","FOUR");
2558 if (0 != strcmp(loc4.getVariant(), "FOUR")) {
4388f060 2559 errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4.getName(), "FOUR", loc4.getVariant());
374ca955
A
2560 }
2561 Locale loc5("","Latn","US","FOUR");
2562 if (0 != strcmp(loc5.getVariant(), "FOUR")) {
4388f060
A
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());
374ca955
A
2568 }
2569}
2570
2571static 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
2585void LocaleTest::TestCanonicalization(void)
2586{
46f4442e 2587 static const struct {
374ca955
A
2588 const char *localeID; /* input */
2589 const char *getNameID; /* expected getName() result */
2590 const char *canonicalID; /* expected canonicalize() result */
2591 } testCases[] = {
3d1f044b
A
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"},
374ca955
A
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 */
3d1f044b 2603 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */
374ca955
A
2604 // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS
2605 // TODO: unify this behavior
51004dcb
A
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 */
374ca955
A
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" },
374ca955
A
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" },
3d1f044b
A
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 // Apple ICU restores these first 3 mappings deleted in open ICU 64
2635 { "", "", "en_US_POSIX" },
2636 { "C", "c", "en_US_POSIX" },
2637 { "POSIX", "posix", "en_US_POSIX" },
2638 //
2639 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" },
2640 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" },
2641 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" },
2642 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" },
2643 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" },
2644 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" },
2645 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" },
2646 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" },
2647 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" },
2648 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" },
2649 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" },
2650 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" },
2651 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" },
2652 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" },
2653 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" },
2654 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" },
2655 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" },
2656 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" },
2657 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" },
2658 { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" },
2659 { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" },
2660 { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */
2661 { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" },
2662 { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" },
2663 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" },
2664 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" },
2665 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" },
2666 { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" },
2667 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */
2668 { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */
2669 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_YU_CYRILLIC" }, /* Linux name */
2670 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */
2671 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */
2672 { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */
2673 { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */
2674 /* PRE_EURO and EURO conversions don't affect other keywords */
2675 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" },
2676 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" },
2677 /* currency keyword overrides PRE_EURO and EURO currency */
2678 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" },
2679 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" },
374ca955
A
2680 };
2681
2682 static const char* label[] = { "createFromName", "createCanonical", "Locale" };
2683
2684 int32_t i, j;
2685
2ca993e8 2686 for (i=0; i < UPRV_LENGTHOF(testCases); i++) {
374ca955
A
2687 for (j=0; j<3; ++j) {
2688 const char* expected = (j==1) ? testCases[i].canonicalID : testCases[i].getNameID;
2689 Locale loc = _canonicalize(j, testCases[i].localeID);
2690 const char* getName = loc.isBogus() ? "BOGUS" : loc.getName();
2691 if(uprv_strcmp(expected, getName) != 0) {
2692 errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"",
2693 label[j], testCases[i].localeID, getName, expected);
2694 } else {
2695 logln("Ok: %s(%s) => \"%s\"",
2696 label[j], testCases[i].localeID, getName);
2697 }
2698 }
2699 }
2700}
46f4442e
A
2701
2702void LocaleTest::TestCurrencyByDate(void)
2703{
2704#if !UCONFIG_NO_FORMATTING
2705 UErrorCode status = U_ZERO_ERROR;
2706 UDate date = uprv_getUTCtime();
340931cb 2707 UChar TMP[4] = {0, 0, 0, 0};
46f4442e
A
2708 int32_t index = 0;
2709 int32_t resLen = 0;
2710 UnicodeString tempStr, resultStr;
2711
2712 // Cycle through historical currencies
2713 date = (UDate)-630720000000.0; // pre 1961 - no currency defined
729e4ab9 2714 index = ucurr_countCurrencies("eo_AM", date, &status);
46f4442e
A
2715 if (index != 0)
2716 {
729e4ab9 2717 errcheckln(status, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status));
46f4442e
A
2718 }
2719 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2720 if (resLen != 0) {
729e4ab9 2721 errcheckln(status, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status));
46f4442e
A
2722 }
2723 status = U_ZERO_ERROR;
2724
2725 date = (UDate)0.0; // 1970 - one currency defined
729e4ab9 2726 index = ucurr_countCurrencies("eo_AM", date, &status);
46f4442e
A
2727 if (index != 1)
2728 {
729e4ab9 2729 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
46f4442e
A
2730 }
2731 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2732 tempStr.setTo(TMP);
2733 resultStr.setTo("SUR");
2734 if (resultStr != tempStr) {
729e4ab9 2735 errcheckln(status, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status));
46f4442e
A
2736 }
2737
2738 date = (UDate)693792000000.0; // 1992 - one currency defined
2739 index = ucurr_countCurrencies("eo_AM", date, &status);
2740 if (index != 1)
2741 {
729e4ab9 2742 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
46f4442e
A
2743 }
2744 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2745 tempStr.setTo(TMP);
2746 resultStr.setTo("RUR");
2747 if (resultStr != tempStr) {
729e4ab9 2748 errcheckln(status, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status));
46f4442e
A
2749 }
2750
2751 date = (UDate)977616000000.0; // post 1993 - one currency defined
2752 index = ucurr_countCurrencies("eo_AM", date, &status);
2753 if (index != 1)
2754 {
729e4ab9 2755 errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status));
46f4442e
A
2756 }
2757 resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status);
2758 tempStr.setTo(TMP);
2759 resultStr.setTo("AMD");
2760 if (resultStr != tempStr) {
729e4ab9 2761 errcheckln(status, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status));
46f4442e
A
2762 }
2763
2764 // Locale AD has multiple currencies at once
2765 date = (UDate)977616000000.0; // year 2001
2766 index = ucurr_countCurrencies("eo_AD", date, &status);
2767 if (index != 4)
2768 {
729e4ab9 2769 errcheckln(status, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status));
46f4442e
A
2770 }
2771 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2772 tempStr.setTo(TMP);
2773 resultStr.setTo("EUR");
2774 if (resultStr != tempStr) {
729e4ab9 2775 errcheckln(status, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status));
46f4442e
A
2776 }
2777 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2778 tempStr.setTo(TMP);
2779 resultStr.setTo("ESP");
2780 if (resultStr != tempStr) {
729e4ab9 2781 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
46f4442e
A
2782 }
2783 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
2784 tempStr.setTo(TMP);
2785 resultStr.setTo("FRF");
2786 if (resultStr != tempStr) {
729e4ab9 2787 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
46f4442e
A
2788 }
2789 resLen = ucurr_forLocaleAndDate("eo_AD", date, 4, TMP, 4, &status);
2790 tempStr.setTo(TMP);
2791 resultStr.setTo("ADP");
2792 if (resultStr != tempStr) {
729e4ab9 2793 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
46f4442e
A
2794 }
2795
2796 date = (UDate)0.0; // year 1970
2797 index = ucurr_countCurrencies("eo_AD", date, &status);
2798 if (index != 3)
2799 {
729e4ab9 2800 errcheckln(status, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status));
46f4442e
A
2801 }
2802 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2803 tempStr.setTo(TMP);
2804 resultStr.setTo("ESP");
2805 if (resultStr != tempStr) {
729e4ab9 2806 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
46f4442e
A
2807 }
2808 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2809 tempStr.setTo(TMP);
2810 resultStr.setTo("FRF");
2811 if (resultStr != tempStr) {
729e4ab9 2812 errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status));
46f4442e
A
2813 }
2814 resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status);
2815 tempStr.setTo(TMP);
2816 resultStr.setTo("ADP");
2817 if (resultStr != tempStr) {
729e4ab9 2818 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
46f4442e
A
2819 }
2820
2821 date = (UDate)-630720000000.0; // year 1950
2822 index = ucurr_countCurrencies("eo_AD", date, &status);
2823 if (index != 2)
2824 {
729e4ab9 2825 errcheckln(status, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status));
46f4442e
A
2826 }
2827 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2828 tempStr.setTo(TMP);
2829 resultStr.setTo("ESP");
2830 if (resultStr != tempStr) {
729e4ab9 2831 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
46f4442e
A
2832 }
2833 resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status);
2834 tempStr.setTo(TMP);
2835 resultStr.setTo("ADP");
2836 if (resultStr != tempStr) {
729e4ab9 2837 errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status));
46f4442e
A
2838 }
2839
2840 date = (UDate)-2207520000000.0; // year 1900
2841 index = ucurr_countCurrencies("eo_AD", date, &status);
2842 if (index != 1)
2843 {
729e4ab9 2844 errcheckln(status, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status));
46f4442e
A
2845 }
2846 resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status);
2847 tempStr.setTo(TMP);
2848 resultStr.setTo("ESP");
2849 if (resultStr != tempStr) {
729e4ab9 2850 errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status));
46f4442e
A
2851 }
2852
2853 // Locale UA has gap between years 1994 - 1996
2854 date = (UDate)788400000000.0;
2855 index = ucurr_countCurrencies("eo_UA", date, &status);
2856 if (index != 0)
2857 {
729e4ab9 2858 errcheckln(status, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status));
46f4442e
A
2859 }
2860 resLen = ucurr_forLocaleAndDate("eo_UA", date, index, TMP, 4, &status);
2861 if (resLen != 0) {
729e4ab9 2862 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
46f4442e
A
2863 }
2864 status = U_ZERO_ERROR;
2865
2866 // Test index bounds
2867 resLen = ucurr_forLocaleAndDate("eo_UA", date, 100, TMP, 4, &status);
2868 if (resLen != 0) {
729e4ab9 2869 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
46f4442e
A
2870 }
2871 status = U_ZERO_ERROR;
2872
2873 resLen = ucurr_forLocaleAndDate("eo_UA", date, 0, TMP, 4, &status);
2874 if (resLen != 0) {
729e4ab9 2875 errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status));
46f4442e
A
2876 }
2877 status = U_ZERO_ERROR;
2878
2879 // Test for bogus locale
2880 index = ucurr_countCurrencies("eo_QQ", date, &status);
2881 if (index != 0)
2882 {
729e4ab9 2883 errcheckln(status, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status));
46f4442e
A
2884 }
2885 status = U_ZERO_ERROR;
2886 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 1, TMP, 4, &status);
2887 if (resLen != 0) {
729e4ab9 2888 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
46f4442e
A
2889 }
2890 status = U_ZERO_ERROR;
2891 resLen = ucurr_forLocaleAndDate("eo_QQ", date, 0, TMP, 4, &status);
2892 if (resLen != 0) {
729e4ab9 2893 errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status));
46f4442e
A
2894 }
2895 status = U_ZERO_ERROR;
2896
2897 // Cycle through histrocial currencies
2898 date = (UDate)977616000000.0; // 2001 - one currency
2899 index = ucurr_countCurrencies("eo_AO", date, &status);
2900 if (index != 1)
2901 {
729e4ab9 2902 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
46f4442e
A
2903 }
2904 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2905 tempStr.setTo(TMP);
2906 resultStr.setTo("AOA");
2907 if (resultStr != tempStr) {
729e4ab9 2908 errcheckln(status, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status));
46f4442e
A
2909 }
2910
2911 date = (UDate)819936000000.0; // 1996 - 2 currencies
2912 index = ucurr_countCurrencies("eo_AO", date, &status);
2913 if (index != 2)
2914 {
729e4ab9 2915 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
46f4442e
A
2916 }
2917 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2918 tempStr.setTo(TMP);
2919 resultStr.setTo("AOR");
2920 if (resultStr != tempStr) {
729e4ab9 2921 errcheckln(status, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status));
46f4442e
A
2922 }
2923 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
2924 tempStr.setTo(TMP);
2925 resultStr.setTo("AON");
2926 if (resultStr != tempStr) {
729e4ab9 2927 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
46f4442e
A
2928 }
2929
2930 date = (UDate)662256000000.0; // 1991 - 2 currencies
2931 index = ucurr_countCurrencies("eo_AO", date, &status);
2932 if (index != 2)
2933 {
729e4ab9 2934 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
46f4442e
A
2935 }
2936 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2937 tempStr.setTo(TMP);
2938 resultStr.setTo("AON");
2939 if (resultStr != tempStr) {
729e4ab9 2940 errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status));
46f4442e
A
2941 }
2942 resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status);
2943 tempStr.setTo(TMP);
2944 resultStr.setTo("AOK");
2945 if (resultStr != tempStr) {
729e4ab9 2946 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
46f4442e
A
2947 }
2948
2949 date = (UDate)315360000000.0; // 1980 - one currency
2950 index = ucurr_countCurrencies("eo_AO", date, &status);
2951 if (index != 1)
2952 {
729e4ab9 2953 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
46f4442e
A
2954 }
2955 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2956 tempStr.setTo(TMP);
2957 resultStr.setTo("AOK");
2958 if (resultStr != tempStr) {
729e4ab9 2959 errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status));
46f4442e
A
2960 }
2961
2962 date = (UDate)0.0; // 1970 - no currencies
2963 index = ucurr_countCurrencies("eo_AO", date, &status);
2964 if (index != 0)
2965 {
729e4ab9 2966 errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status));
46f4442e
A
2967 }
2968 resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status);
2969 if (resLen != 0) {
729e4ab9 2970 errcheckln(status, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status));
46f4442e
A
2971 }
2972 status = U_ZERO_ERROR;
2973
2974 // Test with currency keyword override
2975 date = (UDate)977616000000.0; // 2001 - two currencies
2976 index = ucurr_countCurrencies("eo_DE@currency=DEM", date, &status);
2977 if (index != 2)
2978 {
729e4ab9 2979 errcheckln(status, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status));
46f4442e
A
2980 }
2981 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 1, TMP, 4, &status);
2982 tempStr.setTo(TMP);
2983 resultStr.setTo("EUR");
2984 if (resultStr != tempStr) {
729e4ab9 2985 errcheckln(status, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status));
46f4442e
A
2986 }
2987 resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 2, TMP, 4, &status);
2988 tempStr.setTo(TMP);
2989 resultStr.setTo("DEM");
2990 if (resultStr != tempStr) {
729e4ab9 2991 errcheckln(status, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status));
46f4442e
A
2992 }
2993
2994 // Test Euro Support
2995 status = U_ZERO_ERROR; // reset
2996 date = uprv_getUTCtime();
2997
2998 UChar USD[4];
2999 ucurr_forLocaleAndDate("en_US", date, 1, USD, 4, &status);
3000
3001 UChar YEN[4];
3002 ucurr_forLocaleAndDate("ja_JP", date, 1, YEN, 4, &status);
3003
3004 ucurr_forLocaleAndDate("en_US", date, 1, TMP, 4, &status);
3005 if (u_strcmp(USD, TMP) != 0) {
729e4ab9 3006 errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status));
46f4442e 3007 }
46f4442e
A
3008 ucurr_forLocaleAndDate("en_US_Q", date, 1, TMP, 4, &status);
3009 if (u_strcmp(USD, TMP) != 0) {
729e4ab9 3010 errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status));
46f4442e
A
3011 }
3012 status = U_ZERO_ERROR; // reset
3013#endif
3014}
729e4ab9
A
3015
3016void LocaleTest::TestGetVariantWithKeywords(void)
3017{
3018 Locale l("en_US_VALLEY@foo=value");
3019 const char *variant = l.getVariant();
3020 logln(variant);
3021 test_assert(strcmp("VALLEY", variant) == 0);
3022
3023 UErrorCode status = U_ZERO_ERROR;
3024 char buffer[50];
3025 int32_t len = l.getKeywordValue("foo", buffer, 50, status);
3026 buffer[len] = '\0';
3027 test_assert(strcmp("value", buffer) == 0);
3028}
b331163b
A
3029
3030void LocaleTest::TestIsRightToLeft() {
3031 assertFalse("root LTR", Locale::getRoot().isRightToLeft());
3032 assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
3033 assertTrue("ar RTL", Locale("ar").isRightToLeft());
3034 assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), FALSE, TRUE);
3035 assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
3036 assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
3037 assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), FALSE, TRUE); // Sorani Kurdish
3038 assertFalse("fil LTR", Locale("fil").isRightToLeft());
3039 assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
3d1f044b
A
3040 // Additional Apple tests for rdar://51447187
3041 assertTrue("sd RTL", Locale("sd").isRightToLeft());
3042 assertTrue("sd_Arab RTL", Locale("sd_Arab").isRightToLeft());
3043 assertFalse("sd_Deva LTR", Locale("sd_Deva").isRightToLeft());
3044 assertFalse("mni_Beng LTR", Locale("mni_Beng").isRightToLeft());
3045 assertFalse("mni_Mtei LTR", Locale("mni_Mtei").isRightToLeft());
3046 assertFalse("sat_Deva LTR", Locale("sat_Deva").isRightToLeft());
3047 assertFalse("sat_Olck LTR", Locale("sat_Olck").isRightToLeft());
3048 assertTrue("ks RTL", Locale("ks").isRightToLeft());
3049 assertTrue("ks_Arab RTL", Locale("ks_Arab").isRightToLeft());
3050 assertTrue("ks_Aran RTL", Locale("ks_Aran").isRightToLeft());
3051 assertFalse("ks_Deva LTR", Locale("ks_Deva").isRightToLeft());
3052 assertFalse("pa LTR", Locale("pa").isRightToLeft());
3053 assertFalse("pa_Guru LTR", Locale("pa_Guru").isRightToLeft());
3054 assertTrue("pa_Arab RTL", Locale("pa_Arab").isRightToLeft());
3055 assertTrue("pa_Aran RTL", Locale("pa_Aran").isRightToLeft());
3056 assertTrue("ur RTL", Locale("ur").isRightToLeft());
3057 assertTrue("ur_Arab RTL", Locale("ur_Arab").isRightToLeft());
3058 assertTrue("ur_Aran RTL", Locale("ur_Aran").isRightToLeft());
b331163b
A
3059}
3060
3061void LocaleTest::TestBug11421() {
3062 Locale::getDefault().getBaseName();
3063 int32_t numLocales;
3064 const Locale *localeList = Locale::getAvailableLocales(numLocales);
3065 for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) {
3066 const Locale &loc = localeList[localeIndex];
3067 if (strncmp(loc.getName(), loc.getBaseName(), strlen(loc.getBaseName()))) {
3068 errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"",
3069 __FILE__, __LINE__, loc.getName(), loc.getBaseName());
3070 break;
3071 }
3072 }
3073}
0f5d89e8
A
3074
3075// TestBug13277. The failure manifests as valgrind errors.
3076// See the trac ticket for details.
3077//
3078
3079void LocaleTest::TestBug13277() {
3080 UErrorCode status = U_ZERO_ERROR;
3081 CharString name("en-us-x-foo", -1, status);
3082 while (name.length() < 152) {
3083 name.append("-x-foo", -1, status);
3084 }
3085
3086 while (name.length() < 160) {
3087 name.append('z', status);
3088 Locale loc(name.data(), nullptr, nullptr, nullptr);
3089 }
3090}
3091
3092// TestBug13554 Check for read past end of array in getPosixID().
3093// The bug shows as an Address Sanitizer failure.
3094
3095void LocaleTest::TestBug13554() {
3096 UErrorCode status = U_ZERO_ERROR;
3097 const int BUFFER_SIZE = 100;
3098 char posixID[BUFFER_SIZE];
3099
3100 for (uint32_t hostid = 0; hostid < 0x500; ++hostid) {
3101 status = U_ZERO_ERROR;
3102 uprv_convertToPosix(hostid, posixID, BUFFER_SIZE, &status);
3103 }
3104}
3105
3d1f044b
A
3106void LocaleTest::TestBug20410() {
3107 IcuTestErrorCode status(*this, "TestBug20410()");
3108
3109 static const char tag1[] = "art-lojban-x-0";
3110 static const Locale expected1("jbo@x=0");
3111 Locale result1 = Locale::forLanguageTag(tag1, status);
3112 status.errIfFailureAndReset("\"%s\"", tag1);
3113 assertEquals(tag1, expected1.getName(), result1.getName());
3114
3115 static const char tag2[] = "zh-xiang-u-nu-thai-x-0";
3116 static const Locale expected2("hsn@numbers=thai;x=0");
3117 Locale result2 = Locale::forLanguageTag(tag2, status);
3118 status.errIfFailureAndReset("\"%s\"", tag2);
3119 assertEquals(tag2, expected2.getName(), result2.getName());
3120
3121 static const char locid3[] = "art__lojban@x=0";
3122 Locale result3 = Locale::createCanonical(locid3);
3123 static const Locale expected3("art__LOJBAN@x=0");
3124 assertEquals(locid3, expected3.getName(), result3.getName());
3125
3126 static const char locid4[] = "art-lojban-x-0";
3127 Locale result4 = Locale::createCanonical(locid4);
3128 static const Locale expected4("jbo@x=0");
3129 assertEquals(locid4, expected4.getName(), result4.getName());
3130}
3131
340931cb
A
3132void LocaleTest::TestConstructorAcceptsBCP47() {
3133 IcuTestErrorCode status(*this, "TestConstructorAcceptsBCP47");
3134
3135 Locale loc1("ar-EG-u-nu-latn");
3136 Locale loc2("ar-EG@numbers=latn");
3137 Locale loc3("ar-EG");
3138 std::string val;
3139
3140 // Check getKeywordValue "numbers"
3141 val = loc1.getKeywordValue<std::string>("numbers", status);
3142 assertEquals("BCP47 syntax has ICU keyword value", "latn", val.c_str());
3143
3144 val = loc2.getKeywordValue<std::string>("numbers", status);
3145 assertEquals("ICU syntax has ICU keyword value", "latn", val.c_str());
3146
3147 val = loc3.getKeywordValue<std::string>("numbers", status);
3148 assertEquals("Default, ICU keyword", "", val.c_str());
3149
3150 // Check getUnicodeKeywordValue "nu"
3151 val = loc1.getUnicodeKeywordValue<std::string>("nu", status);
3152 assertEquals("BCP47 syntax has short unicode keyword value", "latn", val.c_str());
3153
3154 val = loc2.getUnicodeKeywordValue<std::string>("nu", status);
3155 assertEquals("ICU syntax has short unicode keyword value", "latn", val.c_str());
3156
3157 val = loc3.getUnicodeKeywordValue<std::string>("nu", status);
3158 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, short unicode keyword");
3159
3160 // Check getUnicodeKeywordValue "numbers"
3161 val = loc1.getUnicodeKeywordValue<std::string>("numbers", status);
3162 assertEquals("BCP47 syntax has long unicode keyword value", "latn", val.c_str());
3163
3164 val = loc2.getUnicodeKeywordValue<std::string>("numbers", status);
3165 assertEquals("ICU syntax has long unicode keyword value", "latn", val.c_str());
3166
3167 val = loc3.getUnicodeKeywordValue<std::string>("numbers", status);
3168 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, long unicode keyword");
3169}
3170
3d1f044b
A
3171void LocaleTest::TestForLanguageTag() {
3172 IcuTestErrorCode status(*this, "TestForLanguageTag()");
3173
3174 static const char tag_en[] = "en-US";
3175 static const char tag_oed[] = "en-GB-oed";
3176 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
3177 static const char tag_ill[] = "!";
3178 static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' };
3179 static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz";
3180
3181 static const Locale loc_en("en_US");
3182 static const Locale loc_oed("en_GB_OXENDICT");
3183 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
3184 static const Locale loc_null("");
3185 static const Locale loc_gb("en_GB");
3186 static const Locale loc_ext("en_GB@1=abc-efg;a=xyz");
3187
3188 Locale result_en = Locale::forLanguageTag(tag_en, status);
3189 status.errIfFailureAndReset("\"%s\"", tag_en);
3190 assertEquals(tag_en, loc_en.getName(), result_en.getName());
3191
3192 Locale result_oed = Locale::forLanguageTag(tag_oed, status);
3193 status.errIfFailureAndReset("\"%s\"", tag_oed);
3194 assertEquals(tag_oed, loc_oed.getName(), result_oed.getName());
3195
3196 Locale result_af = Locale::forLanguageTag(tag_af, status);
3197 status.errIfFailureAndReset("\"%s\"", tag_af);
3198 assertEquals(tag_af, loc_af.getName(), result_af.getName());
3199
3200 Locale result_ill = Locale::forLanguageTag(tag_ill, status);
3201 assertEquals(tag_ill, U_ILLEGAL_ARGUMENT_ERROR, status.reset());
3202 assertTrue(result_ill.getName(), result_ill.isBogus());
3203
3204 Locale result_null = Locale::forLanguageTag(nullptr, status);
3205 status.errIfFailureAndReset("nullptr");
3206 assertEquals("nullptr", loc_null.getName(), result_null.getName());
3207
3208 StringPiece sp_substr(tag_oed, 5); // "en-GB", no NUL.
3209 Locale result_substr = Locale::forLanguageTag(sp_substr, status);
3210 status.errIfFailureAndReset("\"%.*s\"", sp_substr.size(), sp_substr.data());
3211 assertEquals(CharString(sp_substr, status).data(),
3212 loc_gb.getName(), result_substr.getName());
3213
3214 StringPiece sp_no_nul(tag_no_nul, sizeof tag_no_nul); // "en-GB", no NUL.
3215 Locale result_no_nul = Locale::forLanguageTag(sp_no_nul, status);
3216 status.errIfFailureAndReset("\"%.*s\"", sp_no_nul.size(), sp_no_nul.data());
3217 assertEquals(CharString(sp_no_nul, status).data(),
3218 loc_gb.getName(), result_no_nul.getName());
3219
3220 Locale result_ext = Locale::forLanguageTag(tag_ext, status);
3221 status.errIfFailureAndReset("\"%s\"", tag_ext);
3222 assertEquals(tag_ext, loc_ext.getName(), result_ext.getName());
3223}
3224
3225void LocaleTest::TestToLanguageTag() {
3226 IcuTestErrorCode status(*this, "TestToLanguageTag()");
3227
3228 static const Locale loc_c("en_US_POSIX");
3229 static const Locale loc_en("en_US");
3230 static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo");
3231 static const Locale loc_ext("en@0=abc;a=xyz");
3232 static const Locale loc_empty("");
3233 static const Locale loc_ill("!");
3234
3235 static const char tag_c[] = "en-US-u-va-posix";
3236 static const char tag_en[] = "en-US";
3237 static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
3238 static const char tag_ext[] = "en-0-abc-a-xyz";
3239 static const char tag_und[] = "und";
3240
3241 std::string result;
3242 StringByteSink<std::string> sink(&result);
3243 loc_c.toLanguageTag(sink, status);
3244 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
3245 assertEquals(loc_c.getName(), tag_c, result.c_str());
3246
3247 std::string result_c = loc_c.toLanguageTag<std::string>(status);
3248 status.errIfFailureAndReset("\"%s\"", loc_c.getName());
3249 assertEquals(loc_c.getName(), tag_c, result_c.c_str());
3250
3251 std::string result_en = loc_en.toLanguageTag<std::string>(status);
3252 status.errIfFailureAndReset("\"%s\"", loc_en.getName());
3253 assertEquals(loc_en.getName(), tag_en, result_en.c_str());
3254
3255 std::string result_af = loc_af.toLanguageTag<std::string>(status);
3256 status.errIfFailureAndReset("\"%s\"", loc_af.getName());
3257 assertEquals(loc_af.getName(), tag_af, result_af.c_str());
3258
3259 std::string result_ext = loc_ext.toLanguageTag<std::string>(status);
3260 status.errIfFailureAndReset("\"%s\"", loc_ext.getName());
3261 assertEquals(loc_ext.getName(), tag_ext, result_ext.c_str());
3262
3263 std::string result_empty = loc_empty.toLanguageTag<std::string>(status);
3264 status.errIfFailureAndReset("\"%s\"", loc_empty.getName());
3265 assertEquals(loc_empty.getName(), tag_und, result_empty.c_str());
3266
3267 std::string result_ill = loc_ill.toLanguageTag<std::string>(status);
3268 status.errIfFailureAndReset("\"%s\"", loc_ill.getName());
3269 assertEquals(loc_ill.getName(), tag_und, result_ill.c_str());
3270
3271 Locale loc_bogus;
3272 loc_bogus.setToBogus();
3273 std::string result_bogus = loc_bogus.toLanguageTag<std::string>(status);
3274 assertEquals("bogus", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
3275 assertTrue(result_bogus.c_str(), result_bogus.empty());
3276}
3277
3278void LocaleTest::TestMoveAssign() {
3279 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
3280 Locale l1("de@collation=phonebook;x="
3281 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3282 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3283 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3284 "aaaaabbbbbzz");
3285
3286 Locale l2;
3287 {
3288 Locale l3(l1);
3289 assertTrue("l1 == l3", l1 == l3);
3290 l2 = std::move(l3);
3291 assertTrue("l1 == l2", l1 == l2);
3292 assertTrue("l2 != l3", l2.getName() != l3.getName());
3293 }
3294
3295 // This should remain true also after l3 has been destructed.
3296 assertTrue("l1 == l2, again", l1 == l2);
3297
3298 Locale l4("de@collation=phonebook");
3299
3300 Locale l5;
3301 {
3302 Locale l6(l4);
3303 assertTrue("l4 == l6", l4 == l6);
3304 l5 = std::move(l6);
3305 assertTrue("l4 == l5", l4 == l5);
3306 assertTrue("l5 != l6", l5.getName() != l6.getName());
3307 }
3308
3309 // This should remain true also after l6 has been destructed.
3310 assertTrue("l4 == l5, again", l4 == l5);
3311
3312 Locale l7("vo_Cyrl_AQ_EURO");
3313
3314 Locale l8;
3315 {
3316 Locale l9(l7);
3317 assertTrue("l7 == l9", l7 == l9);
3318 l8 = std::move(l9);
3319 assertTrue("l7 == l8", l7 == l8);
3320 assertTrue("l8 != l9", l8.getName() != l9.getName());
3321 }
3322
3323 // This should remain true also after l9 has been destructed.
3324 assertTrue("l7 == l8, again", l7 == l8);
3325
3326 assertEquals("language", l7.getLanguage(), l8.getLanguage());
3327 assertEquals("script", l7.getScript(), l8.getScript());
3328 assertEquals("country", l7.getCountry(), l8.getCountry());
3329 assertEquals("variant", l7.getVariant(), l8.getVariant());
3330 assertEquals("bogus", l7.isBogus(), l8.isBogus());
3331}
3332
3333void LocaleTest::TestMoveCtor() {
3334 // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
3335 Locale l1("de@collation=phonebook;x="
3336 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3337 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3338 "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
3339 "aaaaabbbbbzz");
3340
3341 Locale l3(l1);
3342 assertTrue("l1 == l3", l1 == l3);
3343 Locale l2(std::move(l3));
3344 assertTrue("l1 == l2", l1 == l2);
3345 assertTrue("l2 != l3", l2.getName() != l3.getName());
3346
3347 Locale l4("de@collation=phonebook");
3348
3349 Locale l6(l4);
3350 assertTrue("l4 == l6", l4 == l6);
3351 Locale l5(std::move(l6));
3352 assertTrue("l4 == l5", l4 == l5);
3353 assertTrue("l5 != l6", l5.getName() != l6.getName());
3354
3355 Locale l7("vo_Cyrl_AQ_EURO");
3356
3357 Locale l9(l7);
3358 assertTrue("l7 == l9", l7 == l9);
3359 Locale l8(std::move(l9));
3360 assertTrue("l7 == l8", l7 == l8);
3361 assertTrue("l8 != l9", l8.getName() != l9.getName());
3362
3363 assertEquals("language", l7.getLanguage(), l8.getLanguage());
3364 assertEquals("script", l7.getScript(), l8.getScript());
3365 assertEquals("country", l7.getCountry(), l8.getCountry());
3366 assertEquals("variant", l7.getVariant(), l8.getVariant());
3367 assertEquals("bogus", l7.isBogus(), l8.isBogus());
3368}
3369
3370void LocaleTest::TestBug20407iVariantPreferredValue() {
3371 IcuTestErrorCode status(*this, "TestBug20407iVariantPreferredValue()");
0f5d89e8 3372
3d1f044b
A
3373 Locale l = Locale::forLanguageTag("hy-arevela", status);
3374 status.errIfFailureAndReset("hy-arevela fail");
3375 assertTrue("!l.isBogus()", !l.isBogus());
3376
3377 std::string result = l.toLanguageTag<std::string>(status);
3378 assertEquals(l.getName(), "hy", result.c_str());
3379
3380 l = Locale::forLanguageTag("hy-arevmda", status);
3381 status.errIfFailureAndReset("hy-arevmda");
3382 assertTrue("!l.isBogus()", !l.isBogus());
3383
3384 result = l.toLanguageTag<std::string>(status);
3385 assertEquals(l.getName(), "hyw", result.c_str());
3386}
3387
3388void LocaleTest::TestBug13417VeryLongLanguageTag() {
3389 IcuTestErrorCode status(*this, "TestBug13417VeryLongLanguageTag()");
3390
3391 static const char tag[] =
3392 "zh-x"
3393 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3394 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3395 "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz"
3396 "-foo-bar-baz-fxx"
3397 ;
3398
3399 Locale l = Locale::forLanguageTag(tag, status);
3400 status.errIfFailureAndReset("\"%s\"", tag);
3401 assertTrue("!l.isBogus()", !l.isBogus());
3402
3403 std::string result = l.toLanguageTag<std::string>(status);
3404 status.errIfFailureAndReset("\"%s\"", l.getName());
3405 assertEquals("equals", tag, result.c_str());
3406}
3407
3408void LocaleTest::TestBug11053UnderlineTimeZone() {
3409 static const char* const tz_in_ext[] = {
3410 "etadd",
3411 "tzdar",
3412 "eheai",
3413 "sttms",
3414 "arirj",
3415 "arrgl",
3416 "aruaq",
3417 "arluq",
3418 "mxpvr",
3419 "brbvb",
3420 "arbue",
3421 "caycb",
3422 "brcgr",
3423 "cayzs",
3424 "crsjo",
3425 "caydq",
3426 "svsal",
3427 "cafne",
3428 "caglb",
3429 "cagoo",
3430 "tcgdt",
3431 "ustel",
3432 "bolpb",
3433 "uslax",
3434 "sxphi",
3435 "mxmex",
3436 "usnyc",
3437 "usxul",
3438 "usndcnt",
3439 "usndnsl",
3440 "ttpos",
3441 "brpvh",
3442 "prsju",
3443 "clpuq",
3444 "caffs",
3445 "cayek",
3446 "brrbr",
3447 "mxstis",
3448 "dosdq",
3449 "brsao",
3450 "gpsbh",
3451 "casjf",
3452 "knbas",
3453 "lccas",
3454 "vistt",
3455 "vcsvd",
3456 "cayyn",
3457 "cathu",
3458 "hkhkg",
3459 "mykul",
3460 "khpnh",
3461 "cvrai",
3462 "gsgrv",
3463 "shshn",
3464 "aubhq",
3465 "auldh",
3466 "imdgs",
3467 "smsai",
3468 "asppg",
3469 "pgpom",
3470 };
3471 static const char* const tzname_with_underline[] = {
3472 "America/Buenos_Aires",
3473 "America/Coral_Harbour",
3474 "America/Los_Angeles",
3475 "America/Mexico_City",
3476 "America/New_York",
3477 "America/Rio_Branco",
3478 "America/Sao_Paulo",
3479 "America/St_Johns",
3480 "America/St_Thomas",
3481 "Australia/Broken_Hill",
3482 "Australia/Lord_Howe",
3483 "Pacific/Pago_Pago",
3484 };
3485 std::string locale_str;
3486 for (int32_t i = 0; i < UPRV_LENGTHOF(tz_in_ext); i++) {
3487 locale_str = "en-u-tz-";
3488 locale_str += tz_in_ext[i];
3489 Locale l(locale_str.c_str());
3490 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
3491 }
3492 for (int32_t i = 0; i < UPRV_LENGTHOF(tzname_with_underline); i++) {
3493 locale_str = "en@timezone=";
3494 locale_str += tzname_with_underline[i];
3495 Locale l(locale_str.c_str());
3496 assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus());
3497 }
3498 locale_str = "en_US@timezone=America/Coral_Harbour";
3499 Locale l2(locale_str.c_str());
3500 assertTrue((locale_str + " !l2.isBogus()").c_str(), !l2.isBogus());
3501 locale_str = "en_Latn@timezone=America/New_York";
3502 Locale l3(locale_str.c_str());
3503 assertTrue((locale_str + " !l3.isBogus()").c_str(), !l3.isBogus());
3504 locale_str = "en_Latn_US@timezone=Australia/Broken_Hill";
3505 Locale l4(locale_str.c_str());
3506 assertTrue((locale_str + " !l4.isBogus()").c_str(), !l4.isBogus());
3507 locale_str = "en-u-tz-ciabj";
3508 Locale l5(locale_str.c_str());
3509 assertTrue((locale_str + " !l5.isBogus()").c_str(), !l5.isBogus());
3510 locale_str = "en-US-u-tz-asppg";
3511 Locale l6(locale_str.c_str());
3512 assertTrue((locale_str + " !l6.isBogus()").c_str(), !l6.isBogus());
3513 locale_str = "fil-Latn-u-tz-cvrai";
3514 Locale l7(locale_str.c_str());
3515 assertTrue((locale_str + " !l7.isBogus()").c_str(), !l7.isBogus());
3516 locale_str = "fil-Latn-PH-u-tz-gsgrv";
3517 Locale l8(locale_str.c_str());
3518 assertTrue((locale_str + " !l8.isBogus()").c_str(), !l8.isBogus());
3519}
3520
3521void LocaleTest::TestUnd() {
3522 IcuTestErrorCode status(*this, "TestUnd()");
3523
3524 static const char empty[] = "";
3525 static const char root[] = "root";
3526 static const char und[] = "und";
3527
3528 Locale empty_ctor(empty);
3529 Locale empty_tag = Locale::forLanguageTag(empty, status);
3530 status.errIfFailureAndReset("\"%s\"", empty);
3531
3532 Locale root_ctor(root);
3533 Locale root_tag = Locale::forLanguageTag(root, status);
3534 Locale root_build = LocaleBuilder().setLanguageTag(root).build(status);
3535 status.errIfFailureAndReset("\"%s\"", root);
3536
3537 Locale und_ctor(und);
3538 Locale und_tag = Locale::forLanguageTag(und, status);
3539 Locale und_build = LocaleBuilder().setLanguageTag(und).build(status);
3540 status.errIfFailureAndReset("\"%s\"", und);
3541
3542 assertEquals("getName() 1", empty, empty_ctor.getName());
3543 assertEquals("getName() 2", root, root_ctor.getName()); // open ICU expects empty
3544 assertEquals("getName() 3", und, und_ctor.getName()); // open ICU expects empty
3545
3546 assertEquals("getName() 4", empty, empty_tag.getName());
3547 assertEquals("getName() 5", root, root_tag.getName()); // open ICU expects empty
3548 assertEquals("getName() 6", empty, und_tag.getName());
3549
3550 assertEquals("getName() 7", root, root_build.getName()); // open ICU expects empty
3551 assertEquals("getName() 8", empty, und_build.getName());
3552
3553 assertEquals("toLanguageTag() 1", und, empty_ctor.toLanguageTag<std::string>(status).c_str());
3554 assertEquals("toLanguageTag() 2", root, root_ctor.toLanguageTag<std::string>(status).c_str()); // open ICU expects und
3555 assertEquals("toLanguageTag() 3", und, und_ctor.toLanguageTag<std::string>(status).c_str());
3556 status.errIfFailureAndReset();
3557
3558 assertEquals("toLanguageTag() 4", und, empty_tag.toLanguageTag<std::string>(status).c_str());
3559 assertEquals("toLanguageTag() 5", root, root_tag.toLanguageTag<std::string>(status).c_str()); // open ICU expects und
3560 assertEquals("toLanguageTag() 6", und, und_tag.toLanguageTag<std::string>(status).c_str());
3561 status.errIfFailureAndReset();
3562
3563 assertEquals("toLanguageTag() 7", root, root_build.toLanguageTag<std::string>(status).c_str()); // open ICU expects und
3564 assertEquals("toLanguageTag() 8", und, und_build.toLanguageTag<std::string>(status).c_str());
3565 status.errIfFailureAndReset();
3566
3567 assertTrue("empty_ctor == empty_tag", empty_ctor == empty_tag);
3568
3569 assertTrue("root_ctor == root_tag", root_ctor == root_tag);
3570 assertTrue("root_ctor == root_build", root_ctor == root_build);
3571 assertTrue("root_tag == root_build", root_tag == root_build);
3572
3573 //assertTrue("und_ctor == und_tag", und_ctor == und_tag); // change from open ICU
3574 //assertTrue("und_ctor == und_build", und_ctor == und_build); // change from open ICU
3575 assertTrue("und_tag == und_build", und_tag == und_build);
3576
3577 //assertTrue("empty_ctor == root_ctor", empty_ctor == root_ctor); // change from open ICU
3578 //assertTrue("empty_ctor == und_ctor", empty_ctor == und_ctor); // change from open ICU
3579 //assertTrue("root_ctor == und_ctor", root_ctor == und_ctor); // change from open ICU
3580
3581 //assertTrue("empty_tag == root_tag", empty_tag == root_tag); // change from open ICU
3582 assertTrue("empty_tag == und_tag", empty_tag == und_tag);
3583 //assertTrue("root_tag == und_tag", root_tag == und_tag); // change from open ICU
3584
3585 //assertTrue("root_build == und_build", root_build == und_build); // change from open ICU
3586
3587 static const Locale& displayLocale = Locale::getEnglish();
3588 static const UnicodeString displayName("Unknown language");
3589 static const UnicodeString displayRoot("Root");
3590 static const UnicodeString displayEmpty("");
3591 UnicodeString tmp;
3592
3593 assertEquals("getDisplayName() 1", displayEmpty, empty_ctor.getDisplayName(displayLocale, tmp)); // change from open ICU
3594 assertEquals("getDisplayName() 2", displayRoot, root_ctor.getDisplayName(displayLocale, tmp)); // change from open ICU
3595 assertEquals("getDisplayName() 3", displayName, und_ctor.getDisplayName(displayLocale, tmp));
3596
3597 assertEquals("getDisplayName() 4", displayEmpty, empty_tag.getDisplayName(displayLocale, tmp)); // change from open ICU
3598 assertEquals("getDisplayName() 5", displayRoot, root_tag.getDisplayName(displayLocale, tmp)); // change from open ICU
3599 assertEquals("getDisplayName() 6", displayEmpty, und_tag.getDisplayName(displayLocale, tmp)); // change from open ICU
3600
3601 assertEquals("getDisplayName() 7", displayRoot, root_build.getDisplayName(displayLocale, tmp)); // change from open ICU
3602 assertEquals("getDisplayName() 8", displayEmpty, und_build.getDisplayName(displayLocale, tmp)); // change from open ICU
3603}
3604
3605void LocaleTest::TestUndScript() {
3606 IcuTestErrorCode status(*this, "TestUndScript()");
3607
3608 static const char id[] = "_Cyrl";
3609 static const char tag[] = "und-Cyrl";
3610 static const char script[] = "Cyrl";
3611 static const char tag_[] = "und_Cyrl";
3612
3613 Locale locale_ctor(id);
3614 Locale locale_legacy(tag);
3615 Locale locale_tag = Locale::forLanguageTag(tag, status);
3616 Locale locale_build = LocaleBuilder().setScript(script).build(status);
3617 status.errIfFailureAndReset("\"%s\"", tag);
3618
3619 assertEquals("getName() 1", id, locale_ctor.getName());
3620 assertEquals("getName() 2", tag_, locale_legacy.getName()); // change from open ICU
3621 assertEquals("getName() 3", id, locale_tag.getName());
3622 assertEquals("getName() 4", id, locale_build.getName());
3623
3624 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
3625 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
3626 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
3627 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
3628 status.errIfFailureAndReset();
3629
3630 static const Locale& displayLocale = Locale::getEnglish();
3631 static const UnicodeString displayName("Unknown language (Cyrillic)");
3632 static const UnicodeString displayScript("Cyrillic");
3633 UnicodeString tmp;
3634
3635 assertEquals("getDisplayName() 1", displayScript, locale_ctor.getDisplayName(displayLocale, tmp)); // change from open-source
3636 assertEquals("getDisplayName() 2", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
3637 assertEquals("getDisplayName() 3", displayScript, locale_tag.getDisplayName(displayLocale, tmp)); // change from open-source
3638 assertEquals("getDisplayName() 4", displayScript, locale_build.getDisplayName(displayLocale, tmp)); // change from open-source
3639}
3640
3641void LocaleTest::TestUndRegion() {
3642 IcuTestErrorCode status(*this, "TestUndRegion()");
3643
3644 static const char id[] = "_AQ";
3645 static const char tag[] = "und-AQ";
3646 static const char region[] = "AQ";
3647 static const char tag_[] = "und_AQ";
3648
3649 Locale locale_ctor(id);
3650 Locale locale_legacy(tag);
3651 Locale locale_tag = Locale::forLanguageTag(tag, status);
3652 Locale locale_build = LocaleBuilder().setRegion(region).build(status);
3653 status.errIfFailureAndReset("\"%s\"", tag);
3654
3655 assertEquals("getName() 1", id, locale_ctor.getName());
3656 assertEquals("getName() 2", tag_, locale_legacy.getName()); // change from open ICU
3657 assertEquals("getName() 3", id, locale_tag.getName());
3658 assertEquals("getName() 4", id, locale_build.getName());
3659
3660 assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str());
3661 assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str());
3662 assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str());
3663 assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str());
3664 status.errIfFailureAndReset();
3665
3666 static const Locale& displayLocale = Locale::getEnglish();
3667 static const UnicodeString displayName("Unknown language (Antarctica)");
3668 static const UnicodeString displayRegion("Antarctica");
3669 UnicodeString tmp;
3670
3671 assertEquals("getDisplayName() 1", displayRegion, locale_ctor.getDisplayName(displayLocale, tmp)); // change from open-source
3672 assertEquals("getDisplayName() 2", displayName, locale_legacy.getDisplayName(displayLocale, tmp));
3673 assertEquals("getDisplayName() 3", displayRegion, locale_tag.getDisplayName(displayLocale, tmp)); // change from open-source
3674 assertEquals("getDisplayName() 4", displayRegion, locale_build.getDisplayName(displayLocale, tmp)); // change from open-source
3675}
3676
3677void LocaleTest::TestUndCAPI() {
3678 IcuTestErrorCode status(*this, "TestUndCAPI()");
3679
3680 static const char empty[] = "";
3681 static const char root[] = "root";
3682 static const char und[] = "und";
3683
3684 static const char empty_script[] = "_Cyrl";
3685 static const char empty_region[] = "_AQ";
3686
3687 static const char und_script[] = "und_Cyrl";
3688 static const char und_region[] = "und_AQ";
3689
3690 char tmp[ULOC_FULLNAME_CAPACITY];
3691 int32_t reslen;
3692
3693 // uloc_getName()
3694
3695 uprv_memset(tmp, '!', sizeof tmp);
3696 reslen = uloc_getName(empty, tmp, sizeof tmp, status);
3697 status.errIfFailureAndReset("\"%s\"", empty);
3698 assertTrue("reslen >= 0", reslen >= 0);
3699 assertEquals("uloc_getName() 1", empty, tmp);
3700
3701 uprv_memset(tmp, '!', sizeof tmp);
3702 reslen = uloc_getName(root, tmp, sizeof tmp, status);
3703 status.errIfFailureAndReset("\"%s\"", root);
3704 assertTrue("reslen >= 0", reslen >= 0);
3705 assertEquals("uloc_getName() 2", root, tmp); // change from open ICU
3706
3707 uprv_memset(tmp, '!', sizeof tmp);
3708 reslen = uloc_getName(und, tmp, sizeof tmp, status);
3709 status.errIfFailureAndReset("\"%s\"", und);
3710 assertTrue("reslen >= 0", reslen >= 0);
3711 assertEquals("uloc_getName() 3", und, tmp); // change from open ICU
3712
3713 uprv_memset(tmp, '!', sizeof tmp);
3714 reslen = uloc_getName(empty_script, tmp, sizeof tmp, status);
3715 status.errIfFailureAndReset("\"%s\"", empty_script);
3716 assertTrue("reslen >= 0", reslen >= 0);
3717 assertEquals("uloc_getName() 4", empty_script, tmp);
3718
3719 uprv_memset(tmp, '!', sizeof tmp);
3720 reslen = uloc_getName(empty_region, tmp, sizeof tmp, status);
3721 status.errIfFailureAndReset("\"%s\"", empty_region);
3722 assertTrue("reslen >= 0", reslen >= 0);
3723 assertEquals("uloc_getName() 5", empty_region, tmp);
3724
3725 uprv_memset(tmp, '!', sizeof tmp);
3726 reslen = uloc_getName(und_script, tmp, sizeof tmp, status);
3727 status.errIfFailureAndReset("\"%s\"", und_script);
3728 assertTrue("reslen >= 0", reslen >= 0);
3729 assertEquals("uloc_getName() 6", und_script, tmp); // change from open ICU
3730
3731 uprv_memset(tmp, '!', sizeof tmp);
3732 reslen = uloc_getName(und_region, tmp, sizeof tmp, status);
3733 status.errIfFailureAndReset("\"%s\"", und_region);
3734 assertTrue("reslen >= 0", reslen >= 0);
3735 assertEquals("uloc_getName() 7", und_region, tmp); // change from open ICU
3736
3737 // uloc_getBaseName()
3738
3739 uprv_memset(tmp, '!', sizeof tmp);
3740 reslen = uloc_getBaseName(empty, tmp, sizeof tmp, status);
3741 status.errIfFailureAndReset("\"%s\"", empty);
3742 assertTrue("reslen >= 0", reslen >= 0);
3743 assertEquals("uloc_getBaseName() 1", empty, tmp);
3744
3745 uprv_memset(tmp, '!', sizeof tmp);
3746 reslen = uloc_getBaseName(root, tmp, sizeof tmp, status);
3747 status.errIfFailureAndReset("\"%s\"", root);
3748 assertTrue("reslen >= 0", reslen >= 0);
3749 assertEquals("uloc_getBaseName() 2", root, tmp); // change from open ICU
3750
3751 uprv_memset(tmp, '!', sizeof tmp);
3752 reslen = uloc_getBaseName(und, tmp, sizeof tmp, status);
3753 status.errIfFailureAndReset("\"%s\"", und);
3754 assertTrue("reslen >= 0", reslen >= 0);
3755 assertEquals("uloc_getBaseName() 3", und, tmp); // change from open ICU
3756
3757 uprv_memset(tmp, '!', sizeof tmp);
3758 reslen = uloc_getBaseName(empty_script, tmp, sizeof tmp, status);
3759 status.errIfFailureAndReset("\"%s\"", empty_script);
3760 assertTrue("reslen >= 0", reslen >= 0);
3761 assertEquals("uloc_getBaseName() 4", empty_script, tmp);
3762
3763 uprv_memset(tmp, '!', sizeof tmp);
3764 reslen = uloc_getBaseName(empty_region, tmp, sizeof tmp, status);
3765 status.errIfFailureAndReset("\"%s\"", empty_region);
3766 assertTrue("reslen >= 0", reslen >= 0);
3767 assertEquals("uloc_getBaseName() 5", empty_region, tmp);
3768
3769 uprv_memset(tmp, '!', sizeof tmp);
3770 reslen = uloc_getBaseName(und_script, tmp, sizeof tmp, status);
3771 status.errIfFailureAndReset("\"%s\"", und_script);
3772 assertTrue("reslen >= 0", reslen >= 0);
3773 assertEquals("uloc_getBaseName() 6", und_script, tmp); // change from open ICU
3774
3775 uprv_memset(tmp, '!', sizeof tmp);
3776 reslen = uloc_getBaseName(und_region, tmp, sizeof tmp, status);
3777 status.errIfFailureAndReset("\"%s\"", und_region);
3778 assertTrue("reslen >= 0", reslen >= 0);
3779 assertEquals("uloc_getBaseName() 7", und_region, tmp); // change from open ICU
3780
3781 // uloc_getParent()
3782
3783 uprv_memset(tmp, '!', sizeof tmp);
3784 reslen = uloc_getParent(empty, tmp, sizeof tmp, status);
3785 status.errIfFailureAndReset("\"%s\"", empty);
3786 assertTrue("reslen >= 0", reslen >= 0);
3787 assertEquals("uloc_getParent() 1", empty, tmp);
3788
3789 uprv_memset(tmp, '!', sizeof tmp);
3790 reslen = uloc_getParent(root, tmp, sizeof tmp, status);
3791 status.errIfFailureAndReset("\"%s\"", root);
3792 assertTrue("reslen >= 0", reslen >= 0);
3793 assertEquals("uloc_getParent() 2", empty, tmp);
3794
3795 uprv_memset(tmp, '!', sizeof tmp);
3796 reslen = uloc_getParent(und, tmp, sizeof tmp, status);
3797 status.errIfFailureAndReset("\"%s\"", und);
3798 assertTrue("reslen >= 0", reslen >= 0);
3799 assertEquals("uloc_getParent() 3", empty, tmp);
3800
3801 uprv_memset(tmp, '!', sizeof tmp);
3802 reslen = uloc_getParent(empty_script, tmp, sizeof tmp, status);
3803 status.errIfFailureAndReset("\"%s\"", empty_script);
3804 assertTrue("reslen >= 0", reslen >= 0);
3805 assertEquals("uloc_getParent() 4", empty, tmp);
3806
3807 uprv_memset(tmp, '!', sizeof tmp);
3808 reslen = uloc_getParent(empty_region, tmp, sizeof tmp, status);
3809 status.errIfFailureAndReset("\"%s\"", empty_region);
3810 assertTrue("reslen >= 0", reslen >= 0);
3811 assertEquals("uloc_getParent() 5", empty, tmp);
3812
3813 uprv_memset(tmp, '!', sizeof tmp);
3814 reslen = uloc_getParent(und_script, tmp, sizeof tmp, status);
3815 status.errIfFailureAndReset("\"%s\"", und_script);
3816 assertTrue("reslen >= 0", reslen >= 0);
3817 assertEquals("uloc_getParent() 6", und, tmp); // change from open ICU
3818
3819 uprv_memset(tmp, '!', sizeof tmp);
3820 reslen = uloc_getParent(und_region, tmp, sizeof tmp, status);
3821 status.errIfFailureAndReset("\"%s\"", und_region);
3822 assertTrue("reslen >= 0", reslen >= 0);
3823 assertEquals("uloc_getParent() 7", und, tmp); // change from open ICU
3824
3825 // uloc_getLanguage()
3826
3827 uprv_memset(tmp, '!', sizeof tmp);
3828 reslen = uloc_getLanguage(empty, tmp, sizeof tmp, status);
3829 status.errIfFailureAndReset("\"%s\"", empty);
3830 assertTrue("reslen >= 0", reslen >= 0);
3831 assertEquals("uloc_getLanguage() 1", empty, tmp);
3832
3833 uprv_memset(tmp, '!', sizeof tmp);
3834 reslen = uloc_getLanguage(root, tmp, sizeof tmp, status);
3835 status.errIfFailureAndReset("\"%s\"", root);
3836 assertTrue("reslen >= 0", reslen >= 0);
3837 assertEquals("uloc_getLanguage() 2", root, tmp); // change from open ICU
3838
3839 uprv_memset(tmp, '!', sizeof tmp);
3840 reslen = uloc_getLanguage(und, tmp, sizeof tmp, status);
3841 status.errIfFailureAndReset("\"%s\"", und);
3842 assertTrue("reslen >= 0", reslen >= 0);
3843 assertEquals("uloc_getLanguage() 3", und, tmp); // change from open ICU
3844
3845 uprv_memset(tmp, '!', sizeof tmp);
3846 reslen = uloc_getLanguage(empty_script, tmp, sizeof tmp, status);
3847 status.errIfFailureAndReset("\"%s\"", empty_script);
3848 assertTrue("reslen >= 0", reslen >= 0);
3849 assertEquals("uloc_getLanguage() 4", empty, tmp);
3850
3851 uprv_memset(tmp, '!', sizeof tmp);
3852 reslen = uloc_getLanguage(empty_region, tmp, sizeof tmp, status);
3853 status.errIfFailureAndReset("\"%s\"", empty_region);
3854 assertTrue("reslen >= 0", reslen >= 0);
3855 assertEquals("uloc_getLanguage() 5", empty, tmp);
3856
3857 uprv_memset(tmp, '!', sizeof tmp);
3858 reslen = uloc_getLanguage(und_script, tmp, sizeof tmp, status);
3859 status.errIfFailureAndReset("\"%s\"", und_script);
3860 assertTrue("reslen >= 0", reslen >= 0);
3861 assertEquals("uloc_getLanguage() 6", und, tmp); // change from open ICU
3862
3863 uprv_memset(tmp, '!', sizeof tmp);
3864 reslen = uloc_getLanguage(und_region, tmp, sizeof tmp, status);
3865 status.errIfFailureAndReset("\"%s\"", und_region);
3866 assertTrue("reslen >= 0", reslen >= 0);
3867 assertEquals("uloc_getLanguage() 7", und, tmp); // change from open ICU
3868}
340931cb
A
3869
3870#define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array))
3871
3872void LocaleTest::TestRangeIterator() {
3873 IcuTestErrorCode status(*this, "TestRangeIterator");
3874 Locale locales[] = { "fr", "en_GB", "en" };
3875 Locale::RangeIterator<Locale *> iter(ARRAY_RANGE(locales));
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 == &locales[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 == &locales[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 == &locales[2]);
3891
3892 assertFalse("3.hasNext()", iter.hasNext());
3893}
3894
3895void LocaleTest::TestPointerConvertingIterator() {
3896 IcuTestErrorCode status(*this, "TestPointerConvertingIterator");
3897 Locale locales[] = { "fr", "en_GB", "en" };
3898 Locale *pointers[] = { locales, locales + 1, locales + 2 };
3899 // Lambda with explicit reference return type to prevent copy-constructing a temporary
3900 // which would be destructed right away.
3901 Locale::ConvertingIterator<Locale **, std::function<const Locale &(const Locale *)>> iter(
3902 ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; });
3903
3904 assertTrue("0.hasNext()", iter.hasNext());
3905 const Locale &l0 = iter.next();
3906 assertEquals("0.next()", "fr", l0.getName());
3907 assertTrue("&0.next()", &l0 == pointers[0]);
3908
3909 assertTrue("1.hasNext()", iter.hasNext());
3910 const Locale &l1 = iter.next();
3911 assertEquals("1.next()", "en_GB", l1.getName());
3912 assertTrue("&1.next()", &l1 == pointers[1]);
3913
3914 assertTrue("2.hasNext()", iter.hasNext());
3915 const Locale &l2 = iter.next();
3916 assertEquals("2.next()", "en", l2.getName());
3917 assertTrue("&2.next()", &l2 == pointers[2]);
3918
3919 assertFalse("3.hasNext()", iter.hasNext());
3920}
3921
3922namespace {
3923
3924class LocaleFromTag {
3925public:
3926 LocaleFromTag() : locale(Locale::getRoot()) {}
3927 const Locale &operator()(const char *tag) { return locale = Locale(tag); }
3928
3929private:
3930 // Store the locale in the converter, rather than return a reference to a temporary,
3931 // or a value which could go out of scope with the caller's reference to it.
3932 Locale locale;
3933};
3934
3935} // namespace
3936
3937void LocaleTest::TestTagConvertingIterator() {
3938 IcuTestErrorCode status(*this, "TestTagConvertingIterator");
3939 const char *tags[] = { "fr", "en_GB", "en" };
3940 LocaleFromTag converter;
3941 Locale::ConvertingIterator<const char **, LocaleFromTag> iter(ARRAY_RANGE(tags), converter);
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
3958void LocaleTest::TestCapturingTagConvertingIterator() {
3959 IcuTestErrorCode status(*this, "TestCapturingTagConvertingIterator");
3960 const char *tags[] = { "fr", "en_GB", "en" };
3961 // Store the converted locale in a locale variable,
3962 // rather than return a reference to a temporary,
3963 // or a value which could go out of scope with the caller's reference to it.
3964 Locale locale;
3965 // Lambda with explicit reference return type to prevent copy-constructing a temporary
3966 // which would be destructed right away.
3967 Locale::ConvertingIterator<const char **, std::function<const Locale &(const char *)>> iter(
3968 ARRAY_RANGE(tags), [&](const char *tag) -> const Locale & { return locale = Locale(tag); });
3969
3970 assertTrue("0.hasNext()", iter.hasNext());
3971 const Locale &l0 = iter.next();
3972 assertEquals("0.next()", "fr", l0.getName());
3973
3974 assertTrue("1.hasNext()", iter.hasNext());
3975 const Locale &l1 = iter.next();
3976 assertEquals("1.next()", "en_GB", l1.getName());
3977
3978 assertTrue("2.hasNext()", iter.hasNext());
3979 const Locale &l2 = iter.next();
3980 assertEquals("2.next()", "en", l2.getName());
3981
3982 assertFalse("3.hasNext()", iter.hasNext());
3983}
3984
3985void LocaleTest::TestSetUnicodeKeywordValueInLongLocale() {
3986 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueInLongLocale");
3987 const char* value = "efghijkl";
3988 icu::Locale l("de");
3989 char keyword[3];
3990 CharString expected("de-u", status);
3991 keyword[2] = '\0';
3992 for (char i = 'a'; i < 's'; i++) {
3993 keyword[0] = keyword[1] = i;
3994 expected.append("-", status);
3995 expected.append(keyword, status);
3996 expected.append("-", status);
3997 expected.append(value, status);
3998 l.setUnicodeKeywordValue(keyword, value, status);
3999 if (status.errIfFailureAndReset(
4000 "setUnicodeKeywordValue(\"%s\", \"%s\") fail while locale is \"%s\"",
4001 keyword, value, l.getName())) {
4002 return;
4003 }
4004 std::string tag = l.toLanguageTag<std::string>(status);
4005 if (status.errIfFailureAndReset(
4006 "toLanguageTag fail on \"%s\"", l.getName())) {
4007 return;
4008 }
4009 if (tag != expected.data()) {
4010 errln("Expected to get \"%s\" bug got \"%s\"", tag.c_str(),
4011 expected.data());
4012 return;
4013 }
4014 }
4015}
4016
4017void LocaleTest::TestSetUnicodeKeywordValueNullInLongLocale() {
4018 IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueNullInLongLocale");
4019 const char *exts[] = {"cf", "cu", "em", "kk", "kr", "ks", "kv", "lb", "lw",
4020 "ms", "nu", "rg", "sd", "ss", "tz"};
4021 for (int32_t i = 0; i < UPRV_LENGTHOF(exts); i++) {
4022 CharString tag("de-u", status);
4023 for (int32_t j = 0; j <= i; j++) {
4024 tag.append("-", status).append(exts[j], status);
4025 }
4026 if (status.errIfFailureAndReset(
4027 "Cannot create tag \"%s\"", tag.data())) {
4028 continue;
4029 }
4030 Locale l = Locale::forLanguageTag(tag.data(), status);
4031 if (status.errIfFailureAndReset(
4032 "Locale::forLanguageTag(\"%s\") failed", tag.data())) {
4033 continue;
4034 }
4035 for (int32_t j = 0; j <= i; j++) {
4036 l.setUnicodeKeywordValue(exts[j], nullptr, status);
4037 if (status.errIfFailureAndReset(
4038 "Locale(\"%s\").setUnicodeKeywordValue(\"%s\", nullptr) failed",
4039 tag.data(), exts[j])) {
4040 continue;
4041 }
4042 }
4043 if (strcmp("de", l.getName()) != 0) {
4044 errln("setUnicodeKeywordValue should remove all extensions from "
4045 "\"%s\" and only have \"de\", but is \"%s\" instead.",
4046 tag.data(), l.getName());
4047 }
4048 }
4049}