1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /** 4 ******************************************************************************* 5 * Copyright (C) 2001-2016, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 */ 9 10 #include "utypeinfo.h" // for 'typeid' to work 11 12 #include "unicode/utypes.h" 13 14 #if !UCONFIG_NO_SERVICE 15 16 #include "cmemory.h" 17 #include "icusvtst.h" 18 #include "servloc.h" 19 #include <stdio.h> 20 21 22 class MyListener : public EventListener { 23 }; 24 25 class WrongListener : public EventListener { 26 }; 27 28 class ICUNSubclass : public ICUNotifier { 29 public: 30 UBool acceptsListener(const EventListener& /*l*/) const { 31 return TRUE; 32 // return l instanceof MyListener; 33 } 34 35 virtual void notifyListener(EventListener& /*l*/) const { 36 } 37 }; 38 39 // This factory does nothing 40 class LKFSubclass0 : public LocaleKeyFactory { 41 public: 42 LKFSubclass0() 43 : LocaleKeyFactory(VISIBLE, "LKFSubclass0") 44 { 45 } 46 }; 47 48 class LKFSubclass : public LocaleKeyFactory { 49 Hashtable table; 50 51 public: 52 LKFSubclass(UBool visible) 53 : LocaleKeyFactory(visible ? VISIBLE : INVISIBLE, "LKFSubclass") 54 { 55 UErrorCode status = U_ZERO_ERROR; 56 table.put("en_US", this, status); 57 } 58 59 protected: 60 virtual const Hashtable* getSupportedIDs(UErrorCode &/*status*/) const { 61 return &table; 62 } 63 }; 64 65 class Integer : public UObject { 66 public: 67 const int32_t _val; 68 69 Integer(int32_t val) : _val(val) { 70 } 71 72 Integer(const Integer& rhs) : UObject(rhs), _val(rhs._val) { 73 } 74 virtual ~Integer() { 75 } 76 77 public: 78 /** 79 * UObject boilerplate. 80 */ 81 static UClassID getStaticClassID() { 82 return (UClassID)&fgClassID; 83 } 84 85 virtual UClassID getDynamicClassID() const { 86 return getStaticClassID(); 87 } 88 89 virtual UBool operator==(const UObject& other) const 90 { 91 return typeid(*this) == typeid(other) && 92 _val == ((Integer&)other)._val; 93 } 94 95 public: 96 virtual UnicodeString& debug(UnicodeString& result) const { 97 debugClass(result); 98 result.append(" val: "); 99 result.append(_val); 100 return result; 101 } 102 103 virtual UnicodeString& debugClass(UnicodeString& result) const { 104 return result.append("Integer"); 105 } 106 107 private: 108 static const char fgClassID; 109 }; 110 111 const char Integer::fgClassID = '\0'; 112 113 // use locale keys 114 class TestIntegerService : public ICUService { 115 public: 116 ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const { 117 return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale 118 } 119 120 virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) 121 { 122 Integer* i; 123 if (U_SUCCESS(status) && obj && (i = dynamic_cast<Integer*>(obj)) != NULL) { 124 return new SimpleFactory(i, id, visible); 125 } 126 return NULL; 127 } 128 129 virtual UObject* cloneInstance(UObject* instance) const { 130 return instance ? new Integer(*(Integer*)instance) : NULL; 131 } 132 }; 133 134 135 ICUServiceTest::ICUServiceTest() { 136 } 137 138 ICUServiceTest::~ICUServiceTest() { 139 } 140 141 void 142 ICUServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name, 143 char* /*par*/) 144 { 145 switch (index) { 146 TESTCASE(0,testAPI_One); 147 TESTCASE(1,testAPI_Two); 148 TESTCASE(2,testRBF); 149 TESTCASE(3,testNotification); 150 TESTCASE(4,testLocale); 151 TESTCASE(5,testWrapFactory); 152 TESTCASE(6,testCoverage); 153 default: name = ""; break; 154 } 155 } 156 157 UnicodeString append(UnicodeString& result, const UObject* obj) 158 { 159 char buffer[128]; 160 if (obj == NULL) { 161 result.append("NULL"); 162 } else { 163 const UnicodeString* s; 164 const Locale* loc; 165 const Integer* i; 166 if ((s = dynamic_cast<const UnicodeString*>(obj)) != NULL) { 167 result.append(*s); 168 } else if ((loc = dynamic_cast<const Locale*>(obj)) != NULL) { 169 result.append(loc->getName()); 170 } else if ((i = dynamic_cast<const Integer*>(obj)) != NULL) { 171 sprintf(buffer, "%d", (int)i->_val); 172 result.append(buffer); 173 } else { 174 sprintf(buffer, "%p", (const void*)obj); 175 result.append(buffer); 176 } 177 } 178 return result; 179 } 180 181 UnicodeString& 182 ICUServiceTest::lrmsg(UnicodeString& result, const UnicodeString& message, const UObject* lhs, const UObject* rhs) const 183 { 184 result.append(message); 185 result.append(" lhs: "); 186 append(result, lhs); 187 result.append(", rhs: "); 188 append(result, rhs); 189 return result; 190 } 191 192 void 193 ICUServiceTest::confirmBoolean(const UnicodeString& message, UBool val) 194 { 195 if (val) { 196 logln(message); 197 } else { 198 errln(message); 199 } 200 } 201 202 #if 0 203 void 204 ICUServiceTest::confirmEqual(const UnicodeString& message, const UObject* lhs, const UObject* rhs) 205 { 206 UBool equ = (lhs == NULL) 207 ? (rhs == NULL) 208 : (rhs != NULL && lhs->operator==(*rhs)); 209 210 UnicodeString temp; 211 lrmsg(temp, message, lhs, rhs); 212 213 if (equ) { 214 logln(temp); 215 } else { 216 errln(temp); 217 } 218 } 219 #else 220 void 221 ICUServiceTest::confirmEqual(const UnicodeString& message, const Integer* lhs, const Integer* rhs) 222 { 223 UBool equ = (lhs == NULL) 224 ? (rhs == NULL) 225 : (rhs != NULL && lhs->operator==(*rhs)); 226 227 UnicodeString temp; 228 lrmsg(temp, message, lhs, rhs); 229 230 if (equ) { 231 logln(temp); 232 } else { 233 errln(temp); 234 } 235 } 236 237 void 238 ICUServiceTest::confirmEqual(const UnicodeString& message, const UnicodeString* lhs, const UnicodeString* rhs) 239 { 240 UBool equ = (lhs == NULL) 241 ? (rhs == NULL) 242 : (rhs != NULL && lhs->operator==(*rhs)); 243 244 UnicodeString temp; 245 lrmsg(temp, message, lhs, rhs); 246 247 if (equ) { 248 logln(temp); 249 } else { 250 errln(temp); 251 } 252 } 253 254 void 255 ICUServiceTest::confirmEqual(const UnicodeString& message, const Locale* lhs, const Locale* rhs) 256 { 257 UBool equ = (lhs == NULL) 258 ? (rhs == NULL) 259 : (rhs != NULL && lhs->operator==(*rhs)); 260 261 UnicodeString temp; 262 lrmsg(temp, message, lhs, rhs); 263 264 if (equ) { 265 logln(temp); 266 } else { 267 errln(temp); 268 } 269 } 270 #endif 271 272 // use these for now 273 void 274 ICUServiceTest::confirmStringsEqual(const UnicodeString& message, const UnicodeString& lhs, const UnicodeString& rhs) 275 { 276 UBool equ = lhs == rhs; 277 278 UnicodeString temp = message; 279 temp.append(" lhs: "); 280 temp.append(lhs); 281 temp.append(" rhs: "); 282 temp.append(rhs); 283 284 if (equ) { 285 logln(temp); 286 } else { 287 dataerrln(temp); 288 } 289 } 290 291 292 void 293 ICUServiceTest::confirmIdentical(const UnicodeString& message, const UObject* lhs, const UObject *rhs) 294 { 295 UnicodeString temp; 296 lrmsg(temp, message, lhs, rhs); 297 if (lhs == rhs) { 298 logln(temp); 299 } else { 300 errln(temp); 301 } 302 } 303 304 void 305 ICUServiceTest::confirmIdentical(const UnicodeString& message, int32_t lhs, int32_t rhs) 306 { 307 if (lhs == rhs) { 308 logln(message + " lhs: " + lhs + " rhs: " + rhs); 309 } else { 310 errln(message + " lhs: " + lhs + " rhs: " + rhs); 311 } 312 } 313 314 void 315 ICUServiceTest::msgstr(const UnicodeString& message, UObject* obj, UBool err) 316 { 317 if (obj) { 318 UnicodeString* str = (UnicodeString*)obj; 319 logln(message + *str); 320 delete str; 321 } else if (err) { 322 errln("Error " + message + "string is NULL"); 323 } 324 } 325 326 void 327 ICUServiceTest::testAPI_One() 328 { 329 // create a service using locale keys, 330 TestIntegerService service; 331 332 // register an object with one locale, 333 // search for an object with a more specific locale 334 // should return the original object 335 UErrorCode status = U_ZERO_ERROR; 336 Integer* singleton0 = new Integer(0); 337 service.registerInstance(singleton0, "en_US", status); 338 { 339 UErrorCode status = U_ZERO_ERROR; 340 Integer* result = (Integer*)service.get("en_US_FOO", status); 341 confirmEqual("1) en_US_FOO -> en_US", result, singleton0); 342 delete result; 343 } 344 345 // register a new object with the more specific locale 346 // search for an object with that locale 347 // should return the new object 348 Integer* singleton1 = new Integer(1); 349 service.registerInstance(singleton1, "en_US_FOO", status); 350 { 351 UErrorCode status = U_ZERO_ERROR; 352 Integer* result = (Integer*)service.get("en_US_FOO", status); 353 confirmEqual("2) en_US_FOO -> en_US_FOO", result, singleton1); 354 delete result; 355 } 356 357 // search for an object that falls back to the first registered locale 358 { 359 UErrorCode status = U_ZERO_ERROR; 360 Integer* result = (Integer*)service.get("en_US_BAR", status); 361 confirmEqual("3) en_US_BAR -> en_US", result, singleton0); 362 delete result; 363 } 364 365 // get a list of the factories, should be two 366 { 367 confirmIdentical("4) factory size", service.countFactories(), 2); 368 } 369 370 // register a new object with yet another locale 371 Integer* singleton2 = new Integer(2); 372 service.registerInstance(singleton2, "en", status); 373 { 374 confirmIdentical("5) factory size", service.countFactories(), 3); 375 } 376 377 // search for an object with the new locale 378 // stack of factories is now en, en_US_FOO, en_US 379 // search for en_US should still find en_US object 380 { 381 UErrorCode status = U_ZERO_ERROR; 382 Integer* result = (Integer*)service.get("en_US_BAR", status); 383 confirmEqual("6) en_US_BAR -> en_US", result, singleton0); 384 delete result; 385 } 386 387 // register a new object with an old id, should hide earlier factory using this id, but leave it there 388 Integer* singleton3 = new Integer(3); 389 URegistryKey s3key = service.registerInstance(singleton3, "en_US", status); 390 { 391 confirmIdentical("9) factory size", service.countFactories(), 4); 392 } 393 394 // should get data from that new factory 395 { 396 UErrorCode status = U_ZERO_ERROR; 397 Integer* result = (Integer*)service.get("en_US_BAR", status); 398 confirmEqual("10) en_US_BAR -> (3)", result, singleton3); 399 delete result; 400 } 401 402 // remove new factory 403 // should have fewer factories again 404 // singleton3 dead! 405 { 406 UErrorCode status = U_ZERO_ERROR; 407 service.unregister(s3key, status); 408 confirmIdentical("11) factory size", service.countFactories(), 3); 409 } 410 411 // should get original data again after remove factory 412 { 413 UErrorCode status = U_ZERO_ERROR; 414 Integer* result = (Integer*)service.get("en_US_BAR", status); 415 confirmEqual("12) en_US_BAR -> (3)", result, singleton0); 416 delete result; 417 } 418 419 // shouldn't find unregistered ids 420 { 421 UErrorCode status = U_ZERO_ERROR; 422 Integer* result = (Integer*)service.get("foo", status); 423 confirmIdentical("13) foo -> null", result, NULL); 424 delete result; 425 } 426 427 // should find non-canonical strings 428 { 429 UnicodeString resultID; 430 UErrorCode status = U_ZERO_ERROR; 431 Integer* result = (Integer*)service.get("EN_us_fOo", &resultID, status); 432 confirmEqual("14a) find-non-canonical", result, singleton1); 433 confirmStringsEqual("14b) find non-canonical", resultID, "en_US_FOO"); 434 delete result; 435 } 436 437 // should be able to register non-canonical strings and get them canonicalized 438 Integer* singleton4 = new Integer(4); 439 service.registerInstance(singleton4, "eN_ca_dUde", status); 440 { 441 UnicodeString resultID; 442 UErrorCode status = U_ZERO_ERROR; 443 Integer* result = (Integer*)service.get("En_Ca_DuDe", &resultID, status); 444 confirmEqual("15a) find-non-canonical", result, singleton4); 445 confirmStringsEqual("15b) register non-canonical", resultID, "en_CA_DUDE"); 446 delete result; 447 } 448 449 // should be able to register invisible factories, these will not 450 // be visible by default, but if you know the secret password you 451 // can still access these services... 452 Integer* singleton5 = new Integer(5); 453 service.registerInstance(singleton5, "en_US_BAR", FALSE, status); 454 { 455 UErrorCode status = U_ZERO_ERROR; 456 Integer* result = (Integer*)service.get("en_US_BAR", status); 457 confirmEqual("17) get invisible", result, singleton5); 458 delete result; 459 } 460 461 // should not be able to locate invisible services 462 { 463 UErrorCode status = U_ZERO_ERROR; 464 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status); 465 service.getVisibleIDs(ids, status); 466 UnicodeString target = "en_US_BAR"; 467 confirmBoolean("18) find invisible", !ids.contains(&target)); 468 } 469 470 // clear factory and caches 471 service.reset(); 472 confirmBoolean("19) is default", service.isDefault()); 473 } 474 475 /* 476 ****************************************************************** 477 */ 478 class TestStringSimpleKeyService : public ICUService { 479 public: 480 481 virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) 482 { 483 // We could put this type check into ICUService itself, but we'd still 484 // have to implement cloneInstance. Otherwise we could just tell the service 485 // what the object type is when we create it, and the default implementation 486 // could handle everything for us. Phooey. 487 if (obj && dynamic_cast<UnicodeString*>(obj) != NULL) { 488 return ICUService::createSimpleFactory(obj, id, visible, status); 489 } 490 return NULL; 491 } 492 493 virtual UObject* cloneInstance(UObject* instance) const { 494 return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL; 495 } 496 }; 497 498 class TestStringService : public ICUService { 499 public: 500 ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const { 501 return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale 502 } 503 504 virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& /* status */) 505 { 506 UnicodeString* s; 507 if (obj && (s = dynamic_cast<UnicodeString*>(obj)) != NULL) { 508 return new SimpleFactory(s, id, visible); 509 } 510 return NULL; 511 } 512 513 virtual UObject* cloneInstance(UObject* instance) const { 514 return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL; 515 } 516 }; 517 518 // this creates a string for any id, but doesn't report anything 519 class AnonymousStringFactory : public ICUServiceFactory 520 { 521 public: 522 virtual UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& /* status */) const { 523 return new UnicodeString(key.getID()); 524 } 525 526 virtual void updateVisibleIDs(Hashtable& /*result*/, UErrorCode& /*status*/) const { 527 // do nothing 528 } 529 530 virtual UnicodeString& getDisplayName(const UnicodeString& /*id*/, const Locale& /*locale*/, UnicodeString& result) const { 531 // do nothing 532 return result; 533 } 534 535 static UClassID getStaticClassID() { 536 return (UClassID)&fgClassID; 537 } 538 539 virtual UClassID getDynamicClassID() const { 540 return getStaticClassID(); 541 } 542 543 private: 544 static const char fgClassID; 545 }; 546 547 const char AnonymousStringFactory::fgClassID = '\0'; 548 549 class TestMultipleKeyStringFactory : public ICUServiceFactory { 550 UErrorCode _status; 551 UVector _ids; 552 UnicodeString _factoryID; 553 554 public: 555 TestMultipleKeyStringFactory(const UnicodeString ids[], int32_t count, const UnicodeString& factoryID) 556 : _status(U_ZERO_ERROR) 557 , _ids(uprv_deleteUObject, uhash_compareUnicodeString, count, _status) 558 , _factoryID(factoryID + ": ") 559 { 560 for (int i = 0; i < count; ++i) { 561 _ids.addElement(new UnicodeString(ids[i]), _status); 562 } 563 } 564 565 ~TestMultipleKeyStringFactory() { 566 } 567 568 UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const { 569 if (U_FAILURE(status)) { 570 return NULL; 571 } 572 UnicodeString temp; 573 key.currentID(temp); 574 if (U_SUCCESS(_status)) { 575 if (_ids.contains(&temp)) { 576 return new UnicodeString(_factoryID + temp); 577 } 578 } else { 579 status = _status; 580 } 581 return NULL; 582 } 583 584 void updateVisibleIDs(Hashtable& result, UErrorCode& status) const { 585 if (U_SUCCESS(_status)) { 586 for (int32_t i = 0; i < _ids.size(); ++i) { 587 result.put(*(UnicodeString*)_ids[i], (void*)this, status); 588 } 589 } 590 } 591 592 UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const { 593 if (U_SUCCESS(_status) && _ids.contains((void*)&id)) { 594 char buffer[128]; 595 UErrorCode status = U_ZERO_ERROR; 596 int32_t len = id.extract(buffer, sizeof(buffer), NULL, status); 597 if (U_SUCCESS(status)) { 598 if (len == sizeof(buffer)) { 599 --len; 600 } 601 buffer[len] = 0; 602 Locale loc = Locale::createFromName(buffer); 603 loc.getDisplayName(locale, result); 604 return result; 605 } 606 } 607 result.setToBogus(); // shouldn't happen 608 return result; 609 } 610 611 static UClassID getStaticClassID() { 612 return (UClassID)&fgClassID; 613 } 614 615 virtual UClassID getDynamicClassID() const { 616 return getStaticClassID(); 617 } 618 619 private: 620 static const char fgClassID; 621 }; 622 623 const char TestMultipleKeyStringFactory::fgClassID = '\0'; 624 625 void 626 ICUServiceTest::testAPI_Two() 627 { 628 UErrorCode status = U_ZERO_ERROR; 629 TestStringService service; 630 service.registerFactory(new AnonymousStringFactory(), status); 631 632 // anonymous factory will still handle the id 633 { 634 UErrorCode status = U_ZERO_ERROR; 635 const UnicodeString en_US = "en_US"; 636 UnicodeString* result = (UnicodeString*)service.get(en_US, status); 637 confirmEqual("21) locale", result, &en_US); 638 delete result; 639 } 640 641 // still normalizes id 642 { 643 UErrorCode status = U_ZERO_ERROR; 644 const UnicodeString en_US_BAR = "en_US_BAR"; 645 UnicodeString resultID; 646 UnicodeString* result = (UnicodeString*)service.get("EN_us_bar", &resultID, status); 647 confirmEqual("22) locale", &resultID, &en_US_BAR); 648 delete result; 649 } 650 651 // we can override for particular ids 652 UnicodeString* singleton0 = new UnicodeString("Zero"); 653 service.registerInstance(singleton0, "en_US_BAR", status); 654 { 655 UErrorCode status = U_ZERO_ERROR; 656 UnicodeString* result = (UnicodeString*)service.get("en_US_BAR", status); 657 confirmEqual("23) override super", result, singleton0); 658 delete result; 659 } 660 661 // empty service should not recognize anything 662 service.reset(); 663 { 664 UErrorCode status = U_ZERO_ERROR; 665 UnicodeString* result = (UnicodeString*)service.get("en_US", status); 666 confirmIdentical("24) empty", result, NULL); 667 } 668 669 // create a custom multiple key factory 670 { 671 UnicodeString xids[] = { 672 "en_US_VALLEY_GIRL", 673 "en_US_VALLEY_BOY", 674 "en_US_SURFER_GAL", 675 "en_US_SURFER_DUDE" 676 }; 677 int32_t count = UPRV_LENGTHOF(xids); 678 679 ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Later"); 680 service.registerFactory(f, status); 681 } 682 683 // iterate over the visual ids returned by the multiple factory 684 { 685 UErrorCode status = U_ZERO_ERROR; 686 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status); 687 service.getVisibleIDs(ids, status); 688 for (int i = 0; i < ids.size(); ++i) { 689 const UnicodeString* id = (const UnicodeString*)ids[i]; 690 UnicodeString* result = (UnicodeString*)service.get(*id, status); 691 if (result) { 692 logln(" " + *id + " --> " + *result); 693 delete result; 694 } else { 695 errln("could not find " + *id); 696 } 697 } 698 // four visible ids 699 confirmIdentical("25) visible ids", ids.size(), 4); 700 } 701 702 // iterate over the display names 703 { 704 UErrorCode status = U_ZERO_ERROR; 705 UVector names(status); 706 service.getDisplayNames(names, status); 707 for (int i = 0; i < names.size(); ++i) { 708 const StringPair* pair = (const StringPair*)names[i]; 709 logln(" " + pair->displayName + " --> " + pair->id); 710 } 711 confirmIdentical("26) display names", names.size(), 4); 712 } 713 714 // no valid display name 715 { 716 UnicodeString name; 717 service.getDisplayName("en_US_VALLEY_GEEK", name); 718 confirmBoolean("27) get display name", name.isBogus()); 719 } 720 721 { 722 UnicodeString name; 723 service.getDisplayName("en_US_SURFER_DUDE", name, Locale::getEnglish()); 724 confirmStringsEqual("28) get display name", name, "English (United States, SURFER_DUDE)"); 725 } 726 727 // register another multiple factory 728 { 729 UnicodeString xids[] = { 730 "en_US_SURFER", 731 "en_US_SURFER_GAL", 732 "en_US_SILICON", 733 "en_US_SILICON_GEEK", 734 }; 735 int32_t count = UPRV_LENGTHOF(xids); 736 737 ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Rad dude"); 738 service.registerFactory(f, status); 739 } 740 741 // this time, we have seven display names 742 // Rad dude's surfer gal 'replaces' Later's surfer gal 743 { 744 UErrorCode status = U_ZERO_ERROR; 745 UVector names(status); 746 service.getDisplayNames(names, Locale("es"), status); 747 for (int i = 0; i < names.size(); ++i) { 748 const StringPair* pair = (const StringPair*)names[i]; 749 logln(" " + pair->displayName + " --> " + pair->id); 750 } 751 confirmIdentical("29) display names", names.size(), 7); 752 } 753 754 // we should get the display name corresponding to the actual id 755 // returned by the id we used. 756 { 757 UErrorCode status = U_ZERO_ERROR; 758 UnicodeString actualID; 759 UnicodeString id = "en_us_surfer_gal"; 760 UnicodeString* gal = (UnicodeString*)service.get(id, &actualID, status); 761 if (gal != NULL) { 762 UnicodeString displayName; 763 logln("actual id: " + actualID); 764 service.getDisplayName(actualID, displayName, Locale::getEnglish()); 765 logln("found actual: " + *gal + " with display name: " + displayName); 766 confirmBoolean("30) found display name for actual", !displayName.isBogus()); 767 768 service.getDisplayName(id, displayName, Locale::getEnglish()); 769 logln("found actual: " + *gal + " with display name: " + displayName); 770 confirmBoolean("31) found display name for query", displayName.isBogus()); 771 772 delete gal; 773 } else { 774 errln("30) service could not find entry for " + id); 775 } 776 } 777 778 // this should be handled by the 'dude' factory, since it overrides en_US_SURFER. 779 { 780 UErrorCode status = U_ZERO_ERROR; 781 UnicodeString actualID; 782 UnicodeString id = "en_US_SURFER_BOZO"; 783 UnicodeString* bozo = (UnicodeString*)service.get(id, &actualID, status); 784 if (bozo != NULL) { 785 UnicodeString displayName; 786 service.getDisplayName(actualID, displayName, Locale::getEnglish()); 787 logln("found actual: " + *bozo + " with display name: " + displayName); 788 confirmBoolean("32) found display name for actual", !displayName.isBogus()); 789 790 service.getDisplayName(id, displayName, Locale::getEnglish()); 791 logln("found actual: " + *bozo + " with display name: " + displayName); 792 confirmBoolean("33) found display name for query", displayName.isBogus()); 793 794 delete bozo; 795 } else { 796 errln("32) service could not find entry for " + id); 797 } 798 } 799 800 // certainly not default... 801 { 802 confirmBoolean("34) is default ", !service.isDefault()); 803 } 804 805 { 806 UErrorCode status = U_ZERO_ERROR; 807 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status); 808 service.getVisibleIDs(ids, status); 809 for (int i = 0; i < ids.size(); ++i) { 810 const UnicodeString* id = (const UnicodeString*)ids[i]; 811 msgstr(*id + "? ", service.get(*id, status)); 812 } 813 814 logstr("valleygirl? ", service.get("en_US_VALLEY_GIRL", status)); 815 logstr("valleyboy? ", service.get("en_US_VALLEY_BOY", status)); 816 logstr("valleydude? ", service.get("en_US_VALLEY_DUDE", status)); 817 logstr("surfergirl? ", service.get("en_US_SURFER_GIRL", status)); 818 } 819 } 820 821 822 class CalifornioLanguageFactory : public ICUResourceBundleFactory 823 { 824 public: 825 static const char* californio; // = "en_US_CA"; 826 static const char* valley; // = californio ## "_VALLEY"; 827 static const char* surfer; // = californio ## "_SURFER"; 828 static const char* geek; // = californio ## "_GEEK"; 829 static Hashtable* supportedIDs; // = NULL; 830 831 static void cleanup(void) { 832 delete supportedIDs; 833 supportedIDs = NULL; 834 } 835 836 const Hashtable* getSupportedIDs(UErrorCode& status) const 837 { 838 if (supportedIDs == NULL) { 839 Hashtable* table = new Hashtable(); 840 table->put(UnicodeString(californio), (void*)table, status); 841 table->put(UnicodeString(valley), (void*)table, status); 842 table->put(UnicodeString(surfer), (void*)table, status); 843 table->put(UnicodeString(geek), (void*)table, status); 844 845 // not necessarily atomic, but this is a test... 846 supportedIDs = table; 847 } 848 return supportedIDs; 849 } 850 851 UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 852 { 853 UnicodeString prefix = ""; 854 UnicodeString suffix = ""; 855 UnicodeString ls = locale.getName(); 856 if (LocaleUtility::isFallbackOf(californio, ls)) { 857 if (!ls.caseCompare(valley, 0)) { 858 prefix = "Like, you know, it's so totally "; 859 } else if (!ls.caseCompare(surfer, 0)) { 860 prefix = "Dude, it's "; 861 } else if (!ls.caseCompare(geek, 0)) { 862 prefix = "I'd estimate it is approximately "; 863 } else { 864 prefix = "Huh? Maybe "; 865 } 866 } 867 if (LocaleUtility::isFallbackOf(californio, id)) { 868 if (!id.caseCompare(valley, 0)) { 869 suffix = "like the Valley, you know? Let's go to the mall!"; 870 } else if (!id.caseCompare(surfer, 0)) { 871 suffix = "time to hit those gnarly waves, Dude!!!"; 872 } else if (!id.caseCompare(geek, 0)) { 873 suffix = "all systems go. T-Minus 9, 8, 7..."; 874 } else { 875 suffix = "No Habla Englais"; 876 } 877 } else { 878 suffix = ICUResourceBundleFactory::getDisplayName(id, locale, result); 879 } 880 881 result = prefix + suffix; 882 return result; 883 } 884 }; 885 886 const char* CalifornioLanguageFactory::californio = "en_US_CA"; 887 const char* CalifornioLanguageFactory::valley = "en_US_CA_VALLEY"; 888 const char* CalifornioLanguageFactory::surfer = "en_US_CA_SURFER"; 889 const char* CalifornioLanguageFactory::geek = "en_US_CA_GEEK"; 890 Hashtable* CalifornioLanguageFactory::supportedIDs = NULL; 891 892 void 893 ICUServiceTest::testRBF() 894 { 895 // resource bundle factory. 896 UErrorCode status = U_ZERO_ERROR; 897 TestStringService service; 898 service.registerFactory(new ICUResourceBundleFactory(), status); 899 900 // list all of the resources 901 { 902 UErrorCode status = U_ZERO_ERROR; 903 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status); 904 service.getVisibleIDs(ids, status); 905 logln("all visible ids:"); 906 for (int i = 0; i < ids.size(); ++i) { 907 const UnicodeString* id = (const UnicodeString*)ids[i]; 908 logln(*id); 909 } 910 } 911 912 // get all the display names of these resources 913 // this should be fast since the display names were cached. 914 { 915 UErrorCode status = U_ZERO_ERROR; 916 UVector names(status); 917 service.getDisplayNames(names, Locale::getGermany(), status); 918 logln("service display names for de_DE"); 919 for (int i = 0; i < names.size(); ++i) { 920 const StringPair* pair = (const StringPair*)names[i]; 921 logln(" " + pair->displayName + " --> " + pair->id); 922 } 923 } 924 925 service.registerFactory(new CalifornioLanguageFactory(), status); 926 927 // get all the display names of these resources 928 { 929 logln("californio language factory:"); 930 const char* idNames[] = { 931 CalifornioLanguageFactory::californio, 932 CalifornioLanguageFactory::valley, 933 CalifornioLanguageFactory::surfer, 934 CalifornioLanguageFactory::geek, 935 }; 936 int32_t count = UPRV_LENGTHOF(idNames); 937 938 for (int i = 0; i < count; ++i) { 939 logln(UnicodeString("\n --- ") + idNames[i] + " ---"); 940 { 941 UErrorCode status = U_ZERO_ERROR; 942 UVector names(status); 943 service.getDisplayNames(names, idNames[i], status); 944 for (int i = 0; i < names.size(); ++i) { 945 const StringPair* pair = (const StringPair*)names[i]; 946 logln(" " + pair->displayName + " --> " + pair->id); 947 } 948 } 949 } 950 } 951 CalifornioLanguageFactory::cleanup(); 952 } 953 954 class SimpleListener : public ServiceListener { 955 ICUServiceTest* _test; 956 UnicodeString _name; 957 958 public: 959 SimpleListener(ICUServiceTest* test, const UnicodeString& name) : _test(test), _name(name) {} 960 961 virtual void serviceChanged(const ICUService& service) const { 962 UnicodeString serviceName = "listener "; 963 serviceName.append(_name); 964 serviceName.append(" n++"); 965 serviceName.append(" service changed: " ); 966 service.getName(serviceName); 967 _test->logln(serviceName); 968 } 969 }; 970 971 void 972 ICUServiceTest::testNotification() 973 { 974 SimpleListener one(this, "one"); 975 SimpleListener two(this, "two"); 976 { 977 UErrorCode status = U_ZERO_ERROR; 978 979 logln("simple registration notification"); 980 TestStringService ls; 981 ls.addListener(&one, status); 982 ls.addListener(&two, status); 983 984 logln("registering foo... "); 985 ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status); 986 logln("registering bar... "); 987 ls.registerInstance(new UnicodeString("Bar"), "en_BAR", status); 988 logln("getting foo..."); 989 UnicodeString* result = (UnicodeString*)ls.get("en_FOO", status); 990 logln(*result); 991 delete result; 992 993 logln("removing listener 2..."); 994 ls.removeListener(&two, status); 995 logln("registering baz..."); 996 ls.registerInstance(new UnicodeString("Baz"), "en_BAZ", status); 997 logln("removing listener 1"); 998 ls.removeListener(&one, status); 999 logln("registering burp..."); 1000 ls.registerInstance(new UnicodeString("Burp"), "en_BURP", status); 1001 1002 // should only get one notification even if register multiple times 1003 logln("... trying multiple registration"); 1004 ls.addListener(&one, status); 1005 ls.addListener(&one, status); 1006 ls.addListener(&one, status); 1007 ls.addListener(&two, status); 1008 ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status); 1009 logln("... registered foo"); 1010 } 1011 #if 0 1012 // same thread, so we can't callback within notification, unlike Java 1013 ServiceListener l3 = new ServiceListener() { 1014 private int n; 1015 public void serviceChanged(ICUService s) { 1016 logln("listener 3 report " + n++ + " service changed..."); 1017 if (s.get("en_BOINK") == null) { // don't recurse on ourselves!!! 1018 logln("registering boink..."); 1019 s.registerInstance("boink", "en_BOINK"); 1020 } 1021 } 1022 }; 1023 ls.addListener(l3); 1024 logln("registering boo..."); 1025 ls.registerInstance("Boo", "en_BOO"); 1026 #endif 1027 1028 logln("...done"); 1029 } 1030 1031 class TestStringLocaleService : public ICULocaleService { 1032 public: 1033 virtual UObject* cloneInstance(UObject* instance) const { 1034 return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL; 1035 } 1036 }; 1037 1038 void ICUServiceTest::testLocale() { 1039 UErrorCode status = U_ZERO_ERROR; 1040 TestStringLocaleService service; 1041 1042 UnicodeString* root = new UnicodeString("root"); 1043 UnicodeString* german = new UnicodeString("german"); 1044 UnicodeString* germany = new UnicodeString("german_Germany"); 1045 UnicodeString* japanese = new UnicodeString("japanese"); 1046 UnicodeString* japan = new UnicodeString("japanese_Japan"); 1047 1048 service.registerInstance(root, "", status); 1049 service.registerInstance(german, "de", status); 1050 service.registerInstance(germany, Locale::getGermany(), status); 1051 service.registerInstance(japanese, (UnicodeString)"ja", TRUE, status); 1052 service.registerInstance(japan, Locale::getJapan(), status); 1053 1054 { 1055 UErrorCode status = U_ZERO_ERROR; 1056 UnicodeString* target = (UnicodeString*)service.get("de_US", status); 1057 confirmEqual("test de_US", german, target); 1058 delete target; 1059 } 1060 1061 { 1062 UErrorCode status = U_ZERO_ERROR; 1063 UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, status); 1064 confirmEqual("test de_US 2", german, target); 1065 delete target; 1066 } 1067 1068 { 1069 UErrorCode status = U_ZERO_ERROR; 1070 UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, status); 1071 confirmEqual("test de_US 3", german, target); 1072 delete target; 1073 } 1074 1075 { 1076 UErrorCode status = U_ZERO_ERROR; 1077 Locale actualReturn; 1078 UnicodeString* target = (UnicodeString*)service.get("de_US", &actualReturn, status); 1079 confirmEqual("test de_US 5", german, target); 1080 confirmEqual("test de_US 6", &actualReturn, &Locale::getGerman()); 1081 delete target; 1082 } 1083 1084 { 1085 UErrorCode status = U_ZERO_ERROR; 1086 Locale actualReturn; 1087 UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, &actualReturn, status); 1088 confirmEqual("test de_US 7", &actualReturn, &Locale::getGerman()); 1089 delete target; 1090 } 1091 1092 { 1093 UErrorCode status = U_ZERO_ERROR; 1094 Locale actualReturn; 1095 UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, &actualReturn, status); 1096 confirmEqual("test de_US 8", german, target); 1097 confirmEqual("test de_US 9", &actualReturn, &Locale::getGerman()); 1098 delete target; 1099 } 1100 1101 UnicodeString* one = new UnicodeString("one/de_US"); 1102 UnicodeString* two = new UnicodeString("two/de_US"); 1103 1104 service.registerInstance(one, Locale("de_US"), 1, status); 1105 service.registerInstance(two, Locale("de_US"), 2, status); 1106 1107 { 1108 UErrorCode status = U_ZERO_ERROR; 1109 UnicodeString* target = (UnicodeString*)service.get("de_US", 1, status); 1110 confirmEqual("test de_US kind 1", one, target); 1111 delete target; 1112 } 1113 1114 { 1115 UErrorCode status = U_ZERO_ERROR; 1116 UnicodeString* target = (UnicodeString*)service.get("de_US", 2, status); 1117 confirmEqual("test de_US kind 2", two, target); 1118 delete target; 1119 } 1120 1121 { 1122 UErrorCode status = U_ZERO_ERROR; 1123 UnicodeString* target = (UnicodeString*)service.get("de_US", status); 1124 confirmEqual("test de_US kind 3", german, target); 1125 delete target; 1126 } 1127 1128 { 1129 UErrorCode status = U_ZERO_ERROR; 1130 UnicodeString english = "en"; 1131 Locale localeResult; 1132 UnicodeString result; 1133 LocaleKey* lkey = LocaleKey::createWithCanonicalFallback(&english, NULL, 1234, status); 1134 logln("lkey prefix: " + lkey->prefix(result)); 1135 result.remove(); 1136 logln("lkey descriptor: " + lkey->currentDescriptor(result)); 1137 result.remove(); 1138 logln(UnicodeString("lkey current locale: ") + lkey->currentLocale(localeResult).getName()); 1139 result.remove(); 1140 1141 lkey->fallback(); 1142 logln("lkey descriptor 2: " + lkey->currentDescriptor(result)); 1143 result.remove(); 1144 1145 lkey->fallback(); 1146 logln("lkey descriptor 3: " + lkey->currentDescriptor(result)); 1147 result.remove(); 1148 delete lkey; // tentatively weiv 1149 } 1150 1151 { 1152 UErrorCode status = U_ZERO_ERROR; 1153 UnicodeString* target = (UnicodeString*)service.get("za_PPP", status); 1154 confirmEqual("test zappp", root, target); 1155 delete target; 1156 } 1157 1158 Locale loc = Locale::getDefault(); 1159 Locale::setDefault(Locale::getJapanese(), status); 1160 { 1161 UErrorCode status = U_ZERO_ERROR; 1162 UnicodeString* target = (UnicodeString*)service.get("za_PPP", status); 1163 confirmEqual("test with ja locale", japanese, target); 1164 delete target; 1165 } 1166 1167 { 1168 UErrorCode status = U_ZERO_ERROR; 1169 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status); 1170 service.getVisibleIDs(ids, status); 1171 logln("all visible ids:"); 1172 for (int i = 0; i < ids.size(); ++i) { 1173 const UnicodeString* id = (const UnicodeString*)ids[i]; 1174 logln(*id); 1175 } 1176 } 1177 1178 Locale::setDefault(loc, status); 1179 { 1180 UErrorCode status = U_ZERO_ERROR; 1181 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status); 1182 service.getVisibleIDs(ids, status); 1183 logln("all visible ids:"); 1184 for (int i = 0; i < ids.size(); ++i) { 1185 const UnicodeString* id = (const UnicodeString*)ids[i]; 1186 logln(*id); 1187 } 1188 } 1189 1190 { 1191 UErrorCode status = U_ZERO_ERROR; 1192 UnicodeString* target = (UnicodeString*)service.get("za_PPP", status); 1193 confirmEqual("test with en locale", root, target); 1194 delete target; 1195 } 1196 1197 { 1198 UErrorCode status = U_ZERO_ERROR; 1199 StringEnumeration* locales = service.getAvailableLocales(); 1200 if (locales) { 1201 confirmIdentical("test available locales", locales->count(status), 6); 1202 logln("locales: "); 1203 { 1204 const char* p; 1205 while ((p = locales->next(NULL, status))) { 1206 logln(p); 1207 } 1208 } 1209 logln(" "); 1210 delete locales; 1211 } else { 1212 errln("could not create available locales"); 1213 } 1214 } 1215 } 1216 1217 class WrapFactory : public ICUServiceFactory { 1218 public: 1219 static const UnicodeString& getGreetingID() { 1220 if (greetingID == NULL) { 1221 greetingID = new UnicodeString("greeting"); 1222 } 1223 return *greetingID; 1224 } 1225 1226 static void cleanup() { 1227 delete greetingID; 1228 greetingID = NULL; 1229 } 1230 1231 UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const { 1232 if (U_SUCCESS(status)) { 1233 UnicodeString temp; 1234 if (key.currentID(temp).compare(getGreetingID()) == 0) { 1235 UnicodeString* previous = (UnicodeString*)service->getKey((ICUServiceKey&)key, NULL, this, status); 1236 if (previous) { 1237 previous->insert(0, "A different greeting: \""); 1238 previous->append("\""); 1239 return previous; 1240 } 1241 } 1242 } 1243 return NULL; 1244 } 1245 1246 void updateVisibleIDs(Hashtable& result, UErrorCode& status) const { 1247 if (U_SUCCESS(status)) { 1248 result.put("greeting", (void*)this, status); 1249 } 1250 } 1251 1252 UnicodeString& getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const { 1253 result.append("wrap '"); 1254 result.append(id); 1255 result.append("'"); 1256 return result; 1257 } 1258 1259 /** 1260 * UObject boilerplate. 1261 */ 1262 static UClassID getStaticClassID() { 1263 return (UClassID)&fgClassID; 1264 } 1265 1266 virtual UClassID getDynamicClassID() const { 1267 return getStaticClassID(); 1268 } 1269 1270 private: 1271 static const char fgClassID; 1272 static UnicodeString* greetingID; 1273 }; 1274 1275 UnicodeString* WrapFactory::greetingID = NULL; 1276 const char WrapFactory::fgClassID = '\0'; 1277 1278 void 1279 ICUServiceTest::testWrapFactory() 1280 { 1281 UnicodeString* greeting = new UnicodeString("Hello There"); 1282 UnicodeString greetingID = "greeting"; 1283 UErrorCode status = U_ZERO_ERROR; 1284 TestStringService service; 1285 service.registerInstance(greeting, greetingID, status); 1286 1287 { 1288 UErrorCode status = U_ZERO_ERROR; 1289 UnicodeString* result = (UnicodeString*)service.get(greetingID, status); 1290 if (result) { 1291 logln("test one: " + *result); 1292 delete result; 1293 } 1294 } 1295 1296 service.registerFactory(new WrapFactory(), status); 1297 { 1298 UErrorCode status = U_ZERO_ERROR; 1299 UnicodeString* result = (UnicodeString*)service.get(greetingID, status); 1300 UnicodeString target = "A different greeting: \"Hello There\""; 1301 confirmEqual("wrap test: ", result, &target); 1302 delete result; 1303 } 1304 1305 WrapFactory::cleanup(); 1306 } 1307 1308 // misc coverage tests 1309 void ICUServiceTest::testCoverage() 1310 { 1311 // ICUServiceKey 1312 { 1313 UnicodeString temp; 1314 ICUServiceKey key("foobar"); 1315 logln("ID: " + key.getID()); 1316 logln("canonicalID: " + key.canonicalID(temp)); 1317 logln("currentID: " + key.currentID(temp.remove())); 1318 logln("has fallback: " + UnicodeString(key.fallback() ? "true" : "false")); 1319 1320 if (key.getDynamicClassID() != ICUServiceKey::getStaticClassID()) { 1321 errln("service key rtt failed."); 1322 } 1323 } 1324 1325 // SimpleFactory 1326 { 1327 UErrorCode status = U_ZERO_ERROR; 1328 1329 UnicodeString* obj = new UnicodeString("An Object"); 1330 SimpleFactory* sf = new SimpleFactory(obj, "object"); 1331 1332 UnicodeString temp; 1333 logln(sf->getDisplayName("object", Locale::getDefault(), temp)); 1334 1335 if (sf->getDynamicClassID() != SimpleFactory::getStaticClassID()) { 1336 errln("simple factory rtti failed."); 1337 } 1338 1339 // ICUService 1340 { 1341 TestStringService service; 1342 service.registerFactory(sf, status); 1343 1344 { 1345 UnicodeString* result = (UnicodeString*)service.get("object", status); 1346 if (result) { 1347 logln("object is: " + *result); 1348 delete result; 1349 } else { 1350 errln("could not get object"); 1351 } 1352 } 1353 } 1354 } 1355 1356 // ICUServiceKey 1357 { 1358 UErrorCode status = U_ZERO_ERROR; 1359 UnicodeString* howdy = new UnicodeString("Howdy"); 1360 1361 TestStringSimpleKeyService service; 1362 service.registerInstance(howdy, "Greetings", status); 1363 { 1364 UnicodeString* result = (UnicodeString*)service.get("Greetings", status); 1365 if (result) { 1366 logln("object is: " + *result); 1367 delete result; 1368 } else { 1369 errln("could not get object"); 1370 } 1371 } 1372 1373 UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status); 1374 // yuck, this is awkward to use. All because we pass null in an overload. 1375 // TODO: change this. 1376 UnicodeString str("Greet"); 1377 service.getVisibleIDs(ids, &str, status); 1378 confirmIdentical("no fallback of greet", ids.size(), 0); 1379 } 1380 1381 // ICULocaleService 1382 1383 // LocaleKey 1384 { 1385 UnicodeString primary("en_US"); 1386 UnicodeString fallback("ja_JP"); 1387 UErrorCode status = U_ZERO_ERROR; 1388 LocaleKey* key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status); 1389 1390 if (key->getDynamicClassID() != LocaleKey::getStaticClassID()) { 1391 errln("localekey rtti error"); 1392 } 1393 1394 if (!key->isFallbackOf("en_US_FOOBAR")) { 1395 errln("localekey should be fallback for en_US_FOOBAR"); 1396 } 1397 if (!key->isFallbackOf("en_US")) { 1398 errln("localekey should be fallback for en_US"); 1399 } 1400 if (key->isFallbackOf("en")) { 1401 errln("localekey should not be fallback for en"); 1402 } 1403 1404 do { 1405 Locale loc; 1406 logln(UnicodeString("current locale: ") + key->currentLocale(loc).getName()); 1407 logln(UnicodeString("canonical locale: ") + key->canonicalLocale(loc).getName()); 1408 logln(UnicodeString("is fallback of en: ") + (key->isFallbackOf("en") ? "true" : " false")); 1409 } while (key->fallback()); 1410 delete key; 1411 1412 // LocaleKeyFactory 1413 key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status); 1414 1415 UnicodeString result; 1416 LKFSubclass lkf(TRUE); // empty 1417 Hashtable table; 1418 1419 UObject *obj = lkf.create(*key, NULL, status); 1420 logln("obj: " + UnicodeString(obj ? "obj" : "null")); 1421 logln(lkf.getDisplayName("en_US", Locale::getDefault(), result)); 1422 lkf.updateVisibleIDs(table, status); 1423 delete obj; 1424 if (table.count() != 1) { 1425 errln("visible IDs does not contain en_US"); 1426 } 1427 1428 LKFSubclass invisibleLKF(FALSE); 1429 obj = lkf.create(*key, NULL, status); 1430 logln("obj: " + UnicodeString(obj ? "obj" : "null")); 1431 logln(invisibleLKF.getDisplayName("en_US", Locale::getDefault(), result.remove())); 1432 invisibleLKF.updateVisibleIDs(table, status); 1433 if (table.count() != 0) { 1434 errln("visible IDs contains en_US"); 1435 } 1436 delete obj; 1437 delete key; 1438 1439 key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, 123, status); 1440 if (U_SUCCESS(status)) { 1441 UnicodeString str; 1442 key->currentDescriptor(str); 1443 key->parsePrefix(str); 1444 if (str != "123") { 1445 errln("did not get expected prefix"); 1446 } 1447 delete key; 1448 } 1449 1450 // coverage, getSupportedIDs is either overridden or the calling method is 1451 LKFSubclass0 lkFactory; 1452 Hashtable table0; 1453 lkFactory.updateVisibleIDs(table0, status); 1454 if (table0.count() != 0) { 1455 errln("LKF returned non-empty hashtable"); 1456 } 1457 1458 1459 // ResourceBundleFactory 1460 key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status); 1461 ICUResourceBundleFactory rbf; 1462 UObject* icurb = rbf.create(*key, NULL, status); 1463 if (icurb != NULL) { 1464 logln("got resource bundle for key"); 1465 delete icurb; 1466 } 1467 delete key; 1468 } 1469 1470 #if 0 1471 // ICUNotifier 1472 ICUNotifier nf = new ICUNSubclass(); 1473 try { 1474 nf.addListener(null); 1475 errln("added null listener"); 1476 } 1477 catch (NullPointerException e) { 1478 logln(e.getMessage()); 1479 } 1480 catch (Exception e) { 1481 errln("got wrong exception"); 1482 } 1483 1484 try { 1485 nf.addListener(new WrongListener()); 1486 errln("added wrong listener"); 1487 } 1488 catch (InternalError e) { 1489 logln(e.getMessage()); 1490 } 1491 catch (Exception e) { 1492 errln("got wrong exception"); 1493 } 1494 1495 try { 1496 nf.removeListener(null); 1497 errln("removed null listener"); 1498 } 1499 catch (NullPointerException e) { 1500 logln(e.getMessage()); 1501 } 1502 catch (Exception e) { 1503 errln("got wrong exception"); 1504 } 1505 1506 nf.removeListener(new MyListener()); 1507 nf.notifyChanged(); 1508 nf.addListener(new MyListener()); 1509 nf.removeListener(new MyListener()); 1510 #endif 1511 } 1512 1513 1514 /* !UCONFIG_NO_SERVICE */ 1515 #endif 1516 1517 1518