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