1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
10 #include "unicode/utypes.h"
13 * IntlTest is a base class for tests.
23 #include "unicode/ctest.h" // for str_timeDelta
24 #include "unicode/curramt.h"
25 #include "unicode/locid.h"
26 #include "unicode/putil.h"
27 #include "unicode/smpdtfmt.h"
28 #include "unicode/timezone.h"
29 #include "unicode/uclean.h"
30 #include "unicode/ucnv.h"
31 #include "unicode/unistr.h"
32 #include "unicode/ures.h"
33 #include "unicode/utf16.h"
42 #include "putilimp.h" // for uprv_getRawUTCtime()
54 static char* _testDataPath
=NULL
;
56 // Static list of errors found
57 static UnicodeString errorList
;
58 static void *knownList
= NULL
; // known issues
59 static UBool noKnownIssues
= FALSE
; // if TRUE, don't emit known issues
61 //-----------------------------------------------------------------------------
62 //convenience classes to ease porting code that uses the Java
63 //string-concatenation operator (moved from findword test by rtg)
65 // [LIU] Just to get things working
67 UCharToUnicodeString(UChar c
)
68 { return UnicodeString(c
); }
70 // [rtg] Just to get things working
72 operator+(const UnicodeString
& left
,
75 char buffer
[64]; // nos changed from 10 to 64
76 char danger
= 'p'; // guard against overrunning the buffer (rtg)
78 sprintf(buffer
, "%ld", num
);
79 assert(danger
== 'p');
85 operator+(const UnicodeString
& left
,
88 char buffer
[64]; // nos changed from 10 to 64
89 char danger
= 'p'; // guard against overrunning the buffer (rtg)
91 sprintf(buffer
, "%lu", num
);
92 assert(danger
== 'p');
98 Int64ToUnicodeString(int64_t num
)
100 char buffer
[64]; // nos changed from 10 to 64
101 char danger
= 'p'; // guard against overrunning the buffer (rtg)
103 #if defined(_MSC_VER)
104 sprintf(buffer
, "%I64d", num
);
106 sprintf(buffer
, "%lld", (long long)num
);
108 assert(danger
== 'p');
114 DoubleToUnicodeString(double num
)
116 char buffer
[64]; // nos changed from 10 to 64
117 char danger
= 'p'; // guard against overrunning the buffer (rtg)
119 sprintf(buffer
, "%1.14e", num
);
120 assert(danger
== 'p');
125 // [LIU] Just to get things working
127 operator+(const UnicodeString
& left
,
130 char buffer
[64]; // was 32, made it arbitrarily bigger (rtg)
131 char danger
= 'p'; // guard against overrunning the buffer (rtg)
133 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
134 // 53*log(2)/log(10) = 15.95
135 // so there is no need to show more than 16 digits. [alan]
137 sprintf(buffer
, "%.17g", num
);
138 assert(danger
== 'p');
140 return left
+ buffer
;
145 operator+(const UnicodeString
& left
,
147 return left
+ Int64ToUnicodeString(num
);
151 #if !UCONFIG_NO_FORMATTING
154 * Return a string display for this, without surrounding braces.
156 UnicodeString
_toString(const Formattable
& f
) {
158 switch (f
.getType()) {
159 case Formattable::kDate
:
161 UErrorCode status
= U_ZERO_ERROR
;
162 SimpleDateFormat
fmt(status
);
163 if (U_SUCCESS(status
)) {
165 fmt
.format(f
.getDate(), s
, pos
);
166 s
.insert(0, "Date:");
168 s
= UnicodeString("Error creating date format]");
172 case Formattable::kDouble
:
173 s
= UnicodeString("double:") + f
.getDouble();
175 case Formattable::kLong
:
176 s
= UnicodeString("long:") + f
.getLong();
179 case Formattable::kInt64
:
180 s
= UnicodeString("int64:") + Int64ToUnicodeString(f
.getInt64());
183 case Formattable::kString
:
185 s
.insert(0, "String:");
187 case Formattable::kArray
:
190 const Formattable
* array
= f
.getArray(n
);
191 s
.insert(0, UnicodeString("Array:"));
192 UnicodeString
delim(", ");
193 for (i
=0; i
<n
; ++i
) {
197 s
= s
+ _toString(array
[i
]);
201 case Formattable::kObject
: {
202 const CurrencyAmount
* c
= dynamic_cast<const CurrencyAmount
*>(f
.getObject());
204 s
= _toString(c
->getNumber()) + " " + UnicodeString(c
->getISOCurrency());
206 s
= UnicodeString("Unknown UObject");
211 s
= UnicodeString("Unknown Formattable type=") + (int32_t)f
.getType();
218 * Originally coded this as operator+, but that makes the expression
219 * + char* ambiguous. - liu
221 UnicodeString
toString(const Formattable
& f
) {
222 UnicodeString
s((UChar
)91/*[*/);
223 s
.append(_toString(f
));
224 s
.append((UChar
)0x5d/*]*/);
230 // useful when operator+ won't cooperate
231 UnicodeString
toString(int32_t n
) {
232 return UnicodeString() + (long)n
;
237 UnicodeString
toString(UBool b
) {
238 return b
? UnicodeString("TRUE"):UnicodeString("FALSE");
241 UnicodeString
toString(const UnicodeSet
& uniset
, UErrorCode
& status
) {
242 UnicodeString result
;
243 uniset
.toPattern(result
, status
);
247 // stephen - cleaned up 05/05/99
248 UnicodeString
operator+(const UnicodeString
& left
, char num
)
249 { return left
+ (long)num
; }
250 UnicodeString
operator+(const UnicodeString
& left
, short num
)
251 { return left
+ (long)num
; }
252 UnicodeString
operator+(const UnicodeString
& left
, int num
)
253 { return left
+ (long)num
; }
254 UnicodeString
operator+(const UnicodeString
& left
, unsigned char num
)
255 { return left
+ (unsigned long)num
; }
256 UnicodeString
operator+(const UnicodeString
& left
, unsigned short num
)
257 { return left
+ (unsigned long)num
; }
258 UnicodeString
operator+(const UnicodeString
& left
, unsigned int num
)
259 { return left
+ (unsigned long)num
; }
260 UnicodeString
operator+(const UnicodeString
& left
, float num
)
261 { return left
+ (double)num
; }
265 // Append a hex string to the target
267 IntlTest::appendHex(uint32_t number
,
269 UnicodeString
& target
)
271 static const UChar digitString
[] = {
272 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
273 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
274 }; /* "0123456789ABCDEF" */
276 if (digits
< 0) { // auto-digits
279 while (number
> max
) {
281 max
= (max
<< 8) | 0xff;
287 target
+= digitString
[(number
>> 28) & 0xF];
290 target
+= digitString
[(number
>> 24) & 0xF];
293 target
+= digitString
[(number
>> 20) & 0xF];
296 target
+= digitString
[(number
>> 16) & 0xF];
299 target
+= digitString
[(number
>> 12) & 0xF];
302 target
+= digitString
[(number
>> 8) & 0xF];
305 target
+= digitString
[(number
>> 4) & 0xF];
308 target
+= digitString
[(number
>> 0) & 0xF];
317 IntlTest::toHex(uint32_t number
, int32_t digits
) {
318 UnicodeString result
;
319 appendHex(number
, digits
, result
);
323 static inline UBool
isPrintable(UChar32 c
) {
324 return c
<= 0x7E && (c
>= 0x20 || c
== 9 || c
== 0xA || c
== 0xD);
327 // Replace nonprintable characters with unicode escapes
329 IntlTest::prettify(const UnicodeString
&source
,
330 UnicodeString
&target
)
337 for (i
= 0; i
< source
.length(); )
339 UChar32 ch
= source
.char32At(i
);
342 if (!isPrintable(ch
))
346 appendHex(ch
, 4, target
);
349 appendHex(ch
, 8, target
);
363 // Replace nonprintable characters with unicode escapes
365 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
368 UnicodeString target
;
372 for (i
= 0; i
< source
.length();)
374 UChar32 ch
= source
.char32At(i
);
377 if (!isPrintable(ch
))
379 if (parseBackslash
) {
380 // If we are preceded by an odd number of backslashes,
381 // then this character has already been backslash escaped.
382 // Delete a backslash.
383 int32_t backslashCount
= 0;
384 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
385 if (target
.charAt(j
) == (UChar
)92) {
391 if ((backslashCount
% 2) == 1) {
392 target
.truncate(target
.length() - 1);
397 appendHex(ch
, 4, target
);
400 appendHex(ch
, 8, target
);
414 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
415 * set, try to deduce the directory in which ICU was built,
416 * and set ICU_DATA to "icu/source/data" in that location.
417 * The intent is to allow the tests to have a good chance
418 * of running without requiring that the user manually set
419 * ICU_DATA. Common data isn't a problem, since it is
420 * picked up via a static (build time) reference, but the
421 * tests dynamically load some data.
423 void IntlTest::setICU_DATA() {
424 const char *original_ICU_DATA
= getenv("ICU_DATA");
426 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
427 /* If the user set ICU_DATA, don't second-guess the person. */
431 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
432 // to point to the top of the build hierarchy, which may or
433 // may not be the same as the source directory, depending on
434 // the configure options used. At any rate,
435 // set the data path to the built data from this directory.
436 // The value is complete with quotes, so it can be used
437 // as-is as a string constant.
439 #if defined (U_TOPBUILDDIR)
441 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
442 u_setDataDirectory(env_string
);
447 // Use #else so we don't get compiler warnings due to the return above.
449 /* On Windows, the file name obtained from __FILE__ includes a full path.
450 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
451 * Change to "wherever\icu\source\data"
454 char p
[sizeof(__FILE__
) + 10];
459 /* We want to back over three '\' chars. */
460 /* Only Windows should end up here, so looking for '\' is safe. */
461 for (i
=1; i
<=3; i
++) {
462 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
463 if (pBackSlash
!= NULL
) {
464 *pBackSlash
= 0; /* Truncate the string at the '\' */
468 if (pBackSlash
!= NULL
) {
469 /* We found and truncated three names from the path.
470 * Now append "source\data" and set the environment
472 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
473 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
477 /* __FILE__ on MSVC7 does not contain the directory */
478 u_setDataDirectory(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
484 /* No location for the data dir was identifiable.
485 * Add other fallbacks for the test data location here if the need arises
490 //--------------------------------------------------------------------------------------
492 static const int32_t indentLevel_offset
= 3;
493 static const char delim
= '/';
495 IntlTest
* IntlTest::gTest
= NULL
;
497 static int32_t execCount
= 0;
499 void it_log( UnicodeString message
)
502 IntlTest::gTest
->log( message
);
505 void it_logln( UnicodeString message
)
508 IntlTest::gTest
->logln( message
);
511 void it_logln( void )
514 IntlTest::gTest
->logln();
517 void it_info( UnicodeString message
)
520 IntlTest::gTest
->info( message
);
523 void it_infoln( UnicodeString message
)
526 IntlTest::gTest
->infoln( message
);
529 void it_infoln( void )
532 IntlTest::gTest
->infoln();
538 IntlTest::gTest
->err();
541 void it_err( UnicodeString message
)
544 IntlTest::gTest
->err( message
);
547 void it_errln( UnicodeString message
)
550 IntlTest::gTest
->errln( message
);
553 void it_dataerr( UnicodeString message
)
556 IntlTest::gTest
->dataerr( message
);
559 void it_dataerrln( UnicodeString message
)
562 IntlTest::gTest
->dataerrln( message
);
575 warn_on_missing_data
= FALSE
;
580 LL_indentlevel
= indentLevel_offset
;
582 strcpy(basePath
, "/");
586 void IntlTest::setCaller( IntlTest
* callingTest
)
588 caller
= callingTest
;
590 warn_on_missing_data
= caller
->warn_on_missing_data
;
591 verbose
= caller
->verbose
;
592 no_err_msg
= caller
->no_err_msg
;
593 quick
= caller
->quick
;
594 threadCount
= caller
->threadCount
;
595 testoutfp
= caller
->testoutfp
;
596 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
597 numProps
= caller
->numProps
;
598 for (int32_t i
= 0; i
< numProps
; i
++) {
599 proplines
[i
] = caller
->proplines
[i
];
604 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
606 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
607 testToBeCalled
.setCaller( this );
608 strcpy(testToBeCalled
.basePath
, this->basePath
);
609 UBool result
= testToBeCalled
.runTest( testPath
, par
, testToBeCalled
.basePath
);
610 strcpy(testToBeCalled
.basePath
, this->basePath
); // reset it.
614 void IntlTest::setPath( char* pathVal
)
616 this->testPath
= pathVal
;
619 UBool
IntlTest::setVerbose( UBool verboseVal
)
621 UBool rval
= this->verbose
;
622 this->verbose
= verboseVal
;
626 UBool
IntlTest::setNotime( UBool no_time
)
628 UBool rval
= this->no_time
;
629 this->no_time
= no_time
;
633 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
635 UBool rval
= this->warn_on_missing_data
;
636 this->warn_on_missing_data
= warn_on_missing_dataVal
;
640 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
642 UBool rval
= this->no_err_msg
;
643 this->no_err_msg
= no_err_msgVal
;
647 UBool
IntlTest::setQuick( UBool quickVal
)
649 UBool rval
= this->quick
;
650 this->quick
= quickVal
;
654 UBool
IntlTest::setLeaks( UBool leaksVal
)
656 UBool rval
= this->leaks
;
657 this->leaks
= leaksVal
;
661 int32_t IntlTest::setThreadCount( int32_t count
)
663 int32_t rval
= this->threadCount
;
664 this->threadCount
= count
;
668 int32_t IntlTest::getErrors( void )
673 int32_t IntlTest::getDataErrors( void )
675 return dataErrorCount
;
678 UBool
IntlTest::runTest( char* name
, char* par
, char *baseName
)
683 char* baseNameBuffer
= NULL
;
685 if(baseName
== NULL
) {
686 baseNameBuffer
= (char*)malloc(1024);
687 baseName
=baseNameBuffer
;
688 strcpy(baseName
, "/");
692 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
694 testPath
= pos
+1; // store subpath for calling subtest
695 *pos
= 0; // split into two strings
700 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
701 rval
= runTestLoop( NULL
, par
, baseName
);
703 }else if (strcmp( name
, "LIST" ) == 0) {
708 rval
= runTestLoop( name
, par
, baseName
);
712 *pos
= delim
; // restore original value at pos
713 if(baseNameBuffer
!=NULL
) {
714 free(baseNameBuffer
);
719 // call individual tests, to be overridden to call implementations
720 void IntlTest::runIndexedTest( int32_t /*index*/, UBool
/*exec*/, const char* & /*name*/, char* /*par*/ )
722 // to be overridden by a method like:
725 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
726 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
727 default: name = ""; break;
730 this->errln("*** runIndexedTest needs to be overridden! ***");
734 UBool
IntlTest::runTestLoop( char* testname
, char* par
, char *baseName
)
739 int32_t lastErrorCount
;
741 UBool lastTestFailed
;
743 if(baseName
== NULL
) {
744 printf("ERROR: baseName can't be null.\n");
747 if ((char *)this->basePath
!= baseName
) {
748 strcpy(this->basePath
, baseName
);
752 char * saveBaseLoc
= baseName
+strlen(baseName
);
754 IntlTest
* saveTest
= gTest
;
757 this->runIndexedTest( index
, FALSE
, name
, par
);
758 if (strcmp(name
,"skip") == 0) {
759 run_this_test
= FALSE
;
761 if (!name
|| (name
[0] == 0))
764 run_this_test
= TRUE
;
766 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
770 lastErrorCount
= errorCount
;
773 sprintf(msg
, "%s {", name
);
774 LL_message(msg
, TRUE
);
775 UDate timeStart
= uprv_getRawUTCtime();
776 strcpy(saveBaseLoc
,name
);
777 strcat(saveBaseLoc
,"/");
779 strcpy(currName
, name
); // set
780 this->runIndexedTest( index
, TRUE
, name
, par
);
781 currName
[0]=0; // reset
783 UDate timeStop
= uprv_getRawUTCtime();
784 rval
= TRUE
; // at least one test has been called
787 sprintf(secs
, "%f", (timeStop
-timeStart
)/1000.0);
793 strcpy(saveBaseLoc
,name
);
796 ctest_xml_testcase(baseName
, name
, secs
, (lastErrorCount
!=errorCount
)?"err":NULL
);
799 saveBaseLoc
[0]=0; /* reset path */
801 if (lastErrorCount
== errorCount
) {
802 sprintf( msg
, " } OK: %s ", name
);
803 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
804 lastTestFailed
= FALSE
;
806 sprintf(msg
, " } ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
807 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
809 for(int i
=0;i
<LL_indentlevel
;i
++) {
814 lastTestFailed
= TRUE
;
817 if (lastTestFailed
) {
818 LL_message( "", TRUE
);
820 LL_message( msg
, TRUE
);
821 if (lastTestFailed
) {
822 LL_message( "", TRUE
);
837 * Adds given string to the log if we are in verbose mode.
839 void IntlTest::log( const UnicodeString
&message
)
842 LL_message( message
, FALSE
);
847 * Adds given string to the log if we are in verbose mode. Adds a new line to
850 void IntlTest::logln( const UnicodeString
&message
)
853 LL_message( message
, TRUE
);
857 void IntlTest::logln( void )
860 LL_message( "", TRUE
);
865 * Unconditionally adds given string to the log.
867 void IntlTest::info( const UnicodeString
&message
)
869 LL_message( message
, FALSE
);
873 * Unconditionally adds given string to the log. Adds a new line to
876 void IntlTest::infoln( const UnicodeString
&message
)
878 LL_message( message
, TRUE
);
881 void IntlTest::infoln( void )
883 LL_message( "", TRUE
);
886 int32_t IntlTest::IncErrorCount( void )
889 if (caller
) caller
->IncErrorCount();
893 int32_t IntlTest::IncDataErrorCount( void )
896 if (caller
) caller
->IncDataErrorCount();
897 return dataErrorCount
;
905 void IntlTest::err( const UnicodeString
&message
)
908 if (!no_err_msg
) LL_message( message
, FALSE
);
911 void IntlTest::errln( const UnicodeString
&message
)
914 if (!no_err_msg
) LL_message( message
, TRUE
);
917 void IntlTest::dataerr( const UnicodeString
&message
)
921 if (!warn_on_missing_data
) {
925 if (!no_err_msg
) LL_message( message
, FALSE
);
928 void IntlTest::dataerrln( const UnicodeString
&message
)
930 int32_t errCount
= IncDataErrorCount();
932 if (!warn_on_missing_data
) {
936 msg
= UnicodeString("[DATA] " + message
);
940 if ( errCount
== 1) {
941 LL_message( msg
+ " - (Are you missing data?)", TRUE
); // only show this message the first time
943 LL_message( msg
, TRUE
);
948 void IntlTest::errcheckln(UErrorCode status
, const UnicodeString
&message
) {
949 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
956 /* convenience functions that include sprintf formatting */
957 void IntlTest::log(const char *fmt
, ...)
963 /* sprintf it just to make sure that the information is valid */
964 vsprintf(buffer
, fmt
, ap
);
967 log(UnicodeString(buffer
, (const char *)NULL
));
971 void IntlTest::logln(const char *fmt
, ...)
977 /* sprintf it just to make sure that the information is valid */
978 vsprintf(buffer
, fmt
, ap
);
981 logln(UnicodeString(buffer
, (const char *)NULL
));
985 UBool
IntlTest::logKnownIssue(const char *ticket
, const char *fmt
, ...)
991 /* sprintf it just to make sure that the information is valid */
992 vsprintf(buffer
, fmt
, ap
);
994 return logKnownIssue(ticket
, UnicodeString(buffer
, (const char *)NULL
));
997 UBool
IntlTest::logKnownIssue(const char *ticket
) {
998 return logKnownIssue(ticket
, UnicodeString());
1001 UBool
IntlTest::logKnownIssue(const char *ticket
, const UnicodeString
&msg
) {
1002 if(noKnownIssues
) return FALSE
;
1004 char fullpath
[2048];
1005 strcpy(fullpath
, basePath
);
1006 strcat(fullpath
, currName
);
1007 UnicodeString msg2
= msg
;
1008 UBool firstForTicket
= TRUE
, firstForWhere
= TRUE
;
1009 knownList
= udbg_knownIssue_openU(knownList
, ticket
, fullpath
, msg2
.getTerminatedBuffer(), &firstForTicket
, &firstForWhere
);
1011 msg2
= UNICODE_STRING_SIMPLE("(Known issue #") +
1012 UnicodeString(ticket
, -1, US_INV
) + UNICODE_STRING_SIMPLE(") ") + msg
;
1013 if(firstForTicket
|| firstForWhere
) {
1022 /* convenience functions that include sprintf formatting */
1023 void IntlTest::info(const char *fmt
, ...)
1029 /* sprintf it just to make sure that the information is valid */
1030 vsprintf(buffer
, fmt
, ap
);
1032 info(UnicodeString(buffer
, (const char *)NULL
));
1035 void IntlTest::infoln(const char *fmt
, ...)
1041 /* sprintf it just to make sure that the information is valid */
1042 vsprintf(buffer
, fmt
, ap
);
1044 infoln(UnicodeString(buffer
, (const char *)NULL
));
1047 void IntlTest::err(const char *fmt
, ...)
1053 vsprintf(buffer
, fmt
, ap
);
1055 err(UnicodeString(buffer
, (const char *)NULL
));
1058 void IntlTest::errln(const char *fmt
, ...)
1064 vsprintf(buffer
, fmt
, ap
);
1066 errln(UnicodeString(buffer
, (const char *)NULL
));
1069 void IntlTest::dataerrln(const char *fmt
, ...)
1075 vsprintf(buffer
, fmt
, ap
);
1077 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1080 void IntlTest::errcheckln(UErrorCode status
, const char *fmt
, ...)
1086 vsprintf(buffer
, fmt
, ap
);
1089 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
1090 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1092 errln(UnicodeString(buffer
, (const char *)NULL
));
1096 void IntlTest::printErrors()
1098 IntlTest::LL_message(errorList
, TRUE
);
1101 UBool
IntlTest::printKnownIssues()
1103 if(knownList
!= NULL
) {
1104 udbg_knownIssue_print(knownList
);
1105 udbg_knownIssue_close(knownList
);
1112 static UMutex messageMutex
= U_MUTEX_INITIALIZER
;
1114 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
1116 // Synchronize this function.
1117 // All error messages generated by tests funnel through here.
1118 // Multithreaded tests can concurrently generate errors, requiring synchronization
1119 // to keep each message together.
1120 Mutex
lock(&messageMutex
);
1122 // string that starts with a LineFeed character and continues
1123 // with spaces according to the current indentation
1124 static const UChar indentUChars
[] = {
1126 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1127 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1128 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1129 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1130 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1131 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1132 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1133 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1134 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1135 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1137 U_ASSERT(1 + LL_indentlevel
<= UPRV_LENGTHOF(indentUChars
));
1138 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
1143 // stream out the indentation string first if necessary
1144 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
1146 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1149 // replace each LineFeed by the indentation string
1150 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
1152 // stream out the message
1153 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
1155 length
= length
> 30000 ? 30000 : length
;
1156 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1160 char newLine
= '\n';
1161 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
1164 // A newline usually flushes the buffer, but
1165 // flush the message just in case of a core dump.
1166 fflush((FILE *)testoutfp
);
1170 * Print a usage message for this test class.
1172 void IntlTest::usage( void )
1174 UBool save_verbose
= setVerbose( TRUE
);
1175 logln("Test names:");
1176 logln("-----------");
1179 const char* name
= NULL
;
1181 this->runIndexedTest( index
, FALSE
, name
);
1185 }while (name
&& (name
[0] != 0));
1186 setVerbose( save_verbose
);
1190 // memory leak reporting software will be able to take advantage of the testsuite
1191 // being run a second time local to a specific method in order to report only actual leaks
1193 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
1195 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
1196 strLeak
->append(" for verifying purify filter");
1197 return this->runTest( name
, par
);
1201 #if UCONFIG_NO_LEGACY_CONVERSION
1202 # define TRY_CNV_1 "iso-8859-1"
1203 # define TRY_CNV_2 "ibm-1208"
1205 # define TRY_CNV_1 "iso-8859-7"
1206 # define TRY_CNV_2 "sjis"
1209 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1210 U_CAPI
void unistr_printLengths();
1214 main(int argc
, char* argv
[])
1216 UBool syntax
= FALSE
;
1218 UBool verbose
= FALSE
;
1219 UBool no_err_msg
= FALSE
;
1220 UBool no_time
= FALSE
;
1223 UBool leaks
= FALSE
;
1225 const char *summary_file
= NULL
;
1226 UBool warnOnMissingData
= FALSE
;
1227 UBool defaultDataFound
= FALSE
;
1228 int32_t threadCount
= 12;
1229 UErrorCode errorCode
= U_ZERO_ERROR
;
1230 UConverter
*cnv
= NULL
;
1231 const char *warnOrErr
= "Failure";
1232 UDate startTime
, endTime
;
1234 const char *props
[IntlTest::kMaxProps
];
1237 U_MAIN_INIT_ARGS(argc
, argv
);
1239 startTime
= uprv_getRawUTCtime();
1241 for (int i
= 1; i
< argc
; ++i
) {
1242 if (argv
[i
][0] == '-') {
1243 const char* str
= argv
[i
] + 1;
1244 if (strcmp("verbose", str
) == 0 ||
1245 strcmp("v", str
) == 0)
1247 else if (strcmp("noerrormsg", str
) == 0 ||
1248 strcmp("n", str
) == 0)
1250 else if (strcmp("exhaustive", str
) == 0 ||
1251 strcmp("e", str
) == 0)
1253 else if (strcmp("all", str
) == 0 ||
1254 strcmp("a", str
) == 0)
1256 else if (strcmp("utf-8", str
) == 0 ||
1257 strcmp("u", str
) == 0)
1259 else if (strcmp("noknownissues", str
) == 0 ||
1260 strcmp("K", str
) == 0)
1261 noKnownIssues
= TRUE
;
1262 else if (strcmp("leaks", str
) == 0 ||
1263 strcmp("l", str
) == 0)
1265 else if (strcmp("notime", str
) == 0 ||
1266 strcmp("T", str
) == 0)
1268 else if (strncmp("E", str
, 1) == 0)
1269 summary_file
= str
+1;
1270 else if (strcmp("x", str
)==0) {
1272 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1275 if(ctest_xml_setFileName(argv
[i
])) { /* set the name */
1276 return 1; /* error */
1278 } else if (strcmp("w", str
) == 0) {
1279 warnOnMissingData
= TRUE
;
1280 warnOrErr
= "WARNING";
1282 else if (strncmp("threads:", str
, 8) == 0) {
1283 threadCount
= atoi(str
+ 8);
1285 else if (strncmp("prop:", str
, 5) == 0) {
1286 if (nProps
< IntlTest::kMaxProps
) {
1287 props
[nProps
] = str
+ 5;
1299 if (!all
&& !name
) {
1301 } else if (all
&& name
) {
1308 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1310 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1311 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1312 "### notime (T), \n"
1313 "### threads:<threadCount>\n"
1314 "### (The default thread count is 12.),\n"
1315 "### (Specify either -all (shortcut -a) or a test name). \n"
1316 "### -all will run all of the tests.\n"
1318 "### To get a list of the test names type: intltest LIST \n"
1319 "### To run just the utility tests type: intltest utility \n"
1321 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1322 "### For example to list the utility tests type: intltest utility/LIST \n"
1323 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1325 "### A parameter can be specified for a test by appending '@' and the value \n"
1326 "### to the testname. \n\n");
1330 if (nProps
> IntlTest::kMaxProps
) {
1331 fprintf(stdout
, "### Too many properties. Exiting.\n");
1334 MajorTestLevel major
;
1335 major
.setVerbose( verbose
);
1336 major
.setNoErrMsg( no_err_msg
);
1337 major
.setQuick( quick
);
1338 major
.setLeaks( leaks
);
1339 major
.setThreadCount( threadCount
);
1340 major
.setWarnOnMissingData( warnOnMissingData
);
1341 major
.setNotime (no_time
);
1342 for (int32_t i
= 0; i
< nProps
; i
++) {
1343 major
.setProperty(props
[i
]);
1347 fprintf(stdout
, "-----------------------------------------------\n");
1348 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1349 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1353 const char *charsetFamily
= "Unknown";
1354 int32_t voidSize
= (int32_t)sizeof(void*);
1355 int32_t bits
= voidSize
* 8;
1356 if(U_CHARSET_FAMILY
==U_ASCII_FAMILY
) {
1357 charsetFamily
="ASCII";
1358 } else if(U_CHARSET_FAMILY
==U_EBCDIC_FAMILY
) {
1359 charsetFamily
="EBCDIC";
1362 " Bits: %d, Byte order: %s, Chars: %s\n",
1363 bits
, U_IS_BIG_ENDIAN
?"Big endian":"Little endian",
1366 fprintf(stdout
, "-----------------------------------------------\n");
1367 fprintf(stdout
, " Options: \n");
1368 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1369 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1370 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1371 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1372 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1373 fprintf(stdout
, " utf-8 (u) : %s\n", (utf8
? "On" : "Off"));
1374 fprintf(stdout
, " notime (T) : %s\n", (no_time
? "On" : "Off"));
1375 fprintf(stdout
, " noknownissues (K) : %s\n", (noKnownIssues
? "On" : "Off"));
1376 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1377 fprintf(stdout
, " Threads : %d\n", threadCount
);
1378 for (int32_t i
= 0; i
< nProps
; i
++) {
1379 fprintf(stdout
, " Custom property (prop:) : %s\n", props
[i
]);
1381 fprintf(stdout
, "-----------------------------------------------\n");
1384 ucnv_setDefaultName("utf-8");
1386 /* Check whether ICU will initialize without forcing the build data directory into
1387 * the ICU_DATA path. Success here means either the data dll contains data, or that
1388 * this test program was run with ICU_DATA set externally. Failure of this check
1389 * is normal when ICU data is not packaged into a shared library.
1391 * Whether or not this test succeeds, we want to cleanup and reinitialize
1392 * with a data path so that data loading from individual files can be tested.
1395 if (U_FAILURE(errorCode
)) {
1397 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1398 defaultDataFound
= FALSE
;
1401 defaultDataFound
= TRUE
;
1405 ucnv_setDefaultName("utf-8");
1407 errorCode
= U_ZERO_ERROR
;
1409 /* Initialize ICU */
1410 if (!defaultDataFound
) {
1411 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1414 if (U_FAILURE(errorCode
)) {
1416 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1417 "*** Check the ICU_DATA environment variable and \n"
1418 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1419 if(warnOnMissingData
== 0) {
1420 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1426 // initial check for the default converter
1427 errorCode
= U_ZERO_ERROR
;
1428 cnv
= ucnv_open(0, &errorCode
);
1434 "*** %s! The default converter [%s] cannot be opened.\n"
1435 "*** Check the ICU_DATA environment variable and\n"
1436 "*** check that the data files are present.\n",
1437 warnOrErr
, ucnv_getDefaultName());
1438 if(!warnOnMissingData
) {
1439 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1445 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1451 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1452 "*** Check the ICU_DATA environment variable and \n"
1453 "*** check that the data files are present.\n", warnOrErr
);
1454 if(!warnOnMissingData
) {
1455 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1460 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1462 if(U_FAILURE(errorCode
)) {
1464 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1465 "*** Check the ICU_DATA environment variable and \n"
1466 "*** check that the data files are present.\n", warnOrErr
);
1467 if(!warnOnMissingData
) {
1468 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1473 Locale originalLocale
; // Save the default locale for comparison later on.
1475 if(ctest_xml_init("intltest"))
1479 /* TODO: Add option to call u_cleanup and rerun tests. */
1483 major
.run_phase2( NULL
, NULL
);
1486 for (int i
= 1; i
< argc
; ++i
) {
1487 if (argv
[i
][0] != '-') {
1488 char* name
= argv
[i
];
1489 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1491 char baseName
[1024];
1492 sprintf(baseName
, "/%s/", name
);
1494 char* parameter
= strchr( name
, '@' );
1500 UBool res
= major
.runTest( name
, parameter
, baseName
);
1502 major
.run_phase2( name
, parameter
);
1504 if (!res
|| (execCount
<= 0)) {
1505 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1507 } else if(!strcmp(argv
[i
],"-x")) {
1514 #if !UCONFIG_NO_FORMATTING
1515 CalendarTimeZoneTest::cleanup();
1518 free(_testDataPath
);
1521 Locale lastDefaultLocale
;
1522 if (originalLocale
!= lastDefaultLocale
) {
1523 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1526 fprintf(stdout
, "\n--------------------------------------\n");
1527 if( major
.printKnownIssues() ) {
1528 fprintf(stdout
, " To run suppressed tests, use the -K option. \n");
1530 if (major
.getErrors() == 0) {
1531 /* Call it twice to make sure that the defaults were reset. */
1532 /* Call it before the OK message to verify proper cleanup. */
1536 fprintf(stdout
, "OK: All tests passed without error.\n");
1538 if (major
.getDataErrors() != 0) {
1539 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1542 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1543 major
.printErrors();
1545 if(summary_file
!= NULL
) {
1546 FILE *summf
= fopen(summary_file
, "w");
1547 if( summf
!= NULL
) {
1549 int32_t length
= errorList
.extract(0, errorList
.length(), buf
, sizeof(buf
));
1550 fwrite(buf
, sizeof(*buf
), length
, (FILE*)summf
);
1556 if (major
.getDataErrors() != 0) {
1557 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1558 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1559 "\tthe '-w' option to turn these errors into warnings.\n");
1562 /* Call afterwards to display errors. */
1566 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1567 unistr_printLengths();
1570 fprintf(stdout
, "--------------------------------------\n");
1572 if (execCount
<= 0) {
1573 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1576 endTime
= uprv_getRawUTCtime();
1577 diffTime
= (int32_t)(endTime
- startTime
);
1578 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1579 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1580 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1581 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1582 (int)(diffTime%U_MILLIS_PER_SECOND
));
1585 if(ctest_xml_fini())
1588 return major
.getErrors();
1591 const char* IntlTest::loadTestData(UErrorCode
& err
){
1592 if( _testDataPath
== NULL
){
1593 const char* directory
=NULL
;
1594 UResourceBundle
* test
=NULL
;
1596 const char* tdrelativepath
;
1598 #if defined (U_TOPBUILDDIR)
1599 tdrelativepath
= "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1600 directory
= U_TOPBUILDDIR
;
1602 tdrelativepath
= ".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1603 directory
= pathToDataDirectory();
1606 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1609 /* u_getDataDirectory shoul return \source\data ... set the
1610 * directory to ..\source\data\..\test\testdata\out\testdata
1612 strcpy(tdpath
, directory
);
1613 strcat(tdpath
, tdrelativepath
);
1614 strcat(tdpath
,"testdata");
1616 test
=ures_open(tdpath
, "testtypes", &err
);
1619 err
= U_FILE_ACCESS_ERROR
;
1620 it_dataerrln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1624 _testDataPath
= tdpath
;
1625 return _testDataPath
;
1627 return _testDataPath
;
1630 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1631 return loadTestData(err
);
1634 /* Returns the path to icu/source/test/testdata/ */
1635 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1636 const char *srcDataDir
= NULL
;
1638 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1640 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1641 FILE *f
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"rbbitst.txt", "r");
1643 /* We're in icu/source/test/intltest/ */
1647 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1648 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
1649 "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1655 char *IntlTest::getUnidataPath(char path
[]) {
1656 const int kUnicodeDataTxtLength
= 15; // strlen("UnicodeData.txt")
1658 // Look inside ICU_DATA first.
1659 strcpy(path
, pathToDataDirectory());
1660 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1661 FILE *f
= fopen(path
, "r");
1664 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1668 // As a fallback, try to guess where the source data was located
1669 // at the time ICU was built, and look there.
1671 strcpy(path
, U_TOPSRCDIR U_FILE_SEP_STRING
"data");
1673 UErrorCode errorCode
= U_ZERO_ERROR
;
1674 const char *testDataPath
= loadTestData(errorCode
);
1675 if(U_FAILURE(errorCode
)) {
1676 it_errln(UnicodeString(
1677 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1678 u_errorName(errorCode
));
1681 strcpy(path
, testDataPath
);
1682 strcat(path
, U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1683 U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1684 U_FILE_SEP_STRING
"data");
1686 strcat(path
, U_FILE_SEP_STRING
);
1687 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1688 f
= fopen(path
, "r");
1691 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1697 const char* IntlTest::fgDataDir
= NULL
;
1699 /* returns the path to icu/source/data */
1700 const char * IntlTest::pathToDataDirectory()
1703 if(fgDataDir
!= NULL
) {
1707 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1708 // to point to the top of the build hierarchy, which may or
1709 // may not be the same as the source directory, depending on
1710 // the configure options used. At any rate,
1711 // set the data path to the built data from this directory.
1712 // The value is complete with quotes, so it can be used
1713 // as-is as a string constant.
1715 #if defined (U_TOPSRCDIR)
1717 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1721 /* On Windows, the file name obtained from __FILE__ includes a full path.
1722 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1723 * Change to "wherever\icu\source\data"
1726 static char p
[sizeof(__FILE__
) + 10];
1730 strcpy(p
, __FILE__
);
1731 /* We want to back over three '\' chars. */
1732 /* Only Windows should end up here, so looking for '\' is safe. */
1733 for (i
=1; i
<=3; i
++) {
1734 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1735 if (pBackSlash
!= NULL
) {
1736 *pBackSlash
= 0; /* Truncate the string at the '\' */
1740 if (pBackSlash
!= NULL
) {
1741 /* We found and truncated three names from the path.
1742 * Now append "source\data" and set the environment
1744 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1748 /* __FILE__ on MSVC7 does not contain the directory */
1749 FILE *file
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1752 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1755 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1766 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1767 * It converts an invariant-character string into a UnicodeString, with
1768 * unescaping \u sequences.
1770 UnicodeString
CharsToUnicodeString(const char* chars
){
1771 return UnicodeString(chars
, -1, US_INV
).unescape();
1774 UnicodeString
ctou(const char* chars
) {
1775 return CharsToUnicodeString(chars
);
1778 #define RAND_M (714025)
1779 #define RAND_IA (1366)
1780 #define RAND_IC (150889)
1782 static int32_t RAND_SEED
;
1785 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1786 * with care: Does not return all possible values; returns one of
1787 * 714,025 values, uniformly spaced. However, the period is
1788 * effectively infinite. See: Numerical Recipes, section 7.1.
1790 * @param seedp pointer to seed. Set *seedp to any negative value
1791 * to restart the sequence.
1793 float IntlTest::random(int32_t* seedp
) {
1794 static int32_t iy
, ir
[98];
1795 static UBool first
=TRUE
;
1797 if (*seedp
< 0 || first
) {
1799 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1800 for (j
=1;j
<=97;++j
) {
1801 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1804 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1807 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1808 U_ASSERT(j
>=1 && j
<=97);
1810 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1812 return (float) iy
/RAND_M
;
1816 * Convenience method using a global seed.
1818 float IntlTest::random() {
1819 return random(&RAND_SEED
);
1824 * Integer random number class implementation.
1825 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1827 IntlTest::icu_rand::icu_rand(uint32_t seed
) {
1828 seed
= seed
% 2147483647UL;
1835 IntlTest::icu_rand::~icu_rand() {}
1837 void IntlTest::icu_rand::seed(uint32_t seed
) {
1844 uint32_t IntlTest::icu_rand::operator() () {
1845 fLast
= ((uint64_t)fLast
* 48271UL) % 2147483647UL;
1849 uint32_t IntlTest::icu_rand::getSeed() {
1850 return (uint32_t) fLast
;
1855 static inline UChar
toHex(int32_t i
) {
1856 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1859 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1860 for (int32_t i
=0; i
<s
.length(); ++i
) {
1862 if (c
<= (UChar
)0x7F) {
1865 result
+= (UChar
)0x5c;
1866 result
+= (UChar
)0x75;
1867 result
+= toHex((c
>> 12) & 0xF);
1868 result
+= toHex((c
>> 8) & 0xF);
1869 result
+= toHex((c
>> 4) & 0xF);
1870 result
+= toHex( c
& 0xF);
1876 #define VERBOSE_ASSERTIONS
1878 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
, UBool possibleDataError
, const char *file
, int line
) {
1881 if (possibleDataError
) {
1882 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1884 errln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1886 } else if (!quiet
) {
1887 logln("%s:%d: Ok: %s", file
, line
, message
);
1891 if (possibleDataError
) {
1892 dataerrln("FAIL: assertTrue() failed: %s", message
);
1894 errln("FAIL: assertTrue() failed: %s", message
);
1896 } else if (!quiet
) {
1897 logln("Ok: %s", message
);
1904 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
, UBool possibleDataError
) {
1906 if (possibleDataError
) {
1907 dataerrln("FAIL: assertTrue() failed: %s", message
);
1909 errln("FAIL: assertTrue() failed: %s", message
);
1911 } else if (!quiet
) {
1912 logln("Ok: %s", message
);
1917 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
, UBool possibleDataError
, const char *file
, int line
) {
1919 file
= ""; // prevent failure if no file given
1921 if (U_FAILURE(ec
)) {
1922 if (possibleDataError
) {
1923 dataerrln("FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1925 errcheckln(ec
, "FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1929 logln("OK: %s:%d: %s - (%s)", file
, line
, message
, u_errorName(ec
));
1934 UBool
IntlTest::assertEquals(const char* message
,
1935 const UnicodeString
& expected
,
1936 const UnicodeString
& actual
,
1937 UBool possibleDataError
) {
1938 if (expected
!= actual
) {
1939 if (possibleDataError
) {
1940 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
1942 "; expected " + prettify(expected
));
1944 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1946 "; expected " + prettify(expected
));
1950 #ifdef VERBOSE_ASSERTIONS
1952 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1958 UBool
IntlTest::assertEquals(const char* message
,
1959 const char* expected
,
1960 const char* actual
) {
1961 if (uprv_strcmp(expected
, actual
) != 0) {
1962 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1964 "\"; expected \"" + expected
+ "\"");
1967 #ifdef VERBOSE_ASSERTIONS
1969 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1975 UBool
IntlTest::assertEquals(const char* message
,
1978 if (expected
!= actual
) {
1979 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1980 actual
+ "=0x" + toHex(actual
) +
1981 "; expected " + expected
+ "=0x" + toHex(expected
));
1984 #ifdef VERBOSE_ASSERTIONS
1986 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
+ "=0x" + toHex(actual
));
1992 UBool
IntlTest::assertEquals(const char* message
,
1995 if (expected
!= actual
) {
1996 errln((UnicodeString
)"FAIL: " + message
+ "; got int64 " +
1997 Int64ToUnicodeString(actual
) +
1998 "; expected " + Int64ToUnicodeString(expected
) );
2001 #ifdef VERBOSE_ASSERTIONS
2003 logln((UnicodeString
)"Ok: " + message
+ "; got int64 " + Int64ToUnicodeString(actual
));
2009 UBool
IntlTest::assertEquals(const char* message
,
2012 bool bothNaN
= std::isnan(expected
) && std::isnan(actual
);
2013 if (expected
!= actual
&& !bothNaN
) {
2014 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2016 "; expected " + expected
);
2019 #ifdef VERBOSE_ASSERTIONS
2021 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
);
2028 UBool
IntlTest::assertEquals(const char* message
,
2031 if (expected
!= actual
) {
2032 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2034 "; expected " + toString(expected
));
2037 #ifdef VERBOSE_ASSERTIONS
2039 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2046 UBool
IntlTest::assertEquals(const char* message
,
2047 UErrorCode expected
,
2048 UErrorCode actual
) {
2049 if (expected
!= actual
) {
2050 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2051 u_errorName(actual
) +
2052 "; expected " + u_errorName(expected
));
2055 #ifdef VERBOSE_ASSERTIONS
2057 logln((UnicodeString
)"Ok: " + message
+ "; got " + u_errorName(actual
));
2063 UBool
IntlTest::assertEquals(const char* message
,
2064 const UnicodeSet
& expected
,
2065 const UnicodeSet
& actual
) {
2066 IcuTestErrorCode
status(*this, "assertEqualsUniSet");
2067 if (expected
!= actual
) {
2068 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2069 toString(actual
, status
) +
2070 "; expected " + toString(expected
, status
));
2073 #ifdef VERBOSE_ASSERTIONS
2075 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
, status
));
2082 #if !UCONFIG_NO_FORMATTING
2083 UBool
IntlTest::assertEquals(const char* message
,
2084 const Formattable
& expected
,
2085 const Formattable
& actual
,
2086 UBool possibleDataError
) {
2087 if (expected
!= actual
) {
2088 if (possibleDataError
) {
2089 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
2091 "; expected " + toString(expected
));
2093 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2095 "; expected " + toString(expected
));
2099 #ifdef VERBOSE_ASSERTIONS
2101 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2108 static char ASSERT_BUF
[256];
2110 static const char* extractToAssertBuf(const UnicodeString
& message
) {
2112 escape(message
, buf
);
2113 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
2114 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
2118 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
, UBool possibleDataError
) {
2119 return assertTrue(extractToAssertBuf(message
), condition
, quiet
, possibleDataError
);
2122 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
, UBool possibleDataError
) {
2123 return assertFalse(extractToAssertBuf(message
), condition
, quiet
, possibleDataError
);
2126 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
2127 return assertSuccess(extractToAssertBuf(message
), ec
);
2130 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2131 const UnicodeString
& expected
,
2132 const UnicodeString
& actual
,
2133 UBool possibleDataError
) {
2134 return assertEquals(extractToAssertBuf(message
), expected
, actual
, possibleDataError
);
2137 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2138 const char* expected
,
2139 const char* actual
) {
2140 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2142 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2145 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2147 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2150 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2152 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2155 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2157 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2160 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2162 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2163 UErrorCode expected
,
2164 UErrorCode actual
) {
2165 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2167 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2168 const UnicodeSet
& expected
,
2169 const UnicodeSet
& actual
) {
2170 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2173 #if !UCONFIG_NO_FORMATTING
2174 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2175 const Formattable
& expected
,
2176 const Formattable
& actual
) {
2177 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2181 void IntlTest::setProperty(const char* propline
) {
2182 if (numProps
< kMaxProps
) {
2183 proplines
[numProps
] = propline
;
2188 const char* IntlTest::getProperty(const char* prop
) {
2189 const char* val
= NULL
;
2190 for (int32_t i
= 0; i
< numProps
; i
++) {
2191 int32_t plen
= uprv_strlen(prop
);
2192 if ((int32_t)uprv_strlen(proplines
[i
]) > plen
+ 1
2193 && proplines
[i
][plen
] == '='
2194 && uprv_strncmp(proplines
[i
], prop
, plen
) == 0) {
2195 val
= &(proplines
[i
][plen
+1]);
2203 * Hey, Emacs, please set the following:
2206 * indent-tabs-mode: nil