1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2014, 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 msg2 = UNICODE_STRING_SIMPLE("(Known issue #") + 981 UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg; 982 if(firstForTicket || firstForWhere) { 983 infoln(msg2); 984 } else { 985 logln(msg2); 986 } 987 988 return TRUE; 989} 990 991/* convenience functions that include sprintf formatting */ 992void IntlTest::info(const char *fmt, ...) 993{ 994 char buffer[4000]; 995 va_list ap; 996 997 va_start(ap, fmt); 998 /* sprintf it just to make sure that the information is valid */ 999 vsprintf(buffer, fmt, ap); 1000 va_end(ap); 1001 info(UnicodeString(buffer, "")); 1002} 1003 1004void IntlTest::infoln(const char *fmt, ...) 1005{ 1006 char buffer[4000]; 1007 va_list ap; 1008 1009 va_start(ap, fmt); 1010 /* sprintf it just to make sure that the information is valid */ 1011 vsprintf(buffer, fmt, ap); 1012 va_end(ap); 1013 infoln(UnicodeString(buffer, "")); 1014} 1015 1016void IntlTest::err(const char *fmt, ...) 1017{ 1018 char buffer[4000]; 1019 va_list ap; 1020 1021 va_start(ap, fmt); 1022 vsprintf(buffer, fmt, ap); 1023 va_end(ap); 1024 err(UnicodeString(buffer, "")); 1025} 1026 1027void IntlTest::errln(const char *fmt, ...) 1028{ 1029 char buffer[4000]; 1030 va_list ap; 1031 1032 va_start(ap, fmt); 1033 vsprintf(buffer, fmt, ap); 1034 va_end(ap); 1035 errln(UnicodeString(buffer, "")); 1036} 1037 1038void IntlTest::dataerrln(const char *fmt, ...) 1039{ 1040 char buffer[4000]; 1041 va_list ap; 1042 1043 va_start(ap, fmt); 1044 vsprintf(buffer, fmt, ap); 1045 va_end(ap); 1046 dataerrln(UnicodeString(buffer, "")); 1047} 1048 1049void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...) 1050{ 1051 char buffer[4000]; 1052 va_list ap; 1053 1054 va_start(ap, fmt); 1055 vsprintf(buffer, fmt, ap); 1056 va_end(ap); 1057 1058 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { 1059 dataerrln(UnicodeString(buffer, "")); 1060 } else { 1061 errln(UnicodeString(buffer, "")); 1062 } 1063} 1064 1065void IntlTest::printErrors() 1066{ 1067 IntlTest::LL_message(errorList, TRUE); 1068} 1069 1070UBool IntlTest::printKnownIssues() 1071{ 1072 if(knownList != NULL) { 1073 udbg_knownIssue_print(knownList); 1074 udbg_knownIssue_close(knownList); 1075 return TRUE; 1076 } else { 1077 return FALSE; 1078 } 1079} 1080 1081void IntlTest::LL_message( UnicodeString message, UBool newline ) 1082{ 1083 // string that starts with a LineFeed character and continues 1084 // with spaces according to the current indentation 1085 static const UChar indentUChars[] = { 1086 '\n', 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 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1096 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 1097 }; 1098 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel); 1099 1100 char buffer[30000]; 1101 int32_t length; 1102 1103 // stream out the indentation string first if necessary 1104 length = indent.extract(1, indent.length(), buffer, sizeof(buffer)); 1105 if (length > 0) { 1106 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1107 } 1108 1109 // replace each LineFeed by the indentation string 1110 message.findAndReplace(UnicodeString((UChar)'\n'), indent); 1111 1112 // stream out the message 1113 length = message.extract(0, message.length(), buffer, sizeof(buffer)); 1114 if (length > 0) { 1115 length = length > 30000 ? 30000 : length; 1116 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1117 } 1118 1119 if (newline) { 1120 char newLine = '\n'; 1121 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp); 1122 } 1123 1124 // A newline usually flushes the buffer, but 1125 // flush the message just in case of a core dump. 1126 fflush((FILE *)testoutfp); 1127} 1128 1129/** 1130* Print a usage message for this test class. 1131*/ 1132void IntlTest::usage( void ) 1133{ 1134 UBool save_verbose = setVerbose( TRUE ); 1135 logln("Test names:"); 1136 logln("-----------"); 1137 1138 int32_t index = 0; 1139 const char* name = NULL; 1140 do{ 1141 this->runIndexedTest( index, FALSE, name ); 1142 if (!name) break; 1143 logln(name); 1144 index++; 1145 }while (name && (name[0] != 0)); 1146 setVerbose( save_verbose ); 1147} 1148 1149 1150// memory leak reporting software will be able to take advantage of the testsuite 1151// being run a second time local to a specific method in order to report only actual leaks 1152UBool 1153IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks 1154{ 1155 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter 1156 strLeak->append(" for verifying purify filter"); 1157 return this->runTest( name, par ); 1158} 1159 1160 1161#if UCONFIG_NO_LEGACY_CONVERSION 1162# define TRY_CNV_1 "iso-8859-1" 1163# define TRY_CNV_2 "ibm-1208" 1164#else 1165# define TRY_CNV_1 "iso-8859-7" 1166# define TRY_CNV_2 "sjis" 1167#endif 1168 1169int 1170main(int argc, char* argv[]) 1171{ 1172 UBool syntax = FALSE; 1173 UBool all = FALSE; 1174 UBool verbose = FALSE; 1175 UBool no_err_msg = FALSE; 1176 UBool no_time = FALSE; 1177 UBool quick = TRUE; 1178 UBool name = FALSE; 1179 UBool leaks = FALSE; 1180 UBool utf8 = FALSE; 1181 const char *summary_file = NULL; 1182 UBool warnOnMissingData = FALSE; 1183 UBool defaultDataFound = FALSE; 1184 int32_t threadCount = 1; 1185 UErrorCode errorCode = U_ZERO_ERROR; 1186 UConverter *cnv = NULL; 1187 const char *warnOrErr = "Failure"; 1188 UDate startTime, endTime; 1189 int32_t diffTime; 1190 const char *props[IntlTest::kMaxProps]; 1191 int32_t nProps = 0; 1192 1193 U_MAIN_INIT_ARGS(argc, argv); 1194 1195 startTime = uprv_getRawUTCtime(); 1196 1197 for (int i = 1; i < argc; ++i) { 1198 if (argv[i][0] == '-') { 1199 const char* str = argv[i] + 1; 1200 if (strcmp("verbose", str) == 0 || 1201 strcmp("v", str) == 0) 1202 verbose = TRUE; 1203 else if (strcmp("noerrormsg", str) == 0 || 1204 strcmp("n", str) == 0) 1205 no_err_msg = TRUE; 1206 else if (strcmp("exhaustive", str) == 0 || 1207 strcmp("e", str) == 0) 1208 quick = FALSE; 1209 else if (strcmp("all", str) == 0 || 1210 strcmp("a", str) == 0) 1211 all = TRUE; 1212 else if (strcmp("utf-8", str) == 0 || 1213 strcmp("u", str) == 0) 1214 utf8 = TRUE; 1215 else if (strcmp("noknownissues", str) == 0 || 1216 strcmp("K", str) == 0) 1217 noKnownIssues = TRUE; 1218 else if (strcmp("leaks", str) == 0 || 1219 strcmp("l", str) == 0) 1220 leaks = TRUE; 1221 else if (strcmp("notime", str) == 0 || 1222 strcmp("T", str) == 0) 1223 no_time = TRUE; 1224 else if (strncmp("E", str, 1) == 0) 1225 summary_file = str+1; 1226 else if (strcmp("x", str)==0) { 1227 if(++i>=argc) { 1228 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n"); 1229 syntax = TRUE; 1230 } 1231 if(ctest_xml_setFileName(argv[i])) { /* set the name */ 1232 return 1; /* error */ 1233 } 1234 } else if (strcmp("w", str) == 0) { 1235 warnOnMissingData = TRUE; 1236 warnOrErr = "WARNING"; 1237 } 1238 else if (strncmp("threads:", str, 8) == 0) { 1239 threadCount = atoi(str + 8); 1240 } 1241 else if (strncmp("prop:", str, 5) == 0) { 1242 if (nProps < IntlTest::kMaxProps) { 1243 props[nProps] = str + 5; 1244 } 1245 nProps++; 1246 } 1247 else { 1248 syntax = TRUE; 1249 } 1250 }else{ 1251 name = TRUE; 1252 } 1253 } 1254 1255 if (!all && !name) { 1256 all = TRUE; 1257 } else if (all && name) { 1258 syntax = TRUE; 1259 } 1260 1261 if (syntax) { 1262 fprintf(stdout, 1263 "### Syntax:\n" 1264 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" 1265 "### \n" 1266 "### Options are: verbose (v), all (a), noerrormsg (n), \n" 1267 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n" 1268 "### notime (T), \n" 1269 "### threads:<threadCount> (Mulithreading must first be \n" 1270 "### enabled otherwise this will be ignored. \n" 1271 "### The default thread count is 1.),\n" 1272 "### (Specify either -all (shortcut -a) or a test name). \n" 1273 "### -all will run all of the tests.\n" 1274 "### \n" 1275 "### To get a list of the test names type: intltest LIST \n" 1276 "### To run just the utility tests type: intltest utility \n" 1277 "### \n" 1278 "### Test names can be nested using slashes (\"testA/subtest1\") \n" 1279 "### For example to list the utility tests type: intltest utility/LIST \n" 1280 "### To run just the Locale test type: intltest utility/LocaleTest \n" 1281 "### \n" 1282 "### A parameter can be specified for a test by appending '@' and the value \n" 1283 "### to the testname. \n\n"); 1284 return 1; 1285 } 1286 1287 if (nProps > IntlTest::kMaxProps) { 1288 fprintf(stdout, "### Too many properties. Exiting.\n"); 1289 } 1290 1291 MajorTestLevel major; 1292 major.setVerbose( verbose ); 1293 major.setNoErrMsg( no_err_msg ); 1294 major.setQuick( quick ); 1295 major.setLeaks( leaks ); 1296 major.setThreadCount( threadCount ); 1297 major.setWarnOnMissingData( warnOnMissingData ); 1298 major.setNotime (no_time); 1299 for (int32_t i = 0; i < nProps; i++) { 1300 major.setProperty(props[i]); 1301 } 1302 1303 1304 fprintf(stdout, "-----------------------------------------------\n"); 1305 fprintf(stdout, " IntlTest (C++) Test Suite for \n"); 1306 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); 1307 1308 1309 { 1310 const char *charsetFamily = "Unknown"; 1311 int32_t voidSize = (int32_t)sizeof(void*); 1312 int32_t bits = voidSize * 8; 1313 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) { 1314 charsetFamily="ASCII"; 1315 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) { 1316 charsetFamily="EBCDIC"; 1317 } 1318 fprintf(stdout, 1319 " Bits: %d, Byte order: %s, Chars: %s\n", 1320 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian", 1321 charsetFamily); 1322 } 1323 fprintf(stdout, "-----------------------------------------------\n"); 1324 fprintf(stdout, " Options: \n"); 1325 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); 1326 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); 1327 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); 1328 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); 1329 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); 1330 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off")); 1331 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off")); 1332 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off")); 1333 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); 1334#if (ICU_USE_THREADS==0) 1335 fprintf(stdout, " Threads : Disabled\n"); 1336#else 1337 fprintf(stdout, " Threads : %d\n", threadCount); 1338#endif 1339 for (int32_t i = 0; i < nProps; i++) { 1340 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]); 1341 } 1342 fprintf(stdout, "-----------------------------------------------\n"); 1343 1344 if(utf8) { 1345 ucnv_setDefaultName("utf-8"); 1346 } 1347 /* Check whether ICU will initialize without forcing the build data directory into 1348 * the ICU_DATA path. Success here means either the data dll contains data, or that 1349 * this test program was run with ICU_DATA set externally. Failure of this check 1350 * is normal when ICU data is not packaged into a shared library. 1351 * 1352 * Whether or not this test succeeds, we want to cleanup and reinitialize 1353 * with a data path so that data loading from individual files can be tested. 1354 */ 1355 u_init(&errorCode); 1356 if (U_FAILURE(errorCode)) { 1357 fprintf(stderr, 1358 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n"); 1359 defaultDataFound = FALSE; 1360 } 1361 else { 1362 defaultDataFound = TRUE; 1363 } 1364 u_cleanup(); 1365 if(utf8) { 1366 ucnv_setDefaultName("utf-8"); 1367 } 1368 errorCode = U_ZERO_ERROR; 1369 1370 /* Initialize ICU */ 1371 if (!defaultDataFound) { 1372 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. 1373 } 1374 u_init(&errorCode); 1375 if (U_FAILURE(errorCode)) { 1376 fprintf(stderr, 1377 "#### ERROR! %s: u_init() failed with status = \"%s\".\n" 1378 "*** Check the ICU_DATA environment variable and \n" 1379 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); 1380 if(warnOnMissingData == 0) { 1381 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1382 u_cleanup(); 1383 return 1; 1384 } 1385 } 1386 1387 // initial check for the default converter 1388 errorCode = U_ZERO_ERROR; 1389 cnv = ucnv_open(0, &errorCode); 1390 if(cnv != 0) { 1391 // ok 1392 ucnv_close(cnv); 1393 } else { 1394 fprintf(stdout, 1395 "*** %s! The default converter [%s] cannot be opened.\n" 1396 "*** Check the ICU_DATA environment variable and\n" 1397 "*** check that the data files are present.\n", 1398 warnOrErr, ucnv_getDefaultName()); 1399 if(!warnOnMissingData) { 1400 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1401 return 1; 1402 } 1403 } 1404 1405 // try more data 1406 cnv = ucnv_open(TRY_CNV_2, &errorCode); 1407 if(cnv != 0) { 1408 // ok 1409 ucnv_close(cnv); 1410 } else { 1411 fprintf(stdout, 1412 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" 1413 "*** Check the ICU_DATA environment variable and \n" 1414 "*** check that the data files are present.\n", warnOrErr); 1415 if(!warnOnMissingData) { 1416 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1417 return 1; 1418 } 1419 } 1420 1421 UResourceBundle *rb = ures_open(0, "en", &errorCode); 1422 ures_close(rb); 1423 if(U_FAILURE(errorCode)) { 1424 fprintf(stdout, 1425 "*** %s! The \"en\" locale resource bundle cannot be opened.\n" 1426 "*** Check the ICU_DATA environment variable and \n" 1427 "*** check that the data files are present.\n", warnOrErr); 1428 if(!warnOnMissingData) { 1429 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1430 return 1; 1431 } 1432 } 1433 1434 Locale originalLocale; // Save the default locale for comparison later on. 1435 1436 if(ctest_xml_init("intltest")) 1437 return 1; 1438 1439 1440 /* TODO: Add option to call u_cleanup and rerun tests. */ 1441 if (all) { 1442 major.runTest(); 1443 if (leaks) { 1444 major.run_phase2( NULL, NULL ); 1445 } 1446 }else{ 1447 for (int i = 1; i < argc; ++i) { 1448 if (argv[i][0] != '-') { 1449 char* name = argv[i]; 1450 fprintf(stdout, "\n=== Handling test: %s: ===\n", name); 1451 1452 char baseName[1024]; 1453 sprintf(baseName, "/%s/", name); 1454 1455 char* parameter = strchr( name, '@' ); 1456 if (parameter) { 1457 *parameter = 0; 1458 parameter += 1; 1459 } 1460 execCount = 0; 1461 UBool res = major.runTest( name, parameter, baseName ); 1462 if (leaks && res) { 1463 major.run_phase2( name, parameter ); 1464 } 1465 if (!res || (execCount <= 0)) { 1466 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name); 1467 } 1468 } else if(!strcmp(argv[i],"-x")) { 1469 i++; 1470 } 1471 } 1472 } 1473 1474 1475#if !UCONFIG_NO_FORMATTING 1476 CalendarTimeZoneTest::cleanup(); 1477#endif 1478 1479 free(_testDataPath); 1480 _testDataPath = 0; 1481 1482 Locale lastDefaultLocale; 1483 if (originalLocale != lastDefaultLocale) { 1484 major.errln("FAILURE: A test changed the default locale without resetting it."); 1485 } 1486 1487 fprintf(stdout, "\n--------------------------------------\n"); 1488 if( major.printKnownIssues() ) { 1489 fprintf(stdout, " To run suppressed tests, use the -K option. \n"); 1490 } 1491 if (major.getErrors() == 0) { 1492 /* Call it twice to make sure that the defaults were reset. */ 1493 /* Call it before the OK message to verify proper cleanup. */ 1494 u_cleanup(); 1495 u_cleanup(); 1496 1497 fprintf(stdout, "OK: All tests passed without error.\n"); 1498 1499 if (major.getDataErrors() != 0) { 1500 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n"); 1501 } 1502 }else{ 1503 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors()); 1504 major.printErrors(); 1505 1506 if(summary_file != NULL) { 1507 FILE *summf = fopen(summary_file, "w"); 1508 if( summf != NULL) { 1509 char buf[10000]; 1510 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf)); 1511 fwrite(buf, sizeof(*buf), length, (FILE*)summf); 1512 fclose(summf); 1513 } 1514 } 1515 1516 1517 if (major.getDataErrors() != 0) { 1518 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n" 1519 "\tstock ICU data (i.e some have been added or removed), consider using\n" 1520 "\tthe '-w' option to turn these errors into warnings.\n"); 1521 } 1522 1523 /* Call afterwards to display errors. */ 1524 u_cleanup(); 1525 } 1526 1527 fprintf(stdout, "--------------------------------------\n"); 1528 1529 if (execCount <= 0) { 1530 fprintf(stdout, "***** Not all called tests actually exist! *****\n"); 1531 } 1532 if(!no_time) { 1533 endTime = uprv_getRawUTCtime(); 1534 diffTime = (int32_t)(endTime - startTime); 1535 printf("Elapsed Time: %02d:%02d:%02d.%03d\n", 1536 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), 1537 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), 1538 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), 1539 (int)(diffTime%U_MILLIS_PER_SECOND)); 1540 } 1541 1542 if(ctest_xml_fini()) 1543 return 1; 1544 1545 return major.getErrors(); 1546} 1547 1548const char* IntlTest::loadTestData(UErrorCode& err){ 1549 if( _testDataPath == NULL){ 1550 const char* directory=NULL; 1551 UResourceBundle* test =NULL; 1552 char* tdpath=NULL; 1553 const char* tdrelativepath; 1554 1555#if defined (U_TOPBUILDDIR) 1556 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1557 directory = U_TOPBUILDDIR; 1558#else 1559 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1560 directory = pathToDataDirectory(); 1561#endif 1562 1563 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100)); 1564 1565 1566 /* u_getDataDirectory shoul return \source\data ... set the 1567 * directory to ..\source\data\..\test\testdata\out\testdata 1568 */ 1569 strcpy(tdpath, directory); 1570 strcat(tdpath, tdrelativepath); 1571 strcat(tdpath,"testdata"); 1572 1573 test=ures_open(tdpath, "testtypes", &err); 1574 1575 if(U_FAILURE(err)){ 1576 err = U_FILE_ACCESS_ERROR; 1577 it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); 1578 return ""; 1579 } 1580 ures_close(test); 1581 _testDataPath = tdpath; 1582 return _testDataPath; 1583 } 1584 return _testDataPath; 1585} 1586 1587const char* IntlTest::getTestDataPath(UErrorCode& err) { 1588 return loadTestData(err); 1589} 1590 1591/* Returns the path to icu/source/test/testdata/ */ 1592const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) { 1593 const char *srcDataDir = NULL; 1594#ifdef U_TOPSRCDIR 1595 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1596#else 1597 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1598 FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r"); 1599 if (f) { 1600 /* We're in icu/source/test/intltest/ */ 1601 fclose(f); 1602 } 1603 else { 1604 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */ 1605 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING 1606 "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1607 } 1608#endif 1609 return srcDataDir; 1610} 1611 1612char *IntlTest::getUnidataPath(char path[]) { 1613 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt") 1614 1615 // Look inside ICU_DATA first. 1616 strcpy(path, pathToDataDirectory()); 1617 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt"); 1618 FILE *f = fopen(path, "r"); 1619 if(f != NULL) { 1620 fclose(f); 1621 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename. 1622 return path; 1623 } 1624 1625 // As a fallback, try to guess where the source data was located 1626 // at the time ICU was built, and look there. 1627# ifdef U_TOPSRCDIR 1628 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data"); 1629# else 1630 UErrorCode errorCode = U_ZERO_ERROR; 1631 const char *testDataPath = loadTestData(errorCode); 1632 if(U_FAILURE(errorCode)) { 1633 it_errln(UnicodeString( 1634 "unable to find path to source/data/unidata/ and loadTestData() failed: ") + 1635 u_errorName(errorCode)); 1636 return NULL; 1637 } 1638 strcpy(path, testDataPath); 1639 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." 1640 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." 1641 U_FILE_SEP_STRING "data"); 1642# endif 1643 strcat(path, U_FILE_SEP_STRING); 1644 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt"); 1645 f = fopen(path, "r"); 1646 if(f != NULL) { 1647 fclose(f); 1648 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename. 1649 return path; 1650 } 1651 return NULL; 1652} 1653 1654const char* IntlTest::fgDataDir = NULL; 1655 1656/* returns the path to icu/source/data */ 1657const char * IntlTest::pathToDataDirectory() 1658{ 1659 1660 if(fgDataDir != NULL) { 1661 return fgDataDir; 1662 } 1663 1664 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst 1665 // to point to the top of the build hierarchy, which may or 1666 // may not be the same as the source directory, depending on 1667 // the configure options used. At any rate, 1668 // set the data path to the built data from this directory. 1669 // The value is complete with quotes, so it can be used 1670 // as-is as a string constant. 1671 */ 1672#if defined (U_TOPSRCDIR) 1673 { 1674 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1675 } 1676#else 1677 1678 /* On Windows, the file name obtained from __FILE__ includes a full path. 1679 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 1680 * Change to "wherever\icu\source\data" 1681 */ 1682 { 1683 static char p[sizeof(__FILE__) + 10]; 1684 char *pBackSlash; 1685 int i; 1686 1687 strcpy(p, __FILE__); 1688 /* We want to back over three '\' chars. */ 1689 /* Only Windows should end up here, so looking for '\' is safe. */ 1690 for (i=1; i<=3; i++) { 1691 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 1692 if (pBackSlash != NULL) { 1693 *pBackSlash = 0; /* Truncate the string at the '\' */ 1694 } 1695 } 1696 1697 if (pBackSlash != NULL) { 1698 /* We found and truncated three names from the path. 1699 * Now append "source\data" and set the environment 1700 */ 1701 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); 1702 fgDataDir = p; 1703 } 1704 else { 1705 /* __FILE__ on MSVC7 does not contain the directory */ 1706 FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 1707 if (file) { 1708 fclose(file); 1709 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1710 } 1711 else { 1712 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1713 } 1714 } 1715 } 1716#endif 1717 1718 return fgDataDir; 1719 1720} 1721 1722/* 1723 * This is a variant of cintltst/ccolltst.c:CharsToUChars(). 1724 * It converts an invariant-character string into a UnicodeString, with 1725 * unescaping \u sequences. 1726 */ 1727UnicodeString CharsToUnicodeString(const char* chars){ 1728 return UnicodeString(chars, -1, US_INV).unescape(); 1729} 1730 1731UnicodeString ctou(const char* chars) { 1732 return CharsToUnicodeString(chars); 1733} 1734 1735#define RAND_M (714025) 1736#define RAND_IA (1366) 1737#define RAND_IC (150889) 1738 1739static int32_t RAND_SEED; 1740 1741/** 1742 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use 1743 * with care: Does not return all possible values; returns one of 1744 * 714,025 values, uniformly spaced. However, the period is 1745 * effectively infinite. See: Numerical Recipes, section 7.1. 1746 * 1747 * @param seedp pointer to seed. Set *seedp to any negative value 1748 * to restart the sequence. 1749 */ 1750float IntlTest::random(int32_t* seedp) { 1751 static int32_t iy, ir[98]; 1752 static UBool first=TRUE; 1753 int32_t j; 1754 if (*seedp < 0 || first) { 1755 first = FALSE; 1756 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp); 1757 for (j=1;j<=97;++j) { 1758 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1759 ir[j]=(*seedp); 1760 } 1761 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1762 iy=(*seedp); 1763 } 1764 j=(int32_t)(1 + 97.0*iy/RAND_M); 1765 U_ASSERT(j>=1 && j<=97); 1766 iy=ir[j]; 1767 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1768 ir[j]=(*seedp); 1769 return (float) iy/RAND_M; 1770} 1771 1772/** 1773 * Convenience method using a global seed. 1774 */ 1775float IntlTest::random() { 1776 return random(&RAND_SEED); 1777} 1778 1779static inline UChar toHex(int32_t i) { 1780 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); 1781} 1782 1783static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) { 1784 for (int32_t i=0; i<s.length(); ++i) { 1785 UChar c = s[i]; 1786 if (c <= (UChar)0x7F) { 1787 result += c; 1788 } else { 1789 result += (UChar)0x5c; 1790 result += (UChar)0x75; 1791 result += toHex((c >> 12) & 0xF); 1792 result += toHex((c >> 8) & 0xF); 1793 result += toHex((c >> 4) & 0xF); 1794 result += toHex( c & 0xF); 1795 } 1796 } 1797 return result; 1798} 1799 1800#define VERBOSE_ASSERTIONS 1801 1802UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) { 1803 if (file != NULL) { 1804 if (!condition) { 1805 if (possibleDataError) { 1806 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1807 } else { 1808 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1809 } 1810 } else if (!quiet) { 1811 logln("%s:%d: Ok: %s", file, line, message); 1812 } 1813 } else { 1814 if (!condition) { 1815 if (possibleDataError) { 1816 dataerrln("FAIL: assertTrue() failed: %s", message); 1817 } else { 1818 errln("FAIL: assertTrue() failed: %s", message); 1819 } 1820 } else if (!quiet) { 1821 logln("Ok: %s", message); 1822 } 1823 1824 } 1825 return condition; 1826} 1827 1828UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { 1829 if (condition) { 1830 errln("FAIL: assertFalse() failed: %s", message); 1831 } else if (!quiet) { 1832 logln("Ok: %s", message); 1833 } 1834 return !condition; 1835} 1836 1837UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) { 1838 if( file==NULL ) { 1839 file = ""; // prevent failure if no file given 1840 } 1841 if (U_FAILURE(ec)) { 1842 if (possibleDataError) { 1843 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1844 } else { 1845 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1846 } 1847 return FALSE; 1848 } else { 1849 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec)); 1850 } 1851 return TRUE; 1852} 1853 1854UBool IntlTest::assertEquals(const char* message, 1855 const UnicodeString& expected, 1856 const UnicodeString& actual, 1857 UBool possibleDataError) { 1858 if (expected != actual) { 1859 if (possibleDataError) { 1860 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1861 prettify(actual) + 1862 "; expected " + prettify(expected)); 1863 } else { 1864 errln((UnicodeString)"FAIL: " + message + "; got " + 1865 prettify(actual) + 1866 "; expected " + prettify(expected)); 1867 } 1868 return FALSE; 1869 } 1870#ifdef VERBOSE_ASSERTIONS 1871 else { 1872 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual)); 1873 } 1874#endif 1875 return TRUE; 1876} 1877 1878UBool IntlTest::assertEquals(const char* message, 1879 const char* expected, 1880 const char* actual) { 1881 if (uprv_strcmp(expected, actual) != 0) { 1882 errln((UnicodeString)"FAIL: " + message + "; got \"" + 1883 actual + 1884 "\"; expected \"" + expected + "\""); 1885 return FALSE; 1886 } 1887#ifdef VERBOSE_ASSERTIONS 1888 else { 1889 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\""); 1890 } 1891#endif 1892 return TRUE; 1893} 1894 1895UBool IntlTest::assertEquals(const char* message, 1896 int32_t expected, 1897 int32_t actual) { 1898 if (expected != actual) { 1899 errln((UnicodeString)"FAIL: " + message + "; got " + 1900 actual + "=0x" + toHex(actual) + 1901 "; expected " + expected + "=0x" + toHex(expected)); 1902 return FALSE; 1903 } 1904#ifdef VERBOSE_ASSERTIONS 1905 else { 1906 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual)); 1907 } 1908#endif 1909 return TRUE; 1910} 1911 1912UBool IntlTest::assertEquals(const char* message, 1913 int64_t expected, 1914 int64_t actual) { 1915 if (expected != actual) { 1916 errln((UnicodeString)"FAIL: " + message + "; got int64 " + 1917 Int64ToUnicodeString(actual) + 1918 "; expected " + Int64ToUnicodeString(expected) ); 1919 return FALSE; 1920 } 1921#ifdef VERBOSE_ASSERTIONS 1922 else { 1923 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual)); 1924 } 1925#endif 1926 return TRUE; 1927} 1928 1929UBool IntlTest::assertEquals(const char* message, 1930 UBool expected, 1931 UBool actual) { 1932 if (expected != actual) { 1933 errln((UnicodeString)"FAIL: " + message + "; got " + 1934 toString(actual) + 1935 "; expected " + toString(expected)); 1936 return FALSE; 1937 } 1938#ifdef VERBOSE_ASSERTIONS 1939 else { 1940 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1941 } 1942#endif 1943 return TRUE; 1944} 1945 1946#if !UCONFIG_NO_FORMATTING 1947UBool IntlTest::assertEquals(const char* message, 1948 const Formattable& expected, 1949 const Formattable& actual, 1950 UBool possibleDataError) { 1951 if (expected != actual) { 1952 if (possibleDataError) { 1953 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1954 toString(actual) + 1955 "; expected " + toString(expected)); 1956 } else { 1957 errln((UnicodeString)"FAIL: " + message + "; got " + 1958 toString(actual) + 1959 "; expected " + toString(expected)); 1960 } 1961 return FALSE; 1962 } 1963#ifdef VERBOSE_ASSERTIONS 1964 else { 1965 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1966 } 1967#endif 1968 return TRUE; 1969} 1970#endif 1971 1972static char ASSERT_BUF[256]; 1973 1974static const char* extractToAssertBuf(const UnicodeString& message) { 1975 UnicodeString buf; 1976 escape(message, buf); 1977 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0); 1978 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0; 1979 return ASSERT_BUF; 1980} 1981 1982UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) { 1983 return assertTrue(extractToAssertBuf(message), condition, quiet); 1984} 1985 1986UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) { 1987 return assertFalse(extractToAssertBuf(message), condition, quiet); 1988} 1989 1990UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) { 1991 return assertSuccess(extractToAssertBuf(message), ec); 1992} 1993 1994UBool IntlTest::assertEquals(const UnicodeString& message, 1995 const UnicodeString& expected, 1996 const UnicodeString& actual, 1997 UBool possibleDataError) { 1998 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError); 1999} 2000 2001UBool IntlTest::assertEquals(const UnicodeString& message, 2002 const char* expected, 2003 const char* actual) { 2004 return assertEquals(extractToAssertBuf(message), expected, actual); 2005} 2006UBool IntlTest::assertEquals(const UnicodeString& message, 2007 UBool expected, 2008 UBool actual) { 2009 return assertEquals(extractToAssertBuf(message), expected, actual); 2010} 2011UBool IntlTest::assertEquals(const UnicodeString& message, 2012 int32_t expected, 2013 int32_t actual) { 2014 return assertEquals(extractToAssertBuf(message), expected, actual); 2015} 2016UBool IntlTest::assertEquals(const UnicodeString& message, 2017 int64_t expected, 2018 int64_t actual) { 2019 return assertEquals(extractToAssertBuf(message), expected, actual); 2020} 2021 2022#if !UCONFIG_NO_FORMATTING 2023UBool IntlTest::assertEquals(const UnicodeString& message, 2024 const Formattable& expected, 2025 const Formattable& actual) { 2026 return assertEquals(extractToAssertBuf(message), expected, actual); 2027} 2028#endif 2029 2030void IntlTest::setProperty(const char* propline) { 2031 if (numProps < kMaxProps) { 2032 proplines[numProps] = propline; 2033 } 2034 numProps++; 2035} 2036 2037const char* IntlTest::getProperty(const char* prop) { 2038 const char* val = NULL; 2039 for (int32_t i = 0; i < numProps; i++) { 2040 int32_t plen = uprv_strlen(prop); 2041 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1 2042 && proplines[i][plen] == '=' 2043 && uprv_strncmp(proplines[i], prop, plen) == 0) { 2044 val = &(proplines[i][plen+1]); 2045 break; 2046 } 2047 } 2048 return val; 2049} 2050 2051/* 2052 * Hey, Emacs, please set the following: 2053 * 2054 * Local Variables: 2055 * indent-tabs-mode: nil 2056 * End: 2057 * 2058 */ 2059