intltest.cpp revision b13da9df870a61b11249bf741347908dbea0edd8
1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2007, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 8#include "unicode/utypes.h" 9 10/** 11 * IntlTest is a base class for tests. 12 */ 13 14#include <stdio.h> 15#include <string.h> 16#include <assert.h> 17#include <stdarg.h> 18#include <stdlib.h> 19 20#include "unicode/unistr.h" 21#include "unicode/ures.h" 22#include "unicode/smpdtfmt.h" 23#include "unicode/ucnv.h" 24#include "unicode/uclean.h" 25#include "unicode/timezone.h" 26#include "unicode/curramt.h" 27#include "unicode/putil.h" 28 29#include "intltest.h" 30#include "caltztst.h" 31#include "itmajor.h" 32#include "cstring.h" 33#include "umutex.h" 34#include "uassert.h" 35#include "cmemory.h" 36#include "uoptions.h" 37 38#include "putilimp.h" // for uprv_getUTCtime() 39#include "unicode/locid.h" 40 41 42#ifdef XP_MAC_CONSOLE 43#include <console.h> 44#include "Files.h" 45#endif 46 47 48static char* _testDataPath=NULL; 49 50// Static list of errors found 51static UnicodeString errorList; 52 53//----------------------------------------------------------------------------- 54//convenience classes to ease porting code that uses the Java 55//string-concatenation operator (moved from findword test by rtg) 56 57// [LIU] Just to get things working 58UnicodeString 59UCharToUnicodeString(UChar c) 60{ return UnicodeString(c); } 61 62// [rtg] Just to get things working 63UnicodeString 64operator+(const UnicodeString& left, 65 long num) 66{ 67 char buffer[64]; // nos changed from 10 to 64 68 char danger = 'p'; // guard against overrunning the buffer (rtg) 69 70 sprintf(buffer, "%ld", num); 71 assert(danger == 'p'); 72 73 return left + buffer; 74} 75 76UnicodeString 77operator+(const UnicodeString& left, 78 unsigned long num) 79{ 80 char buffer[64]; // nos changed from 10 to 64 81 char danger = 'p'; // guard against overrunning the buffer (rtg) 82 83 sprintf(buffer, "%lu", num); 84 assert(danger == 'p'); 85 86 return left + buffer; 87} 88 89UnicodeString 90Int64ToUnicodeString(int64_t num) 91{ 92 char buffer[64]; // nos changed from 10 to 64 93 char danger = 'p'; // guard against overrunning the buffer (rtg) 94 95#ifdef U_WINDOWS 96 sprintf(buffer, "%I64d", num); 97#else 98 sprintf(buffer, "%lld", (long long)num); 99#endif 100 assert(danger == 'p'); 101 102 return buffer; 103} 104 105// [LIU] Just to get things working 106UnicodeString 107operator+(const UnicodeString& left, 108 double num) 109{ 110 char buffer[64]; // was 32, made it arbitrarily bigger (rtg) 111 char danger = 'p'; // guard against overrunning the buffer (rtg) 112 113 // IEEE floating point has 52 bits of mantissa, plus one assumed bit 114 // 53*log(2)/log(10) = 15.95 115 // so there is no need to show more than 16 digits. [alan] 116 117 sprintf(buffer, "%.17g", num); 118 assert(danger == 'p'); 119 120 return left + buffer; 121} 122 123#if !UCONFIG_NO_FORMATTING 124 125/** 126 * Return a string display for for this, without surrounding braces. 127 */ 128UnicodeString _toString(const Formattable& f) { 129 UnicodeString s; 130 switch (f.getType()) { 131 case Formattable::kDate: 132 { 133 UErrorCode status = U_ZERO_ERROR; 134 SimpleDateFormat fmt(status); 135 if (U_SUCCESS(status)) { 136 FieldPosition pos; 137 fmt.format(f.getDate(), s, pos); 138 s.insert(0, "Date:"); 139 } else { 140 s = UnicodeString("Error creating date format]"); 141 } 142 } 143 break; 144 case Formattable::kDouble: 145 s = UnicodeString("double:") + f.getDouble(); 146 break; 147 case Formattable::kLong: 148 s = UnicodeString("long:") + f.getLong(); 149 break; 150 151 case Formattable::kInt64: 152 s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64()); 153 break; 154 155 case Formattable::kString: 156 f.getString(s); 157 s.insert(0, "String:"); 158 break; 159 case Formattable::kArray: 160 { 161 int32_t i, n; 162 const Formattable* array = f.getArray(n); 163 s.insert(0, UnicodeString("Array:")); 164 UnicodeString delim(", "); 165 for (i=0; i<n; ++i) { 166 if (i > 0) { 167 s.append(delim); 168 } 169 s = s + _toString(array[i]); 170 } 171 } 172 break; 173 case Formattable::kObject: 174 if (f.getObject()->getDynamicClassID() == 175 CurrencyAmount::getStaticClassID()) { 176 const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject(); 177 s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency()); 178 } else { 179 s = UnicodeString("Unknown UObject"); 180 } 181 break; 182 default: 183 s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType(); 184 break; 185 } 186 return s; 187} 188 189/** 190 * Originally coded this as operator+, but that makes the expression 191 * + char* ambiguous. - liu 192 */ 193UnicodeString toString(const Formattable& f) { 194 UnicodeString s((UChar)91/*[*/); 195 s.append(_toString(f)); 196 s.append((UChar)0x5d/*]*/); 197 return s; 198} 199 200#endif 201 202// useful when operator+ won't cooperate 203UnicodeString toString(int32_t n) { 204 return UnicodeString() + (long)n; 205} 206 207// stephen - cleaned up 05/05/99 208UnicodeString operator+(const UnicodeString& left, char num) 209{ return left + (long)num; } 210UnicodeString operator+(const UnicodeString& left, short num) 211{ return left + (long)num; } 212UnicodeString operator+(const UnicodeString& left, int num) 213{ return left + (long)num; } 214UnicodeString operator+(const UnicodeString& left, unsigned char num) 215{ return left + (unsigned long)num; } 216UnicodeString operator+(const UnicodeString& left, unsigned short num) 217{ return left + (unsigned long)num; } 218UnicodeString operator+(const UnicodeString& left, unsigned int num) 219{ return left + (unsigned long)num; } 220UnicodeString operator+(const UnicodeString& left, float num) 221{ return left + (double)num; } 222 223//------------------ 224 225// Append a hex string to the target 226UnicodeString& 227IntlTest::appendHex(uint32_t number, 228 int32_t digits, 229 UnicodeString& target) 230{ 231 static const UChar digitString[] = { 232 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 233 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0 234 }; /* "0123456789ABCDEF" */ 235 236 switch (digits) 237 { 238 case 8: 239 target += digitString[(number >> 28) & 0xF]; 240 case 7: 241 target += digitString[(number >> 24) & 0xF]; 242 case 6: 243 target += digitString[(number >> 20) & 0xF]; 244 case 5: 245 target += digitString[(number >> 16) & 0xF]; 246 case 4: 247 target += digitString[(number >> 12) & 0xF]; 248 case 3: 249 target += digitString[(number >> 8) & 0xF]; 250 case 2: 251 target += digitString[(number >> 4) & 0xF]; 252 case 1: 253 target += digitString[(number >> 0) & 0xF]; 254 break; 255 default: 256 target += "**"; 257 } 258 return target; 259} 260 261// Replace nonprintable characters with unicode escapes 262UnicodeString& 263IntlTest::prettify(const UnicodeString &source, 264 UnicodeString &target) 265{ 266 int32_t i; 267 268 target.remove(); 269 target += "\""; 270 271 for (i = 0; i < source.length(); ) 272 { 273 UChar32 ch = source.char32At(i); 274 i += UTF_CHAR_LENGTH(ch); 275 276 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E) 277 { 278 if (ch <= 0xFFFF) { 279 target += "\\u"; 280 appendHex(ch, 4, target); 281 } else { 282 target += "\\U"; 283 appendHex(ch, 8, target); 284 } 285 } 286 else 287 { 288 target += ch; 289 } 290 } 291 292 target += "\""; 293 294 return target; 295} 296 297// Replace nonprintable characters with unicode escapes 298UnicodeString 299IntlTest::prettify(const UnicodeString &source, UBool parseBackslash) 300{ 301 int32_t i; 302 UnicodeString target; 303 target.remove(); 304 target += "\""; 305 306 for (i = 0; i < source.length();) 307 { 308 UChar32 ch = source.char32At(i); 309 i += UTF_CHAR_LENGTH(ch); 310 311 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E) 312 { 313 if (parseBackslash) { 314 // If we are preceded by an odd number of backslashes, 315 // then this character has already been backslash escaped. 316 // Delete a backslash. 317 int32_t backslashCount = 0; 318 for (int32_t j=target.length()-1; j>=0; --j) { 319 if (target.charAt(j) == (UChar)92) { 320 ++backslashCount; 321 } else { 322 break; 323 } 324 } 325 if ((backslashCount % 2) == 1) { 326 target.truncate(target.length() - 1); 327 } 328 } 329 if (ch <= 0xFFFF) { 330 target += "\\u"; 331 appendHex(ch, 4, target); 332 } else { 333 target += "\\U"; 334 appendHex(ch, 8, target); 335 } 336 } 337 else 338 { 339 target += ch; 340 } 341 } 342 343 target += "\""; 344 345 return target; 346} 347 348/* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already 349 * set, try to deduce the directory in which ICU was built, 350 * and set ICU_DATA to "icu/source/data" in that location. 351 * The intent is to allow the tests to have a good chance 352 * of running without requiring that the user manually set 353 * ICU_DATA. Common data isn't a problem, since it is 354 * picked up via a static (build time) reference, but the 355 * tests dynamically load some data. 356 */ 357void IntlTest::setICU_DATA() { 358 const char *original_ICU_DATA = getenv("ICU_DATA"); 359 360 if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) { 361 /* If the user set ICU_DATA, don't second-guess the person. */ 362 return; 363 } 364 365 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst 366 // to point to the top of the build hierarchy, which may or 367 // may not be the same as the source directory, depending on 368 // the configure options used. At any rate, 369 // set the data path to the built data from this directory. 370 // The value is complete with quotes, so it can be used 371 // as-is as a string constant. 372 373#if defined (U_TOPBUILDDIR) 374 { 375 static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 376 u_setDataDirectory(env_string); 377 return; 378 } 379 380#else 381 // Use #else so we don't get compiler warnings due to the return above. 382 383 /* On Windows, the file name obtained from __FILE__ includes a full path. 384 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 385 * Change to "wherever\icu\source\data" 386 */ 387 { 388 char p[sizeof(__FILE__) + 10]; 389 char *pBackSlash; 390 int i; 391 392 strcpy(p, __FILE__); 393 /* We want to back over three '\' chars. */ 394 /* Only Windows should end up here, so looking for '\' is safe. */ 395 for (i=1; i<=3; i++) { 396 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 397 if (pBackSlash != NULL) { 398 *pBackSlash = 0; /* Truncate the string at the '\' */ 399 } 400 } 401 402 if (pBackSlash != NULL) { 403 /* We found and truncated three names from the path. 404 * Now append "source\data" and set the environment 405 */ 406 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); 407 u_setDataDirectory(p); /* p is "ICU_DATA=wherever\icu\source\data" */ 408 return; 409 } 410 else { 411 /* __FILE__ on MSVC7 does not contain the directory */ 412 u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); 413 return; 414 } 415 } 416#endif 417 418 /* No location for the data dir was identifiable. 419 * Add other fallbacks for the test data location here if the need arises 420 */ 421} 422 423 424//-------------------------------------------------------------------------------------- 425 426static const int32_t indentLevel_offset = 3; 427static const char delim = '/'; 428 429IntlTest* IntlTest::gTest = NULL; 430 431static int32_t execCount = 0; 432 433void it_log( UnicodeString message ) 434{ 435 if (IntlTest::gTest) 436 IntlTest::gTest->log( message ); 437} 438 439void it_logln( UnicodeString message ) 440{ 441 if (IntlTest::gTest) 442 IntlTest::gTest->logln( message ); 443} 444 445void it_logln( void ) 446{ 447 if (IntlTest::gTest) 448 IntlTest::gTest->logln(); 449} 450 451void it_info( UnicodeString message ) 452{ 453 if (IntlTest::gTest) 454 IntlTest::gTest->info( message ); 455} 456 457void it_infoln( UnicodeString message ) 458{ 459 if (IntlTest::gTest) 460 IntlTest::gTest->infoln( message ); 461} 462 463void it_infoln( void ) 464{ 465 if (IntlTest::gTest) 466 IntlTest::gTest->infoln(); 467} 468 469void it_err() 470{ 471 if (IntlTest::gTest) 472 IntlTest::gTest->err(); 473} 474 475void it_err( UnicodeString message ) 476{ 477 if (IntlTest::gTest) 478 IntlTest::gTest->err( message ); 479} 480 481void it_errln( UnicodeString message ) 482{ 483 if (IntlTest::gTest) 484 IntlTest::gTest->errln( message ); 485} 486 487void it_dataerr( UnicodeString message ) 488{ 489 if (IntlTest::gTest) 490 IntlTest::gTest->dataerr( message ); 491} 492 493void it_dataerrln( UnicodeString message ) 494{ 495 if (IntlTest::gTest) 496 IntlTest::gTest->dataerrln( message ); 497} 498 499IntlTest::IntlTest() 500{ 501 caller = NULL; 502 testPath = NULL; 503 LL_linestart = TRUE; 504 errorCount = 0; 505 dataErrorCount = 0; 506 verbose = FALSE; 507 no_err_msg = FALSE; 508 warn_on_missing_data = FALSE; 509 quick = FALSE; 510 leaks = FALSE; 511 testoutfp = stdout; 512 LL_indentlevel = indentLevel_offset; 513} 514 515void IntlTest::setCaller( IntlTest* callingTest ) 516{ 517 caller = callingTest; 518 if (caller) { 519 verbose = caller->verbose; 520 no_err_msg = caller->no_err_msg; 521 quick = caller->quick; 522 testoutfp = caller->testoutfp; 523 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset; 524 } 525} 526 527UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par ) 528{ 529 execCount--; // correct a previously assumed test-exec, as this only calls a subtest 530 testToBeCalled.setCaller( this ); 531 return testToBeCalled.runTest( testPath, par ); 532} 533 534void IntlTest::setPath( char* pathVal ) 535{ 536 this->testPath = pathVal; 537} 538 539UBool IntlTest::setVerbose( UBool verboseVal ) 540{ 541 UBool rval = this->verbose; 542 this->verbose = verboseVal; 543 return rval; 544} 545 546UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal ) 547{ 548 UBool rval = this->warn_on_missing_data; 549 this->warn_on_missing_data = warn_on_missing_dataVal; 550 return rval; 551} 552 553UBool IntlTest::setNoErrMsg( UBool no_err_msgVal ) 554{ 555 UBool rval = this->no_err_msg; 556 this->no_err_msg = no_err_msgVal; 557 return rval; 558} 559 560UBool IntlTest::setQuick( UBool quickVal ) 561{ 562 UBool rval = this->quick; 563 this->quick = quickVal; 564 return rval; 565} 566 567UBool IntlTest::setLeaks( UBool leaksVal ) 568{ 569 UBool rval = this->leaks; 570 this->leaks = leaksVal; 571 return rval; 572} 573 574int32_t IntlTest::getErrors( void ) 575{ 576 return errorCount; 577} 578 579int32_t IntlTest::getDataErrors( void ) 580{ 581 return dataErrorCount; 582} 583 584UBool IntlTest::runTest( char* name, char* par ) 585{ 586 UBool rval; 587 char* pos = NULL; 588 589 if (name) 590 pos = strchr( name, delim ); // check if name contains path (by looking for '/') 591 if (pos) { 592 testPath = pos+1; // store subpath for calling subtest 593 *pos = 0; // split into two strings 594 }else{ 595 testPath = NULL; 596 } 597 598 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) { 599 rval = runTestLoop( NULL, par ); 600 601 }else if (strcmp( name, "LIST" ) == 0) { 602 this->usage(); 603 rval = TRUE; 604 605 }else{ 606 rval = runTestLoop( name, par ); 607 } 608 609 if (pos) 610 *pos = delim; // restore original value at pos 611 return rval; 612} 613 614// call individual tests, to be overriden to call implementations 615void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par ) 616{ 617 // to be overriden by a method like: 618 /* 619 switch (index) { 620 case 0: name = "First Test"; if (exec) FirstTest( par ); break; 621 case 1: name = "Second Test"; if (exec) SecondTest( par ); break; 622 default: name = ""; break; 623 } 624 */ 625 this->errln("*** runIndexedTest needs to be overriden! ***"); 626 name = ""; exec = exec; index = index; par = par; 627} 628 629 630UBool IntlTest::runTestLoop( char* testname, char* par ) 631{ 632 int32_t index = 0; 633 const char* name; 634 UBool run_this_test; 635 int32_t lastErrorCount; 636 UBool rval = FALSE; 637 UBool lastTestFailed; 638 639 IntlTest* saveTest = gTest; 640 gTest = this; 641 do { 642 this->runIndexedTest( index, FALSE, name, par ); 643 if (!name || (name[0] == 0)) 644 break; 645 if (!testname) { 646 run_this_test = TRUE; 647 }else{ 648 run_this_test = (UBool) (strcmp( name, testname ) == 0); 649 } 650 if (run_this_test) { 651 lastErrorCount = errorCount; 652 execCount++; 653 this->runIndexedTest( index, TRUE, name, par ); 654 rval = TRUE; // at least one test has been called 655 char msg[256]; 656 if (lastErrorCount == errorCount) { 657 sprintf( msg, "---OK: %s", name ); 658 lastTestFailed = FALSE; 659 }else{ 660 sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name); 661 662 for(int i=0;i<LL_indentlevel;i++) { 663 errorList += " "; 664 } 665 errorList += name; 666 errorList += "\n"; 667 lastTestFailed = TRUE; 668 } 669 LL_indentlevel -= 3; 670 if (lastTestFailed) { 671 LL_message( "", TRUE); 672 } 673 LL_message( msg, TRUE); 674 if (lastTestFailed) { 675 LL_message( "", TRUE); 676 } 677 LL_indentlevel += 3; 678 } 679 index++; 680 }while(name); 681 682 gTest = saveTest; 683 return rval; 684} 685 686 687/** 688* Adds given string to the log if we are in verbose mode. 689*/ 690void IntlTest::log( const UnicodeString &message ) 691{ 692 if( verbose ) { 693 LL_message( message, FALSE ); 694 } 695} 696 697/** 698* Adds given string to the log if we are in verbose mode. Adds a new line to 699* the given message. 700*/ 701void IntlTest::logln( const UnicodeString &message ) 702{ 703 if( verbose ) { 704 LL_message( message, TRUE ); 705 } 706} 707 708void IntlTest::logln( void ) 709{ 710 if( verbose ) { 711 LL_message( "", TRUE ); 712 } 713} 714 715/** 716* Unconditionally adds given string to the log. 717*/ 718void IntlTest::info( const UnicodeString &message ) 719{ 720 LL_message( message, FALSE ); 721} 722 723/** 724* Unconditionally adds given string to the log. Adds a new line to 725* the given message. 726*/ 727void IntlTest::infoln( const UnicodeString &message ) 728{ 729 LL_message( message, TRUE ); 730} 731 732void IntlTest::infoln( void ) 733{ 734 LL_message( "", TRUE ); 735} 736 737int32_t IntlTest::IncErrorCount( void ) 738{ 739 errorCount++; 740 if (caller) caller->IncErrorCount(); 741 return errorCount; 742} 743 744int32_t IntlTest::IncDataErrorCount( void ) 745{ 746 dataErrorCount++; 747 if (caller) caller->IncDataErrorCount(); 748 return dataErrorCount; 749} 750 751void IntlTest::err() 752{ 753 IncErrorCount(); 754} 755 756void IntlTest::err( const UnicodeString &message ) 757{ 758 IncErrorCount(); 759 if (!no_err_msg) LL_message( message, FALSE ); 760} 761 762void IntlTest::errln( const UnicodeString &message ) 763{ 764 IncErrorCount(); 765 if (!no_err_msg) LL_message( message, TRUE ); 766} 767 768void IntlTest::dataerr( const UnicodeString &message ) 769{ 770 IncDataErrorCount(); 771 772 if (!warn_on_missing_data) { 773 IncErrorCount(); 774 } 775 776 if (!no_err_msg) LL_message( message, FALSE ); 777} 778 779void IntlTest::dataerrln( const UnicodeString &message ) 780{ 781 IncDataErrorCount(); 782 783 if (!warn_on_missing_data) { 784 IncErrorCount(); 785 } 786 787 if (!no_err_msg) LL_message( message, TRUE ); 788} 789 790/* convenience functions that include sprintf formatting */ 791void IntlTest::log(const char *fmt, ...) 792{ 793 char buffer[4000]; 794 va_list ap; 795 796 va_start(ap, fmt); 797 /* sprintf it just to make sure that the information is valid */ 798 vsprintf(buffer, fmt, ap); 799 va_end(ap); 800 if( verbose ) { 801 log(UnicodeString(buffer, "")); 802 } 803} 804 805void IntlTest::logln(const char *fmt, ...) 806{ 807 char buffer[4000]; 808 va_list ap; 809 810 va_start(ap, fmt); 811 /* sprintf it just to make sure that the information is valid */ 812 vsprintf(buffer, fmt, ap); 813 va_end(ap); 814 if( verbose ) { 815 logln(UnicodeString(buffer, "")); 816 } 817} 818 819/* convenience functions that include sprintf formatting */ 820void IntlTest::info(const char *fmt, ...) 821{ 822 char buffer[4000]; 823 va_list ap; 824 825 va_start(ap, fmt); 826 /* sprintf it just to make sure that the information is valid */ 827 vsprintf(buffer, fmt, ap); 828 va_end(ap); 829 info(UnicodeString(buffer, "")); 830} 831 832void IntlTest::infoln(const char *fmt, ...) 833{ 834 char buffer[4000]; 835 va_list ap; 836 837 va_start(ap, fmt); 838 /* sprintf it just to make sure that the information is valid */ 839 vsprintf(buffer, fmt, ap); 840 va_end(ap); 841 infoln(UnicodeString(buffer, "")); 842} 843 844void IntlTest::err(const char *fmt, ...) 845{ 846 char buffer[4000]; 847 va_list ap; 848 849 va_start(ap, fmt); 850 vsprintf(buffer, fmt, ap); 851 va_end(ap); 852 err(UnicodeString(buffer, "")); 853} 854 855void IntlTest::errln(const char *fmt, ...) 856{ 857 char buffer[4000]; 858 va_list ap; 859 860 va_start(ap, fmt); 861 vsprintf(buffer, fmt, ap); 862 va_end(ap); 863 errln(UnicodeString(buffer, "")); 864} 865 866void IntlTest::dataerrln(const char *fmt, ...) 867{ 868 char buffer[4000]; 869 va_list ap; 870 871 va_start(ap, fmt); 872 vsprintf(buffer, fmt, ap); 873 va_end(ap); 874 dataerrln(UnicodeString(buffer, "")); 875} 876 877void IntlTest::printErrors() 878{ 879 IntlTest::LL_message(errorList, TRUE); 880} 881 882void IntlTest::LL_message( UnicodeString message, UBool newline ) 883{ 884 // string that starts with a LineFeed character and continues 885 // with spaces according to the current indentation 886 static const UChar indentUChars[] = { 887 '\n', 888 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 889 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 890 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 891 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 892 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 893 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 894 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 895 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 896 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 897 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 898 }; 899 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel); 900 901 char buffer[10000]; 902 int32_t length; 903 904 // stream out the indentation string first if necessary 905 length = indent.extract(1, indent.length(), buffer, sizeof(buffer)); 906 if (length > 0) { 907 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 908 } 909 910 // replace each LineFeed by the indentation string 911 message.findAndReplace(UnicodeString((UChar)'\n'), indent); 912 913 // stream out the message 914 length = message.extract(0, message.length(), buffer, sizeof(buffer)); 915 if (length > 0) { 916 length = length > 10000 ? 10000 : length; 917 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 918 } 919 920 if (newline) { 921 char newLine = '\n'; 922 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp); 923 } 924 925 // A newline usually flushes the buffer, but 926 // flush the message just in case of a core dump. 927 fflush((FILE *)testoutfp); 928} 929 930/** 931* Print a usage message for this test class. 932*/ 933void IntlTest::usage( void ) 934{ 935 UBool save_verbose = setVerbose( TRUE ); 936 logln("Test names:"); 937 logln("-----------"); 938 939 int32_t index = 0; 940 const char* name = NULL; 941 do{ 942 this->runIndexedTest( index, FALSE, name ); 943 if (!name) break; 944 logln(name); 945 index++; 946 }while (name && (name[0] != 0)); 947 setVerbose( save_verbose ); 948} 949 950 951// memory leak reporting software will be able to take advantage of the testsuite 952// being run a second time local to a specific method in order to report only actual leaks 953UBool 954IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks 955{ 956 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter 957 strLeak->append(" for verifying purify filter"); 958 return this->runTest( name, par ); 959} 960 961 962#if UCONFIG_NO_LEGACY_CONVERSION 963# define TRY_CNV_1 "iso-8859-1" 964# define TRY_CNV_2 "ibm-1208" 965#else 966# define TRY_CNV_1 "iso-8859-7" 967# define TRY_CNV_2 "sjis" 968#endif 969 970int 971main(int argc, char* argv[]) 972{ 973 UBool syntax = FALSE; 974 UBool all = FALSE; 975 UBool verbose = FALSE; 976 UBool no_err_msg = FALSE; 977 UBool quick = TRUE; 978 UBool name = FALSE; 979 UBool leaks = FALSE; 980 UBool warnOnMissingData = FALSE; 981 UBool defaultDataFound = FALSE; 982 UErrorCode errorCode = U_ZERO_ERROR; 983 UConverter *cnv = NULL; 984 const char *warnOrErr = "Failure"; 985 UDate startTime, endTime; 986 int32_t diffTime; 987 988 U_MAIN_INIT_ARGS(argc, argv); 989 990 startTime = uprv_getUTCtime(); 991 992 for (int i = 1; i < argc; ++i) { 993 if (argv[i][0] == '-') { 994 const char* str = argv[i] + 1; 995 if (strcmp("verbose", str) == 0 || 996 strcmp("v", str) == 0) 997 verbose = TRUE; 998 else if (strcmp("noerrormsg", str) == 0 || 999 strcmp("n", str) == 0) 1000 no_err_msg = TRUE; 1001 else if (strcmp("exhaustive", str) == 0 || 1002 strcmp("e", str) == 0) 1003 quick = FALSE; 1004 else if (strcmp("all", str) == 0 || 1005 strcmp("a", str) == 0) 1006 all = TRUE; 1007 else if (strcmp("leaks", str) == 0 || 1008 strcmp("l", str) == 0) 1009 leaks = TRUE; 1010 else if (strcmp("w", str) == 0) { 1011 warnOnMissingData = TRUE; 1012 warnOrErr = "WARNING"; 1013 } 1014 else { 1015 syntax = TRUE; 1016 } 1017 }else{ 1018 name = TRUE; 1019 } 1020 } 1021 1022 if (!all && !name) { 1023 all = TRUE; 1024 } else if (all && name) { 1025 syntax = TRUE; 1026 } 1027 1028 if (syntax) { 1029 fprintf(stdout, 1030 "### Syntax:\n" 1031 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" 1032 "### where options are: verbose (v), all (a), noerrormsg (n), \n" 1033 "### exhaustive (e), leaks (l)" 1034 "### (Specify either -all (shortcut -a) or a test name). \n" 1035 "### -all will run all of the tests.\n" 1036 "### \n" 1037 "### To get a list of the test names type: intltest LIST \n" 1038 "### To run just the utility tests type: intltest utility \n" 1039 "### \n" 1040 "### Test names can be nested using slashes (\"testA/subtest1\") \n" 1041 "### For example to list the utility tests type: intltest utility/LIST \n" 1042 "### To run just the Locale test type: intltest utility/LocaleTest \n" 1043 "### \n" 1044 "### A parameter can be specified for a test by appending '@' and the value \n" 1045 "### to the testname. \n\n"); 1046 return 1; 1047 } 1048 1049 UBool all_tests_exist = TRUE; 1050 MajorTestLevel major; 1051 major.setVerbose( verbose ); 1052 major.setNoErrMsg( no_err_msg ); 1053 major.setQuick( quick ); 1054 major.setLeaks( leaks ); 1055 major.setWarnOnMissingData( warnOnMissingData ); 1056 fprintf(stdout, "-----------------------------------------------\n"); 1057 fprintf(stdout, " IntlTest (C++) Test Suite for \n"); 1058 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); 1059 fprintf(stdout, "-----------------------------------------------\n"); 1060 fprintf(stdout, " Options: \n"); 1061 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); 1062 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); 1063 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); 1064 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); 1065 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); 1066 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); 1067 fprintf(stdout, "-----------------------------------------------\n"); 1068 1069 /* Check whether ICU will initialize without forcing the build data directory into 1070 * the ICU_DATA path. Success here means either the data dll contains data, or that 1071 * this test program was run with ICU_DATA set externally. Failure of this check 1072 * is normal when ICU data is not packaged into a shared library. 1073 * 1074 * Whether or not this test succeeds, we want to cleanup and reinitialize 1075 * with a data path so that data loading from individual files can be tested. 1076 */ 1077 u_init(&errorCode); 1078 if (U_FAILURE(errorCode)) { 1079 fprintf(stderr, 1080 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n"); 1081 defaultDataFound = FALSE; 1082 } 1083 else { 1084 defaultDataFound = TRUE; 1085 } 1086 u_cleanup(); 1087 errorCode = U_ZERO_ERROR; 1088 1089 /* Initialize ICU */ 1090 if (!defaultDataFound) { 1091 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. 1092 } 1093 u_init(&errorCode); 1094 if (U_FAILURE(errorCode)) { 1095 fprintf(stderr, 1096 "#### ERROR! %s: u_init() failed with status = \"%s\".\n" 1097 "*** Check the ICU_DATA environment variable and \n" 1098 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); 1099 if(warnOnMissingData == 0) { 1100 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1101 u_cleanup(); 1102 return 1; 1103 } 1104 } 1105 1106 1107 // initial check for the default converter 1108 errorCode = U_ZERO_ERROR; 1109 cnv = ucnv_open(0, &errorCode); 1110 if(cnv != 0) { 1111 // ok 1112 ucnv_close(cnv); 1113 } else { 1114 fprintf(stdout, 1115 "*** %s! The default converter [%s] cannot be opened.\n" 1116 "*** Check the ICU_DATA environment variable and\n" 1117 "*** check that the data files are present.\n", 1118 warnOrErr, ucnv_getDefaultName()); 1119 if(!warnOnMissingData) { 1120 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1121 return 1; 1122 } 1123 } 1124 1125 // try more data 1126 cnv = ucnv_open(TRY_CNV_2, &errorCode); 1127 if(cnv != 0) { 1128 // ok 1129 ucnv_close(cnv); 1130 } else { 1131 fprintf(stdout, 1132 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" 1133 "*** Check the ICU_DATA environment variable and \n" 1134 "*** check that the data files are present.\n", warnOrErr); 1135 if(!warnOnMissingData) { 1136 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1137 return 1; 1138 } 1139 } 1140 1141 UResourceBundle *rb = ures_open(0, "en", &errorCode); 1142 ures_close(rb); 1143 if(U_FAILURE(errorCode)) { 1144 fprintf(stdout, 1145 "*** %s! The \"en\" locale resource bundle cannot be opened.\n" 1146 "*** Check the ICU_DATA environment variable and \n" 1147 "*** check that the data files are present.\n", warnOrErr); 1148 if(!warnOnMissingData) { 1149 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1150 return 1; 1151 } 1152 } 1153 1154 Locale originalLocale; // Save the default locale for comparison later on. 1155 1156 /* TODO: Add option to call u_cleanup and rerun tests. */ 1157 if (all) { 1158 major.runTest(); 1159 if (leaks) { 1160 major.run_phase2( NULL, NULL ); 1161 } 1162 }else{ 1163 for (int i = 1; i < argc; ++i) { 1164 if (argv[i][0] != '-') { 1165 char* name = argv[i]; 1166 fprintf(stdout, "\n=== Handling test: %s: ===\n", name); 1167 char* parameter = strchr( name, '@' ); 1168 if (parameter) { 1169 *parameter = 0; 1170 parameter += 1; 1171 } 1172 execCount = 0; 1173 UBool res = major.runTest( name, parameter ); 1174 if (leaks && res) { 1175 major.run_phase2( name, parameter ); 1176 } 1177 if (!res || (execCount <= 0)) { 1178 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name); 1179 all_tests_exist = FALSE; 1180 } 1181 } 1182 } 1183 } 1184 1185#if !UCONFIG_NO_FORMATTING 1186 CalendarTimeZoneTest::cleanup(); 1187#endif 1188 1189 free(_testDataPath); 1190 _testDataPath = 0; 1191 1192 Locale lastDefaultLocale; 1193 if (originalLocale != lastDefaultLocale) { 1194 major.errln("FAILURE: A test changed the default locale without resetting it."); 1195 } 1196 1197 fprintf(stdout, "\n--------------------------------------\n"); 1198 if (major.getErrors() == 0) { 1199 /* Call it twice to make sure that the defaults were reset. */ 1200 /* Call it before the OK message to verify proper cleanup. */ 1201 u_cleanup(); 1202 u_cleanup(); 1203 1204 fprintf(stdout, "OK: All tests passed without error.\n"); 1205 1206 if (major.getDataErrors() != 0) { 1207 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n"); 1208 } 1209 }else{ 1210 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors()); 1211 major.printErrors(); 1212 1213 1214 if (major.getDataErrors() != 0) { 1215 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n" 1216 "\tstock ICU data (i.e some have been added or removed), consider using\n" 1217 "\tthe '-w' option to turn these errors into warnings.\n"); 1218 } 1219 1220 /* Call afterwards to display errors. */ 1221 u_cleanup(); 1222 } 1223 1224 fprintf(stdout, "--------------------------------------\n"); 1225 1226 if (execCount <= 0) { 1227 fprintf(stdout, "***** Not all called tests actually exist! *****\n"); 1228 } 1229 endTime = uprv_getUTCtime(); 1230 diffTime = (int32_t)(endTime - startTime); 1231 printf("Elapsed Time: %02d:%02d:%02d.%03d\n", 1232 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), 1233 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), 1234 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), 1235 (int)(diffTime%U_MILLIS_PER_SECOND)); 1236 return major.getErrors(); 1237} 1238 1239const char* IntlTest::loadTestData(UErrorCode& err){ 1240 if( _testDataPath == NULL){ 1241 const char* directory=NULL; 1242 UResourceBundle* test =NULL; 1243 char* tdpath=NULL; 1244 const char* tdrelativepath; 1245 1246#if defined (U_TOPBUILDDIR) 1247 tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; 1248 directory = U_TOPBUILDDIR; 1249#else 1250 tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; 1251 directory = pathToDataDirectory(); 1252#endif 1253 1254 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100)); 1255 1256 1257 /* u_getDataDirectory shoul return \source\data ... set the 1258 * directory to ..\source\data\..\test\testdata\out\testdata 1259 */ 1260 strcpy(tdpath, directory); 1261 strcat(tdpath, tdrelativepath); 1262 strcat(tdpath,"testdata"); 1263 1264 test=ures_open(tdpath, "testtypes", &err); 1265 1266 if(U_FAILURE(err)){ 1267 err = U_FILE_ACCESS_ERROR; 1268 it_errln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); 1269 return ""; 1270 } 1271 ures_close(test); 1272 _testDataPath = tdpath; 1273 return _testDataPath; 1274 } 1275 return _testDataPath; 1276} 1277 1278const char* IntlTest::getTestDataPath(UErrorCode& err) { 1279 return loadTestData(err); 1280} 1281 1282/* Returns the path to icu/source/test/testdata/ */ 1283const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) { 1284 const char *srcDataDir = NULL; 1285#ifdef U_TOPSRCDIR 1286 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; 1287#else 1288 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; 1289 FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r"); 1290 if (f) { 1291 /* We're in icu/source/test/intltest/ */ 1292 fclose(f); 1293 } 1294 else { 1295 /* We're in icu/source/test/intltest/(Debug|Release) */ 1296 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; 1297 } 1298#endif 1299 return srcDataDir; 1300} 1301 1302const char* IntlTest::fgDataDir = NULL; 1303 1304/* returns the path to icu/source/data */ 1305const char * IntlTest::pathToDataDirectory() 1306{ 1307 1308 if(fgDataDir != NULL) { 1309 return fgDataDir; 1310 } 1311 1312 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst 1313 // to point to the top of the build hierarchy, which may or 1314 // may not be the same as the source directory, depending on 1315 // the configure options used. At any rate, 1316 // set the data path to the built data from this directory. 1317 // The value is complete with quotes, so it can be used 1318 // as-is as a string constant. 1319 */ 1320#if defined (U_TOPSRCDIR) 1321 { 1322 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1323 } 1324#else 1325 1326 /* On Windows, the file name obtained from __FILE__ includes a full path. 1327 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 1328 * Change to "wherever\icu\source\data" 1329 */ 1330 { 1331 static char p[sizeof(__FILE__) + 10]; 1332 char *pBackSlash; 1333 int i; 1334 1335 strcpy(p, __FILE__); 1336 /* We want to back over three '\' chars. */ 1337 /* Only Windows should end up here, so looking for '\' is safe. */ 1338 for (i=1; i<=3; i++) { 1339 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 1340 if (pBackSlash != NULL) { 1341 *pBackSlash = 0; /* Truncate the string at the '\' */ 1342 } 1343 } 1344 1345 if (pBackSlash != NULL) { 1346 /* We found and truncated three names from the path. 1347 * Now append "source\data" and set the environment 1348 */ 1349 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); 1350 fgDataDir = p; 1351 } 1352 else { 1353 /* __FILE__ on MSVC7 does not contain the directory */ 1354 FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 1355 if (file) { 1356 fclose(file); 1357 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1358 } 1359 else { 1360 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1361 } 1362 } 1363 } 1364#endif 1365 1366 return fgDataDir; 1367 1368} 1369 1370/* 1371 * This is a variant of cintltst/ccolltst.c:CharsToUChars(). 1372 * It converts a character string into a UnicodeString, with 1373 * unescaping \u sequences. 1374 */ 1375UnicodeString CharsToUnicodeString(const char* chars) 1376{ 1377 UnicodeString str(chars, ""); // Invariant conversion 1378 return str.unescape(); 1379} 1380 1381UnicodeString ctou(const char* chars) { 1382 return CharsToUnicodeString(chars); 1383} 1384 1385#define RAND_M (714025) 1386#define RAND_IA (1366) 1387#define RAND_IC (150889) 1388 1389static int32_t RAND_SEED; 1390 1391/** 1392 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use 1393 * with care: Does not return all possible values; returns one of 1394 * 714,025 values, uniformly spaced. However, the period is 1395 * effectively infinite. See: Numerical Recipes, section 7.1. 1396 * 1397 * @param seedp pointer to seed. Set *seedp to any negative value 1398 * to restart the sequence. 1399 */ 1400float IntlTest::random(int32_t* seedp) { 1401 static int32_t iy, ir[98]; 1402 static UBool first=TRUE; 1403 int32_t j; 1404 if (*seedp < 0 || first) { 1405 first = FALSE; 1406 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp); 1407 for (j=1;j<=97;++j) { 1408 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1409 ir[j]=(*seedp); 1410 } 1411 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1412 iy=(*seedp); 1413 } 1414 j=(int32_t)(1 + 97.0*iy/RAND_M); 1415 U_ASSERT(j>=1 && j<=97); 1416 iy=ir[j]; 1417 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1418 ir[j]=(*seedp); 1419 return (float) iy/RAND_M; 1420} 1421 1422/** 1423 * Convenience method using a global seed. 1424 */ 1425float IntlTest::random() { 1426 return random(&RAND_SEED); 1427} 1428 1429static inline UChar toHex(int32_t i) { 1430 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); 1431} 1432 1433static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) { 1434 for (int32_t i=0; i<s.length(); ++i) { 1435 UChar c = s[i]; 1436 if (c <= (UChar)0x7F) { 1437 result += c; 1438 } else { 1439 result += (UChar)0x5c; 1440 result += (UChar)0x75; 1441 result += toHex((c >> 12) & 0xF); 1442 result += toHex((c >> 8) & 0xF); 1443 result += toHex((c >> 4) & 0xF); 1444 result += toHex( c & 0xF); 1445 } 1446 } 1447 return result; 1448} 1449 1450#define VERBOSE_ASSERTIONS 1451 1452UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) { 1453 if (!condition) { 1454 errln("FAIL: assertTrue() failed: %s", message); 1455 } else if (!quiet) { 1456 logln("Ok: %s", message); 1457 } 1458 return condition; 1459} 1460 1461UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { 1462 if (condition) { 1463 errln("FAIL: assertFalse() failed: %s", message); 1464 } else if (!quiet) { 1465 logln("Ok: %s", message); 1466 } 1467 return !condition; 1468} 1469 1470UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) { 1471 if (U_FAILURE(ec)) { 1472 errln("FAIL: %s (%s)", message, u_errorName(ec)); 1473 return FALSE; 1474 } 1475 return TRUE; 1476} 1477 1478UBool IntlTest::assertEquals(const char* message, 1479 const UnicodeString& expected, 1480 const UnicodeString& actual) { 1481 if (expected != actual) { 1482 errln((UnicodeString)"FAIL: " + message + "; got " + 1483 prettify(actual) + 1484 "; expected " + prettify(expected)); 1485 return FALSE; 1486 } 1487#ifdef VERBOSE_ASSERTIONS 1488 else { 1489 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual)); 1490 } 1491#endif 1492 return TRUE; 1493} 1494 1495UBool IntlTest::assertEquals(const char* message, 1496 const char* expected, 1497 const char* actual) { 1498 if (uprv_strcmp(expected, actual) != 0) { 1499 errln((UnicodeString)"FAIL: " + message + "; got \"" + 1500 actual + 1501 "\"; expected \"" + expected + "\""); 1502 return FALSE; 1503 } 1504#ifdef VERBOSE_ASSERTIONS 1505 else { 1506 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\""); 1507 } 1508#endif 1509 return TRUE; 1510} 1511 1512#if !UCONFIG_NO_FORMATTING 1513UBool IntlTest::assertEquals(const char* message, 1514 const Formattable& expected, 1515 const Formattable& actual) { 1516 if (expected != actual) { 1517 errln((UnicodeString)"FAIL: " + message + "; got " + 1518 toString(actual) + 1519 "; expected " + toString(expected)); 1520 return FALSE; 1521 } 1522#ifdef VERBOSE_ASSERTIONS 1523 else { 1524 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1525 } 1526#endif 1527 return TRUE; 1528} 1529#endif 1530 1531static char ASSERT_BUF[256]; 1532 1533static const char* extractToAssertBuf(const UnicodeString& message) { 1534 UnicodeString buf; 1535 escape(message, buf); 1536 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0); 1537 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0; 1538 return ASSERT_BUF; 1539} 1540 1541UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) { 1542 return assertTrue(extractToAssertBuf(message), condition, quiet); 1543} 1544 1545UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) { 1546 return assertFalse(extractToAssertBuf(message), condition, quiet); 1547} 1548 1549UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) { 1550 return assertSuccess(extractToAssertBuf(message), ec); 1551} 1552 1553UBool IntlTest::assertEquals(const UnicodeString& message, 1554 const UnicodeString& expected, 1555 const UnicodeString& actual) { 1556 return assertEquals(extractToAssertBuf(message), expected, actual); 1557} 1558 1559UBool IntlTest::assertEquals(const UnicodeString& message, 1560 const char* expected, 1561 const char* actual) { 1562 return assertEquals(extractToAssertBuf(message), expected, actual); 1563} 1564//-------------------------------------------------------------------- 1565// Time bomb - allows temporary behavior that expires at a given 1566// release 1567//-------------------------------------------------------------------- 1568 1569UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) { 1570 UVersionInfo v; 1571 u_getVersion(v); 1572 return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0); 1573} 1574 1575#if !UCONFIG_NO_FORMATTING 1576UBool IntlTest::assertEquals(const UnicodeString& message, 1577 const Formattable& expected, 1578 const Formattable& actual) { 1579 return assertEquals(extractToAssertBuf(message), expected, actual); 1580} 1581#endif 1582 1583/* 1584 * Hey, Emacs, please set the following: 1585 * 1586 * Local Variables: 1587 * indent-tabs-mode: nil 1588 * End: 1589 * 1590 */ 1591