1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 **********************************************************************
5 * Copyright (C) 2002-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 **********************************************************************
8 * file name: iotest.cpp
10 * tab size: 8 (not used)
13 * created on: 2002feb21
14 * created by: George Rhoten
18 #include "unicode/ustdio.h"
19 #include "unicode/uclean.h"
21 #include "unicode/ucnv.h"
22 #include "unicode/uchar.h"
23 #include "unicode/unistr.h"
24 #include "unicode/ustring.h"
28 #include "unicode/tstdtmod.h"
34 class DataDrivenLogger : public TestLog {
35 static const char* fgDataDir;
36 static char *fgTestDataPath;
39 static void cleanUp() {
42 fgTestDataPath = NULL;
45 virtual void errln( const UnicodeString &message ) {
47 message.extract(0, message.length(), buffer, sizeof(buffer));
48 buffer[3999] = 0; /* NULL terminate */
52 virtual void logln( const UnicodeString &message ) {
54 message.extract(0, message.length(), buffer, sizeof(buffer));
55 buffer[3999] = 0; /* NULL terminate */
59 virtual void dataerrln( const UnicodeString &message ) {
61 message.extract(0, message.length(), buffer, sizeof(buffer));
62 buffer[3999] = 0; /* NULL terminate */
66 static const char * pathToDataDirectory(void)
69 if(fgDataDir != NULL) {
73 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
74 // to point to the top of the build hierarchy, which may or
75 // may not be the same as the source directory, depending on
76 // the configure options used. At any rate,
77 // set the data path to the built data from this directory.
78 // The value is complete with quotes, so it can be used
79 // as-is as a string constant.
81 #if defined (U_TOPSRCDIR)
83 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
87 /* On Windows, the file name obtained from __FILE__ includes a full path.
88 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
89 * Change to "wherever\icu\source\data"
92 static char p[sizeof(__FILE__) + 10];
97 /* We want to back over three '\' chars. */
98 /* Only Windows should end up here, so looking for '\' is safe. */
99 for (i=1; i<=3; i++) {
100 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
101 if (pBackSlash != NULL) {
102 *pBackSlash = 0; /* Truncate the string at the '\' */
106 if (pBackSlash != NULL) {
107 /* We found and truncated three names from the path.
108 * Now append "source\data" and set the environment
110 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
114 /* __FILE__ on MSVC7 does not contain the directory */
115 FILE *file = fopen(".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
118 fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
121 fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
131 static const char* loadTestData(UErrorCode& err){
132 if( fgTestDataPath == NULL){
133 const char* directory=NULL;
134 UResourceBundle* test =NULL;
136 const char* tdrelativepath;
138 #if defined (U_TOPBUILDDIR)
139 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
140 directory = U_TOPBUILDDIR;
142 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
143 directory = pathToDataDirectory();
146 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
149 /* u_getDataDirectory shoul return \source\data ... set the
150 * directory to ..\source\data\..\test\testdata\out\testdata
152 strcpy(tdpath, directory);
153 strcat(tdpath, tdrelativepath);
154 strcat(tdpath,"testdata");
156 test=ures_open(tdpath, "testtypes", &err);
159 err = U_FILE_ACCESS_ERROR;
160 log_data_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(err));
164 fgTestDataPath = tdpath;
166 return fgTestDataPath;
169 virtual const char* getTestDataPath(UErrorCode& err) {
170 return loadTestData(err);
174 const char* DataDrivenLogger::fgDataDir = NULL;
175 char* DataDrivenLogger::fgTestDataPath = NULL;
177 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
179 uto64(const UChar *buffer)
182 /* iterate through buffer */
184 /* read the next digit */
186 if (!u_isxdigit(*buffer)) {
187 log_err("\\u%04X is not a valid hex digit for this test\n", (UChar)*buffer);
189 result += *buffer - 0x0030 - (*buffer >= 0x0041 ? (*buffer >= 0x0061 ? 39 : 7) : 0);
197 static void U_CALLCONV DataDrivenPrintf(void)
199 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
200 UErrorCode errorCode;
201 TestDataModule *dataModule;
203 const DataMap *testCase;
204 DataDrivenLogger logger;
207 char cFormat[sizeof(cBuffer)];
208 char cExpected[sizeof(cBuffer)];
209 UnicodeString tempStr;
211 UChar expectedResult[512];
219 int32_t uBufferLenReturned;
221 const char *fileLocale = "en_US_POSIX";
222 int32_t uFileBufferLenReturned;
223 LocalUFILEPointer testFile;
225 errorCode=U_ZERO_ERROR;
226 dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
227 if(U_SUCCESS(errorCode)) {
228 testData=dataModule->createTestData("printf", errorCode);
229 if(U_SUCCESS(errorCode)) {
230 for(i=0; testData->nextCase(testCase, errorCode); ++i) {
231 if(U_FAILURE(errorCode)) {
232 log_err("error retrieving icuio/printf test case %d - %s\n",
233 i, u_errorName(errorCode));
234 errorCode=U_ZERO_ERROR;
237 testFile.adoptInstead(u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8"));
238 if (testFile.isNull()) {
239 log_err("Can't open test file - %s\n",
243 u_memset(uBuffer, 0x2A, UPRV_LENGTHOF(uBuffer));
244 uBuffer[UPRV_LENGTHOF(uBuffer)-1] = 0;
245 tempStr=testCase->getString("format", errorCode);
246 tempStr.extract(format, UPRV_LENGTHOF(format), errorCode);
247 tempStr=testCase->getString("result", errorCode);
248 tempStr.extract(expectedResult, UPRV_LENGTHOF(expectedResult), errorCode);
249 tempStr=testCase->getString("argument", errorCode);
250 tempStr.extract(argument, UPRV_LENGTHOF(argument), errorCode);
251 u_austrncpy(cBuffer, format, sizeof(cBuffer));
252 if(U_FAILURE(errorCode)) {
253 log_err("error retrieving icuio/printf test case %d - %s\n",
254 i, u_errorName(errorCode));
255 errorCode=U_ZERO_ERROR;
258 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
259 switch (testCase->getString("argumentType", errorCode)[0]) {
260 case 0x64: // 'd' double
261 dbl = atof(u_austrcpy(cBuffer, argument));
262 uBufferLenReturned = u_sprintf_u(uBuffer, format, dbl);
263 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, dbl);
265 case 0x31: // '1' int8_t
266 i8 = (int8_t)uto64(argument);
267 uBufferLenReturned = u_sprintf_u(uBuffer, format, i8);
268 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i8);
270 case 0x32: // '2' int16_t
271 i16 = (int16_t)uto64(argument);
272 uBufferLenReturned = u_sprintf_u(uBuffer, format, i16);
273 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i16);
275 case 0x34: // '4' int32_t
276 i32 = (int32_t)uto64(argument);
277 uBufferLenReturned = u_sprintf_u(uBuffer, format, i32);
278 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i32);
280 case 0x38: // '8' int64_t
281 i64 = uto64(argument);
282 uBufferLenReturned = u_sprintf_u(uBuffer, format, i64);
283 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i64);
285 case 0x73: // 's' char *
286 u_austrncpy(cBuffer, argument, sizeof(cBuffer));
287 uBufferLenReturned = u_sprintf_u(uBuffer, format, cBuffer);
288 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, cBuffer);
290 case 0x53: // 'S' UChar *
291 uBufferLenReturned = u_sprintf_u(uBuffer, format, argument);
292 uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, argument);
295 uBufferLenReturned = 0;
296 uFileBufferLenReturned = 0;
297 log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
299 if (u_strcmp(uBuffer, expectedResult) != 0) {
300 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
301 u_austrncpy(cFormat, format, sizeof(cFormat));
302 u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
303 cBuffer[sizeof(cBuffer)-1] = 0;
304 log_err("FAILURE string test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
305 i, cFormat, cBuffer, cExpected);
307 if (uBufferLenReturned <= 0) {
308 log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
311 else if (uBuffer[uBufferLenReturned-1] == 0
312 || uBuffer[uBufferLenReturned] != 0
313 || uBuffer[uBufferLenReturned+1] != 0x2A
314 || uBuffer[uBufferLenReturned+2] != 0x2A)
316 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
317 cBuffer[sizeof(cBuffer)-1] = 0;
318 log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
319 i, cBuffer, uBufferLenReturned);
321 testFile.adoptInstead(u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8"));
322 if (testFile.isNull()) {
323 log_err("Can't open test file - %s\n",
327 u_fgets(uBuffer, UPRV_LENGTHOF(uBuffer), testFile.getAlias());
328 if (u_strcmp(uBuffer, expectedResult) != 0) {
329 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
330 u_austrncpy(cFormat, format, sizeof(cFormat));
331 u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
332 cBuffer[sizeof(cBuffer)-1] = 0;
333 log_err("FAILURE file test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
334 i, cFormat, cBuffer, cExpected);
336 if (uFileBufferLenReturned != uBufferLenReturned)
338 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
339 cBuffer[sizeof(cBuffer)-1] = 0;
340 log_err("FAILURE uFileBufferLenReturned(%d) != uBufferLenReturned(%d)\n",
341 uFileBufferLenReturned, uBufferLenReturned);
344 if(U_FAILURE(errorCode)) {
345 log_err("error running icuio/printf test case %d - %s\n",
346 i, u_errorName(errorCode));
347 errorCode=U_ZERO_ERROR;
356 log_data_err("Failed: could not load test icuio data\n");
363 static void U_CALLCONV DataDrivenScanf(void)
365 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
366 UErrorCode errorCode;
367 TestDataModule *dataModule;
369 const DataMap *testCase;
370 DataDrivenLogger logger;
373 char cExpected[sizeof(cBuffer)];
374 UnicodeString tempStr;
376 UChar expectedResult[512];
379 int8_t i8, expected8;
380 int16_t i16, expected16;
381 int32_t i32, expected32;
382 int64_t i64, expected64;
383 double dbl, expectedDbl;
384 volatile float flt, expectedFlt; // Use volatile in order to get around an Intel compiler issue.
385 int32_t uBufferLenReturned;
387 //const char *fileLocale = "en_US_POSIX";
388 //int32_t uFileBufferLenReturned;
391 errorCode=U_ZERO_ERROR;
392 dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
393 if(U_SUCCESS(errorCode)) {
394 testData=dataModule->createTestData("scanf", errorCode);
395 if(U_SUCCESS(errorCode)) {
396 for(i=0; testData->nextCase(testCase, errorCode); ++i) {
397 if(U_FAILURE(errorCode)) {
398 log_err("error retrieving icuio/printf test case %d - %s\n",
399 i, u_errorName(errorCode));
400 errorCode=U_ZERO_ERROR;
403 /* testFile = u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8");
405 log_err("Can't open test file - %s\n",
408 u_memset(uBuffer, 0x2A, UPRV_LENGTHOF(uBuffer));
409 uBuffer[UPRV_LENGTHOF(uBuffer)-1] = 0;
410 tempStr=testCase->getString("format", errorCode);
411 tempStr.extract(format, UPRV_LENGTHOF(format), errorCode);
412 tempStr=testCase->getString("result", errorCode);
413 tempStr.extract(expectedResult, UPRV_LENGTHOF(expectedResult), errorCode);
414 tempStr=testCase->getString("argument", errorCode);
415 tempStr.extract(argument, UPRV_LENGTHOF(argument), errorCode);
416 u_austrncpy(cBuffer, format, sizeof(cBuffer));
417 if(U_FAILURE(errorCode)) {
418 log_err("error retrieving icuio/printf test case %d - %s\n",
419 i, u_errorName(errorCode));
420 errorCode=U_ZERO_ERROR;
423 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
424 switch (testCase->getString("argumentType", errorCode)[0]) {
425 case 0x64: // 'd' double
426 expectedDbl = atof(u_austrcpy(cBuffer, expectedResult));
427 uBufferLenReturned = u_sscanf_u(argument, format, &dbl);
428 //uFileBufferLenReturned = u_fscanf_u(testFile, format, dbl);
429 if (dbl != expectedDbl) {
430 log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
431 i, dbl, expectedDbl);
434 case 0x66: // 'f' float
435 expectedFlt = (float)atof(u_austrcpy(cBuffer, expectedResult));
436 uBufferLenReturned = u_sscanf_u(argument, format, &flt);
437 //uFileBufferLenReturned = u_fscanf_u(testFile, format, flt);
438 if (flt != expectedFlt) {
439 log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
440 i, flt, expectedFlt);
443 case 0x31: // '1' int8_t
444 expected8 = (int8_t)uto64(expectedResult);
445 uBufferLenReturned = u_sscanf_u(argument, format, &i8);
446 //uFileBufferLenReturned = u_fscanf_u(testFile, format, i8);
447 if (i8 != expected8) {
448 log_err("error in scanf test case[%d] Got: %02X Exp: %02X\n",
452 case 0x32: // '2' int16_t
453 expected16 = (int16_t)uto64(expectedResult);
454 uBufferLenReturned = u_sscanf_u(argument, format, &i16);
455 //uFileBufferLenReturned = u_fscanf_u(testFile, format, i16);
456 if (i16 != expected16) {
457 log_err("error in scanf test case[%d] Got: %04X Exp: %04X\n",
461 case 0x34: // '4' int32_t
462 expected32 = (int32_t)uto64(expectedResult);
463 uBufferLenReturned = u_sscanf_u(argument, format, &i32);
464 //uFileBufferLenReturned = u_fscanf_u(testFile, format, i32);
465 if (i32 != expected32) {
466 log_err("error in scanf test case[%d] Got: %08X Exp: %08X\n",
470 case 0x38: // '8' int64_t
471 expected64 = uto64(expectedResult);
472 uBufferLenReturned = u_sscanf_u(argument, format, &i64);
473 //uFileBufferLenReturned = u_fscanf_u(testFile, format, i64);
474 if (i64 != expected64) {
475 log_err("error in scanf 64-bit. Test case = %d\n", i);
478 case 0x73: // 's' char *
479 u_austrcpy(cExpected, expectedResult);
480 uBufferLenReturned = u_sscanf_u(argument, format, cBuffer);
481 //uFileBufferLenReturned = u_fscanf_u(testFile, format, cBuffer);
482 if (strcmp(cBuffer, cExpected) != 0) {
483 log_err("error in scanf char * string. Got \"%s\" Expected \"%s\". Test case = %d\n", cBuffer, cExpected, i);
486 case 0x53: // 'S' UChar *
487 uBufferLenReturned = u_sscanf_u(argument, format, uBuffer);
488 //uFileBufferLenReturned = u_fscanf_u(testFile, format, argument);
489 if (u_strcmp(uBuffer, expectedResult) != 0) {
490 u_austrcpy(cExpected, format);
491 u_austrcpy(cBuffer, uBuffer);
492 log_err("error in scanf UChar * string %s Got: \"%s\". Test case = %d\n", cExpected, cBuffer, i);
496 uBufferLenReturned = 0;
497 //uFileBufferLenReturned = 0;
498 log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
500 if (uBufferLenReturned != 1) {
501 log_err("error scanf converted %d arguments. Test case = %d\n", uBufferLenReturned, i);
503 /* if (u_strcmp(uBuffer, expectedResult) != 0) {
504 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
505 u_austrncpy(cFormat, format, sizeof(cFormat));
506 u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
507 cBuffer[sizeof(cBuffer)-1] = 0;
508 log_err("FAILURE string test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
509 i, cFormat, cBuffer, cExpected);
511 if (uBuffer[uBufferLenReturned-1] == 0
512 || uBuffer[uBufferLenReturned] != 0
513 || uBuffer[uBufferLenReturned+1] != 0x2A
514 || uBuffer[uBufferLenReturned+2] != 0x2A)
516 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
517 cBuffer[sizeof(cBuffer)-1] = 0;
518 log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
519 i, cBuffer, uBufferLenReturned);
521 /* u_fclose(testFile);
522 testFile = u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8");
524 log_err("Can't open test file - %s\n",
528 u_fgets(uBuffer, UPRV_LENGTHOF(uBuffer), testFile);
529 if (u_strcmp(uBuffer, expectedResult) != 0) {
530 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
531 u_austrncpy(cFormat, format, sizeof(cFormat));
532 u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
533 cBuffer[sizeof(cBuffer)-1] = 0;
534 log_err("FAILURE file test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
535 i, cFormat, cBuffer, cExpected);
537 if (uFileBufferLenReturned != uBufferLenReturned)
539 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
540 cBuffer[sizeof(cBuffer)-1] = 0;
541 log_err("FAILURE uFileBufferLenReturned(%d) != uBufferLenReturned(%d)\n",
542 uFileBufferLenReturned, uBufferLenReturned);
545 if(U_FAILURE(errorCode)) {
546 log_err("error running icuio/printf test case %d - %s\n",
547 i, u_errorName(errorCode));
548 errorCode=U_ZERO_ERROR;
551 // u_fclose(testFile);
558 log_data_err("Failed: could not load test icuio data\n");
565 static void U_CALLCONV DataDrivenPrintfPrecision(void)
567 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
568 UErrorCode errorCode;
569 TestDataModule *dataModule;
571 const DataMap *testCase;
572 DataDrivenLogger logger;
575 char cFormat[sizeof(cBuffer)];
576 char cExpected[sizeof(cBuffer)];
577 UnicodeString tempStr;
579 UChar expectedResult[512];
588 int32_t uBufferLenReturned;
590 errorCode=U_ZERO_ERROR;
591 dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
592 if(U_SUCCESS(errorCode)) {
593 testData=dataModule->createTestData("printfPrecision", errorCode);
594 if(U_SUCCESS(errorCode)) {
595 for(i=0; testData->nextCase(testCase, errorCode); ++i) {
596 if(U_FAILURE(errorCode)) {
597 log_err("error retrieving icuio/printf test case %d - %s\n",
598 i, u_errorName(errorCode));
599 errorCode=U_ZERO_ERROR;
602 u_memset(uBuffer, 0x2A, UPRV_LENGTHOF(uBuffer));
603 uBuffer[UPRV_LENGTHOF(uBuffer)-1] = 0;
604 tempStr=testCase->getString("format", errorCode);
605 tempStr.extract(format, UPRV_LENGTHOF(format), errorCode);
606 tempStr=testCase->getString("result", errorCode);
607 tempStr.extract(expectedResult, UPRV_LENGTHOF(expectedResult), errorCode);
608 tempStr=testCase->getString("argument", errorCode);
609 tempStr.extract(argument, UPRV_LENGTHOF(argument), errorCode);
610 precision=testCase->getInt28("precision", errorCode);
611 u_austrncpy(cBuffer, format, sizeof(cBuffer));
612 if(U_FAILURE(errorCode)) {
613 log_err("error retrieving icuio/printf test case %d - %s\n",
614 i, u_errorName(errorCode));
615 errorCode=U_ZERO_ERROR;
618 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
619 switch (testCase->getString("argumentType", errorCode)[0]) {
620 case 0x64: // 'd' double
621 dbl = atof(u_austrcpy(cBuffer, argument));
622 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, dbl);
624 case 0x31: // '1' int8_t
625 i8 = (int8_t)uto64(argument);
626 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i8);
628 case 0x32: // '2' int16_t
629 i16 = (int16_t)uto64(argument);
630 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i16);
632 case 0x34: // '4' int32_t
633 i32 = (int32_t)uto64(argument);
634 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i32);
636 case 0x38: // '8' int64_t
637 i64 = uto64(argument);
638 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i64);
640 case 0x73: // 's' char *
641 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
642 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, cBuffer);
644 case 0x53: // 'S' UChar *
645 uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, argument);
648 uBufferLenReturned = 0;
649 log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
651 if (u_strcmp(uBuffer, expectedResult) != 0) {
652 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
653 u_austrncpy(cFormat, format, sizeof(cFormat));
654 u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
655 cBuffer[sizeof(cBuffer)-1] = 0;
656 log_err("FAILURE test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
657 i, cFormat, cBuffer, cExpected);
659 if (uBufferLenReturned <= 0) {
660 log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
663 else if (uBuffer[uBufferLenReturned-1] == 0
664 || uBuffer[uBufferLenReturned] != 0
665 || uBuffer[uBufferLenReturned+1] != 0x2A
666 || uBuffer[uBufferLenReturned+2] != 0x2A)
668 u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
669 cBuffer[sizeof(cBuffer)-1] = 0;
670 log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
671 i, cBuffer, uBufferLenReturned);
673 if(U_FAILURE(errorCode)) {
674 log_err("error running icuio/printf test case %d - %s\n",
675 i, u_errorName(errorCode));
676 errorCode=U_ZERO_ERROR;
685 log_data_err("Failed: could not load test icuio data\n");
691 static void addAllTests(TestNode** root) {
694 addTranslitTest(root);
696 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_LEGACY_CONVERSION
697 addTest(root, &DataDrivenPrintf, "datadriv/DataDrivenPrintf");
698 addTest(root, &DataDrivenPrintfPrecision, "datadriv/DataDrivenPrintfPrecision");
699 addTest(root, &DataDrivenScanf, "datadriv/DataDrivenScanf");
701 #if U_IOSTREAM_SOURCE >= 199711
702 addStreamTests(root);
706 /* returns the path to icu/source/data/out */
707 static const char *ctest_dataOutDir()
709 static const char *dataOutDir = NULL;
715 /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
716 // to point to the top of the build hierarchy, which may or
717 // may not be the same as the source directory, depending on
718 // the configure options used. At any rate,
719 // set the data path to the built data from this directory.
720 // The value is complete with quotes, so it can be used
721 // as-is as a string constant.
723 #if defined (U_TOPBUILDDIR)
725 dataOutDir = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
729 /* On Windows, the file name obtained from __FILE__ includes a full path.
730 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
731 * Change to "wherever\icu\source\data"
734 static char p[sizeof(__FILE__) + 20];
739 /* We want to back over three '\' chars. */
740 /* Only Windows should end up here, so looking for '\' is safe. */
741 for (i=1; i<=3; i++) {
742 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
743 if (pBackSlash != NULL) {
744 *pBackSlash = 0; /* Truncate the string at the '\' */
748 if (pBackSlash != NULL) {
749 /* We found and truncated three names from the path.
750 * Now append "source\data" and set the environment
752 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
756 /* __FILE__ on MSVC7 does not contain the directory */
757 FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
760 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
763 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
772 /* ctest_setICU_DATA - if the ICU_DATA environment variable is not already
773 * set, try to deduce the directory in which ICU was built,
774 * and set ICU_DATA to "icu/source/data" in that location.
775 * The intent is to allow the tests to have a good chance
776 * of running without requiring that the user manually set
777 * ICU_DATA. Common data isn't a problem, since it is
778 * picked up via a static (build time) reference, but the
779 * tests dynamically load some data.
781 static void ctest_setICU_DATA() {
783 /* No location for the data dir was identifiable.
784 * Add other fallbacks for the test data location here if the need arises
786 if (getenv("ICU_DATA") == NULL) {
787 /* If ICU_DATA isn't set, set it to the usual location */
788 u_setDataDirectory(ctest_dataOutDir());
794 * Note: this assumes that context is a pointer to STANDARD_TEST_FILE. It would be
795 * cleaner to define an acutal context with a string pointer in it and set STANDARD_TEST_FILE
796 * after the call to initArgs()...
798 static int U_CALLCONV argHandler(int arg, int /*argc*/, const char * const argv[], void *context)
800 const char **str = (const char **) context;
802 if (argv[arg][0] != '/' && argv[arg][0] != '-') {
811 int main(int argc, char* argv[])
814 TestNode *root = NULL;
815 UErrorCode errorCode = U_ZERO_ERROR;
816 UDate startTime, endTime;
819 startTime = uprv_getRawUTCtime();
821 /* Check whether ICU will initialize without forcing the build data directory into
822 * the ICU_DATA path. Success here means either the data dll contains data, or that
823 * this test program was run with ICU_DATA set externally. Failure of this check
824 * is normal when ICU data is not packaged into a shared library.
826 * Whether or not this test succeeds, we want to cleanup and reinitialize
827 * with a data path so that data loading from individual files can be tested.
830 if (U_FAILURE(errorCode)) {
832 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
835 errorCode = U_ZERO_ERROR;
836 if (!initArgs(argc, argv, argHandler, (void *) &STANDARD_TEST_FILE)) {
837 /* Error already displayed. */
842 ctest_setICU_DATA(); /* u_setDataDirectory() must happen Before u_init() */
844 if (U_FAILURE(errorCode)) {
846 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
847 "*** Check the ICU_DATA environment variable and \n"
848 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
852 fprintf(stdout, "Default charset for this run is %s\n", ucnv_getDefaultName());
855 nerrors = runTestRequest(root, argc, argv);
859 FILE* fileToRemove = fopen(STANDARD_TEST_FILE, "r");
860 /* This should delete any temporary files. */
862 fclose(fileToRemove);
863 log_verbose("Deleting: %s\n", STANDARD_TEST_FILE);
864 if (remove(STANDARD_TEST_FILE) != 0) {
865 /* Maybe someone didn't close the file correctly. */
866 fprintf(stderr, "FAIL: Could not delete %s\n", STANDARD_TEST_FILE);
873 cleanUpTestTree(root);
874 DataDrivenLogger::cleanUp();
877 endTime = uprv_getRawUTCtime();
878 diffTime = (int32_t)(endTime - startTime);
879 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
880 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
881 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
882 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
883 (int)(diffTime%U_MILLIS_PER_SECOND));