1 /******************************************************************** 
   3  * Copyright (c) 2002-2008, International Business Machines Corporation and 
   4  * others. All Rights Reserved. 
   5  ********************************************************************/ 
   8 #include "cmemory.h" // UAlignedMemory 
  14  * Test for UObject, currently only the classID. 
  17  *   TESTCLASSID_ABSTRACT(Bar) 
  18  *      --  Bar is expected to be abstract. Only the static ID will be tested. 
  20  *   TESTCLASSID_DEFAULT(Foo) 
  21  *      --  Foo will be default-constructed. 
  23  *   TESTCLASSID_CTOR(Foo, (1, 2, 3, status)) 
  24  *      -- Second argument is (parenthesized) constructor argument. 
  25  *          Will be called as:   new Foo ( 1, 2, 3, status)  [status is tested] 
  27  *   TESTCLASSID_FACTORY(Foo, fooCreateFunction(status) )  
  28  *      -- call fooCreateFunction.  'status' will be tested & reset 
  30  *   TESTCLASSID_FACTORY_HIDDEN(class, factory) 
  31  *      -- call factory.  Class is not available from a header. 
  32  *      'status' will be tested & reset. This only tests uniqueness. 
  36 #define TESTCLASSID_FACTORY(c, f) { delete testClass(f, #c, #f, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - " #f " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } } 
  37 #define TESTCLASSID_TRANSLIT(c, t) { delete testClass(Transliterator::createInstance(UnicodeString(t), UTRANS_FORWARD,parseError,status), #c, "Transliterator: " #t, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - Transliterator: " #t " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } } 
  38 #define TESTCLASSID_CTOR(c, x) { delete testClass(new c x, #c, "new " #c #x, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - new " #x " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } } 
  39 #define TESTCLASSID_DEFAULT(c) delete testClass(new c, #c, "new " #c , c::getStaticClassID()) 
  40 #define TESTCLASSID_ABSTRACT(c) testClass(NULL, #c, NULL, c::getStaticClassID()) 
  41 #define TESTCLASSID_FACTORY_HIDDEN(c, f) {UObject *objVar = f; delete testClass(objVar, #c, #f, objVar!=NULL? objVar->getDynamicClassID(): NULL); if(U_FAILURE(status)) { errln(UnicodeString(#c " - " #f " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } } 
  43 #define MAX_CLASS_ID 200 
  45 static UClassID    ids
[MAX_CLASS_ID
]; 
  46 static const char *ids_factory
[MAX_CLASS_ID
]; 
  47 static const char *ids_class
[MAX_CLASS_ID
]; 
  48 static uint32_t    ids_count 
= 0; 
  50 UObject 
*UObjectTest::testClass(UObject 
*obj
, 
  51                 const char *className
, const char *factory
,  
  55     UnicodeString what 
= UnicodeString(className
) + " * x= " + UnicodeString(factory
?factory
:" ABSTRACT ") + "; "; 
  56     UClassID dynamicID 
= NULL
; 
  58     if(ids_count 
>= MAX_CLASS_ID
) { 
  60         sprintf(count
, " (currently %d) ", MAX_CLASS_ID
); 
  61         errln("FAIL: Fatal: Ran out of IDs! Increase MAX_CLASS_ID." + UnicodeString(count
) + what
); 
  66         dynamicID 
= obj
->getDynamicClassID(); 
  71         sprintf(tmp
, " [static=%p, dynamic=%p] ", staticID
, dynamicID
); 
  75     if(staticID 
== NULL
) { 
  76         errln("FAIL: staticID == NULL!" + what
); 
  79     if(factory 
!= NULL
) {  /* NULL factory means: abstract */ 
  81             errln( "FAIL: ==NULL!" + what
); 
  85         if(dynamicID 
== NULL
) { 
  86             errln("FAIL: dynamicID == NULL!" + what
); 
  89         if(dynamicID 
!= staticID
) { 
  90             errln("FAIL: dynamicID != staticID!" + what 
); 
  94     // Bail out if static ID is null. Error message was already printed. 
  95     if(staticID 
== NULL
) { 
  99     for(i
=0;i
<ids_count
;i
++) { 
 100         if(staticID 
== ids
[i
]) { 
 101             if(!strcmp(ids_class
[i
], className
)) { 
 102                 logln("OK: ID found is the same as " + UnicodeString(ids_class
[i
]) + UnicodeString(" *y= ") + ids_factory
[i
] + what
); 
 105                 errln("FAIL: ID is the same as " + UnicodeString(ids_class
[i
]) + UnicodeString(" *y= ") + ids_factory
[i
] + what
); 
 111     ids
[ids_count
] = staticID
; 
 112     ids_factory
[ids_count
] = factory
; 
 113     ids_class
[ids_count
] = className
; 
 120 // begin actual #includes for things to be tested 
 122 // The following script will generate the #includes needed here: 
 124 //    find common i18n -name '*.h' -print | xargs fgrep ClassID | cut -d: -f1 | cut -d\/ -f2-  | sort | uniq | sed -e 's%.*%#include "&"%' 
 127 #include "unicode/utypes.h" 
 129 // Internal Things (woo) 
 130 #include "cpdtrans.h" 
 132 #include "rbt_data.h" 
 133 #include "nultrans.h" 
 134 #include "anytrans.h" 
 135 #include "digitlst.h" 
 137 #include "funcrepl.h" 
 138 #include "servnotf.h" 
 141 #include "name2uni.h" 
 143 #include "nortrans.h" 
 145 #include "remtrans.h" 
 146 #include "strmatch.h" 
 148 #include "titletrn.h" 
 149 #include "tolowtrn.h" 
 150 #include "toupptrn.h" 
 151 #include "unesctrn.h" 
 152 #include "uni2name.h" 
 154 #include "uvectr32.h" 
 156 #include "buddhcal.h" 
 157 #include "islamcal.h" 
 158 #include "japancal.h" 
 159 #include "hebrwcal.h" 
 160 #include "persncal.h" 
 161 #include "taiwncal.h" 
 162 #include "indiancal.h" 
 163 #include "chnsecal.h" 
 164 #include "windtfmt.h" 
 165 #include "winnmfmt.h" 
 166 #include "ustrenum.h" 
 168 #include "reldtfmt.h" 
 171 #include "unicode/brkiter.h" 
 172 #include "unicode/calendar.h" 
 173 #include "unicode/caniter.h" 
 174 #include "unicode/chariter.h" 
 175 #include "unicode/choicfmt.h" 
 176 #include "unicode/coleitr.h" 
 177 #include "unicode/coll.h" 
 178 #include "unicode/curramt.h" 
 179 #include "unicode/datefmt.h" 
 180 #include "unicode/dcfmtsym.h" 
 181 #include "unicode/decimfmt.h" 
 182 #include "unicode/dtfmtsym.h" 
 183 #include "unicode/dtptngen.h" 
 184 #include "unicode/fieldpos.h" 
 185 #include "unicode/fmtable.h" 
 186 #include "unicode/format.h" 
 187 #include "unicode/gregocal.h" 
 188 #include "unicode/locid.h" 
 189 #include "unicode/msgfmt.h" 
 190 #include "unicode/normlzr.h" 
 191 #include "unicode/numfmt.h" 
 192 #include "unicode/parsepos.h" 
 193 #include "unicode/plurrule.h" 
 194 #include "unicode/plurfmt.h" 
 195 #include "unicode/rbbi.h" 
 196 #include "unicode/rbnf.h" 
 197 #include "unicode/regex.h" 
 198 #include "unicode/resbund.h" 
 199 #include "unicode/schriter.h" 
 200 #include "unicode/simpletz.h" 
 201 #include "unicode/smpdtfmt.h" 
 202 #include "unicode/sortkey.h" 
 203 #include "unicode/stsearch.h" 
 204 #include "unicode/tblcoll.h" 
 205 #include "unicode/timezone.h" 
 206 #include "unicode/translit.h" 
 207 #include "unicode/uchriter.h" 
 208 #include "unicode/unifilt.h" 
 209 #include "unicode/unifunct.h" 
 210 #include "unicode/uniset.h" 
 211 #include "unicode/unistr.h" 
 212 #include "unicode/uobject.h" 
 213 #include "unicode/usetiter.h" 
 214 //#include "unicode/bidi.h" 
 215 //#include "unicode/convert.h" 
 217 // END includes ============================================================= 
 219 #define UOBJTEST_TEST_INTERNALS 0   /* do NOT test Internal things - their functions aren't exported on Win32 */ 
 221 #if !UCONFIG_NO_SERVICE 
 222 /* The whole purpose of this class is to expose the constructor, and gain access to the superclasses RTTI. */ 
 223 class TestLocaleKeyFactory 
: public LocaleKeyFactory 
{ 
 225     TestLocaleKeyFactory(int32_t coverage
) : LocaleKeyFactory(coverage
) {} 
 229 void UObjectTest::testIDs() 
 232     UErrorCode status 
= U_ZERO_ERROR
; 
 233     static const UChar SMALL_STR
[] = {0x51, 0x51, 0x51, 0}; // "QQQ" 
 235 #if !UCONFIG_NO_TRANSLITERATION || !UCONFIG_NO_FORMATTING 
 236     UParseError parseError
; 
 240 #if !UCONFIG_NO_NORMALIZATION 
 241     TESTCLASSID_FACTORY(CanonicalIterator
, new CanonicalIterator(UnicodeString("abc"), status
)); 
 243     //TESTCLASSID_DEFAULT(CollationElementIterator); 
 244 #if !UCONFIG_NO_COLLATION 
 245     TESTCLASSID_DEFAULT(CollationKey
); 
 246     TESTCLASSID_FACTORY(UStringEnumeration
, Collator::getKeywords(status
)); 
 247     //TESTCLASSID_FACTORY_HIDDEN(CollationLocaleListEnumeration, Collator::getAvailableLocales()); 
 249     //TESTCLASSID_FACTORY(CompoundTransliterator, Transliterator::createInstance(UnicodeString("Any-Jex;Hangul-Jamo"), UTRANS_FORWARD, parseError, status)); 
 251 #if !UCONFIG_NO_FORMATTING 
 252     /* TESTCLASSID_FACTORY(NFSubstitution,  NFSubstitution::makeSubstitution(8, */ 
 253     /* TESTCLASSID_DEFAULT(DigitList);  UMemory but not UObject*/ 
 254     TESTCLASSID_ABSTRACT(NumberFormat
); 
 255     TESTCLASSID_CTOR(RuleBasedNumberFormat
, (UnicodeString("%default: -x: minus >>;"), parseError
, status
)); 
 256     TESTCLASSID_CTOR(ChoiceFormat
, (UNICODE_STRING_SIMPLE("0#are no files|1#is one file|1<are many files"), status
)); 
 257     TESTCLASSID_CTOR(MessageFormat
, (UnicodeString(), status
)); 
 258     TESTCLASSID_CTOR(DateFormatSymbols
, (status
)); 
 259     TESTCLASSID_CTOR(PluralFormat
, (status
)); 
 260     TESTCLASSID_CTOR(PluralRules
, (status
)); 
 261     TESTCLASSID_FACTORY(DateTimePatternGenerator
, DateTimePatternGenerator::createInstance(status
)); 
 262     TESTCLASSID_FACTORY(RelativeDateFormat
, DateFormat::createDateInstance(DateFormat::kFullRelative
, Locale::getUS())); 
 263     TESTCLASSID_CTOR(DecimalFormatSymbols
, (status
)); 
 264     TESTCLASSID_DEFAULT(FieldPosition
); 
 265     TESTCLASSID_DEFAULT(Formattable
); 
 266     TESTCLASSID_CTOR(CurrencyAmount
, (1.0, SMALL_STR
, status
)); 
 267     TESTCLASSID_CTOR(CurrencyUnit
, (SMALL_STR
, status
)); 
 268     TESTCLASSID_FACTORY_HIDDEN(CurrencyFormat
, MeasureFormat::createCurrencyFormat(Locale::getUS(), status
)); 
 269     TESTCLASSID_FACTORY(GregorianCalendar
, Calendar::createInstance(Locale("@calendar=gregorian"), status
)); 
 270     TESTCLASSID_FACTORY(BuddhistCalendar
, Calendar::createInstance(Locale("@calendar=buddhist"), status
)); 
 271     TESTCLASSID_FACTORY(IslamicCalendar
, Calendar::createInstance(Locale("@calendar=islamic"), status
)); 
 272     TESTCLASSID_FACTORY(JapaneseCalendar
, Calendar::createInstance(Locale("@calendar=japanese"), status
)); 
 273     TESTCLASSID_FACTORY(HebrewCalendar
, Calendar::createInstance(Locale("@calendar=hebrew"), status
)); 
 274     TESTCLASSID_FACTORY(PersianCalendar
, Calendar::createInstance(Locale("@calendar=persian"), status
)); 
 275     TESTCLASSID_FACTORY(IndianCalendar
, Calendar::createInstance(Locale("@calendar=indian"), status
)); 
 276     TESTCLASSID_FACTORY(ChineseCalendar
, Calendar::createInstance(Locale("@calendar=chinese"), status
)); 
 277     TESTCLASSID_FACTORY(TaiwanCalendar
, Calendar::createInstance(Locale("@calendar=roc"), status
)); 
 279     TESTCLASSID_FACTORY(Win32DateFormat
, DateFormat::createDateInstance(DateFormat::kFull
, Locale("@compat=host"))); 
 280     TESTCLASSID_FACTORY(Win32NumberFormat
, NumberFormat::createInstance(Locale("@compat=host"), status
)); 
 284 #if !UCONFIG_NO_BREAK_ITERATION 
 285     /* TESTCLASSID_ABSTRACT(BreakIterator); No staticID!  */ 
 286     TESTCLASSID_FACTORY(RuleBasedBreakIterator
, BreakIterator::createLineInstance("mt",status
)); 
 287     //TESTCLASSID_FACTORY(DictionaryBasedBreakIterator, BreakIterator::createLineInstance("th",status)); 
 289 #if !UCONFIG_NO_SERVICE 
 290     TESTCLASSID_FACTORY_HIDDEN(ICULocaleService
, BreakIterator::getAvailableLocales()); 
 294     //TESTCLASSID_DEFAULT(GregorianCalendar); 
 296 #if !UCONFIG_NO_TRANSLITERATION 
 297     TESTCLASSID_TRANSLIT(AnyTransliterator
, "Any-Latin"); 
 298     TESTCLASSID_TRANSLIT(CompoundTransliterator
, "Latin-Greek"); 
 299     TESTCLASSID_TRANSLIT(EscapeTransliterator
, "Any-Hex"); 
 300     TESTCLASSID_TRANSLIT(LowercaseTransliterator
, "Lower"); 
 301     TESTCLASSID_TRANSLIT(NameUnicodeTransliterator
, "Name-Any"); 
 302     TESTCLASSID_TRANSLIT(NormalizationTransliterator
, "NFD"); 
 303     TESTCLASSID_TRANSLIT(NullTransliterator
, "Null"); 
 304     TESTCLASSID_TRANSLIT(RemoveTransliterator
, "Remove"); 
 305     TESTCLASSID_FACTORY(RuleBasedTransliterator
, Transliterator::createFromRules(UnicodeString("abcd"),UnicodeString("a>b;"),UTRANS_FORWARD
,parseError
,status
)); 
 306     TESTCLASSID_TRANSLIT(TitlecaseTransliterator
, "Title"); 
 307     TESTCLASSID_TRANSLIT(UnescapeTransliterator
, "Hex-Any"); 
 308     TESTCLASSID_TRANSLIT(UnicodeNameTransliterator
, "Any-Name"); 
 309     TESTCLASSID_TRANSLIT(UppercaseTransliterator
, "Upper"); 
 310     TESTCLASSID_ABSTRACT(CaseMapTransliterator
); 
 311     TESTCLASSID_ABSTRACT(Transliterator
); 
 312     TESTCLASSID_FACTORY_HIDDEN(TransliteratorRegistry::Enumeration
, Transliterator::getAvailableIDs(status
)); 
 314 #if UOBJTEST_TEST_INTERNALS 
 315     TESTCLASSID_CTOR(Quantifier
, (NULL
, 0, 0)); 
 316     TESTCLASSID_CTOR(FunctionReplacer
, (NULL
,NULL
)); 
 317     TESTCLASSID_CTOR(StringMatcher
, (UnicodeString("x"), 0,0,0,TransliterationRuleData(status
))); 
 318     TESTCLASSID_CTOR(StringReplacer
,(UnicodeString(),new TransliterationRuleData(status
))); 
 322     TESTCLASSID_FACTORY(Locale
, new Locale("123")); 
 323     TESTCLASSID_FACTORY_HIDDEN(KeywordEnumeration
, Locale("@a=b").createKeywords(status
)); 
 325     //TESTCLASSID_DEFAULT(Normalizer); 
 327     //TESTCLASSID_DEFAULT(NumeratorSubstitution); 
 329 #if !UCONFIG_NO_TRANSLITERATION 
 330     TESTCLASSID_DEFAULT(ParsePosition
); 
 335     //TESTCLASSID_DEFAULT(RegexCompile); 
 336     //TESTCLASSID_DEFAULT(RegexMatcher); 
 337     //TESTCLASSID_DEFAULT(RegexPattern); 
 339     //TESTCLASSID_DEFAULT(ReplaceableGlue); 
 340     TESTCLASSID_FACTORY(ResourceBundle
, new ResourceBundle(UnicodeString(), status
) ); 
 341     //TESTCLASSID_DEFAULT(RuleBasedTransliterator); 
 343     //TESTCLASSID_DEFAULT(SimpleFwdCharIterator); 
 344     //TESTCLASSID_DEFAULT(StringReplacer); 
 345     //TESTCLASSID_DEFAULT(StringSearch); 
 347     //TESTCLASSID_DEFAULT(TestMultipleKeyStringFactory); 
 348     //TESTCLASSID_DEFAULT(TestReplaceable); 
 350 #if !UCONFIG_NO_FORMATTING 
 351     TESTCLASSID_ABSTRACT(TimeZone
); 
 352     TESTCLASSID_FACTORY(OlsonTimeZone
, TimeZone::createTimeZone(UnicodeString("America/Los_Angeles"))); 
 353     TESTCLASSID_FACTORY_HIDDEN(KeywordEnumeration
, TimeZone::createEnumeration()); 
 356     TESTCLASSID_DEFAULT(UnicodeString
); 
 357     TESTCLASSID_CTOR(UnicodeSet
, (0, 1)); 
 358     TESTCLASSID_ABSTRACT(UnicodeFilter
); 
 359     TESTCLASSID_ABSTRACT(UnicodeFunctor
); 
 360     TESTCLASSID_CTOR(UnicodeSetIterator
,(UnicodeSet(0,1))); 
 361     TESTCLASSID_CTOR(UStack
, (status
)); 
 362     TESTCLASSID_CTOR(UVector
, (status
)); 
 363     TESTCLASSID_CTOR(UVector32
, (status
)); 
 365 #if !UCONFIG_NO_SERVICE 
 366     TESTCLASSID_CTOR(SimpleFactory
, (NULL
, UnicodeString("foo"))); 
 367     TESTCLASSID_DEFAULT(EventListener
); 
 368     TESTCLASSID_DEFAULT(ICUResourceBundleFactory
); 
 369     //TESTCLASSID_DEFAULT(Key); // does not exist? 
 370     UnicodeString 
baz("baz"); 
 371     UnicodeString 
bat("bat"); 
 372     TESTCLASSID_FACTORY(LocaleKey
, LocaleKey::createWithCanonicalFallback(&baz
, &bat
, LocaleKey::KIND_ANY
, status
)); 
 373     TESTCLASSID_CTOR(SimpleLocaleKeyFactory
, (NULL
, UnicodeString("bar"), 8, 12) ); 
 374     TESTCLASSID_CTOR(TestLocaleKeyFactory
, (42));   // Test replacement for LocaleKeyFactory 
 375 //#if UOBJTEST_TEST_INTERNALS 
 376 //    TESTCLASSID_CTOR(LocaleKeyFactory, (42)); 
 380 #if UOBJTEST_DUMP_IDS 
 382     for(i
=0;i
<ids_count
;i
++) { 
 384         sprintf(junk
, " %4d:\t%p\t%s\t%s\n",  
 385             i
, ids
[i
], ids_class
[i
], ids_factory
[i
]); 
 386         logln(UnicodeString(junk
)); 
 391 void UObjectTest::testUMemory() { 
 392     // additional tests for code coverage 
 393 #if U_OVERRIDE_CXX_ALLOCATION && U_HAVE_PLACEMENT_NEW 
 394     UAlignedMemory stackMemory
[sizeof(UnicodeString
)/sizeof(UAlignedMemory
)+1]; 
 398     p
=new(stackMemory
) UnicodeString(len
, (UChar32
)0x20ac, len
); 
 399     if((void *)p
!=(void *)stackMemory
) { 
 400         errln("placement new did not place the object at the expected address"); 
 402     if(p
->length()!=len 
|| p
->charAt(0)!=0x20ac || p
->charAt(len
-1)!=0x20ac) { 
 403         errln("constructor used with placement new did not work right"); 
 407      * It is not possible to simply say 
 408      *     delete(p, stackMemory); 
 409      * which results in a call to the normal, non-placement delete operator. 
 411      * Via a search on google.com for "c++ placement delete" I found 
 412      * http://cpptips.hyperformix.com/cpptips/placement_del3 
 415      * TITLE: using placement delete 
 417      * (Newsgroups: comp.std.c++, 27 Aug 97) 
 421      * > I do not completely understand how placement works on operator delete. 
 423      * There is no delete-expression which will invoke a placement 
 424      * form of operator delete. You can still call the function 
 425      * explicitly. Example: 
 427      *     // destroy object and delete space manually 
 429      *     operator delete(p, 12); 
 431      * ... so that's what I am doing here. 
 434     // destroy object and delete space manually 
 436     UnicodeString::operator delete(p
, stackMemory
);  
 438     // Jitterbug 4452, for coverage 
 439     UnicodeString 
*pa 
= new UnicodeString
[2]; 
 440     if ( !pa
[0].isEmpty() || !pa
[1].isEmpty()){ 
 441         errln("constructor used with array new did not work right"); 
 446     // try to call the compiler-generated UMemory::operator=(class UMemory const &) 
 451 void UObjectTest::TestMFCCompatibility() { 
 452 #if U_HAVE_DEBUG_LOCATION_NEW 
 453     /* Make sure that it compiles with MFC's debuggable new usage. */ 
 454     UnicodeString 
*str 
= new(__FILE__
, __LINE__
) UnicodeString(); 
 455     str
->append((UChar
)0x0040); // Is it usable? 
 456     if(str
->charAt(0) != 0x0040) { 
 457         errln("debug new doesn't work."); 
 459     UnicodeString::operator delete(str
, __FILE__
, __LINE__
); 
 463 /* --------------- */ 
 465 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break; 
 468 void UObjectTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /* par */ ) 
 473     CASE(1, testUMemory
); 
 474     CASE(2, TestMFCCompatibility
); 
 476     default: name 
= ""; break; //needed to end loop