Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / iotest / iotest.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 **********************************************************************
5 *   Copyright (C) 2002-2016, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 **********************************************************************
8 *   file name:  iotest.cpp
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2002feb21
14 *   created by: George Rhoten
15 */
16
17
18 #include "unicode/ustdio.h"
19 #include "unicode/uclean.h"
20
21 #include "unicode/ucnv.h"
22 #include "unicode/uchar.h"
23 #include "unicode/unistr.h"
24 #include "unicode/ustring.h"
25 #include "cmemory.h"
26 #include "ustr_cnv.h"
27 #include "iotest.h"
28 #include "unicode/tstdtmod.h"
29 #include "putilimp.h"
30
31 #include <string.h>
32 #include <stdlib.h>
33
34 class DataDrivenLogger : public TestLog {
35     static const char* fgDataDir;
36     static char *fgTestDataPath;
37
38 public:
39     static void cleanUp() {
40         if (fgTestDataPath) {
41             free(fgTestDataPath);
42             fgTestDataPath = NULL;
43         }
44     }
45     virtual void errln( const UnicodeString &message ) {
46         char buffer[4000];
47         message.extract(0, message.length(), buffer, sizeof(buffer));
48         buffer[3999] = 0; /* NULL terminate */
49         log_err(buffer);
50     }
51
52     virtual void logln( const UnicodeString &message ) {
53         char buffer[4000];
54         message.extract(0, message.length(), buffer, sizeof(buffer));
55         buffer[3999] = 0; /* NULL terminate */
56         log_info(buffer);
57     }
58
59     virtual void dataerrln( const UnicodeString &message ) {
60         char buffer[4000];
61         message.extract(0, message.length(), buffer, sizeof(buffer));
62         buffer[3999] = 0; /* NULL terminate */
63         log_data_err(buffer);
64     }
65
66     static const char * pathToDataDirectory(void)
67     {
68
69         if(fgDataDir != NULL) {
70             return fgDataDir;
71         }
72
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.
80         */
81     #if defined (U_TOPSRCDIR)
82         {
83             fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
84         }
85     #else
86
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"
90         */
91         {
92             static char p[sizeof(__FILE__) + 10];
93             char *pBackSlash;
94             int i;
95
96             strcpy(p, __FILE__);
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 '\'   */
103                 }
104             }
105
106             if (pBackSlash != NULL) {
107                 /* We found and truncated three names from the path.
108                 *  Now append "source\data" and set the environment
109                 */
110                 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
111                 fgDataDir = p;
112             }
113             else {
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");
116                 if (file) {
117                     fclose(file);
118                     fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
119                 }
120                 else {
121                     fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
122                 }
123             }
124         }
125     #endif
126
127         return fgDataDir;
128
129     }
130
131     static const char* loadTestData(UErrorCode& err){
132         if( fgTestDataPath == NULL){
133             const char*      directory=NULL;
134             UResourceBundle* test =NULL;
135             char* tdpath=NULL;
136             const char* tdrelativepath;
137
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;
141 #else
142             tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
143             directory = pathToDataDirectory();
144 #endif
145
146             tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
147
148
149             /* u_getDataDirectory shoul return \source\data ... set the
150             * directory to ..\source\data\..\test\testdata\out\testdata
151             */
152             strcpy(tdpath, directory);
153             strcat(tdpath, tdrelativepath);
154             strcat(tdpath,"testdata");
155
156             test=ures_open(tdpath, "testtypes", &err);
157
158             if(U_FAILURE(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));
161                 return "";
162             }
163             ures_close(test);
164             fgTestDataPath = tdpath;
165         }
166         return fgTestDataPath;
167     }
168
169     virtual const char* getTestDataPath(UErrorCode& err) {
170         return loadTestData(err);
171     }
172 };
173
174 const char* DataDrivenLogger::fgDataDir = NULL;
175 char* DataDrivenLogger::fgTestDataPath = NULL;
176
177 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
178 static int64_t
179 uto64(const UChar     *buffer)
180 {
181     int64_t result = 0;
182     /* iterate through buffer */
183     while(*buffer) {
184         /* read the next digit */
185         result *= 16;
186         if (!u_isxdigit(*buffer)) {
187             log_err("\\u%04X is not a valid hex digit for this test\n", (UChar)*buffer);
188         }
189         result += *buffer - 0x0030 - (*buffer >= 0x0041 ? (*buffer >= 0x0061 ? 39 : 7) : 0);
190         buffer++;
191     }
192     return result;
193 }
194 #endif
195
196 U_CDECL_BEGIN
197 static void U_CALLCONV DataDrivenPrintf(void)
198 {
199 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
200     UErrorCode errorCode;
201     TestDataModule *dataModule;
202     TestData *testData;
203     const DataMap *testCase;
204     DataDrivenLogger logger;
205     UChar uBuffer[512];
206     char cBuffer[512];
207     char cFormat[sizeof(cBuffer)];
208     char cExpected[sizeof(cBuffer)];
209     UnicodeString tempStr;
210     UChar format[512];
211     UChar expectedResult[512];
212     UChar argument[512];
213     int32_t i;
214     int8_t i8;
215     int16_t i16;
216     int32_t i32;
217     int64_t i64;
218     double dbl;
219     int32_t uBufferLenReturned;
220
221     const char *fileLocale = "en_US_POSIX";
222     int32_t uFileBufferLenReturned;
223     LocalUFILEPointer testFile;
224
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;
235                     continue;
236                 }
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",
240                             STANDARD_TEST_FILE);
241                     continue;
242                 }
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;
256                     continue;
257                 }
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);
264                     break;
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);
269                     break;
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);
274                     break;
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);
279                     break;
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);
284                     break;
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);
289                     break;
290                 case 0x53:  // 'S' UChar *
291                     uBufferLenReturned = u_sprintf_u(uBuffer, format, argument);
292                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, argument);
293                     break;
294                 default:
295                     uBufferLenReturned = 0;
296                     uFileBufferLenReturned = 0;
297                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
298                 }
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);
306                 }
307                 if (uBufferLenReturned <= 0) {
308                     log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
309                             i, cBuffer);
310                 }
311                 else if (uBuffer[uBufferLenReturned-1] == 0
312                     || uBuffer[uBufferLenReturned] != 0
313                     || uBuffer[uBufferLenReturned+1] != 0x2A
314                     || uBuffer[uBufferLenReturned+2] != 0x2A)
315                 {
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);
320                 }
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",
324                             STANDARD_TEST_FILE);
325                 }
326                 uBuffer[0]=0;
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);
335                 }
336                 if (uFileBufferLenReturned != uBufferLenReturned)
337                 {
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);
342                 }
343
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;
348                     continue;
349                 }
350             }
351             delete testData;
352         }
353         delete dataModule;
354     }
355     else {
356         log_data_err("Failed: could not load test icuio data\n");
357     }
358 #endif
359 }
360 U_CDECL_END
361
362 U_CDECL_BEGIN
363 static void U_CALLCONV DataDrivenScanf(void)
364 {
365 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
366     UErrorCode errorCode;
367     TestDataModule *dataModule;
368     TestData *testData;
369     const DataMap *testCase;
370     DataDrivenLogger logger;
371     UChar uBuffer[512];
372     char cBuffer[512];
373     char cExpected[sizeof(cBuffer)];
374     UnicodeString tempStr;
375     UChar format[512];
376     UChar expectedResult[512];
377     UChar argument[512];
378     int32_t i;
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;
386
387     //const char *fileLocale = "en_US_POSIX";
388     //int32_t uFileBufferLenReturned;
389     //UFILE *testFile;
390
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;
401                     continue;
402                 }
403 /*                testFile = u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8");
404                 if (!testFile) {
405                     log_err("Can't open test file - %s\n",
406                             STANDARD_TEST_FILE);
407                 }*/
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;
421                     continue;
422                 }
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);
432                     }
433                     break;
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);
441                     }
442                     break;
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",
449                                 i, i8, expected8);
450                     }
451                     break;
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",
458                                 i, i16, expected16);
459                     }
460                     break;
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",
467                                 i, i32, expected32);
468                     }
469                     break;
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);
476                     }
477                     break;
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);
484                     }
485                     break;
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);
493                     }
494                     break;
495                 default:
496                     uBufferLenReturned = 0;
497                     //uFileBufferLenReturned = 0;
498                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
499                 }
500                 if (uBufferLenReturned != 1) {
501                     log_err("error scanf converted %d arguments. Test case = %d\n", uBufferLenReturned, i);
502                 }
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);
510                 }
511                 if (uBuffer[uBufferLenReturned-1] == 0
512                     || uBuffer[uBufferLenReturned] != 0
513                     || uBuffer[uBufferLenReturned+1] != 0x2A
514                     || uBuffer[uBufferLenReturned+2] != 0x2A)
515                 {
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);
520                 }*/
521 /*                u_fclose(testFile);
522                 testFile = u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8");
523                 if (!testFile) {
524                     log_err("Can't open test file - %s\n",
525                             STANDARD_TEST_FILE);
526                 }
527                 uBuffer[0];
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);
536                 }
537                 if (uFileBufferLenReturned != uBufferLenReturned)
538                 {
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);
543                 }
544 */
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;
549                     continue;
550                 }
551 //                u_fclose(testFile);
552             }
553             delete testData;
554         }
555         delete dataModule;
556     }
557     else {
558         log_data_err("Failed: could not load test icuio data\n");
559     }
560 #endif
561 }
562 U_CDECL_END
563
564 U_CDECL_BEGIN
565 static void U_CALLCONV DataDrivenPrintfPrecision(void)
566 {
567 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
568     UErrorCode errorCode;
569     TestDataModule *dataModule;
570     TestData *testData;
571     const DataMap *testCase;
572     DataDrivenLogger logger;
573     UChar uBuffer[512];
574     char cBuffer[512];
575     char cFormat[sizeof(cBuffer)];
576     char cExpected[sizeof(cBuffer)];
577     UnicodeString tempStr;
578     UChar format[512];
579     UChar expectedResult[512];
580     UChar argument[512];
581     int32_t precision;
582     int32_t i;
583     int8_t i8;
584     int16_t i16;
585     int32_t i32;
586     int64_t i64;
587     double dbl;
588     int32_t uBufferLenReturned;
589
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;
600                     continue;
601                 }
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;
616                     continue;
617                 }
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);
623                     break;
624                 case 0x31:  // '1' int8_t
625                     i8 = (int8_t)uto64(argument);
626                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i8);
627                     break;
628                 case 0x32:  // '2' int16_t
629                     i16 = (int16_t)uto64(argument);
630                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i16);
631                     break;
632                 case 0x34:  // '4' int32_t
633                     i32 = (int32_t)uto64(argument);
634                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i32);
635                     break;
636                 case 0x38:  // '8' int64_t
637                     i64 = uto64(argument);
638                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i64);
639                     break;
640                 case 0x73:  // 's' char *
641                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
642                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, cBuffer);
643                     break;
644                 case 0x53:  // 'S' UChar *
645                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, argument);
646                     break;
647                 default:
648                     uBufferLenReturned = 0;
649                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
650                 }
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);
658                 }
659                 if (uBufferLenReturned <= 0) {
660                     log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
661                             i, cBuffer);
662                 }
663                 else if (uBuffer[uBufferLenReturned-1] == 0
664                     || uBuffer[uBufferLenReturned] != 0
665                     || uBuffer[uBufferLenReturned+1] != 0x2A
666                     || uBuffer[uBufferLenReturned+2] != 0x2A)
667                 {
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);
672                 }
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;
677                     continue;
678                 }
679             }
680             delete testData;
681         }
682         delete dataModule;
683     }
684     else {
685         log_data_err("Failed: could not load test icuio data\n");
686     }
687 #endif
688 }
689 U_CDECL_END
690
691 static void addAllTests(TestNode** root) {
692     addFileTest(root);
693     addStringTest(root);
694     addTranslitTest(root);
695
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");
700 #endif
701 #if U_IOSTREAM_SOURCE >= 199711
702     addStreamTests(root);
703 #endif
704 }
705
706 /* returns the path to icu/source/data/out */
707 static const char *ctest_dataOutDir()
708 {
709     static const char *dataOutDir = NULL;
710
711     if(dataOutDir) {
712         return dataOutDir;
713     }
714
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.
722     */
723 #if defined (U_TOPBUILDDIR)
724     {
725         dataOutDir = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
726     }
727 #else
728
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"
732      */
733     {
734         static char p[sizeof(__FILE__) + 20];
735         char *pBackSlash;
736         int i;
737
738         strcpy(p, __FILE__);
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 '\'   */
745             }
746         }
747
748         if (pBackSlash != NULL) {
749             /* We found and truncated three names from the path.
750              *  Now append "source\data" and set the environment
751              */
752             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
753             dataOutDir = p;
754         }
755         else {
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");
758             if (file) {
759                 fclose(file);
760                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
761             }
762             else {
763                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
764             }
765         }
766     }
767 #endif
768
769     return dataOutDir;
770 }
771
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.
780  */
781 static void ctest_setICU_DATA() {
782
783     /* No location for the data dir was identifiable.
784      *   Add other fallbacks for the test data location here if the need arises
785      */
786     if (getenv("ICU_DATA") == NULL) {
787         /* If ICU_DATA isn't set, set it to the usual location */
788         u_setDataDirectory(ctest_dataOutDir());
789     }
790 }
791
792 U_CDECL_BEGIN
793 /*
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()...
797  */
798 static int U_CALLCONV argHandler(int arg, int /*argc*/, const char * const argv[], void *context)
799 {
800     const char **str = (const char **) context;
801
802     if (argv[arg][0] != '/' && argv[arg][0] != '-') {
803         *str = argv[arg];
804         return 1;
805     }
806
807     return 0;
808 }
809 U_CDECL_END
810
811 int main(int argc, char* argv[])
812 {
813     int32_t nerrors = 0;
814     TestNode *root = NULL;
815     UErrorCode errorCode = U_ZERO_ERROR;
816     UDate startTime, endTime;
817     int32_t diffTime;
818
819     startTime = uprv_getRawUTCtime();
820
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.
825     *
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.
828     */
829     u_init(&errorCode);
830     if (U_FAILURE(errorCode)) {
831         fprintf(stderr,
832             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
833     }
834     u_cleanup();
835     errorCode = U_ZERO_ERROR;
836     if (!initArgs(argc, argv, argHandler, (void *) &STANDARD_TEST_FILE)) {
837         /* Error already displayed. */
838         return -1;
839     }
840
841     /* Initialize ICU */
842     ctest_setICU_DATA();    /* u_setDataDirectory() must happen Before u_init() */
843     u_init(&errorCode);
844     if (U_FAILURE(errorCode)) {
845         fprintf(stderr,
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));
849         return 1;
850     }
851
852     fprintf(stdout, "Default charset for this run is %s\n", ucnv_getDefaultName());
853
854     addAllTests(&root);
855     nerrors = runTestRequest(root, argc, argv);
856
857 #if 1
858     {
859         FILE* fileToRemove = fopen(STANDARD_TEST_FILE, "r");
860         /* This should delete any temporary files. */
861         if (fileToRemove) {
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);
867                 nerrors += 1;
868             }
869         }
870     }
871 #endif
872
873     cleanUpTestTree(root);
874     DataDrivenLogger::cleanUp();
875     u_cleanup();
876
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));
884
885     return nerrors;
886 }