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