1 /********************************************************************
3 * Copyright (c) 1997-2004, 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"
43 static char* _testDataPath
=NULL
;
45 // Static list of errors found
46 static UnicodeString errorList
;
48 //-----------------------------------------------------------------------------
49 //convenience classes to ease porting code that uses the Java
50 //string-concatenation operator (moved from findword test by rtg)
52 // [LIU] Just to get things working
54 UCharToUnicodeString(UChar c
)
55 { return UnicodeString(c
); }
57 // [rtg] Just to get things working
59 operator+(const UnicodeString
& left
,
62 char buffer
[64]; // nos changed from 10 to 64
63 char danger
= 'p'; // guard against overrunning the buffer (rtg)
65 sprintf(buffer
, "%ld", num
);
66 assert(danger
== 'p');
72 operator+(const UnicodeString
& left
,
75 char buffer
[64]; // nos changed from 10 to 64
76 char danger
= 'p'; // guard against overrunning the buffer (rtg)
78 sprintf(buffer
, "%lu", num
);
79 assert(danger
== 'p');
85 Int64ToUnicodeString(int64_t num
)
87 char buffer
[64]; // nos changed from 10 to 64
88 char danger
= 'p'; // guard against overrunning the buffer (rtg)
91 sprintf(buffer
, "%I64d", num
);
93 sprintf(buffer
, "%lld", num
);
95 assert(danger
== 'p');
100 // [LIU] Just to get things working
102 operator+(const UnicodeString
& left
,
105 char buffer
[64]; // was 32, made it arbitrarily bigger (rtg)
106 char danger
= 'p'; // guard against overrunning the buffer (rtg)
108 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
109 // 53*log(2)/log(10) = 15.95
110 // so there is no need to show more than 16 digits. [alan]
112 sprintf(buffer
, "%.16g", num
);
113 assert(danger
== 'p');
115 return left
+ buffer
;
118 #if !UCONFIG_NO_FORMATTING
121 * Return a string display for for this, without surrounding braces.
123 UnicodeString
_toString(const Formattable
& f
) {
125 switch (f
.getType()) {
126 case Formattable::kDate
:
128 UErrorCode status
= U_ZERO_ERROR
;
129 SimpleDateFormat
fmt(status
);
130 if (U_SUCCESS(status
)) {
132 fmt
.format(f
.getDate(), s
, pos
);
133 s
.insert(0, "Date:");
135 s
= UnicodeString("Error creating date format]");
139 case Formattable::kDouble
:
140 s
= UnicodeString("double:") + f
.getDouble();
142 case Formattable::kLong
:
143 s
= UnicodeString("long:") + f
.getLong();
146 case Formattable::kInt64
:
147 s
= UnicodeString("int64:") + Int64ToUnicodeString(f
.getInt64());
150 case Formattable::kString
:
152 s
.insert(0, "String:");
154 case Formattable::kArray
:
157 const Formattable
* array
= f
.getArray(n
);
158 s
.insert(0, UnicodeString("Array:"));
159 UnicodeString
delim(", ");
160 for (i
=0; i
<n
; ++i
) {
164 s
= s
+ _toString(array
[i
]);
168 case Formattable::kObject
:
169 if (f
.getObject()->getDynamicClassID() ==
170 CurrencyAmount::getStaticClassID()) {
171 const CurrencyAmount
& c
= (const CurrencyAmount
&) *f
.getObject();
172 s
= _toString(c
.getNumber()) + " " + UnicodeString(c
.getISOCurrency());
174 s
= UnicodeString("Unknown UObject");
178 s
= UnicodeString("Unknown Formattable type=") + (int32_t)f
.getType();
185 * Originally coded this as operator+, but that makes the expression
186 * + char* ambiguous. - liu
188 UnicodeString
toString(const Formattable
& f
) {
189 UnicodeString
s((UChar
)91/*[*/);
190 s
.append(_toString(f
));
191 s
.append((UChar
)0x5d/*]*/);
197 // useful when operator+ won't cooperate
198 UnicodeString
toString(int32_t n
) {
199 return UnicodeString() + (long)n
;
202 // stephen - cleaned up 05/05/99
203 UnicodeString
operator+(const UnicodeString
& left
, char num
)
204 { return left
+ (long)num
; }
205 UnicodeString
operator+(const UnicodeString
& left
, short num
)
206 { return left
+ (long)num
; }
207 UnicodeString
operator+(const UnicodeString
& left
, int num
)
208 { return left
+ (long)num
; }
209 UnicodeString
operator+(const UnicodeString
& left
, unsigned char num
)
210 { return left
+ (unsigned long)num
; }
211 UnicodeString
operator+(const UnicodeString
& left
, unsigned short num
)
212 { return left
+ (unsigned long)num
; }
213 UnicodeString
operator+(const UnicodeString
& left
, unsigned int num
)
214 { return left
+ (unsigned long)num
; }
215 UnicodeString
operator+(const UnicodeString
& left
, float num
)
216 { return left
+ (double)num
; }
220 // Append a hex string to the target
222 IntlTest::appendHex(uint32_t number
,
224 UnicodeString
& target
)
226 static const UChar digitString
[] = {
227 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
228 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
229 }; /* "0123456789ABCDEF" */
234 target
+= digitString
[(number
>> 28) & 0xF];
236 target
+= digitString
[(number
>> 24) & 0xF];
238 target
+= digitString
[(number
>> 20) & 0xF];
240 target
+= digitString
[(number
>> 16) & 0xF];
242 target
+= digitString
[(number
>> 12) & 0xF];
244 target
+= digitString
[(number
>> 8) & 0xF];
246 target
+= digitString
[(number
>> 4) & 0xF];
248 target
+= digitString
[(number
>> 0) & 0xF];
256 // Replace nonprintable characters with unicode escapes
258 IntlTest::prettify(const UnicodeString
&source
,
259 UnicodeString
&target
)
266 for (i
= 0; i
< source
.length(); )
268 UChar32 ch
= source
.char32At(i
);
269 i
+= UTF_CHAR_LENGTH(ch
);
271 if (ch
< 0x09 || (ch
> 0x0A && ch
< 0x20)|| ch
> 0x7E)
275 appendHex(ch
, 4, target
);
278 appendHex(ch
, 8, target
);
292 // Replace nonprintable characters with unicode escapes
294 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
297 UnicodeString target
;
301 for (i
= 0; i
< source
.length();)
303 UChar32 ch
= source
.char32At(i
);
304 i
+= UTF_CHAR_LENGTH(ch
);
306 if (ch
< 0x09 || (ch
> 0x0A && ch
< 0x20)|| ch
> 0x7E)
308 if (parseBackslash
) {
309 // If we are preceded by an odd number of backslashes,
310 // then this character has already been backslash escaped.
311 // Delete a backslash.
312 int32_t backslashCount
= 0;
313 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
314 if (target
.charAt(j
) == (UChar
)92) {
320 if ((backslashCount
% 2) == 1) {
321 target
.truncate(target
.length() - 1);
326 appendHex(ch
, 4, target
);
329 appendHex(ch
, 8, target
);
343 #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) || defined(OS2)
344 #define PREV_DIR ".."
346 #define PREV_DIR "/../"
350 IntlTest::pathnameInContext( char* fullname
, int32_t maxsize
, const char* relPath
) //nosmac
354 const char inpSepChar
= '|';
356 // So what's going on is that ICU_DATA during tests points to:
357 // ICU | source | data
358 //and we want ICU | source |
360 // We'll add | test | testdata
362 // So, just add a .. here - back up one level
364 mainDir
= u_getDataDirectory();
365 sepChar
= U_FILE_SEP_CHAR
;
366 char sepString
[] = U_FILE_SEP_STRING
;
371 OSErr err
= GetVol( volName
, &volNum
);
374 mainDir
= (char*) &(volName
[1]);
375 mainDir
[volName
[0]] = 0;
377 char mainDirBuffer
[255];
379 strcpy(mainDirBuffer
, mainDir
);
380 strcat(mainDirBuffer
, PREV_DIR
);
382 mainDirBuffer
[0]='\0';
384 mainDir
=mainDirBuffer
;
387 if (relPath
[0] == '|')
389 int32_t lenMainDir
= strlen(mainDir
);
390 int32_t lenRelPath
= strlen(relPath
);
391 if (maxsize
< lenMainDir
+ lenRelPath
+ 2) {
395 strcpy(fullname
, mainDir
);
396 strcat(fullname
, sepString
);
397 strcat(fullname
, relPath
);
398 char* tmp
= strchr(fullname
, inpSepChar
);
401 tmp
= strchr(tmp
+1, inpSepChar
);
405 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
406 * set, try to deduce the directory in which ICU was built,
407 * and set ICU_DATA to "icu/source/data" in that location.
408 * The intent is to allow the tests to have a good chance
409 * of running without requiring that the user manually set
410 * ICU_DATA. Common data isn't a problem, since it is
411 * picked up via a static (build time) reference, but the
412 * tests dynamically load some data.
414 void IntlTest::setICU_DATA() {
415 const char *original_ICU_DATA
= getenv("ICU_DATA");
417 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
418 /* If the user set ICU_DATA, don't second-guess the person. */
422 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
423 // to point to the top of the build hierarchy, which may or
424 // may not be the same as the source directory, depending on
425 // the configure options used. At any rate,
426 // set the data path to the built data from this directory.
427 // The value is complete with quotes, so it can be used
428 // as-is as a string constant.
430 #if defined (U_TOPBUILDDIR)
432 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
433 u_setDataDirectory(env_string
);
438 // Use #else so we don't get compiler warnings due to the return above.
440 /* On Windows, the file name obtained from __FILE__ includes a full path.
441 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
442 * Change to "wherever\icu\source\data"
445 char p
[sizeof(__FILE__
) + 10];
450 /* We want to back over three '\' chars. */
451 /* Only Windows should end up here, so looking for '\' is safe. */
452 for (i
=1; i
<=3; i
++) {
453 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
454 if (pBackSlash
!= NULL
) {
455 *pBackSlash
= 0; /* Truncate the string at the '\' */
459 if (pBackSlash
!= NULL
) {
460 /* We found and truncated three names from the path.
461 * Now append "source\data" and set the environment
463 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
464 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
468 /* __FILE__ on MSVC7 does not contain the directory */
469 u_setDataDirectory(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
475 /* No location for the data dir was identifiable.
476 * Add other fallbacks for the test data location here if the need arises
481 //--------------------------------------------------------------------------------------
483 static const int32_t indentLevel_offset
= 3;
484 static const char delim
= '/';
486 IntlTest
* IntlTest::gTest
= NULL
;
488 static int32_t execCount
= 0;
490 void it_log( UnicodeString message
)
493 IntlTest::gTest
->log( message
);
496 void it_logln( UnicodeString message
)
499 IntlTest::gTest
->logln( message
);
502 void it_logln( void )
505 IntlTest::gTest
->logln();
508 void it_info( UnicodeString message
)
511 IntlTest::gTest
->info( message
);
514 void it_infoln( UnicodeString message
)
517 IntlTest::gTest
->infoln( message
);
520 void it_infoln( void )
523 IntlTest::gTest
->infoln();
529 IntlTest::gTest
->err();
532 void it_err( UnicodeString message
)
535 IntlTest::gTest
->err( message
);
538 void it_errln( UnicodeString message
)
541 IntlTest::gTest
->errln( message
);
556 LL_indentlevel
= indentLevel_offset
;
559 void IntlTest::setCaller( IntlTest
* callingTest
)
561 caller
= callingTest
;
563 verbose
= caller
->verbose
;
564 no_err_msg
= caller
->no_err_msg
;
565 quick
= caller
->quick
;
566 testoutfp
= caller
->testoutfp
;
567 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
571 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
573 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
574 testToBeCalled
.setCaller( this );
575 return testToBeCalled
.runTest( path
, par
);
578 void IntlTest::setPath( char* pathVal
)
580 this->path
= pathVal
;
583 UBool
IntlTest::setVerbose( UBool verboseVal
)
585 UBool rval
= this->verbose
;
586 this->verbose
= verboseVal
;
590 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
592 UBool rval
= this->no_err_msg
;
593 this->no_err_msg
= no_err_msgVal
;
597 UBool
IntlTest::setQuick( UBool quickVal
)
599 UBool rval
= this->quick
;
600 this->quick
= quickVal
;
604 UBool
IntlTest::setLeaks( UBool leaksVal
)
606 UBool rval
= this->leaks
;
607 this->leaks
= leaksVal
;
611 int32_t IntlTest::getErrors( void )
616 UBool
IntlTest::runTest( char* name
, char* par
)
622 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
624 path
= pos
+1; // store subpath for calling subtest
625 *pos
= 0; // split into two strings
630 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
631 rval
= runTestLoop( NULL
, par
);
633 }else if (strcmp( name
, "LIST" ) == 0) {
638 rval
= runTestLoop( name
, par
);
642 *pos
= delim
; // restore original value at pos
646 // call individual tests, to be overriden to call implementations
647 void IntlTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* par
)
649 // to be overriden by a method like:
652 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
653 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
654 default: name = ""; break;
657 this->errln("*** runIndexedTest needs to be overriden! ***");
658 name
= ""; exec
= exec
; index
= index
; par
= par
;
662 UBool
IntlTest::runTestLoop( char* testname
, char* par
)
667 int32_t lastErrorCount
;
669 UBool lastTestFailed
;
671 IntlTest
* saveTest
= gTest
;
674 this->runIndexedTest( index
, FALSE
, name
, par
);
675 if (!name
|| (name
[0] == 0))
678 run_this_test
= TRUE
;
680 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
683 lastErrorCount
= errorCount
;
685 this->runIndexedTest( index
, TRUE
, name
, par
);
686 rval
= TRUE
; // at least one test has been called
688 if (lastErrorCount
== errorCount
) {
689 sprintf( msg
, "---OK: %s", name
);
690 lastTestFailed
= FALSE
;
692 sprintf(msg
, "---ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
694 for(int i
=0;i
<LL_indentlevel
;i
++) {
699 lastTestFailed
= TRUE
;
702 if (lastTestFailed
) {
703 LL_message( "", TRUE
);
705 LL_message( msg
, TRUE
);
706 if (lastTestFailed
) {
707 LL_message( "", TRUE
);
720 * Adds given string to the log if we are in verbose mode.
722 void IntlTest::log( const UnicodeString
&message
)
725 LL_message( message
, FALSE
);
730 * Adds given string to the log if we are in verbose mode. Adds a new line to
733 void IntlTest::logln( const UnicodeString
&message
)
736 LL_message( message
, TRUE
);
740 void IntlTest::logln( void )
743 LL_message( "", TRUE
);
748 * Unconditionally adds given string to the log.
750 void IntlTest::info( const UnicodeString
&message
)
752 LL_message( message
, FALSE
);
756 * Unconditionally adds given string to the log. Adds a new line to
759 void IntlTest::infoln( const UnicodeString
&message
)
761 LL_message( message
, TRUE
);
764 void IntlTest::infoln( void )
766 LL_message( "", TRUE
);
769 int32_t IntlTest::IncErrorCount( void )
772 if (caller
) caller
->IncErrorCount();
776 void IntlTest::err() {
780 void IntlTest::err( const UnicodeString
&message
)
783 if (!no_err_msg
) LL_message( message
, FALSE
);
786 void IntlTest::errln( const UnicodeString
&message
)
789 if (!no_err_msg
) LL_message( message
, TRUE
);
792 /* convenience functions that include sprintf formatting */
793 void IntlTest::log(const char *fmt
, ...)
799 /* sprintf it just to make sure that the information is valid */
800 vsprintf(buffer
, fmt
, ap
);
803 log(UnicodeString(buffer
, ""));
807 void IntlTest::logln(const char *fmt
, ...)
813 /* sprintf it just to make sure that the information is valid */
814 vsprintf(buffer
, fmt
, ap
);
817 logln(UnicodeString(buffer
, ""));
821 /* convenience functions that include sprintf formatting */
822 void IntlTest::info(const char *fmt
, ...)
828 /* sprintf it just to make sure that the information is valid */
829 vsprintf(buffer
, fmt
, ap
);
831 info(UnicodeString(buffer
, ""));
834 void IntlTest::infoln(const char *fmt
, ...)
840 /* sprintf it just to make sure that the information is valid */
841 vsprintf(buffer
, fmt
, ap
);
843 infoln(UnicodeString(buffer
, ""));
846 void IntlTest::err(const char *fmt
, ...)
852 vsprintf(buffer
, fmt
, ap
);
854 err(UnicodeString(buffer
, ""));
857 void IntlTest::errln(const char *fmt
, ...)
863 vsprintf(buffer
, fmt
, ap
);
865 errln(UnicodeString(buffer
, ""));
868 void IntlTest::printErrors()
870 IntlTest::LL_message(errorList
, TRUE
);
873 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
875 // string that starts with a LineFeed character and continues
876 // with spaces according to the current indentation
877 static const UChar indentUChars
[] = {
879 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
880 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
881 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
882 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
883 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
884 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
885 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
886 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
887 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
888 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
890 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
895 // stream out the indentation string first if necessary
896 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
898 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
901 // replace each LineFeed by the indentation string
902 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
904 // stream out the message
905 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
907 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
912 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
915 // A newline usually flushes the buffer, but
916 // flush the message just in case of a core dump.
917 fflush((FILE *)testoutfp
);
921 * Print a usage message for this test class.
923 void IntlTest::usage( void )
925 UBool save_verbose
= setVerbose( TRUE
);
926 logln("Test names:");
927 logln("-----------");
930 const char* name
= NULL
;
932 this->runIndexedTest( index
, FALSE
, name
);
936 }while (name
&& (name
[0] != 0));
937 setVerbose( save_verbose
);
941 // memory leak reporting software will be able to take advantage of the testsuite
942 // being run a second time local to a specific method in order to report only actual leaks
944 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
946 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
947 strLeak
->append(" for verifying purify filter");
948 return this->runTest( name
, par
);
952 #if UCONFIG_NO_LEGACY_CONVERSION
953 # define TRY_CNV_1 "iso-8859-1"
954 # define TRY_CNV_2 "ibm-1208"
956 # define TRY_CNV_1 "iso-8859-7"
957 # define TRY_CNV_2 "sjis"
961 main(int argc
, char* argv
[])
963 UBool syntax
= FALSE
;
965 UBool verbose
= FALSE
;
966 UBool no_err_msg
= FALSE
;
970 UBool warnOnMissingData
= FALSE
;
971 UErrorCode errorCode
= U_ZERO_ERROR
;
972 UConverter
*cnv
= NULL
;
973 const char *warnOrErr
= "Failure";
975 #ifdef XP_MAC_CONSOLE
976 argc
= ccommand( &argv
);
980 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
982 if (U_FAILURE(errorCode
)) {
984 "#### %s: u_init() failed, error is \"%s\".\n"
985 "#### Most commonly indicates that the ICU data is not accesible.\n"
986 "#### Check setting of ICU_DATA, or check that ICU data library is available\n"
987 "#### ICU_DATA is currently set to \"%s\"\n", argv
[0], u_errorName(errorCode
), u_getDataDirectory());
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 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
, "-----------------------------------------------\n");
1068 // Check that u_init() works
1069 errorCode
= U_ZERO_ERROR
;
1071 if (U_FAILURE(errorCode
)) {
1073 "*** u_init() failed with error code = %s\n"
1074 "*** Check the ICU_DATA environment variable and\n"
1075 "*** check that the data files are present.\n",
1076 u_errorName(errorCode
));
1077 if(!warnOnMissingData
) {
1078 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1084 // initial check for the default converter
1085 errorCode
= U_ZERO_ERROR
;
1086 cnv
= ucnv_open(0, &errorCode
);
1092 "*** %s! The default converter [%s] cannot be opened.\n"
1093 "*** Check the ICU_DATA environment variable and\n"
1094 "*** check that the data files are present.\n",
1095 warnOrErr
, ucnv_getDefaultName());
1096 if(!warnOnMissingData
) {
1097 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1103 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1109 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1110 "*** Check the ICU_DATA environment variable and \n"
1111 "*** check that the data files are present.\n", warnOrErr
);
1112 if(!warnOnMissingData
) {
1113 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1118 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1120 if(U_FAILURE(errorCode
)) {
1122 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1123 "*** Check the ICU_DATA environment variable and \n"
1124 "*** check that the data files are present.\n", warnOrErr
);
1125 if(!warnOnMissingData
) {
1126 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1131 /* TODO: Add option to call u_cleanup and rerun tests. */
1135 major
.run_phase2( NULL
, NULL
);
1138 for (int i
= 1; i
< argc
; ++i
) {
1139 if (argv
[i
][0] != '-') {
1140 char* name
= argv
[i
];
1141 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1142 char* parameter
= strchr( name
, '@' );
1148 UBool res
= major
.runTest( name
, parameter
);
1150 major
.run_phase2( name
, parameter
);
1152 if (!res
|| (execCount
<= 0)) {
1153 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1154 all_tests_exist
= FALSE
;
1160 #if !UCONFIG_NO_FORMATTING
1161 CalendarTimeZoneTest::cleanup();
1164 free(_testDataPath
);
1167 fprintf(stdout
, "\n--------------------------------------\n");
1168 if (major
.getErrors() == 0) {
1169 /* Call it twice to make sure that the defaults were reset. */
1170 /* Call it before the OK message to verify proper cleanup. */
1174 fprintf(stdout
, "OK: All tests passed without error.\n");
1176 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1177 major
.printErrors();
1179 /* Call afterwards to display errors. */
1183 fprintf(stdout
, "--------------------------------------\n");
1185 if (execCount
<= 0) {
1186 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1188 return major
.getErrors();
1191 const char* IntlTest::loadTestData(UErrorCode
& err
){
1192 if( _testDataPath
== NULL
){
1193 const char* directory
=NULL
;
1194 UResourceBundle
* test
=NULL
;
1196 const char* tdrelativepath
;
1198 #if defined (U_TOPBUILDDIR)
1199 tdrelativepath
= "test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1200 directory
= U_TOPBUILDDIR
;
1202 tdrelativepath
= ".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1203 directory
= pathToDataDirectory();
1206 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1209 /* u_getDataDirectory shoul return \source\data ... set the
1210 * directory to ..\source\data\..\test\testdata\out\testdata
1212 strcpy(tdpath
, directory
);
1213 strcat(tdpath
, tdrelativepath
);
1214 strcat(tdpath
,"testdata");
1216 test
=ures_open(tdpath
, "testtypes", &err
);
1219 err
= U_FILE_ACCESS_ERROR
;
1220 it_errln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1224 _testDataPath
= tdpath
;
1225 return _testDataPath
;
1227 return _testDataPath
;
1230 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1231 return loadTestData(err
);
1234 /* Returns the path to icu/source/test/testdata/ */
1235 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1236 const char *srcDataDir
= NULL
;
1238 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1240 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1241 FILE *f
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"rbbitst.txt", "r");
1243 /* We're in icu/source/test/intltest/ */
1247 /* We're in icu/source/test/intltest/(Debug|Release) */
1248 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1254 const char* IntlTest::fgDataDir
= NULL
;
1256 /* returns the path to icu/source/data */
1257 const char * IntlTest::pathToDataDirectory()
1260 if(fgDataDir
!= NULL
) {
1264 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1265 // to point to the top of the build hierarchy, which may or
1266 // may not be the same as the source directory, depending on
1267 // the configure options used. At any rate,
1268 // set the data path to the built data from this directory.
1269 // The value is complete with quotes, so it can be used
1270 // as-is as a string constant.
1272 #if defined (U_TOPSRCDIR)
1274 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1278 /* On Windows, the file name obtained from __FILE__ includes a full path.
1279 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1280 * Change to "wherever\icu\source\data"
1283 static char p
[sizeof(__FILE__
) + 10];
1287 strcpy(p
, __FILE__
);
1288 /* We want to back over three '\' chars. */
1289 /* Only Windows should end up here, so looking for '\' is safe. */
1290 for (i
=1; i
<=3; i
++) {
1291 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1292 if (pBackSlash
!= NULL
) {
1293 *pBackSlash
= 0; /* Truncate the string at the '\' */
1297 if (pBackSlash
!= NULL
) {
1298 /* We found and truncated three names from the path.
1299 * Now append "source\data" and set the environment
1301 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1305 /* __FILE__ on MSVC7 does not contain the directory */
1306 FILE *file
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1309 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1312 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1323 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1324 * It converts a character string into a UnicodeString, with
1325 * unescaping \u sequences.
1327 UnicodeString
CharsToUnicodeString(const char* chars
)
1329 UnicodeString
str(chars
, ""); // Invariant conversion
1330 return str
.unescape();
1333 UnicodeString
ctou(const char* chars
) {
1334 return CharsToUnicodeString(chars
);
1337 #define RAND_M (714025)
1338 #define RAND_IA (1366)
1339 #define RAND_IC (150889)
1341 static int32_t RAND_SEED
;
1344 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1345 * with care: Does not return all possible values; returns one of
1346 * 714,025 values, uniformly spaced. However, the period is
1347 * effectively infinite. See: Numerical Recipes, section 7.1.
1349 * @param seedp pointer to seed. Set *seedp to any negative value
1350 * to restart the sequence.
1352 float IntlTest::random(int32_t* seedp
) {
1353 static int32_t iy
, ir
[98];
1354 static UBool first
=TRUE
;
1356 if (*seedp
< 0 || first
) {
1358 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1359 for (j
=1;j
<=97;++j
) {
1360 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1363 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1366 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1367 U_ASSERT(j
>=1 && j
<=97);
1369 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1371 return (float) iy
/RAND_M
;
1375 * Convenience method using a global seed.
1377 float IntlTest::random() {
1378 return random(&RAND_SEED
);
1381 static inline UChar
toHex(int32_t i
) {
1382 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1385 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1386 for (int32_t i
=0; i
<s
.length(); ++i
) {
1388 if (c
<= (UChar
)0x7F) {
1391 result
+= (UChar
)0x5c;
1392 result
+= (UChar
)0x75;
1393 result
+= toHex((c
>> 12) & 0xF);
1394 result
+= toHex((c
>> 8) & 0xF);
1395 result
+= toHex((c
>> 4) & 0xF);
1396 result
+= toHex( c
& 0xF);
1402 #define VERBOSE_ASSERTIONS
1404 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
) {
1406 errln("FAIL: assertTrue() failed: %s", message
);
1407 } else if (!quiet
) {
1408 logln("Ok: %s", message
);
1413 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1415 errln("FAIL: assertFalse() failed: %s", message
);
1416 } else if (!quiet
) {
1417 logln("Ok: %s", message
);
1422 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
) {
1423 if (U_FAILURE(ec
)) {
1424 errln("FAIL: %s (%s)", message
, u_errorName(ec
));
1430 UBool
IntlTest::assertEquals(const char* message
,
1431 const UnicodeString
& expected
,
1432 const UnicodeString
& actual
) {
1433 if (expected
!= actual
) {
1434 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1436 "; expected " + prettify(expected
));
1439 #ifdef VERBOSE_ASSERTIONS
1441 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1447 UBool
IntlTest::assertEquals(const char* message
,
1448 const char* expected
,
1449 const char* actual
) {
1450 if (uprv_strcmp(expected
, actual
) != 0) {
1451 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1453 "\"; expected \"" + expected
+ "\"");
1456 #ifdef VERBOSE_ASSERTIONS
1458 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1464 #if !UCONFIG_NO_FORMATTING
1465 UBool
IntlTest::assertEquals(const char* message
,
1466 const Formattable
& expected
,
1467 const Formattable
& actual
) {
1468 if (expected
!= actual
) {
1469 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1471 "; expected " + toString(expected
));
1474 #ifdef VERBOSE_ASSERTIONS
1476 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
1483 static char ASSERT_BUF
[256];
1485 static const char* extractToAssertBuf(const UnicodeString
& message
) {
1487 escape(message
, buf
);
1488 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
1489 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
1493 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1494 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
1497 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1498 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
1501 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
1502 return assertSuccess(extractToAssertBuf(message
), ec
);
1505 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1506 const UnicodeString
& expected
,
1507 const UnicodeString
& actual
) {
1508 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1511 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1512 const char* expected
,
1513 const char* actual
) {
1514 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1516 //--------------------------------------------------------------------
1517 // Time bomb - allows temporary behavior that expires at a given
1519 //--------------------------------------------------------------------
1521 UBool
IntlTest::isICUVersionAtLeast(const UVersionInfo x
) {
1524 return (uprv_memcmp(v
, x
, U_MAX_VERSION_LENGTH
) >= 0);
1527 #if !UCONFIG_NO_FORMATTING
1528 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1529 const Formattable
& expected
,
1530 const Formattable
& actual
) {
1531 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1536 * Hey, Emacs, please set the following:
1539 * indent-tabs-mode: nil