1 /********************************************************************
3 * Copyright (c) 1997-2016, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
8 #include "unicode/utypes.h"
11 * IntlTest is a base class for tests.
20 #include "unicode/ctest.h" // for str_timeDelta
21 #include "unicode/curramt.h"
22 #include "unicode/locid.h"
23 #include "unicode/putil.h"
24 #include "unicode/smpdtfmt.h"
25 #include "unicode/timezone.h"
26 #include "unicode/uclean.h"
27 #include "unicode/ucnv.h"
28 #include "unicode/unistr.h"
29 #include "unicode/ures.h"
38 #include "putilimp.h" // for uprv_getRawUTCtime()
50 static char* _testDataPath
=NULL
;
52 // Static list of errors found
53 static UnicodeString errorList
;
54 static void *knownList
= NULL
; // known issues
55 static UBool noKnownIssues
= FALSE
; // if TRUE, don't emit known issues
57 //-----------------------------------------------------------------------------
58 //convenience classes to ease porting code that uses the Java
59 //string-concatenation operator (moved from findword test by rtg)
61 // [LIU] Just to get things working
63 UCharToUnicodeString(UChar c
)
64 { return UnicodeString(c
); }
66 // [rtg] Just to get things working
68 operator+(const UnicodeString
& left
,
71 char buffer
[64]; // nos changed from 10 to 64
72 char danger
= 'p'; // guard against overrunning the buffer (rtg)
74 sprintf(buffer
, "%ld", num
);
75 assert(danger
== 'p');
81 operator+(const UnicodeString
& left
,
84 char buffer
[64]; // nos changed from 10 to 64
85 char danger
= 'p'; // guard against overrunning the buffer (rtg)
87 sprintf(buffer
, "%lu", num
);
88 assert(danger
== 'p');
94 Int64ToUnicodeString(int64_t num
)
96 char buffer
[64]; // nos changed from 10 to 64
97 char danger
= 'p'; // guard against overrunning the buffer (rtg)
100 sprintf(buffer
, "%I64d", num
);
102 sprintf(buffer
, "%lld", (long long)num
);
104 assert(danger
== 'p');
109 // [LIU] Just to get things working
111 operator+(const UnicodeString
& left
,
114 char buffer
[64]; // was 32, made it arbitrarily bigger (rtg)
115 char danger
= 'p'; // guard against overrunning the buffer (rtg)
117 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
118 // 53*log(2)/log(10) = 15.95
119 // so there is no need to show more than 16 digits. [alan]
121 sprintf(buffer
, "%.17g", num
);
122 assert(danger
== 'p');
124 return left
+ buffer
;
129 operator+(const UnicodeString
& left
,
131 return left
+ Int64ToUnicodeString(num
);
135 #if !UCONFIG_NO_FORMATTING
138 * Return a string display for this, without surrounding braces.
140 UnicodeString
_toString(const Formattable
& f
) {
142 switch (f
.getType()) {
143 case Formattable::kDate
:
145 UErrorCode status
= U_ZERO_ERROR
;
146 SimpleDateFormat
fmt(status
);
147 if (U_SUCCESS(status
)) {
149 fmt
.format(f
.getDate(), s
, pos
);
150 s
.insert(0, "Date:");
152 s
= UnicodeString("Error creating date format]");
156 case Formattable::kDouble
:
157 s
= UnicodeString("double:") + f
.getDouble();
159 case Formattable::kLong
:
160 s
= UnicodeString("long:") + f
.getLong();
163 case Formattable::kInt64
:
164 s
= UnicodeString("int64:") + Int64ToUnicodeString(f
.getInt64());
167 case Formattable::kString
:
169 s
.insert(0, "String:");
171 case Formattable::kArray
:
174 const Formattable
* array
= f
.getArray(n
);
175 s
.insert(0, UnicodeString("Array:"));
176 UnicodeString
delim(", ");
177 for (i
=0; i
<n
; ++i
) {
181 s
= s
+ _toString(array
[i
]);
185 case Formattable::kObject
: {
186 const CurrencyAmount
* c
= dynamic_cast<const CurrencyAmount
*>(f
.getObject());
188 s
= _toString(c
->getNumber()) + " " + UnicodeString(c
->getISOCurrency());
190 s
= UnicodeString("Unknown UObject");
195 s
= UnicodeString("Unknown Formattable type=") + (int32_t)f
.getType();
202 * Originally coded this as operator+, but that makes the expression
203 * + char* ambiguous. - liu
205 UnicodeString
toString(const Formattable
& f
) {
206 UnicodeString
s((UChar
)91/*[*/);
207 s
.append(_toString(f
));
208 s
.append((UChar
)0x5d/*]*/);
214 // useful when operator+ won't cooperate
215 UnicodeString
toString(int32_t n
) {
216 return UnicodeString() + (long)n
;
221 UnicodeString
toString(UBool b
) {
222 return b
? UnicodeString("TRUE"):UnicodeString("FALSE");
225 // stephen - cleaned up 05/05/99
226 UnicodeString
operator+(const UnicodeString
& left
, char num
)
227 { return left
+ (long)num
; }
228 UnicodeString
operator+(const UnicodeString
& left
, short num
)
229 { return left
+ (long)num
; }
230 UnicodeString
operator+(const UnicodeString
& left
, int num
)
231 { return left
+ (long)num
; }
232 UnicodeString
operator+(const UnicodeString
& left
, unsigned char num
)
233 { return left
+ (unsigned long)num
; }
234 UnicodeString
operator+(const UnicodeString
& left
, unsigned short num
)
235 { return left
+ (unsigned long)num
; }
236 UnicodeString
operator+(const UnicodeString
& left
, unsigned int num
)
237 { return left
+ (unsigned long)num
; }
238 UnicodeString
operator+(const UnicodeString
& left
, float num
)
239 { return left
+ (double)num
; }
243 // Append a hex string to the target
245 IntlTest::appendHex(uint32_t number
,
247 UnicodeString
& target
)
249 static const UChar digitString
[] = {
250 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
251 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
252 }; /* "0123456789ABCDEF" */
254 if (digits
< 0) { // auto-digits
257 while (number
> max
) {
259 max
= (max
<< 8) | 0xff;
265 target
+= digitString
[(number
>> 28) & 0xF];
268 target
+= digitString
[(number
>> 24) & 0xF];
271 target
+= digitString
[(number
>> 20) & 0xF];
274 target
+= digitString
[(number
>> 16) & 0xF];
277 target
+= digitString
[(number
>> 12) & 0xF];
280 target
+= digitString
[(number
>> 8) & 0xF];
283 target
+= digitString
[(number
>> 4) & 0xF];
286 target
+= digitString
[(number
>> 0) & 0xF];
295 IntlTest::toHex(uint32_t number
, int32_t digits
) {
296 UnicodeString result
;
297 appendHex(number
, digits
, result
);
301 static inline UBool
isPrintable(UChar32 c
) {
302 return c
<= 0x7E && (c
>= 0x20 || c
== 9 || c
== 0xA || c
== 0xD);
305 // Replace nonprintable characters with unicode escapes
307 IntlTest::prettify(const UnicodeString
&source
,
308 UnicodeString
&target
)
315 for (i
= 0; i
< source
.length(); )
317 UChar32 ch
= source
.char32At(i
);
320 if (!isPrintable(ch
))
324 appendHex(ch
, 4, target
);
327 appendHex(ch
, 8, target
);
341 // Replace nonprintable characters with unicode escapes
343 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
346 UnicodeString target
;
350 for (i
= 0; i
< source
.length();)
352 UChar32 ch
= source
.char32At(i
);
355 if (!isPrintable(ch
))
357 if (parseBackslash
) {
358 // If we are preceded by an odd number of backslashes,
359 // then this character has already been backslash escaped.
360 // Delete a backslash.
361 int32_t backslashCount
= 0;
362 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
363 if (target
.charAt(j
) == (UChar
)92) {
369 if ((backslashCount
% 2) == 1) {
370 target
.truncate(target
.length() - 1);
375 appendHex(ch
, 4, target
);
378 appendHex(ch
, 8, target
);
392 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
393 * set, try to deduce the directory in which ICU was built,
394 * and set ICU_DATA to "icu/source/data" in that location.
395 * The intent is to allow the tests to have a good chance
396 * of running without requiring that the user manually set
397 * ICU_DATA. Common data isn't a problem, since it is
398 * picked up via a static (build time) reference, but the
399 * tests dynamically load some data.
401 void IntlTest::setICU_DATA() {
402 const char *original_ICU_DATA
= getenv("ICU_DATA");
404 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
405 /* If the user set ICU_DATA, don't second-guess the person. */
409 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
410 // to point to the top of the build hierarchy, which may or
411 // may not be the same as the source directory, depending on
412 // the configure options used. At any rate,
413 // set the data path to the built data from this directory.
414 // The value is complete with quotes, so it can be used
415 // as-is as a string constant.
417 #if defined (U_TOPBUILDDIR)
419 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
420 u_setDataDirectory(env_string
);
425 // Use #else so we don't get compiler warnings due to the return above.
427 /* On Windows, the file name obtained from __FILE__ includes a full path.
428 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
429 * Change to "wherever\icu\source\data"
432 char p
[sizeof(__FILE__
) + 10];
437 /* We want to back over three '\' chars. */
438 /* Only Windows should end up here, so looking for '\' is safe. */
439 for (i
=1; i
<=3; i
++) {
440 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
441 if (pBackSlash
!= NULL
) {
442 *pBackSlash
= 0; /* Truncate the string at the '\' */
446 if (pBackSlash
!= NULL
) {
447 /* We found and truncated three names from the path.
448 * Now append "source\data" and set the environment
450 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
451 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
455 /* __FILE__ on MSVC7 does not contain the directory */
456 u_setDataDirectory(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
462 /* No location for the data dir was identifiable.
463 * Add other fallbacks for the test data location here if the need arises
468 //--------------------------------------------------------------------------------------
470 static const int32_t indentLevel_offset
= 3;
471 static const char delim
= '/';
473 IntlTest
* IntlTest::gTest
= NULL
;
475 static int32_t execCount
= 0;
477 void it_log( UnicodeString message
)
480 IntlTest::gTest
->log( message
);
483 void it_logln( UnicodeString message
)
486 IntlTest::gTest
->logln( message
);
489 void it_logln( void )
492 IntlTest::gTest
->logln();
495 void it_info( UnicodeString message
)
498 IntlTest::gTest
->info( message
);
501 void it_infoln( UnicodeString message
)
504 IntlTest::gTest
->infoln( message
);
507 void it_infoln( void )
510 IntlTest::gTest
->infoln();
516 IntlTest::gTest
->err();
519 void it_err( UnicodeString message
)
522 IntlTest::gTest
->err( message
);
525 void it_errln( UnicodeString message
)
528 IntlTest::gTest
->errln( message
);
531 void it_dataerr( UnicodeString message
)
534 IntlTest::gTest
->dataerr( message
);
537 void it_dataerrln( UnicodeString message
)
540 IntlTest::gTest
->dataerrln( message
);
553 warn_on_missing_data
= FALSE
;
558 LL_indentlevel
= indentLevel_offset
;
560 strcpy(basePath
, "/");
564 void IntlTest::setCaller( IntlTest
* callingTest
)
566 caller
= callingTest
;
568 warn_on_missing_data
= caller
->warn_on_missing_data
;
569 verbose
= caller
->verbose
;
570 no_err_msg
= caller
->no_err_msg
;
571 quick
= caller
->quick
;
572 threadCount
= caller
->threadCount
;
573 testoutfp
= caller
->testoutfp
;
574 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
575 numProps
= caller
->numProps
;
576 for (int32_t i
= 0; i
< numProps
; i
++) {
577 proplines
[i
] = caller
->proplines
[i
];
582 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
584 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
585 testToBeCalled
.setCaller( this );
586 strcpy(testToBeCalled
.basePath
, this->basePath
);
587 UBool result
= testToBeCalled
.runTest( testPath
, par
, testToBeCalled
.basePath
);
588 strcpy(testToBeCalled
.basePath
, this->basePath
); // reset it.
592 void IntlTest::setPath( char* pathVal
)
594 this->testPath
= pathVal
;
597 UBool
IntlTest::setVerbose( UBool verboseVal
)
599 UBool rval
= this->verbose
;
600 this->verbose
= verboseVal
;
604 UBool
IntlTest::setNotime( UBool no_time
)
606 UBool rval
= this->no_time
;
607 this->no_time
= no_time
;
611 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
613 UBool rval
= this->warn_on_missing_data
;
614 this->warn_on_missing_data
= warn_on_missing_dataVal
;
618 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
620 UBool rval
= this->no_err_msg
;
621 this->no_err_msg
= no_err_msgVal
;
625 UBool
IntlTest::setQuick( UBool quickVal
)
627 UBool rval
= this->quick
;
628 this->quick
= quickVal
;
632 UBool
IntlTest::setLeaks( UBool leaksVal
)
634 UBool rval
= this->leaks
;
635 this->leaks
= leaksVal
;
639 int32_t IntlTest::setThreadCount( int32_t count
)
641 int32_t rval
= this->threadCount
;
642 this->threadCount
= count
;
646 int32_t IntlTest::getErrors( void )
651 int32_t IntlTest::getDataErrors( void )
653 return dataErrorCount
;
656 UBool
IntlTest::runTest( char* name
, char* par
, char *baseName
)
661 char* baseNameBuffer
= NULL
;
663 if(baseName
== NULL
) {
664 baseNameBuffer
= (char*)malloc(1024);
665 baseName
=baseNameBuffer
;
666 strcpy(baseName
, "/");
670 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
672 testPath
= pos
+1; // store subpath for calling subtest
673 *pos
= 0; // split into two strings
678 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
679 rval
= runTestLoop( NULL
, par
, baseName
);
681 }else if (strcmp( name
, "LIST" ) == 0) {
686 rval
= runTestLoop( name
, par
, baseName
);
690 *pos
= delim
; // restore original value at pos
691 if(baseNameBuffer
!=NULL
) {
692 free(baseNameBuffer
);
697 // call individual tests, to be overriden to call implementations
698 void IntlTest::runIndexedTest( int32_t /*index*/, UBool
/*exec*/, const char* & /*name*/, char* /*par*/ )
700 // to be overriden by a method like:
703 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
704 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
705 default: name = ""; break;
708 this->errln("*** runIndexedTest needs to be overriden! ***");
712 UBool
IntlTest::runTestLoop( char* testname
, char* par
, char *baseName
)
717 int32_t lastErrorCount
;
719 UBool lastTestFailed
;
721 if(baseName
== NULL
) {
722 printf("ERROR: baseName can't be null.\n");
725 if ((char *)this->basePath
!= baseName
) {
726 strcpy(this->basePath
, baseName
);
730 char * saveBaseLoc
= baseName
+strlen(baseName
);
732 IntlTest
* saveTest
= gTest
;
735 this->runIndexedTest( index
, FALSE
, name
, par
);
736 if (strcmp(name
,"skip") == 0) {
737 run_this_test
= FALSE
;
739 if (!name
|| (name
[0] == 0))
742 run_this_test
= TRUE
;
744 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
748 lastErrorCount
= errorCount
;
751 sprintf(msg
, "%s {", name
);
752 LL_message(msg
, TRUE
);
753 UDate timeStart
= uprv_getRawUTCtime();
754 strcpy(saveBaseLoc
,name
);
755 strcat(saveBaseLoc
,"/");
757 strcpy(currName
, name
); // set
758 this->runIndexedTest( index
, TRUE
, name
, par
);
759 currName
[0]=0; // reset
761 UDate timeStop
= uprv_getRawUTCtime();
762 rval
= TRUE
; // at least one test has been called
765 sprintf(secs
, "%f", (timeStop
-timeStart
)/1000.0);
771 strcpy(saveBaseLoc
,name
);
774 ctest_xml_testcase(baseName
, name
, secs
, (lastErrorCount
!=errorCount
)?"err":NULL
);
777 saveBaseLoc
[0]=0; /* reset path */
779 if (lastErrorCount
== errorCount
) {
780 sprintf( msg
, " } OK: %s ", name
);
781 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
782 lastTestFailed
= FALSE
;
784 sprintf(msg
, " } ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
785 if(!no_time
) str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
787 for(int i
=0;i
<LL_indentlevel
;i
++) {
792 lastTestFailed
= TRUE
;
795 if (lastTestFailed
) {
796 LL_message( "", TRUE
);
798 LL_message( msg
, TRUE
);
799 if (lastTestFailed
) {
800 LL_message( "", TRUE
);
815 * Adds given string to the log if we are in verbose mode.
817 void IntlTest::log( const UnicodeString
&message
)
820 LL_message( message
, FALSE
);
825 * Adds given string to the log if we are in verbose mode. Adds a new line to
828 void IntlTest::logln( const UnicodeString
&message
)
831 LL_message( message
, TRUE
);
835 void IntlTest::logln( void )
838 LL_message( "", TRUE
);
843 * Unconditionally adds given string to the log.
845 void IntlTest::info( const UnicodeString
&message
)
847 LL_message( message
, FALSE
);
851 * Unconditionally adds given string to the log. Adds a new line to
854 void IntlTest::infoln( const UnicodeString
&message
)
856 LL_message( message
, TRUE
);
859 void IntlTest::infoln( void )
861 LL_message( "", TRUE
);
864 int32_t IntlTest::IncErrorCount( void )
867 if (caller
) caller
->IncErrorCount();
871 int32_t IntlTest::IncDataErrorCount( void )
874 if (caller
) caller
->IncDataErrorCount();
875 return dataErrorCount
;
883 void IntlTest::err( const UnicodeString
&message
)
886 if (!no_err_msg
) LL_message( message
, FALSE
);
889 void IntlTest::errln( const UnicodeString
&message
)
892 if (!no_err_msg
) LL_message( message
, TRUE
);
895 void IntlTest::dataerr( const UnicodeString
&message
)
899 if (!warn_on_missing_data
) {
903 if (!no_err_msg
) LL_message( message
, FALSE
);
906 void IntlTest::dataerrln( const UnicodeString
&message
)
908 int32_t errCount
= IncDataErrorCount();
910 if (!warn_on_missing_data
) {
914 msg
= UnicodeString("[DATA] " + message
);
918 if ( errCount
== 1) {
919 LL_message( msg
+ " - (Are you missing data?)", TRUE
); // only show this message the first time
921 LL_message( msg
, TRUE
);
926 void IntlTest::errcheckln(UErrorCode status
, const UnicodeString
&message
) {
927 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
934 /* convenience functions that include sprintf formatting */
935 void IntlTest::log(const char *fmt
, ...)
941 /* sprintf it just to make sure that the information is valid */
942 vsprintf(buffer
, fmt
, ap
);
945 log(UnicodeString(buffer
, (const char *)NULL
));
949 void IntlTest::logln(const char *fmt
, ...)
955 /* sprintf it just to make sure that the information is valid */
956 vsprintf(buffer
, fmt
, ap
);
959 logln(UnicodeString(buffer
, (const char *)NULL
));
963 UBool
IntlTest::logKnownIssue(const char *ticket
, const char *fmt
, ...)
969 /* sprintf it just to make sure that the information is valid */
970 vsprintf(buffer
, fmt
, ap
);
972 return logKnownIssue(ticket
, UnicodeString(buffer
, (const char *)NULL
));
975 UBool
IntlTest::logKnownIssue(const char *ticket
) {
976 return logKnownIssue(ticket
, UnicodeString());
979 UBool
IntlTest::logKnownIssue(const char *ticket
, const UnicodeString
&msg
) {
980 if(noKnownIssues
) return FALSE
;
983 strcpy(fullpath
, basePath
);
984 strcat(fullpath
, currName
);
985 UnicodeString msg2
= msg
;
986 UBool firstForTicket
= TRUE
, firstForWhere
= TRUE
;
987 knownList
= udbg_knownIssue_openU(knownList
, ticket
, fullpath
, msg2
.getTerminatedBuffer(), &firstForTicket
, &firstForWhere
);
989 msg2
= UNICODE_STRING_SIMPLE("(Known issue #") +
990 UnicodeString(ticket
, -1, US_INV
) + UNICODE_STRING_SIMPLE(") ") + msg
;
991 if(firstForTicket
|| firstForWhere
) {
1000 /* convenience functions that include sprintf formatting */
1001 void IntlTest::info(const char *fmt
, ...)
1007 /* sprintf it just to make sure that the information is valid */
1008 vsprintf(buffer
, fmt
, ap
);
1010 info(UnicodeString(buffer
, (const char *)NULL
));
1013 void IntlTest::infoln(const char *fmt
, ...)
1019 /* sprintf it just to make sure that the information is valid */
1020 vsprintf(buffer
, fmt
, ap
);
1022 infoln(UnicodeString(buffer
, (const char *)NULL
));
1025 void IntlTest::err(const char *fmt
, ...)
1031 vsprintf(buffer
, fmt
, ap
);
1033 err(UnicodeString(buffer
, (const char *)NULL
));
1036 void IntlTest::errln(const char *fmt
, ...)
1042 vsprintf(buffer
, fmt
, ap
);
1044 errln(UnicodeString(buffer
, (const char *)NULL
));
1047 void IntlTest::dataerrln(const char *fmt
, ...)
1053 vsprintf(buffer
, fmt
, ap
);
1055 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1058 void IntlTest::errcheckln(UErrorCode status
, const char *fmt
, ...)
1064 vsprintf(buffer
, fmt
, ap
);
1067 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
1068 dataerrln(UnicodeString(buffer
, (const char *)NULL
));
1070 errln(UnicodeString(buffer
, (const char *)NULL
));
1074 void IntlTest::printErrors()
1076 IntlTest::LL_message(errorList
, TRUE
);
1079 UBool
IntlTest::printKnownIssues()
1081 if(knownList
!= NULL
) {
1082 udbg_knownIssue_print(knownList
);
1083 udbg_knownIssue_close(knownList
);
1090 static UMutex messageMutex
= U_MUTEX_INITIALIZER
;
1092 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
1094 // Synchronize this function.
1095 // All error messages generated by tests funnel through here.
1096 // Multithreaded tests can concurrently generate errors, requiring syncronization
1097 // to keep each message together.
1098 Mutex
lock(&messageMutex
);
1100 // string that starts with a LineFeed character and continues
1101 // with spaces according to the current indentation
1102 static const UChar indentUChars
[] = {
1104 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1105 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
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
1115 U_ASSERT(1 + LL_indentlevel
<= UPRV_LENGTHOF(indentUChars
));
1116 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
1121 // stream out the indentation string first if necessary
1122 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
1124 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1127 // replace each LineFeed by the indentation string
1128 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
1130 // stream out the message
1131 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
1133 length
= length
> 30000 ? 30000 : length
;
1134 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1138 char newLine
= '\n';
1139 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
1142 // A newline usually flushes the buffer, but
1143 // flush the message just in case of a core dump.
1144 fflush((FILE *)testoutfp
);
1148 * Print a usage message for this test class.
1150 void IntlTest::usage( void )
1152 UBool save_verbose
= setVerbose( TRUE
);
1153 logln("Test names:");
1154 logln("-----------");
1157 const char* name
= NULL
;
1159 this->runIndexedTest( index
, FALSE
, name
);
1163 }while (name
&& (name
[0] != 0));
1164 setVerbose( save_verbose
);
1168 // memory leak reporting software will be able to take advantage of the testsuite
1169 // being run a second time local to a specific method in order to report only actual leaks
1171 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
1173 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
1174 strLeak
->append(" for verifying purify filter");
1175 return this->runTest( name
, par
);
1179 #if UCONFIG_NO_LEGACY_CONVERSION
1180 # define TRY_CNV_1 "iso-8859-1"
1181 # define TRY_CNV_2 "ibm-1208"
1183 # define TRY_CNV_1 "iso-8859-7"
1184 # define TRY_CNV_2 "sjis"
1187 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1188 U_CAPI
void unistr_printLengths();
1192 main(int argc
, char* argv
[])
1194 UBool syntax
= FALSE
;
1196 UBool verbose
= FALSE
;
1197 UBool no_err_msg
= FALSE
;
1198 UBool no_time
= FALSE
;
1201 UBool leaks
= FALSE
;
1203 const char *summary_file
= NULL
;
1204 UBool warnOnMissingData
= FALSE
;
1205 UBool defaultDataFound
= FALSE
;
1206 int32_t threadCount
= 12;
1207 UErrorCode errorCode
= U_ZERO_ERROR
;
1208 UConverter
*cnv
= NULL
;
1209 const char *warnOrErr
= "Failure";
1210 UDate startTime
, endTime
;
1212 const char *props
[IntlTest::kMaxProps
];
1215 U_MAIN_INIT_ARGS(argc
, argv
);
1217 startTime
= uprv_getRawUTCtime();
1219 for (int i
= 1; i
< argc
; ++i
) {
1220 if (argv
[i
][0] == '-') {
1221 const char* str
= argv
[i
] + 1;
1222 if (strcmp("verbose", str
) == 0 ||
1223 strcmp("v", str
) == 0)
1225 else if (strcmp("noerrormsg", str
) == 0 ||
1226 strcmp("n", str
) == 0)
1228 else if (strcmp("exhaustive", str
) == 0 ||
1229 strcmp("e", str
) == 0)
1231 else if (strcmp("all", str
) == 0 ||
1232 strcmp("a", str
) == 0)
1234 else if (strcmp("utf-8", str
) == 0 ||
1235 strcmp("u", str
) == 0)
1237 else if (strcmp("noknownissues", str
) == 0 ||
1238 strcmp("K", str
) == 0)
1239 noKnownIssues
= TRUE
;
1240 else if (strcmp("leaks", str
) == 0 ||
1241 strcmp("l", str
) == 0)
1243 else if (strcmp("notime", str
) == 0 ||
1244 strcmp("T", str
) == 0)
1246 else if (strncmp("E", str
, 1) == 0)
1247 summary_file
= str
+1;
1248 else if (strcmp("x", str
)==0) {
1250 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1253 if(ctest_xml_setFileName(argv
[i
])) { /* set the name */
1254 return 1; /* error */
1256 } else if (strcmp("w", str
) == 0) {
1257 warnOnMissingData
= TRUE
;
1258 warnOrErr
= "WARNING";
1260 else if (strncmp("threads:", str
, 8) == 0) {
1261 threadCount
= atoi(str
+ 8);
1263 else if (strncmp("prop:", str
, 5) == 0) {
1264 if (nProps
< IntlTest::kMaxProps
) {
1265 props
[nProps
] = str
+ 5;
1277 if (!all
&& !name
) {
1279 } else if (all
&& name
) {
1286 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1288 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1289 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1290 "### notime (T), \n"
1291 "### threads:<threadCount>\n"
1292 "### (The default thread count is 12.),\n"
1293 "### (Specify either -all (shortcut -a) or a test name). \n"
1294 "### -all will run all of the tests.\n"
1296 "### To get a list of the test names type: intltest LIST \n"
1297 "### To run just the utility tests type: intltest utility \n"
1299 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1300 "### For example to list the utility tests type: intltest utility/LIST \n"
1301 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1303 "### A parameter can be specified for a test by appending '@' and the value \n"
1304 "### to the testname. \n\n");
1308 if (nProps
> IntlTest::kMaxProps
) {
1309 fprintf(stdout
, "### Too many properties. Exiting.\n");
1312 MajorTestLevel major
;
1313 major
.setVerbose( verbose
);
1314 major
.setNoErrMsg( no_err_msg
);
1315 major
.setQuick( quick
);
1316 major
.setLeaks( leaks
);
1317 major
.setThreadCount( threadCount
);
1318 major
.setWarnOnMissingData( warnOnMissingData
);
1319 major
.setNotime (no_time
);
1320 for (int32_t i
= 0; i
< nProps
; i
++) {
1321 major
.setProperty(props
[i
]);
1325 fprintf(stdout
, "-----------------------------------------------\n");
1326 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1327 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1331 const char *charsetFamily
= "Unknown";
1332 int32_t voidSize
= (int32_t)sizeof(void*);
1333 int32_t bits
= voidSize
* 8;
1334 if(U_CHARSET_FAMILY
==U_ASCII_FAMILY
) {
1335 charsetFamily
="ASCII";
1336 } else if(U_CHARSET_FAMILY
==U_EBCDIC_FAMILY
) {
1337 charsetFamily
="EBCDIC";
1340 " Bits: %d, Byte order: %s, Chars: %s\n",
1341 bits
, U_IS_BIG_ENDIAN
?"Big endian":"Little endian",
1344 fprintf(stdout
, "-----------------------------------------------\n");
1345 fprintf(stdout
, " Options: \n");
1346 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1347 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1348 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1349 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1350 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1351 fprintf(stdout
, " utf-8 (u) : %s\n", (utf8
? "On" : "Off"));
1352 fprintf(stdout
, " notime (T) : %s\n", (no_time
? "On" : "Off"));
1353 fprintf(stdout
, " noknownissues (K) : %s\n", (noKnownIssues
? "On" : "Off"));
1354 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1355 fprintf(stdout
, " Threads : %d\n", threadCount
);
1356 for (int32_t i
= 0; i
< nProps
; i
++) {
1357 fprintf(stdout
, " Custom property (prop:) : %s\n", props
[i
]);
1359 fprintf(stdout
, "-----------------------------------------------\n");
1362 ucnv_setDefaultName("utf-8");
1364 /* Check whether ICU will initialize without forcing the build data directory into
1365 * the ICU_DATA path. Success here means either the data dll contains data, or that
1366 * this test program was run with ICU_DATA set externally. Failure of this check
1367 * is normal when ICU data is not packaged into a shared library.
1369 * Whether or not this test succeeds, we want to cleanup and reinitialize
1370 * with a data path so that data loading from individual files can be tested.
1373 if (U_FAILURE(errorCode
)) {
1375 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1376 defaultDataFound
= FALSE
;
1379 defaultDataFound
= TRUE
;
1383 ucnv_setDefaultName("utf-8");
1385 errorCode
= U_ZERO_ERROR
;
1387 /* Initialize ICU */
1388 if (!defaultDataFound
) {
1389 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1392 if (U_FAILURE(errorCode
)) {
1394 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1395 "*** Check the ICU_DATA environment variable and \n"
1396 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1397 if(warnOnMissingData
== 0) {
1398 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1404 // initial check for the default converter
1405 errorCode
= U_ZERO_ERROR
;
1406 cnv
= ucnv_open(0, &errorCode
);
1412 "*** %s! The default converter [%s] cannot be opened.\n"
1413 "*** Check the ICU_DATA environment variable and\n"
1414 "*** check that the data files are present.\n",
1415 warnOrErr
, ucnv_getDefaultName());
1416 if(!warnOnMissingData
) {
1417 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1423 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1429 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1430 "*** Check the ICU_DATA environment variable and \n"
1431 "*** check that the data files are present.\n", warnOrErr
);
1432 if(!warnOnMissingData
) {
1433 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1438 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1440 if(U_FAILURE(errorCode
)) {
1442 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1443 "*** Check the ICU_DATA environment variable and \n"
1444 "*** check that the data files are present.\n", warnOrErr
);
1445 if(!warnOnMissingData
) {
1446 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1451 Locale originalLocale
; // Save the default locale for comparison later on.
1453 if(ctest_xml_init("intltest"))
1457 /* TODO: Add option to call u_cleanup and rerun tests. */
1461 major
.run_phase2( NULL
, NULL
);
1464 for (int i
= 1; i
< argc
; ++i
) {
1465 if (argv
[i
][0] != '-') {
1466 char* name
= argv
[i
];
1467 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1469 char baseName
[1024];
1470 sprintf(baseName
, "/%s/", name
);
1472 char* parameter
= strchr( name
, '@' );
1478 UBool res
= major
.runTest( name
, parameter
, baseName
);
1480 major
.run_phase2( name
, parameter
);
1482 if (!res
|| (execCount
<= 0)) {
1483 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1485 } else if(!strcmp(argv
[i
],"-x")) {
1492 #if !UCONFIG_NO_FORMATTING
1493 CalendarTimeZoneTest::cleanup();
1496 free(_testDataPath
);
1499 Locale lastDefaultLocale
;
1500 if (originalLocale
!= lastDefaultLocale
) {
1501 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1504 fprintf(stdout
, "\n--------------------------------------\n");
1505 if( major
.printKnownIssues() ) {
1506 fprintf(stdout
, " To run suppressed tests, use the -K option. \n");
1508 if (major
.getErrors() == 0) {
1509 /* Call it twice to make sure that the defaults were reset. */
1510 /* Call it before the OK message to verify proper cleanup. */
1514 fprintf(stdout
, "OK: All tests passed without error.\n");
1516 if (major
.getDataErrors() != 0) {
1517 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1520 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1521 major
.printErrors();
1523 if(summary_file
!= NULL
) {
1524 FILE *summf
= fopen(summary_file
, "w");
1525 if( summf
!= NULL
) {
1527 int32_t length
= errorList
.extract(0, errorList
.length(), buf
, sizeof(buf
));
1528 fwrite(buf
, sizeof(*buf
), length
, (FILE*)summf
);
1534 if (major
.getDataErrors() != 0) {
1535 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1536 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1537 "\tthe '-w' option to turn these errors into warnings.\n");
1540 /* Call afterwards to display errors. */
1544 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1545 unistr_printLengths();
1548 fprintf(stdout
, "--------------------------------------\n");
1550 if (execCount
<= 0) {
1551 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1554 endTime
= uprv_getRawUTCtime();
1555 diffTime
= (int32_t)(endTime
- startTime
);
1556 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1557 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1558 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1559 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1560 (int)(diffTime%U_MILLIS_PER_SECOND
));
1563 if(ctest_xml_fini())
1566 return major
.getErrors();
1569 const char* IntlTest::loadTestData(UErrorCode
& err
){
1570 if( _testDataPath
== NULL
){
1571 const char* directory
=NULL
;
1572 UResourceBundle
* test
=NULL
;
1574 const char* tdrelativepath
;
1576 #if defined (U_TOPBUILDDIR)
1577 tdrelativepath
= "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1578 directory
= U_TOPBUILDDIR
;
1580 tdrelativepath
= ".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
1581 directory
= pathToDataDirectory();
1584 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1587 /* u_getDataDirectory shoul return \source\data ... set the
1588 * directory to ..\source\data\..\test\testdata\out\testdata
1590 strcpy(tdpath
, directory
);
1591 strcat(tdpath
, tdrelativepath
);
1592 strcat(tdpath
,"testdata");
1594 test
=ures_open(tdpath
, "testtypes", &err
);
1597 err
= U_FILE_ACCESS_ERROR
;
1598 it_dataerrln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1602 _testDataPath
= tdpath
;
1603 return _testDataPath
;
1605 return _testDataPath
;
1608 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1609 return loadTestData(err
);
1612 /* Returns the path to icu/source/test/testdata/ */
1613 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1614 const char *srcDataDir
= NULL
;
1616 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1618 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1619 FILE *f
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
"rbbitst.txt", "r");
1621 /* We're in icu/source/test/intltest/ */
1625 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1626 srcDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
1627 "test" U_FILE_SEP_STRING
"testdata" U_FILE_SEP_STRING
;
1633 char *IntlTest::getUnidataPath(char path
[]) {
1634 const int kUnicodeDataTxtLength
= 15; // strlen("UnicodeData.txt")
1636 // Look inside ICU_DATA first.
1637 strcpy(path
, pathToDataDirectory());
1638 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1639 FILE *f
= fopen(path
, "r");
1642 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1646 // As a fallback, try to guess where the source data was located
1647 // at the time ICU was built, and look there.
1649 strcpy(path
, U_TOPSRCDIR U_FILE_SEP_STRING
"data");
1651 UErrorCode errorCode
= U_ZERO_ERROR
;
1652 const char *testDataPath
= loadTestData(errorCode
);
1653 if(U_FAILURE(errorCode
)) {
1654 it_errln(UnicodeString(
1655 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1656 u_errorName(errorCode
));
1659 strcpy(path
, testDataPath
);
1660 strcat(path
, U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1661 U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".."
1662 U_FILE_SEP_STRING
"data");
1664 strcat(path
, U_FILE_SEP_STRING
);
1665 strcat(path
, "unidata" U_FILE_SEP_STRING
"UnicodeData.txt");
1666 f
= fopen(path
, "r");
1669 *(strchr(path
, 0) - kUnicodeDataTxtLength
) = 0; // Remove the basename.
1675 const char* IntlTest::fgDataDir
= NULL
;
1677 /* returns the path to icu/source/data */
1678 const char * IntlTest::pathToDataDirectory()
1681 if(fgDataDir
!= NULL
) {
1685 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1686 // to point to the top of the build hierarchy, which may or
1687 // may not be the same as the source directory, depending on
1688 // the configure options used. At any rate,
1689 // set the data path to the built data from this directory.
1690 // The value is complete with quotes, so it can be used
1691 // as-is as a string constant.
1693 #if defined (U_TOPSRCDIR)
1695 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1699 /* On Windows, the file name obtained from __FILE__ includes a full path.
1700 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1701 * Change to "wherever\icu\source\data"
1704 static char p
[sizeof(__FILE__
) + 10];
1708 strcpy(p
, __FILE__
);
1709 /* We want to back over three '\' chars. */
1710 /* Only Windows should end up here, so looking for '\' is safe. */
1711 for (i
=1; i
<=3; i
++) {
1712 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1713 if (pBackSlash
!= NULL
) {
1714 *pBackSlash
= 0; /* Truncate the string at the '\' */
1718 if (pBackSlash
!= NULL
) {
1719 /* We found and truncated three names from the path.
1720 * Now append "source\data" and set the environment
1722 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1726 /* __FILE__ on MSVC7 does not contain the directory */
1727 FILE *file
= fopen(".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1730 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1733 fgDataDir
= ".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
".." U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1744 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1745 * It converts an invariant-character string into a UnicodeString, with
1746 * unescaping \u sequences.
1748 UnicodeString
CharsToUnicodeString(const char* chars
){
1749 return UnicodeString(chars
, -1, US_INV
).unescape();
1752 UnicodeString
ctou(const char* chars
) {
1753 return CharsToUnicodeString(chars
);
1756 #define RAND_M (714025)
1757 #define RAND_IA (1366)
1758 #define RAND_IC (150889)
1760 static int32_t RAND_SEED
;
1763 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1764 * with care: Does not return all possible values; returns one of
1765 * 714,025 values, uniformly spaced. However, the period is
1766 * effectively infinite. See: Numerical Recipes, section 7.1.
1768 * @param seedp pointer to seed. Set *seedp to any negative value
1769 * to restart the sequence.
1771 float IntlTest::random(int32_t* seedp
) {
1772 static int32_t iy
, ir
[98];
1773 static UBool first
=TRUE
;
1775 if (*seedp
< 0 || first
) {
1777 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1778 for (j
=1;j
<=97;++j
) {
1779 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1782 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1785 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1786 U_ASSERT(j
>=1 && j
<=97);
1788 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1790 return (float) iy
/RAND_M
;
1794 * Convenience method using a global seed.
1796 float IntlTest::random() {
1797 return random(&RAND_SEED
);
1802 * Integer random number class implementation.
1803 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1805 IntlTest::icu_rand::icu_rand(uint32_t seed
) {
1806 seed
= seed
% 2147483647UL;
1813 IntlTest::icu_rand::~icu_rand() {}
1815 void IntlTest::icu_rand::seed(uint32_t seed
) {
1822 uint32_t IntlTest::icu_rand::operator() () {
1823 fLast
= ((uint64_t)fLast
* 48271UL) % 2147483647UL;
1827 uint32_t IntlTest::icu_rand::getSeed() {
1828 return (uint32_t) fLast
;
1833 static inline UChar
toHex(int32_t i
) {
1834 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1837 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1838 for (int32_t i
=0; i
<s
.length(); ++i
) {
1840 if (c
<= (UChar
)0x7F) {
1843 result
+= (UChar
)0x5c;
1844 result
+= (UChar
)0x75;
1845 result
+= toHex((c
>> 12) & 0xF);
1846 result
+= toHex((c
>> 8) & 0xF);
1847 result
+= toHex((c
>> 4) & 0xF);
1848 result
+= toHex( c
& 0xF);
1854 #define VERBOSE_ASSERTIONS
1856 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
, UBool possibleDataError
, const char *file
, int line
) {
1859 if (possibleDataError
) {
1860 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1862 errln("%s:%d: FAIL: assertTrue() failed: %s", file
, line
, message
);
1864 } else if (!quiet
) {
1865 logln("%s:%d: Ok: %s", file
, line
, message
);
1869 if (possibleDataError
) {
1870 dataerrln("FAIL: assertTrue() failed: %s", message
);
1872 errln("FAIL: assertTrue() failed: %s", message
);
1874 } else if (!quiet
) {
1875 logln("Ok: %s", message
);
1882 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1884 errln("FAIL: assertFalse() failed: %s", message
);
1885 } else if (!quiet
) {
1886 logln("Ok: %s", message
);
1891 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
, UBool possibleDataError
, const char *file
, int line
) {
1893 file
= ""; // prevent failure if no file given
1895 if (U_FAILURE(ec
)) {
1896 if (possibleDataError
) {
1897 dataerrln("FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1899 errcheckln(ec
, "FAIL: %s:%d: %s (%s)", file
, line
, message
, u_errorName(ec
));
1903 logln("OK: %s:%d: %s - (%s)", file
, line
, message
, u_errorName(ec
));
1908 UBool
IntlTest::assertEquals(const char* message
,
1909 const UnicodeString
& expected
,
1910 const UnicodeString
& actual
,
1911 UBool possibleDataError
) {
1912 if (expected
!= actual
) {
1913 if (possibleDataError
) {
1914 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
1916 "; expected " + prettify(expected
));
1918 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1920 "; expected " + prettify(expected
));
1924 #ifdef VERBOSE_ASSERTIONS
1926 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1932 UBool
IntlTest::assertEquals(const char* message
,
1933 const char* expected
,
1934 const char* actual
) {
1935 if (uprv_strcmp(expected
, actual
) != 0) {
1936 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1938 "\"; expected \"" + expected
+ "\"");
1941 #ifdef VERBOSE_ASSERTIONS
1943 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1949 UBool
IntlTest::assertEquals(const char* message
,
1952 if (expected
!= actual
) {
1953 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1954 actual
+ "=0x" + toHex(actual
) +
1955 "; expected " + expected
+ "=0x" + toHex(expected
));
1958 #ifdef VERBOSE_ASSERTIONS
1960 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
+ "=0x" + toHex(actual
));
1966 UBool
IntlTest::assertEquals(const char* message
,
1969 if (expected
!= actual
) {
1970 errln((UnicodeString
)"FAIL: " + message
+ "; got int64 " +
1971 Int64ToUnicodeString(actual
) +
1972 "; expected " + Int64ToUnicodeString(expected
) );
1975 #ifdef VERBOSE_ASSERTIONS
1977 logln((UnicodeString
)"Ok: " + message
+ "; got int64 " + Int64ToUnicodeString(actual
));
1983 UBool
IntlTest::assertEquals(const char* message
,
1986 if (expected
!= actual
) {
1987 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1989 "; expected " + expected
);
1992 #ifdef VERBOSE_ASSERTIONS
1994 logln((UnicodeString
)"Ok: " + message
+ "; got " + actual
);
2001 UBool
IntlTest::assertEquals(const char* message
,
2004 if (expected
!= actual
) {
2005 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2007 "; expected " + toString(expected
));
2010 #ifdef VERBOSE_ASSERTIONS
2012 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2018 #if !UCONFIG_NO_FORMATTING
2019 UBool
IntlTest::assertEquals(const char* message
,
2020 const Formattable
& expected
,
2021 const Formattable
& actual
,
2022 UBool possibleDataError
) {
2023 if (expected
!= actual
) {
2024 if (possibleDataError
) {
2025 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
2027 "; expected " + toString(expected
));
2029 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
2031 "; expected " + toString(expected
));
2035 #ifdef VERBOSE_ASSERTIONS
2037 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
2044 static char ASSERT_BUF
[256];
2046 static const char* extractToAssertBuf(const UnicodeString
& message
) {
2048 escape(message
, buf
);
2049 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
2050 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
2054 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
2055 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
2058 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
2059 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
2062 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
2063 return assertSuccess(extractToAssertBuf(message
), ec
);
2066 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2067 const UnicodeString
& expected
,
2068 const UnicodeString
& actual
,
2069 UBool possibleDataError
) {
2070 return assertEquals(extractToAssertBuf(message
), expected
, actual
, possibleDataError
);
2073 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2074 const char* expected
,
2075 const char* actual
) {
2076 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2078 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2081 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2083 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2086 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2088 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2091 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2094 #if !UCONFIG_NO_FORMATTING
2095 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
2096 const Formattable
& expected
,
2097 const Formattable
& actual
) {
2098 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
2102 void IntlTest::setProperty(const char* propline
) {
2103 if (numProps
< kMaxProps
) {
2104 proplines
[numProps
] = propline
;
2109 const char* IntlTest::getProperty(const char* prop
) {
2110 const char* val
= NULL
;
2111 for (int32_t i
= 0; i
< numProps
; i
++) {
2112 int32_t plen
= uprv_strlen(prop
);
2113 if ((int32_t)uprv_strlen(proplines
[i
]) > plen
+ 1
2114 && proplines
[i
][plen
] == '='
2115 && uprv_strncmp(proplines
[i
], prop
, plen
) == 0) {
2116 val
= &(proplines
[i
][plen
+1]);
2124 * Hey, Emacs, please set the following:
2127 * indent-tabs-mode: nil