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