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