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