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