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