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