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 
main(int argc,const char * const argv[])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 */
ctest_dataSrcDir()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 */
ctest_dataOutDir()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  */
ctest_setICU_DATA()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  */
safeGetICUDataDirectory()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 
ctest_resetICU()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 
CharsToUChars(const char * str)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 
austrdup(const UChar * unichars)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 
aescstrdup(const UChar * unichars,int32_t length)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 
loadTestData(UErrorCode * err)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  */
ctest_setTimeZone(const char * optionalTimeZone,UErrorCode * status)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  */
ctest_resetTimeZone(void)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 
ctst_malloc(size_t size)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
ctst_freeAll()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 
assertSuccessCheck(const char * msg,UErrorCode * ec,UBool possibleDataError)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 
assertSuccess(const char * msg,UErrorCode * ec)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 */
assertTrue(const char * msg,int condition)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 
assertEquals(const char * message,const char * expected,const char * actual)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