1 /********************************************************************
3 * Copyright (c) 1997-2006, 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/unistr.h"
21 #include "unicode/ures.h"
22 #include "unicode/smpdtfmt.h"
23 #include "unicode/ucnv.h"
24 #include "unicode/uclean.h"
25 #include "unicode/timezone.h"
26 #include "unicode/curramt.h"
27 #include "unicode/putil.h"
38 #include "putilimp.h" // for uprv_getUTCtime()
39 #include "unicode/locid.h"
48 static char* _testDataPath
=NULL
;
50 // Static list of errors found
51 static UnicodeString errorList
;
53 //-----------------------------------------------------------------------------
54 //convenience classes to ease porting code that uses the Java
55 //string-concatenation operator (moved from findword test by rtg)
57 // [LIU] Just to get things working
59 UCharToUnicodeString(UChar c
)
60 { return UnicodeString(c
); }
62 // [rtg] Just to get things working
64 operator+(const UnicodeString
& left
,
67 char buffer
[64]; // nos changed from 10 to 64
68 char danger
= 'p'; // guard against overrunning the buffer (rtg)
70 sprintf(buffer
, "%ld", num
);
71 assert(danger
== 'p');
77 operator+(const UnicodeString
& left
,
80 char buffer
[64]; // nos changed from 10 to 64
81 char danger
= 'p'; // guard against overrunning the buffer (rtg)
83 sprintf(buffer
, "%lu", num
);
84 assert(danger
== 'p');
90 Int64ToUnicodeString(int64_t num
)
92 char buffer
[64]; // nos changed from 10 to 64
93 char danger
= 'p'; // guard against overrunning the buffer (rtg)
96 sprintf(buffer
, "%I64d", num
);
98 sprintf(buffer
, "%lld", (long long)num
);
100 assert(danger
== 'p');
105 // [LIU] Just to get things working
107 operator+(const UnicodeString
& left
,
110 char buffer
[64]; // was 32, made it arbitrarily bigger (rtg)
111 char danger
= 'p'; // guard against overrunning the buffer (rtg)
113 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
114 // 53*log(2)/log(10) = 15.95
115 // so there is no need to show more than 16 digits. [alan]
117 sprintf(buffer
, "%.16g", num
);
118 assert(danger
== 'p');
120 return left
+ buffer
;
123 #if !UCONFIG_NO_FORMATTING
126 * Return a string display for for this, without surrounding braces.
128 UnicodeString
_toString(const Formattable
& f
) {
130 switch (f
.getType()) {
131 case Formattable::kDate
:
133 UErrorCode status
= U_ZERO_ERROR
;
134 SimpleDateFormat
fmt(status
);
135 if (U_SUCCESS(status
)) {
137 fmt
.format(f
.getDate(), s
, pos
);
138 s
.insert(0, "Date:");
140 s
= UnicodeString("Error creating date format]");
144 case Formattable::kDouble
:
145 s
= UnicodeString("double:") + f
.getDouble();
147 case Formattable::kLong
:
148 s
= UnicodeString("long:") + f
.getLong();
151 case Formattable::kInt64
:
152 s
= UnicodeString("int64:") + Int64ToUnicodeString(f
.getInt64());
155 case Formattable::kString
:
157 s
.insert(0, "String:");
159 case Formattable::kArray
:
162 const Formattable
* array
= f
.getArray(n
);
163 s
.insert(0, UnicodeString("Array:"));
164 UnicodeString
delim(", ");
165 for (i
=0; i
<n
; ++i
) {
169 s
= s
+ _toString(array
[i
]);
173 case Formattable::kObject
:
174 if (f
.getObject()->getDynamicClassID() ==
175 CurrencyAmount::getStaticClassID()) {
176 const CurrencyAmount
& c
= (const CurrencyAmount
&) *f
.getObject();
177 s
= _toString(c
.getNumber()) + " " + UnicodeString(c
.getISOCurrency());
179 s
= UnicodeString("Unknown UObject");
183 s
= UnicodeString("Unknown Formattable type=") + (int32_t)f
.getType();
190 * Originally coded this as operator+, but that makes the expression
191 * + char* ambiguous. - liu
193 UnicodeString
toString(const Formattable
& f
) {
194 UnicodeString
s((UChar
)91/*[*/);
195 s
.append(_toString(f
));
196 s
.append((UChar
)0x5d/*]*/);
202 // useful when operator+ won't cooperate
203 UnicodeString
toString(int32_t n
) {
204 return UnicodeString() + (long)n
;
207 // stephen - cleaned up 05/05/99
208 UnicodeString
operator+(const UnicodeString
& left
, char num
)
209 { return left
+ (long)num
; }
210 UnicodeString
operator+(const UnicodeString
& left
, short num
)
211 { return left
+ (long)num
; }
212 UnicodeString
operator+(const UnicodeString
& left
, int num
)
213 { return left
+ (long)num
; }
214 UnicodeString
operator+(const UnicodeString
& left
, unsigned char num
)
215 { return left
+ (unsigned long)num
; }
216 UnicodeString
operator+(const UnicodeString
& left
, unsigned short num
)
217 { return left
+ (unsigned long)num
; }
218 UnicodeString
operator+(const UnicodeString
& left
, unsigned int num
)
219 { return left
+ (unsigned long)num
; }
220 UnicodeString
operator+(const UnicodeString
& left
, float num
)
221 { return left
+ (double)num
; }
225 // Append a hex string to the target
227 IntlTest::appendHex(uint32_t number
,
229 UnicodeString
& target
)
231 static const UChar digitString
[] = {
232 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
233 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
234 }; /* "0123456789ABCDEF" */
239 target
+= digitString
[(number
>> 28) & 0xF];
241 target
+= digitString
[(number
>> 24) & 0xF];
243 target
+= digitString
[(number
>> 20) & 0xF];
245 target
+= digitString
[(number
>> 16) & 0xF];
247 target
+= digitString
[(number
>> 12) & 0xF];
249 target
+= digitString
[(number
>> 8) & 0xF];
251 target
+= digitString
[(number
>> 4) & 0xF];
253 target
+= digitString
[(number
>> 0) & 0xF];
261 // Replace nonprintable characters with unicode escapes
263 IntlTest::prettify(const UnicodeString
&source
,
264 UnicodeString
&target
)
271 for (i
= 0; i
< source
.length(); )
273 UChar32 ch
= source
.char32At(i
);
274 i
+= UTF_CHAR_LENGTH(ch
);
276 if (ch
< 0x09 || (ch
> 0x0A && ch
< 0x20)|| ch
> 0x7E)
280 appendHex(ch
, 4, target
);
283 appendHex(ch
, 8, target
);
297 // Replace nonprintable characters with unicode escapes
299 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
302 UnicodeString target
;
306 for (i
= 0; i
< source
.length();)
308 UChar32 ch
= source
.char32At(i
);
309 i
+= UTF_CHAR_LENGTH(ch
);
311 if (ch
< 0x09 || (ch
> 0x0A && ch
< 0x20)|| ch
> 0x7E)
313 if (parseBackslash
) {
314 // If we are preceded by an odd number of backslashes,
315 // then this character has already been backslash escaped.
316 // Delete a backslash.
317 int32_t backslashCount
= 0;
318 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
319 if (target
.charAt(j
) == (UChar
)92) {
325 if ((backslashCount
% 2) == 1) {
326 target
.truncate(target
.length() - 1);
331 appendHex(ch
, 4, target
);
334 appendHex(ch
, 8, target
);
348 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
349 * set, try to deduce the directory in which ICU was built,
350 * and set ICU_DATA to "icu/source/data" in that location.
351 * The intent is to allow the tests to have a good chance
352 * of running without requiring that the user manually set
353 * ICU_DATA. Common data isn't a problem, since it is
354 * picked up via a static (build time) reference, but the
355 * tests dynamically load some data.
357 void IntlTest::setICU_DATA() {
358 const char *original_ICU_DATA
= getenv("ICU_DATA");
360 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
361 /* If the user set ICU_DATA, don't second-guess the person. */
365 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
366 // to point to the top of the build hierarchy, which may or
367 // may not be the same as the source directory, depending on
368 // the configure options used. At any rate,
369 // set the data path to the built data from this directory.
370 // The value is complete with quotes, so it can be used
371 // as-is as a string constant.
373 #if defined (U_TOPBUILDDIR)
375 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
376 u_setDataDirectory(env_string
);
381 // Use #else so we don't get compiler warnings due to the return above.
383 /* On Windows, the file name obtained from __FILE__ includes a full path.
384 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
385 * Change to "wherever\icu\source\data"
388 char p
[sizeof(__FILE__
) + 10];
393 /* We want to back over three '\' chars. */
394 /* Only Windows should end up here, so looking for '\' is safe. */
395 for (i
=1; i
<=3; i
++) {
396 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
397 if (pBackSlash
!= NULL
) {
398 *pBackSlash
= 0; /* Truncate the string at the '\' */
402 if (pBackSlash
!= NULL
) {
403 /* We found and truncated three names from the path.
404 * Now append "source\data" and set the environment
406 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
407 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
411 /* __FILE__ on MSVC7 does not contain the directory */
412 u_setDataDirectory(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
418 /* No location for the data dir was identifiable.
419 * Add other fallbacks for the test data location here if the need arises
424 //--------------------------------------------------------------------------------------
426 static const int32_t indentLevel_offset
= 3;
427 static const char delim
= '/';
429 IntlTest
* IntlTest::gTest
= NULL
;
431 static int32_t execCount
= 0;
433 void it_log( UnicodeString message
)
436 IntlTest::gTest
->log( message
);
439 void it_logln( UnicodeString message
)
442 IntlTest::gTest
->logln( message
);
445 void it_logln( void )
448 IntlTest::gTest
->logln();
451 void it_info( UnicodeString message
)
454 IntlTest::gTest
->info( message
);
457 void it_infoln( UnicodeString message
)
460 IntlTest::gTest
->infoln( message
);
463 void it_infoln( void )
466 IntlTest::gTest
->infoln();
472 IntlTest::gTest
->err();
475 void it_err( UnicodeString message
)
478 IntlTest::gTest
->err( message
);
481 void it_errln( UnicodeString message
)
484 IntlTest::gTest
->errln( message
);
487 void it_dataerr( UnicodeString message
)
490 IntlTest::gTest
->dataerr( message
);
493 void it_dataerrln( UnicodeString message
)
496 IntlTest::gTest
->dataerrln( message
);
508 warn_on_missing_data
= FALSE
;
512 LL_indentlevel
= indentLevel_offset
;
515 void IntlTest::setCaller( IntlTest
* callingTest
)
517 caller
= callingTest
;
519 verbose
= caller
->verbose
;
520 no_err_msg
= caller
->no_err_msg
;
521 quick
= caller
->quick
;
522 testoutfp
= caller
->testoutfp
;
523 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
527 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
529 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
530 testToBeCalled
.setCaller( this );
531 return testToBeCalled
.runTest( testPath
, par
);
534 void IntlTest::setPath( char* pathVal
)
536 this->testPath
= pathVal
;
539 UBool
IntlTest::setVerbose( UBool verboseVal
)
541 UBool rval
= this->verbose
;
542 this->verbose
= verboseVal
;
546 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
548 UBool rval
= this->warn_on_missing_data
;
549 this->warn_on_missing_data
= warn_on_missing_dataVal
;
553 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
555 UBool rval
= this->no_err_msg
;
556 this->no_err_msg
= no_err_msgVal
;
560 UBool
IntlTest::setQuick( UBool quickVal
)
562 UBool rval
= this->quick
;
563 this->quick
= quickVal
;
567 UBool
IntlTest::setLeaks( UBool leaksVal
)
569 UBool rval
= this->leaks
;
570 this->leaks
= leaksVal
;
574 int32_t IntlTest::getErrors( void )
579 int32_t IntlTest::getDataErrors( void )
581 return dataErrorCount
;
584 UBool
IntlTest::runTest( char* name
, char* par
)
590 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
592 testPath
= pos
+1; // store subpath for calling subtest
593 *pos
= 0; // split into two strings
598 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
599 rval
= runTestLoop( NULL
, par
);
601 }else if (strcmp( name
, "LIST" ) == 0) {
606 rval
= runTestLoop( name
, par
);
610 *pos
= delim
; // restore original value at pos
614 // call individual tests, to be overriden to call implementations
615 void IntlTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* par
)
617 // to be overriden by a method like:
620 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
621 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
622 default: name = ""; break;
625 this->errln("*** runIndexedTest needs to be overriden! ***");
626 name
= ""; exec
= exec
; index
= index
; par
= par
;
630 UBool
IntlTest::runTestLoop( char* testname
, char* par
)
635 int32_t lastErrorCount
;
637 UBool lastTestFailed
;
639 IntlTest
* saveTest
= gTest
;
642 this->runIndexedTest( index
, FALSE
, name
, par
);
643 if (!name
|| (name
[0] == 0))
646 run_this_test
= TRUE
;
648 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
651 lastErrorCount
= errorCount
;
653 this->runIndexedTest( index
, TRUE
, name
, par
);
654 rval
= TRUE
; // at least one test has been called
656 if (lastErrorCount
== errorCount
) {
657 sprintf( msg
, "---OK: %s", name
);
658 lastTestFailed
= FALSE
;
660 sprintf(msg
, "---ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
662 for(int i
=0;i
<LL_indentlevel
;i
++) {
667 lastTestFailed
= TRUE
;
670 if (lastTestFailed
) {
671 LL_message( "", TRUE
);
673 LL_message( msg
, TRUE
);
674 if (lastTestFailed
) {
675 LL_message( "", TRUE
);
688 * Adds given string to the log if we are in verbose mode.
690 void IntlTest::log( const UnicodeString
&message
)
693 LL_message( message
, FALSE
);
698 * Adds given string to the log if we are in verbose mode. Adds a new line to
701 void IntlTest::logln( const UnicodeString
&message
)
704 LL_message( message
, TRUE
);
708 void IntlTest::logln( void )
711 LL_message( "", TRUE
);
716 * Unconditionally adds given string to the log.
718 void IntlTest::info( const UnicodeString
&message
)
720 LL_message( message
, FALSE
);
724 * Unconditionally adds given string to the log. Adds a new line to
727 void IntlTest::infoln( const UnicodeString
&message
)
729 LL_message( message
, TRUE
);
732 void IntlTest::infoln( void )
734 LL_message( "", TRUE
);
737 int32_t IntlTest::IncErrorCount( void )
740 if (caller
) caller
->IncErrorCount();
744 int32_t IntlTest::IncDataErrorCount( void )
747 if (caller
) caller
->IncDataErrorCount();
748 return dataErrorCount
;
756 void IntlTest::err( const UnicodeString
&message
)
759 if (!no_err_msg
) LL_message( message
, FALSE
);
762 void IntlTest::errln( const UnicodeString
&message
)
765 if (!no_err_msg
) LL_message( message
, TRUE
);
768 void IntlTest::dataerr( const UnicodeString
&message
)
772 if (!warn_on_missing_data
) {
776 if (!no_err_msg
) LL_message( message
, FALSE
);
779 void IntlTest::dataerrln( const UnicodeString
&message
)
783 if (!warn_on_missing_data
) {
787 if (!no_err_msg
) LL_message( message
, TRUE
);
790 /* convenience functions that include sprintf formatting */
791 void IntlTest::log(const char *fmt
, ...)
797 /* sprintf it just to make sure that the information is valid */
798 vsprintf(buffer
, fmt
, ap
);
801 log(UnicodeString(buffer
, ""));
805 void IntlTest::logln(const char *fmt
, ...)
811 /* sprintf it just to make sure that the information is valid */
812 vsprintf(buffer
, fmt
, ap
);
815 logln(UnicodeString(buffer
, ""));
819 /* convenience functions that include sprintf formatting */
820 void IntlTest::info(const char *fmt
, ...)
826 /* sprintf it just to make sure that the information is valid */
827 vsprintf(buffer
, fmt
, ap
);
829 info(UnicodeString(buffer
, ""));
832 void IntlTest::infoln(const char *fmt
, ...)
838 /* sprintf it just to make sure that the information is valid */
839 vsprintf(buffer
, fmt
, ap
);
841 infoln(UnicodeString(buffer
, ""));
844 void IntlTest::err(const char *fmt
, ...)
850 vsprintf(buffer
, fmt
, ap
);
852 err(UnicodeString(buffer
, ""));
855 void IntlTest::errln(const char *fmt
, ...)
861 vsprintf(buffer
, fmt
, ap
);
863 errln(UnicodeString(buffer
, ""));
866 void IntlTest::dataerrln(const char *fmt
, ...)
872 vsprintf(buffer
, fmt
, ap
);
874 dataerrln(UnicodeString(buffer
, ""));
877 void IntlTest::printErrors()
879 IntlTest::LL_message(errorList
, TRUE
);
882 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
884 // string that starts with a LineFeed character and continues
885 // with spaces according to the current indentation
886 static const UChar indentUChars
[] = {
888 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
889 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
890 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
891 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
892 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
893 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
894 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
895 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
896 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
897 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
899 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
904 // stream out the indentation string first if necessary
905 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
907 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
910 // replace each LineFeed by the indentation string
911 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
913 // stream out the message
914 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
916 length
= length
> 10000 ? 10000 : length
;
917 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
922 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
925 // A newline usually flushes the buffer, but
926 // flush the message just in case of a core dump.
927 fflush((FILE *)testoutfp
);
931 * Print a usage message for this test class.
933 void IntlTest::usage( void )
935 UBool save_verbose
= setVerbose( TRUE
);
936 logln("Test names:");
937 logln("-----------");
940 const char* name
= NULL
;
942 this->runIndexedTest( index
, FALSE
, name
);
946 }while (name
&& (name
[0] != 0));
947 setVerbose( save_verbose
);
951 // memory leak reporting software will be able to take advantage of the testsuite
952 // being run a second time local to a specific method in order to report only actual leaks
954 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
956 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
957 strLeak
->append(" for verifying purify filter");
958 return this->runTest( name
, par
);
962 #if UCONFIG_NO_LEGACY_CONVERSION
963 # define TRY_CNV_1 "iso-8859-1"
964 # define TRY_CNV_2 "ibm-1208"
966 # define TRY_CNV_1 "iso-8859-7"
967 # define TRY_CNV_2 "sjis"
971 main(int argc
, char* argv
[])
973 UBool syntax
= FALSE
;
975 UBool verbose
= FALSE
;
976 UBool no_err_msg
= FALSE
;
980 UBool warnOnMissingData
= FALSE
;
981 UBool defaultDataFound
= FALSE
;
982 UErrorCode errorCode
= U_ZERO_ERROR
;
983 UConverter
*cnv
= NULL
;
984 const char *warnOrErr
= "Failure";
985 UDate startTime
, endTime
;
988 U_MAIN_INIT_ARGS(argc
, argv
);
990 startTime
= uprv_getUTCtime();
992 for (int i
= 1; i
< argc
; ++i
) {
993 if (argv
[i
][0] == '-') {
994 const char* str
= argv
[i
] + 1;
995 if (strcmp("verbose", str
) == 0 ||
996 strcmp("v", str
) == 0)
998 else if (strcmp("noerrormsg", str
) == 0 ||
999 strcmp("n", str
) == 0)
1001 else if (strcmp("exhaustive", str
) == 0 ||
1002 strcmp("e", str
) == 0)
1004 else if (strcmp("all", str
) == 0 ||
1005 strcmp("a", str
) == 0)
1007 else if (strcmp("leaks", str
) == 0 ||
1008 strcmp("l", str
) == 0)
1010 else if (strcmp("w", str
) == 0) {
1011 warnOnMissingData
= TRUE
;
1012 warnOrErr
= "WARNING";
1022 if (!all
&& !name
) {
1024 } else if (all
&& name
) {
1031 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1032 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
1033 "### exhaustive (e), leaks (l)"
1034 "### (Specify either -all (shortcut -a) or a test name). \n"
1035 "### -all will run all of the tests.\n"
1037 "### To get a list of the test names type: intltest LIST \n"
1038 "### To run just the utility tests type: intltest utility \n"
1040 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1041 "### For example to list the utility tests type: intltest utility/LIST \n"
1042 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1044 "### A parameter can be specified for a test by appending '@' and the value \n"
1045 "### to the testname. \n\n");
1049 UBool all_tests_exist
= TRUE
;
1050 MajorTestLevel major
;
1051 major
.setVerbose( verbose
);
1052 major
.setNoErrMsg( no_err_msg
);
1053 major
.setQuick( quick
);
1054 major
.setLeaks( leaks
);
1055 major
.setWarnOnMissingData( warnOnMissingData
);
1056 fprintf(stdout
, "-----------------------------------------------\n");
1057 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1058 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1059 fprintf(stdout
, "-----------------------------------------------\n");
1060 fprintf(stdout
, " Options: \n");
1061 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1062 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1063 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1064 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1065 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1066 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1067 fprintf(stdout
, "-----------------------------------------------\n");
1069 /* Check whether ICU will initialize without forcing the build data directory into
1070 * the ICU_DATA path. Success here means either the data dll contains data, or that
1071 * this test program was run with ICU_DATA set externally. Failure of this check
1072 * is normal when ICU data is not packaged into a shared library.
1074 * Whether or not this test succeeds, we want to cleanup and reinitialize
1075 * with a data path so that data loading from individual files can be tested.
1078 if (U_FAILURE(errorCode
)) {
1080 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1081 defaultDataFound
= FALSE
;
1084 defaultDataFound
= TRUE
;
1087 errorCode
= U_ZERO_ERROR
;
1089 /* Initialize ICU */
1090 if (!defaultDataFound
) {
1091 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1094 if (U_FAILURE(errorCode
)) {
1096 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1097 "*** Check the ICU_DATA environment variable and \n"
1098 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1099 if(warnOnMissingData
== 0) {
1100 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1107 // initial check for the default converter
1108 errorCode
= U_ZERO_ERROR
;
1109 cnv
= ucnv_open(0, &errorCode
);
1115 "*** %s! The default converter [%s] cannot be opened.\n"
1116 "*** Check the ICU_DATA environment variable and\n"
1117 "*** check that the data files are present.\n",
1118 warnOrErr
, ucnv_getDefaultName());
1119 if(!warnOnMissingData
) {
1120 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1126 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1132 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1133 "*** Check the ICU_DATA environment variable and \n"
1134 "*** check that the data files are present.\n", warnOrErr
);
1135 if(!warnOnMissingData
) {
1136 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1141 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1143 if(U_FAILURE(errorCode
)) {
1145 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1146 "*** Check the ICU_DATA environment variable and \n"
1147 "*** check that the data files are present.\n", warnOrErr
);
1148 if(!warnOnMissingData
) {
1149 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1154 Locale originalLocale
; // Save the default locale for comparison later on.
1156 /* TODO: Add option to call u_cleanup and rerun tests. */
1160 major
.run_phase2( NULL
, NULL
);
1163 for (int i
= 1; i
< argc
; ++i
) {
1164 if (argv
[i
][0] != '-') {
1165 char* name
= argv
[i
];
1166 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1167 char* parameter
= strchr( name
, '@' );
1173 UBool res
= major
.runTest( name
, parameter
);
1175 major
.run_phase2( name
, parameter
);
1177 if (!res
|| (execCount
<= 0)) {
1178 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1179 all_tests_exist
= FALSE
;
1185 #if !UCONFIG_NO_FORMATTING
1186 CalendarTimeZoneTest::cleanup();
1189 free(_testDataPath
);
1192 Locale lastDefaultLocale
;
1193 if (originalLocale
!= lastDefaultLocale
) {
1194 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1197 fprintf(stdout
, "\n--------------------------------------\n");
1198 if (major
.getErrors() == 0) {
1199 /* Call it twice to make sure that the defaults were reset. */
1200 /* Call it before the OK message to verify proper cleanup. */
1204 fprintf(stdout
, "OK: All tests passed without error.\n");
1206 if (major
.getDataErrors() != 0) {
1207 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1210 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1211 major
.printErrors();
1214 if (major
.getDataErrors() != 0) {
1215 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1216 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1217 "\tthe '-w' option to turn these errors into warnings.\n");
1220 /* Call afterwards to display errors. */
1224 fprintf(stdout
, "--------------------------------------\n");
1226 if (execCount
<= 0) {
1227 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1229 endTime
= uprv_getUTCtime();
1230 diffTime
= (int32_t)(endTime
- startTime
);
1231 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1232 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1233 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1234 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1235 (int)(diffTime%U_MILLIS_PER_SECOND
));
1236 return major
.getErrors();
1239 const char* IntlTest::loadTestData(UErrorCode
& err
){
1240 if( _testDataPath
== NULL
){
1241 const char* directory
=NULL
;
1242 UResourceBundle
* test
=NULL
;
1244 const char* tdrelativepath
;
1246 #if defined (U_TOPBUILDDIR)
1247 tdrelativepath
= "test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1248 directory
= U_TOPBUILDDIR
;
1250 tdrelativepath
= ".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1251 directory
= pathToDataDirectory();
1254 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1257 /* u_getDataDirectory shoul return \source\data ... set the
1258 * directory to ..\source\data\..\test\testdata\out\testdata
1260 strcpy(tdpath
, directory
);
1261 strcat(tdpath
, tdrelativepath
);
1262 strcat(tdpath
,"testdata");
1264 test
=ures_open(tdpath
, "testtypes", &err
);
1267 err
= U_FILE_ACCESS_ERROR
;
1268 it_errln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1272 _testDataPath
= tdpath
;
1273 return _testDataPath
;
1275 return _testDataPath
;
1278 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1279 return loadTestData(err
);
1282 /* Returns the path to icu/source/test/testdata/ */
1283 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1284 const char *srcDataDir
= NULL
;
1286 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1288 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1289 FILE *f
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"rbbitst.txt", "r");
1291 /* We're in icu/source/test/intltest/ */
1295 /* We're in icu/source/test/intltest/(Debug|Release) */
1296 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1302 const char* IntlTest::fgDataDir
= NULL
;
1304 /* returns the path to icu/source/data */
1305 const char * IntlTest::pathToDataDirectory()
1308 if(fgDataDir
!= NULL
) {
1312 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1313 // to point to the top of the build hierarchy, which may or
1314 // may not be the same as the source directory, depending on
1315 // the configure options used. At any rate,
1316 // set the data path to the built data from this directory.
1317 // The value is complete with quotes, so it can be used
1318 // as-is as a string constant.
1320 #if defined (U_TOPSRCDIR)
1322 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1326 /* On Windows, the file name obtained from __FILE__ includes a full path.
1327 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1328 * Change to "wherever\icu\source\data"
1331 static char p
[sizeof(__FILE__
) + 10];
1335 strcpy(p
, __FILE__
);
1336 /* We want to back over three '\' chars. */
1337 /* Only Windows should end up here, so looking for '\' is safe. */
1338 for (i
=1; i
<=3; i
++) {
1339 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1340 if (pBackSlash
!= NULL
) {
1341 *pBackSlash
= 0; /* Truncate the string at the '\' */
1345 if (pBackSlash
!= NULL
) {
1346 /* We found and truncated three names from the path.
1347 * Now append "source\data" and set the environment
1349 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1353 /* __FILE__ on MSVC7 does not contain the directory */
1354 FILE *file
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1357 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1360 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1371 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1372 * It converts a character string into a UnicodeString, with
1373 * unescaping \u sequences.
1375 UnicodeString
CharsToUnicodeString(const char* chars
)
1377 UnicodeString
str(chars
, ""); // Invariant conversion
1378 return str
.unescape();
1381 UnicodeString
ctou(const char* chars
) {
1382 return CharsToUnicodeString(chars
);
1385 #define RAND_M (714025)
1386 #define RAND_IA (1366)
1387 #define RAND_IC (150889)
1389 static int32_t RAND_SEED
;
1392 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1393 * with care: Does not return all possible values; returns one of
1394 * 714,025 values, uniformly spaced. However, the period is
1395 * effectively infinite. See: Numerical Recipes, section 7.1.
1397 * @param seedp pointer to seed. Set *seedp to any negative value
1398 * to restart the sequence.
1400 float IntlTest::random(int32_t* seedp
) {
1401 static int32_t iy
, ir
[98];
1402 static UBool first
=TRUE
;
1404 if (*seedp
< 0 || first
) {
1406 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1407 for (j
=1;j
<=97;++j
) {
1408 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1411 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1414 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1415 U_ASSERT(j
>=1 && j
<=97);
1417 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1419 return (float) iy
/RAND_M
;
1423 * Convenience method using a global seed.
1425 float IntlTest::random() {
1426 return random(&RAND_SEED
);
1429 static inline UChar
toHex(int32_t i
) {
1430 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1433 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1434 for (int32_t i
=0; i
<s
.length(); ++i
) {
1436 if (c
<= (UChar
)0x7F) {
1439 result
+= (UChar
)0x5c;
1440 result
+= (UChar
)0x75;
1441 result
+= toHex((c
>> 12) & 0xF);
1442 result
+= toHex((c
>> 8) & 0xF);
1443 result
+= toHex((c
>> 4) & 0xF);
1444 result
+= toHex( c
& 0xF);
1450 #define VERBOSE_ASSERTIONS
1452 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
) {
1454 errln("FAIL: assertTrue() failed: %s", message
);
1455 } else if (!quiet
) {
1456 logln("Ok: %s", message
);
1461 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1463 errln("FAIL: assertFalse() failed: %s", message
);
1464 } else if (!quiet
) {
1465 logln("Ok: %s", message
);
1470 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
) {
1471 if (U_FAILURE(ec
)) {
1472 errln("FAIL: %s (%s)", message
, u_errorName(ec
));
1478 UBool
IntlTest::assertEquals(const char* message
,
1479 const UnicodeString
& expected
,
1480 const UnicodeString
& actual
) {
1481 if (expected
!= actual
) {
1482 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1484 "; expected " + prettify(expected
));
1487 #ifdef VERBOSE_ASSERTIONS
1489 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1495 UBool
IntlTest::assertEquals(const char* message
,
1496 const char* expected
,
1497 const char* actual
) {
1498 if (uprv_strcmp(expected
, actual
) != 0) {
1499 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1501 "\"; expected \"" + expected
+ "\"");
1504 #ifdef VERBOSE_ASSERTIONS
1506 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1512 #if !UCONFIG_NO_FORMATTING
1513 UBool
IntlTest::assertEquals(const char* message
,
1514 const Formattable
& expected
,
1515 const Formattable
& actual
) {
1516 if (expected
!= actual
) {
1517 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1519 "; expected " + toString(expected
));
1522 #ifdef VERBOSE_ASSERTIONS
1524 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
1531 static char ASSERT_BUF
[256];
1533 static const char* extractToAssertBuf(const UnicodeString
& message
) {
1535 escape(message
, buf
);
1536 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
1537 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
1541 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1542 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
1545 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1546 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
1549 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
1550 return assertSuccess(extractToAssertBuf(message
), ec
);
1553 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1554 const UnicodeString
& expected
,
1555 const UnicodeString
& actual
) {
1556 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1559 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1560 const char* expected
,
1561 const char* actual
) {
1562 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1564 //--------------------------------------------------------------------
1565 // Time bomb - allows temporary behavior that expires at a given
1567 //--------------------------------------------------------------------
1569 UBool
IntlTest::isICUVersionAtLeast(const UVersionInfo x
) {
1572 return (uprv_memcmp(v
, x
, U_MAX_VERSION_LENGTH
) >= 0);
1575 #if !UCONFIG_NO_FORMATTING
1576 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1577 const Formattable
& expected
,
1578 const Formattable
& actual
) {
1579 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1584 * Hey, Emacs, please set the following:
1587 * indent-tabs-mode: nil