• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **********************************************************************
3 *   Copyright (C) 2002-2012, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 **********************************************************************
6 *   file name:  iotest.cpp
7 *   encoding:   US-ASCII
8 *   tab size:   8 (not used)
9 *   indentation:4
10 *
11 *   created on: 2002feb21
12 *   created by: George Rhoten
13 */
14 
15 
16 #include "unicode/ustdio.h"
17 #include "unicode/uclean.h"
18 
19 #include "unicode/ucnv.h"
20 #include "unicode/uchar.h"
21 #include "unicode/unistr.h"
22 #include "unicode/ustring.h"
23 #include "ustr_cnv.h"
24 #include "iotest.h"
25 #include "unicode/tstdtmod.h"
26 #include "putilimp.h"
27 
28 #include <string.h>
29 #include <stdlib.h>
30 
31 class DataDrivenLogger : public TestLog {
32     static const char* fgDataDir;
33     static char *fgTestDataPath;
34 
35 public:
cleanUp()36     static void cleanUp() {
37         if (fgTestDataPath) {
38             free(fgTestDataPath);
39             fgTestDataPath = NULL;
40         }
41     }
errln(const UnicodeString & message)42     virtual void errln( const UnicodeString &message ) {
43         char buffer[4000];
44         message.extract(0, message.length(), buffer, sizeof(buffer));
45         buffer[3999] = 0; /* NULL terminate */
46         log_err(buffer);
47     }
48 
logln(const UnicodeString & message)49     virtual void logln( const UnicodeString &message ) {
50         char buffer[4000];
51         message.extract(0, message.length(), buffer, sizeof(buffer));
52         buffer[3999] = 0; /* NULL terminate */
53         log_info(buffer);
54     }
55 
dataerrln(const UnicodeString & message)56     virtual void dataerrln( const UnicodeString &message ) {
57         char buffer[4000];
58         message.extract(0, message.length(), buffer, sizeof(buffer));
59         buffer[3999] = 0; /* NULL terminate */
60         log_data_err(buffer);
61     }
62 
pathToDataDirectory(void)63     static const char * pathToDataDirectory(void)
64     {
65 
66         if(fgDataDir != NULL) {
67             return fgDataDir;
68         }
69 
70         /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
71         //              to point to the top of the build hierarchy, which may or
72         //              may not be the same as the source directory, depending on
73         //              the configure options used.  At any rate,
74         //              set the data path to the built data from this directory.
75         //              The value is complete with quotes, so it can be used
76         //              as-is as a string constant.
77         */
78     #if defined (U_TOPSRCDIR)
79         {
80             fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
81         }
82     #else
83 
84         /* On Windows, the file name obtained from __FILE__ includes a full path.
85         *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
86         *             Change to    "wherever\icu\source\data"
87         */
88         {
89             static char p[sizeof(__FILE__) + 10];
90             char *pBackSlash;
91             int i;
92 
93             strcpy(p, __FILE__);
94             /* We want to back over three '\' chars.                            */
95             /*   Only Windows should end up here, so looking for '\' is safe.   */
96             for (i=1; i<=3; i++) {
97                 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
98                 if (pBackSlash != NULL) {
99                     *pBackSlash = 0;        /* Truncate the string at the '\'   */
100                 }
101             }
102 
103             if (pBackSlash != NULL) {
104                 /* We found and truncated three names from the path.
105                 *  Now append "source\data" and set the environment
106                 */
107                 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
108                 fgDataDir = p;
109             }
110             else {
111                 /* __FILE__ on MSVC7 does not contain the directory */
112                 FILE *file = fopen(".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
113                 if (file) {
114                     fclose(file);
115                     fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
116                 }
117                 else {
118                     fgDataDir = ".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
119                 }
120             }
121         }
122     #endif
123 
124         return fgDataDir;
125 
126     }
127 
loadTestData(UErrorCode & err)128     static const char* loadTestData(UErrorCode& err){
129         if( fgTestDataPath == NULL){
130             const char*      directory=NULL;
131             UResourceBundle* test =NULL;
132             char* tdpath=NULL;
133             const char* tdrelativepath;
134 
135 #if defined (U_TOPBUILDDIR)
136             tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
137             directory = U_TOPBUILDDIR;
138 #else
139             tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
140             directory = pathToDataDirectory();
141 #endif
142 
143             tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
144 
145 
146             /* u_getDataDirectory shoul return \source\data ... set the
147             * directory to ..\source\data\..\test\testdata\out\testdata
148             */
149             strcpy(tdpath, directory);
150             strcat(tdpath, tdrelativepath);
151             strcat(tdpath,"testdata");
152 
153             test=ures_open(tdpath, "testtypes", &err);
154 
155             if(U_FAILURE(err)){
156                 err = U_FILE_ACCESS_ERROR;
157                 log_data_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(err));
158                 return "";
159             }
160             ures_close(test);
161             fgTestDataPath = tdpath;
162         }
163         return fgTestDataPath;
164     }
165 
getTestDataPath(UErrorCode & err)166     virtual const char* getTestDataPath(UErrorCode& err) {
167         return loadTestData(err);
168     }
169 };
170 
171 const char* DataDrivenLogger::fgDataDir = NULL;
172 char* DataDrivenLogger::fgTestDataPath = NULL;
173 
174 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
175 static int64_t
uto64(const UChar * buffer)176 uto64(const UChar     *buffer)
177 {
178     int64_t result = 0;
179     /* iterate through buffer */
180     while(*buffer) {
181         /* read the next digit */
182         result *= 16;
183         if (!u_isxdigit(*buffer)) {
184             log_err("\\u%04X is not a valid hex digit for this test\n", (UChar)*buffer);
185         }
186         result += *buffer - 0x0030 - (*buffer >= 0x0041 ? (*buffer >= 0x0061 ? 39 : 7) : 0);
187         buffer++;
188     }
189     return result;
190 }
191 #endif
192 
193 U_CDECL_BEGIN
DataDrivenPrintf(void)194 static void U_CALLCONV DataDrivenPrintf(void)
195 {
196 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
197     UErrorCode errorCode;
198     TestDataModule *dataModule;
199     TestData *testData;
200     const DataMap *testCase;
201     DataDrivenLogger logger;
202     UChar uBuffer[512];
203     char cBuffer[512];
204     char cFormat[sizeof(cBuffer)];
205     char cExpected[sizeof(cBuffer)];
206     UnicodeString tempStr;
207     UChar format[512];
208     UChar expectedResult[512];
209     UChar argument[512];
210     int32_t i;
211     int8_t i8;
212     int16_t i16;
213     int32_t i32;
214     int64_t i64;
215     double dbl;
216     int32_t uBufferLenReturned;
217 
218     const char *fileLocale = "en_US_POSIX";
219     int32_t uFileBufferLenReturned;
220     LocalUFILEPointer testFile;
221 
222     errorCode=U_ZERO_ERROR;
223     dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
224     if(U_SUCCESS(errorCode)) {
225         testData=dataModule->createTestData("printf", errorCode);
226         if(U_SUCCESS(errorCode)) {
227             for(i=0; testData->nextCase(testCase, errorCode); ++i) {
228                 if(U_FAILURE(errorCode)) {
229                     log_err("error retrieving icuio/printf test case %d - %s\n",
230                             i, u_errorName(errorCode));
231                     errorCode=U_ZERO_ERROR;
232                     continue;
233                 }
234                 testFile.adoptInstead(u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8"));
235                 if (testFile.isNull()) {
236                     log_err("Can't open test file - %s\n",
237                             STANDARD_TEST_FILE);
238                     continue;
239                 }
240                 u_memset(uBuffer, 0x2A, sizeof(uBuffer)/sizeof(uBuffer[0]));
241                 uBuffer[sizeof(uBuffer)/sizeof(uBuffer[0])-1] = 0;
242                 tempStr=testCase->getString("format", errorCode);
243                 tempStr.extract(format, sizeof(format)/sizeof(format[0]), errorCode);
244                 tempStr=testCase->getString("result", errorCode);
245                 tempStr.extract(expectedResult, sizeof(expectedResult)/sizeof(expectedResult[0]), errorCode);
246                 tempStr=testCase->getString("argument", errorCode);
247                 tempStr.extract(argument, sizeof(argument)/sizeof(argument[0]), errorCode);
248                 u_austrncpy(cBuffer, format, sizeof(cBuffer));
249                 if(U_FAILURE(errorCode)) {
250                     log_err("error retrieving icuio/printf test case %d - %s\n",
251                             i, u_errorName(errorCode));
252                     errorCode=U_ZERO_ERROR;
253                     continue;
254                 }
255                 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
256                 switch (testCase->getString("argumentType", errorCode)[0]) {
257                 case 0x64:  // 'd' double
258                     dbl = atof(u_austrcpy(cBuffer, argument));
259                     uBufferLenReturned = u_sprintf_u(uBuffer, format, dbl);
260                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, dbl);
261                     break;
262                 case 0x31:  // '1' int8_t
263                     i8 = (int8_t)uto64(argument);
264                     uBufferLenReturned = u_sprintf_u(uBuffer, format, i8);
265                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i8);
266                     break;
267                 case 0x32:  // '2' int16_t
268                     i16 = (int16_t)uto64(argument);
269                     uBufferLenReturned = u_sprintf_u(uBuffer, format, i16);
270                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i16);
271                     break;
272                 case 0x34:  // '4' int32_t
273                     i32 = (int32_t)uto64(argument);
274                     uBufferLenReturned = u_sprintf_u(uBuffer, format, i32);
275                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i32);
276                     break;
277                 case 0x38:  // '8' int64_t
278                     i64 = uto64(argument);
279                     uBufferLenReturned = u_sprintf_u(uBuffer, format, i64);
280                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, i64);
281                     break;
282                 case 0x73:  // 's' char *
283                     u_austrncpy(cBuffer, argument, sizeof(cBuffer));
284                     uBufferLenReturned = u_sprintf_u(uBuffer, format, cBuffer);
285                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, cBuffer);
286                     break;
287                 case 0x53:  // 'S' UChar *
288                     uBufferLenReturned = u_sprintf_u(uBuffer, format, argument);
289                     uFileBufferLenReturned = u_fprintf_u(testFile.getAlias(), format, argument);
290                     break;
291                 default:
292                     uBufferLenReturned = 0;
293                     uFileBufferLenReturned = 0;
294                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
295                 }
296                 if (u_strcmp(uBuffer, expectedResult) != 0) {
297                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
298                     u_austrncpy(cFormat, format, sizeof(cFormat));
299                     u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
300                     cBuffer[sizeof(cBuffer)-1] = 0;
301                     log_err("FAILURE string test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
302                             i, cFormat, cBuffer, cExpected);
303                 }
304                 if (uBufferLenReturned <= 0) {
305                     log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
306                             i, cBuffer);
307                 }
308                 else if (uBuffer[uBufferLenReturned-1] == 0
309                     || uBuffer[uBufferLenReturned] != 0
310                     || uBuffer[uBufferLenReturned+1] != 0x2A
311                     || uBuffer[uBufferLenReturned+2] != 0x2A)
312                 {
313                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
314                     cBuffer[sizeof(cBuffer)-1] = 0;
315                     log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
316                             i, cBuffer, uBufferLenReturned);
317                 }
318                 testFile.adoptInstead(u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8"));
319                 if (testFile.isNull()) {
320                     log_err("Can't open test file - %s\n",
321                             STANDARD_TEST_FILE);
322                 }
323                 uBuffer[0]=0;
324                 u_fgets(uBuffer, sizeof(uBuffer)/sizeof(uBuffer[0]), testFile.getAlias());
325                 if (u_strcmp(uBuffer, expectedResult) != 0) {
326                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
327                     u_austrncpy(cFormat, format, sizeof(cFormat));
328                     u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
329                     cBuffer[sizeof(cBuffer)-1] = 0;
330                     log_err("FAILURE file test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
331                             i, cFormat, cBuffer, cExpected);
332                 }
333                 if (uFileBufferLenReturned != uBufferLenReturned)
334                 {
335                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
336                     cBuffer[sizeof(cBuffer)-1] = 0;
337                     log_err("FAILURE uFileBufferLenReturned(%d) != uBufferLenReturned(%d)\n",
338                             uFileBufferLenReturned, uBufferLenReturned);
339                 }
340 
341                 if(U_FAILURE(errorCode)) {
342                     log_err("error running icuio/printf test case %d - %s\n",
343                             i, u_errorName(errorCode));
344                     errorCode=U_ZERO_ERROR;
345                     continue;
346                 }
347             }
348             delete testData;
349         }
350         delete dataModule;
351     }
352     else {
353         log_data_err("Failed: could not load test icuio data\n");
354     }
355 #endif
356 }
357 U_CDECL_END
358 
359 U_CDECL_BEGIN
DataDrivenScanf(void)360 static void U_CALLCONV DataDrivenScanf(void)
361 {
362 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
363     UErrorCode errorCode;
364     TestDataModule *dataModule;
365     TestData *testData;
366     const DataMap *testCase;
367     DataDrivenLogger logger;
368     UChar uBuffer[512];
369     char cBuffer[512];
370     char cExpected[sizeof(cBuffer)];
371     UnicodeString tempStr;
372     UChar format[512];
373     UChar expectedResult[512];
374     UChar argument[512];
375     int32_t i;
376     int8_t i8, expected8;
377     int16_t i16, expected16;
378     int32_t i32, expected32;
379     int64_t i64, expected64;
380     double dbl, expectedDbl;
381     volatile float flt, expectedFlt; // Use volatile in order to get around an Intel compiler issue.
382     int32_t uBufferLenReturned;
383 
384     //const char *fileLocale = "en_US_POSIX";
385     //int32_t uFileBufferLenReturned;
386     //UFILE *testFile;
387 
388     errorCode=U_ZERO_ERROR;
389     dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
390     if(U_SUCCESS(errorCode)) {
391         testData=dataModule->createTestData("scanf", errorCode);
392         if(U_SUCCESS(errorCode)) {
393             for(i=0; testData->nextCase(testCase, errorCode); ++i) {
394                 if(U_FAILURE(errorCode)) {
395                     log_err("error retrieving icuio/printf test case %d - %s\n",
396                             i, u_errorName(errorCode));
397                     errorCode=U_ZERO_ERROR;
398                     continue;
399                 }
400 /*                testFile = u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8");
401                 if (!testFile) {
402                     log_err("Can't open test file - %s\n",
403                             STANDARD_TEST_FILE);
404                 }*/
405                 u_memset(uBuffer, 0x2A, sizeof(uBuffer)/sizeof(uBuffer[0]));
406                 uBuffer[sizeof(uBuffer)/sizeof(uBuffer[0])-1] = 0;
407                 tempStr=testCase->getString("format", errorCode);
408                 tempStr.extract(format, sizeof(format)/sizeof(format[0]), errorCode);
409                 tempStr=testCase->getString("result", errorCode);
410                 tempStr.extract(expectedResult, sizeof(expectedResult)/sizeof(expectedResult[0]), errorCode);
411                 tempStr=testCase->getString("argument", errorCode);
412                 tempStr.extract(argument, sizeof(argument)/sizeof(argument[0]), errorCode);
413                 u_austrncpy(cBuffer, format, sizeof(cBuffer));
414                 if(U_FAILURE(errorCode)) {
415                     log_err("error retrieving icuio/printf test case %d - %s\n",
416                             i, u_errorName(errorCode));
417                     errorCode=U_ZERO_ERROR;
418                     continue;
419                 }
420                 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
421                 switch (testCase->getString("argumentType", errorCode)[0]) {
422                 case 0x64:  // 'd' double
423                     expectedDbl = atof(u_austrcpy(cBuffer, expectedResult));
424                     uBufferLenReturned = u_sscanf_u(argument, format, &dbl);
425                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, dbl);
426                     if (dbl != expectedDbl) {
427                         log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
428                                 i, dbl, expectedDbl);
429                     }
430                     break;
431                 case 0x66:  // 'f' float
432                     expectedFlt = (float)atof(u_austrcpy(cBuffer, expectedResult));
433                     uBufferLenReturned = u_sscanf_u(argument, format, &flt);
434                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, flt);
435                     if (flt != expectedFlt) {
436                         log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
437                                 i, flt, expectedFlt);
438                     }
439                     break;
440                 case 0x31:  // '1' int8_t
441                     expected8 = (int8_t)uto64(expectedResult);
442                     uBufferLenReturned = u_sscanf_u(argument, format, &i8);
443                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, i8);
444                     if (i8 != expected8) {
445                         log_err("error in scanf test case[%d] Got: %02X Exp: %02X\n",
446                                 i, i8, expected8);
447                     }
448                     break;
449                 case 0x32:  // '2' int16_t
450                     expected16 = (int16_t)uto64(expectedResult);
451                     uBufferLenReturned = u_sscanf_u(argument, format, &i16);
452                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, i16);
453                     if (i16 != expected16) {
454                         log_err("error in scanf test case[%d] Got: %04X Exp: %04X\n",
455                                 i, i16, expected16);
456                     }
457                     break;
458                 case 0x34:  // '4' int32_t
459                     expected32 = (int32_t)uto64(expectedResult);
460                     uBufferLenReturned = u_sscanf_u(argument, format, &i32);
461                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, i32);
462                     if (i32 != expected32) {
463                         log_err("error in scanf test case[%d] Got: %08X Exp: %08X\n",
464                                 i, i32, expected32);
465                     }
466                     break;
467                 case 0x38:  // '8' int64_t
468                     expected64 = uto64(expectedResult);
469                     uBufferLenReturned = u_sscanf_u(argument, format, &i64);
470                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, i64);
471                     if (i64 != expected64) {
472                         log_err("error in scanf 64-bit. Test case = %d\n", i);
473                     }
474                     break;
475                 case 0x73:  // 's' char *
476                     u_austrcpy(cExpected, expectedResult);
477                     uBufferLenReturned = u_sscanf_u(argument, format, cBuffer);
478                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, cBuffer);
479                     if (strcmp(cBuffer, cExpected) != 0) {
480                         log_err("error in scanf char * string. Got \"%s\" Expected \"%s\". Test case = %d\n", cBuffer, cExpected, i);
481                     }
482                     break;
483                 case 0x53:  // 'S' UChar *
484                     uBufferLenReturned = u_sscanf_u(argument, format, uBuffer);
485                     //uFileBufferLenReturned = u_fscanf_u(testFile, format, argument);
486                     if (u_strcmp(uBuffer, expectedResult) != 0) {
487                         u_austrcpy(cExpected, format);
488                         u_austrcpy(cBuffer, uBuffer);
489                         log_err("error in scanf UChar * string %s Got: \"%s\". Test case = %d\n", cExpected, cBuffer, i);
490                     }
491                     break;
492                 default:
493                     uBufferLenReturned = 0;
494                     //uFileBufferLenReturned = 0;
495                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
496                 }
497                 if (uBufferLenReturned != 1) {
498                     log_err("error scanf converted %d arguments. Test case = %d\n", uBufferLenReturned, i);
499                 }
500 /*                if (u_strcmp(uBuffer, expectedResult) != 0) {
501                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
502                     u_austrncpy(cFormat, format, sizeof(cFormat));
503                     u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
504                     cBuffer[sizeof(cBuffer)-1] = 0;
505                     log_err("FAILURE string test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
506                             i, cFormat, cBuffer, cExpected);
507                 }
508                 if (uBuffer[uBufferLenReturned-1] == 0
509                     || uBuffer[uBufferLenReturned] != 0
510                     || uBuffer[uBufferLenReturned+1] != 0x2A
511                     || uBuffer[uBufferLenReturned+2] != 0x2A)
512                 {
513                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
514                     cBuffer[sizeof(cBuffer)-1] = 0;
515                     log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
516                             i, cBuffer, uBufferLenReturned);
517                 }*/
518 /*                u_fclose(testFile);
519                 testFile = u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8");
520                 if (!testFile) {
521                     log_err("Can't open test file - %s\n",
522                             STANDARD_TEST_FILE);
523                 }
524                 uBuffer[0];
525                 u_fgets(uBuffer, sizeof(uBuffer)/sizeof(uBuffer[0]), testFile);
526                 if (u_strcmp(uBuffer, expectedResult) != 0) {
527                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
528                     u_austrncpy(cFormat, format, sizeof(cFormat));
529                     u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
530                     cBuffer[sizeof(cBuffer)-1] = 0;
531                     log_err("FAILURE file test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
532                             i, cFormat, cBuffer, cExpected);
533                 }
534                 if (uFileBufferLenReturned != uBufferLenReturned)
535                 {
536                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
537                     cBuffer[sizeof(cBuffer)-1] = 0;
538                     log_err("FAILURE uFileBufferLenReturned(%d) != uBufferLenReturned(%d)\n",
539                             uFileBufferLenReturned, uBufferLenReturned);
540                 }
541 */
542                 if(U_FAILURE(errorCode)) {
543                     log_err("error running icuio/printf test case %d - %s\n",
544                             i, u_errorName(errorCode));
545                     errorCode=U_ZERO_ERROR;
546                     continue;
547                 }
548 //                u_fclose(testFile);
549             }
550             delete testData;
551         }
552         delete dataModule;
553     }
554     else {
555         log_data_err("Failed: could not load test icuio data\n");
556     }
557 #endif
558 }
559 U_CDECL_END
560 
561 U_CDECL_BEGIN
DataDrivenPrintfPrecision(void)562 static void U_CALLCONV DataDrivenPrintfPrecision(void)
563 {
564 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
565     UErrorCode errorCode;
566     TestDataModule *dataModule;
567     TestData *testData;
568     const DataMap *testCase;
569     DataDrivenLogger logger;
570     UChar uBuffer[512];
571     char cBuffer[512];
572     char cFormat[sizeof(cBuffer)];
573     char cExpected[sizeof(cBuffer)];
574     UnicodeString tempStr;
575     UChar format[512];
576     UChar expectedResult[512];
577     UChar argument[512];
578     int32_t precision;
579     int32_t i;
580     int8_t i8;
581     int16_t i16;
582     int32_t i32;
583     int64_t i64;
584     double dbl;
585     int32_t uBufferLenReturned;
586 
587     errorCode=U_ZERO_ERROR;
588     dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
589     if(U_SUCCESS(errorCode)) {
590         testData=dataModule->createTestData("printfPrecision", errorCode);
591         if(U_SUCCESS(errorCode)) {
592             for(i=0; testData->nextCase(testCase, errorCode); ++i) {
593                 if(U_FAILURE(errorCode)) {
594                     log_err("error retrieving icuio/printf test case %d - %s\n",
595                             i, u_errorName(errorCode));
596                     errorCode=U_ZERO_ERROR;
597                     continue;
598                 }
599                 u_memset(uBuffer, 0x2A, sizeof(uBuffer)/sizeof(uBuffer[0]));
600                 uBuffer[sizeof(uBuffer)/sizeof(uBuffer[0])-1] = 0;
601                 tempStr=testCase->getString("format", errorCode);
602                 tempStr.extract(format, sizeof(format)/sizeof(format[0]), errorCode);
603                 tempStr=testCase->getString("result", errorCode);
604                 tempStr.extract(expectedResult, sizeof(expectedResult)/sizeof(expectedResult[0]), errorCode);
605                 tempStr=testCase->getString("argument", errorCode);
606                 tempStr.extract(argument, sizeof(argument)/sizeof(argument[0]), errorCode);
607                 precision=testCase->getInt28("precision", errorCode);
608                 u_austrncpy(cBuffer, format, sizeof(cBuffer));
609                 if(U_FAILURE(errorCode)) {
610                     log_err("error retrieving icuio/printf test case %d - %s\n",
611                             i, u_errorName(errorCode));
612                     errorCode=U_ZERO_ERROR;
613                     continue;
614                 }
615                 log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
616                 switch (testCase->getString("argumentType", errorCode)[0]) {
617                 case 0x64:  // 'd' double
618                     dbl = atof(u_austrcpy(cBuffer, argument));
619                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, dbl);
620                     break;
621                 case 0x31:  // '1' int8_t
622                     i8 = (int8_t)uto64(argument);
623                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i8);
624                     break;
625                 case 0x32:  // '2' int16_t
626                     i16 = (int16_t)uto64(argument);
627                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i16);
628                     break;
629                 case 0x34:  // '4' int32_t
630                     i32 = (int32_t)uto64(argument);
631                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i32);
632                     break;
633                 case 0x38:  // '8' int64_t
634                     i64 = uto64(argument);
635                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i64);
636                     break;
637                 case 0x73:  // 's' char *
638                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
639                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, cBuffer);
640                     break;
641                 case 0x53:  // 'S' UChar *
642                     uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, argument);
643                     break;
644                 default:
645                     uBufferLenReturned = 0;
646                     log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
647                 }
648                 if (u_strcmp(uBuffer, expectedResult) != 0) {
649                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
650                     u_austrncpy(cFormat, format, sizeof(cFormat));
651                     u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
652                     cBuffer[sizeof(cBuffer)-1] = 0;
653                     log_err("FAILURE test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
654                             i, cFormat, cBuffer, cExpected);
655                 }
656                 if (uBufferLenReturned <= 0) {
657                     log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
658                             i, cBuffer);
659                 }
660                 else if (uBuffer[uBufferLenReturned-1] == 0
661                     || uBuffer[uBufferLenReturned] != 0
662                     || uBuffer[uBufferLenReturned+1] != 0x2A
663                     || uBuffer[uBufferLenReturned+2] != 0x2A)
664                 {
665                     u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
666                     cBuffer[sizeof(cBuffer)-1] = 0;
667                     log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
668                             i, cBuffer, uBufferLenReturned);
669                 }
670                 if(U_FAILURE(errorCode)) {
671                     log_err("error running icuio/printf test case %d - %s\n",
672                             i, u_errorName(errorCode));
673                     errorCode=U_ZERO_ERROR;
674                     continue;
675                 }
676             }
677             delete testData;
678         }
679         delete dataModule;
680     }
681     else {
682         log_data_err("Failed: could not load test icuio data\n");
683     }
684 #endif
685 }
686 U_CDECL_END
687 
addAllTests(TestNode ** root)688 static void addAllTests(TestNode** root) {
689     addFileTest(root);
690     addStringTest(root);
691     addTranslitTest(root);
692 
693 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_LEGACY_CONVERSION
694     addTest(root, &DataDrivenPrintf, "datadriv/DataDrivenPrintf");
695     addTest(root, &DataDrivenPrintfPrecision, "datadriv/DataDrivenPrintfPrecision");
696     addTest(root, &DataDrivenScanf, "datadriv/DataDrivenScanf");
697 #endif
698 #if U_IOSTREAM_SOURCE >= 199711
699     addStreamTests(root);
700 #endif
701 }
702 
703 /* returns the path to icu/source/data/out */
ctest_dataOutDir()704 static const char *ctest_dataOutDir()
705 {
706     static const char *dataOutDir = NULL;
707 
708     if(dataOutDir) {
709         return dataOutDir;
710     }
711 
712     /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
713     //              to point to the top of the build hierarchy, which may or
714     //              may not be the same as the source directory, depending on
715     //              the configure options used.  At any rate,
716     //              set the data path to the built data from this directory.
717     //              The value is complete with quotes, so it can be used
718     //              as-is as a string constant.
719     */
720 #if defined (U_TOPBUILDDIR)
721     {
722         dataOutDir = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
723     }
724 #else
725 
726     /* On Windows, the file name obtained from __FILE__ includes a full path.
727      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
728      *             Change to    "wherever\icu\source\data"
729      */
730     {
731         static char p[sizeof(__FILE__) + 20];
732         char *pBackSlash;
733         int i;
734 
735         strcpy(p, __FILE__);
736         /* We want to back over three '\' chars.                            */
737         /*   Only Windows should end up here, so looking for '\' is safe.   */
738         for (i=1; i<=3; i++) {
739             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
740             if (pBackSlash != NULL) {
741                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
742             }
743         }
744 
745         if (pBackSlash != NULL) {
746             /* We found and truncated three names from the path.
747              *  Now append "source\data" and set the environment
748              */
749             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
750             dataOutDir = p;
751         }
752         else {
753             /* __FILE__ on MSVC7 does not contain the directory */
754             FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
755             if (file) {
756                 fclose(file);
757                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
758             }
759             else {
760                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
761             }
762         }
763     }
764 #endif
765 
766     return dataOutDir;
767 }
768 
769 /*  ctest_setICU_DATA  - if the ICU_DATA environment variable is not already
770  *                       set, try to deduce the directory in which ICU was built,
771  *                       and set ICU_DATA to "icu/source/data" in that location.
772  *                       The intent is to allow the tests to have a good chance
773  *                       of running without requiring that the user manually set
774  *                       ICU_DATA.  Common data isn't a problem, since it is
775  *                       picked up via a static (build time) reference, but the
776  *                       tests dynamically load some data.
777  */
ctest_setICU_DATA()778 static void ctest_setICU_DATA() {
779 
780     /* No location for the data dir was identifiable.
781      *   Add other fallbacks for the test data location here if the need arises
782      */
783     if (getenv("ICU_DATA") == NULL) {
784         /* If ICU_DATA isn't set, set it to the usual location */
785         u_setDataDirectory(ctest_dataOutDir());
786     }
787 }
788 
789 U_CDECL_BEGIN
790 /*
791  * Note: this assumes that context is a pointer to STANDARD_TEST_FILE. It would be
792  * cleaner to define an acutal context with a string pointer in it and set STANDARD_TEST_FILE
793  * after the call to initArgs()...
794  */
argHandler(int arg,int,const char * const argv[],void * context)795 static int U_CALLCONV argHandler(int arg, int /*argc*/, const char * const argv[], void *context)
796 {
797     const char **str = (const char **) context;
798 
799     if (argv[arg][0] != '/' && argv[arg][0] != '-') {
800         *str = argv[arg];
801         return 1;
802     }
803 
804     return 0;
805 }
806 U_CDECL_END
807 
main(int argc,char * argv[])808 int main(int argc, char* argv[])
809 {
810     int32_t nerrors = 0;
811     TestNode *root = NULL;
812     UErrorCode errorCode = U_ZERO_ERROR;
813     UDate startTime, endTime;
814     int32_t diffTime;
815 
816     startTime = uprv_getRawUTCtime();
817 
818     /* Check whether ICU will initialize without forcing the build data directory into
819     *  the ICU_DATA path.  Success here means either the data dll contains data, or that
820     *  this test program was run with ICU_DATA set externally.  Failure of this check
821     *  is normal when ICU data is not packaged into a shared library.
822     *
823     *  Whether or not this test succeeds, we want to cleanup and reinitialize
824     *  with a data path so that data loading from individual files can be tested.
825     */
826     u_init(&errorCode);
827     if (U_FAILURE(errorCode)) {
828         fprintf(stderr,
829             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
830     }
831     u_cleanup();
832     errorCode = U_ZERO_ERROR;
833     if (!initArgs(argc, argv, argHandler, (void *) &STANDARD_TEST_FILE)) {
834         /* Error already displayed. */
835         return -1;
836     }
837 
838     /* Initialize ICU */
839     ctest_setICU_DATA();    /* u_setDataDirectory() must happen Before u_init() */
840     u_init(&errorCode);
841     if (U_FAILURE(errorCode)) {
842         fprintf(stderr,
843             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
844             "*** Check the ICU_DATA environment variable and \n"
845             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
846         return 1;
847     }
848 
849     fprintf(stdout, "Default charset for this run is %s\n", ucnv_getDefaultName());
850 
851     addAllTests(&root);
852     nerrors = runTestRequest(root, argc, argv);
853 
854 #if 1
855     {
856         FILE* fileToRemove = fopen(STANDARD_TEST_FILE, "r");
857         /* This should delete any temporary files. */
858         if (fileToRemove) {
859             fclose(fileToRemove);
860             log_verbose("Deleting: %s\n", STANDARD_TEST_FILE);
861             if (remove(STANDARD_TEST_FILE) != 0) {
862                 /* Maybe someone didn't close the file correctly. */
863                 fprintf(stderr, "FAIL: Could not delete %s\n", STANDARD_TEST_FILE);
864                 nerrors += 1;
865             }
866         }
867     }
868 #endif
869 
870     cleanUpTestTree(root);
871     DataDrivenLogger::cleanUp();
872     u_cleanup();
873 
874     endTime = uprv_getRawUTCtime();
875     diffTime = (int32_t)(endTime - startTime);
876     printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
877         (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
878         (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
879         (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
880         (int)(diffTime%U_MILLIS_PER_SECOND));
881 
882     return nerrors;
883 }
884