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:
cleanUp()36 static void cleanUp() {
37 if (fgTestDataPath) {
38 free(fgTestDataPath);
39 fgTestDataPath = NULL;
40 }
41 }
errln(const UnicodeString & message)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
logln(const UnicodeString & message)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
dataerrln(const UnicodeString & message)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
pathToDataDirectory(void)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
loadTestData(UErrorCode & err)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
getTestDataPath(UErrorCode & err)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
uto64(const UChar * buffer)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
DataDrivenPrintf(void)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
DataDrivenScanf(void)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
DataDrivenPrintfPrecision(void)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
addAllTests(TestNode ** root)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 */
ctest_dataOutDir()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 */
ctest_setICU_DATA()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 */
argHandler(int arg,int,const char * const argv[],void * context)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
main(int argc,char * argv[])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