]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /******************************************************************** |
2 | * COPYRIGHT: | |
57a6839d | 3 | * Copyright (c) 1997-2013, International Business Machines Corporation and |
b75a7d8f A |
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" | |
374ca955 | 23 | #include "cstring.h" |
b75a7d8f | 24 | #include "cintltst.h" |
374ca955 | 25 | #include "uassert.h" |
73c04bcf | 26 | #include "cmemory.h" |
b75a7d8f A |
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" | |
374ca955 A |
32 | #include "unicode/ucal.h" |
33 | #include "uoptions.h" | |
729e4ab9 A |
34 | #include "putilimp.h" /* for uprv_getRawUTCtime() */ |
35 | #ifdef URES_DEBUG | |
36 | #include "uresimp.h" /* for ures_dumpCacheContents() */ | |
37 | #endif | |
b75a7d8f A |
38 | |
39 | #ifdef XP_MAC_CONSOLE | |
40 | # include <console.h> | |
41 | #endif | |
42 | ||
51004dcb A |
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 | ||
b75a7d8f | 50 | #define CTST_LEAK_CHECK 1 |
51004dcb | 51 | |
b75a7d8f | 52 | #ifdef CTST_LEAK_CHECK |
51004dcb | 53 | static void ctst_freeAll(void); |
b75a7d8f A |
54 | #endif |
55 | ||
56 | static char* _testDataPath=NULL; | |
57 | ||
58 | /* | |
59 | * Forward Declarations | |
60 | */ | |
61 | void ctest_setICU_DATA(void); | |
62 | ||
b75a7d8f | 63 | |
b75a7d8f A |
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 | ||
46f4442e A |
73 | static int gOrigArgc; |
74 | static const char* const * gOrigArgv; | |
374ca955 | 75 | |
b75a7d8f A |
76 | int main(int argc, const char* const argv[]) |
77 | { | |
78 | int nerrors = 0; | |
374ca955 | 79 | UBool defaultDataFound; |
b75a7d8f A |
80 | TestNode *root; |
81 | const char *warnOrErr = "Failure"; | |
73c04bcf A |
82 | UDate startTime, endTime; |
83 | int32_t diffTime; | |
b75a7d8f A |
84 | |
85 | /* initial check for the default converter */ | |
86 | UErrorCode errorCode = U_ZERO_ERROR; | |
87 | UResourceBundle *rb; | |
88 | UConverter *cnv; | |
89 | ||
374ca955 A |
90 | U_MAIN_INIT_ARGS(argc, argv); |
91 | ||
729e4ab9 | 92 | startTime = uprv_getRawUTCtime(); |
73c04bcf | 93 | |
46f4442e A |
94 | gOrigArgc = argc; |
95 | gOrigArgv = argv; | |
96 | if (!initArgs(argc, argv, NULL, NULL)) { | |
97 | /* Error already displayed. */ | |
98 | return -1; | |
374ca955 | 99 | } |
46f4442e A |
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. | |
374ca955 | 108 | */ |
46f4442e A |
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; | |
b75a7d8f | 115 | } |
46f4442e | 116 | u_cleanup(); |
729e4ab9 A |
117 | #ifdef URES_DEBUG |
118 | fprintf(stderr, "After initial u_cleanup: RB cache %s empty.\n", ures_dumpCacheContents()?"WAS NOT":"was"); | |
119 | #endif | |
374ca955 | 120 | |
729e4ab9 | 121 | while (getTestOption(REPEAT_TESTS_OPTION) > 0) { /* Loop runs once per complete execution of the tests |
374ca955 | 122 | * used for -r (repeat) test option. */ |
46f4442e A |
123 | if (!initArgs(argc, argv, NULL, NULL)) { |
124 | /* Error already displayed. */ | |
125 | return -1; | |
b75a7d8f | 126 | } |
374ca955 | 127 | errorCode = U_ZERO_ERROR; |
374ca955 A |
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)) { | |
b75a7d8f | 135 | fprintf(stderr, |
374ca955 | 136 | "#### ERROR! %s: u_init() failed with status = \"%s\".\n" |
b75a7d8f | 137 | "*** Check the ICU_DATA environment variable and \n" |
374ca955 | 138 | "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); |
729e4ab9 | 139 | if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { |
374ca955 A |
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 | } | |
b75a7d8f | 144 | } |
374ca955 A |
145 | |
146 | ||
b75a7d8f A |
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); | |
729e4ab9 | 158 | if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { |
b75a7d8f | 159 | fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); |
374ca955 | 160 | u_cleanup(); |
b75a7d8f A |
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); | |
729e4ab9 | 174 | if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { |
b75a7d8f | 175 | fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); |
374ca955 | 176 | u_cleanup(); |
b75a7d8f A |
177 | return 1; |
178 | } | |
179 | } | |
180 | ||
46f4442e A |
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()); | |
729e4ab9 | 193 | if(!getTestOption(WARN_ON_MISSING_DATA_OPTION)) { |
46f4442e A |
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 | } | |
b75a7d8f A |
200 | fprintf(stdout, "Default locale for this run is %s\n", uloc_getDefault()); |
201 | ||
374ca955 A |
202 | /* Build a tree of all tests. |
203 | * Subsequently will be used to find / iterate the tests to run */ | |
b75a7d8f A |
204 | root = NULL; |
205 | addAllTests(&root); | |
374ca955 A |
206 | |
207 | /* Tests acutally run HERE. TODO: separate command line option parsing & setting from test execution!! */ | |
46f4442e | 208 | nerrors = runTestRequest(root, argc, argv); |
374ca955 | 209 | |
729e4ab9 A |
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)); | |
b75a7d8f A |
213 | } |
214 | cleanUpTestTree(root); | |
374ca955 | 215 | |
b75a7d8f A |
216 | #ifdef CTST_LEAK_CHECK |
217 | ctst_freeAll(); | |
b75a7d8f | 218 | /* To check for leaks */ |
b75a7d8f | 219 | u_cleanup(); /* nuke the hashtable.. so that any still-open cnvs are leaked */ |
51004dcb A |
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 | } | |
729e4ab9 A |
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 | |
b75a7d8f | 232 | #endif |
b75a7d8f | 233 | |
374ca955 | 234 | } /* End of loop that repeats the entire test, if requested. (Normally doesn't loop) */ |
b75a7d8f | 235 | |
729e4ab9 | 236 | endTime = uprv_getRawUTCtime(); |
73c04bcf A |
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 | ||
b75a7d8f A |
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 | ||
b75a7d8f A |
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 | ||
b75a7d8f A |
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 ); | |
374ca955 | 333 | dataSrcDir = p; |
b75a7d8f A |
334 | } |
335 | else { | |
336 | /* __FILE__ on MSVC7 does not contain the directory */ | |
374ca955 A |
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 { | |
729e4ab9 | 343 | dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; |
374ca955 | 344 | } |
b75a7d8f A |
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 | { | |
374ca955 | 372 | dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; |
b75a7d8f A |
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 | ||
b75a7d8f A |
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); | |
374ca955 | 400 | dataOutDir = p; |
b75a7d8f A |
401 | } |
402 | else { | |
403 | /* __FILE__ on MSVC7 does not contain the directory */ | |
374ca955 A |
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 { | |
729e4ab9 | 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; |
374ca955 | 411 | } |
b75a7d8f A |
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 | ||
b75a7d8f A |
430 | /* No location for the data dir was identifiable. |
431 | * Add other fallbacks for the test data location here if the need arises | |
432 | */ | |
374ca955 A |
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 | } | |
b75a7d8f A |
437 | } |
438 | ||
46f4442e A |
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)) { | |
729e4ab9 | 466 | log_err_status(status, "u_init failed with %s\n", u_errorName(status)); |
46f4442e A |
467 | return FALSE; |
468 | } | |
469 | return TRUE; | |
470 | } | |
471 | ||
b75a7d8f A |
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 | |
4388f060 | 504 | # if U_PLATFORM == U_PF_OS390 |
b75a7d8f A |
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); | |
729e4ab9 | 519 | ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_C, &cb, &p, &errorCode); |
b75a7d8f A |
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){ | |
b75a7d8f | 527 | if( _testDataPath == NULL){ |
73c04bcf A |
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; | |
b75a7d8f | 537 | directory= ctest_dataOutDir(); |
73c04bcf | 538 | #endif |
b75a7d8f A |
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; | |
46f4442e | 559 | log_data_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(*err)); |
b75a7d8f A |
560 | return ""; |
561 | } | |
562 | ures_close(test); | |
563 | _testDataPath = tdpath; | |
564 | return _testDataPath; | |
565 | } | |
566 | return _testDataPath; | |
567 | } | |
568 | ||
374ca955 A |
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]) { | |
729e4ab9 | 585 | log_data_err("*** Error: time zone saved twice. New value will be %s (Are you missing data?)\n", |
374ca955 A |
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 | ||
b75a7d8f | 622 | |
b75a7d8f | 623 | void *ctst_malloc(size_t size) { |
51004dcb | 624 | ctst_allocated_total++; |
b75a7d8f A |
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 | |
51004dcb | 636 | static void ctst_freeAll() { |
b75a7d8f | 637 | int i; |
51004dcb | 638 | if(ctst_free == FALSE) { /* only free up to the allocated mark */ |
b75a7d8f A |
639 | for(i=0; i<ctst_allocated; i++) { |
640 | free(ctst_allocated_stuff[i]); | |
374ca955 | 641 | ctst_allocated_stuff[i] = NULL; |
b75a7d8f | 642 | } |
51004dcb | 643 | } else { /* free all */ |
b75a7d8f A |
644 | for(i=0; i<CTST_MAX_ALLOC; i++) { |
645 | free(ctst_allocated_stuff[i]); | |
374ca955 | 646 | ctst_allocated_stuff[i] = NULL; |
b75a7d8f A |
647 | } |
648 | } | |
374ca955 | 649 | ctst_allocated = 0; |
b75a7d8f A |
650 | _testDataPath=NULL; |
651 | } | |
374ca955 A |
652 | |
653 | #define VERBOSE_ASSERTIONS | |
654 | ||
57a6839d | 655 | U_CFUNC UBool assertSuccessCheck(const char* msg, UErrorCode* ec, UBool possibleDataError) { |
374ca955 A |
656 | U_ASSERT(ec!=NULL); |
657 | if (U_FAILURE(*ec)) { | |
57a6839d A |
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 | } | |
374ca955 A |
663 | return FALSE; |
664 | } | |
665 | return TRUE; | |
666 | } | |
667 | ||
57a6839d A |
668 | U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec) { |
669 | U_ASSERT(ec!=NULL); | |
670 | return assertSuccessCheck(msg, ec, FALSE); | |
671 | } | |
672 | ||
374ca955 A |
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 | } | |
4388f060 | 701 | |
b75a7d8f | 702 | #endif |