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