1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9
10 #include "unicode/utypes.h"
11
12 /**
13 * IntlTest is a base class for tests.
14 */
15
16 #include <assert.h>
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <cmath>
22 #include <math.h>
23
24 #include "unicode/ctest.h" // for str_timeDelta
25 #include "unicode/curramt.h"
26 #include "unicode/locid.h"
27 #include "unicode/putil.h"
28 #include "unicode/smpdtfmt.h"
29 #include "unicode/timezone.h"
30 #include "unicode/uclean.h"
31 #include "unicode/ucnv.h"
32 #include "unicode/unistr.h"
33 #include "unicode/ures.h"
34 #include "unicode/utf16.h"
35
36 #include "intltest.h"
37
38 #include "caltztst.h"
39 #include "cmemory.h"
40 #include "cstring.h"
41 #include "itmajor.h"
42 #include "lstmbe.h"
43 #include "mutex.h"
44 #include "putilimp.h" // for uprv_getRawUTCtime()
45 #include "uassert.h"
46 #include "udbgutil.h"
47 #include "umutex.h"
48 #include "uoptions.h"
49 #include "number_decnum.h"
50
51 #ifdef XP_MAC_CONSOLE
52 #include <console.h>
53 #include "Files.h"
54 #endif
55
56
57 static char* _testDataPath=NULL;
58
59 // Static list of errors found
60 static UnicodeString errorList;
61 static void *knownList = NULL; // known issues
62 static UBool noKnownIssues = false; // if true, don't emit known issues
63
64 //-----------------------------------------------------------------------------
65 //convenience classes to ease porting code that uses the Java
66 //string-concatenation operator (moved from findword test by rtg)
67
68 // [LIU] Just to get things working
69 UnicodeString
UCharToUnicodeString(UChar c)70 UCharToUnicodeString(UChar c)
71 { return UnicodeString(c); }
72
73 // [rtg] Just to get things working
74 UnicodeString
operator +(const UnicodeString & left,long num)75 operator+(const UnicodeString& left,
76 long num)
77 {
78 char buffer[64]; // nos changed from 10 to 64
79 char danger = 'p'; // guard against overrunning the buffer (rtg)
80
81 sprintf(buffer, "%ld", num);
82 assert(danger == 'p');
83
84 return left + buffer;
85 }
86
87 UnicodeString
operator +(const UnicodeString & left,unsigned long num)88 operator+(const UnicodeString& left,
89 unsigned long num)
90 {
91 char buffer[64]; // nos changed from 10 to 64
92 char danger = 'p'; // guard against overrunning the buffer (rtg)
93
94 sprintf(buffer, "%lu", num);
95 assert(danger == 'p');
96
97 return left + buffer;
98 }
99
100 UnicodeString
Int64ToUnicodeString(int64_t num)101 Int64ToUnicodeString(int64_t num)
102 {
103 char buffer[64]; // nos changed from 10 to 64
104 char danger = 'p'; // guard against overrunning the buffer (rtg)
105
106 #if defined(_MSC_VER)
107 sprintf(buffer, "%I64d", num);
108 #else
109 sprintf(buffer, "%lld", (long long)num);
110 #endif
111 assert(danger == 'p');
112
113 return buffer;
114 }
115
116 UnicodeString
DoubleToUnicodeString(double num)117 DoubleToUnicodeString(double num)
118 {
119 char buffer[64]; // nos changed from 10 to 64
120 char danger = 'p'; // guard against overrunning the buffer (rtg)
121
122 sprintf(buffer, "%1.14e", num);
123 assert(danger == 'p');
124
125 return buffer;
126 }
127
128 // [LIU] Just to get things working
129 UnicodeString
operator +(const UnicodeString & left,double num)130 operator+(const UnicodeString& left,
131 double num)
132 {
133 char buffer[64]; // was 32, made it arbitrarily bigger (rtg)
134 char danger = 'p'; // guard against overrunning the buffer (rtg)
135
136 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
137 // 53*log(2)/log(10) = 15.95
138 // so there is no need to show more than 16 digits. [alan]
139
140 sprintf(buffer, "%.17g", num);
141 assert(danger == 'p');
142
143 return left + buffer;
144 }
145
146 #if 0
147 UnicodeString
148 operator+(const UnicodeString& left,
149 int64_t num) {
150 return left + Int64ToUnicodeString(num);
151 }
152 #endif
153
154 #if !UCONFIG_NO_FORMATTING
155
156 /**
157 * Return a string display for this, without surrounding braces.
158 */
_toString(const Formattable & f)159 UnicodeString _toString(const Formattable& f) {
160 UnicodeString s;
161 switch (f.getType()) {
162 case Formattable::kDate:
163 {
164 UErrorCode status = U_ZERO_ERROR;
165 SimpleDateFormat fmt(status);
166 if (U_SUCCESS(status)) {
167 FieldPosition pos;
168 fmt.format(f.getDate(), s, pos);
169 s.insert(0, "Date:");
170 } else {
171 s = UnicodeString("Error creating date format]");
172 }
173 }
174 break;
175 case Formattable::kDouble:
176 s = UnicodeString("double:") + f.getDouble();
177 break;
178 case Formattable::kLong:
179 s = UnicodeString("long:") + f.getLong();
180 break;
181
182 case Formattable::kInt64:
183 s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
184 break;
185
186 case Formattable::kString:
187 f.getString(s);
188 s.insert(0, "String:");
189 break;
190 case Formattable::kArray:
191 {
192 int32_t i, n;
193 const Formattable* array = f.getArray(n);
194 s.insert(0, UnicodeString("Array:"));
195 UnicodeString delim(", ");
196 for (i=0; i<n; ++i) {
197 if (i > 0) {
198 s.append(delim);
199 }
200 s = s + _toString(array[i]);
201 }
202 }
203 break;
204 case Formattable::kObject: {
205 const CurrencyAmount* c = dynamic_cast<const CurrencyAmount*>(f.getObject());
206 if (c != NULL) {
207 s = _toString(c->getNumber()) + " " + UnicodeString(c->getISOCurrency());
208 } else {
209 s = UnicodeString("Unknown UObject");
210 }
211 break;
212 }
213 default:
214 s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
215 break;
216 }
217 return s;
218 }
219
220 /**
221 * Originally coded this as operator+, but that makes the expression
222 * + char* ambiguous. - liu
223 */
toString(const Formattable & f)224 UnicodeString toString(const Formattable& f) {
225 UnicodeString s((UChar)91/*[*/);
226 s.append(_toString(f));
227 s.append((UChar)0x5d/*]*/);
228 return s;
229 }
230
231 #endif
232
233 // useful when operator+ won't cooperate
toString(int32_t n)234 UnicodeString toString(int32_t n) {
235 return UnicodeString() + (long)n;
236 }
237
238
239
toString(UBool b)240 UnicodeString toString(UBool b) {
241 return b ? UnicodeString("true"):UnicodeString("false");
242 }
243
toString(const UnicodeSet & uniset,UErrorCode & status)244 UnicodeString toString(const UnicodeSet& uniset, UErrorCode& status) {
245 UnicodeString result;
246 uniset.toPattern(result, status);
247 return result;
248 }
249
250 // stephen - cleaned up 05/05/99
operator +(const UnicodeString & left,char num)251 UnicodeString operator+(const UnicodeString& left, char num)
252 { return left + (long)num; }
operator +(const UnicodeString & left,short num)253 UnicodeString operator+(const UnicodeString& left, short num)
254 { return left + (long)num; }
operator +(const UnicodeString & left,int num)255 UnicodeString operator+(const UnicodeString& left, int num)
256 { return left + (long)num; }
operator +(const UnicodeString & left,unsigned char num)257 UnicodeString operator+(const UnicodeString& left, unsigned char num)
258 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned short num)259 UnicodeString operator+(const UnicodeString& left, unsigned short num)
260 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned int num)261 UnicodeString operator+(const UnicodeString& left, unsigned int num)
262 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,float num)263 UnicodeString operator+(const UnicodeString& left, float num)
264 { return left + (double)num; }
265
266 //------------------
267
268 // Append a hex string to the target
269 UnicodeString&
appendHex(uint32_t number,int32_t digits,UnicodeString & target)270 IntlTest::appendHex(uint32_t number,
271 int32_t digits,
272 UnicodeString& target)
273 {
274 static const UChar digitString[] = {
275 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
276 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
277 }; /* "0123456789ABCDEF" */
278
279 if (digits < 0) { // auto-digits
280 digits = 2;
281 uint32_t max = 0xff;
282 while (number > max) {
283 digits += 2;
284 max = (max << 8) | 0xff;
285 }
286 }
287 switch (digits)
288 {
289 case 8:
290 target += digitString[(number >> 28) & 0xF];
291 U_FALLTHROUGH;
292 case 7:
293 target += digitString[(number >> 24) & 0xF];
294 U_FALLTHROUGH;
295 case 6:
296 target += digitString[(number >> 20) & 0xF];
297 U_FALLTHROUGH;
298 case 5:
299 target += digitString[(number >> 16) & 0xF];
300 U_FALLTHROUGH;
301 case 4:
302 target += digitString[(number >> 12) & 0xF];
303 U_FALLTHROUGH;
304 case 3:
305 target += digitString[(number >> 8) & 0xF];
306 U_FALLTHROUGH;
307 case 2:
308 target += digitString[(number >> 4) & 0xF];
309 U_FALLTHROUGH;
310 case 1:
311 target += digitString[(number >> 0) & 0xF];
312 break;
313 default:
314 target += "**";
315 }
316 return target;
317 }
318
319 UnicodeString
toHex(uint32_t number,int32_t digits)320 IntlTest::toHex(uint32_t number, int32_t digits) {
321 UnicodeString result;
322 appendHex(number, digits, result);
323 return result;
324 }
325
isPrintable(UChar32 c)326 static inline UBool isPrintable(UChar32 c) {
327 return c <= 0x7E && (c >= 0x20 || c == 9 || c == 0xA || c == 0xD);
328 }
329
330 // Replace nonprintable characters with unicode escapes
331 UnicodeString&
prettify(const UnicodeString & source,UnicodeString & target)332 IntlTest::prettify(const UnicodeString &source,
333 UnicodeString &target)
334 {
335 int32_t i;
336
337 target.remove();
338 target += "\"";
339
340 for (i = 0; i < source.length(); )
341 {
342 UChar32 ch = source.char32At(i);
343 i += U16_LENGTH(ch);
344
345 if (!isPrintable(ch))
346 {
347 if (ch <= 0xFFFF) {
348 target += "\\u";
349 appendHex(ch, 4, target);
350 } else {
351 target += "\\U";
352 appendHex(ch, 8, target);
353 }
354 }
355 else
356 {
357 target += ch;
358 }
359 }
360
361 target += "\"";
362
363 return target;
364 }
365
366 // Replace nonprintable characters with unicode escapes
367 UnicodeString
prettify(const UnicodeString & source,UBool parseBackslash)368 IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
369 {
370 int32_t i;
371 UnicodeString target;
372 target.remove();
373 target += "\"";
374
375 for (i = 0; i < source.length();)
376 {
377 UChar32 ch = source.char32At(i);
378 i += U16_LENGTH(ch);
379
380 if (!isPrintable(ch))
381 {
382 if (parseBackslash) {
383 // If we are preceded by an odd number of backslashes,
384 // then this character has already been backslash escaped.
385 // Delete a backslash.
386 int32_t backslashCount = 0;
387 for (int32_t j=target.length()-1; j>=0; --j) {
388 if (target.charAt(j) == (UChar)92) {
389 ++backslashCount;
390 } else {
391 break;
392 }
393 }
394 if ((backslashCount % 2) == 1) {
395 target.truncate(target.length() - 1);
396 }
397 }
398 if (ch <= 0xFFFF) {
399 target += "\\u";
400 appendHex(ch, 4, target);
401 } else {
402 target += "\\U";
403 appendHex(ch, 8, target);
404 }
405 }
406 else
407 {
408 target += ch;
409 }
410 }
411
412 target += "\"";
413
414 return target;
415 }
416
417 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
418 * set, try to deduce the directory in which ICU was built,
419 * and set ICU_DATA to "icu/source/data" in that location.
420 * The intent is to allow the tests to have a good chance
421 * of running without requiring that the user manually set
422 * ICU_DATA. Common data isn't a problem, since it is
423 * picked up via a static (build time) reference, but the
424 * tests dynamically load some data.
425 */
setICU_DATA()426 void IntlTest::setICU_DATA() {
427 const char *original_ICU_DATA = getenv("ICU_DATA");
428
429 if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
430 /* If the user set ICU_DATA, don't second-guess the person. */
431 return;
432 }
433
434 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
435 // to point to the top of the build hierarchy, which may or
436 // may not be the same as the source directory, depending on
437 // the configure options used. At any rate,
438 // set the data path to the built data from this directory.
439 // The value is complete with quotes, so it can be used
440 // as-is as a string constant.
441
442 #if defined (U_TOPBUILDDIR)
443 {
444 static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
445 u_setDataDirectory(env_string);
446 return;
447 }
448
449 #else
450 // Use #else so we don't get compiler warnings due to the return above.
451
452 /* On Windows, the file name obtained from __FILE__ includes a full path.
453 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
454 * Change to "wherever\icu\source\data"
455 */
456 {
457 char p[sizeof(__FILE__) + 10];
458 char *pBackSlash;
459 int i;
460
461 strcpy(p, __FILE__);
462 /* We want to back over three '\' chars. */
463 /* Only Windows should end up here, so looking for '\' is safe. */
464 for (i=1; i<=3; i++) {
465 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
466 if (pBackSlash != NULL) {
467 *pBackSlash = 0; /* Truncate the string at the '\' */
468 }
469 }
470
471 if (pBackSlash != NULL) {
472 /* We found and truncated three names from the path.
473 * Now append "source\data" and set the environment
474 */
475 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
476 u_setDataDirectory(p); /* p is "ICU_DATA=wherever\icu\source\data" */
477 return;
478 }
479 else {
480 /* __FILE__ on MSVC7 does not contain the directory */
481 u_setDataDirectory(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
482 return;
483 }
484 }
485 #endif
486
487 /* No location for the data dir was identifiable.
488 * Add other fallbacks for the test data location here if the need arises
489 */
490 }
491
492
493 //--------------------------------------------------------------------------------------
494
495 static const int32_t indentLevel_offset = 3;
496 static const char delim = '/';
497
498 IntlTest* IntlTest::gTest = NULL;
499
500 static int32_t execCount = 0;
501
it_log(UnicodeString message)502 void it_log( UnicodeString message )
503 {
504 if (IntlTest::gTest)
505 IntlTest::gTest->log( message );
506 }
507
it_logln(UnicodeString message)508 void it_logln( UnicodeString message )
509 {
510 if (IntlTest::gTest)
511 IntlTest::gTest->logln( message );
512 }
513
it_logln(void)514 void it_logln( void )
515 {
516 if (IntlTest::gTest)
517 IntlTest::gTest->logln();
518 }
519
it_info(UnicodeString message)520 void it_info( UnicodeString message )
521 {
522 if (IntlTest::gTest)
523 IntlTest::gTest->info( message );
524 }
525
it_infoln(UnicodeString message)526 void it_infoln( UnicodeString message )
527 {
528 if (IntlTest::gTest)
529 IntlTest::gTest->infoln( message );
530 }
531
it_infoln(void)532 void it_infoln( void )
533 {
534 if (IntlTest::gTest)
535 IntlTest::gTest->infoln();
536 }
537
it_err()538 void it_err()
539 {
540 if (IntlTest::gTest)
541 IntlTest::gTest->err();
542 }
543
it_err(UnicodeString message)544 void it_err( UnicodeString message )
545 {
546 if (IntlTest::gTest)
547 IntlTest::gTest->err( message );
548 }
549
it_errln(UnicodeString message)550 void it_errln( UnicodeString message )
551 {
552 if (IntlTest::gTest)
553 IntlTest::gTest->errln( message );
554 }
555
it_dataerr(UnicodeString message)556 void it_dataerr( UnicodeString message )
557 {
558 if (IntlTest::gTest)
559 IntlTest::gTest->dataerr( message );
560 }
561
it_dataerrln(UnicodeString message)562 void it_dataerrln( UnicodeString message )
563 {
564 if (IntlTest::gTest)
565 IntlTest::gTest->dataerrln( message );
566 }
567
IntlTest()568 IntlTest::IntlTest()
569 {
570 caller = NULL;
571 testPath = NULL;
572 LL_linestart = true;
573 errorCount = 0;
574 dataErrorCount = 0;
575 verbose = false;
576 no_time = false;
577 no_err_msg = false;
578 warn_on_missing_data = false;
579 quick = false;
580 leaks = false;
581 threadCount = 12;
582 testoutfp = stdout;
583 LL_indentlevel = indentLevel_offset;
584 numProps = 0;
585 strcpy(basePath, "/");
586 currName[0]=0;
587 }
588
setCaller(IntlTest * callingTest)589 void IntlTest::setCaller( IntlTest* callingTest )
590 {
591 caller = callingTest;
592 if (caller) {
593 warn_on_missing_data = caller->warn_on_missing_data;
594 verbose = caller->verbose;
595 no_err_msg = caller->no_err_msg;
596 quick = caller->quick;
597 threadCount = caller->threadCount;
598 testoutfp = caller->testoutfp;
599 write_golden_data = caller->write_golden_data;
600 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
601 numProps = caller->numProps;
602 for (int32_t i = 0; i < numProps; i++) {
603 proplines[i] = caller->proplines[i];
604 }
605 }
606 }
607
callTest(IntlTest & testToBeCalled,char * par)608 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
609 {
610 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
611 testToBeCalled.setCaller( this );
612 strcpy(testToBeCalled.basePath, this->basePath );
613 UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
614 strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
615 return result;
616 }
617
setPath(char * pathVal)618 void IntlTest::setPath( char* pathVal )
619 {
620 this->testPath = pathVal;
621 }
622
setVerbose(UBool verboseVal)623 UBool IntlTest::setVerbose( UBool verboseVal )
624 {
625 UBool rval = this->verbose;
626 this->verbose = verboseVal;
627 return rval;
628 }
629
setNotime(UBool no_time)630 UBool IntlTest::setNotime( UBool no_time )
631 {
632 UBool rval = this->no_time;
633 this->no_time = no_time;
634 return rval;
635 }
636
setWarnOnMissingData(UBool warn_on_missing_dataVal)637 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
638 {
639 UBool rval = this->warn_on_missing_data;
640 this->warn_on_missing_data = warn_on_missing_dataVal;
641 return rval;
642 }
643
setWriteGoldenData(UBool write_golden_data)644 UBool IntlTest::setWriteGoldenData( UBool write_golden_data )
645 {
646 UBool rval = this->write_golden_data;
647 this->write_golden_data = write_golden_data;
648 return rval;
649 }
650
setNoErrMsg(UBool no_err_msgVal)651 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
652 {
653 UBool rval = this->no_err_msg;
654 this->no_err_msg = no_err_msgVal;
655 return rval;
656 }
657
setQuick(UBool quickVal)658 UBool IntlTest::setQuick( UBool quickVal )
659 {
660 UBool rval = this->quick;
661 this->quick = quickVal;
662 return rval;
663 }
664
setLeaks(UBool leaksVal)665 UBool IntlTest::setLeaks( UBool leaksVal )
666 {
667 UBool rval = this->leaks;
668 this->leaks = leaksVal;
669 return rval;
670 }
671
setThreadCount(int32_t count)672 int32_t IntlTest::setThreadCount( int32_t count )
673 {
674 int32_t rval = this->threadCount;
675 this->threadCount = count;
676 return rval;
677 }
678
getErrors(void)679 int32_t IntlTest::getErrors( void )
680 {
681 return errorCount;
682 }
683
getDataErrors(void)684 int32_t IntlTest::getDataErrors( void )
685 {
686 return dataErrorCount;
687 }
688
runTest(char * name,char * par,char * baseName)689 UBool IntlTest::runTest( char* name, char* par, char *baseName )
690 {
691 UBool rval;
692 char* pos = NULL;
693
694 char* baseNameBuffer = NULL;
695
696 if(baseName == NULL) {
697 baseNameBuffer = (char*)malloc(1024);
698 baseName=baseNameBuffer;
699 strcpy(baseName, "/");
700 }
701
702 if (name)
703 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
704 if (pos) {
705 testPath = pos+1; // store subpath for calling subtest
706 *pos = 0; // split into two strings
707 }else{
708 testPath = NULL;
709 }
710
711 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
712 rval = runTestLoop( NULL, par, baseName );
713
714 }else if (strcmp( name, "LIST" ) == 0) {
715 this->usage();
716 rval = true;
717
718 }else{
719 rval = runTestLoop( name, par, baseName );
720 }
721
722 if (pos)
723 *pos = delim; // restore original value at pos
724 if(baseNameBuffer!=NULL) {
725 free(baseNameBuffer);
726 }
727 return rval;
728 }
729
730 // call individual tests, to be overridden to call implementations
runIndexedTest(int32_t,UBool,const char * &,char *)731 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
732 {
733 // to be overridden by a method like:
734 /*
735 switch (index) {
736 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
737 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
738 default: name = ""; break;
739 }
740 */
741 this->errln("*** runIndexedTest needs to be overridden! ***");
742 }
743
744
runTestLoop(char * testname,char * par,char * baseName)745 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
746 {
747 int32_t index = 0;
748 const char* name;
749 UBool run_this_test;
750 int32_t lastErrorCount;
751 UBool rval = false;
752 UBool lastTestFailed;
753
754 if(baseName == NULL) {
755 printf("ERROR: baseName can't be null.\n");
756 return false;
757 } else {
758 if ((char *)this->basePath != baseName) {
759 strcpy(this->basePath, baseName);
760 }
761 }
762
763 char * saveBaseLoc = baseName+strlen(baseName);
764
765 IntlTest* saveTest = gTest;
766 gTest = this;
767 do {
768 this->runIndexedTest( index, false, name, par );
769 if (strcmp(name,"skip") == 0) {
770 run_this_test = false;
771 } else {
772 if (!name || (name[0] == 0))
773 break;
774 if (!testname) {
775 run_this_test = true;
776 }else{
777 run_this_test = (UBool) (strcmp( name, testname ) == 0);
778 }
779 }
780 if (run_this_test) {
781 lastErrorCount = errorCount;
782 execCount++;
783 char msg[256];
784 sprintf(msg, "%s {", name);
785 LL_message(msg, true);
786 UDate timeStart = uprv_getRawUTCtime();
787 strcpy(saveBaseLoc,name);
788 strcat(saveBaseLoc,"/");
789
790 strcpy(currName, name); // set
791 this->runIndexedTest( index, true, name, par );
792 currName[0]=0; // reset
793
794 UDate timeStop = uprv_getRawUTCtime();
795 rval = true; // at least one test has been called
796 char secs[256];
797 if(!no_time) {
798 sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
799 } else {
800 secs[0]=0;
801 }
802
803
804 strcpy(saveBaseLoc,name);
805
806
807 ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
808
809
810 saveBaseLoc[0]=0; /* reset path */
811
812 if (lastErrorCount == errorCount) {
813 sprintf( msg, " } OK: %s ", name );
814 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
815 lastTestFailed = false;
816 }else{
817 sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
818 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
819
820 for(int i=0;i<LL_indentlevel;i++) {
821 errorList += " ";
822 }
823 errorList += name;
824 errorList += "\n";
825 lastTestFailed = true;
826 }
827 LL_indentlevel -= 3;
828 if (lastTestFailed) {
829 LL_message( "", true);
830 }
831 LL_message( msg, true);
832 if (lastTestFailed) {
833 LL_message( "", true);
834 }
835 LL_indentlevel += 3;
836 }
837 index++;
838 }while(name);
839
840 *saveBaseLoc = 0;
841
842 gTest = saveTest;
843 return rval;
844 }
845
846
847 /**
848 * Adds given string to the log if we are in verbose mode.
849 */
log(const UnicodeString & message)850 void IntlTest::log( const UnicodeString &message )
851 {
852 if( verbose ) {
853 LL_message( message, false );
854 }
855 }
856
857 /**
858 * Adds given string to the log if we are in verbose mode. Adds a new line to
859 * the given message.
860 */
logln(const UnicodeString & message)861 void IntlTest::logln( const UnicodeString &message )
862 {
863 if( verbose ) {
864 LL_message( message, true );
865 }
866 }
867
logln(void)868 void IntlTest::logln( void )
869 {
870 if( verbose ) {
871 LL_message( "", true );
872 }
873 }
874
875 /**
876 * Unconditionally adds given string to the log.
877 */
info(const UnicodeString & message)878 void IntlTest::info( const UnicodeString &message )
879 {
880 LL_message( message, false );
881 }
882
883 /**
884 * Unconditionally adds given string to the log. Adds a new line to
885 * the given message.
886 */
infoln(const UnicodeString & message)887 void IntlTest::infoln( const UnicodeString &message )
888 {
889 LL_message( message, true );
890 }
891
infoln(void)892 void IntlTest::infoln( void )
893 {
894 LL_message( "", true );
895 }
896
IncErrorCount(void)897 int32_t IntlTest::IncErrorCount( void )
898 {
899 errorCount++;
900 if (caller) caller->IncErrorCount();
901 return errorCount;
902 }
903
IncDataErrorCount(void)904 int32_t IntlTest::IncDataErrorCount( void )
905 {
906 dataErrorCount++;
907 if (caller) caller->IncDataErrorCount();
908 return dataErrorCount;
909 }
910
err()911 void IntlTest::err()
912 {
913 IncErrorCount();
914 }
915
err(const UnicodeString & message)916 void IntlTest::err( const UnicodeString &message )
917 {
918 IncErrorCount();
919 if (!no_err_msg) LL_message( message, false );
920 }
921
errln(const UnicodeString & message)922 void IntlTest::errln( const UnicodeString &message )
923 {
924 IncErrorCount();
925 if (!no_err_msg) LL_message( message, true );
926 }
927
dataerr(const UnicodeString & message)928 void IntlTest::dataerr( const UnicodeString &message )
929 {
930 IncDataErrorCount();
931
932 if (!warn_on_missing_data) {
933 IncErrorCount();
934 }
935
936 if (!no_err_msg) LL_message( message, false );
937 }
938
dataerrln(const UnicodeString & message)939 void IntlTest::dataerrln( const UnicodeString &message )
940 {
941 int32_t errCount = IncDataErrorCount();
942 UnicodeString msg;
943 if (!warn_on_missing_data) {
944 IncErrorCount();
945 msg = message;
946 } else {
947 msg = UnicodeString("[DATA] " + message);
948 }
949
950 if (!no_err_msg) {
951 if ( errCount == 1) {
952 LL_message( msg + " - (Are you missing data?)", true ); // only show this message the first time
953 } else {
954 LL_message( msg , true );
955 }
956 }
957 }
958
errcheckln(UErrorCode status,const UnicodeString & message)959 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
960 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
961 dataerrln(message);
962 } else {
963 errln(message);
964 }
965 }
966
967 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)968 void IntlTest::log(const char *fmt, ...)
969 {
970 char buffer[4000];
971 va_list ap;
972
973 va_start(ap, fmt);
974 /* sprintf it just to make sure that the information is valid */
975 vsprintf(buffer, fmt, ap);
976 va_end(ap);
977 if( verbose ) {
978 log(UnicodeString(buffer, (const char *)NULL));
979 }
980 }
981
logln(const char * fmt,...)982 void IntlTest::logln(const char *fmt, ...)
983 {
984 char buffer[4000];
985 va_list ap;
986
987 va_start(ap, fmt);
988 /* sprintf it just to make sure that the information is valid */
989 vsprintf(buffer, fmt, ap);
990 va_end(ap);
991 if( verbose ) {
992 logln(UnicodeString(buffer, (const char *)NULL));
993 }
994 }
995
logKnownIssue(const char * ticket,const char * fmt,...)996 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
997 {
998 char buffer[4000];
999 va_list ap;
1000
1001 va_start(ap, fmt);
1002 /* sprintf it just to make sure that the information is valid */
1003 vsprintf(buffer, fmt, ap);
1004 va_end(ap);
1005 return logKnownIssue(ticket, UnicodeString(buffer, (const char *)NULL));
1006 }
1007
logKnownIssue(const char * ticket)1008 UBool IntlTest::logKnownIssue(const char *ticket) {
1009 return logKnownIssue(ticket, UnicodeString());
1010 }
1011
logKnownIssue(const char * ticket,const UnicodeString & msg)1012 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
1013 if(noKnownIssues) return false;
1014
1015 char fullpath[2048];
1016 strcpy(fullpath, basePath);
1017 strcat(fullpath, currName);
1018 UnicodeString msg2 = msg;
1019 UBool firstForTicket = true, firstForWhere = true;
1020 knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
1021
1022 msg2 = UNICODE_STRING_SIMPLE("(Known issue ") +
1023 UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg;
1024 if(firstForTicket || firstForWhere) {
1025 infoln(msg2);
1026 } else {
1027 logln(msg2);
1028 }
1029
1030 return true;
1031 }
1032
1033 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)1034 void IntlTest::info(const char *fmt, ...)
1035 {
1036 char buffer[4000];
1037 va_list ap;
1038
1039 va_start(ap, fmt);
1040 /* sprintf it just to make sure that the information is valid */
1041 vsprintf(buffer, fmt, ap);
1042 va_end(ap);
1043 info(UnicodeString(buffer, (const char *)NULL));
1044 }
1045
infoln(const char * fmt,...)1046 void IntlTest::infoln(const char *fmt, ...)
1047 {
1048 char buffer[4000];
1049 va_list ap;
1050
1051 va_start(ap, fmt);
1052 /* sprintf it just to make sure that the information is valid */
1053 vsprintf(buffer, fmt, ap);
1054 va_end(ap);
1055 infoln(UnicodeString(buffer, (const char *)NULL));
1056 }
1057
err(const char * fmt,...)1058 void IntlTest::err(const char *fmt, ...)
1059 {
1060 char buffer[4000];
1061 va_list ap;
1062
1063 va_start(ap, fmt);
1064 vsprintf(buffer, fmt, ap);
1065 va_end(ap);
1066 err(UnicodeString(buffer, (const char *)NULL));
1067 }
1068
errln(const char * fmt,...)1069 void IntlTest::errln(const char *fmt, ...)
1070 {
1071 char buffer[4000];
1072 va_list ap;
1073
1074 va_start(ap, fmt);
1075 vsprintf(buffer, fmt, ap);
1076 va_end(ap);
1077 errln(UnicodeString(buffer, (const char *)NULL));
1078 }
1079
dataerrln(const char * fmt,...)1080 void IntlTest::dataerrln(const char *fmt, ...)
1081 {
1082 char buffer[4000];
1083 va_list ap;
1084
1085 va_start(ap, fmt);
1086 vsprintf(buffer, fmt, ap);
1087 va_end(ap);
1088 dataerrln(UnicodeString(buffer, (const char *)NULL));
1089 }
1090
errcheckln(UErrorCode status,const char * fmt,...)1091 void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...)
1092 {
1093 char buffer[4000];
1094 va_list ap;
1095
1096 va_start(ap, fmt);
1097 vsprintf(buffer, fmt, ap);
1098 va_end(ap);
1099
1100 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1101 dataerrln(UnicodeString(buffer, (const char *)NULL));
1102 } else {
1103 errln(UnicodeString(buffer, (const char *)NULL));
1104 }
1105 }
1106
printErrors()1107 void IntlTest::printErrors()
1108 {
1109 IntlTest::LL_message(errorList, true);
1110 }
1111
printKnownIssues()1112 UBool IntlTest::printKnownIssues()
1113 {
1114 if(knownList != NULL) {
1115 udbg_knownIssue_print(knownList);
1116 udbg_knownIssue_close(knownList);
1117 return true;
1118 } else {
1119 return false;
1120 }
1121 }
1122
1123
LL_message(UnicodeString message,UBool newline)1124 void IntlTest::LL_message( UnicodeString message, UBool newline )
1125 {
1126 // Synchronize this function.
1127 // All error messages generated by tests funnel through here.
1128 // Multithreaded tests can concurrently generate errors, requiring synchronization
1129 // to keep each message together.
1130 static UMutex messageMutex;
1131 Mutex lock(&messageMutex);
1132
1133 // string that starts with a LineFeed character and continues
1134 // with spaces according to the current indentation
1135 static const UChar indentUChars[] = {
1136 '\n',
1137 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1138 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1139 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1140 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1141 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1142 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1143 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1144 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1145 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1146 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1147 };
1148 U_ASSERT(1 + LL_indentlevel <= UPRV_LENGTHOF(indentUChars));
1149 UnicodeString indent(false, indentUChars, 1 + LL_indentlevel);
1150
1151 char buffer[30000];
1152 int32_t length;
1153
1154 // stream out the indentation string first if necessary
1155 length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1156 if (length > 0) {
1157 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1158 }
1159
1160 // replace each LineFeed by the indentation string
1161 message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1162
1163 // stream out the message
1164 length = message.extract(0, message.length(), buffer, sizeof(buffer));
1165 if (length > 0) {
1166 length = length > 30000 ? 30000 : length;
1167 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1168 }
1169
1170 if (newline) {
1171 char newLine = '\n';
1172 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1173 }
1174
1175 // A newline usually flushes the buffer, but
1176 // flush the message just in case of a core dump.
1177 fflush((FILE *)testoutfp);
1178 }
1179
1180 /**
1181 * Print a usage message for this test class.
1182 */
usage(void)1183 void IntlTest::usage( void )
1184 {
1185 UBool save_verbose = setVerbose( true );
1186 logln("Test names:");
1187 logln("-----------");
1188
1189 int32_t index = 0;
1190 const char* name = NULL;
1191 do{
1192 this->runIndexedTest( index, false, name );
1193 if (!name) break;
1194 logln(name);
1195 index++;
1196 }while (name && (name[0] != 0));
1197 setVerbose( save_verbose );
1198 }
1199
1200
1201 // memory leak reporting software will be able to take advantage of the testsuite
1202 // being run a second time local to a specific method in order to report only actual leaks
1203 UBool
run_phase2(char * name,char * par)1204 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1205 {
1206 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1207 strLeak->append(" for verifying purify filter");
1208 return this->runTest( name, par );
1209 }
1210
1211
1212 #if UCONFIG_NO_LEGACY_CONVERSION
1213 # define TRY_CNV_1 "iso-8859-1"
1214 # define TRY_CNV_2 "ibm-1208"
1215 #else
1216 # define TRY_CNV_1 "iso-8859-7"
1217 # define TRY_CNV_2 "sjis"
1218 #endif
1219
1220 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1221 U_CAPI void unistr_printLengths();
1222 #endif
1223
1224 int
main(int argc,char * argv[])1225 main(int argc, char* argv[])
1226 {
1227 UBool syntax = false;
1228 UBool all = false;
1229 UBool verbose = false;
1230 UBool no_err_msg = false;
1231 UBool no_time = false;
1232 UBool quick = true;
1233 UBool name = false;
1234 UBool leaks = false;
1235 UBool utf8 = false;
1236 const char *summary_file = NULL;
1237 UBool warnOnMissingData = false;
1238 UBool writeGoldenData = false;
1239 UBool defaultDataFound = false;
1240 int32_t threadCount = 12;
1241 UErrorCode errorCode = U_ZERO_ERROR;
1242 UConverter *cnv = NULL;
1243 const char *warnOrErr = "Failure";
1244 UDate startTime, endTime;
1245 int32_t diffTime;
1246 const char *props[IntlTest::kMaxProps];
1247 int32_t nProps = 0;
1248
1249 U_MAIN_INIT_ARGS(argc, argv);
1250
1251 startTime = uprv_getRawUTCtime();
1252
1253 for (int i = 1; i < argc; ++i) {
1254 if (argv[i][0] == '-') {
1255 const char* str = argv[i] + 1;
1256 if (strcmp("verbose", str) == 0 ||
1257 strcmp("v", str) == 0)
1258 verbose = true;
1259 else if (strcmp("noerrormsg", str) == 0 ||
1260 strcmp("n", str) == 0)
1261 no_err_msg = true;
1262 else if (strcmp("exhaustive", str) == 0 ||
1263 strcmp("e", str) == 0)
1264 quick = false;
1265 else if (strcmp("all", str) == 0 ||
1266 strcmp("a", str) == 0)
1267 all = true;
1268 else if (strcmp("utf-8", str) == 0 ||
1269 strcmp("u", str) == 0)
1270 utf8 = true;
1271 else if (strcmp("noknownissues", str) == 0 ||
1272 strcmp("K", str) == 0)
1273 noKnownIssues = true;
1274 else if (strcmp("leaks", str) == 0 ||
1275 strcmp("l", str) == 0)
1276 leaks = true;
1277 else if (strcmp("notime", str) == 0 ||
1278 strcmp("T", str) == 0)
1279 no_time = true;
1280 else if (strcmp("goldens", str) == 0 ||
1281 strcmp("G", str) == 0)
1282 writeGoldenData = true;
1283 else if (strncmp("E", str, 1) == 0)
1284 summary_file = str+1;
1285 else if (strcmp("x", str)==0) {
1286 if(++i>=argc) {
1287 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1288 syntax = true;
1289 }
1290 if(ctest_xml_setFileName(argv[i])) { /* set the name */
1291 return 1; /* error */
1292 }
1293 } else if (strcmp("w", str) == 0) {
1294 warnOnMissingData = true;
1295 warnOrErr = "WARNING";
1296 }
1297 else if (strncmp("threads:", str, 8) == 0) {
1298 threadCount = atoi(str + 8);
1299 }
1300 else if (strncmp("prop:", str, 5) == 0) {
1301 if (nProps < IntlTest::kMaxProps) {
1302 props[nProps] = str + 5;
1303 }
1304 nProps++;
1305 }
1306 else {
1307 syntax = true;
1308 }
1309 }else{
1310 name = true;
1311 }
1312 }
1313
1314 if (!all && !name) {
1315 all = true;
1316 } else if (all && name) {
1317 syntax = true;
1318 }
1319
1320 if (syntax) {
1321 fprintf(stdout,
1322 "### Syntax:\n"
1323 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1324 "### \n"
1325 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1326 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<property>=<value>, \n"
1327 "### notime (T), \n"
1328 "### threads:<threadCount>\n"
1329 "### (The default thread count is 12.),\n"
1330 "### (Specify either -all (shortcut -a) or a test name). \n"
1331 "### -all will run all of the tests.\n"
1332 "### \n"
1333 "### To get a list of the test names type: intltest LIST \n"
1334 "### To run just the utility tests type: intltest utility \n"
1335 "### \n"
1336 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1337 "### For example to list the utility tests type: intltest utility/LIST \n"
1338 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1339 "### \n"
1340 "### A parameter can be specified for a test by appending '@' and the value \n"
1341 "### to the testname. \n\n");
1342 return 1;
1343 }
1344
1345 if (nProps > IntlTest::kMaxProps) {
1346 fprintf(stdout, "### Too many properties. Exiting.\n");
1347 }
1348
1349 MajorTestLevel major;
1350 major.setVerbose( verbose );
1351 major.setNoErrMsg( no_err_msg );
1352 major.setQuick( quick );
1353 major.setLeaks( leaks );
1354 major.setThreadCount( threadCount );
1355 major.setWarnOnMissingData( warnOnMissingData );
1356 major.setWriteGoldenData( writeGoldenData );
1357 major.setNotime (no_time);
1358 for (int32_t i = 0; i < nProps; i++) {
1359 major.setProperty(props[i]);
1360 }
1361
1362
1363 fprintf(stdout, "-----------------------------------------------\n");
1364 fprintf(stdout, " IntlTest (C++) Test Suite for \n");
1365 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION);
1366
1367
1368 {
1369 const char *charsetFamily = "Unknown";
1370 int32_t voidSize = (int32_t)sizeof(void*);
1371 int32_t bits = voidSize * 8;
1372 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1373 charsetFamily="ASCII";
1374 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1375 charsetFamily="EBCDIC";
1376 }
1377 fprintf(stdout,
1378 " Bits: %d, Byte order: %s, Chars: %s\n",
1379 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1380 charsetFamily);
1381 }
1382 fprintf(stdout, "-----------------------------------------------\n");
1383 fprintf(stdout, " Options: \n");
1384 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off"));
1385 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off"));
1386 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off"));
1387 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off"));
1388 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
1389 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off"));
1390 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off"));
1391 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off"));
1392 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1393 fprintf(stdout, " Write golden data (G) : %s\n", (writeGoldenData? "On" : "Off"));
1394 fprintf(stdout, " Threads : %d\n", threadCount);
1395 for (int32_t i = 0; i < nProps; i++) {
1396 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]);
1397 }
1398 fprintf(stdout, "-----------------------------------------------\n");
1399
1400 if(utf8) {
1401 ucnv_setDefaultName("utf-8");
1402 }
1403 /* Check whether ICU will initialize without forcing the build data directory into
1404 * the ICU_DATA path. Success here means either the data dll contains data, or that
1405 * this test program was run with ICU_DATA set externally. Failure of this check
1406 * is normal when ICU data is not packaged into a shared library.
1407 *
1408 * Whether or not this test succeeds, we want to cleanup and reinitialize
1409 * with a data path so that data loading from individual files can be tested.
1410 */
1411 u_init(&errorCode);
1412 if (U_FAILURE(errorCode)) {
1413 fprintf(stderr,
1414 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1415 defaultDataFound = false;
1416 }
1417 else {
1418 defaultDataFound = true;
1419 }
1420 u_cleanup();
1421 if(utf8) {
1422 ucnv_setDefaultName("utf-8");
1423 }
1424 errorCode = U_ZERO_ERROR;
1425
1426 /* Initialize ICU */
1427 if (!defaultDataFound) {
1428 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1429 }
1430 u_init(&errorCode);
1431 if (U_FAILURE(errorCode)) {
1432 fprintf(stderr,
1433 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1434 "*** Check the ICU_DATA environment variable and \n"
1435 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1436 if(warnOnMissingData == 0) {
1437 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1438 u_cleanup();
1439 return 1;
1440 }
1441 }
1442
1443 // initial check for the default converter
1444 errorCode = U_ZERO_ERROR;
1445 cnv = ucnv_open(0, &errorCode);
1446 if(cnv != 0) {
1447 // ok
1448 ucnv_close(cnv);
1449 } else {
1450 fprintf(stdout,
1451 "*** %s! The default converter [%s] cannot be opened.\n"
1452 "*** Check the ICU_DATA environment variable and\n"
1453 "*** check that the data files are present.\n",
1454 warnOrErr, ucnv_getDefaultName());
1455 if(!warnOnMissingData) {
1456 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1457 return 1;
1458 }
1459 }
1460
1461 // try more data
1462 cnv = ucnv_open(TRY_CNV_2, &errorCode);
1463 if(cnv != 0) {
1464 // ok
1465 ucnv_close(cnv);
1466 } else {
1467 fprintf(stdout,
1468 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1469 "*** Check the ICU_DATA environment variable and \n"
1470 "*** check that the data files are present.\n", warnOrErr);
1471 if(!warnOnMissingData) {
1472 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1473 return 1;
1474 }
1475 }
1476
1477 UResourceBundle *rb = ures_open(0, "en", &errorCode);
1478 ures_close(rb);
1479 if(U_FAILURE(errorCode)) {
1480 fprintf(stdout,
1481 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1482 "*** Check the ICU_DATA environment variable and \n"
1483 "*** check that the data files are present.\n", warnOrErr);
1484 if(!warnOnMissingData) {
1485 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1486 return 1;
1487 }
1488 }
1489
1490 Locale originalLocale; // Save the default locale for comparison later on.
1491
1492 if(ctest_xml_init("intltest"))
1493 return 1;
1494
1495
1496 /* TODO: Add option to call u_cleanup and rerun tests. */
1497 if (all) {
1498 major.runTest();
1499 if (leaks) {
1500 major.run_phase2( NULL, NULL );
1501 }
1502 }else{
1503 for (int i = 1; i < argc; ++i) {
1504 if (argv[i][0] != '-') {
1505 char* name = argv[i];
1506 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1507
1508 char baseName[1024];
1509 sprintf(baseName, "/%s/", name);
1510
1511 char* parameter = strchr( name, '@' );
1512 if (parameter) {
1513 *parameter = 0;
1514 parameter += 1;
1515 }
1516 execCount = 0;
1517 UBool res = major.runTest( name, parameter, baseName );
1518 if (leaks && res) {
1519 major.run_phase2( name, parameter );
1520 }
1521 if (!res || (execCount <= 0)) {
1522 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1523 }
1524 } else if(!strcmp(argv[i],"-x")) {
1525 i++;
1526 }
1527 }
1528 }
1529
1530
1531 #if !UCONFIG_NO_FORMATTING
1532 CalendarTimeZoneTest::cleanup();
1533 #endif
1534
1535 free(_testDataPath);
1536 _testDataPath = 0;
1537
1538 Locale lastDefaultLocale;
1539 if (originalLocale != lastDefaultLocale) {
1540 major.errln("FAILURE: A test changed the default locale without resetting it.");
1541 }
1542
1543 fprintf(stdout, "\n--------------------------------------\n");
1544 if( major.printKnownIssues() ) {
1545 fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1546 }
1547 if (major.getErrors() == 0) {
1548 /* Call it twice to make sure that the defaults were reset. */
1549 /* Call it before the OK message to verify proper cleanup. */
1550 u_cleanup();
1551 u_cleanup();
1552
1553 fprintf(stdout, "OK: All tests passed without error.\n");
1554
1555 if (major.getDataErrors() != 0) {
1556 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1557 }
1558 }else{
1559 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1560 major.printErrors();
1561
1562 if(summary_file != NULL) {
1563 FILE *summf = fopen(summary_file, "w");
1564 if( summf != NULL) {
1565 char buf[10000];
1566 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1567 fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1568 fclose(summf);
1569 }
1570 }
1571
1572
1573 if (major.getDataErrors() != 0) {
1574 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1575 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1576 "\tthe '-w' option to turn these errors into warnings.\n");
1577 }
1578
1579 /* Call afterwards to display errors. */
1580 u_cleanup();
1581 }
1582
1583 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1584 unistr_printLengths();
1585 #endif
1586
1587 fprintf(stdout, "--------------------------------------\n");
1588
1589 if (execCount <= 0) {
1590 fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1591 }
1592 if(!no_time) {
1593 endTime = uprv_getRawUTCtime();
1594 diffTime = (int32_t)(endTime - startTime);
1595 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1596 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1597 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1598 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1599 (int)(diffTime%U_MILLIS_PER_SECOND));
1600 }
1601
1602 if(ctest_xml_fini())
1603 return 1;
1604
1605 return major.getErrors();
1606 }
1607
loadTestData(UErrorCode & err)1608 const char* IntlTest::loadTestData(UErrorCode& err){
1609 if ( _testDataPath == NULL){
1610 const char* directory=NULL;
1611 UResourceBundle* test =NULL;
1612 char* tdpath=NULL;
1613 const char* tdrelativepath;
1614
1615 #if defined (U_TOPBUILDDIR)
1616 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1617 directory = U_TOPBUILDDIR;
1618 #else
1619 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1620 directory = pathToDataDirectory();
1621 #endif
1622
1623 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1624
1625 if (tdpath == NULL) {
1626 err = U_MEMORY_ALLOCATION_ERROR;
1627 it_dataerrln((UnicodeString) "Could not allocate memory for _testDataPath " + u_errorName(err));
1628 return "";
1629 }
1630
1631 /* u_getDataDirectory shoul return \source\data ... set the
1632 * directory to ..\source\data\..\test\testdata\out\testdata
1633 */
1634 strcpy(tdpath, directory);
1635 strcat(tdpath, tdrelativepath);
1636 strcat(tdpath,"testdata");
1637
1638 test=ures_open(tdpath, "testtypes", &err);
1639
1640 if (U_FAILURE(err)) {
1641 err = U_FILE_ACCESS_ERROR;
1642 it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1643 return "";
1644 }
1645 ures_close(test);
1646 _testDataPath = tdpath;
1647 return _testDataPath;
1648 }
1649 return _testDataPath;
1650 }
1651
getTestDataPath(UErrorCode & err)1652 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1653 return loadTestData(err);
1654 }
1655
1656 /**
1657 * Returns the path to icu/source/test/testdata/
1658 * Note: this function is parallel with C loadSourceTestData in cintltst.c
1659 */
getSourceTestData(UErrorCode &)1660 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1661 const char *srcDataDir = NULL;
1662 #ifdef U_TOPSRCDIR
1663 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1664 #else
1665 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1666 FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r");
1667 if (f) {
1668 /* We're in icu/source/test/intltest/ */
1669 fclose(f);
1670 }
1671 else {
1672 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1673 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1674 "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1675 }
1676 #endif
1677 return srcDataDir;
1678 }
1679
getUnidataPath(char path[])1680 char *IntlTest::getUnidataPath(char path[]) {
1681 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt")
1682
1683 // Look inside ICU_DATA first.
1684 strcpy(path, pathToDataDirectory());
1685 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1686 FILE *f = fopen(path, "r");
1687 if(f != NULL) {
1688 fclose(f);
1689 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1690 return path;
1691 }
1692
1693 // As a fallback, try to guess where the source data was located
1694 // at the time ICU was built, and look there.
1695 # ifdef U_TOPSRCDIR
1696 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data");
1697 # else
1698 UErrorCode errorCode = U_ZERO_ERROR;
1699 const char *testDataPath = loadTestData(errorCode);
1700 if(U_FAILURE(errorCode)) {
1701 it_errln(UnicodeString(
1702 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1703 u_errorName(errorCode));
1704 return NULL;
1705 }
1706 strcpy(path, testDataPath);
1707 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1708 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1709 U_FILE_SEP_STRING "data");
1710 # endif
1711 strcat(path, U_FILE_SEP_STRING);
1712 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1713 f = fopen(path, "r");
1714 if(f != NULL) {
1715 fclose(f);
1716 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1717 return path;
1718 }
1719 return NULL;
1720 }
1721
1722 const char* IntlTest::fgDataDir = NULL;
1723
1724 /* returns the path to icu/source/data */
pathToDataDirectory()1725 const char * IntlTest::pathToDataDirectory()
1726 {
1727
1728 if(fgDataDir != NULL) {
1729 return fgDataDir;
1730 }
1731
1732 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1733 // to point to the top of the build hierarchy, which may or
1734 // may not be the same as the source directory, depending on
1735 // the configure options used. At any rate,
1736 // set the data path to the built data from this directory.
1737 // The value is complete with quotes, so it can be used
1738 // as-is as a string constant.
1739 */
1740 #if defined (U_TOPSRCDIR)
1741 {
1742 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1743 }
1744 #else
1745
1746 /* On Windows, the file name obtained from __FILE__ includes a full path.
1747 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1748 * Change to "wherever\icu\source\data"
1749 */
1750 {
1751 static char p[sizeof(__FILE__) + 10];
1752 char *pBackSlash;
1753 int i;
1754
1755 strcpy(p, __FILE__);
1756 /* We want to back over three '\' chars. */
1757 /* Only Windows should end up here, so looking for '\' is safe. */
1758 for (i=1; i<=3; i++) {
1759 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1760 if (pBackSlash != NULL) {
1761 *pBackSlash = 0; /* Truncate the string at the '\' */
1762 }
1763 }
1764
1765 if (pBackSlash != NULL) {
1766 /* We found and truncated three names from the path.
1767 * Now append "source\data" and set the environment
1768 */
1769 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1770 fgDataDir = p;
1771 }
1772 else {
1773 /* __FILE__ on MSVC7 does not contain the directory */
1774 FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1775 if (file) {
1776 fclose(file);
1777 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1778 }
1779 else {
1780 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1781 }
1782 }
1783 }
1784 #endif
1785
1786 return fgDataDir;
1787
1788 }
1789
1790 /*
1791 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1792 * It converts an invariant-character string into a UnicodeString, with
1793 * unescaping \u sequences.
1794 */
CharsToUnicodeString(const char * chars)1795 UnicodeString CharsToUnicodeString(const char* chars){
1796 return UnicodeString(chars, -1, US_INV).unescape();
1797 }
1798
ctou(const char * chars)1799 UnicodeString ctou(const char* chars) {
1800 return CharsToUnicodeString(chars);
1801 }
1802
1803 #define RAND_M (714025)
1804 #define RAND_IA (1366)
1805 #define RAND_IC (150889)
1806
1807 static int32_t RAND_SEED;
1808
1809 /**
1810 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1811 * with care: Does not return all possible values; returns one of
1812 * 714,025 values, uniformly spaced. However, the period is
1813 * effectively infinite. See: Numerical Recipes, section 7.1.
1814 *
1815 * @param seedp pointer to seed. Set *seedp to any negative value
1816 * to restart the sequence.
1817 */
random(int32_t * seedp)1818 float IntlTest::random(int32_t* seedp) {
1819 static int32_t iy, ir[98];
1820 static UBool first=true;
1821 int32_t j;
1822 if (*seedp < 0 || first) {
1823 first = false;
1824 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1825 for (j=1;j<=97;++j) {
1826 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1827 ir[j]=(*seedp);
1828 }
1829 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1830 iy=(*seedp);
1831 }
1832 j=(int32_t)(1 + 97.0*iy/RAND_M);
1833 U_ASSERT(j>=1 && j<=97);
1834 iy=ir[j];
1835 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1836 ir[j]=(*seedp);
1837 return (float) iy/RAND_M;
1838 }
1839
1840 /**
1841 * Convenience method using a global seed.
1842 */
random()1843 float IntlTest::random() {
1844 return random(&RAND_SEED);
1845 }
1846
1847
1848 /*
1849 * Integer random number class implementation.
1850 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1851 */
icu_rand(uint32_t seed)1852 IntlTest::icu_rand::icu_rand(uint32_t seed) {
1853 seed = seed % 2147483647UL;
1854 if (seed == 0) {
1855 seed = 1;
1856 }
1857 fLast = seed;
1858 }
1859
~icu_rand()1860 IntlTest::icu_rand::~icu_rand() {}
1861
seed(uint32_t seed)1862 void IntlTest::icu_rand::seed(uint32_t seed) {
1863 if (seed == 0) {
1864 seed = 1;
1865 }
1866 fLast = seed;
1867 }
1868
operator ()()1869 uint32_t IntlTest::icu_rand::operator() () {
1870 fLast = ((uint64_t)fLast * 48271UL) % 2147483647UL;
1871 return fLast;
1872 }
1873
getSeed()1874 uint32_t IntlTest::icu_rand::getSeed() {
1875 return (uint32_t) fLast;
1876 }
1877
1878
1879
toHex(int32_t i)1880 static inline UChar toHex(int32_t i) {
1881 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1882 }
1883
escape(const UnicodeString & s,UnicodeString & result)1884 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1885 for (int32_t i=0; i<s.length(); ++i) {
1886 UChar c = s[i];
1887 if (c <= (UChar)0x7F) {
1888 result += c;
1889 } else {
1890 result += (UChar)0x5c;
1891 result += (UChar)0x75;
1892 result += toHex((c >> 12) & 0xF);
1893 result += toHex((c >> 8) & 0xF);
1894 result += toHex((c >> 4) & 0xF);
1895 result += toHex( c & 0xF);
1896 }
1897 }
1898 return result;
1899 }
1900
1901 #define VERBOSE_ASSERTIONS
1902
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1903 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1904 if (file != NULL) {
1905 if (!condition) {
1906 if (possibleDataError) {
1907 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1908 } else {
1909 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1910 }
1911 } else if (!quiet) {
1912 logln("%s:%d: Ok: %s", file, line, message);
1913 }
1914 } else {
1915 if (!condition) {
1916 if (possibleDataError) {
1917 dataerrln("FAIL: assertTrue() failed: %s", message);
1918 } else {
1919 errln("FAIL: assertTrue() failed: %s", message);
1920 }
1921 } else if (!quiet) {
1922 logln("Ok: %s", message);
1923 }
1924
1925 }
1926 return condition;
1927 }
1928
assertFalse(const char * message,UBool condition,UBool quiet,UBool possibleDataError)1929 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
1930 if (condition) {
1931 if (possibleDataError) {
1932 dataerrln("FAIL: assertFalse() failed: %s", message);
1933 } else {
1934 errln("FAIL: assertFalse() failed: %s", message);
1935 }
1936 } else if (!quiet) {
1937 logln("Ok: %s", message);
1938 }
1939 return !condition;
1940 }
1941
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1942 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1943 if( file==NULL ) {
1944 file = ""; // prevent failure if no file given
1945 }
1946 if (U_FAILURE(ec)) {
1947 if (possibleDataError) {
1948 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1949 } else {
1950 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1951 }
1952 return false;
1953 } else {
1954 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1955 }
1956 return true;
1957 }
1958
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1959 UBool IntlTest::assertEquals(const char* message,
1960 const UnicodeString& expected,
1961 const UnicodeString& actual,
1962 UBool possibleDataError) {
1963 if (expected != actual) {
1964 if (possibleDataError) {
1965 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1966 prettify(actual) +
1967 "; expected " + prettify(expected));
1968 } else {
1969 errln((UnicodeString)"FAIL: " + message + "; got " +
1970 prettify(actual) +
1971 "; expected " + prettify(expected));
1972 }
1973 return false;
1974 }
1975 #ifdef VERBOSE_ASSERTIONS
1976 else {
1977 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1978 }
1979 #endif
1980 return true;
1981 }
1982
assertEquals(const char * message,const char * expected,const char * actual)1983 UBool IntlTest::assertEquals(const char* message,
1984 const char* expected,
1985 const char* actual) {
1986 U_ASSERT(expected != nullptr);
1987 U_ASSERT(actual != nullptr);
1988 if (uprv_strcmp(expected, actual) != 0) {
1989 errln((UnicodeString)"FAIL: " + message + "; got \"" +
1990 actual +
1991 "\"; expected \"" + expected + "\"");
1992 return false;
1993 }
1994 #ifdef VERBOSE_ASSERTIONS
1995 else {
1996 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1997 }
1998 #endif
1999 return true;
2000 }
2001
assertEquals(const char * message,int32_t expected,int32_t actual)2002 UBool IntlTest::assertEquals(const char* message,
2003 int32_t expected,
2004 int32_t actual) {
2005 if (expected != actual) {
2006 errln((UnicodeString)"FAIL: " + message + "; got " +
2007 actual + "=0x" + toHex(actual) +
2008 "; expected " + expected + "=0x" + toHex(expected));
2009 return false;
2010 }
2011 #ifdef VERBOSE_ASSERTIONS
2012 else {
2013 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
2014 }
2015 #endif
2016 return true;
2017 }
2018
assertEquals(const char * message,int64_t expected,int64_t actual)2019 UBool IntlTest::assertEquals(const char* message,
2020 int64_t expected,
2021 int64_t actual) {
2022 if (expected != actual) {
2023 errln((UnicodeString)"FAIL: " + message + "; got int64 " +
2024 Int64ToUnicodeString(actual) +
2025 "; expected " + Int64ToUnicodeString(expected) );
2026 return false;
2027 }
2028 #ifdef VERBOSE_ASSERTIONS
2029 else {
2030 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
2031 }
2032 #endif
2033 return true;
2034 }
2035
assertEquals(const char * message,double expected,double actual)2036 UBool IntlTest::assertEquals(const char* message,
2037 double expected,
2038 double actual) {
2039 bool bothNaN = std::isnan(expected) && std::isnan(actual);
2040 if (expected != actual && !bothNaN) {
2041 errln((UnicodeString)"FAIL: " + message + "; got " +
2042 actual +
2043 "; expected " + expected);
2044 return false;
2045 }
2046 #ifdef VERBOSE_ASSERTIONS
2047 else {
2048 logln((UnicodeString)"Ok: " + message + "; got " + actual);
2049 }
2050 #endif
2051 return true;
2052 }
2053
assertEquals(const char * message,UBool expected,UBool actual)2054 UBool IntlTest::assertEquals(const char* message,
2055 UBool expected,
2056 UBool actual) {
2057 if (expected != actual) {
2058 errln((UnicodeString)"FAIL: " + message + "; got " +
2059 toString(actual) +
2060 "; expected " + toString(expected));
2061 return false;
2062 }
2063 #ifdef VERBOSE_ASSERTIONS
2064 else {
2065 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
2066 }
2067 #endif
2068 return true;
2069 }
2070
2071
assertEquals(const char * message,UErrorCode expected,UErrorCode actual)2072 UBool IntlTest::assertEquals(const char* message,
2073 UErrorCode expected,
2074 UErrorCode actual) {
2075 if (expected != actual) {
2076 errln((UnicodeString)"FAIL: " + message + "; got " +
2077 u_errorName(actual) +
2078 "; expected " + u_errorName(expected));
2079 return false;
2080 }
2081 #ifdef VERBOSE_ASSERTIONS
2082 else {
2083 logln((UnicodeString)"Ok: " + message + "; got " + u_errorName(actual));
2084 }
2085 #endif
2086 return true;
2087 }
2088
assertEquals(const char * message,const UnicodeSet & expected,const UnicodeSet & actual)2089 UBool IntlTest::assertEquals(const char* message,
2090 const UnicodeSet& expected,
2091 const UnicodeSet& actual) {
2092 IcuTestErrorCode status(*this, "assertEqualsUniSet");
2093 if (expected != actual) {
2094 errln((UnicodeString)"FAIL: " + message + "; got " +
2095 toString(actual, status) +
2096 "; expected " + toString(expected, status));
2097 return false;
2098 }
2099 #ifdef VERBOSE_ASSERTIONS
2100 else {
2101 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual, status));
2102 }
2103 #endif
2104 return true;
2105 }
2106
2107
2108 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)2109 UBool IntlTest::assertEquals(const char* message,
2110 const Formattable& expected,
2111 const Formattable& actual,
2112 UBool possibleDataError) {
2113 if (expected != actual) {
2114 if (possibleDataError) {
2115 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
2116 toString(actual) +
2117 "; expected " + toString(expected));
2118 } else {
2119 errln((UnicodeString)"FAIL: " + message + "; got " +
2120 toString(actual) +
2121 "; expected " + toString(expected));
2122 }
2123 return false;
2124 }
2125 #ifdef VERBOSE_ASSERTIONS
2126 else {
2127 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
2128 }
2129 #endif
2130 return true;
2131 }
2132 #endif
2133
vectorToString(const std::vector<std::string> & strings)2134 std::string vectorToString(const std::vector<std::string>& strings) {
2135 std::string result = "{";
2136 bool first = true;
2137 for (auto element : strings) {
2138 if (first) {
2139 first = false;
2140 } else {
2141 result += ", ";
2142 }
2143 result += "\"";
2144 result += element;
2145 result += "\"";
2146 }
2147 result += "}";
2148 return result;
2149 }
2150
assertEquals(const char * message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2151 UBool IntlTest::assertEquals(const char* message,
2152 const std::vector<std::string>& expected,
2153 const std::vector<std::string>& actual) {
2154 if (expected != actual) {
2155 std::string expectedAsString = vectorToString(expected);
2156 std::string actualAsString = vectorToString(actual);
2157 errln((UnicodeString)"FAIL: " + message +
2158 "; got " + actualAsString.c_str() +
2159 "; expected " + expectedAsString.c_str());
2160 return false;
2161 }
2162 #ifdef VERBOSE_ASSERTIONS
2163 else {
2164 logln((UnicodeString)"Ok: " + message + "; got " + vectorToString(actual).c_str());
2165 }
2166 #endif
2167 return true;
2168 }
2169
assertNotEquals(const char * message,int32_t expectedNot,int32_t actual)2170 UBool IntlTest::assertNotEquals(const char* message,
2171 int32_t expectedNot,
2172 int32_t actual) {
2173 if (expectedNot == actual) {
2174 errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2175 "; expected != " + expectedNot);
2176 return false;
2177 }
2178 #ifdef VERBOSE_ASSERTIONS
2179 else {
2180 logln((UnicodeString)("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2181 " != " + expectedNot);
2182 }
2183 #endif
2184 return true;
2185 }
2186
assertEqualsNear(const char * message,double expected,double actual,double delta)2187 UBool IntlTest::assertEqualsNear(const char* message,
2188 double expected,
2189 double actual,
2190 double delta) {
2191 bool bothNaN = std::isnan(expected) && std::isnan(actual);
2192 bool bothPosInf = uprv_isPositiveInfinity(expected) && uprv_isPositiveInfinity(actual);
2193 bool bothNegInf = uprv_isNegativeInfinity(expected) && uprv_isNegativeInfinity(actual);
2194 if (bothPosInf || bothNegInf || bothNaN) {
2195 // We don't care about delta in these cases
2196 return true;
2197 }
2198 if (std::isnan(delta) || std::isinf(delta)) {
2199 errln((UnicodeString)("FAIL: ") + message + "; nonsensical delta " + delta +
2200 " - delta may not be NaN or Inf. (Got " + actual + "; expected " + expected + ".)");
2201 return false;
2202 }
2203 double difference = std::abs(expected - actual);
2204 if (expected != actual && (difference > delta || std::isnan(difference))) {
2205 errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "; expected " + expected +
2206 "; acceptable delta " + delta);
2207 return false;
2208 }
2209 #ifdef VERBOSE_ASSERTIONS
2210 else {
2211 logln((UnicodeString)("Ok: ") + message + "; got " + actual);
2212 }
2213 #endif
2214 return true;
2215 }
2216
2217 static char ASSERT_BUF[256];
2218
extractToAssertBuf(const UnicodeString & message)2219 static const char* extractToAssertBuf(const UnicodeString& message) {
2220 UnicodeString buf;
2221 escape(message, buf);
2222 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
2223 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
2224 return ASSERT_BUF;
2225 }
2226
assertTrue(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2227 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2228 return assertTrue(extractToAssertBuf(message), condition, quiet, possibleDataError);
2229 }
2230
assertFalse(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2231 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2232 return assertFalse(extractToAssertBuf(message), condition, quiet, possibleDataError);
2233 }
2234
assertSuccess(const UnicodeString & message,UErrorCode ec)2235 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2236 return assertSuccess(extractToAssertBuf(message), ec);
2237 }
2238
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)2239 UBool IntlTest::assertEquals(const UnicodeString& message,
2240 const UnicodeString& expected,
2241 const UnicodeString& actual,
2242 UBool possibleDataError) {
2243 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
2244 }
2245
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2246 UBool IntlTest::assertEquals(const UnicodeString& message,
2247 const char* expected,
2248 const char* actual) {
2249 return assertEquals(extractToAssertBuf(message), expected, actual);
2250 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2251 UBool IntlTest::assertEquals(const UnicodeString& message,
2252 UBool expected,
2253 UBool actual) {
2254 return assertEquals(extractToAssertBuf(message), expected, actual);
2255 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2256 UBool IntlTest::assertEquals(const UnicodeString& message,
2257 int32_t expected,
2258 int32_t actual) {
2259 return assertEquals(extractToAssertBuf(message), expected, actual);
2260 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2261 UBool IntlTest::assertEquals(const UnicodeString& message,
2262 int64_t expected,
2263 int64_t actual) {
2264 return assertEquals(extractToAssertBuf(message), expected, actual);
2265 }
assertEquals(const UnicodeString & message,double expected,double actual)2266 UBool IntlTest::assertEquals(const UnicodeString& message,
2267 double expected,
2268 double actual) {
2269 return assertEquals(extractToAssertBuf(message), expected, actual);
2270 }
assertEquals(const UnicodeString & message,UErrorCode expected,UErrorCode actual)2271 UBool IntlTest::assertEquals(const UnicodeString& message,
2272 UErrorCode expected,
2273 UErrorCode actual) {
2274 return assertEquals(extractToAssertBuf(message), expected, actual);
2275 }
assertEquals(const UnicodeString & message,const UnicodeSet & expected,const UnicodeSet & actual)2276 UBool IntlTest::assertEquals(const UnicodeString& message,
2277 const UnicodeSet& expected,
2278 const UnicodeSet& actual) {
2279 return assertEquals(extractToAssertBuf(message), expected, actual);
2280 }
assertEquals(const UnicodeString & message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2281 UBool IntlTest::assertEquals(const UnicodeString& message,
2282 const std::vector<std::string>& expected,
2283 const std::vector<std::string>& actual) {
2284 return assertEquals(extractToAssertBuf(message), expected, actual);
2285 }
assertNotEquals(const UnicodeString & message,int32_t expectedNot,int32_t actual)2286 UBool IntlTest::assertNotEquals(const UnicodeString &message,
2287 int32_t expectedNot,
2288 int32_t actual) {
2289 return assertNotEquals(extractToAssertBuf(message), expectedNot, actual);
2290 }
assertEqualsNear(const UnicodeString & message,double expected,double actual,double delta)2291 UBool IntlTest::assertEqualsNear(const UnicodeString& message,
2292 double expected,
2293 double actual,
2294 double delta) {
2295 return assertEqualsNear(extractToAssertBuf(message), expected, actual, delta);
2296 }
2297
2298 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2299 UBool IntlTest::assertEquals(const UnicodeString& message,
2300 const Formattable& expected,
2301 const Formattable& actual) {
2302 return assertEquals(extractToAssertBuf(message), expected, actual);
2303 }
2304 #endif
2305
setProperty(const char * propline)2306 void IntlTest::setProperty(const char* propline) {
2307 if (numProps < kMaxProps) {
2308 proplines[numProps] = propline;
2309 }
2310 numProps++;
2311 }
2312
getProperty(const char * prop)2313 const char* IntlTest::getProperty(const char* prop) {
2314 const char* val = NULL;
2315 for (int32_t i = 0; i < numProps; i++) {
2316 int32_t plen = static_cast<int32_t>(uprv_strlen(prop));
2317 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
2318 && proplines[i][plen] == '='
2319 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2320 val = &(proplines[i][plen+1]);
2321 break;
2322 }
2323 }
2324 return val;
2325 }
2326
2327 //-------------------------------------------------------------------------------
2328 //
2329 // ReadAndConvertFile Read a text data file, convert it to UChars, and
2330 // return the data in one big UChar * buffer, which the caller must delete.
2331 //
2332 // parameters:
2333 // fileName: the name of the file, with no directory part. The test data directory
2334 // is assumed.
2335 // ulen an out parameter, receives the actual length (in UChars) of the file data.
2336 // encoding The file encoding. If the file contains a BOM, that will override the encoding
2337 // specified here. The BOM, if it exists, will be stripped from the returned data.
2338 // Pass NULL for the system default encoding.
2339 // status
2340 // returns:
2341 // The file data, converted to UChar.
2342 // The caller must delete this when done with
2343 // delete [] theBuffer;
2344 //
2345 //
2346 //--------------------------------------------------------------------------------
ReadAndConvertFile(const char * fileName,int & ulen,const char * encoding,UErrorCode & status)2347 UChar *IntlTest::ReadAndConvertFile(const char *fileName, int &ulen, const char *encoding, UErrorCode &status) {
2348 UChar *retPtr = NULL;
2349 char *fileBuf = NULL;
2350 UConverter* conv = NULL;
2351 FILE *f = NULL;
2352
2353 ulen = 0;
2354 if (U_FAILURE(status)) {
2355 return retPtr;
2356 }
2357
2358 //
2359 // Open the file.
2360 //
2361 f = fopen(fileName, "rb");
2362 if (f == 0) {
2363 dataerrln("Error opening test data file %s\n", fileName);
2364 status = U_FILE_ACCESS_ERROR;
2365 return NULL;
2366 }
2367 //
2368 // Read it in
2369 //
2370 int fileSize;
2371 int amt_read;
2372
2373 fseek( f, 0, SEEK_END);
2374 fileSize = ftell(f);
2375 fileBuf = new char[fileSize];
2376 fseek(f, 0, SEEK_SET);
2377 amt_read = static_cast<int>(fread(fileBuf, 1, fileSize, f));
2378 if (amt_read != fileSize || fileSize <= 0) {
2379 errln("Error reading test data file.");
2380 goto cleanUpAndReturn;
2381 }
2382
2383 //
2384 // Look for a Unicode Signature (BOM) on the data just read
2385 //
2386 int32_t signatureLength;
2387 const char * fileBufC;
2388 const char* bomEncoding;
2389
2390 fileBufC = fileBuf;
2391 bomEncoding = ucnv_detectUnicodeSignature(
2392 fileBuf, fileSize, &signatureLength, &status);
2393 if(bomEncoding!=NULL ){
2394 fileBufC += signatureLength;
2395 fileSize -= signatureLength;
2396 encoding = bomEncoding;
2397 }
2398
2399 //
2400 // Open a converter to take the rule file to UTF-16
2401 //
2402 conv = ucnv_open(encoding, &status);
2403 if (U_FAILURE(status)) {
2404 goto cleanUpAndReturn;
2405 }
2406
2407 //
2408 // Convert the rules to UChar.
2409 // Preflight first to determine required buffer size.
2410 //
2411 ulen = ucnv_toUChars(conv,
2412 NULL, // dest,
2413 0, // destCapacity,
2414 fileBufC,
2415 fileSize,
2416 &status);
2417 if (status == U_BUFFER_OVERFLOW_ERROR) {
2418 // Buffer Overflow is expected from the preflight operation.
2419 status = U_ZERO_ERROR;
2420
2421 retPtr = new UChar[ulen+1];
2422 ucnv_toUChars(conv,
2423 retPtr, // dest,
2424 ulen+1,
2425 fileBufC,
2426 fileSize,
2427 &status);
2428 }
2429
2430 cleanUpAndReturn:
2431 fclose(f);
2432 delete []fileBuf;
2433 ucnv_close(conv);
2434 if (U_FAILURE(status)) {
2435 errln("ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status));
2436 delete []retPtr;
2437 retPtr = 0;
2438 ulen = 0;
2439 }
2440 return retPtr;
2441 }
2442
2443 #if !UCONFIG_NO_BREAK_ITERATION
LSTMDataIsBuilt()2444 UBool LSTMDataIsBuilt() {
2445 // If we can find the LSTM data, the RBBI will use the LSTM engine.
2446 // So we skip the test which depending on the dictionary data.
2447 UErrorCode status = U_ZERO_ERROR;
2448 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_THAI, status));
2449 UBool thaiDataIsBuilt = U_SUCCESS(status);
2450 status = U_ZERO_ERROR;
2451 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_MYANMAR, status));
2452 UBool burmeseDataIsBuilt = U_SUCCESS(status);
2453 return thaiDataIsBuilt | burmeseDataIsBuilt;
2454 }
2455
skipLSTMTest()2456 UBool IntlTest::skipLSTMTest() {
2457 return ! LSTMDataIsBuilt();
2458 }
skipDictionaryTest()2459 UBool IntlTest::skipDictionaryTest() {
2460 return LSTMDataIsBuilt();
2461 }
2462 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */
2463
2464 /*
2465 * Hey, Emacs, please set the following:
2466 *
2467 * Local Variables:
2468 * indent-tabs-mode: nil
2469 * End:
2470 *
2471 */
2472