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.
22 #include "unicode/ctest.h" // for str_timeDelta
23 #include "unicode/curramt.h"
24 #include "unicode/locid.h"
25 #include "unicode/putil.h"
26 #include "unicode/smpdtfmt.h"
27 #include "unicode/timezone.h"
28 #include "unicode/uclean.h"
29 #include "unicode/ucnv.h"
30 #include "unicode/unistr.h"
31 #include "unicode/ures.h"
40 #include "putilimp.h" // for uprv_getRawUTCtime()
52 static char* _testDataPath
=NULL
;
54 // Static list of errors found
55 static UnicodeString errorList
;
56 static void *knownList
= NULL
; // known issues
57 static UBool noKnownIssues
= FALSE
; // if TRUE, don't emit known issues
59 //-----------------------------------------------------------------------------
60 //convenience classes to ease porting code that uses the Java
61 //string-concatenation operator (moved from findword test by rtg)
63 // [LIU] Just to get things working
65 UCharToUnicodeString(UChar c
)
66 { return UnicodeString(c
); }
68 // [rtg] Just to get things working
70 operator+(const UnicodeString
& left
,
73 char buffer
[64]; // nos changed from 10 to 64
74 char danger
= 'p'; // guard against overrunning the buffer (rtg)
76 sprintf(buffer
, "%ld", num
);
77 assert(danger
== 'p');
83 operator+(const UnicodeString
& left
,
86 char buffer
[64]; // nos changed from 10 to 64
87 char danger
= 'p'; // guard against overrunning the buffer (rtg)
89 sprintf(buffer
, "%lu", num
);
90 assert(danger
== 'p');
96 Int64ToUnicodeString(int64_t num
)
98 char buffer
[64]; // nos changed from 10 to 64
99 char danger
= 'p'; // guard against overrunning the buffer (rtg)
101 #if defined(_MSC_VER)
102 sprintf(buffer
, "%I64d", num
);
104 sprintf(buffer
, "%lld", (long long)num
);
106 assert(danger
== 'p');
111 // [LIU] Just to get things working
113 operator+(const UnicodeString
& left
,
116 char buffer
[64]; // was 32, made it arbitrarily bigger (rtg)
117 char danger
= 'p'; // guard against overrunning the buffer (rtg)
119 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
120 // 53*log(2)/log(10) = 15.95
121 // so there is no need to show more than 16 digits. [alan]
123 sprintf(buffer
, "%.17g", num
);
124 assert(danger
== 'p');
126 return left
+ buffer
;
131 operator+(const UnicodeString
& left
,
133 return left
+ Int64ToUnicodeString(num
);
137 #if !UCONFIG_NO_FORMATTING
140 * Return a string display for this, without surrounding braces.
142 UnicodeString
_toString(const Formattable
& f
) {
144 switch (f
.getType()) {
145 case Formattable::kDate
:
147 UErrorCode status
= U_ZERO_ERROR
;
148 SimpleDateFormat
fmt(status
);
149 if (U_SUCCESS(status
)) {
151 fmt
.format(f
.getDate(), s
, pos
);
152 s
.insert(0, "Date:");
154 s
= UnicodeString("Error creating date format]");
158 case Formattable::kDouble
:
159 s
= UnicodeString("double:") + f
.getDouble();
161 case Formattable::kLong
:
162 s
= UnicodeString("long:") + f
.getLong();
165 case Formattable::kInt64
:
166 s
= UnicodeString("int64:") + Int64ToUnicodeString(f
.getInt64());
169 case Formattable::kString
:
171 s
.insert(0, "String:");
173 case Formattable::kArray
:
176 const Formattable
* array
= f
.getArray(n
);
177 s
.insert(0, UnicodeString("Array:"));
178 UnicodeString
delim(", ");
179 for (i
=0; i
<n
; ++i
) {
183 s
= s
+ _toString(array
[i
]);
187 case Formattable::kObject
: {
188 const CurrencyAmount
* c
= dynamic_cast<const CurrencyAmount
*>(f
.getObject());
190 s
= _toString(c
->getNumber()) + " " + UnicodeString(c
->getISOCurrency());
192 s
= UnicodeString("Unknown UObject");
197 s
= UnicodeString("Unknown Formattable type=") + (int32_t)f
.getType();
204 * Originally coded this as operator+, but that makes the expression
205 * + char* ambiguous. - liu
207 UnicodeString
toString(const Formattable
& f
) {
208 UnicodeString
s((UChar
)91/*[*/);
209 s
.append(_toString(f
));
210 s
.append((UChar
)0x5d/*]*/);
216 // useful when operator+ won't cooperate
217 UnicodeString
toString(int32_t n
) {
218 return UnicodeString() + (long)n
;
223 UnicodeString
toString(UBool b
) {
224 return b
? UnicodeString("TRUE"):UnicodeString("FALSE");
227 // stephen - cleaned up 05/05/99
228 UnicodeString
operator+(const UnicodeString
& left
, char num
)
229 { return left
+ (long)num
; }
230 UnicodeString
operator+(const UnicodeString
& left
, short num
)
231 { return left
+ (long)num
; }
232 UnicodeString
operator+(const UnicodeString
& left
, int num
)
233 { return left
+ (long)num
; }
234 UnicodeString
operator+(const UnicodeString
& left
, unsigned char num
)
235 { return left
+ (unsigned long)num
; }
236 UnicodeString
operator+(const UnicodeString
& left
, unsigned short num
)
237 { return left
+ (unsigned long)num
; }
238 UnicodeString
operator+(const UnicodeString
& left
, unsigned int num
)
239 { return left
+ (unsigned long)num
; }
240 UnicodeString
operator+(const UnicodeString
& left
, float num
)
241 { return left
+ (double)num
; }
245 // Append a hex string to the target
247 IntlTest::appendHex(uint32_t number
,
249 UnicodeString
& target
)
251 static const UChar digitString
[] = {
252 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
253 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
254 }; /* "0123456789ABCDEF" */
256 if (digits
< 0) { // auto-digits
259 while (number
> max
) {
261 max
= (max
<< 8) | 0xff;
267 target
+= digitString
[(number
>> 28) & 0xF];
270 target
+= digitString
[(number
>> 24) & 0xF];
273 target
+= digitString
[(number
>> 20) & 0xF];
276 target
+= digitString
[(number
>> 16) & 0xF];
279 target
+= digitString
[(number
>> 12) & 0xF];
282 target
+= digitString
[(number
>> 8) & 0xF];
285 target
+= digitString
[(number
>> 4) & 0xF];
288 target
+= digitString
[(number
>> 0) & 0xF];
297 IntlTest::toHex(uint32_t number
, int32_t digits
) {
298 UnicodeString result
;
299 appendHex(number
, digits
, result
);
303 static inline UBool
isPrintable(UChar32 c
) {
304 return c
<= 0x7E && (c
>= 0x20 || c
== 9 || c
== 0xA || c
== 0xD);
307 // Replace nonprintable characters with unicode escapes
309 IntlTest::prettify(const UnicodeString
&source
,
310 UnicodeString
&target
)
317 for (i
= 0; i
< source
.length(); )
319 UChar32 ch
= source
.char32At(i
);
322 if (!isPrintable(ch
))
326 appendHex(ch
, 4, target
);
329 appendHex(ch
, 8, target
);
343 // Replace nonprintable characters with unicode escapes
345 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
348 UnicodeString target
;
352 for (i
= 0; i
< source
.length();)
354 UChar32 ch
= source
.char32At(i
);
357 if (!isPrintable(ch
))
359 if (parseBackslash
) {
360 // If we are preceded by an odd number of backslashes,
361 // then this character has already been backslash escaped.
362 // Delete a backslash.
363 int32_t backslashCount
= 0;
364 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
365 if (target
.charAt(j
) == (UChar
)92) {
371 if ((backslashCount
% 2) == 1) {
372 target
.truncate(target
.length() - 1);
377 appendHex(ch
, 4, target
);
380 appendHex(ch
, 8, target
);
394 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
395 * set, try to deduce the directory in which ICU was built,
396 * and set ICU_DATA to "icu/source/data" in that location.
397 * The intent is to allow the tests to have a good chance
398 * of running without requiring that the user manually set
399 * ICU_DATA. Common data isn't a problem, since it is
400 * picked up via a static (build time) reference, but the
401 * tests dynamically load some data.
403 void IntlTest::setICU_DATA() {
404 const char *original_ICU_DATA
= getenv("ICU_DATA");
406 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
407 /* If the user set ICU_DATA, don't second-guess the person. */
411 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
412 // to point to the top of the build hierarchy, which may or
413 // may not be the same as the source directory, depending on
414 // the configure options used. At any rate,
415 // set the data path to the built data from this directory.
416 // The value is complete with quotes, so it can be used
417 // as-is as a string constant.
419 #if defined (U_TOPBUILDDIR)
421 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
422 u_setDataDirectory(env_string
);
427 // Use #else so we don't get compiler warnings due to the return above.
429 /* On Windows, the file name obtained from __FILE__ includes a full path.
430 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
431 * Change to "wherever\icu\source\data"
434 char p
[sizeof(__FILE__
) + 10];
439 /* We want to back over three '\' chars. */
440 /* Only Windows should end up here, so looking for '\' is safe. */
441 for (i
=1; i
<=3; i
++) {
442 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
443 if (pBackSlash
!= NULL
) {
444 *pBackSlash
= 0; /* Truncate the string at the '\' */
448 if (pBackSlash
!= NULL
) {
449 /* We found and truncated three names from the path.
450 * Now append "source\data" and set the environment
452 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
453 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
457 /* __FILE__ on MSVC7 does not contain the directory */
458 u_setDataDirectory(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
464 /* No location for the data dir was identifiable.
465 * Add other fallbacks for the test data location here if the need arises
470 //--------------------------------------------------------------------------------------
472 static const int32_t indentLevel_offset
= 3;
473 static const char delim
= '/';
475 IntlTest
* IntlTest::gTest
= NULL
;
477 static int32_t execCount
= 0;
479 void it_log( UnicodeString message
)
482 IntlTest::gTest
->log( message
);
485 void it_logln( UnicodeString message
)
488 IntlTest::gTest
->logln( message
);
491 void it_logln( void )
494 IntlTest::gTest
->logln();
497 void it_info( UnicodeString message
)
500 IntlTest::gTest
->info( message
);
503 void it_infoln( UnicodeString message
)
506 IntlTest::gTest
->infoln( message
);
509 void it_infoln( void )
512 IntlTest::gTest
->infoln();
518 IntlTest::gTest
->err();
521 void it_err( UnicodeString message
)
524 IntlTest::gTest
->err( message
);
527 void it_errln( UnicodeString message
)
530 IntlTest::gTest
->errln( message
);
533 void it_dataerr( UnicodeString message
)
536 IntlTest::gTest
->dataerr( message
);
539 void it_dataerrln( UnicodeString message
)
542 IntlTest::gTest
->dataerrln( message
);
555 warn_on_missing_data
= FALSE
;
560 LL_indentlevel
= indentLevel_offset
;
562 strcpy(basePath
, "/");
566 void IntlTest::setCaller( IntlTest
* callingTest
)
568 caller
= callingTest
;
570 warn_on_missing_data
= caller
->warn_on_missing_data
;
571 verbose
= caller
->verbose
;
572 no_err_msg
= caller
->no_err_msg
;
573 quick
= caller
->quick
;
574 threadCount
= caller
->threadCount
;
575 testoutfp
= caller
->testoutfp
;
576 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
577 numProps
= caller
->numProps
;
578 for (int32_t i
= 0; i
< numProps
; i
++) {
579 proplines
[i
] = caller
->proplines
[i
];
584 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
586 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
587 testToBeCalled
.setCaller( this );
588 strcpy(testToBeCalled
.basePath
, this->basePath
);
589 UBool result
= testToBeCalled
.runTest( testPath
, par
, testToBeCalled
.basePath
);
590 strcpy(testToBeCalled
.basePath
, this->basePath
); // reset it.
594 void IntlTest::setPath( char* pathVal
)
596 this->testPath
= pathVal
;
599 UBool
IntlTest::setVerbose( UBool verboseVal
)
601 UBool rval
= this->verbose
;
602 this->verbose
= verboseVal
;
606 UBool
IntlTest::setNotime( UBool no_time
)
608 UBool rval
= this->no_time
;
609 this->no_time
= no_time
;
613 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
615 UBool rval
= this->warn_on_missing_data
;
616 this->warn_on_missing_data
= warn_on_missing_dataVal
;
620 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
622 UBool rval
= this->no_err_msg
;
623 this->no_err_msg
= no_err_msgVal
;
627 UBool
IntlTest::setQuick( UBool quickVal
)
629 UBool rval
= this->quick
;
630 this->quick
= quickVal
;
634 UBool
IntlTest::setLeaks( UBool leaksVal
)
636 UBool rval
= this->leaks
;
637 this->leaks
= leaksVal
;
641 int32_t IntlTest::setThreadCount( int32_t count
)
643 int32_t rval
= this->threadCount
;
644 this->threadCount
= count
;
648 int32_t IntlTest::getErrors( void )
653 int32_t IntlTest::getDataErrors( void )
655 return dataErrorCount
;
658 UBool
IntlTest::runTest( char* name
, char* par
, char *baseName
)
663 char* baseNameBuffer
= NULL
;
665 if(baseName
== NULL
) {
666 baseNameBuffer
= (char*)malloc(1024);
667 baseName
=baseNameBuffer
;
668 strcpy(baseName
, "/");
672 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
674 testPath
= pos
+1; // store subpath for calling subtest
675 *pos
= 0; // split into two strings
680 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
681 rval
= runTestLoop( NULL
, par
, baseName
);
683 }else if (strcmp( name
, "LIST" ) == 0) {
688 rval
= runTestLoop( name
, par
, baseName
);
692 *pos
= delim
; // restore original value at pos
693 if(baseNameBuffer
!=NULL
) {
694 free(baseNameBuffer
);
699 // call individual tests, to be overriden to call implementations
700 void IntlTest::runIndexedTest( int32_t /*index*/, UBool
/*exec*/, const char* & /*name*/, char* /*par*/ )
702 // to be overriden by a method like:
705 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
706 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
707 default: name = ""; break;
710 this->errln("*** runIndexedTest needs to be overriden! ***");
714 UBool
IntlTest::runTestLoop( char* testname
, char* par
, char *baseName
)
719 int32_t lastErrorCount
;
721 UBool lastTestFailed
;
723 if(baseName
== NULL
) {
724 printf("ERROR: baseName can't be null.\n");
727 if ((char *)this->basePath
!= baseName
) {
728 strcpy(this->basePath
, baseName
);
732 char * saveBaseLoc
= baseName
+strlen(baseName
);
734 IntlTest
* saveTest
= gTest
;
737 this->runIndexedTest( index
, FALSE
, name
, par
);
738 if (strcmp(name
,"skip") == 0) {
739 run_this_test
= FALSE
;
741 if (!name
|| (name
[0] == 0))
744 run_this_test
= TRUE
;
746 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
750 lastErrorCount
= errorCount
;
753 sprintf(msg
, "%s {", name
);
754 LL_message(msg
, TRUE
);
755 UDate timeStart
= uprv_getRawUTCtime();
756 strcpy(saveBaseLoc
,name
);
757 strcat(saveBaseLoc
,"/");
759 strcpy(currName
, name
); // set
760 this->runIndexedTest( index
, TRUE
, name
, par
);
761 currName
[0]=0; // reset
763 UDate timeStop
= uprv_getRawUTCtime();
764 rval
= TRUE
; // at least one test has been called
767 sprintf(secs
, "%f", (timeStop
-timeStart
)/1000.0);
773 strcpy(saveBaseLoc
,name
);
776 ctest_xml_testcase(baseName
, name
, secs
, (lastErrorCount
!=errorCount
)?"err":NULL
);
779 saveBaseLoc
[0]=0; /* reset path */
781 if (lastErrorCount
== errorCount
) {
782 sprintf( msg
, " } OK: %s ", name
);
783 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
784 lastTestFailed
= FALSE
;
786 sprintf(msg
, " } ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
787 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
789 for(int i
=0;i
<LL_indentlevel
;i
++) {
794 lastTestFailed
= TRUE
;
797 if (lastTestFailed
) {
798 LL_message( "", TRUE
);
800 LL_message( msg
, TRUE
);
801 if (lastTestFailed
) {
802 LL_message( "", TRUE
);
817 * Adds given string to the log if we are in verbose mode.
819 void IntlTest::log( const UnicodeString
&message
)
822 LL_message( message
, FALSE
);
827 * Adds given string to the log if we are in verbose mode. Adds a new line to
830 void IntlTest::logln( const UnicodeString
&message
)
833 LL_message( message
, TRUE
);
837 void IntlTest::logln( void )
840 LL_message( "", TRUE
);
845 * Unconditionally adds given string to the log.
847 void IntlTest::info( const UnicodeString
&message
)
849 LL_message( message
, FALSE
);
853 * Unconditionally adds given string to the log. Adds a new line to
856 void IntlTest::infoln( const UnicodeString
&message
)
858 LL_message( message
, TRUE
);
861 void IntlTest::infoln( void )
863 LL_message( "", TRUE
);
866 int32_t IntlTest::IncErrorCount( void )
869 if (caller
) caller
->IncErrorCount();
873 int32_t IntlTest::IncDataErrorCount( void )
876 if (caller
) caller
->IncDataErrorCount();
877 return dataErrorCount
;
885 void IntlTest::err( const UnicodeString
&message
)
888 if (!no_err_msg
) LL_message( message
, FALSE
);
891 void IntlTest::errln( const UnicodeString
&message
)
894 if (!no_err_msg
) LL_message( message
, TRUE
);
897 void IntlTest::dataerr( const UnicodeString
&message
)
901 if (!warn_on_missing_data
) {
905 if (!no_err_msg
) LL_message( message
, FALSE
);
908 void IntlTest::dataerrln( const UnicodeString
&message
)
910 int32_t errCount
= IncDataErrorCount();
912 if (!warn_on_missing_data
) {
916 msg
= UnicodeString("[DATA] " + message
);
920 if ( errCount
== 1) {
921 LL_message( msg
+ " - (Are you missing data?)", TRUE
); // only show this message the first time
923 LL_message( msg
, TRUE
);
928 void IntlTest::errcheckln(UErrorCode status
, const UnicodeString
&message
) {
929 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
936 /* convenience functions that include sprintf formatting */
937 void IntlTest::log(const char *fmt
, ...)
943 /* sprintf it just to make sure that the information is valid */
944 vsprintf(buffer
, fmt
, ap
);
947 log(UnicodeString(buffer
, (const char *)NULL
));
951 void IntlTest::logln(const char *fmt
, ...)
957 /* sprintf it just to make sure that the information is valid */
958 vsprintf(buffer
, fmt
, ap
);
961 logln(UnicodeString(buffer
, (const char *)NULL
));
965 UBool
IntlTest::logKnownIssue(const char *ticket
, const char *fmt
, ...)
971 /* sprintf it just to make sure that the information is valid */
972 vsprintf(buffer
, fmt
, ap
);
974 return logKnownIssue(ticket
, UnicodeString(buffer
, (const char *)NULL
));
977 UBool
IntlTest::logKnownIssue(const char *ticket
) {
978 return logKnownIssue(ticket
, UnicodeString());
981 UBool
IntlTest::logKnownIssue(const char *ticket
, const UnicodeString
&msg
) {
982 if(noKnownIssues
) return FALSE
;
985 strcpy(fullpath
, basePath
);
986 strcat(fullpath
, currName
);
987 UnicodeString msg2
= msg
;
988 UBool firstForTicket
= TRUE
, firstForWhere
= TRUE
;
989 knownList
= udbg_knownIssue_openU(knownList
, ticket
, fullpath
, msg2
.getTerminatedBuffer(), &firstForTicket
, &firstForWhere
);
991 msg2
= UNICODE_STRING_SIMPLE("(Known issue #") +
992 UnicodeString(ticket
, -1, US_INV
) + UNICODE_STRING_SIMPLE(") ") + msg
;
993 if(firstForTicket
|| firstForWhere
) {
1002 /* convenience functions that include sprintf formatting */
1003 void IntlTest::info(const char *fmt
, ...)
1009 /* sprintf it just to make sure that the information is valid */
1010 vsprintf(buffer
, fmt
, ap
);
1012 info(UnicodeString(buffer
, (const char *)NULL
));
1015 void IntlTest::infoln(const char *fmt
, ...)
1021 /* sprintf it just to make sure that the information is valid */
1022 vsprintf(buffer
, fmt
, ap
);
1024 infoln(UnicodeString(buffer
, (const char *)NULL
));
1027 void IntlTest::err(const char *fmt
, ...)
1033 vsprintf(buffer
, fmt
, ap
);
1035 err(UnicodeString(buffer
, (const char *)NULL
));
1038 void IntlTest::errln(const char *fmt
, ...)
1044 vsprintf(buffer
, fmt
, ap
);
1046 errln(UnicodeString(buffer
, (const char *)NULL
));
1049 void IntlTest::dataerrln(const char *fmt
, ...)
1055 vsprintf(buffer
, fmt
, ap
);
1057 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1060 void IntlTest::errcheckln(UErrorCode status
, const char *fmt
, ...)
1066 vsprintf(buffer
, fmt
, ap
);
1069 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
1070 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1072 errln(UnicodeString(buffer
, (const char *)NULL
));
1076 void IntlTest::printErrors()
1078 IntlTest::LL_message(errorList
, TRUE
);
1081 UBool
IntlTest::printKnownIssues()
1083 if(knownList
!= NULL
) {
1084 udbg_knownIssue_print(knownList
);
1085 udbg_knownIssue_close(knownList
);
1092 static UMutex messageMutex
= U_MUTEX_INITIALIZER
;
1094 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
1096 // Synchronize this function.
1097 // All error messages generated by tests funnel through here.
1098 // Multithreaded tests can concurrently generate errors, requiring syncronization
1099 // to keep each message together.
1100 Mutex
lock(&messageMutex
);
1102 // string that starts with a LineFeed character and continues
1103 // with spaces according to the current indentation
1104 static const UChar indentUChars
[] = {
1106 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1107 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1108 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1109 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1110 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1111 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1112 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1113 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1114 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1115 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1117 U_ASSERT(1 + LL_indentlevel
<= UPRV_LENGTHOF(indentUChars
));
1118 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
1123 // stream out the indentation string first if necessary
1124 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
1126 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1129 // replace each LineFeed by the indentation string
1130 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
1132 // stream out the message
1133 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
1135 length
= length
> 30000 ? 30000 : length
;
1136 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1140 char newLine
= '\n';
1141 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
1144 // A newline usually flushes the buffer, but
1145 // flush the message just in case of a core dump.
1146 fflush((FILE *)testoutfp
);
1150 * Print a usage message for this test class.
1152 void IntlTest::usage( void )
1154 UBool save_verbose
= setVerbose( TRUE
);
1155 logln("Test names:");
1156 logln("-----------");
1159 const char* name
= NULL
;
1161 this->runIndexedTest( index
, FALSE
, name
);
1165 }while (name
&& (name
[0] != 0));
1166 setVerbose( save_verbose
);
1170 // memory leak reporting software will be able to take advantage of the testsuite
1171 // being run a second time local to a specific method in order to report only actual leaks
1173 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
1175 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
1176 strLeak
->append(" for verifying purify filter");
1177 return this->runTest( name
, par
);
1181 #if UCONFIG_NO_LEGACY_CONVERSION
1182 # define TRY_CNV_1 "iso-8859-1"
1183 # define TRY_CNV_2 "ibm-1208"
1185 # define TRY_CNV_1 "iso-8859-7"
1186 # define TRY_CNV_2 "sjis"
1189 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1190 U_CAPI
void unistr_printLengths();
1194 main(int argc
, char* argv
[])
1196 UBool syntax
= FALSE
;
1198 UBool verbose
= FALSE
;
1199 UBool no_err_msg
= FALSE
;
1200 UBool no_time
= FALSE
;
1203 UBool leaks
= FALSE
;
1205 const char *summary_file
= NULL
;
1206 UBool warnOnMissingData
= FALSE
;
1207 UBool defaultDataFound
= FALSE
;
1208 int32_t threadCount
= 12;
1209 UErrorCode errorCode
= U_ZERO_ERROR
;
1210 UConverter
*cnv
= NULL
;
1211 const char *warnOrErr
= "Failure";
1212 UDate startTime
, endTime
;
1214 const char *props
[IntlTest::kMaxProps
];
1217 U_MAIN_INIT_ARGS(argc
, argv
);
1219 startTime
= uprv_getRawUTCtime();
1221 for (int i
= 1; i
< argc
; ++i
) {
1222 if (argv
[i
][0] == '-') {
1223 const char* str
= argv
[i
] + 1;
1224 if (strcmp("verbose", str
) == 0 ||
1225 strcmp("v", str
) == 0)
1227 else if (strcmp("noerrormsg", str
) == 0 ||
1228 strcmp("n", str
) == 0)
1230 else if (strcmp("exhaustive", str
) == 0 ||
1231 strcmp("e", str
) == 0)
1233 else if (strcmp("all", str
) == 0 ||
1234 strcmp("a", str
) == 0)
1236 else if (strcmp("utf-8", str
) == 0 ||
1237 strcmp("u", str
) == 0)
1239 else if (strcmp("noknownissues", str
) == 0 ||
1240 strcmp("K", str
) == 0)
1241 noKnownIssues
= TRUE
;
1242 else if (strcmp("leaks", str
) == 0 ||
1243 strcmp("l", str
) == 0)
1245 else if (strcmp("notime", str
) == 0 ||
1246 strcmp("T", str
) == 0)
1248 else if (strncmp("E", str
, 1) == 0)
1249 summary_file
= str
+1;
1250 else if (strcmp("x", str
)==0) {
1252 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1255 if(ctest_xml_setFileName(argv
[i
])) { /* set the name */
1256 return 1; /* error */
1258 } else if (strcmp("w", str
) == 0) {
1259 warnOnMissingData
= TRUE
;
1260 warnOrErr
= "WARNING";
1262 else if (strncmp("threads:", str
, 8) == 0) {
1263 threadCount
= atoi(str
+ 8);
1265 else if (strncmp("prop:", str
, 5) == 0) {
1266 if (nProps
< IntlTest::kMaxProps
) {
1267 props
[nProps
] = str
+ 5;
1279 if (!all
&& !name
) {
1281 } else if (all
&& name
) {
1288 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1290 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1291 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1292 "### notime (T), \n"
1293 "### threads:<threadCount>\n"
1294 "### (The default thread count is 12.),\n"
1295 "### (Specify either -all (shortcut -a) or a test name). \n"
1296 "### -all will run all of the tests.\n"
1298 "### To get a list of the test names type: intltest LIST \n"
1299 "### To run just the utility tests type: intltest utility \n"
1301 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1302 "### For example to list the utility tests type: intltest utility/LIST \n"
1303 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1305 "### A parameter can be specified for a test by appending '@' and the value \n"
1306 "### to the testname. \n\n");
1310 if (nProps
> IntlTest::kMaxProps
) {
1311 fprintf(stdout
, "### Too many properties. Exiting.\n");
1314 MajorTestLevel major
;
1315 major
.setVerbose( verbose
);
1316 major
.setNoErrMsg( no_err_msg
);
1317 major
.setQuick( quick
);
1318 major
.setLeaks( leaks
);
1319 major
.setThreadCount( threadCount
);
1320 major
.setWarnOnMissingData( warnOnMissingData
);
1321 major
.setNotime (no_time
);
1322 for (int32_t i
= 0; i
< nProps
; i
++) {
1323 major
.setProperty(props
[i
]);
1327 fprintf(stdout
, "-----------------------------------------------\n");
1328 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1329 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1333 const char *charsetFamily
= "Unknown";
1334 int32_t voidSize
= (int32_t)sizeof(void*);
1335 int32_t bits
= voidSize
* 8;
1336 if(U_CHARSET_FAMILY
==U_ASCII_FAMILY
) {
1337 charsetFamily
="ASCII";
1338 } else if(U_CHARSET_FAMILY
==U_EBCDIC_FAMILY
) {
1339 charsetFamily
="EBCDIC";
1342 " Bits: %d, Byte order: %s, Chars: %s\n",
1343 bits
, U_IS_BIG_ENDIAN
?"Big endian":"Little endian",
1346 fprintf(stdout
, "-----------------------------------------------\n");
1347 fprintf(stdout
, " Options: \n");
1348 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1349 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1350 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1351 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1352 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1353 fprintf(stdout
, " utf-8 (u) : %s\n", (utf8
? "On" : "Off"));
1354 fprintf(stdout
, " notime (T) : %s\n", (no_time
? "On" : "Off"));
1355 fprintf(stdout
, " noknownissues (K) : %s\n", (noKnownIssues
? "On" : "Off"));
1356 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1357 fprintf(stdout
, " Threads : %d\n", threadCount
);
1358 for (int32_t i
= 0; i
< nProps
; i
++) {
1359 fprintf(stdout
, " Custom property (prop:) : %s\n", props
[i
]);
1361 fprintf(stdout
, "-----------------------------------------------\n");
1364 ucnv_setDefaultName("utf-8");
1366 /* Check whether ICU will initialize without forcing the build data directory into
1367 * the ICU_DATA path. Success here means either the data dll contains data, or that
1368 * this test program was run with ICU_DATA set externally. Failure of this check
1369 * is normal when ICU data is not packaged into a shared library.
1371 * Whether or not this test succeeds, we want to cleanup and reinitialize
1372 * with a data path so that data loading from individual files can be tested.
1375 if (U_FAILURE(errorCode
)) {
1377 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1378 defaultDataFound
= FALSE
;
1381 defaultDataFound
= TRUE
;
1385 ucnv_setDefaultName("utf-8");
1387 errorCode
= U_ZERO_ERROR
;
1389 /* Initialize ICU */
1390 if (!defaultDataFound
) {
1391 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1394 if (U_FAILURE(errorCode
)) {
1396 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1397 "*** Check the ICU_DATA environment variable and \n"
1398 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1399 if(warnOnMissingData
== 0) {
1400 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1406 // initial check for the default converter
1407 errorCode
= U_ZERO_ERROR
;
1408 cnv
= ucnv_open(0, &errorCode
);
1414 "*** %s! The default converter [%s] cannot be opened.\n"
1415 "*** Check the ICU_DATA environment variable and\n"
1416 "*** check that the data files are present.\n",
1417 warnOrErr
, ucnv_getDefaultName());
1418 if(!warnOnMissingData
) {
1419 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1425 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1431 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1432 "*** Check the ICU_DATA environment variable and \n"
1433 "*** check that the data files are present.\n", warnOrErr
);
1434 if(!warnOnMissingData
) {
1435 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1440 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1442 if(U_FAILURE(errorCode
)) {
1444 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1445 "*** Check the ICU_DATA environment variable and \n"
1446 "*** check that the data files are present.\n", warnOrErr
);
1447 if(!warnOnMissingData
) {
1448 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1453 Locale originalLocale
; // Save the default locale for comparison later on.
1455 if(ctest_xml_init("intltest"))
1459 /* TODO: Add option to call u_cleanup and rerun tests. */
1463 major
.run_phase2( NULL
, NULL
);
1466 for (int i
= 1; i
< argc
; ++i
) {
1467 if (argv
[i
][0] != '-') {
1468 char* name
= argv
[i
];
1469 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1471 char baseName
[1024];
1472 sprintf(baseName
, "/%s/", name
);
1474 char* parameter
= strchr( name
, '@' );
1480 UBool res
= major
.runTest( name
, parameter
, baseName
);
1482 major
.run_phase2( name
, parameter
);
1484 if (!res
|| (execCount
<= 0)) {
1485 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1487 } else if(!strcmp(argv
[i
],"-x")) {
1494 #if !UCONFIG_NO_FORMATTING
1495 CalendarTimeZoneTest::cleanup();
1498 free(_testDataPath
);
1501 Locale lastDefaultLocale
;
1502 if (originalLocale
!= lastDefaultLocale
) {
1503 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1506 fprintf(stdout
, "\n--------------------------------------\n");
1507 if( major
.printKnownIssues() ) {
1508 fprintf(stdout
, " To run suppressed tests, use the -K option. \n");
1510 if (major
.getErrors() == 0) {
1511 /* Call it twice to make sure that the defaults were reset. */
1512 /* Call it before the OK message to verify proper cleanup. */
1516 fprintf(stdout
, "OK: All tests passed without error.\n");
1518 if (major
.getDataErrors() != 0) {
1519 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1522 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1523 major
.printErrors();
1525 if(summary_file
!= NULL
) {
1526 FILE *summf
= fopen(summary_file
, "w");
1527 if( summf
!= NULL
) {
1529 int32_t length
= errorList
.extract(0, errorList
.length(), buf
, sizeof(buf
));
1530 fwrite(buf
, sizeof(*buf
), length
, (FILE*)summf
);
1536 if (major
.getDataErrors() != 0) {
1537 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1538 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1539 "\tthe '-w' option to turn these errors into warnings.\n");
1542 /* Call afterwards to display errors. */
1546 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1547 unistr_printLengths();
1550 fprintf(stdout
, "--------------------------------------\n");
1552 if (execCount
<= 0) {
1553 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1556 endTime
= uprv_getRawUTCtime();
1557 diffTime
= (int32_t)(endTime
- startTime
);
1558 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1559 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1560 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1561 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1562 (int)(diffTime%U_MILLIS_PER_SECOND
));
1565 if(ctest_xml_fini())
1568 return major
.getErrors();
1571 const char* IntlTest::loadTestData(UErrorCode
& err
){
1572 if( _testDataPath
== NULL
){
1573 const char* directory
=NULL
;
1574 UResourceBundle
* test
=NULL
;
1576 const char* tdrelativepath
;
1578 #if defined (U_TOPBUILDDIR)
1579 tdrelativepath
= "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1580 directory
= U_TOPBUILDDIR
;
1582 tdrelativepath
= ".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1583 directory
= pathToDataDirectory();
1586 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1589 /* u_getDataDirectory shoul return \source\data ... set the
1590 * directory to ..\source\data\..\test\testdata\out\testdata
1592 strcpy(tdpath
, directory
);
1593 strcat(tdpath
, tdrelativepath
);
1594 strcat(tdpath
,"testdata");
1596 test
=ures_open(tdpath
, "testtypes", &err
);
1599 err
= U_FILE_ACCESS_ERROR
;
1600 it_dataerrln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1604 _testDataPath
= tdpath
;
1605 return _testDataPath
;
1607 return _testDataPath
;
1610 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1611 return loadTestData(err
);
1614 /* Returns the path to icu/source/test/testdata/ */
1615 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1616 const char *srcDataDir
= NULL
;
1618 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1620 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1621 FILE *f
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"rbbitst.txt", "r");
1623 /* We're in icu/source/test/intltest/ */
1627 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1628 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
1629 "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1635 char *IntlTest::getUnidataPath(char path
[]) {
1636 const int kUnicodeDataTxtLength
= 15; // strlen("UnicodeData.txt")
1638 // Look inside ICU_DATA first.
1639 strcpy(path
, pathToDataDirectory());
1640 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1641 FILE *f
= fopen(path
, "r");
1644 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1648 // As a fallback, try to guess where the source data was located
1649 // at the time ICU was built, and look there.
1651 strcpy(path
, U_TOPSRCDIR U_FILE_SEP_STRING
"data");
1653 UErrorCode errorCode
= U_ZERO_ERROR
;
1654 const char *testDataPath
= loadTestData(errorCode
);
1655 if(U_FAILURE(errorCode
)) {
1656 it_errln(UnicodeString(
1657 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1658 u_errorName(errorCode
));
1661 strcpy(path
, testDataPath
);
1662 strcat(path
, U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1663 U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1664 U_FILE_SEP_STRING
"data");
1666 strcat(path
, U_FILE_SEP_STRING
);
1667 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1668 f
= fopen(path
, "r");
1671 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1677 const char* IntlTest::fgDataDir
= NULL
;
1679 /* returns the path to icu/source/data */
1680 const char * IntlTest::pathToDataDirectory()
1683 if(fgDataDir
!= NULL
) {
1687 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1688 // to point to the top of the build hierarchy, which may or
1689 // may not be the same as the source directory, depending on
1690 // the configure options used. At any rate,
1691 // set the data path to the built data from this directory.
1692 // The value is complete with quotes, so it can be used
1693 // as-is as a string constant.
1695 #if defined (U_TOPSRCDIR)
1697 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1701 /* On Windows, the file name obtained from __FILE__ includes a full path.
1702 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1703 * Change to "wherever\icu\source\data"
1706 static char p
[sizeof(__FILE__
) + 10];
1710 strcpy(p
, __FILE__
);
1711 /* We want to back over three '\' chars. */
1712 /* Only Windows should end up here, so looking for '\' is safe. */
1713 for (i
=1; i
<=3; i
++) {
1714 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1715 if (pBackSlash
!= NULL
) {
1716 *pBackSlash
= 0; /* Truncate the string at the '\' */
1720 if (pBackSlash
!= NULL
) {
1721 /* We found and truncated three names from the path.
1722 * Now append "source\data" and set the environment
1724 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1728 /* __FILE__ on MSVC7 does not contain the directory */
1729 FILE *file
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1732 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1735 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1746 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1747 * It converts an invariant-character string into a UnicodeString, with
1748 * unescaping \u sequences.
1750 UnicodeString
CharsToUnicodeString(const char* chars
){
1751 return UnicodeString(chars
, -1, US_INV
).unescape();
1754 UnicodeString
ctou(const char* chars
) {
1755 return CharsToUnicodeString(chars
);
1758 #define RAND_M (714025)
1759 #define RAND_IA (1366)
1760 #define RAND_IC (150889)
1762 static int32_t RAND_SEED
;
1765 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1766 * with care: Does not return all possible values; returns one of
1767 * 714,025 values, uniformly spaced. However, the period is
1768 * effectively infinite. See: Numerical Recipes, section 7.1.
1770 * @param seedp pointer to seed. Set *seedp to any negative value
1771 * to restart the sequence.
1773 float IntlTest::random(int32_t* seedp
) {
1774 static int32_t iy
, ir
[98];
1775 static UBool first
=TRUE
;
1777 if (*seedp
< 0 || first
) {
1779 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1780 for (j
=1;j
<=97;++j
) {
1781 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1784 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1787 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1788 U_ASSERT(j
>=1 && j
<=97);
1790 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1792 return (float) iy
/RAND_M
;
1796 * Convenience method using a global seed.
1798 float IntlTest::random() {
1799 return random(&RAND_SEED
);
1804 * Integer random number class implementation.
1805 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1807 IntlTest::icu_rand::icu_rand(uint32_t seed
) {
1808 seed
= seed
% 2147483647UL;
1815 IntlTest::icu_rand::~icu_rand() {}
1817 void IntlTest::icu_rand::seed(uint32_t seed
) {
1824 uint32_t IntlTest::icu_rand::operator() () {
1825 fLast
= ((uint64_t)fLast
* 48271UL) % 2147483647UL;
1829 uint32_t IntlTest::icu_rand::getSeed() {
1830 return (uint32_t) fLast
;
1835 static inline UChar
toHex(int32_t i
) {
1836 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1839 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1840 for (int32_t i
=0; i
<s
.length(); ++i
) {
1842 if (c
<= (UChar
)0x7F) {
1845 result
+= (UChar
)0x5c;
1846 result
+= (UChar
)0x75;
1847 result
+= toHex((c
>> 12) & 0xF);
1848 result
+= toHex((c
>> 8) & 0xF);
1849 result
+= toHex((c
>> 4) & 0xF);
1850 result
+= toHex( c
& 0xF);
1856 #define VERBOSE_ASSERTIONS
1858 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
, UBool possibleDataError
, const char *file
, int line
) {
1861 if (possibleDataError
) {
1862 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1864 errln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1866 } else if (!quiet
) {
1867 logln("%s:%d: Ok: %s", file
, line
, message
);
1871 if (possibleDataError
) {
1872 dataerrln("FAIL: assertTrue() failed: %s", message
);
1874 errln("FAIL: assertTrue() failed: %s", message
);
1876 } else if (!quiet
) {
1877 logln("Ok: %s", message
);
1884 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1886 errln("FAIL: assertFalse() failed: %s", message
);
1887 } else if (!quiet
) {
1888 logln("Ok: %s", message
);
1893 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
, UBool possibleDataError
, const char *file
, int line
) {
1895 file
= ""; // prevent failure if no file given
1897 if (U_FAILURE(ec
)) {
1898 if (possibleDataError
) {
1899 dataerrln("FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1901 errcheckln(ec
, "FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1905 logln("OK: %s:%d: %s - (%s)", file
, line
, message
, u_errorName(ec
));
1910 UBool
IntlTest::assertEquals(const char* message
,
1911 const UnicodeString
& expected
,
1912 const UnicodeString
& actual
,
1913 UBool possibleDataError
) {
1914 if (expected
!= actual
) {
1915 if (possibleDataError
) {
1916 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
1918 "; expected " + prettify(expected
));
1920 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1922 "; expected " + prettify(expected
));
1926 #ifdef VERBOSE_ASSERTIONS
1928 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1934 UBool
IntlTest::assertEquals(const char* message
,
1935 const char* expected
,
1936 const char* actual
) {
1937 if (uprv_strcmp(expected
, actual
) != 0) {
1938 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1940 "\"; expected \"" + expected
+ "\"");
1943 #ifdef VERBOSE_ASSERTIONS
1945 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1951 UBool
IntlTest::assertEquals(const char* message
,
1954 if (expected
!= actual
) {
1955 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1956 actual
+ "=0x" + toHex(actual
) +
1957 "; expected " + expected
+ "=0x" + toHex(expected
));
1960 #ifdef VERBOSE_ASSERTIONS
1962 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
+ "=0x" + toHex(actual
));
1968 UBool
IntlTest::assertEquals(const char* message
,
1971 if (expected
!= actual
) {
1972 errln((UnicodeString
)"FAIL: " + message
+ "; got int64 " +
1973 Int64ToUnicodeString(actual
) +
1974 "; expected " + Int64ToUnicodeString(expected
) );
1977 #ifdef VERBOSE_ASSERTIONS
1979 logln((UnicodeString
)"Ok: " + message
+ "; got int64 " + Int64ToUnicodeString(actual
));
1985 UBool
IntlTest::assertEquals(const char* message
,
1988 if (expected
!= actual
) {
1989 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1991 "; expected " + expected
);
1994 #ifdef VERBOSE_ASSERTIONS
1996 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
);
2003 UBool
IntlTest::assertEquals(const char* message
,
2006 if (expected
!= actual
) {
2007 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2009 "; expected " + toString(expected
));
2012 #ifdef VERBOSE_ASSERTIONS
2014 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2020 #if !UCONFIG_NO_FORMATTING
2021 UBool
IntlTest::assertEquals(const char* message
,
2022 const Formattable
& expected
,
2023 const Formattable
& actual
,
2024 UBool possibleDataError
) {
2025 if (expected
!= actual
) {
2026 if (possibleDataError
) {
2027 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
2029 "; expected " + toString(expected
));
2031 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2033 "; expected " + toString(expected
));
2037 #ifdef VERBOSE_ASSERTIONS
2039 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2046 static char ASSERT_BUF
[256];
2048 static const char* extractToAssertBuf(const UnicodeString
& message
) {
2050 escape(message
, buf
);
2051 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
2052 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
2056 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
2057 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
2060 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
2061 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
2064 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
2065 return assertSuccess(extractToAssertBuf(message
), ec
);
2068 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2069 const UnicodeString
& expected
,
2070 const UnicodeString
& actual
,
2071 UBool possibleDataError
) {
2072 return assertEquals(extractToAssertBuf(message
), expected
, actual
, possibleDataError
);
2075 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2076 const char* expected
,
2077 const char* actual
) {
2078 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2080 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2083 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2085 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2088 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2090 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2093 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2096 #if !UCONFIG_NO_FORMATTING
2097 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2098 const Formattable
& expected
,
2099 const Formattable
& actual
) {
2100 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2104 void IntlTest::setProperty(const char* propline
) {
2105 if (numProps
< kMaxProps
) {
2106 proplines
[numProps
] = propline
;
2111 const char* IntlTest::getProperty(const char* prop
) {
2112 const char* val
= NULL
;
2113 for (int32_t i
= 0; i
< numProps
; i
++) {
2114 int32_t plen
= uprv_strlen(prop
);
2115 if ((int32_t)uprv_strlen(proplines
[i
]) > plen
+ 1
2116 && proplines
[i
][plen
] == '='
2117 && uprv_strncmp(proplines
[i
], prop
, plen
) == 0) {
2118 val
= &(proplines
[i
][plen
+1]);
2126 * Hey, Emacs, please set the following:
2129 * indent-tabs-mode: nil