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