1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2010, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 /******************************************************************************** 7 * 8 * File CINTLTST.C 9 * 10 * Modification History: 11 * Name Description 12 * Madhu Katragadda Creation 13 ********************************************************************************* 14 */ 15 16 /*The main root for C API tests*/ 17 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include "unicode/utypes.h" 22 #include "unicode/putil.h" 23 #include "cstring.h" 24 #include "cintltst.h" 25 #include "umutex.h" 26 #include "uassert.h" 27 #include "cmemory.h" 28 #include "unicode/uchar.h" 29 #include "unicode/ustring.h" 30 #include "unicode/ucnv.h" 31 #include "unicode/ures.h" 32 #include "unicode/uclean.h" 33 #include "unicode/ucal.h" 34 #include "uoptions.h" 35 #include "putilimp.h" /* for uprv_getRawUTCtime() */ 36 #ifdef URES_DEBUG 37 #include "uresimp.h" /* for ures_dumpCacheContents() */ 38 #endif 39 40 #ifdef XP_MAC_CONSOLE 41 # include <console.h> 42 #endif 43 44 #define CTST_LEAK_CHECK 1 45 #ifdef CTST_LEAK_CHECK 46 U_CFUNC void ctst_freeAll(void); 47 #endif 48 49 static char* _testDataPath=NULL; 50 51 /* 52 * Forward Declarations 53 */ 54 void ctest_setICU_DATA(void); 55 56 57 58 #if UCONFIG_NO_LEGACY_CONVERSION 59 # define TRY_CNV_1 "iso-8859-1" 60 # define TRY_CNV_2 "ibm-1208" 61 #else 62 # define TRY_CNV_1 "iso-8859-7" 63 # define TRY_CNV_2 "sjis" 64 #endif 65 66 static int gOrigArgc; 67 static const char* const * gOrigArgv; 68 69 int main(int argc, const char* const argv[]) 70 { 71 int nerrors = 0; 72 UBool defaultDataFound; 73 TestNode *root; 74 const char *warnOrErr = "Failure"; 75 UDate startTime, endTime; 76 int32_t diffTime; 77 78 /* initial check for the default converter */ 79 UErrorCode errorCode = U_ZERO_ERROR; 80 UResourceBundle *rb; 81 UConverter *cnv; 82 83 U_MAIN_INIT_ARGS(argc, argv); 84 85 startTime = uprv_getRawUTCtime(); 86 87 gOrigArgc = argc; 88 gOrigArgv = argv; 89 if (!initArgs(argc, argv, NULL, NULL)) { 90 /* Error already displayed. */ 91 return -1; 92 } 93 94 /* Check whether ICU will initialize without forcing the build data directory into 95 * the ICU_DATA path. Success here means either the data dll contains data, or that 96 * this test program was run with ICU_DATA set externally. Failure of this check 97 * is normal when ICU data is not packaged into a shared library. 98 * 99 * Whether or not this test succeeds, we want to cleanup and reinitialize 100 * with a data path so that data loading from individual files can be tested. 101 */ 102 defaultDataFound = TRUE; 103 u_init(&errorCode); 104 if (U_FAILURE(errorCode)) { 105 fprintf(stderr, 106 "#### Note: ICU Init without build-specific setDataDirectory() failed. %s\n", u_errorName(errorCode)); 107 defaultDataFound = FALSE; 108 } 109 u_cleanup(); 110 #ifdef URES_DEBUG 111 fprintf(stderr, "After initial u_cleanup: RB cache %s empty.\n", ures_dumpCacheContents()?"WAS NOT":"was"); 112 #endif 113 114 while (getTestOption(REPEAT_TESTS_OPTION) > 0) { /* Loop runs once per complete execution of the tests 115 * used for -r (repeat) test option. */ 116 if (!initArgs(argc, argv, NULL, NULL)) { 117 /* Error already displayed. */ 118 return -1; 119 } 120 errorCode = U_ZERO_ERROR; 121 122 /* Initialize ICU */ 123 if (!defaultDataFound) { 124 ctest_setICU_DATA(); /* u_setDataDirectory() must happen Before u_init() */ 125 } 126 u_init(&errorCode); 127 if (U_FAILURE(errorCode)) { 128 fprintf(stderr, 129 "#### ERROR! %s: u_init() failed with status = \"%s\".\n" 130 "*** Check the ICU_DATA environment variable and \n" 131 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); 132 if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { 133 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 134 u_cleanup(); 135 return 1; 136 } 137 } 138 139 140 141 /* try more data */ 142 cnv = ucnv_open(TRY_CNV_2, &errorCode); 143 if(cnv != 0) { 144 /* ok */ 145 ucnv_close(cnv); 146 } else { 147 fprintf(stderr, 148 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" 149 "*** Check the ICU_DATA environment variable and \n" 150 "*** check that the data files are present.\n", warnOrErr); 151 if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { 152 fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 153 u_cleanup(); 154 return 1; 155 } 156 } 157 158 rb = ures_open(NULL, "en", &errorCode); 159 if(U_SUCCESS(errorCode)) { 160 /* ok */ 161 ures_close(rb); 162 } else { 163 fprintf(stderr, 164 "*** %s! The \"en\" locale resource bundle cannot be opened.\n" 165 "*** Check the ICU_DATA environment variable and \n" 166 "*** check that the data files are present.\n", warnOrErr); 167 if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { 168 fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); 169 u_cleanup(); 170 return 1; 171 } 172 } 173 174 errorCode = U_ZERO_ERROR; 175 rb = ures_open(NULL, NULL, &errorCode); 176 if(U_SUCCESS(errorCode)) { 177 /* ok */ 178 if (errorCode == U_USING_DEFAULT_WARNING || errorCode == U_USING_FALLBACK_WARNING) { 179 fprintf(stderr, 180 "#### Note: The default locale %s is not available\n", uloc_getDefault()); 181 } 182 ures_close(rb); 183 } else { 184 fprintf(stderr, 185 "*** %s! Can not open a resource bundle for the default locale %s\n", warnOrErr, uloc_getDefault()); 186 if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { 187 fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n" 188 "*** purposely removed, to continue test anyway.\n"); 189 u_cleanup(); 190 return 1; 191 } 192 } 193 fprintf(stdout, "Default locale for this run is %s\n", uloc_getDefault()); 194 195 /* Build a tree of all tests. 196 * Subsequently will be used to find / iterate the tests to run */ 197 root = NULL; 198 addAllTests(&root); 199 200 /* Tests acutally run HERE. TODO: separate command line option parsing & setting from test execution!! */ 201 nerrors = runTestRequest(root, argc, argv); 202 203 setTestOption(REPEAT_TESTS_OPTION, DECREMENT_OPTION_VALUE); 204 if (getTestOption(REPEAT_TESTS_OPTION) > 0) { 205 printf("Repeating tests %d more time(s)\n", getTestOption(REPEAT_TESTS_OPTION)); 206 } 207 cleanUpTestTree(root); 208 209 #ifdef CTST_LEAK_CHECK 210 ctst_freeAll(); 211 /* To check for leaks */ 212 u_cleanup(); /* nuke the hashtable.. so that any still-open cnvs are leaked */ 213 #ifdef URES_DEBUG 214 if(ures_dumpCacheContents()) { 215 fprintf(stderr, "Error: After final u_cleanup, RB cache was not empty.\n"); 216 nerrors++; 217 } else { 218 fprintf(stderr,"OK: After final u_cleanup, RB cache was empty.\n"); 219 } 220 #endif 221 #endif 222 223 } /* End of loop that repeats the entire test, if requested. (Normally doesn't loop) */ 224 225 if (ALLOCATION_COUNT > 0) { 226 fprintf(stderr, "There were %d blocks leaked!\n", ALLOCATION_COUNT); 227 nerrors++; 228 } 229 endTime = uprv_getRawUTCtime(); 230 diffTime = (int32_t)(endTime - startTime); 231 printf("Elapsed Time: %02d:%02d:%02d.%03d\n", 232 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), 233 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), 234 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), 235 (int)(diffTime%U_MILLIS_PER_SECOND)); 236 237 return nerrors ? 1 : 0; 238 } 239 240 /* 241 static void ctest_appendToDataDirectory(const char *toAppend) 242 { 243 const char *oldPath =""; 244 char newBuf [1024]; 245 char *newPath = newBuf; 246 int32_t oldLen; 247 int32_t newLen; 248 249 if((toAppend == NULL) || (*toAppend == 0)) { 250 return; 251 } 252 253 oldPath = u_getDataDirectory(); 254 if( (oldPath==NULL) || (*oldPath == 0)) { 255 u_setDataDirectory(toAppend); 256 } else { 257 oldLen = strlen(oldPath); 258 newLen = strlen(toAppend)+1+oldLen; 259 260 if(newLen > 1022) 261 { 262 newPath = (char *)ctst_malloc(newLen); 263 } 264 265 strcpy(newPath, oldPath); 266 strcpy(newPath+oldLen, U_PATH_SEP_STRING); 267 strcpy(newPath+oldLen+1, toAppend); 268 269 u_setDataDirectory(newPath); 270 271 if(newPath != newBuf) 272 { 273 free(newPath); 274 } 275 } 276 } 277 */ 278 279 /* returns the path to icu/source/data */ 280 const char * ctest_dataSrcDir() 281 { 282 static const char *dataSrcDir = NULL; 283 284 if(dataSrcDir) { 285 return dataSrcDir; 286 } 287 288 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst 289 // to point to the top of the build hierarchy, which may or 290 // may not be the same as the source directory, depending on 291 // the configure options used. At any rate, 292 // set the data path to the built data from this directory. 293 // The value is complete with quotes, so it can be used 294 // as-is as a string constant. 295 */ 296 #if defined (U_TOPSRCDIR) 297 { 298 dataSrcDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 299 } 300 #else 301 302 /* On Windows, the file name obtained from __FILE__ includes a full path. 303 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 304 * Change to "wherever\icu\source\data" 305 */ 306 { 307 static char p[sizeof(__FILE__) + 20]; 308 char *pBackSlash; 309 int i; 310 311 strcpy(p, __FILE__); 312 /* We want to back over three '\' chars. */ 313 /* Only Windows should end up here, so looking for '\' is safe. */ 314 for (i=1; i<=3; i++) { 315 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 316 if (pBackSlash != NULL) { 317 *pBackSlash = 0; /* Truncate the string at the '\' */ 318 } 319 } 320 321 if (pBackSlash != NULL) { 322 /* We found and truncated three names from the path. 323 * Now append "source\data" and set the environment 324 */ 325 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); 326 dataSrcDir = p; 327 } 328 else { 329 /* __FILE__ on MSVC7 does not contain the directory */ 330 FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 331 if (file) { 332 fclose(file); 333 dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 334 } 335 else { 336 dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; 337 } 338 } 339 } 340 #endif 341 342 return dataSrcDir; 343 344 } 345 346 /* returns the path to icu/source/data/out */ 347 const char *ctest_dataOutDir() 348 { 349 static const char *dataOutDir = NULL; 350 351 if(dataOutDir) { 352 return dataOutDir; 353 } 354 355 /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst 356 // to point to the top of the build hierarchy, which may or 357 // may not be the same as the source directory, depending on 358 // the configure options used. At any rate, 359 // set the data path to the built data from this directory. 360 // The value is complete with quotes, so it can be used 361 // as-is as a string constant. 362 */ 363 #if defined (U_TOPBUILDDIR) 364 { 365 dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; 366 } 367 #else 368 369 /* On Windows, the file name obtained from __FILE__ includes a full path. 370 * This file is "wherever\icu\source\test\cintltst\cintltst.c" 371 * Change to "wherever\icu\source\data" 372 */ 373 { 374 static char p[sizeof(__FILE__) + 20]; 375 char *pBackSlash; 376 int i; 377 378 strcpy(p, __FILE__); 379 /* We want to back over three '\' chars. */ 380 /* Only Windows should end up here, so looking for '\' is safe. */ 381 for (i=1; i<=3; i++) { 382 pBackSlash = strrchr(p, U_FILE_SEP_CHAR); 383 if (pBackSlash != NULL) { 384 *pBackSlash = 0; /* Truncate the string at the '\' */ 385 } 386 } 387 388 if (pBackSlash != NULL) { 389 /* We found and truncated three names from the path. 390 * Now append "source\data" and set the environment 391 */ 392 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); 393 dataOutDir = p; 394 } 395 else { 396 /* __FILE__ on MSVC7 does not contain the directory */ 397 FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); 398 if (file) { 399 fclose(file); 400 dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 401 } 402 else { 403 dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; 404 } 405 } 406 } 407 #endif 408 409 return dataOutDir; 410 } 411 412 /* ctest_setICU_DATA - if the ICU_DATA environment variable is not already 413 * set, try to deduce the directory in which ICU was built, 414 * and set ICU_DATA to "icu/source/data" in that location. 415 * The intent is to allow the tests to have a good chance 416 * of running without requiring that the user manually set 417 * ICU_DATA. Common data isn't a problem, since it is 418 * picked up via a static (build time) reference, but the 419 * tests dynamically load some data. 420 */ 421 void ctest_setICU_DATA() { 422 423 /* No location for the data dir was identifiable. 424 * Add other fallbacks for the test data location here if the need arises 425 */ 426 if (getenv("ICU_DATA") == NULL) { 427 /* If ICU_DATA isn't set, set it to the usual location */ 428 u_setDataDirectory(ctest_dataOutDir()); 429 } 430 } 431 432 /* These tests do cleanup and reinitialize ICU in the course of their operation. 433 * The ICU data directory must be preserved across these operations. 434 * Here is a helper function to assist with that. 435 */ 436 static char *safeGetICUDataDirectory() { 437 const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */ 438 char *retStr = NULL; 439 if (dataDir != NULL) { 440 retStr = (char *)malloc(strlen(dataDir)+1); 441 strcpy(retStr, dataDir); 442 } 443 return retStr; 444 } 445 446 UBool ctest_resetICU() { 447 UErrorCode status = U_ZERO_ERROR; 448 char *dataDir = safeGetICUDataDirectory(); 449 450 u_cleanup(); 451 if (!initArgs(gOrigArgc, gOrigArgv, NULL, NULL)) { 452 /* Error already displayed. */ 453 return FALSE; 454 } 455 u_setDataDirectory(dataDir); 456 free(dataDir); 457 u_init(&status); 458 if (U_FAILURE(status)) { 459 log_err_status(status, "u_init failed with %s\n", u_errorName(status)); 460 return FALSE; 461 } 462 return TRUE; 463 } 464 465 UChar* CharsToUChars(const char* str) { 466 /* Might be faster to just use uprv_strlen() as the preflight len - liu */ 467 int32_t len = u_unescape(str, 0, 0); /* preflight */ 468 /* Do NOT use malloc() - we are supposed to be acting like user code! */ 469 UChar *buf = (UChar*) malloc(sizeof(UChar) * (len + 1)); 470 u_unescape(str, buf, len + 1); 471 return buf; 472 } 473 474 char *austrdup(const UChar* unichars) 475 { 476 int length; 477 char *newString; 478 479 length = u_strlen ( unichars ); 480 /*newString = (char*)malloc ( sizeof( char ) * 4 * ( length + 1 ) );*/ /* this leaks for now */ 481 newString = (char*)ctst_malloc ( sizeof( char ) * 4 * ( length + 1 ) ); /* this shouldn't */ 482 483 if ( newString == NULL ) 484 return NULL; 485 486 u_austrcpy ( newString, unichars ); 487 488 return newString; 489 } 490 491 char *aescstrdup(const UChar* unichars,int32_t length){ 492 char *newString,*targetLimit,*target; 493 UConverterFromUCallback cb; 494 const void *p; 495 UErrorCode errorCode = U_ZERO_ERROR; 496 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY 497 # ifdef OS390 498 static const char convName[] = "ibm-1047"; 499 # else 500 static const char convName[] = "ibm-37"; 501 # endif 502 #else 503 static const char convName[] = "US-ASCII"; 504 #endif 505 UConverter* conv = ucnv_open(convName, &errorCode); 506 if(length==-1){ 507 length = u_strlen( unichars); 508 } 509 newString = (char*)ctst_malloc ( sizeof(char) * 8 * (length +1)); 510 target = newString; 511 targetLimit = newString+sizeof(char) * 8 * (length +1); 512 ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_C, &cb, &p, &errorCode); 513 ucnv_fromUnicode(conv,&target,targetLimit, &unichars, (UChar*)(unichars+length),NULL,TRUE,&errorCode); 514 ucnv_close(conv); 515 *target = '\0'; 516 return newString; 517 } 518 519 const char* loadTestData(UErrorCode* err){ 520 if( _testDataPath == NULL){ 521 const char* directory=NULL; 522 UResourceBundle* test =NULL; 523 char* tdpath=NULL; 524 const char* tdrelativepath; 525 #if defined (U_TOPBUILDDIR) 526 tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; 527 directory = U_TOPBUILDDIR; 528 #else 529 tdrelativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; 530 directory= ctest_dataOutDir(); 531 #endif 532 533 tdpath = (char*) ctst_malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 10)); 534 535 536 /* u_getDataDirectory shoul return \source\data ... set the 537 * directory to ..\source\data\..\test\testdata\out\testdata 538 * 539 * Fallback: When Memory mapped file is built 540 * ..\source\data\out\..\..\test\testdata\out\testdata 541 */ 542 strcpy(tdpath, directory); 543 strcat(tdpath, tdrelativepath); 544 strcat(tdpath,"testdata"); 545 546 547 test=ures_open(tdpath, "testtypes", err); 548 549 /* Fall back did not succeed either so return */ 550 if(U_FAILURE(*err)){ 551 *err = U_FILE_ACCESS_ERROR; 552 log_data_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(*err)); 553 return ""; 554 } 555 ures_close(test); 556 _testDataPath = tdpath; 557 return _testDataPath; 558 } 559 return _testDataPath; 560 } 561 562 #define CTEST_MAX_TIMEZONE_SIZE 256 563 static UChar gOriginalTimeZone[CTEST_MAX_TIMEZONE_SIZE] = {0}; 564 565 /** 566 * Call this once to get a consistent timezone. Use ctest_resetTimeZone to set it back to the original value. 567 * @param optionalTimeZone Set this to a requested timezone. 568 * Set to NULL to use the standard test timezone (Pacific Time) 569 */ 570 U_CFUNC void ctest_setTimeZone(const char *optionalTimeZone, UErrorCode *status) { 571 #if !UCONFIG_NO_FORMATTING 572 UChar zoneID[CTEST_MAX_TIMEZONE_SIZE]; 573 574 if (optionalTimeZone == NULL) { 575 optionalTimeZone = "America/Los_Angeles"; 576 } 577 if (gOriginalTimeZone[0]) { 578 log_data_err("*** Error: time zone saved twice. New value will be %s (Are you missing data?)\n", 579 optionalTimeZone); 580 } 581 ucal_getDefaultTimeZone(gOriginalTimeZone, CTEST_MAX_TIMEZONE_SIZE, status); 582 if (U_FAILURE(*status)) { 583 log_err("*** Error: Failed to save default time zone: %s\n", 584 u_errorName(*status)); 585 *status = U_ZERO_ERROR; 586 } 587 588 u_uastrncpy(zoneID, optionalTimeZone, CTEST_MAX_TIMEZONE_SIZE-1); 589 zoneID[CTEST_MAX_TIMEZONE_SIZE-1] = 0; 590 ucal_setDefaultTimeZone(zoneID, status); 591 if (U_FAILURE(*status)) { 592 log_err("*** Error: Failed to set default time zone to \"%s\": %s\n", 593 optionalTimeZone, u_errorName(*status)); 594 } 595 #endif 596 } 597 598 /** 599 * Call this once get back the original timezone 600 */ 601 U_CFUNC void ctest_resetTimeZone(void) { 602 #if !UCONFIG_NO_FORMATTING 603 UErrorCode status = U_ZERO_ERROR; 604 605 ucal_setDefaultTimeZone(gOriginalTimeZone, &status); 606 if (U_FAILURE(status)) { 607 log_err("*** Error: Failed to reset default time zone: %s\n", 608 u_errorName(status)); 609 } 610 /* Set to an empty state */ 611 gOriginalTimeZone[0] = 0; 612 #endif 613 } 614 615 #define CTST_MAX_ALLOC 8192 616 /* Array used as a queue */ 617 static void * ctst_allocated_stuff[CTST_MAX_ALLOC] = {0}; 618 static int ctst_allocated = 0; 619 static UBool ctst_free = FALSE; 620 621 void *ctst_malloc(size_t size) { 622 if(ctst_allocated >= CTST_MAX_ALLOC - 1) { 623 ctst_allocated = 0; 624 ctst_free = TRUE; 625 } 626 if(ctst_allocated_stuff[ctst_allocated]) { 627 free(ctst_allocated_stuff[ctst_allocated]); 628 } 629 return ctst_allocated_stuff[ctst_allocated++] = malloc(size); 630 } 631 632 #ifdef CTST_LEAK_CHECK 633 void ctst_freeAll() { 634 int i; 635 if(ctst_free == 0) { 636 for(i=0; i<ctst_allocated; i++) { 637 free(ctst_allocated_stuff[i]); 638 ctst_allocated_stuff[i] = NULL; 639 } 640 } else { 641 for(i=0; i<CTST_MAX_ALLOC; i++) { 642 free(ctst_allocated_stuff[i]); 643 ctst_allocated_stuff[i] = NULL; 644 } 645 } 646 ctst_allocated = 0; 647 _testDataPath=NULL; 648 } 649 650 #define VERBOSE_ASSERTIONS 651 652 U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec) { 653 U_ASSERT(ec!=NULL); 654 if (U_FAILURE(*ec)) { 655 log_err_status(*ec, "FAIL: %s (%s)\n", msg, u_errorName(*ec)); 656 return FALSE; 657 } 658 return TRUE; 659 } 660 661 /* if 'condition' is a UBool, the compiler complains bitterly about 662 expressions like 'a > 0' which it evaluates as int */ 663 U_CFUNC UBool assertTrue(const char* msg, int /*not UBool*/ condition) { 664 if (!condition) { 665 log_err("FAIL: assertTrue() failed: %s\n", msg); 666 } 667 #ifdef VERBOSE_ASSERTIONS 668 else { 669 log_verbose("Ok: %s\n", msg); 670 } 671 #endif 672 return (UBool)condition; 673 } 674 675 U_CFUNC UBool assertEquals(const char* message, const char* expected, 676 const char* actual) { 677 if (uprv_strcmp(expected, actual) != 0) { 678 log_err("FAIL: %s; got \"%s\"; expected \"%s\"\n", 679 message, actual, expected); 680 return FALSE; 681 } 682 #ifdef VERBOSE_ASSERTIONS 683 else { 684 log_verbose("Ok: %s; got \"%s\"\n", message, actual); 685 } 686 #endif 687 return TRUE; 688 } 689 /*-------------------------------------------------------------------- 690 * Time bomb - allows temporary behavior that expires at a given 691 * release 692 *-------------------------------------------------------------------- 693 */ 694 695 U_CFUNC UBool isICUVersionAtLeast(const UVersionInfo x) { 696 UVersionInfo v; 697 u_getVersion(v); 698 return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0); 699 } 700 #endif 701