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