Home | History | Annotate | Download | only in iotest
      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:
     36     static void cleanUp() {
     37         if (fgTestDataPath) {
     38             free(fgTestDataPath);
     39             fgTestDataPath = NULL;
     40         }
     41     }
     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     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 
     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 
    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 
    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
    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
    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
    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
    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 
    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 */
    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  */
    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  */
    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 
    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