1 /********************************************************************
3 * Copyright (c) 1997-2008, 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
, "%.17g", 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 warn_on_missing_data
= caller
->warn_on_missing_data
;
520 verbose
= caller
->verbose
;
521 no_err_msg
= caller
->no_err_msg
;
522 quick
= caller
->quick
;
523 testoutfp
= caller
->testoutfp
;
524 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
528 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
530 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
531 testToBeCalled
.setCaller( this );
532 return testToBeCalled
.runTest( testPath
, par
);
535 void IntlTest::setPath( char* pathVal
)
537 this->testPath
= pathVal
;
540 UBool
IntlTest::setVerbose( UBool verboseVal
)
542 UBool rval
= this->verbose
;
543 this->verbose
= verboseVal
;
547 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
549 UBool rval
= this->warn_on_missing_data
;
550 this->warn_on_missing_data
= warn_on_missing_dataVal
;
554 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
556 UBool rval
= this->no_err_msg
;
557 this->no_err_msg
= no_err_msgVal
;
561 UBool
IntlTest::setQuick( UBool quickVal
)
563 UBool rval
= this->quick
;
564 this->quick
= quickVal
;
568 UBool
IntlTest::setLeaks( UBool leaksVal
)
570 UBool rval
= this->leaks
;
571 this->leaks
= leaksVal
;
575 int32_t IntlTest::getErrors( void )
580 int32_t IntlTest::getDataErrors( void )
582 return dataErrorCount
;
585 UBool
IntlTest::runTest( char* name
, char* par
)
591 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
593 testPath
= pos
+1; // store subpath for calling subtest
594 *pos
= 0; // split into two strings
599 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
600 rval
= runTestLoop( NULL
, par
);
602 }else if (strcmp( name
, "LIST" ) == 0) {
607 rval
= runTestLoop( name
, par
);
611 *pos
= delim
; // restore original value at pos
615 // call individual tests, to be overriden to call implementations
616 void IntlTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* par
)
618 // to be overriden by a method like:
621 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
622 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
623 default: name = ""; break;
626 this->errln("*** runIndexedTest needs to be overriden! ***");
627 name
= ""; exec
= exec
; index
= index
; par
= par
;
631 UBool
IntlTest::runTestLoop( char* testname
, char* par
)
636 int32_t lastErrorCount
;
638 UBool lastTestFailed
;
640 IntlTest
* saveTest
= gTest
;
643 this->runIndexedTest( index
, FALSE
, name
, par
);
644 if (!name
|| (name
[0] == 0))
647 run_this_test
= TRUE
;
649 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
652 lastErrorCount
= errorCount
;
654 this->runIndexedTest( index
, TRUE
, name
, par
);
655 rval
= TRUE
; // at least one test has been called
657 if (lastErrorCount
== errorCount
) {
658 sprintf( msg
, "---OK: %s", name
);
659 lastTestFailed
= FALSE
;
661 sprintf(msg
, "---ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
663 for(int i
=0;i
<LL_indentlevel
;i
++) {
668 lastTestFailed
= TRUE
;
671 if (lastTestFailed
) {
672 LL_message( "", TRUE
);
674 LL_message( msg
, TRUE
);
675 if (lastTestFailed
) {
676 LL_message( "", TRUE
);
689 * Adds given string to the log if we are in verbose mode.
691 void IntlTest::log( const UnicodeString
&message
)
694 LL_message( message
, FALSE
);
699 * Adds given string to the log if we are in verbose mode. Adds a new line to
702 void IntlTest::logln( const UnicodeString
&message
)
705 LL_message( message
, TRUE
);
709 void IntlTest::logln( void )
712 LL_message( "", TRUE
);
717 * Unconditionally adds given string to the log.
719 void IntlTest::info( const UnicodeString
&message
)
721 LL_message( message
, FALSE
);
725 * Unconditionally adds given string to the log. Adds a new line to
728 void IntlTest::infoln( const UnicodeString
&message
)
730 LL_message( message
, TRUE
);
733 void IntlTest::infoln( void )
735 LL_message( "", TRUE
);
738 int32_t IntlTest::IncErrorCount( void )
741 if (caller
) caller
->IncErrorCount();
745 int32_t IntlTest::IncDataErrorCount( void )
748 if (caller
) caller
->IncDataErrorCount();
749 return dataErrorCount
;
757 void IntlTest::err( const UnicodeString
&message
)
760 if (!no_err_msg
) LL_message( message
, FALSE
);
763 void IntlTest::errln( const UnicodeString
&message
)
766 if (!no_err_msg
) LL_message( message
, TRUE
);
769 void IntlTest::dataerr( const UnicodeString
&message
)
773 if (!warn_on_missing_data
) {
777 if (!no_err_msg
) LL_message( message
, FALSE
);
780 void IntlTest::dataerrln( const UnicodeString
&message
)
784 if (!warn_on_missing_data
) {
788 if (!no_err_msg
) LL_message( message
, TRUE
);
791 /* convenience functions that include sprintf formatting */
792 void IntlTest::log(const char *fmt
, ...)
798 /* sprintf it just to make sure that the information is valid */
799 vsprintf(buffer
, fmt
, ap
);
802 log(UnicodeString(buffer
, ""));
806 void IntlTest::logln(const char *fmt
, ...)
812 /* sprintf it just to make sure that the information is valid */
813 vsprintf(buffer
, fmt
, ap
);
816 logln(UnicodeString(buffer
, ""));
820 /* convenience functions that include sprintf formatting */
821 void IntlTest::info(const char *fmt
, ...)
827 /* sprintf it just to make sure that the information is valid */
828 vsprintf(buffer
, fmt
, ap
);
830 info(UnicodeString(buffer
, ""));
833 void IntlTest::infoln(const char *fmt
, ...)
839 /* sprintf it just to make sure that the information is valid */
840 vsprintf(buffer
, fmt
, ap
);
842 infoln(UnicodeString(buffer
, ""));
845 void IntlTest::err(const char *fmt
, ...)
851 vsprintf(buffer
, fmt
, ap
);
853 err(UnicodeString(buffer
, ""));
856 void IntlTest::errln(const char *fmt
, ...)
862 vsprintf(buffer
, fmt
, ap
);
864 errln(UnicodeString(buffer
, ""));
867 void IntlTest::dataerrln(const char *fmt
, ...)
873 vsprintf(buffer
, fmt
, ap
);
875 dataerrln(UnicodeString(buffer
, ""));
878 void IntlTest::printErrors()
880 IntlTest::LL_message(errorList
, TRUE
);
883 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
885 // string that starts with a LineFeed character and continues
886 // with spaces according to the current indentation
887 static const UChar indentUChars
[] = {
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,
898 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
900 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
905 // stream out the indentation string first if necessary
906 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
908 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
911 // replace each LineFeed by the indentation string
912 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
914 // stream out the message
915 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
917 length
= length
> 10000 ? 10000 : length
;
918 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
923 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
926 // A newline usually flushes the buffer, but
927 // flush the message just in case of a core dump.
928 fflush((FILE *)testoutfp
);
932 * Print a usage message for this test class.
934 void IntlTest::usage( void )
936 UBool save_verbose
= setVerbose( TRUE
);
937 logln("Test names:");
938 logln("-----------");
941 const char* name
= NULL
;
943 this->runIndexedTest( index
, FALSE
, name
);
947 }while (name
&& (name
[0] != 0));
948 setVerbose( save_verbose
);
952 // memory leak reporting software will be able to take advantage of the testsuite
953 // being run a second time local to a specific method in order to report only actual leaks
955 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
957 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
958 strLeak
->append(" for verifying purify filter");
959 return this->runTest( name
, par
);
963 #if UCONFIG_NO_LEGACY_CONVERSION
964 # define TRY_CNV_1 "iso-8859-1"
965 # define TRY_CNV_2 "ibm-1208"
967 # define TRY_CNV_1 "iso-8859-7"
968 # define TRY_CNV_2 "sjis"
972 main(int argc
, char* argv
[])
974 UBool syntax
= FALSE
;
976 UBool verbose
= FALSE
;
977 UBool no_err_msg
= FALSE
;
981 UBool warnOnMissingData
= FALSE
;
982 UBool defaultDataFound
= FALSE
;
983 UErrorCode errorCode
= U_ZERO_ERROR
;
984 UConverter
*cnv
= NULL
;
985 const char *warnOrErr
= "Failure";
986 UDate startTime
, endTime
;
989 U_MAIN_INIT_ARGS(argc
, argv
);
991 startTime
= uprv_getUTCtime();
993 for (int i
= 1; i
< argc
; ++i
) {
994 if (argv
[i
][0] == '-') {
995 const char* str
= argv
[i
] + 1;
996 if (strcmp("verbose", str
) == 0 ||
997 strcmp("v", str
) == 0)
999 else if (strcmp("noerrormsg", str
) == 0 ||
1000 strcmp("n", str
) == 0)
1002 else if (strcmp("exhaustive", str
) == 0 ||
1003 strcmp("e", str
) == 0)
1005 else if (strcmp("all", str
) == 0 ||
1006 strcmp("a", str
) == 0)
1008 else if (strcmp("leaks", str
) == 0 ||
1009 strcmp("l", str
) == 0)
1011 else if (strcmp("w", str
) == 0) {
1012 warnOnMissingData
= TRUE
;
1013 warnOrErr
= "WARNING";
1023 if (!all
&& !name
) {
1025 } else if (all
&& name
) {
1032 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1033 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
1034 "### exhaustive (e), leaks (l)"
1035 "### (Specify either -all (shortcut -a) or a test name). \n"
1036 "### -all will run all of the tests.\n"
1038 "### To get a list of the test names type: intltest LIST \n"
1039 "### To run just the utility tests type: intltest utility \n"
1041 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1042 "### For example to list the utility tests type: intltest utility/LIST \n"
1043 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1045 "### A parameter can be specified for a test by appending '@' and the value \n"
1046 "### to the testname. \n\n");
1050 UBool all_tests_exist
= TRUE
;
1051 MajorTestLevel major
;
1052 major
.setVerbose( verbose
);
1053 major
.setNoErrMsg( no_err_msg
);
1054 major
.setQuick( quick
);
1055 major
.setLeaks( leaks
);
1056 major
.setWarnOnMissingData( warnOnMissingData
);
1057 fprintf(stdout
, "-----------------------------------------------\n");
1058 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1059 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1060 fprintf(stdout
, "-----------------------------------------------\n");
1061 fprintf(stdout
, " Options: \n");
1062 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1063 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1064 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1065 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1066 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1067 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1068 fprintf(stdout
, "-----------------------------------------------\n");
1070 /* Check whether ICU will initialize without forcing the build data directory into
1071 * the ICU_DATA path. Success here means either the data dll contains data, or that
1072 * this test program was run with ICU_DATA set externally. Failure of this check
1073 * is normal when ICU data is not packaged into a shared library.
1075 * Whether or not this test succeeds, we want to cleanup and reinitialize
1076 * with a data path so that data loading from individual files can be tested.
1079 if (U_FAILURE(errorCode
)) {
1081 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1082 defaultDataFound
= FALSE
;
1085 defaultDataFound
= TRUE
;
1088 errorCode
= U_ZERO_ERROR
;
1090 /* Initialize ICU */
1091 if (!defaultDataFound
) {
1092 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1095 if (U_FAILURE(errorCode
)) {
1097 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1098 "*** Check the ICU_DATA environment variable and \n"
1099 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1100 if(warnOnMissingData
== 0) {
1101 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1108 // initial check for the default converter
1109 errorCode
= U_ZERO_ERROR
;
1110 cnv
= ucnv_open(0, &errorCode
);
1116 "*** %s! The default converter [%s] cannot be opened.\n"
1117 "*** Check the ICU_DATA environment variable and\n"
1118 "*** check that the data files are present.\n",
1119 warnOrErr
, ucnv_getDefaultName());
1120 if(!warnOnMissingData
) {
1121 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1127 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1133 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1134 "*** Check the ICU_DATA environment variable and \n"
1135 "*** check that the data files are present.\n", warnOrErr
);
1136 if(!warnOnMissingData
) {
1137 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1142 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1144 if(U_FAILURE(errorCode
)) {
1146 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1147 "*** Check the ICU_DATA environment variable and \n"
1148 "*** check that the data files are present.\n", warnOrErr
);
1149 if(!warnOnMissingData
) {
1150 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1155 Locale originalLocale
; // Save the default locale for comparison later on.
1157 /* TODO: Add option to call u_cleanup and rerun tests. */
1161 major
.run_phase2( NULL
, NULL
);
1164 for (int i
= 1; i
< argc
; ++i
) {
1165 if (argv
[i
][0] != '-') {
1166 char* name
= argv
[i
];
1167 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1168 char* parameter
= strchr( name
, '@' );
1174 UBool res
= major
.runTest( name
, parameter
);
1176 major
.run_phase2( name
, parameter
);
1178 if (!res
|| (execCount
<= 0)) {
1179 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1180 all_tests_exist
= FALSE
;
1186 #if !UCONFIG_NO_FORMATTING
1187 CalendarTimeZoneTest::cleanup();
1190 free(_testDataPath
);
1193 Locale lastDefaultLocale
;
1194 if (originalLocale
!= lastDefaultLocale
) {
1195 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1198 fprintf(stdout
, "\n--------------------------------------\n");
1199 if (major
.getErrors() == 0) {
1200 /* Call it twice to make sure that the defaults were reset. */
1201 /* Call it before the OK message to verify proper cleanup. */
1205 fprintf(stdout
, "OK: All tests passed without error.\n");
1207 if (major
.getDataErrors() != 0) {
1208 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1211 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1212 major
.printErrors();
1215 if (major
.getDataErrors() != 0) {
1216 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1217 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1218 "\tthe '-w' option to turn these errors into warnings.\n");
1221 /* Call afterwards to display errors. */
1225 fprintf(stdout
, "--------------------------------------\n");
1227 if (execCount
<= 0) {
1228 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1230 endTime
= uprv_getUTCtime();
1231 diffTime
= (int32_t)(endTime
- startTime
);
1232 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1233 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1234 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1235 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1236 (int)(diffTime%U_MILLIS_PER_SECOND
));
1237 return major
.getErrors();
1240 const char* IntlTest::loadTestData(UErrorCode
& err
){
1241 if( _testDataPath
== NULL
){
1242 const char* directory
=NULL
;
1243 UResourceBundle
* test
=NULL
;
1245 const char* tdrelativepath
;
1247 #if defined (U_TOPBUILDDIR)
1248 tdrelativepath
= "test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1249 directory
= U_TOPBUILDDIR
;
1251 tdrelativepath
= ".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1252 directory
= pathToDataDirectory();
1255 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1258 /* u_getDataDirectory shoul return \source\data ... set the
1259 * directory to ..\source\data\..\test\testdata\out\testdata
1261 strcpy(tdpath
, directory
);
1262 strcat(tdpath
, tdrelativepath
);
1263 strcat(tdpath
,"testdata");
1265 test
=ures_open(tdpath
, "testtypes", &err
);
1268 err
= U_FILE_ACCESS_ERROR
;
1269 it_dataerrln((UnicodeString
)"[DATA] Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1273 _testDataPath
= tdpath
;
1274 return _testDataPath
;
1276 return _testDataPath
;
1279 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1280 return loadTestData(err
);
1283 /* Returns the path to icu/source/test/testdata/ */
1284 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1285 const char *srcDataDir
= NULL
;
1287 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1289 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1290 FILE *f
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"rbbitst.txt", "r");
1292 /* We're in icu/source/test/intltest/ */
1296 /* We're in icu/source/test/intltest/(Debug|Release) */
1297 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1303 const char* IntlTest::fgDataDir
= NULL
;
1305 /* returns the path to icu/source/data */
1306 const char * IntlTest::pathToDataDirectory()
1309 if(fgDataDir
!= NULL
) {
1313 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1314 // to point to the top of the build hierarchy, which may or
1315 // may not be the same as the source directory, depending on
1316 // the configure options used. At any rate,
1317 // set the data path to the built data from this directory.
1318 // The value is complete with quotes, so it can be used
1319 // as-is as a string constant.
1321 #if defined (U_TOPSRCDIR)
1323 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1327 /* On Windows, the file name obtained from __FILE__ includes a full path.
1328 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1329 * Change to "wherever\icu\source\data"
1332 static char p
[sizeof(__FILE__
) + 10];
1336 strcpy(p
, __FILE__
);
1337 /* We want to back over three '\' chars. */
1338 /* Only Windows should end up here, so looking for '\' is safe. */
1339 for (i
=1; i
<=3; i
++) {
1340 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1341 if (pBackSlash
!= NULL
) {
1342 *pBackSlash
= 0; /* Truncate the string at the '\' */
1346 if (pBackSlash
!= NULL
) {
1347 /* We found and truncated three names from the path.
1348 * Now append "source\data" and set the environment
1350 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1354 /* __FILE__ on MSVC7 does not contain the directory */
1355 FILE *file
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1358 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1361 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1372 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1373 * It converts a character string into a UnicodeString, with
1374 * unescaping \u sequences.
1376 UnicodeString
CharsToUnicodeString(const char* chars
)
1378 UnicodeString
str(chars
, ""); // Invariant conversion
1379 return str
.unescape();
1382 UnicodeString
ctou(const char* chars
) {
1383 return CharsToUnicodeString(chars
);
1386 #define RAND_M (714025)
1387 #define RAND_IA (1366)
1388 #define RAND_IC (150889)
1390 static int32_t RAND_SEED
;
1393 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1394 * with care: Does not return all possible values; returns one of
1395 * 714,025 values, uniformly spaced. However, the period is
1396 * effectively infinite. See: Numerical Recipes, section 7.1.
1398 * @param seedp pointer to seed. Set *seedp to any negative value
1399 * to restart the sequence.
1401 float IntlTest::random(int32_t* seedp
) {
1402 static int32_t iy
, ir
[98];
1403 static UBool first
=TRUE
;
1405 if (*seedp
< 0 || first
) {
1407 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1408 for (j
=1;j
<=97;++j
) {
1409 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1412 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1415 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1416 U_ASSERT(j
>=1 && j
<=97);
1418 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1420 return (float) iy
/RAND_M
;
1424 * Convenience method using a global seed.
1426 float IntlTest::random() {
1427 return random(&RAND_SEED
);
1430 static inline UChar
toHex(int32_t i
) {
1431 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1434 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1435 for (int32_t i
=0; i
<s
.length(); ++i
) {
1437 if (c
<= (UChar
)0x7F) {
1440 result
+= (UChar
)0x5c;
1441 result
+= (UChar
)0x75;
1442 result
+= toHex((c
>> 12) & 0xF);
1443 result
+= toHex((c
>> 8) & 0xF);
1444 result
+= toHex((c
>> 4) & 0xF);
1445 result
+= toHex( c
& 0xF);
1451 #define VERBOSE_ASSERTIONS
1453 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
) {
1455 errln("FAIL: assertTrue() failed: %s", message
);
1456 } else if (!quiet
) {
1457 logln("Ok: %s", message
);
1462 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1464 errln("FAIL: assertFalse() failed: %s", message
);
1465 } else if (!quiet
) {
1466 logln("Ok: %s", message
);
1471 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
) {
1472 if (U_FAILURE(ec
)) {
1473 if (ec
== U_FILE_ACCESS_ERROR
) {
1474 dataerrln("[DATA] Fail: %s.", message
);
1476 errln("FAIL: %s (%s)", message
, u_errorName(ec
));
1483 UBool
IntlTest::assertEquals(const char* message
,
1484 const UnicodeString
& expected
,
1485 const UnicodeString
& actual
) {
1486 if (expected
!= actual
) {
1487 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1489 "; expected " + prettify(expected
));
1492 #ifdef VERBOSE_ASSERTIONS
1494 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1500 UBool
IntlTest::assertEquals(const char* message
,
1501 const char* expected
,
1502 const char* actual
) {
1503 if (uprv_strcmp(expected
, actual
) != 0) {
1504 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1506 "\"; expected \"" + expected
+ "\"");
1509 #ifdef VERBOSE_ASSERTIONS
1511 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1517 #if !UCONFIG_NO_FORMATTING
1518 UBool
IntlTest::assertEquals(const char* message
,
1519 const Formattable
& expected
,
1520 const Formattable
& actual
) {
1521 if (expected
!= actual
) {
1522 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1524 "; expected " + toString(expected
));
1527 #ifdef VERBOSE_ASSERTIONS
1529 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
1536 static char ASSERT_BUF
[256];
1538 static const char* extractToAssertBuf(const UnicodeString
& message
) {
1540 escape(message
, buf
);
1541 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
1542 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
1546 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1547 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
1550 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1551 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
1554 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
1555 return assertSuccess(extractToAssertBuf(message
), ec
);
1558 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1559 const UnicodeString
& expected
,
1560 const UnicodeString
& actual
) {
1561 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1564 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1565 const char* expected
,
1566 const char* actual
) {
1567 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1569 //--------------------------------------------------------------------
1570 // Time bomb - allows temporary behavior that expires at a given
1572 //--------------------------------------------------------------------
1574 UBool
IntlTest::isICUVersionAtLeast(const UVersionInfo x
) {
1577 return (uprv_memcmp(v
, x
, U_MAX_VERSION_LENGTH
) >= 0);
1580 #if !UCONFIG_NO_FORMATTING
1581 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1582 const Formattable
& expected
,
1583 const Formattable
& actual
) {
1584 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1589 * Hey, Emacs, please set the following:
1592 * indent-tabs-mode: nil