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