1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2015, 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 49 static char* _testDataPath=NULL; 50 51 // Static list of errors found 52 static UnicodeString errorList; 53 static void *knownList = NULL; // known issues 54 static 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 61 UnicodeString 62 UCharToUnicodeString(UChar c) 63 { return UnicodeString(c); } 64 65 // [rtg] Just to get things working 66 UnicodeString 67 operator+(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 79 UnicodeString 80 operator+(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 92 UnicodeString 93 Int64ToUnicodeString(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 109 UnicodeString 110 operator+(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 127 UnicodeString 128 operator+(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 */ 139 UnicodeString _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 */ 204 UnicodeString 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 214 UnicodeString toString(int32_t n) { 215 return UnicodeString() + (long)n; 216 } 217 218 219 220 UnicodeString toString(UBool b) { 221 return b ? UnicodeString("TRUE"):UnicodeString("FALSE"); 222 } 223 224 // stephen - cleaned up 05/05/99 225 UnicodeString operator+(const UnicodeString& left, char num) 226 { return left + (long)num; } 227 UnicodeString operator+(const UnicodeString& left, short num) 228 { return left + (long)num; } 229 UnicodeString operator+(const UnicodeString& left, int num) 230 { return left + (long)num; } 231 UnicodeString operator+(const UnicodeString& left, unsigned char num) 232 { return left + (unsigned long)num; } 233 UnicodeString operator+(const UnicodeString& left, unsigned short num) 234 { return left + (unsigned long)num; } 235 UnicodeString operator+(const UnicodeString& left, unsigned int num) 236 { return left + (unsigned long)num; } 237 UnicodeString operator+(const UnicodeString& left, float num) 238 { return left + (double)num; } 239 240 //------------------ 241 242 // Append a hex string to the target 243 UnicodeString& 244 IntlTest::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 286 UnicodeString 287 IntlTest::toHex(uint32_t number, int32_t digits) { 288 UnicodeString result; 289 appendHex(number, digits, result); 290 return result; 291 } 292 293 static 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 298 UnicodeString& 299 IntlTest::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 334 UnicodeString 335 IntlTest::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 */ 393 void 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 462 static const int32_t indentLevel_offset = 3; 463 static const char delim = '/'; 464 465 IntlTest* IntlTest::gTest = NULL; 466 467 static int32_t execCount = 0; 468 469 void it_log( UnicodeString message ) 470 { 471 if (IntlTest::gTest) 472 IntlTest::gTest->log( message ); 473 } 474 475 void it_logln( UnicodeString message ) 476 { 477 if (IntlTest::gTest) 478 IntlTest::gTest->logln( message ); 479 } 480 481 void it_logln( void ) 482 { 483 if (IntlTest::gTest) 484 IntlTest::gTest->logln(); 485 } 486 487 void it_info( UnicodeString message ) 488 { 489 if (IntlTest::gTest) 490 IntlTest::gTest->info( message ); 491 } 492 493 void it_infoln( UnicodeString message ) 494 { 495 if (IntlTest::gTest) 496 IntlTest::gTest->infoln( message ); 497 } 498 499 void it_infoln( void ) 500 { 501 if (IntlTest::gTest) 502 IntlTest::gTest->infoln(); 503 } 504 505 void it_err() 506 { 507 if (IntlTest::gTest) 508 IntlTest::gTest->err(); 509 } 510 511 void it_err( UnicodeString message ) 512 { 513 if (IntlTest::gTest) 514 IntlTest::gTest->err( message ); 515 } 516 517 void it_errln( UnicodeString message ) 518 { 519 if (IntlTest::gTest) 520 IntlTest::gTest->errln( message ); 521 } 522 523 void it_dataerr( UnicodeString message ) 524 { 525 if (IntlTest::gTest) 526 IntlTest::gTest->dataerr( message ); 527 } 528 529 void it_dataerrln( UnicodeString message ) 530 { 531 if (IntlTest::gTest) 532 IntlTest::gTest->dataerrln( message ); 533 } 534 535 IntlTest::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 556 void 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 threadCount = caller->threadCount; 565 testoutfp = caller->testoutfp; 566 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset; 567 numProps = caller->numProps; 568 for (int32_t i = 0; i < numProps; i++) { 569 proplines[i] = caller->proplines[i]; 570 } 571 } 572 } 573 574 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par ) 575 { 576 execCount--; // correct a previously assumed test-exec, as this only calls a subtest 577 testToBeCalled.setCaller( this ); 578 strcpy(testToBeCalled.basePath, this->basePath ); 579 UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath ); 580 strcpy(testToBeCalled.basePath, this->basePath ); // reset it. 581 return result; 582 } 583 584 void IntlTest::setPath( char* pathVal ) 585 { 586 this->testPath = pathVal; 587 } 588 589 UBool IntlTest::setVerbose( UBool verboseVal ) 590 { 591 UBool rval = this->verbose; 592 this->verbose = verboseVal; 593 return rval; 594 } 595 596 UBool IntlTest::setNotime( UBool no_time ) 597 { 598 UBool rval = this->no_time; 599 this->no_time = no_time; 600 return rval; 601 } 602 603 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal ) 604 { 605 UBool rval = this->warn_on_missing_data; 606 this->warn_on_missing_data = warn_on_missing_dataVal; 607 return rval; 608 } 609 610 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal ) 611 { 612 UBool rval = this->no_err_msg; 613 this->no_err_msg = no_err_msgVal; 614 return rval; 615 } 616 617 UBool IntlTest::setQuick( UBool quickVal ) 618 { 619 UBool rval = this->quick; 620 this->quick = quickVal; 621 return rval; 622 } 623 624 UBool IntlTest::setLeaks( UBool leaksVal ) 625 { 626 UBool rval = this->leaks; 627 this->leaks = leaksVal; 628 return rval; 629 } 630 631 int32_t IntlTest::setThreadCount( int32_t count ) 632 { 633 int32_t rval = this->threadCount; 634 this->threadCount = count; 635 return rval; 636 } 637 638 int32_t IntlTest::getErrors( void ) 639 { 640 return errorCount; 641 } 642 643 int32_t IntlTest::getDataErrors( void ) 644 { 645 return dataErrorCount; 646 } 647 648 UBool IntlTest::runTest( char* name, char* par, char *baseName ) 649 { 650 UBool rval; 651 char* pos = NULL; 652 653 char* baseNameBuffer = NULL; 654 655 if(baseName == NULL) { 656 baseNameBuffer = (char*)malloc(1024); 657 baseName=baseNameBuffer; 658 strcpy(baseName, "/"); 659 } 660 661 if (name) 662 pos = strchr( name, delim ); // check if name contains path (by looking for '/') 663 if (pos) { 664 testPath = pos+1; // store subpath for calling subtest 665 *pos = 0; // split into two strings 666 }else{ 667 testPath = NULL; 668 } 669 670 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) { 671 rval = runTestLoop( NULL, par, baseName ); 672 673 }else if (strcmp( name, "LIST" ) == 0) { 674 this->usage(); 675 rval = TRUE; 676 677 }else{ 678 rval = runTestLoop( name, par, baseName ); 679 } 680 681 if (pos) 682 *pos = delim; // restore original value at pos 683 if(baseNameBuffer!=NULL) { 684 free(baseNameBuffer); 685 } 686 return rval; 687 } 688 689 // call individual tests, to be overriden to call implementations 690 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ ) 691 { 692 // to be overriden by a method like: 693 /* 694 switch (index) { 695 case 0: name = "First Test"; if (exec) FirstTest( par ); break; 696 case 1: name = "Second Test"; if (exec) SecondTest( par ); break; 697 default: name = ""; break; 698 } 699 */ 700 this->errln("*** runIndexedTest needs to be overriden! ***"); 701 } 702 703 704 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName ) 705 { 706 int32_t index = 0; 707 const char* name; 708 UBool run_this_test; 709 int32_t lastErrorCount; 710 UBool rval = FALSE; 711 UBool lastTestFailed; 712 713 if(baseName == NULL) { 714 printf("ERROR: baseName can't be null.\n"); 715 return FALSE; 716 } else { 717 if ((char *)this->basePath != baseName) { 718 strcpy(this->basePath, baseName); 719 } 720 } 721 722 char * saveBaseLoc = baseName+strlen(baseName); 723 724 IntlTest* saveTest = gTest; 725 gTest = this; 726 do { 727 this->runIndexedTest( index, FALSE, name, par ); 728 if (strcmp(name,"skip") == 0) { 729 run_this_test = FALSE; 730 } else { 731 if (!name || (name[0] == 0)) 732 break; 733 if (!testname) { 734 run_this_test = TRUE; 735 }else{ 736 run_this_test = (UBool) (strcmp( name, testname ) == 0); 737 } 738 } 739 if (run_this_test) { 740 lastErrorCount = errorCount; 741 execCount++; 742 char msg[256]; 743 sprintf(msg, "%s {", name); 744 LL_message(msg, TRUE); 745 UDate timeStart = uprv_getRawUTCtime(); 746 strcpy(saveBaseLoc,name); 747 strcat(saveBaseLoc,"/"); 748 749 strcpy(currName, name); // set 750 this->runIndexedTest( index, TRUE, name, par ); 751 currName[0]=0; // reset 752 753 UDate timeStop = uprv_getRawUTCtime(); 754 rval = TRUE; // at least one test has been called 755 char secs[256]; 756 if(!no_time) { 757 sprintf(secs, "%f", (timeStop-timeStart)/1000.0); 758 } else { 759 secs[0]=0; 760 } 761 762 763 strcpy(saveBaseLoc,name); 764 765 766 ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL); 767 768 769 saveBaseLoc[0]=0; /* reset path */ 770 771 if (lastErrorCount == errorCount) { 772 sprintf( msg, " } OK: %s ", name ); 773 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); 774 lastTestFailed = FALSE; 775 }else{ 776 sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name); 777 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); 778 779 for(int i=0;i<LL_indentlevel;i++) { 780 errorList += " "; 781 } 782 errorList += name; 783 errorList += "\n"; 784 lastTestFailed = TRUE; 785 } 786 LL_indentlevel -= 3; 787 if (lastTestFailed) { 788 LL_message( "", TRUE); 789 } 790 LL_message( msg, TRUE); 791 if (lastTestFailed) { 792 LL_message( "", TRUE); 793 } 794 LL_indentlevel += 3; 795 } 796 index++; 797 }while(name); 798 799 *saveBaseLoc = 0; 800 801 gTest = saveTest; 802 return rval; 803 } 804 805 806 /** 807 * Adds given string to the log if we are in verbose mode. 808 */ 809 void IntlTest::log( const UnicodeString &message ) 810 { 811 if( verbose ) { 812 LL_message( message, FALSE ); 813 } 814 } 815 816 /** 817 * Adds given string to the log if we are in verbose mode. Adds a new line to 818 * the given message. 819 */ 820 void IntlTest::logln( const UnicodeString &message ) 821 { 822 if( verbose ) { 823 LL_message( message, TRUE ); 824 } 825 } 826 827 void IntlTest::logln( void ) 828 { 829 if( verbose ) { 830 LL_message( "", TRUE ); 831 } 832 } 833 834 /** 835 * Unconditionally adds given string to the log. 836 */ 837 void IntlTest::info( const UnicodeString &message ) 838 { 839 LL_message( message, FALSE ); 840 } 841 842 /** 843 * Unconditionally adds given string to the log. Adds a new line to 844 * the given message. 845 */ 846 void IntlTest::infoln( const UnicodeString &message ) 847 { 848 LL_message( message, TRUE ); 849 } 850 851 void IntlTest::infoln( void ) 852 { 853 LL_message( "", TRUE ); 854 } 855 856 int32_t IntlTest::IncErrorCount( void ) 857 { 858 errorCount++; 859 if (caller) caller->IncErrorCount(); 860 return errorCount; 861 } 862 863 int32_t IntlTest::IncDataErrorCount( void ) 864 { 865 dataErrorCount++; 866 if (caller) caller->IncDataErrorCount(); 867 return dataErrorCount; 868 } 869 870 void IntlTest::err() 871 { 872 IncErrorCount(); 873 } 874 875 void IntlTest::err( const UnicodeString &message ) 876 { 877 IncErrorCount(); 878 if (!no_err_msg) LL_message( message, FALSE ); 879 } 880 881 void IntlTest::errln( const UnicodeString &message ) 882 { 883 IncErrorCount(); 884 if (!no_err_msg) LL_message( message, TRUE ); 885 } 886 887 void IntlTest::dataerr( const UnicodeString &message ) 888 { 889 IncDataErrorCount(); 890 891 if (!warn_on_missing_data) { 892 IncErrorCount(); 893 } 894 895 if (!no_err_msg) LL_message( message, FALSE ); 896 } 897 898 void IntlTest::dataerrln( const UnicodeString &message ) 899 { 900 int32_t errCount = IncDataErrorCount(); 901 UnicodeString msg; 902 if (!warn_on_missing_data) { 903 IncErrorCount(); 904 msg = message; 905 } else { 906 msg = UnicodeString("[DATA] " + message); 907 } 908 909 if (!no_err_msg) { 910 if ( errCount == 1) { 911 LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time 912 } else { 913 LL_message( msg , TRUE ); 914 } 915 } 916 } 917 918 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) { 919 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { 920 dataerrln(message); 921 } else { 922 errln(message); 923 } 924 } 925 926 /* convenience functions that include sprintf formatting */ 927 void IntlTest::log(const char *fmt, ...) 928 { 929 char buffer[4000]; 930 va_list ap; 931 932 va_start(ap, fmt); 933 /* sprintf it just to make sure that the information is valid */ 934 vsprintf(buffer, fmt, ap); 935 va_end(ap); 936 if( verbose ) { 937 log(UnicodeString(buffer, "")); 938 } 939 } 940 941 void IntlTest::logln(const char *fmt, ...) 942 { 943 char buffer[4000]; 944 va_list ap; 945 946 va_start(ap, fmt); 947 /* sprintf it just to make sure that the information is valid */ 948 vsprintf(buffer, fmt, ap); 949 va_end(ap); 950 if( verbose ) { 951 logln(UnicodeString(buffer, "")); 952 } 953 } 954 955 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...) 956 { 957 char buffer[4000]; 958 va_list ap; 959 960 va_start(ap, fmt); 961 /* sprintf it just to make sure that the information is valid */ 962 vsprintf(buffer, fmt, ap); 963 va_end(ap); 964 return logKnownIssue(ticket, UnicodeString(buffer, "")); 965 } 966 967 UBool IntlTest::logKnownIssue(const char *ticket) { 968 return logKnownIssue(ticket, UnicodeString()); 969 } 970 971 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) { 972 if(noKnownIssues) return FALSE; 973 974 char fullpath[2048]; 975 strcpy(fullpath, basePath); 976 strcat(fullpath, currName); 977 UnicodeString msg2 = msg; 978 UBool firstForTicket = TRUE, firstForWhere = TRUE; 979 knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere); 980 981 msg2 = UNICODE_STRING_SIMPLE("(Known issue #") + 982 UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg; 983 if(firstForTicket || firstForWhere) { 984 infoln(msg2); 985 } else { 986 logln(msg2); 987 } 988 989 return TRUE; 990 } 991 992 /* convenience functions that include sprintf formatting */ 993 void IntlTest::info(const char *fmt, ...) 994 { 995 char buffer[4000]; 996 va_list ap; 997 998 va_start(ap, fmt); 999 /* sprintf it just to make sure that the information is valid */ 1000 vsprintf(buffer, fmt, ap); 1001 va_end(ap); 1002 info(UnicodeString(buffer, "")); 1003 } 1004 1005 void IntlTest::infoln(const char *fmt, ...) 1006 { 1007 char buffer[4000]; 1008 va_list ap; 1009 1010 va_start(ap, fmt); 1011 /* sprintf it just to make sure that the information is valid */ 1012 vsprintf(buffer, fmt, ap); 1013 va_end(ap); 1014 infoln(UnicodeString(buffer, "")); 1015 } 1016 1017 void IntlTest::err(const char *fmt, ...) 1018 { 1019 char buffer[4000]; 1020 va_list ap; 1021 1022 va_start(ap, fmt); 1023 vsprintf(buffer, fmt, ap); 1024 va_end(ap); 1025 err(UnicodeString(buffer, "")); 1026 } 1027 1028 void IntlTest::errln(const char *fmt, ...) 1029 { 1030 char buffer[4000]; 1031 va_list ap; 1032 1033 va_start(ap, fmt); 1034 vsprintf(buffer, fmt, ap); 1035 va_end(ap); 1036 errln(UnicodeString(buffer, "")); 1037 } 1038 1039 void IntlTest::dataerrln(const char *fmt, ...) 1040 { 1041 char buffer[4000]; 1042 va_list ap; 1043 1044 va_start(ap, fmt); 1045 vsprintf(buffer, fmt, ap); 1046 va_end(ap); 1047 dataerrln(UnicodeString(buffer, "")); 1048 } 1049 1050 void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...) 1051 { 1052 char buffer[4000]; 1053 va_list ap; 1054 1055 va_start(ap, fmt); 1056 vsprintf(buffer, fmt, ap); 1057 va_end(ap); 1058 1059 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { 1060 dataerrln(UnicodeString(buffer, "")); 1061 } else { 1062 errln(UnicodeString(buffer, "")); 1063 } 1064 } 1065 1066 void IntlTest::printErrors() 1067 { 1068 IntlTest::LL_message(errorList, TRUE); 1069 } 1070 1071 UBool IntlTest::printKnownIssues() 1072 { 1073 if(knownList != NULL) { 1074 udbg_knownIssue_print(knownList); 1075 udbg_knownIssue_close(knownList); 1076 return TRUE; 1077 } else { 1078 return FALSE; 1079 } 1080 } 1081 1082 void IntlTest::LL_message( UnicodeString message, UBool newline ) 1083 { 1084 // string that starts with a LineFeed character and continues 1085 // with spaces according to the current indentation 1086 static const UChar indentUChars[] = { 1087 '\n', 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 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 1098 }; 1099 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel); 1100 1101 char buffer[30000]; 1102 int32_t length; 1103 1104 // stream out the indentation string first if necessary 1105 length = indent.extract(1, indent.length(), buffer, sizeof(buffer)); 1106 if (length > 0) { 1107 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1108 } 1109 1110 // replace each LineFeed by the indentation string 1111 message.findAndReplace(UnicodeString((UChar)'\n'), indent); 1112 1113 // stream out the message 1114 length = message.extract(0, message.length(), buffer, sizeof(buffer)); 1115 if (length > 0) { 1116 length = length > 30000 ? 30000 : length; 1117 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); 1118 } 1119 1120 if (newline) { 1121 char newLine = '\n'; 1122 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp); 1123 } 1124 1125 // A newline usually flushes the buffer, but 1126 // flush the message just in case of a core dump. 1127 fflush((FILE *)testoutfp); 1128 } 1129 1130 /** 1131 * Print a usage message for this test class. 1132 */ 1133 void IntlTest::usage( void ) 1134 { 1135 UBool save_verbose = setVerbose( TRUE ); 1136 logln("Test names:"); 1137 logln("-----------"); 1138 1139 int32_t index = 0; 1140 const char* name = NULL; 1141 do{ 1142 this->runIndexedTest( index, FALSE, name ); 1143 if (!name) break; 1144 logln(name); 1145 index++; 1146 }while (name && (name[0] != 0)); 1147 setVerbose( save_verbose ); 1148 } 1149 1150 1151 // memory leak reporting software will be able to take advantage of the testsuite 1152 // being run a second time local to a specific method in order to report only actual leaks 1153 UBool 1154 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks 1155 { 1156 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter 1157 strLeak->append(" for verifying purify filter"); 1158 return this->runTest( name, par ); 1159 } 1160 1161 1162 #if UCONFIG_NO_LEGACY_CONVERSION 1163 # define TRY_CNV_1 "iso-8859-1" 1164 # define TRY_CNV_2 "ibm-1208" 1165 #else 1166 # define TRY_CNV_1 "iso-8859-7" 1167 # define TRY_CNV_2 "sjis" 1168 #endif 1169 1170 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS 1171 U_CAPI void unistr_printLengths(); 1172 #endif 1173 1174 int 1175 main(int argc, char* argv[]) 1176 { 1177 UBool syntax = FALSE; 1178 UBool all = FALSE; 1179 UBool verbose = FALSE; 1180 UBool no_err_msg = FALSE; 1181 UBool no_time = FALSE; 1182 UBool quick = TRUE; 1183 UBool name = FALSE; 1184 UBool leaks = FALSE; 1185 UBool utf8 = FALSE; 1186 const char *summary_file = NULL; 1187 UBool warnOnMissingData = FALSE; 1188 UBool defaultDataFound = FALSE; 1189 int32_t threadCount = 1; 1190 UErrorCode errorCode = U_ZERO_ERROR; 1191 UConverter *cnv = NULL; 1192 const char *warnOrErr = "Failure"; 1193 UDate startTime, endTime; 1194 int32_t diffTime; 1195 const char *props[IntlTest::kMaxProps]; 1196 int32_t nProps = 0; 1197 1198 U_MAIN_INIT_ARGS(argc, argv); 1199 1200 startTime = uprv_getRawUTCtime(); 1201 1202 for (int i = 1; i < argc; ++i) { 1203 if (argv[i][0] == '-') { 1204 const char* str = argv[i] + 1; 1205 if (strcmp("verbose", str) == 0 || 1206 strcmp("v", str) == 0) 1207 verbose = TRUE; 1208 else if (strcmp("noerrormsg", str) == 0 || 1209 strcmp("n", str) == 0) 1210 no_err_msg = TRUE; 1211 else if (strcmp("exhaustive", str) == 0 || 1212 strcmp("e", str) == 0) 1213 quick = FALSE; 1214 else if (strcmp("all", str) == 0 || 1215 strcmp("a", str) == 0) 1216 all = TRUE; 1217 else if (strcmp("utf-8", str) == 0 || 1218 strcmp("u", str) == 0) 1219 utf8 = TRUE; 1220 else if (strcmp("noknownissues", str) == 0 || 1221 strcmp("K", str) == 0) 1222 noKnownIssues = TRUE; 1223 else if (strcmp("leaks", str) == 0 || 1224 strcmp("l", str) == 0) 1225 leaks = TRUE; 1226 else if (strcmp("notime", str) == 0 || 1227 strcmp("T", str) == 0) 1228 no_time = TRUE; 1229 else if (strncmp("E", str, 1) == 0) 1230 summary_file = str+1; 1231 else if (strcmp("x", str)==0) { 1232 if(++i>=argc) { 1233 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n"); 1234 syntax = TRUE; 1235 } 1236 if(ctest_xml_setFileName(argv[i])) { /* set the name */ 1237 return 1; /* error */ 1238 } 1239 } else if (strcmp("w", str) == 0) { 1240 warnOnMissingData = TRUE; 1241 warnOrErr = "WARNING"; 1242 } 1243 else if (strncmp("threads:", str, 8) == 0) { 1244 threadCount = atoi(str + 8); 1245 } 1246 else if (strncmp("prop:", str, 5) == 0) { 1247 if (nProps < IntlTest::kMaxProps) { 1248 props[nProps] = str + 5; 1249 } 1250 nProps++; 1251 } 1252 else { 1253 syntax = TRUE; 1254 } 1255 }else{ 1256 name = TRUE; 1257 } 1258 } 1259 1260 if (!all && !name) { 1261 all = TRUE; 1262 } else if (all && name) { 1263 syntax = TRUE; 1264 } 1265 1266 if (syntax) { 1267 fprintf(stdout, 1268 "### Syntax:\n" 1269 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" 1270 "### \n" 1271 "### Options are: verbose (v), all (a), noerrormsg (n), \n" 1272 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n" 1273 "### notime (T), \n" 1274 "### threads:<threadCount> (Mulithreading must first be \n" 1275 "### enabled otherwise this will be ignored. \n" 1276 "### The default thread count is 1.),\n" 1277 "### (Specify either -all (shortcut -a) or a test name). \n" 1278 "### -all will run all of the tests.\n" 1279 "### \n" 1280 "### To get a list of the test names type: intltest LIST \n" 1281 "### To run just the utility tests type: intltest utility \n" 1282 "### \n" 1283 "### Test names can be nested using slashes (\"testA/subtest1\") \n" 1284 "### For example to list the utility tests type: intltest utility/LIST \n" 1285 "### To run just the Locale test type: intltest utility/LocaleTest \n" 1286 "### \n" 1287 "### A parameter can be specified for a test by appending '@' and the value \n" 1288 "### to the testname. \n\n"); 1289 return 1; 1290 } 1291 1292 if (nProps > IntlTest::kMaxProps) { 1293 fprintf(stdout, "### Too many properties. Exiting.\n"); 1294 } 1295 1296 MajorTestLevel major; 1297 major.setVerbose( verbose ); 1298 major.setNoErrMsg( no_err_msg ); 1299 major.setQuick( quick ); 1300 major.setLeaks( leaks ); 1301 major.setThreadCount( threadCount ); 1302 major.setWarnOnMissingData( warnOnMissingData ); 1303 major.setNotime (no_time); 1304 for (int32_t i = 0; i < nProps; i++) { 1305 major.setProperty(props[i]); 1306 } 1307 1308 1309 fprintf(stdout, "-----------------------------------------------\n"); 1310 fprintf(stdout, " IntlTest (C++) Test Suite for \n"); 1311 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); 1312 1313 1314 { 1315 const char *charsetFamily = "Unknown"; 1316 int32_t voidSize = (int32_t)sizeof(void*); 1317 int32_t bits = voidSize * 8; 1318 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) { 1319 charsetFamily="ASCII"; 1320 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) { 1321 charsetFamily="EBCDIC"; 1322 } 1323 fprintf(stdout, 1324 " Bits: %d, Byte order: %s, Chars: %s\n", 1325 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian", 1326 charsetFamily); 1327 } 1328 fprintf(stdout, "-----------------------------------------------\n"); 1329 fprintf(stdout, " Options: \n"); 1330 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); 1331 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); 1332 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); 1333 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); 1334 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); 1335 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off")); 1336 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off")); 1337 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off")); 1338 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); 1339 fprintf(stdout, " Threads : %d\n", threadCount); 1340 for (int32_t i = 0; i < nProps; i++) { 1341 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]); 1342 } 1343 fprintf(stdout, "-----------------------------------------------\n"); 1344 1345 if(utf8) { 1346 ucnv_setDefaultName("utf-8"); 1347 } 1348 /* Check whether ICU will initialize without forcing the build data directory into 1349 * the ICU_DATA path. Success here means either the data dll contains data, or that 1350 * this test program was run with ICU_DATA set externally. Failure of this check 1351 * is normal when ICU data is not packaged into a shared library. 1352 * 1353 * Whether or not this test succeeds, we want to cleanup and reinitialize 1354 * with a data path so that data loading from individual files can be tested. 1355 */ 1356 u_init(&errorCode); 1357 if (U_FAILURE(errorCode)) { 1358 fprintf(stderr, 1359 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n"); 1360 defaultDataFound = FALSE; 1361 } 1362 else { 1363 defaultDataFound = TRUE; 1364 } 1365 u_cleanup(); 1366 if(utf8) { 1367 ucnv_setDefaultName("utf-8"); 1368 } 1369 errorCode = U_ZERO_ERROR; 1370 1371 /* Initialize ICU */ 1372 if (!defaultDataFound) { 1373 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. 1374 } 1375 u_init(&errorCode); 1376 if (U_FAILURE(errorCode)) { 1377 fprintf(stderr, 1378 "#### ERROR! %s: u_init() failed with status = \"%s\".\n" 1379 "*** Check the ICU_DATA environment variable and \n" 1380 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); 1381 if(warnOnMissingData == 0) { 1382 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1383 u_cleanup(); 1384 return 1; 1385 } 1386 } 1387 1388 // initial check for the default converter 1389 errorCode = U_ZERO_ERROR; 1390 cnv = ucnv_open(0, &errorCode); 1391 if(cnv != 0) { 1392 // ok 1393 ucnv_close(cnv); 1394 } else { 1395 fprintf(stdout, 1396 "*** %s! The default converter [%s] cannot be opened.\n" 1397 "*** Check the ICU_DATA environment variable and\n" 1398 "*** check that the data files are present.\n", 1399 warnOrErr, ucnv_getDefaultName()); 1400 if(!warnOnMissingData) { 1401 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1402 return 1; 1403 } 1404 } 1405 1406 // try more data 1407 cnv = ucnv_open(TRY_CNV_2, &errorCode); 1408 if(cnv != 0) { 1409 // ok 1410 ucnv_close(cnv); 1411 } else { 1412 fprintf(stdout, 1413 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" 1414 "*** Check the ICU_DATA environment variable and \n" 1415 "*** check that the data files are present.\n", warnOrErr); 1416 if(!warnOnMissingData) { 1417 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1418 return 1; 1419 } 1420 } 1421 1422 UResourceBundle *rb = ures_open(0, "en", &errorCode); 1423 ures_close(rb); 1424 if(U_FAILURE(errorCode)) { 1425 fprintf(stdout, 1426 "*** %s! The \"en\" locale resource bundle cannot be opened.\n" 1427 "*** Check the ICU_DATA environment variable and \n" 1428 "*** check that the data files are present.\n", warnOrErr); 1429 if(!warnOnMissingData) { 1430 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 1431 return 1; 1432 } 1433 } 1434 1435 Locale originalLocale; // Save the default locale for comparison later on. 1436 1437 if(ctest_xml_init("intltest")) 1438 return 1; 1439 1440 1441 /* TODO: Add option to call u_cleanup and rerun tests. */ 1442 if (all) { 1443 major.runTest(); 1444 if (leaks) { 1445 major.run_phase2( NULL, NULL ); 1446 } 1447 }else{ 1448 for (int i = 1; i < argc; ++i) { 1449 if (argv[i][0] != '-') { 1450 char* name = argv[i]; 1451 fprintf(stdout, "\n=== Handling test: %s: ===\n", name); 1452 1453 char baseName[1024]; 1454 sprintf(baseName, "/%s/", name); 1455 1456 char* parameter = strchr( name, '@' ); 1457 if (parameter) { 1458 *parameter = 0; 1459 parameter += 1; 1460 } 1461 execCount = 0; 1462 UBool res = major.runTest( name, parameter, baseName ); 1463 if (leaks && res) { 1464 major.run_phase2( name, parameter ); 1465 } 1466 if (!res || (execCount <= 0)) { 1467 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name); 1468 } 1469 } else if(!strcmp(argv[i],"-x")) { 1470 i++; 1471 } 1472 } 1473 } 1474 1475 1476 #if !UCONFIG_NO_FORMATTING 1477 CalendarTimeZoneTest::cleanup(); 1478 #endif 1479 1480 free(_testDataPath); 1481 _testDataPath = 0; 1482 1483 Locale lastDefaultLocale; 1484 if (originalLocale != lastDefaultLocale) { 1485 major.errln("FAILURE: A test changed the default locale without resetting it."); 1486 } 1487 1488 fprintf(stdout, "\n--------------------------------------\n"); 1489 if( major.printKnownIssues() ) { 1490 fprintf(stdout, " To run suppressed tests, use the -K option. \n"); 1491 } 1492 if (major.getErrors() == 0) { 1493 /* Call it twice to make sure that the defaults were reset. */ 1494 /* Call it before the OK message to verify proper cleanup. */ 1495 u_cleanup(); 1496 u_cleanup(); 1497 1498 fprintf(stdout, "OK: All tests passed without error.\n"); 1499 1500 if (major.getDataErrors() != 0) { 1501 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n"); 1502 } 1503 }else{ 1504 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors()); 1505 major.printErrors(); 1506 1507 if(summary_file != NULL) { 1508 FILE *summf = fopen(summary_file, "w"); 1509 if( summf != NULL) { 1510 char buf[10000]; 1511 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf)); 1512 fwrite(buf, sizeof(*buf), length, (FILE*)summf); 1513 fclose(summf); 1514 } 1515 } 1516 1517 1518 if (major.getDataErrors() != 0) { 1519 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n" 1520 "\tstock ICU data (i.e some have been added or removed), consider using\n" 1521 "\tthe '-w' option to turn these errors into warnings.\n"); 1522 } 1523 1524 /* Call afterwards to display errors. */ 1525 u_cleanup(); 1526 } 1527 1528 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS 1529 unistr_printLengths(); 1530 #endif 1531 1532 fprintf(stdout, "--------------------------------------\n"); 1533 1534 if (execCount <= 0) { 1535 fprintf(stdout, "***** Not all called tests actually exist! *****\n"); 1536 } 1537 if(!no_time) { 1538 endTime = uprv_getRawUTCtime(); 1539 diffTime = (int32_t)(endTime - startTime); 1540 printf("Elapsed Time: %02d:%02d:%02d.%03d\n", 1541 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), 1542 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), 1543 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), 1544 (int)(diffTime%U_MILLIS_PER_SECOND)); 1545 } 1546 1547 if(ctest_xml_fini()) 1548 return 1; 1549 1550 return major.getErrors(); 1551 } 1552 1553 const char* IntlTest::loadTestData(UErrorCode& err){ 1554 if( _testDataPath == NULL){ 1555 const char* directory=NULL; 1556 UResourceBundle* test =NULL; 1557 char* tdpath=NULL; 1558 const char* tdrelativepath; 1559 1560 #if defined (U_TOPBUILDDIR) 1561 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1562 directory = U_TOPBUILDDIR; 1563 #else 1564 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 1565 directory = pathToDataDirectory(); 1566 #endif 1567 1568 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100)); 1569 1570 1571 /* u_getDataDirectory shoul return \source\data ... set the 1572 * directory to ..\source\data\..\test\testdata\out\testdata 1573 */ 1574 strcpy(tdpath, directory); 1575 strcat(tdpath, tdrelativepath); 1576 strcat(tdpath,"testdata"); 1577 1578 test=ures_open(tdpath, "testtypes", &err); 1579 1580 if(U_FAILURE(err)){ 1581 err = U_FILE_ACCESS_ERROR; 1582 it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); 1583 return ""; 1584 } 1585 ures_close(test); 1586 _testDataPath = tdpath; 1587 return _testDataPath; 1588 } 1589 return _testDataPath; 1590 } 1591 1592 const char* IntlTest::getTestDataPath(UErrorCode& err) { 1593 return loadTestData(err); 1594 } 1595 1596 /* Returns the path to icu/source/test/testdata/ */ 1597 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) { 1598 const char *srcDataDir = NULL; 1599 #ifdef U_TOPSRCDIR 1600 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1601 #else 1602 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1603 FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r"); 1604 if (f) { 1605 /* We're in icu/source/test/intltest/ */ 1606 fclose(f); 1607 } 1608 else { 1609 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */ 1610 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING 1611 "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING; 1612 } 1613 #endif 1614 return srcDataDir; 1615 } 1616 1617 char *IntlTest::getUnidataPath(char path[]) { 1618 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt") 1619 1620 // Look inside ICU_DATA first. 1621 strcpy(path, pathToDataDirectory()); 1622 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt"); 1623 FILE *f = fopen(path, "r"); 1624 if(f != NULL) { 1625 fclose(f); 1626 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename. 1627 return path; 1628 } 1629 1630 // As a fallback, try to guess where the source data was located 1631 // at the time ICU was built, and look there. 1632 # ifdef U_TOPSRCDIR 1633 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data"); 1634 # else 1635 UErrorCode errorCode = U_ZERO_ERROR; 1636 const char *testDataPath = loadTestData(errorCode); 1637 if(U_FAILURE(errorCode)) { 1638 it_errln(UnicodeString( 1639 "unable to find path to source/data/unidata/ and loadTestData() failed: ") + 1640 u_errorName(errorCode)); 1641 return NULL; 1642 } 1643 strcpy(path, testDataPath); 1644 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." 1645 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." 1646 U_FILE_SEP_STRING "data"); 1647 # endif 1648 strcat(path, U_FILE_SEP_STRING); 1649 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt"); 1650 f = fopen(path, "r"); 1651 if(f != NULL) { 1652 fclose(f); 1653 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename. 1654 return path; 1655 } 1656 return NULL; 1657 } 1658 1659 const char* IntlTest::fgDataDir = NULL; 1660 1661 /* returns the path to icu/source/data */ 1662 const char * IntlTest::pathToDataDirectory() 1663 { 1664 1665 if(fgDataDir != NULL) { 1666 return fgDataDir; 1667 } 1668 1669 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst 1670 // to point to the top of the build hierarchy, which may or 1671 // may not be the same as the source directory, depending on 1672 // the configure options used. At any rate, 1673 // set the data path to the built data from this directory. 1674 // The value is complete with quotes, so it can be used 1675 // as-is as a string constant. 1676 */ 1677 #if defined (U_TOPSRCDIR) 1678 { 1679 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1680 } 1681 #else 1682 1683 /* On Windows, the file name obtained from __FILE__ includes a full path. 1684 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 1685 * Change to "wherever\icu\source\data" 1686 */ 1687 { 1688 static char p[sizeof(__FILE__) + 10]; 1689 char *pBackSlash; 1690 int i; 1691 1692 strcpy(p, __FILE__); 1693 /* We want to back over three '\' chars. */ 1694 /* Only Windows should end up here, so looking for '\' is safe. */ 1695 for (i=1; i<=3; i++) { 1696 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 1697 if (pBackSlash != NULL) { 1698 *pBackSlash = 0; /* Truncate the string at the '\' */ 1699 } 1700 } 1701 1702 if (pBackSlash != NULL) { 1703 /* We found and truncated three names from the path. 1704 * Now append "source\data" and set the environment 1705 */ 1706 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); 1707 fgDataDir = p; 1708 } 1709 else { 1710 /* __FILE__ on MSVC7 does not contain the directory */ 1711 FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 1712 if (file) { 1713 fclose(file); 1714 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1715 } 1716 else { 1717 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 1718 } 1719 } 1720 } 1721 #endif 1722 1723 return fgDataDir; 1724 1725 } 1726 1727 /* 1728 * This is a variant of cintltst/ccolltst.c:CharsToUChars(). 1729 * It converts an invariant-character string into a UnicodeString, with 1730 * unescaping \u sequences. 1731 */ 1732 UnicodeString CharsToUnicodeString(const char* chars){ 1733 return UnicodeString(chars, -1, US_INV).unescape(); 1734 } 1735 1736 UnicodeString ctou(const char* chars) { 1737 return CharsToUnicodeString(chars); 1738 } 1739 1740 #define RAND_M (714025) 1741 #define RAND_IA (1366) 1742 #define RAND_IC (150889) 1743 1744 static int32_t RAND_SEED; 1745 1746 /** 1747 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use 1748 * with care: Does not return all possible values; returns one of 1749 * 714,025 values, uniformly spaced. However, the period is 1750 * effectively infinite. See: Numerical Recipes, section 7.1. 1751 * 1752 * @param seedp pointer to seed. Set *seedp to any negative value 1753 * to restart the sequence. 1754 */ 1755 float IntlTest::random(int32_t* seedp) { 1756 static int32_t iy, ir[98]; 1757 static UBool first=TRUE; 1758 int32_t j; 1759 if (*seedp < 0 || first) { 1760 first = FALSE; 1761 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp); 1762 for (j=1;j<=97;++j) { 1763 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1764 ir[j]=(*seedp); 1765 } 1766 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1767 iy=(*seedp); 1768 } 1769 j=(int32_t)(1 + 97.0*iy/RAND_M); 1770 U_ASSERT(j>=1 && j<=97); 1771 iy=ir[j]; 1772 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; 1773 ir[j]=(*seedp); 1774 return (float) iy/RAND_M; 1775 } 1776 1777 /** 1778 * Convenience method using a global seed. 1779 */ 1780 float IntlTest::random() { 1781 return random(&RAND_SEED); 1782 } 1783 1784 static inline UChar toHex(int32_t i) { 1785 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); 1786 } 1787 1788 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) { 1789 for (int32_t i=0; i<s.length(); ++i) { 1790 UChar c = s[i]; 1791 if (c <= (UChar)0x7F) { 1792 result += c; 1793 } else { 1794 result += (UChar)0x5c; 1795 result += (UChar)0x75; 1796 result += toHex((c >> 12) & 0xF); 1797 result += toHex((c >> 8) & 0xF); 1798 result += toHex((c >> 4) & 0xF); 1799 result += toHex( c & 0xF); 1800 } 1801 } 1802 return result; 1803 } 1804 1805 #define VERBOSE_ASSERTIONS 1806 1807 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) { 1808 if (file != NULL) { 1809 if (!condition) { 1810 if (possibleDataError) { 1811 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1812 } else { 1813 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); 1814 } 1815 } else if (!quiet) { 1816 logln("%s:%d: Ok: %s", file, line, message); 1817 } 1818 } else { 1819 if (!condition) { 1820 if (possibleDataError) { 1821 dataerrln("FAIL: assertTrue() failed: %s", message); 1822 } else { 1823 errln("FAIL: assertTrue() failed: %s", message); 1824 } 1825 } else if (!quiet) { 1826 logln("Ok: %s", message); 1827 } 1828 1829 } 1830 return condition; 1831 } 1832 1833 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { 1834 if (condition) { 1835 errln("FAIL: assertFalse() failed: %s", message); 1836 } else if (!quiet) { 1837 logln("Ok: %s", message); 1838 } 1839 return !condition; 1840 } 1841 1842 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) { 1843 if( file==NULL ) { 1844 file = ""; // prevent failure if no file given 1845 } 1846 if (U_FAILURE(ec)) { 1847 if (possibleDataError) { 1848 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1849 } else { 1850 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec)); 1851 } 1852 return FALSE; 1853 } else { 1854 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec)); 1855 } 1856 return TRUE; 1857 } 1858 1859 UBool IntlTest::assertEquals(const char* message, 1860 const UnicodeString& expected, 1861 const UnicodeString& actual, 1862 UBool possibleDataError) { 1863 if (expected != actual) { 1864 if (possibleDataError) { 1865 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1866 prettify(actual) + 1867 "; expected " + prettify(expected)); 1868 } else { 1869 errln((UnicodeString)"FAIL: " + message + "; got " + 1870 prettify(actual) + 1871 "; expected " + prettify(expected)); 1872 } 1873 return FALSE; 1874 } 1875 #ifdef VERBOSE_ASSERTIONS 1876 else { 1877 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual)); 1878 } 1879 #endif 1880 return TRUE; 1881 } 1882 1883 UBool IntlTest::assertEquals(const char* message, 1884 const char* expected, 1885 const char* actual) { 1886 if (uprv_strcmp(expected, actual) != 0) { 1887 errln((UnicodeString)"FAIL: " + message + "; got \"" + 1888 actual + 1889 "\"; expected \"" + expected + "\""); 1890 return FALSE; 1891 } 1892 #ifdef VERBOSE_ASSERTIONS 1893 else { 1894 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\""); 1895 } 1896 #endif 1897 return TRUE; 1898 } 1899 1900 UBool IntlTest::assertEquals(const char* message, 1901 int32_t expected, 1902 int32_t actual) { 1903 if (expected != actual) { 1904 errln((UnicodeString)"FAIL: " + message + "; got " + 1905 actual + "=0x" + toHex(actual) + 1906 "; expected " + expected + "=0x" + toHex(expected)); 1907 return FALSE; 1908 } 1909 #ifdef VERBOSE_ASSERTIONS 1910 else { 1911 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual)); 1912 } 1913 #endif 1914 return TRUE; 1915 } 1916 1917 UBool IntlTest::assertEquals(const char* message, 1918 int64_t expected, 1919 int64_t actual) { 1920 if (expected != actual) { 1921 errln((UnicodeString)"FAIL: " + message + "; got int64 " + 1922 Int64ToUnicodeString(actual) + 1923 "; expected " + Int64ToUnicodeString(expected) ); 1924 return FALSE; 1925 } 1926 #ifdef VERBOSE_ASSERTIONS 1927 else { 1928 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual)); 1929 } 1930 #endif 1931 return TRUE; 1932 } 1933 1934 UBool IntlTest::assertEquals(const char* message, 1935 double expected, 1936 double actual) { 1937 if (expected != actual) { 1938 errln((UnicodeString)"FAIL: " + message + "; got " + 1939 actual + 1940 "; expected " + expected); 1941 return FALSE; 1942 } 1943 #ifdef VERBOSE_ASSERTIONS 1944 else { 1945 logln((UnicodeString)"Ok: " + message + "; got " + actual); 1946 } 1947 #endif 1948 return TRUE; 1949 } 1950 1951 1952 UBool IntlTest::assertEquals(const char* message, 1953 UBool expected, 1954 UBool actual) { 1955 if (expected != actual) { 1956 errln((UnicodeString)"FAIL: " + message + "; got " + 1957 toString(actual) + 1958 "; expected " + toString(expected)); 1959 return FALSE; 1960 } 1961 #ifdef VERBOSE_ASSERTIONS 1962 else { 1963 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1964 } 1965 #endif 1966 return TRUE; 1967 } 1968 1969 #if !UCONFIG_NO_FORMATTING 1970 UBool IntlTest::assertEquals(const char* message, 1971 const Formattable& expected, 1972 const Formattable& actual, 1973 UBool possibleDataError) { 1974 if (expected != actual) { 1975 if (possibleDataError) { 1976 dataerrln((UnicodeString)"FAIL: " + message + "; got " + 1977 toString(actual) + 1978 "; expected " + toString(expected)); 1979 } else { 1980 errln((UnicodeString)"FAIL: " + message + "; got " + 1981 toString(actual) + 1982 "; expected " + toString(expected)); 1983 } 1984 return FALSE; 1985 } 1986 #ifdef VERBOSE_ASSERTIONS 1987 else { 1988 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); 1989 } 1990 #endif 1991 return TRUE; 1992 } 1993 #endif 1994 1995 static char ASSERT_BUF[256]; 1996 1997 static const char* extractToAssertBuf(const UnicodeString& message) { 1998 UnicodeString buf; 1999 escape(message, buf); 2000 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0); 2001 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0; 2002 return ASSERT_BUF; 2003 } 2004 2005 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) { 2006 return assertTrue(extractToAssertBuf(message), condition, quiet); 2007 } 2008 2009 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) { 2010 return assertFalse(extractToAssertBuf(message), condition, quiet); 2011 } 2012 2013 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) { 2014 return assertSuccess(extractToAssertBuf(message), ec); 2015 } 2016 2017 UBool IntlTest::assertEquals(const UnicodeString& message, 2018 const UnicodeString& expected, 2019 const UnicodeString& actual, 2020 UBool possibleDataError) { 2021 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError); 2022 } 2023 2024 UBool IntlTest::assertEquals(const UnicodeString& message, 2025 const char* expected, 2026 const char* actual) { 2027 return assertEquals(extractToAssertBuf(message), expected, actual); 2028 } 2029 UBool IntlTest::assertEquals(const UnicodeString& message, 2030 UBool expected, 2031 UBool actual) { 2032 return assertEquals(extractToAssertBuf(message), expected, actual); 2033 } 2034 UBool IntlTest::assertEquals(const UnicodeString& message, 2035 int32_t expected, 2036 int32_t actual) { 2037 return assertEquals(extractToAssertBuf(message), expected, actual); 2038 } 2039 UBool IntlTest::assertEquals(const UnicodeString& message, 2040 int64_t expected, 2041 int64_t actual) { 2042 return assertEquals(extractToAssertBuf(message), expected, actual); 2043 } 2044 2045 #if !UCONFIG_NO_FORMATTING 2046 UBool IntlTest::assertEquals(const UnicodeString& message, 2047 const Formattable& expected, 2048 const Formattable& actual) { 2049 return assertEquals(extractToAssertBuf(message), expected, actual); 2050 } 2051 #endif 2052 2053 void IntlTest::setProperty(const char* propline) { 2054 if (numProps < kMaxProps) { 2055 proplines[numProps] = propline; 2056 } 2057 numProps++; 2058 } 2059 2060 const char* IntlTest::getProperty(const char* prop) { 2061 const char* val = NULL; 2062 for (int32_t i = 0; i < numProps; i++) { 2063 int32_t plen = uprv_strlen(prop); 2064 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1 2065 && proplines[i][plen] == '=' 2066 && uprv_strncmp(proplines[i], prop, plen) == 0) { 2067 val = &(proplines[i][plen+1]); 2068 break; 2069 } 2070 } 2071 return val; 2072 } 2073 2074 /* 2075 * Hey, Emacs, please set the following: 2076 * 2077 * Local Variables: 2078 * indent-tabs-mode: nil 2079 * End: 2080 * 2081 */ 2082