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