Home | History | Annotate | Download | only in iotest
      1 //  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:   UTF-8
     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     addStreamTests(root);
    702 }
    703 
    704 /* returns the path to icu/source/data/out */
    705 static const char *ctest_dataOutDir()
    706 {
    707     static const char *dataOutDir = NULL;
    708 
    709     if(dataOutDir) {
    710         return dataOutDir;
    711     }
    712 
    713     /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
    714     //              to point to the top of the build hierarchy, which may or
    715     //              may not be the same as the source directory, depending on
    716     //              the configure options used.  At any rate,
    717     //              set the data path to the built data from this directory.
    718     //              The value is complete with quotes, so it can be used
    719     //              as-is as a string constant.
    720     */
    721 #if defined (U_TOPBUILDDIR)
    722     {
    723         dataOutDir = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
    724     }
    725 #else
    726 
    727     /* On Windows, the file name obtained from __FILE__ includes a full path.
    728      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
    729      *             Change to    "wherever\icu\source\data"
    730      */
    731     {
    732         static char p[sizeof(__FILE__) + 20];
    733         char *pBackSlash;
    734         int i;
    735 
    736         strcpy(p, __FILE__);
    737         /* We want to back over three '\' chars.                            */
    738         /*   Only Windows should end up here, so looking for '\' is safe.   */
    739         for (i=1; i<=3; i++) {
    740             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
    741             if (pBackSlash != NULL) {
    742                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
    743             }
    744         }
    745 
    746         if (pBackSlash != NULL) {
    747             /* We found and truncated three names from the path.
    748              *  Now append "source\data" and set the environment
    749              */
    750             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
    751             dataOutDir = p;
    752         }
    753         else {
    754             /* __FILE__ on MSVC7 does not contain the directory */
    755             FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
    756             if (file) {
    757                 fclose(file);
    758                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
    759             }
    760             else {
    761                 dataOutDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
    762             }
    763         }
    764     }
    765 #endif
    766 
    767     return dataOutDir;
    768 }
    769 
    770 /*  ctest_setICU_DATA  - if the ICU_DATA environment variable is not already
    771  *                       set, try to deduce the directory in which ICU was built,
    772  *                       and set ICU_DATA to "icu/source/data" in that location.
    773  *                       The intent is to allow the tests to have a good chance
    774  *                       of running without requiring that the user manually set
    775  *                       ICU_DATA.  Common data isn't a problem, since it is
    776  *                       picked up via a static (build time) reference, but the
    777  *                       tests dynamically load some data.
    778  */
    779 static void ctest_setICU_DATA() {
    780 
    781     /* No location for the data dir was identifiable.
    782      *   Add other fallbacks for the test data location here if the need arises
    783      */
    784     if (getenv("ICU_DATA") == NULL) {
    785         /* If ICU_DATA isn't set, set it to the usual location */
    786         u_setDataDirectory(ctest_dataOutDir());
    787     }
    788 }
    789 
    790 U_CDECL_BEGIN
    791 /*
    792  * Note: this assumes that context is a pointer to STANDARD_TEST_FILE. It would be
    793  * cleaner to define an acutal context with a string pointer in it and set STANDARD_TEST_FILE
    794  * after the call to initArgs()...
    795  */
    796 static int U_CALLCONV argHandler(int arg, int /*argc*/, const char * const argv[], void *context)
    797 {
    798     const char **str = (const char **) context;
    799 
    800     if (argv[arg][0] != '/' && argv[arg][0] != '-') {
    801         *str = argv[arg];
    802         return 1;
    803     }
    804 
    805     return 0;
    806 }
    807 U_CDECL_END
    808 
    809 int main(int argc, char* argv[])
    810 {
    811     int32_t nerrors = 0;
    812     TestNode *root = NULL;
    813     UErrorCode errorCode = U_ZERO_ERROR;
    814     UDate startTime, endTime;
    815     int32_t diffTime;
    816 
    817     startTime = uprv_getRawUTCtime();
    818 
    819     /* Check whether ICU will initialize without forcing the build data directory into
    820     *  the ICU_DATA path.  Success here means either the data dll contains data, or that
    821     *  this test program was run with ICU_DATA set externally.  Failure of this check
    822     *  is normal when ICU data is not packaged into a shared library.
    823     *
    824     *  Whether or not this test succeeds, we want to cleanup and reinitialize
    825     *  with a data path so that data loading from individual files can be tested.
    826     */
    827     u_init(&errorCode);
    828     if (U_FAILURE(errorCode)) {
    829         fprintf(stderr,
    830             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
    831     }
    832     u_cleanup();
    833     errorCode = U_ZERO_ERROR;
    834     if (!initArgs(argc, argv, argHandler, (void *) &STANDARD_TEST_FILE)) {
    835         /* Error already displayed. */
    836         return -1;
    837     }
    838 
    839     /* Initialize ICU */
    840     ctest_setICU_DATA();    /* u_setDataDirectory() must happen Before u_init() */
    841     u_init(&errorCode);
    842     if (U_FAILURE(errorCode)) {
    843         fprintf(stderr,
    844             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
    845             "*** Check the ICU_DATA environment variable and \n"
    846             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
    847         return 1;
    848     }
    849 
    850     fprintf(stdout, "Default charset for this run is %s\n", ucnv_getDefaultName());
    851 
    852     addAllTests(&root);
    853     nerrors = runTestRequest(root, argc, argv);
    854 
    855 #if 1
    856     {
    857         FILE* fileToRemove = fopen(STANDARD_TEST_FILE, "r");
    858         /* This should delete any temporary files. */
    859         if (fileToRemove) {
    860             fclose(fileToRemove);
    861             log_verbose("Deleting: %s\n", STANDARD_TEST_FILE);
    862             if (remove(STANDARD_TEST_FILE) != 0) {
    863                 /* Maybe someone didn't close the file correctly. */
    864                 fprintf(stderr, "FAIL: Could not delete %s\n", STANDARD_TEST_FILE);
    865                 nerrors += 1;
    866             }
    867         }
    868     }
    869 #endif
    870 
    871     cleanUpTestTree(root);
    872     DataDrivenLogger::cleanUp();
    873     u_cleanup();
    874 
    875     endTime = uprv_getRawUTCtime();
    876     diffTime = (int32_t)(endTime - startTime);
    877     printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
    878         (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
    879         (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
    880         (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
    881         (int)(diffTime%U_MILLIS_PER_SECOND));
    882 
    883     return nerrors;
    884 }
    885