1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2013, 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_getRawUTCtime() 39#include "unicode/locid.h" 40#include "unicode/ctest.h" // for str_timeDelta 41#include "udbgutil.h" 42 43#ifdef XP_MAC_CONSOLE 44#include <console.h> 45#include "Files.h" 46#endif 47 48 49static char* _testDataPath=NULL; 50 51// Static list of errors found 52static UnicodeString errorList; 53static void *knownList = NULL; // known issues 54static UBool noKnownIssues = FALSE; // if TRUE, don't emit known issues 55 56//----------------------------------------------------------------------------- 57//convenience classes to ease porting code that uses the Java 58//string-concatenation operator (moved from findword test by rtg) 59 60// [LIU] Just to get things working 61UnicodeString 62UCharToUnicodeString(UChar c) 63{ return UnicodeString(c); } 64 65// [rtg] Just to get things working 66UnicodeString 67operator+(const UnicodeString& left, 68 long num) 69{ 70 char buffer[64]; // nos changed from 10 to 64 71 char danger = 'p'; // guard against overrunning the buffer (rtg) 72 73 sprintf(buffer, "%ld", num); 74 assert(danger == 'p'); 75 76 return left + buffer; 77} 78 79UnicodeString 80operator+(const UnicodeString& left, 81 unsigned long num) 82{ 83 char buffer[64]; // nos changed from 10 to 64 84 char danger = 'p'; // guard against overrunning the buffer (rtg) 85 86 sprintf(buffer, "%lu", num); 87 assert(danger == 'p'); 88 89 return left + buffer; 90} 91 92UnicodeString 93Int64ToUnicodeString(int64_t num) 94{ 95 char buffer[64]; // nos changed from 10 to 64 96 char danger = 'p'; // guard against overrunning the buffer (rtg) 97 98#if defined(_MSC_VER) 99 sprintf(buffer, "%I64d", num); 100#else 101 sprintf(buffer, "%lld", (long long)num); 102#endif 103 assert(danger == 'p'); 104 105 return buffer; 106} 107 108// [LIU] Just to get things working 109UnicodeString 110operator+(const UnicodeString& left, 111 double num) 112{ 113 char buffer[64]; // was 32, made it arbitrarily bigger (rtg) 114 char danger = 'p'; // guard against overrunning the buffer (rtg) 115 116 // IEEE floating point has 52 bits of mantissa, plus one assumed bit 117 // 53*log(2)/log(10) = 15.95 118 // so there is no need to show more than 16 digits. [alan] 119 120 sprintf(buffer, "%.17g", num); 121 assert(danger == 'p'); 122 123 return left + buffer; 124} 125 126#if 0 127UnicodeString 128operator+(const UnicodeString& left, 129 int64_t num) { 130 return left + Int64ToUnicodeString(num); 131} 132#endif 133 134#if !UCONFIG_NO_FORMATTING 135 136/** 137 * Return a string display for this, without surrounding braces. 138 */ 139UnicodeString _toString(const Formattable& f) { 140 UnicodeString s; 141 switch (f.getType()) { 142 case Formattable::kDate: 143 { 144 UErrorCode status = U_ZERO_ERROR; 145 SimpleDateFormat fmt(status); 146 if (U_SUCCESS(status)) { 147 FieldPosition pos; 148 fmt.format(f.getDate(), s, pos); 149 s.insert(0, "Date:"); 150 } else { 151 s = UnicodeString("Error creating date format]"); 152 } 153 } 154 break; 155 case Formattable::kDouble: 156 s = UnicodeString("double:") + f.getDouble(); 157 break; 158 case Formattable::kLong: 159 s = UnicodeString("long:") + f.getLong(); 160 break; 161 162 case Formattable::kInt64: 163 s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64()); 164 break; 165 166 case Formattable::kString: 167 f.getString(s); 168 s.insert(0, "String:"); 169 break; 170 case Formattable::kArray: 171 { 172 int32_t i, n; 173 const Formattable* array = f.getArray(n); 174 s.insert(0, UnicodeString("Array:")); 175 UnicodeString delim(", "); 176 for (i=0; i<n; ++i) { 177 if (i > 0) { 178 s.append(delim); 179 } 180 s = s + _toString(array[i]); 181 } 182 } 183 break; 184 case Formattable::kObject: { 185 const CurrencyAmount* c = dynamic_cast<const CurrencyAmount*>(f.getObject()); 186 if (c != NULL) { 187 s = _toString(c->getNumber()) + " " + UnicodeString(c->getISOCurrency()); 188 } else { 189 s = UnicodeString("Unknown UObject"); 190 } 191 break; 192 } 193 default: 194 s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType(); 195 break; 196 } 197 return s; 198} 199 200/** 201 * Originally coded this as operator+, but that makes the expression 202 * + char* ambiguous. - liu 203 */ 204UnicodeString toString(const Formattable& f) { 205 UnicodeString s((UChar)91/*[*/); 206 s.append(_toString(f)); 207 s.append((UChar)0x5d/*]*/); 208 return s; 209} 210 211#endif 212 213// useful when operator+ won't cooperate 214UnicodeString toString(int32_t n) { 215 return UnicodeString() + (long)n; 216} 217 218 219 220UnicodeString toString(UBool b) { 221 return b ? UnicodeString("TRUE"):UnicodeString("FALSE"); 222} 223 224// stephen - cleaned up 05/05/99 225UnicodeString operator+(const UnicodeString& left, char num) 226{ return left + (long)num; } 227UnicodeString operator+(const UnicodeString& left, short num) 228{ return left + (long)num; } 229UnicodeString operator+(const UnicodeString& left, int num) 230{ return left + (long)num; } 231UnicodeString operator+(const UnicodeString& left, unsigned char num) 232{ return left + (unsigned long)num; } 233UnicodeString operator+(const UnicodeString& left, unsigned short num) 234{ return left + (unsigned long)num; } 235UnicodeString operator+(const UnicodeString& left, unsigned int num) 236{ return left + (unsigned long)num; } 237UnicodeString operator+(const UnicodeString& left, float num) 238{ return left + (double)num; } 239 240//------------------ 241 242// Append a hex string to the target 243UnicodeString& 244IntlTest::appendHex(uint32_t number, 245 int32_t digits, 246 UnicodeString& target) 247{ 248 static const UChar digitString[] = { 249 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 250 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0 251 }; /* "0123456789ABCDEF" */ 252 253 if (digits < 0) { // auto-digits 254 digits = 2; 255 uint32_t max = 0xff; 256 while (number > max) { 257 digits += 2; 258 max = (max << 8) | 0xff; 259 } 260 } 261 switch (digits) 262 { 263 case 8: 264 target += digitString[(number >> 28) & 0xF]; 265 case 7: 266 target += digitString[(number >> 24) & 0xF]; 267 case 6: 268 target += digitString[(number >> 20) & 0xF]; 269 case 5: 270 target += digitString[(number >> 16) & 0xF]; 271 case 4: 272 target += digitString[(number >> 12) & 0xF]; 273 case 3: 274 target += digitString[(number >> 8) & 0xF]; 275 case 2: 276 target += digitString[(number >> 4) & 0xF]; 277 case 1: 278 target += digitString[(number >> 0) & 0xF]; 279 break; 280 default: 281 target += "**"; 282 } 283 return target; 284} 285 286UnicodeString 287IntlTest::toHex(uint32_t number, int32_t digits) { 288 UnicodeString result; 289 appendHex(number, digits, result); 290 return result; 291} 292 293static inline UBool isPrintable(UChar32 c) { 294 return c <= 0x7E && (c >= 0x20 || c == 9 || c == 0xA || c == 0xD); 295} 296 297// Replace nonprintable characters with unicode escapes 298UnicodeString& 299IntlTest::prettify(const UnicodeString &source, 300 UnicodeString &target) 301{ 302 int32_t i; 303 304 target.remove(); 305 target += "\""; 306 307 for (i = 0; i < source.length(); ) 308 { 309 UChar32 ch = source.char32At(i); 310 i += U16_LENGTH(ch); 311 312 if (!isPrintable(ch)) 313 { 314 if (ch <= 0xFFFF) { 315 target += "\\u"; 316 appendHex(ch, 4, target); 317 } else { 318 target += "\\U"; 319 appendHex(ch, 8, target); 320 } 321 } 322 else 323 { 324 target += ch; 325 } 326 } 327 328 target += "\""; 329 330 return target; 331} 332 333// Replace nonprintable characters with unicode escapes 334UnicodeString 335IntlTest::prettify(const UnicodeString &source, UBool parseBackslash) 336{ 337 int32_t i; 338 UnicodeString target; 339 target.remove(); 340 target += "\""; 341 342 for (i = 0; i < source.length();) 343 { 344 UChar32 ch = source.char32At(i); 345 i += U16_LENGTH(ch); 346 347 if (!isPrintable(ch)) 348 { 349 if (parseBackslash) { 350 // If we are preceded by an odd number of backslashes, 351 // then this character has already been backslash escaped. 352 // Delete a backslash. 353 int32_t backslashCount = 0; 354 for (int32_t j=target.length()-1; j>=0; --j) { 355 if (target.charAt(j) == (UChar)92) { 356 ++backslashCount; 357 } else { 358 break; 359 } 360 } 361 if ((backslashCount % 2) == 1) { 362 target.truncate(target.length() - 1); 363 } 364 } 365 if (ch <= 0xFFFF) { 366 target += "\\u"; 367 appendHex(ch, 4, target); 368 } else { 369 target += "\\U"; 370 appendHex(ch, 8, target); 371 } 372 } 373 else 374 { 375 target += ch; 376 } 377 } 378 379 target += "\""; 380 381 return target; 382} 383 384/* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already 385 * set, try to deduce the directory in which ICU was built, 386 * and set ICU_DATA to "icu/source/data" in that location. 387 * The intent is to allow the tests to have a good chance 388 * of running without requiring that the user manually set 389 * ICU_DATA. Common data isn't a problem, since it is 390 * picked up via a static (build time) reference, but the 391 * tests dynamically load some data. 392 */ 393void IntlTest::setICU_DATA() { 394 const char *original_ICU_DATA = getenv("ICU_DATA"); 395 396 if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) { 397 /* If the user set ICU_DATA, don't second-guess the person. */ 398 return; 399 } 400 401 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst 402 // to point to the top of the build hierarchy, which may or 403 // may not be the same as the source directory, depending on 404 // the configure options used. At any rate, 405 // set the data path to the built data from this directory. 406 // The value is complete with quotes, so it can be used 407 // as-is as a string constant. 408 409#if defined (U_TOPBUILDDIR) 410 { 411 static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 412 u_setDataDirectory(env_string); 413 return; 414 } 415 416#else 417 // Use #else so we don't get compiler warnings due to the return above. 418 419 /* On Windows, the file name obtained from __FILE__ includes a full path. 420 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 421 * Change to "wherever\icu\source\data" 422 */ 423 { 424 char p[sizeof(__FILE__) + 10]; 425 char *pBackSlash; 426 int i; 427 428 strcpy(p, __FILE__); 429 /* We want to back over three '\' chars. */ 430 /* Only Windows should end up here, so looking for '\' is safe. */ 431 for (i=1; i<=3; i++) { 432 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 433 if (pBackSlash != NULL) { 434 *pBackSlash = 0; /* Truncate the string at the '\' */ 435 } 436 } 437 438 if (pBackSlash != NULL) { 439 /* We found and truncated three names from the path. 440 * Now append "source\data" and set the environment 441 */ 442 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); 443 u_setDataDirectory(p); /* p is "ICU_DATA=wherever\icu\source\data" */ 444 return; 445 } 446 else { 447 /* __FILE__ on MSVC7 does not contain the directory */ 448 u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); 449 return; 450 } 451 } 452#endif 453 454 /* No location for the data dir was identifiable. 455 * Add other fallbacks for the test data location here if the need arises 456 */ 457} 458 459 460//-------------------------------------------------------------------------------------- 461 462static const int32_t indentLevel_offset = 3; 463static const char delim = '/'; 464 465IntlTest* IntlTest::gTest = NULL; 466 467static int32_t execCount = 0; 468 469void it_log( UnicodeString message ) 470{ 471 if (IntlTest::gTest) 472 IntlTest::gTest->log( message ); 473} 474 475void it_logln( UnicodeString message ) 476{ 477 if (IntlTest::gTest) 478 IntlTest::gTest->logln( message ); 479} 480 481void it_logln( void ) 482{ 483 if (IntlTest::gTest) 484 IntlTest::gTest->logln(); 485} 486 487void it_info( UnicodeString message ) 488{ 489 if (IntlTest::gTest) 490 IntlTest::gTest->info( message ); 491} 492 493void it_infoln( UnicodeString message ) 494{ 495 if (IntlTest::gTest) 496 IntlTest::gTest->infoln( message ); 497} 498 499void it_infoln( void ) 500{ 501 if (IntlTest::gTest) 502 IntlTest::gTest->infoln(); 503} 504 505void it_err() 506{ 507 if (IntlTest::gTest) 508 IntlTest::gTest->err(); 509} 510 511void it_err( UnicodeString message ) 512{ 513 if (IntlTest::gTest) 514 IntlTest::gTest->err( message ); 515} 516 517void it_errln( UnicodeString message ) 518{ 519 if (IntlTest::gTest) 520 IntlTest::gTest->errln( message ); 521} 522 523void it_dataerr( UnicodeString message ) 524{ 525 if (IntlTest::gTest) 526 IntlTest::gTest->dataerr( message ); 527} 528 529void it_dataerrln( UnicodeString message ) 530{ 531 if (IntlTest::gTest) 532 IntlTest::gTest->dataerrln( message ); 533} 534 535IntlTest::IntlTest() 536{ 537 caller = NULL; 538 testPath = NULL; 539 LL_linestart = TRUE; 540 errorCount = 0; 541 dataErrorCount = 0; 542 verbose = FALSE; 543 no_time = FALSE; 544 no_err_msg = FALSE; 545 warn_on_missing_data = FALSE; 546 quick = FALSE; 547 leaks = FALSE; 548 threadCount = 1; 549 testoutfp = stdout; 550 LL_indentlevel = indentLevel_offset; 551 numProps = 0; 552 strcpy(basePath, "/"); 553 currName[0]=0; 554} 555 556void IntlTest::setCaller( IntlTest* callingTest ) 557{ 558 caller = callingTest; 559 if (caller) { 560 warn_on_missing_data = caller->warn_on_missing_data; 561 verbose = caller->verbose; 562 no_err_msg = caller->no_err_msg; 563 quick = caller->quick; 564 testoutfp = caller->testoutfp; 565 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset; 566 numProps = caller->numProps; 567 for (int32_t i = 0; i < numProps; i++) { 568 proplines[i] = caller->proplines[i]; 569 } 570 } 571} 572 573UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par ) 574{ 575 execCount--; // correct a previously assumed test-exec, as this only calls a subtest 576 testToBeCalled.setCaller( this ); 577 strcpy(testToBeCalled.basePath, this->basePath ); 578 UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath ); 579 strcpy(testToBeCalled.basePath, this->basePath ); // reset it. 580 return result; 581} 582 583void IntlTest::setPath( char* pathVal ) 584{ 585 this->testPath = pathVal; 586} 587 588UBool IntlTest::setVerbose( UBool verboseVal ) 589{ 590 UBool rval = this->verbose; 591 this->verbose = verboseVal; 592 return rval; 593} 594 595UBool IntlTest::setNotime( UBool no_time ) 596{ 597 UBool rval = this->no_time; 598 this->no_time = no_time; 599 return rval; 600} 601 602UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal ) 603{ 604 UBool rval = this->warn_on_missing_data; 605 this->warn_on_missing_data = warn_on_missing_dataVal; 606 return rval; 607} 608 609UBool IntlTest::setNoErrMsg( UBool no_err_msgVal ) 610{ 611 UBool rval = this->no_err_msg; 612 this->no_err_msg = no_err_msgVal; 613 return rval; 614} 615 616UBool IntlTest::setQuick( UBool quickVal ) 617{ 618 UBool rval = this->quick; 619 this->quick = quickVal; 620 return rval; 621} 622 623UBool IntlTest::setLeaks( UBool leaksVal ) 624{ 625 UBool rval = this->leaks; 626 this->leaks = leaksVal; 627 return rval; 628} 629 630int32_t IntlTest::setThreadCount( int32_t count ) 631{ 632 int32_t rval = this->threadCount; 633 this->threadCount = count; 634 return rval; 635} 636 637int32_t IntlTest::getErrors( void ) 638{ 639 return errorCount; 640} 641 642int32_t IntlTest::getDataErrors( void ) 643{ 644 return dataErrorCount; 645} 646 647UBool IntlTest::runTest( char* name, char* par, char *baseName ) 648{ 649 UBool rval; 650 char* pos = NULL; 651 652 char* baseNameBuffer = NULL; 653 654 if(baseName == NULL) { 655 baseNameBuffer = (char*)malloc(1024); 656 baseName=baseNameBuffer; 657 strcpy(baseName, "/"); 658 } 659 660 if (name) 661 pos = strchr( name, delim ); // check if name contains path (by looking for '/') 662 if (pos) { 663 testPath = pos+1; // store subpath for calling subtest 664 *pos = 0; // split into two strings 665 }else{ 666 testPath = NULL; 667 } 668 669 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) { 670 rval = runTestLoop( NULL, par, baseName ); 671 672 }else if (strcmp( name, "LIST" ) == 0) { 673 this->usage(); 674 rval = TRUE; 675 676 }else{ 677 rval = runTestLoop( name, par, baseName ); 678 } 679 680 if (pos) 681 *pos = delim; // restore original value at pos 682 if(baseNameBuffer!=NULL) { 683 free(baseNameBuffer); 684 } 685 return rval; 686} 687 688// call individual tests, to be overriden to call implementations 689void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ ) 690{ 691 // to be overriden by a method like: 692 /* 693 switch (index) { 694 case 0: name = "First Test"; if (exec) FirstTest( par ); break; 695 case 1: name = "Second Test"; if (exec) SecondTest( par ); break; 696 default: name = ""; break; 697 } 698 */ 699 this->errln("*** runIndexedTest needs to be overriden! ***"); 700} 701 702 703UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName ) 704{ 705 int32_t index = 0; 706 const char* name; 707 UBool run_this_test; 708 int32_t lastErrorCount; 709 UBool rval = FALSE; 710 UBool lastTestFailed; 711 712 if(baseName == NULL) { 713 printf("ERROR: baseName can't be null.\n"); 714 return FALSE; 715 } else { 716 if ((char *)this->basePath != baseName) { 717 strcpy(this->basePath, baseName); 718 } 719 } 720 721 char * saveBaseLoc = baseName+strlen(baseName); 722 723 IntlTest* saveTest = gTest; 724 gTest = this; 725 do { 726 this->runIndexedTest( index, FALSE, name, par ); 727 if (strcmp(name,"skip") == 0) { 728 run_this_test = FALSE; 729 } else { 730 if (!name || (name[0] == 0)) 731 break; 732 if (!testname) { 733 run_this_test = TRUE; 734 }else{ 735 run_this_test = (UBool) (strcmp( name, testname ) == 0); 736 } 737 } 738 if (run_this_test) { 739 lastErrorCount = errorCount; 740 execCount++; 741 char msg[256]; 742 sprintf(msg, "%s {", name); 743 LL_message(msg, TRUE); 744 UDate timeStart = uprv_getRawUTCtime(); 745 strcpy(saveBaseLoc,name); 746 strcat(saveBaseLoc,"/"); 747 748 strcpy(currName, name); // set 749 this->runIndexedTest( index, TRUE, name, par ); 750 currName[0]=0; // reset 751 752 UDate timeStop = uprv_getRawUTCtime(); 753 rval = TRUE; // at least one test has been called 754 char secs[256]; 755 if(!no_time) { 756 sprintf(secs, "%f", (timeStop-timeStart)/1000.0); 757 } else { 758 secs[0]=0; 759 } 760 761 762 strcpy(saveBaseLoc,name); 763 764 765 ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL); 766 767 768 saveBaseLoc[0]=0; /* reset path */ 769 770 if (lastErrorCount == errorCount) { 771 sprintf( msg, " } OK: %s ", name ); 772 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); 773 lastTestFailed = FALSE; 774 }else{ 775 sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name); 776 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); 777 778 for(int i=0;i<LL_indentlevel;i++) { 779 errorList += " "; 780 } 781 errorList += name; 782 errorList += "\n"; 783 lastTestFailed = TRUE; 784 } 785 LL_indentlevel -= 3; 786 if (lastTestFailed) { 787 LL_message( "", TRUE); 788 } 789 LL_message( msg, TRUE); 790 if (lastTestFailed) { 791 LL_message( "", TRUE); 792 } 793 LL_indentlevel += 3; 794 } 795 index++; 796 }while(name); 797 798 *saveBaseLoc = 0; 799 800 gTest = saveTest; 801 return rval; 802} 803 804 805/** 806* Adds given string to the log if we are in verbose mode. 807*/ 808void IntlTest::log( const UnicodeString &message ) 809{ 810 if( verbose ) { 811 LL_message( message, FALSE ); 812 } 813} 814 815/** 816* Adds given string to the log if we are in verbose mode. Adds a new line to 817* the given message. 818*/ 819void IntlTest::logln( const UnicodeString &message ) 820{ 821 if( verbose ) { 822 LL_message( message, TRUE ); 823 } 824} 825 826void IntlTest::logln( void ) 827{ 828 if( verbose ) { 829 LL_message( "", TRUE ); 830 } 831} 832 833/** 834* Unconditionally adds given string to the log. 835*/ 836void IntlTest::info( const UnicodeString &message ) 837{ 838 LL_message( message, FALSE ); 839} 840 841/** 842* Unconditionally adds given string to the log. Adds a new line to 843* the given message. 844*/ 845void IntlTest::infoln( const UnicodeString &message ) 846{ 847 LL_message( message, TRUE ); 848} 849 850void IntlTest::infoln( void ) 851{ 852 LL_message( "", TRUE ); 853} 854 855int32_t IntlTest::IncErrorCount( void ) 856{ 857 errorCount++; 858 if (caller) caller->IncErrorCount(); 859 return errorCount; 860} 861 862int32_t IntlTest::IncDataErrorCount( void ) 863{ 864 dataErrorCount++; 865 if (caller) caller->IncDataErrorCount(); 866 return dataErrorCount; 867} 868 869void IntlTest::err() 870{ 871 IncErrorCount(); 872} 873 874void IntlTest::err( const UnicodeString &message ) 875{ 876 IncErrorCount(); 877 if (!no_err_msg) LL_message( message, FALSE ); 878} 879 880void IntlTest::errln( const UnicodeString &message ) 881{ 882 IncErrorCount(); 883 if (!no_err_msg) LL_message( message, TRUE ); 884} 885 886void IntlTest::dataerr( const UnicodeString &message ) 887{ 888 IncDataErrorCount(); 889 890 if (!warn_on_missing_data) { 891 IncErrorCount(); 892 } 893 894 if (!no_err_msg) LL_message( message, FALSE ); 895} 896 897void IntlTest::dataerrln( const UnicodeString &message ) 898{ 899 int32_t errCount = IncDataErrorCount(); 900 UnicodeString msg; 901 if (!warn_on_missing_data) { 902 IncErrorCount(); 903 msg = message; 904 } else { 905 msg = UnicodeString("[DATA] " + message); 906 } 907 908 if (!no_err_msg) { 909 if ( errCount == 1) { 910 LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time 911 } else { 912 LL_message( msg , TRUE ); 913 } 914 } 915} 916 917void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) { 918 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { 919 dataerrln(message); 920 } else { 921 errln(message); 922 } 923} 924 925/* convenience functions that include sprintf formatting */ 926void IntlTest::log(const char *fmt, ...) 927{ 928 char buffer[4000]; 929 va_list ap; 930 931 va_start(ap, fmt); 932 /* sprintf it just to make sure that the information is valid */ 933 vsprintf(buffer, fmt, ap); 934 va_end(ap); 935 if( verbose ) { 936 log(UnicodeString(buffer, "")); 937 } 938} 939 940void IntlTest::logln(const char *fmt, ...) 941{ 942 char buffer[4000]; 943 va_list ap; 944 945 va_start(ap, fmt); 946 /* sprintf it just to make sure that the information is valid */ 947 vsprintf(buffer, fmt, ap); 948 va_end(ap); 949 if( verbose ) { 950 logln(UnicodeString(buffer, "")); 951 } 952} 953 954UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...) 955{ 956 char buffer[4000]; 957 va_list ap; 958 959 va_start(ap, fmt); 960 /* sprintf it just to make sure that the information is valid */ 961 vsprintf(buffer, fmt, ap); 962 va_end(ap); 963 return logKnownIssue(ticket, UnicodeString(buffer, "")); 964} 965 966UBool IntlTest::logKnownIssue(const char *ticket) { 967 return logKnownIssue(ticket, UnicodeString()); 968} 969 970UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) { 971 if(noKnownIssues) return FALSE; 972 973 char fullpath[2048]; 974 strcpy(fullpath, basePath); 975 strcat(fullpath, currName); 976 UnicodeString msg2 =msg; 977 UBool firstForTicket, firstForWhere; 978 knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere); 979 980 if(firstForTicket || firstForWhere) { 981 infoln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg); 982 } else { 983 logln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg); 984 } 985 986 return TRUE; 987} 988 989/* convenience functions that include sprintf formatting */ 990void IntlTest::info(const char *fmt, ...) 991{ 992 char buffer[4000]; 993 va_list ap; 994 995 va_start(ap, fmt); 996 /* sprintf it just to make sure that the information is valid */ 997 vsprintf(buffer, fmt, ap); 998 va_end(ap); 999 info(UnicodeString(buffer, "")); 1000} 1001 1002void IntlTest::infoln(const char *fmt, ...) 1003{ 1004 char buffer[4000]; 1005 va_list ap; 1006 1007 va_start(ap, fmt); 1008 /* sprintf it just to make sure that the information is valid */ 1009 vsprintf(buffer, fmt, ap); 1010 va_end(ap); 1011 infoln(UnicodeString(buffer, "")); 1012} 1013 1014void IntlTest::err(const char *fmt, ...) 1015{ 1016 char buffer[4000]; 1017 va_list ap; 1018 1019 va_start(ap, fmt); 1020 vsprintf(buffer, fmt, ap); 1021 va_end(ap); 1022 err(UnicodeString(buffer, "")); 1023} 1024 1025void IntlTest::errln(const char *fmt, ...) 1026{ 1027 char buffer[4000]; 1028 va_list ap; 1029 1030 va_start(ap, fmt); 1031 vsprintf(buffer, fmt, ap); 1032 va_end(ap); 1033 errln(UnicodeString(buffer, "")); 1034} 1035 1036void IntlTest::dataerrln(const char *fmt, ...) 1037{ 1038 char buffer[4000]; 1039 va_list ap; 1040 1041 va_start(ap, fmt); 1042 vsprintf(buffer, fmt, ap); 1043 va_end(ap); 1044 dataerrln(UnicodeString(buffer, "")); 1045} 1046 1047void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...) 1048{ 1049 char buffer[4000]; 1050 va_list ap; 1051 1052 va_start(ap, fmt); 1053 vsprintf(buffer, fmt, ap); 1054 va_end(ap); 1055 1056 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { 1057 dataerrln(UnicodeString(buffer, "")); 1058 } else { 1059 errln(UnicodeString(buffer, "")); 1060 } 1061} 1062 1063void IntlTest::printErrors() 1064{ 1065 IntlTest::LL_message(errorList, TRUE); 1066} 1067 1068UBool IntlTest::printKnownIssues() 1069{ 1070 if(knownList != NULL) { 1071 udbg_knownIssue_print(knownList); 1072 udbg_knownIssue_close(knownList); 1073 return TRUE; 1074 } else { 1075 return FALSE; 1076 } 1077} 1078 1079void IntlTest::LL_message( UnicodeString message, UBool newline ) 1080{ 1081 // string that starts with a LineFeed character and continues 1082 // with spaces according to the current indentation 1083 static const UChar indentUChars[] = { 1084 '\n', 1085 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1086 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1087 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1088 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1089 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1090 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1091 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1092 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1093 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1094 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 1095 }; 1096 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel); 1097 1098 char buffer[10000]; 1099 int32_t length; 1100 1101 // stream out the indentation string first if necessary 1102 length = indent.extract(1, indent.length(), buffer, sizeof(buffer)); 1103 if (length > 0) { 1104 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1105 } 1106 1107 // replace each LineFeed by the indentation string 1108 message.findAndReplace(UnicodeString((UChar)'\n'), indent); 1109 1110 // stream out the message 1111 length = message.extract(0, message.length(), buffer, sizeof(buffer)); 1112 if (length > 0) { 1113 length = length > 10000 ? 10000 : length; 1114 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1115 } 1116 1117 if (newline) { 1118 char newLine = '\n'; 1119 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp); 1120 } 1121 1122 // A newline usually flushes the buffer, but 1123 // flush the message just in case of a core dump. 1124 fflush((FILE *)testoutfp); 1125} 1126 1127/** 1128* Print a usage message for this test class. 1129*/ 1130void IntlTest::usage( void ) 1131{ 1132 UBool save_verbose = setVerbose( TRUE ); 1133 logln("Test names:"); 1134 logln("-----------"); 1135 1136 int32_t index = 0; 1137 const char* name = NULL; 1138 do{ 1139 this->runIndexedTest( index, FALSE, name ); 1140 if (!name) break; 1141 logln(name); 1142 index++; 1143 }while (name && (name[0] != 0)); 1144 setVerbose( save_verbose ); 1145} 1146 1147 1148// memory leak reporting software will be able to take advantage of the testsuite 1149// being run a second time local to a specific method in order to report only actual leaks 1150UBool 1151IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks 1152{ 1153 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter 1154 strLeak->append(" for verifying purify filter"); 1155 return this->runTest( name, par ); 1156} 1157 1158 1159#if UCONFIG_NO_LEGACY_CONVERSION 1160# define TRY_CNV_1 "iso-8859-1" 1161# define TRY_CNV_2 "ibm-1208" 1162#else 1163# define TRY_CNV_1 "iso-8859-7" 1164# define TRY_CNV_2 "sjis" 1165#endif 1166 1167int 1168main(int argc, char* argv[]) 1169{ 1170 UBool syntax = FALSE; 1171 UBool all = FALSE; 1172 UBool verbose = FALSE; 1173 UBool no_err_msg = FALSE; 1174 UBool no_time = FALSE; 1175 UBool quick = TRUE; 1176 UBool name = FALSE; 1177 UBool leaks = FALSE; 1178 UBool utf8 = FALSE; 1179 const char *summary_file = NULL; 1180 UBool warnOnMissingData = FALSE; 1181 UBool defaultDataFound = FALSE; 1182 int32_t threadCount = 1; 1183 UErrorCode errorCode = U_ZERO_ERROR; 1184 UConverter *cnv = NULL; 1185 const char *warnOrErr = "Failure"; 1186 UDate startTime, endTime; 1187 int32_t diffTime; 1188 const char *props[IntlTest::kMaxProps]; 1189 int32_t nProps = 0; 1190 1191 U_MAIN_INIT_ARGS(argc, argv); 1192 1193 startTime = uprv_getRawUTCtime(); 1194 1195 for (int i = 1; i < argc; ++i) { 1196 if (argv[i][0] == '-') { 1197 const char* str = argv[i] + 1; 1198 if (strcmp("verbose", str) == 0 || 1199 strcmp("v", str) == 0) 1200 verbose = TRUE; 1201 else if (strcmp("noerrormsg", str) == 0 || 1202 strcmp("n", str) == 0) 1203 no_err_msg = TRUE; 1204 else if (strcmp("exhaustive", str) == 0 || 1205 strcmp("e", str) == 0) 1206 quick = FALSE; 1207 else if (strcmp("all", str) == 0 || 1208 strcmp("a", str) == 0) 1209 all = TRUE; 1210 else if (strcmp("utf-8", str) == 0 || 1211 strcmp("u", str) == 0) 1212 utf8 = TRUE; 1213 else if (strcmp("noknownissues", str) == 0 || 1214 strcmp("K", str) == 0) 1215 noKnownIssues = TRUE; 1216 else if (strcmp("leaks", str) == 0 || 1217 strcmp("l", str) == 0) 1218 leaks = TRUE; 1219 else if (strcmp("notime", str) == 0 || 1220 strcmp("T", str) == 0) 1221 no_time = TRUE; 1222 else if (strncmp("E", str, 1) == 0) 1223 summary_file = str+1; 1224 else if (strcmp("x", str)==0) { 1225 if(++i>=argc) { 1226 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n"); 1227 syntax = TRUE; 1228 } 1229 if(ctest_xml_setFileName(argv[i])) { /* set the name */ 1230 return 1; /* error */ 1231 } 1232 } else if (strcmp("w", str) == 0) { 1233 warnOnMissingData = TRUE; 1234 warnOrErr = "WARNING"; 1235 } 1236 else if (strncmp("threads:", str, 8) == 0) { 1237 threadCount = atoi(str + 8); 1238 } 1239 else if (strncmp("prop:", str, 5) == 0) { 1240 if (nProps < IntlTest::kMaxProps) { 1241 props[nProps] = str + 5; 1242 } 1243 nProps++; 1244 } 1245 else { 1246 syntax = TRUE; 1247 } 1248 }else{ 1249 name = TRUE; 1250 } 1251 } 1252 1253 if (!all && !name) { 1254 all = TRUE; 1255 } else if (all && name) { 1256 syntax = TRUE; 1257 } 1258 1259 if (syntax) { 1260 fprintf(stdout, 1261 "### Syntax:\n" 1262 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" 1263 "### \n" 1264 "### Options are: verbose (v), all (a), noerrormsg (n), \n" 1265 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n" 1266 "### notime (T), \n" 1267 "### threads:<threadCount> (Mulithreading must first be \n" 1268 "### enabled otherwise this will be ignored. \n" 1269 "### The default thread count is 1.),\n" 1270 "### (Specify either -all (shortcut -a) or a test name). \n" 1271 "### -all will run all of the tests.\n" 1272 "### \n" 1273 "### To get a list of the test names type: intltest LIST \n" 1274 "### To run just the utility tests type: intltest utility \n" 1275 "### \n" 1276 "### Test names can be nested using slashes (\"testA/subtest1\") \n" 1277 "### For example to list the utility tests type: intltest utility/LIST \n" 1278 "### To run just the Locale test type: intltest utility/LocaleTest \n" 1279 "### \n" 1280 "### A parameter can be specified for a test by appending '@' and the value \n" 1281 "### to the testname. \n\n"); 1282 return 1; 1283 } 1284 1285 if (nProps > IntlTest::kMaxProps) { 1286 fprintf(stdout, "### Too many properties. Exiting.\n"); 1287 } 1288 1289 MajorTestLevel major; 1290 major.setVerbose( verbose ); 1291 major.setNoErrMsg( no_err_msg ); 1292 major.setQuick( quick ); 1293 major.setLeaks( leaks ); 1294 major.setThreadCount( threadCount ); 1295 major.setWarnOnMissingData( warnOnMissingData ); 1296 major.setNotime (no_time); 1297 for (int32_t i = 0; i < nProps; i++) { 1298 major.setProperty(props[i]); 1299 } 1300 1301 1302 fprintf(stdout, "-----------------------------------------------\n"); 1303 fprintf(stdout, " IntlTest (C++) Test Suite for \n"); 1304 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); 1305 1306 1307 { 1308 const char *charsetFamily = "Unknown"; 1309 int32_t voidSize = (int32_t)sizeof(void*); 1310 int32_t bits = voidSize * 8; 1311 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) { 1312 charsetFamily="ASCII"; 1313 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) { 1314 charsetFamily="EBCDIC"; 1315 } 1316 fprintf(stdout, 1317 " Bits: %d, Byte order: %s, Chars: %s\n", 1318 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian", 1319 charsetFamily); 1320 } 1321 fprintf(stdout, "-----------------------------------------------\n"); 1322 fprintf(stdout, " Options: \n"); 1323 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); 1324 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); 1325 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); 1326 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); 1327 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); 1328 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off")); 1329 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off")); 1330 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off")); 1331 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); 1332#if (ICU_USE_THREADS==0) 1333 fprintf(stdout, " Threads : Disabled\n"); 1334#else 1335 fprintf(stdout, " Threads : %d\n", threadCount); 1336#endif 1337 for (int32_t i = 0; i < nProps; i++) { 1338 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]); 1339 } 1340 fprintf(stdout, "-----------------------------------------------\n"); 1341 1342 if(utf8) { 1343 ucnv_setDefaultName("utf-8"); 1344 } 1345 /* Check whether ICU will initialize without forcing the build data directory into 1346 * the ICU_DATA path. Success here means either the data dll contains data, or that 1347 * this test program was run with ICU_DATA set externally. Failure of this check 1348 * is normal when ICU data is not packaged into a shared library. 1349 * 1350 * Whether or not this test succeeds, we want to cleanup and reinitialize 1351 * with a data path so that data loading from individual files can be tested. 1352 */ 1353 u_init(&errorCode); 1354 if (U_FAILURE(errorCode)) { 1355 fprintf(stderr, 1356 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n"); 1357 defaultDataFound = FALSE; 1358 } 1359 else { 1360 defaultDataFound = TRUE; 1361 } 1362 u_cleanup(); 1363 if(utf8) { 1364 ucnv_setDefaultName("utf-8"); 1365 } 1366 errorCode = U_ZERO_ERROR; 1367 1368 /* Initialize ICU */ 1369 if (!defaultDataFound) { 1370 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. 1371 } 1372 u_init(&errorCode); 1373 if (U_FAILURE(errorCode)) { 1374 fprintf(stderr, 1375 "#### ERROR! %s: u_init() failed with status = \"%s\".\n" 1376 "*** Check the ICU_DATA environment variable and \n" 1377 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); 1378 if(warnOnMissingData == 0) { 1379 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1380 u_cleanup(); 1381 return 1; 1382 } 1383 } 1384 1385 // initial check for the default converter 1386 errorCode = U_ZERO_ERROR; 1387 cnv = ucnv_open(0, &errorCode); 1388 if(cnv != 0) { 1389 // ok 1390 ucnv_close(cnv); 1391 } else { 1392 fprintf(stdout, 1393 "*** %s! The default converter [%s] cannot be opened.\n" 1394 "*** Check the ICU_DATA environment variable and\n" 1395 "*** check that the data files are present.\n", 1396 warnOrErr, ucnv_getDefaultName()); 1397 if(!warnOnMissingData) { 1398 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1399 return 1; 1400 } 1401 } 1402 1403 // try more data 1404 cnv = ucnv_open(TRY_CNV_2, &errorCode); 1405 if(cnv != 0) { 1406 // ok 1407 ucnv_close(cnv); 1408 } else { 1409 fprintf(stdout, 1410 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" 1411 "*** Check the ICU_DATA environment variable and \n" 1412 "*** check that the data files are present.\n", warnOrErr); 1413 if(!warnOnMissingData) { 1414 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1415 return 1; 1416 } 1417 } 1418 1419 UResourceBundle *rb = ures_open(0, "en", &errorCode); 1420 ures_close(rb); 1421 if(U_FAILURE(errorCode)) { 1422 fprintf(stdout, 1423 "*** %s! The \"en\" locale resource bundle cannot be opened.\n" 1424 "*** Check the ICU_DATA environment variable and \n" 1425 "*** check that the data files are present.\n", warnOrErr); 1426 if(!warnOnMissingData) { 1427 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1428 return 1; 1429 } 1430 } 1431 1432 Locale originalLocale; // Save the default locale for comparison later on. 1433 1434 if(ctest_xml_init("intltest")) 1435 return 1; 1436 1437 1438 /* TODO: Add option to call u_cleanup and rerun tests. */ 1439 if (all) { 1440 major.runTest(); 1441 if (leaks) { 1442 major.run_phase2( NULL, NULL ); 1443 } 1444 }else{ 1445 for (int i = 1; i < argc; ++i) { 1446 if (argv[i][0] != '-') { 1447 char* name = argv[i]; 1448 fprintf(stdout, "\n=== Handling test: %s: ===\n", name); 1449 1450 char baseName[1024]; 1451 sprintf(baseName, "/%s/", name); 1452 1453 char* parameter = strchr( name, '@' ); 1454 if (parameter) { 1455 *parameter = 0; 1456 parameter += 1; 1457 } 1458 execCount = 0; 1459 UBool res = major.runTest( name, parameter, baseName ); 1460 if (leaks && res) { 1461 major.run_phase2( name, parameter ); 1462 } 1463 if (!res || (execCount <= 0)) { 1464 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name); 1465 } 1466 } else if(!strcmp(argv[i],"-x")) { 1467 i++; 1468 } 1469 } 1470 } 1471 1472 1473#if !UCONFIG_NO_FORMATTING 1474 CalendarTimeZoneTest::cleanup(); 1475#endif 1476 1477 free(_testDataPath); 1478 _testDataPath = 0; 1479 1480 Locale lastDefaultLocale; 1481 if (originalLocale != lastDefaultLocale) { 1482 major.errln("FAILURE: A test changed the default locale without resetting it."); 1483 } 1484 1485 fprintf(stdout, "\n--------------------------------------\n"); 1486 if( major.printKnownIssues() ) { 1487 fprintf(stdout, " To run suppressed tests, use the -K option. \n"); 1488 } 1489 if (major.getErrors() == 0) { 1490 /* Call it twice to make sure that the defaults were reset. */ 1491 /* Call it before the OK message to verify proper cleanup. */ 1492 u_cleanup(); 1493 u_cleanup(); 1494 1495 fprintf(stdout, "OK: All tests passed without error.\n"); 1496 1497 if (major.getDataErrors() != 0) { 1498 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n"); 1499 } 1500 }else{ 1501 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors()); 1502 major.printErrors(); 1503 1504 if(summary_file != NULL) { 1505 FILE *summf = fopen(summary_file, "w"); 1506 if( summf != NULL) { 1507 char buf[10000]; 1508 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf)); 1509 fwrite(buf, sizeof(*buf), length, (FILE*)summf); 1510 fclose(summf); 1511 } 1512 } 1513 1514 1515 if (major.getDataErrors() != 0) { 1516 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n" 1517 "\tstock ICU data (i.e some have been added or removed), consider using\n" 1518 "\tthe '-w' option to turn these errors into warnings.\n"); 1519 } 1520 1521 /* Call afterwards to display errors. */ 1522 u_cleanup(); 1523 } 1524 1525 fprintf(stdout, "--------------------------------------\n"); 1526 1527 if (execCount <= 0) { 1528 fprintf(stdout, "***** Not all called tests actually exist! *****\n"); 1529 } 1530 if(!no_time) { 1531 endTime = uprv_getRawUTCtime(); 1532 diffTime = (int32_t)(endTime - startTime); 1533 printf("Elapsed Time: %02d:%02d:%02d.%03d\n", 1534 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), 1535 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), 1536 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), 1537 (int)(diffTime%U_MILLIS_PER_SECOND)); 1538 } 1539 1540 if(ctest_xml_fini()) 1541 return 1; 1542 1543 return major.getErrors(); 1544} 1545 1546const char* IntlTest::loadTestData(UErrorCode& err){ 1547 if( _testDataPath == NULL){ 1548 const char* directory=NULL; 1549 UResourceBundle* test =NULL; 1550 char* tdpath=NULL; 1551 const char* tdrelativepath; 1552 1553#if defined (U_TOPBUILDDIR) 1554 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1555 directory = U_TOPBUILDDIR; 1556#else 1557 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1558 directory = pathToDataDirectory(); 1559#endif 1560 1561 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100)); 1562 1563 1564 /* u_getDataDirectory shoul return \source\data ... set the 1565 * directory to ..\source\data\..\test\testdata\out\testdata 1566 */ 1567 strcpy(tdpath, directory); 1568 strcat(tdpath, tdrelativepath); 1569 strcat(tdpath,"testdata"); 1570 1571 test=ures_open(tdpath, "testtypes", &err); 1572 1573 if(U_FAILURE(err)){ 1574 err = U_FILE_ACCESS_ERROR; 1575 it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); 1576 return ""; 1577 } 1578 ures_close(test); 1579 _testDataPath = tdpath; 1580 return _testDataPath; 1581 } 1582 return _testDataPath; 1583} 1584 1585const char* IntlTest::getTestDataPath(UErrorCode& err) { 1586 return loadTestData(err); 1587} 1588 1589/* Returns the path to icu/source/test/testdata/ */ 1590const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) { 1591 const char *srcDataDir = NULL; 1592#ifdef U_TOPSRCDIR 1593 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1594#else 1595 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1596 FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r"); 1597 if (f) { 1598 /* We're in icu/source/test/intltest/ */ 1599 fclose(f); 1600 } 1601 else { 1602 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */ 1603 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata"U_FILE_SEP_STRING; 1604 } 1605#endif 1606 return srcDataDir; 1607} 1608 1609const char* IntlTest::fgDataDir = NULL; 1610 1611/* returns the path to icu/source/data */ 1612const char * IntlTest::pathToDataDirectory() 1613{ 1614 1615 if(fgDataDir != NULL) { 1616 return fgDataDir; 1617 } 1618 1619 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst 1620 // to point to the top of the build hierarchy, which may or 1621 // may not be the same as the source directory, depending on 1622 // the configure options used. At any rate, 1623 // set the data path to the built data from this directory. 1624 // The value is complete with quotes, so it can be used 1625 // as-is as a string constant. 1626 */ 1627#if defined (U_TOPSRCDIR) 1628 { 1629 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1630 } 1631#else 1632 1633 /* On Windows, the file name obtained from __FILE__ includes a full path. 1634 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 1635 * Change to "wherever\icu\source\data" 1636 */ 1637 { 1638 static char p[sizeof(__FILE__) + 10]; 1639 char *pBackSlash; 1640 int i; 1641 1642 strcpy(p, __FILE__); 1643 /* We want to back over three '\' chars. */ 1644 /* Only Windows should end up here, so looking for '\' is safe. */ 1645 for (i=1; i<=3; i++) { 1646 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 1647 if (pBackSlash != NULL) { 1648 *pBackSlash = 0; /* Truncate the string at the '\' */ 1649 } 1650 } 1651 1652 if (pBackSlash != NULL) { 1653 /* We found and truncated three names from the path. 1654 * Now append "source\data" and set the environment 1655 */ 1656 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); 1657 fgDataDir = p; 1658 } 1659 else { 1660 /* __FILE__ on MSVC7 does not contain the directory */ 1661 FILE *file = fopen(".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 1662 if (file) { 1663 fclose(file); 1664 fgDataDir = ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1665 } 1666 else { 1667 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1668 } 1669 } 1670 } 1671#endif 1672 1673 return fgDataDir; 1674 1675} 1676 1677/* 1678 * This is a variant of cintltst/ccolltst.c:CharsToUChars(). 1679 * It converts an invariant-character string into a UnicodeString, with 1680 * unescaping \u sequences. 1681 */ 1682UnicodeString CharsToUnicodeString(const char* chars){ 1683 return UnicodeString(chars, -1, US_INV).unescape(); 1684} 1685 1686UnicodeString ctou(const char* chars) { 1687 return CharsToUnicodeString(chars); 1688} 1689 1690#define RAND_M (714025) 1691#define RAND_IA (1366) 1692#define RAND_IC (150889) 1693 1694static int32_t RAND_SEED; 1695 1696/** 1697 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use 1698 * with care: Does not return all possible values; returns one of 1699 * 714,025 values, uniformly spaced. However, the period is 1700 * effectively infinite. See: Numerical Recipes, section 7.1. 1701 * 1702 * @param seedp pointer to seed. Set *seedp to any negative value 1703 * to restart the sequence. 1704 */ 1705float IntlTest::random(int32_t* seedp) { 1706 static int32_t iy, ir[98]; 1707 static UBool first=TRUE; 1708 int32_t j; 1709 if (*seedp < 0 || first) { 1710 first = FALSE; 1711 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp); 1712 for (j=1;j<=97;++j) { 1713 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1714 ir[j]=(*seedp); 1715 } 1716 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1717 iy=(*seedp); 1718 } 1719 j=(int32_t)(1 + 97.0*iy/RAND_M); 1720 U_ASSERT(j>=1 && j<=97); 1721 iy=ir[j]; 1722 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1723 ir[j]=(*seedp); 1724 return (float) iy/RAND_M; 1725} 1726 1727/** 1728 * Convenience method using a global seed. 1729 */ 1730float IntlTest::random() { 1731 return random(&RAND_SEED); 1732} 1733 1734static inline UChar toHex(int32_t i) { 1735 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); 1736} 1737 1738static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) { 1739 for (int32_t i=0; i<s.length(); ++i) { 1740 UChar c = s[i]; 1741 if (c <= (UChar)0x7F) { 1742 result += c; 1743 } else { 1744 result += (UChar)0x5c; 1745 result += (UChar)0x75; 1746 result += toHex((c >> 12) & 0xF); 1747 result += toHex((c >> 8) & 0xF); 1748 result += toHex((c >> 4) & 0xF); 1749 result += toHex( c & 0xF); 1750 } 1751 } 1752 return result; 1753} 1754 1755#define VERBOSE_ASSERTIONS 1756 1757UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) { 1758 if (file != NULL) { 1759 if (!condition) { 1760 if (possibleDataError) { 1761 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1762 } else { 1763 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1764 } 1765 } else if (!quiet) { 1766 logln("%s:%d: Ok: %s", file, line, message); 1767 } 1768 } else { 1769 if (!condition) { 1770 if (possibleDataError) { 1771 dataerrln("FAIL: assertTrue() failed: %s", message); 1772 } else { 1773 errln("FAIL: assertTrue() failed: %s", message); 1774 } 1775 } else if (!quiet) { 1776 logln("Ok: %s", message); 1777 } 1778 1779 } 1780 return condition; 1781} 1782 1783UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { 1784 if (condition) { 1785 errln("FAIL: assertFalse() failed: %s", message); 1786 } else if (!quiet) { 1787 logln("Ok: %s", message); 1788 } 1789 return !condition; 1790} 1791 1792UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) { 1793 if( file==NULL ) { 1794 file = ""; // prevent failure if no file given 1795 } 1796 if (U_FAILURE(ec)) { 1797 if (possibleDataError) { 1798 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1799 } else { 1800 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1801 } 1802 return FALSE; 1803 } else { 1804 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec)); 1805 } 1806 return TRUE; 1807} 1808 1809UBool IntlTest::assertEquals(const char* message, 1810 const UnicodeString& expected, 1811 const UnicodeString& actual, 1812 UBool possibleDataError) { 1813 if (expected != actual) { 1814 if (possibleDataError) { 1815 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1816 prettify(actual) + 1817 "; expected " + prettify(expected)); 1818 } else { 1819 errln((UnicodeString)"FAIL: " + message + "; got " + 1820 prettify(actual) + 1821 "; expected " + prettify(expected)); 1822 } 1823 return FALSE; 1824 } 1825#ifdef VERBOSE_ASSERTIONS 1826 else { 1827 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual)); 1828 } 1829#endif 1830 return TRUE; 1831} 1832 1833UBool IntlTest::assertEquals(const char* message, 1834 const char* expected, 1835 const char* actual) { 1836 if (uprv_strcmp(expected, actual) != 0) { 1837 errln((UnicodeString)"FAIL: " + message + "; got \"" + 1838 actual + 1839 "\"; expected \"" + expected + "\""); 1840 return FALSE; 1841 } 1842#ifdef VERBOSE_ASSERTIONS 1843 else { 1844 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\""); 1845 } 1846#endif 1847 return TRUE; 1848} 1849 1850UBool IntlTest::assertEquals(const char* message, 1851 int32_t expected, 1852 int32_t actual) { 1853 if (expected != actual) { 1854 errln((UnicodeString)"FAIL: " + message + "; got " + 1855 actual + "=0x" + toHex(actual) + 1856 "; expected " + expected + "=0x" + toHex(expected)); 1857 return FALSE; 1858 } 1859#ifdef VERBOSE_ASSERTIONS 1860 else { 1861 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual)); 1862 } 1863#endif 1864 return TRUE; 1865} 1866 1867UBool IntlTest::assertEquals(const char* message, 1868 int64_t expected, 1869 int64_t actual) { 1870 if (expected != actual) { 1871 errln((UnicodeString)"FAIL: " + message + "; got int64 " + 1872 Int64ToUnicodeString(actual) + 1873 "; expected " + Int64ToUnicodeString(expected) ); 1874 return FALSE; 1875 } 1876#ifdef VERBOSE_ASSERTIONS 1877 else { 1878 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual)); 1879 } 1880#endif 1881 return TRUE; 1882} 1883 1884UBool IntlTest::assertEquals(const char* message, 1885 UBool expected, 1886 UBool actual) { 1887 if (expected != actual) { 1888 errln((UnicodeString)"FAIL: " + message + "; got " + 1889 toString(actual) + 1890 "; expected " + toString(expected)); 1891 return FALSE; 1892 } 1893#ifdef VERBOSE_ASSERTIONS 1894 else { 1895 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1896 } 1897#endif 1898 return TRUE; 1899} 1900 1901#if !UCONFIG_NO_FORMATTING 1902UBool IntlTest::assertEquals(const char* message, 1903 const Formattable& expected, 1904 const Formattable& actual, 1905 UBool possibleDataError) { 1906 if (expected != actual) { 1907 if (possibleDataError) { 1908 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1909 toString(actual) + 1910 "; expected " + toString(expected)); 1911 } else { 1912 errln((UnicodeString)"FAIL: " + message + "; got " + 1913 toString(actual) + 1914 "; expected " + toString(expected)); 1915 } 1916 return FALSE; 1917 } 1918#ifdef VERBOSE_ASSERTIONS 1919 else { 1920 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1921 } 1922#endif 1923 return TRUE; 1924} 1925#endif 1926 1927static char ASSERT_BUF[256]; 1928 1929static const char* extractToAssertBuf(const UnicodeString& message) { 1930 UnicodeString buf; 1931 escape(message, buf); 1932 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0); 1933 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0; 1934 return ASSERT_BUF; 1935} 1936 1937UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) { 1938 return assertTrue(extractToAssertBuf(message), condition, quiet); 1939} 1940 1941UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) { 1942 return assertFalse(extractToAssertBuf(message), condition, quiet); 1943} 1944 1945UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) { 1946 return assertSuccess(extractToAssertBuf(message), ec); 1947} 1948 1949UBool IntlTest::assertEquals(const UnicodeString& message, 1950 const UnicodeString& expected, 1951 const UnicodeString& actual, 1952 UBool possibleDataError) { 1953 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError); 1954} 1955 1956UBool IntlTest::assertEquals(const UnicodeString& message, 1957 const char* expected, 1958 const char* actual) { 1959 return assertEquals(extractToAssertBuf(message), expected, actual); 1960} 1961UBool IntlTest::assertEquals(const UnicodeString& message, 1962 UBool expected, 1963 UBool actual) { 1964 return assertEquals(extractToAssertBuf(message), expected, actual); 1965} 1966UBool IntlTest::assertEquals(const UnicodeString& message, 1967 int32_t expected, 1968 int32_t actual) { 1969 return assertEquals(extractToAssertBuf(message), expected, actual); 1970} 1971UBool IntlTest::assertEquals(const UnicodeString& message, 1972 int64_t expected, 1973 int64_t actual) { 1974 return assertEquals(extractToAssertBuf(message), expected, actual); 1975} 1976 1977#if !UCONFIG_NO_FORMATTING 1978UBool IntlTest::assertEquals(const UnicodeString& message, 1979 const Formattable& expected, 1980 const Formattable& actual) { 1981 return assertEquals(extractToAssertBuf(message), expected, actual); 1982} 1983#endif 1984 1985void IntlTest::setProperty(const char* propline) { 1986 if (numProps < kMaxProps) { 1987 proplines[numProps] = propline; 1988 } 1989 numProps++; 1990} 1991 1992const char* IntlTest::getProperty(const char* prop) { 1993 const char* val = NULL; 1994 for (int32_t i = 0; i < numProps; i++) { 1995 int32_t plen = uprv_strlen(prop); 1996 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1 1997 && proplines[i][plen] == '=' 1998 && uprv_strncmp(proplines[i], prop, plen) == 0) { 1999 val = &(proplines[i][plen+1]); 2000 break; 2001 } 2002 } 2003 return val; 2004} 2005 2006/* 2007 * Hey, Emacs, please set the following: 2008 * 2009 * Local Variables: 2010 * indent-tabs-mode: nil 2011 * End: 2012 * 2013 */ 2014