1 /********************************************************************
3 * Copyright (c) 1997-2010, 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_getRawUTCtime()
39 #include "unicode/locid.h"
40 #include "unicode/ctest.h" // for str_timeDelta
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 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 const CurrencyAmount
* c
= dynamic_cast<const CurrencyAmount
*>(f
.getObject());
176 s
= _toString(c
->getNumber()) + " " + UnicodeString(c
->getISOCurrency());
178 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 static inline UBool
isPrintable(UChar32 c
) {
262 return c
<= 0x7E && (c
>= 0x20 || c
== 9 || c
== 0xA || c
== 0xD);
265 // Replace nonprintable characters with unicode escapes
267 IntlTest::prettify(const UnicodeString
&source
,
268 UnicodeString
&target
)
275 for (i
= 0; i
< source
.length(); )
277 UChar32 ch
= source
.char32At(i
);
280 if (!isPrintable(ch
))
284 appendHex(ch
, 4, target
);
287 appendHex(ch
, 8, target
);
301 // Replace nonprintable characters with unicode escapes
303 IntlTest::prettify(const UnicodeString
&source
, UBool parseBackslash
)
306 UnicodeString target
;
310 for (i
= 0; i
< source
.length();)
312 UChar32 ch
= source
.char32At(i
);
315 if (!isPrintable(ch
))
317 if (parseBackslash
) {
318 // If we are preceded by an odd number of backslashes,
319 // then this character has already been backslash escaped.
320 // Delete a backslash.
321 int32_t backslashCount
= 0;
322 for (int32_t j
=target
.length()-1; j
>=0; --j
) {
323 if (target
.charAt(j
) == (UChar
)92) {
329 if ((backslashCount
% 2) == 1) {
330 target
.truncate(target
.length() - 1);
335 appendHex(ch
, 4, target
);
338 appendHex(ch
, 8, target
);
352 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
353 * set, try to deduce the directory in which ICU was built,
354 * and set ICU_DATA to "icu/source/data" in that location.
355 * The intent is to allow the tests to have a good chance
356 * of running without requiring that the user manually set
357 * ICU_DATA. Common data isn't a problem, since it is
358 * picked up via a static (build time) reference, but the
359 * tests dynamically load some data.
361 void IntlTest::setICU_DATA() {
362 const char *original_ICU_DATA
= getenv("ICU_DATA");
364 if (original_ICU_DATA
!= NULL
&& *original_ICU_DATA
!= 0) {
365 /* If the user set ICU_DATA, don't second-guess the person. */
369 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
370 // to point to the top of the build hierarchy, which may or
371 // may not be the same as the source directory, depending on
372 // the configure options used. At any rate,
373 // set the data path to the built data from this directory.
374 // The value is complete with quotes, so it can be used
375 // as-is as a string constant.
377 #if defined (U_TOPBUILDDIR)
379 static char env_string
[] = U_TOPBUILDDIR
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
;
380 u_setDataDirectory(env_string
);
385 // Use #else so we don't get compiler warnings due to the return above.
387 /* On Windows, the file name obtained from __FILE__ includes a full path.
388 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
389 * Change to "wherever\icu\source\data"
392 char p
[sizeof(__FILE__
) + 10];
397 /* We want to back over three '\' chars. */
398 /* Only Windows should end up here, so looking for '\' is safe. */
399 for (i
=1; i
<=3; i
++) {
400 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
401 if (pBackSlash
!= NULL
) {
402 *pBackSlash
= 0; /* Truncate the string at the '\' */
406 if (pBackSlash
!= NULL
) {
407 /* We found and truncated three names from the path.
408 * Now append "source\data" and set the environment
410 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
411 u_setDataDirectory(p
); /* p is "ICU_DATA=wherever\icu\source\data" */
415 /* __FILE__ on MSVC7 does not contain the directory */
416 u_setDataDirectory(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"out" U_FILE_SEP_STRING
);
422 /* No location for the data dir was identifiable.
423 * Add other fallbacks for the test data location here if the need arises
428 //--------------------------------------------------------------------------------------
430 static const int32_t indentLevel_offset
= 3;
431 static const char delim
= '/';
433 IntlTest
* IntlTest::gTest
= NULL
;
435 static int32_t execCount
= 0;
437 void it_log( UnicodeString message
)
440 IntlTest::gTest
->log( message
);
443 void it_logln( UnicodeString message
)
446 IntlTest::gTest
->logln( message
);
449 void it_logln( void )
452 IntlTest::gTest
->logln();
455 void it_info( UnicodeString message
)
458 IntlTest::gTest
->info( message
);
461 void it_infoln( UnicodeString message
)
464 IntlTest::gTest
->infoln( message
);
467 void it_infoln( void )
470 IntlTest::gTest
->infoln();
476 IntlTest::gTest
->err();
479 void it_err( UnicodeString message
)
482 IntlTest::gTest
->err( message
);
485 void it_errln( UnicodeString message
)
488 IntlTest::gTest
->errln( message
);
491 void it_dataerr( UnicodeString message
)
494 IntlTest::gTest
->dataerr( message
);
497 void it_dataerrln( UnicodeString message
)
500 IntlTest::gTest
->dataerrln( message
);
512 warn_on_missing_data
= FALSE
;
517 LL_indentlevel
= indentLevel_offset
;
519 strcpy(basePath
, "/");
522 void IntlTest::setCaller( IntlTest
* callingTest
)
524 caller
= callingTest
;
526 warn_on_missing_data
= caller
->warn_on_missing_data
;
527 verbose
= caller
->verbose
;
528 no_err_msg
= caller
->no_err_msg
;
529 quick
= caller
->quick
;
530 testoutfp
= caller
->testoutfp
;
531 LL_indentlevel
= caller
->LL_indentlevel
+ indentLevel_offset
;
532 numProps
= caller
->numProps
;
533 for (int32_t i
= 0; i
< numProps
; i
++) {
534 proplines
[i
] = caller
->proplines
[i
];
539 UBool
IntlTest::callTest( IntlTest
& testToBeCalled
, char* par
)
541 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
542 testToBeCalled
.setCaller( this );
543 strcpy(testToBeCalled
.basePath
, this->basePath
);
544 UBool result
= testToBeCalled
.runTest( testPath
, par
, testToBeCalled
.basePath
);
545 strcpy(testToBeCalled
.basePath
, this->basePath
); // reset it.
549 void IntlTest::setPath( char* pathVal
)
551 this->testPath
= pathVal
;
554 UBool
IntlTest::setVerbose( UBool verboseVal
)
556 UBool rval
= this->verbose
;
557 this->verbose
= verboseVal
;
561 UBool
IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal
)
563 UBool rval
= this->warn_on_missing_data
;
564 this->warn_on_missing_data
= warn_on_missing_dataVal
;
568 UBool
IntlTest::setNoErrMsg( UBool no_err_msgVal
)
570 UBool rval
= this->no_err_msg
;
571 this->no_err_msg
= no_err_msgVal
;
575 UBool
IntlTest::setQuick( UBool quickVal
)
577 UBool rval
= this->quick
;
578 this->quick
= quickVal
;
582 UBool
IntlTest::setLeaks( UBool leaksVal
)
584 UBool rval
= this->leaks
;
585 this->leaks
= leaksVal
;
589 int32_t IntlTest::setThreadCount( int32_t count
)
591 int32_t rval
= this->threadCount
;
592 this->threadCount
= count
;
596 int32_t IntlTest::getErrors( void )
601 int32_t IntlTest::getDataErrors( void )
603 return dataErrorCount
;
606 UBool
IntlTest::runTest( char* name
, char* par
, char *baseName
)
611 char* baseNameBuffer
= NULL
;
613 if(baseName
== NULL
) {
614 baseNameBuffer
= (char*)malloc(1024);
615 baseName
=baseNameBuffer
;
616 strcpy(baseName
, "/");
620 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
622 testPath
= pos
+1; // store subpath for calling subtest
623 *pos
= 0; // split into two strings
628 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
629 rval
= runTestLoop( NULL
, par
, baseName
);
631 }else if (strcmp( name
, "LIST" ) == 0) {
636 rval
= runTestLoop( name
, par
, baseName
);
640 *pos
= delim
; // restore original value at pos
641 if(baseNameBuffer
!=NULL
) {
642 free(baseNameBuffer
);
647 // call individual tests, to be overriden to call implementations
648 void IntlTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* par
)
650 // to be overriden by a method like:
653 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
654 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
655 default: name = ""; break;
658 this->errln("*** runIndexedTest needs to be overriden! ***");
659 name
= ""; exec
= exec
; index
= index
; par
= par
;
663 UBool
IntlTest::runTestLoop( char* testname
, char* par
, char *baseName
)
668 int32_t lastErrorCount
;
670 UBool lastTestFailed
;
672 if(baseName
== NULL
) {
673 printf("ERROR: baseName can't be null.\n");
676 if ((char *)this->basePath
!= baseName
) {
677 strcpy(this->basePath
, baseName
);
681 char * saveBaseLoc
= baseName
+strlen(baseName
);
683 IntlTest
* saveTest
= gTest
;
686 this->runIndexedTest( index
, FALSE
, name
, par
);
687 if (strcmp(name
,"skip") == 0) {
688 run_this_test
= FALSE
;
690 if (!name
|| (name
[0] == 0))
693 run_this_test
= TRUE
;
695 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
699 lastErrorCount
= errorCount
;
702 sprintf(msg
, "%s {", name
);
703 LL_message(msg
, TRUE
);
704 UDate timeStart
= uprv_getRawUTCtime();
705 strcpy(saveBaseLoc
,name
);
706 strcat(saveBaseLoc
,"/");
708 this->runIndexedTest( index
, TRUE
, name
, par
);
710 UDate timeStop
= uprv_getRawUTCtime();
711 rval
= TRUE
; // at least one test has been called
713 sprintf(secs
, "%f", (timeStop
-timeStart
)/1000.0);
716 strcpy(saveBaseLoc
,name
);
719 ctest_xml_testcase(baseName
, name
, secs
, (lastErrorCount
!=errorCount
)?"err":NULL
);
722 saveBaseLoc
[0]=0; /* reset path */
724 if (lastErrorCount
== errorCount
) {
725 sprintf( msg
, " } OK: %s ", name
);
726 str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
727 lastTestFailed
= FALSE
;
729 sprintf(msg
, " } ERRORS (%li) in %s", (long)(errorCount
-lastErrorCount
), name
);
730 str_timeDelta(msg
+strlen(msg
),timeStop
-timeStart
);
732 for(int i
=0;i
<LL_indentlevel
;i
++) {
737 lastTestFailed
= TRUE
;
740 if (lastTestFailed
) {
741 LL_message( "", TRUE
);
743 LL_message( msg
, TRUE
);
744 if (lastTestFailed
) {
745 LL_message( "", TRUE
);
760 * Adds given string to the log if we are in verbose mode.
762 void IntlTest::log( const UnicodeString
&message
)
765 LL_message( message
, FALSE
);
770 * Adds given string to the log if we are in verbose mode. Adds a new line to
773 void IntlTest::logln( const UnicodeString
&message
)
776 LL_message( message
, TRUE
);
780 void IntlTest::logln( void )
783 LL_message( "", TRUE
);
788 * Unconditionally adds given string to the log.
790 void IntlTest::info( const UnicodeString
&message
)
792 LL_message( message
, FALSE
);
796 * Unconditionally adds given string to the log. Adds a new line to
799 void IntlTest::infoln( const UnicodeString
&message
)
801 LL_message( message
, TRUE
);
804 void IntlTest::infoln( void )
806 LL_message( "", TRUE
);
809 int32_t IntlTest::IncErrorCount( void )
812 if (caller
) caller
->IncErrorCount();
816 int32_t IntlTest::IncDataErrorCount( void )
819 if (caller
) caller
->IncDataErrorCount();
820 return dataErrorCount
;
828 void IntlTest::err( const UnicodeString
&message
)
831 if (!no_err_msg
) LL_message( message
, FALSE
);
834 void IntlTest::errln( const UnicodeString
&message
)
837 if (!no_err_msg
) LL_message( message
, TRUE
);
840 void IntlTest::dataerr( const UnicodeString
&message
)
844 if (!warn_on_missing_data
) {
848 if (!no_err_msg
) LL_message( message
, FALSE
);
851 void IntlTest::dataerrln( const UnicodeString
&message
)
855 if (!warn_on_missing_data
) {
859 msg
= UnicodeString("[DATA] " + message
);
862 if (!no_err_msg
) LL_message( msg
+ " - (Are you missing data?)", TRUE
);
865 void IntlTest::errcheckln(UErrorCode status
, const UnicodeString
&message
) {
866 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
873 /* convenience functions that include sprintf formatting */
874 void IntlTest::log(const char *fmt
, ...)
880 /* sprintf it just to make sure that the information is valid */
881 vsprintf(buffer
, fmt
, ap
);
884 log(UnicodeString(buffer
, ""));
888 void IntlTest::logln(const char *fmt
, ...)
894 /* sprintf it just to make sure that the information is valid */
895 vsprintf(buffer
, fmt
, ap
);
898 logln(UnicodeString(buffer
, ""));
902 /* convenience functions that include sprintf formatting */
903 void IntlTest::info(const char *fmt
, ...)
909 /* sprintf it just to make sure that the information is valid */
910 vsprintf(buffer
, fmt
, ap
);
912 info(UnicodeString(buffer
, ""));
915 void IntlTest::infoln(const char *fmt
, ...)
921 /* sprintf it just to make sure that the information is valid */
922 vsprintf(buffer
, fmt
, ap
);
924 infoln(UnicodeString(buffer
, ""));
927 void IntlTest::err(const char *fmt
, ...)
933 vsprintf(buffer
, fmt
, ap
);
935 err(UnicodeString(buffer
, ""));
938 void IntlTest::errln(const char *fmt
, ...)
944 vsprintf(buffer
, fmt
, ap
);
946 errln(UnicodeString(buffer
, ""));
949 void IntlTest::dataerrln(const char *fmt
, ...)
955 vsprintf(buffer
, fmt
, ap
);
957 dataerrln(UnicodeString(buffer
, ""));
960 void IntlTest::errcheckln(UErrorCode status
, const char *fmt
, ...)
966 vsprintf(buffer
, fmt
, ap
);
969 if (status
== U_FILE_ACCESS_ERROR
|| status
== U_MISSING_RESOURCE_ERROR
) {
970 dataerrln(UnicodeString(buffer
, ""));
972 errln(UnicodeString(buffer
, ""));
976 void IntlTest::printErrors()
978 IntlTest::LL_message(errorList
, TRUE
);
981 void IntlTest::LL_message( UnicodeString message
, UBool newline
)
983 // string that starts with a LineFeed character and continues
984 // with spaces according to the current indentation
985 static const UChar indentUChars
[] = {
987 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
988 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
989 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
990 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
991 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
992 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
993 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
994 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
995 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
996 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
998 UnicodeString
indent(FALSE
, indentUChars
, 1 + LL_indentlevel
);
1003 // stream out the indentation string first if necessary
1004 length
= indent
.extract(1, indent
.length(), buffer
, sizeof(buffer
));
1006 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1009 // replace each LineFeed by the indentation string
1010 message
.findAndReplace(UnicodeString((UChar
)'\n'), indent
);
1012 // stream out the message
1013 length
= message
.extract(0, message
.length(), buffer
, sizeof(buffer
));
1015 length
= length
> 10000 ? 10000 : length
;
1016 fwrite(buffer
, sizeof(*buffer
), length
, (FILE *)testoutfp
);
1020 char newLine
= '\n';
1021 fwrite(&newLine
, sizeof(newLine
), 1, (FILE *)testoutfp
);
1024 // A newline usually flushes the buffer, but
1025 // flush the message just in case of a core dump.
1026 fflush((FILE *)testoutfp
);
1030 * Print a usage message for this test class.
1032 void IntlTest::usage( void )
1034 UBool save_verbose
= setVerbose( TRUE
);
1035 logln("Test names:");
1036 logln("-----------");
1039 const char* name
= NULL
;
1041 this->runIndexedTest( index
, FALSE
, name
);
1045 }while (name
&& (name
[0] != 0));
1046 setVerbose( save_verbose
);
1050 // memory leak reporting software will be able to take advantage of the testsuite
1051 // being run a second time local to a specific method in order to report only actual leaks
1053 IntlTest::run_phase2( char* name
, char* par
) // supports reporting memory leaks
1055 UnicodeString
* strLeak
= new UnicodeString("forced leak"); // for verifying purify filter
1056 strLeak
->append(" for verifying purify filter");
1057 return this->runTest( name
, par
);
1061 #if UCONFIG_NO_LEGACY_CONVERSION
1062 # define TRY_CNV_1 "iso-8859-1"
1063 # define TRY_CNV_2 "ibm-1208"
1065 # define TRY_CNV_1 "iso-8859-7"
1066 # define TRY_CNV_2 "sjis"
1070 main(int argc
, char* argv
[])
1072 UBool syntax
= FALSE
;
1074 UBool verbose
= FALSE
;
1075 UBool no_err_msg
= FALSE
;
1078 UBool leaks
= FALSE
;
1079 UBool warnOnMissingData
= FALSE
;
1080 UBool defaultDataFound
= FALSE
;
1081 int32_t threadCount
= 1;
1082 UErrorCode errorCode
= U_ZERO_ERROR
;
1083 UConverter
*cnv
= NULL
;
1084 const char *warnOrErr
= "Failure";
1085 UDate startTime
, endTime
;
1087 const char *props
[IntlTest::kMaxProps
];
1090 U_MAIN_INIT_ARGS(argc
, argv
);
1092 startTime
= uprv_getRawUTCtime();
1094 for (int i
= 1; i
< argc
; ++i
) {
1095 if (argv
[i
][0] == '-') {
1096 const char* str
= argv
[i
] + 1;
1097 if (strcmp("verbose", str
) == 0 ||
1098 strcmp("v", str
) == 0)
1100 else if (strcmp("noerrormsg", str
) == 0 ||
1101 strcmp("n", str
) == 0)
1103 else if (strcmp("exhaustive", str
) == 0 ||
1104 strcmp("e", str
) == 0)
1106 else if (strcmp("all", str
) == 0 ||
1107 strcmp("a", str
) == 0)
1109 else if (strcmp("leaks", str
) == 0 ||
1110 strcmp("l", str
) == 0)
1112 else if (strcmp("x", str
)==0) {
1114 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1117 if(ctest_xml_setFileName(argv
[i
])) { /* set the name */
1118 return 1; /* error */
1120 } else if (strcmp("w", str
) == 0) {
1121 warnOnMissingData
= TRUE
;
1122 warnOrErr
= "WARNING";
1124 else if (strncmp("threads:", str
, 8) == 0) {
1125 threadCount
= atoi(str
+ 8);
1127 else if (strncmp("prop:", str
, 5) == 0) {
1128 if (nProps
< IntlTest::kMaxProps
) {
1129 props
[nProps
] = str
+ 5;
1141 if (!all
&& !name
) {
1143 } else if (all
&& name
) {
1150 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1152 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1153 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1154 "### threads:<threadCount> (Mulithreading must first be \n"
1155 "### enabled otherwise this will be ignored. \n"
1156 "### The default thread count is 1.),\n"
1157 "### (Specify either -all (shortcut -a) or a test name). \n"
1158 "### -all will run all of the tests.\n"
1160 "### To get a list of the test names type: intltest LIST \n"
1161 "### To run just the utility tests type: intltest utility \n"
1163 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1164 "### For example to list the utility tests type: intltest utility/LIST \n"
1165 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1167 "### A parameter can be specified for a test by appending '@' and the value \n"
1168 "### to the testname. \n\n");
1172 if (nProps
> IntlTest::kMaxProps
) {
1173 fprintf(stdout
, "### Too many properties. Exiting.\n");
1176 UBool all_tests_exist
= TRUE
;
1177 MajorTestLevel major
;
1178 major
.setVerbose( verbose
);
1179 major
.setNoErrMsg( no_err_msg
);
1180 major
.setQuick( quick
);
1181 major
.setLeaks( leaks
);
1182 major
.setThreadCount( threadCount
);
1183 major
.setWarnOnMissingData( warnOnMissingData
);
1184 for (int32_t i
= 0; i
< nProps
; i
++) {
1185 major
.setProperty(props
[i
]);
1189 fprintf(stdout
, "-----------------------------------------------\n");
1190 fprintf(stdout
, " IntlTest (C++) Test Suite for \n");
1191 fprintf(stdout
, " International Components for Unicode %s\n", U_ICU_VERSION
);
1195 const char *charsetFamily
= "Unknown";
1196 int32_t voidSize
= (int32_t)sizeof(void*);
1197 int32_t bits
= voidSize
* 8;
1198 if(U_CHARSET_FAMILY
==U_ASCII_FAMILY
) {
1199 charsetFamily
="ASCII";
1200 } else if(U_CHARSET_FAMILY
==U_EBCDIC_FAMILY
) {
1201 charsetFamily
="EBCDIC";
1204 " Bits: %d, Byte order: %s, Chars: %s\n",
1205 bits
, U_IS_BIG_ENDIAN
?"Big endian":"Little endian",
1208 fprintf(stdout
, "-----------------------------------------------\n");
1209 fprintf(stdout
, " Options: \n");
1210 fprintf(stdout
, " all (a) : %s\n", (all
? "On" : "Off"));
1211 fprintf(stdout
, " Verbose (v) : %s\n", (verbose
? "On" : "Off"));
1212 fprintf(stdout
, " No error messages (n) : %s\n", (no_err_msg
? "On" : "Off"));
1213 fprintf(stdout
, " Exhaustive (e) : %s\n", (!quick
? "On" : "Off"));
1214 fprintf(stdout
, " Leaks (l) : %s\n", (leaks
? "On" : "Off"));
1215 fprintf(stdout
, " Warn on missing data (w) : %s\n", (warnOnMissingData
? "On" : "Off"));
1216 #if (ICU_USE_THREADS==0)
1217 fprintf(stdout
, " Threads : Disabled\n");
1219 fprintf(stdout
, " Threads : %d\n", threadCount
);
1221 for (int32_t i
= 0; i
< nProps
; i
++) {
1222 fprintf(stdout
, " Custom property (prop:) : %s\n", props
[i
]);
1224 fprintf(stdout
, "-----------------------------------------------\n");
1226 /* Check whether ICU will initialize without forcing the build data directory into
1227 * the ICU_DATA path. Success here means either the data dll contains data, or that
1228 * this test program was run with ICU_DATA set externally. Failure of this check
1229 * is normal when ICU data is not packaged into a shared library.
1231 * Whether or not this test succeeds, we want to cleanup and reinitialize
1232 * with a data path so that data loading from individual files can be tested.
1235 if (U_FAILURE(errorCode
)) {
1237 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1238 defaultDataFound
= FALSE
;
1241 defaultDataFound
= TRUE
;
1244 errorCode
= U_ZERO_ERROR
;
1246 /* Initialize ICU */
1247 if (!defaultDataFound
) {
1248 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1251 if (U_FAILURE(errorCode
)) {
1253 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1254 "*** Check the ICU_DATA environment variable and \n"
1255 "*** check that the data files are present.\n", argv
[0], u_errorName(errorCode
));
1256 if(warnOnMissingData
== 0) {
1257 fprintf(stderr
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1264 // initial check for the default converter
1265 errorCode
= U_ZERO_ERROR
;
1266 cnv
= ucnv_open(0, &errorCode
);
1272 "*** %s! The default converter [%s] cannot be opened.\n"
1273 "*** Check the ICU_DATA environment variable and\n"
1274 "*** check that the data files are present.\n",
1275 warnOrErr
, ucnv_getDefaultName());
1276 if(!warnOnMissingData
) {
1277 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1283 cnv
= ucnv_open(TRY_CNV_2
, &errorCode
);
1289 "*** %s! The converter for " TRY_CNV_2
" cannot be opened.\n"
1290 "*** Check the ICU_DATA environment variable and \n"
1291 "*** check that the data files are present.\n", warnOrErr
);
1292 if(!warnOnMissingData
) {
1293 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1298 UResourceBundle
*rb
= ures_open(0, "en", &errorCode
);
1300 if(U_FAILURE(errorCode
)) {
1302 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1303 "*** Check the ICU_DATA environment variable and \n"
1304 "*** check that the data files are present.\n", warnOrErr
);
1305 if(!warnOnMissingData
) {
1306 fprintf(stdout
, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1311 Locale originalLocale
; // Save the default locale for comparison later on.
1313 if(ctest_xml_init("intltest"))
1317 /* TODO: Add option to call u_cleanup and rerun tests. */
1321 major
.run_phase2( NULL
, NULL
);
1324 for (int i
= 1; i
< argc
; ++i
) {
1325 if (argv
[i
][0] != '-') {
1326 char* name
= argv
[i
];
1327 fprintf(stdout
, "\n=== Handling test: %s: ===\n", name
);
1329 char baseName
[1024];
1330 sprintf(baseName
, "/%s/", name
);
1332 char* parameter
= strchr( name
, '@' );
1338 UBool res
= major
.runTest( name
, parameter
, baseName
);
1340 major
.run_phase2( name
, parameter
);
1342 if (!res
|| (execCount
<= 0)) {
1343 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
1344 all_tests_exist
= FALSE
;
1346 } else if(!strcmp(argv
[i
],"-x")) {
1353 #if !UCONFIG_NO_FORMATTING
1354 CalendarTimeZoneTest::cleanup();
1357 free(_testDataPath
);
1360 Locale lastDefaultLocale
;
1361 if (originalLocale
!= lastDefaultLocale
) {
1362 major
.errln("FAILURE: A test changed the default locale without resetting it.");
1365 fprintf(stdout
, "\n--------------------------------------\n");
1366 if (major
.getErrors() == 0) {
1367 /* Call it twice to make sure that the defaults were reset. */
1368 /* Call it before the OK message to verify proper cleanup. */
1372 fprintf(stdout
, "OK: All tests passed without error.\n");
1374 if (major
.getDataErrors() != 0) {
1375 fprintf(stdout
, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1378 fprintf(stdout
, "Errors in total: %ld.\n", (long)major
.getErrors());
1379 major
.printErrors();
1382 if (major
.getDataErrors() != 0) {
1383 fprintf(stdout
, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1384 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1385 "\tthe '-w' option to turn these errors into warnings.\n");
1388 /* Call afterwards to display errors. */
1392 fprintf(stdout
, "--------------------------------------\n");
1394 if (execCount
<= 0) {
1395 fprintf(stdout
, "***** Not all called tests actually exist! *****\n");
1397 endTime
= uprv_getRawUTCtime();
1398 diffTime
= (int32_t)(endTime
- startTime
);
1399 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1400 (int)((diffTime%U_MILLIS_PER_DAY
)/U_MILLIS_PER_HOUR
),
1401 (int)((diffTime%U_MILLIS_PER_HOUR
)/U_MILLIS_PER_MINUTE
),
1402 (int)((diffTime%U_MILLIS_PER_MINUTE
)/U_MILLIS_PER_SECOND
),
1403 (int)(diffTime%U_MILLIS_PER_SECOND
));
1405 if(ctest_xml_fini())
1408 return major
.getErrors();
1411 const char* IntlTest::loadTestData(UErrorCode
& err
){
1412 if( _testDataPath
== NULL
){
1413 const char* directory
=NULL
;
1414 UResourceBundle
* test
=NULL
;
1416 const char* tdrelativepath
;
1418 #if defined (U_TOPBUILDDIR)
1419 tdrelativepath
= "test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1420 directory
= U_TOPBUILDDIR
;
1422 tdrelativepath
= ".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"out"U_FILE_SEP_STRING
;
1423 directory
= pathToDataDirectory();
1426 tdpath
= (char*) malloc(sizeof(char) *(( strlen(directory
) * strlen(tdrelativepath
)) + 100));
1429 /* u_getDataDirectory shoul return \source\data ... set the
1430 * directory to ..\source\data\..\test\testdata\out\testdata
1432 strcpy(tdpath
, directory
);
1433 strcat(tdpath
, tdrelativepath
);
1434 strcat(tdpath
,"testdata");
1436 test
=ures_open(tdpath
, "testtypes", &err
);
1439 err
= U_FILE_ACCESS_ERROR
;
1440 it_dataerrln((UnicodeString
)"Could not load testtypes.res in testdata bundle with path " + tdpath
+ (UnicodeString
)" - " + u_errorName(err
));
1444 _testDataPath
= tdpath
;
1445 return _testDataPath
;
1447 return _testDataPath
;
1450 const char* IntlTest::getTestDataPath(UErrorCode
& err
) {
1451 return loadTestData(err
);
1454 /* Returns the path to icu/source/test/testdata/ */
1455 const char *IntlTest::getSourceTestData(UErrorCode
& /*err*/) {
1456 const char *srcDataDir
= NULL
;
1458 srcDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1460 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1461 FILE *f
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
"rbbitst.txt", "r");
1463 /* We're in icu/source/test/intltest/ */
1467 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1468 srcDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
;
1474 const char* IntlTest::fgDataDir
= NULL
;
1476 /* returns the path to icu/source/data */
1477 const char * IntlTest::pathToDataDirectory()
1480 if(fgDataDir
!= NULL
) {
1484 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1485 // to point to the top of the build hierarchy, which may or
1486 // may not be the same as the source directory, depending on
1487 // the configure options used. At any rate,
1488 // set the data path to the built data from this directory.
1489 // The value is complete with quotes, so it can be used
1490 // as-is as a string constant.
1492 #if defined (U_TOPSRCDIR)
1494 fgDataDir
= U_TOPSRCDIR U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1498 /* On Windows, the file name obtained from __FILE__ includes a full path.
1499 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1500 * Change to "wherever\icu\source\data"
1503 static char p
[sizeof(__FILE__
) + 10];
1507 strcpy(p
, __FILE__
);
1508 /* We want to back over three '\' chars. */
1509 /* Only Windows should end up here, so looking for '\' is safe. */
1510 for (i
=1; i
<=3; i
++) {
1511 pBackSlash
= strrchr(p
, U_FILE_SEP_CHAR
);
1512 if (pBackSlash
!= NULL
) {
1513 *pBackSlash
= 0; /* Truncate the string at the '\' */
1517 if (pBackSlash
!= NULL
) {
1518 /* We found and truncated three names from the path.
1519 * Now append "source\data" and set the environment
1521 strcpy(pBackSlash
, U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
);
1525 /* __FILE__ on MSVC7 does not contain the directory */
1526 FILE *file
= fopen(".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
"Makefile.in", "r");
1529 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1532 fgDataDir
= ".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
".."U_FILE_SEP_STRING
"data" U_FILE_SEP_STRING
;
1543 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1544 * It converts an invariant-character string into a UnicodeString, with
1545 * unescaping \u sequences.
1547 UnicodeString
CharsToUnicodeString(const char* chars
){
1548 return UnicodeString(chars
, -1, US_INV
).unescape();
1551 UnicodeString
ctou(const char* chars
) {
1552 return CharsToUnicodeString(chars
);
1555 #define RAND_M (714025)
1556 #define RAND_IA (1366)
1557 #define RAND_IC (150889)
1559 static int32_t RAND_SEED
;
1562 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1563 * with care: Does not return all possible values; returns one of
1564 * 714,025 values, uniformly spaced. However, the period is
1565 * effectively infinite. See: Numerical Recipes, section 7.1.
1567 * @param seedp pointer to seed. Set *seedp to any negative value
1568 * to restart the sequence.
1570 float IntlTest::random(int32_t* seedp
) {
1571 static int32_t iy
, ir
[98];
1572 static UBool first
=TRUE
;
1574 if (*seedp
< 0 || first
) {
1576 if ((*seedp
=(RAND_IC
-(*seedp
)) % RAND_M
) < 0) *seedp
= -(*seedp
);
1577 for (j
=1;j
<=97;++j
) {
1578 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1581 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1584 j
=(int32_t)(1 + 97.0*iy
/RAND_M
);
1585 U_ASSERT(j
>=1 && j
<=97);
1587 *seedp
=(RAND_IA
*(*seedp
)+RAND_IC
) % RAND_M
;
1589 return (float) iy
/RAND_M
;
1593 * Convenience method using a global seed.
1595 float IntlTest::random() {
1596 return random(&RAND_SEED
);
1599 static inline UChar
toHex(int32_t i
) {
1600 return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10)));
1603 static UnicodeString
& escape(const UnicodeString
& s
, UnicodeString
& result
) {
1604 for (int32_t i
=0; i
<s
.length(); ++i
) {
1606 if (c
<= (UChar
)0x7F) {
1609 result
+= (UChar
)0x5c;
1610 result
+= (UChar
)0x75;
1611 result
+= toHex((c
>> 12) & 0xF);
1612 result
+= toHex((c
>> 8) & 0xF);
1613 result
+= toHex((c
>> 4) & 0xF);
1614 result
+= toHex( c
& 0xF);
1620 #define VERBOSE_ASSERTIONS
1622 UBool
IntlTest::assertTrue(const char* message
, UBool condition
, UBool quiet
, UBool possibleDataError
) {
1624 if (possibleDataError
) {
1625 dataerrln("FAIL: assertTrue() failed: %s", message
);
1627 errln("FAIL: assertTrue() failed: %s", message
);
1629 } else if (!quiet
) {
1630 logln("Ok: %s", message
);
1635 UBool
IntlTest::assertFalse(const char* message
, UBool condition
, UBool quiet
) {
1637 errln("FAIL: assertFalse() failed: %s", message
);
1638 } else if (!quiet
) {
1639 logln("Ok: %s", message
);
1644 UBool
IntlTest::assertSuccess(const char* message
, UErrorCode ec
, UBool possibleDataError
) {
1645 if (U_FAILURE(ec
)) {
1646 if (possibleDataError
) {
1647 dataerrln("FAIL: %s (%s)", message
, u_errorName(ec
));
1649 errcheckln(ec
, "FAIL: %s (%s)", message
, u_errorName(ec
));
1657 UBool
IntlTest::assertEquals(const char* message
,
1658 const UnicodeString
& expected
,
1659 const UnicodeString
& actual
,
1660 UBool possibleDataError
) {
1661 if (expected
!= actual
) {
1662 if (possibleDataError
) {
1663 dataerrln((UnicodeString
)"FAIL: " + message
+ "; got " +
1665 "; expected " + prettify(expected
));
1667 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1669 "; expected " + prettify(expected
));
1673 #ifdef VERBOSE_ASSERTIONS
1675 logln((UnicodeString
)"Ok: " + message
+ "; got " + prettify(actual
));
1681 UBool
IntlTest::assertEquals(const char* message
,
1682 const char* expected
,
1683 const char* actual
) {
1684 if (uprv_strcmp(expected
, actual
) != 0) {
1685 errln((UnicodeString
)"FAIL: " + message
+ "; got \"" +
1687 "\"; expected \"" + expected
+ "\"");
1690 #ifdef VERBOSE_ASSERTIONS
1692 logln((UnicodeString
)"Ok: " + message
+ "; got \"" + actual
+ "\"");
1698 #if !UCONFIG_NO_FORMATTING
1699 UBool
IntlTest::assertEquals(const char* message
,
1700 const Formattable
& expected
,
1701 const Formattable
& actual
) {
1702 if (expected
!= actual
) {
1703 errln((UnicodeString
)"FAIL: " + message
+ "; got " +
1705 "; expected " + toString(expected
));
1708 #ifdef VERBOSE_ASSERTIONS
1710 logln((UnicodeString
)"Ok: " + message
+ "; got " + toString(actual
));
1717 static char ASSERT_BUF
[256];
1719 static const char* extractToAssertBuf(const UnicodeString
& message
) {
1721 escape(message
, buf
);
1722 buf
.extract(0, 0x7FFFFFFF, ASSERT_BUF
, sizeof(ASSERT_BUF
)-1, 0);
1723 ASSERT_BUF
[sizeof(ASSERT_BUF
)-1] = 0;
1727 UBool
IntlTest::assertTrue(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1728 return assertTrue(extractToAssertBuf(message
), condition
, quiet
);
1731 UBool
IntlTest::assertFalse(const UnicodeString
& message
, UBool condition
, UBool quiet
) {
1732 return assertFalse(extractToAssertBuf(message
), condition
, quiet
);
1735 UBool
IntlTest::assertSuccess(const UnicodeString
& message
, UErrorCode ec
) {
1736 return assertSuccess(extractToAssertBuf(message
), ec
);
1739 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1740 const UnicodeString
& expected
,
1741 const UnicodeString
& actual
) {
1742 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1745 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1746 const char* expected
,
1747 const char* actual
) {
1748 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1750 //--------------------------------------------------------------------
1751 // Time bomb - allows temporary behavior that expires at a given
1753 //--------------------------------------------------------------------
1755 UBool
IntlTest::isICUVersionAtLeast(const UVersionInfo x
) {
1758 return (uprv_memcmp(v
, x
, U_MAX_VERSION_LENGTH
) >= 0);
1761 #if !UCONFIG_NO_FORMATTING
1762 UBool
IntlTest::assertEquals(const UnicodeString
& message
,
1763 const Formattable
& expected
,
1764 const Formattable
& actual
) {
1765 return assertEquals(extractToAssertBuf(message
), expected
, actual
);
1769 void IntlTest::setProperty(const char* propline
) {
1770 if (numProps
< kMaxProps
) {
1771 proplines
[numProps
] = propline
;
1776 const char* IntlTest::getProperty(const char* prop
) {
1777 const char* val
= NULL
;
1778 for (int32_t i
= 0; i
< numProps
; i
++) {
1779 int32_t plen
= uprv_strlen(prop
);
1780 if ((int32_t)uprv_strlen(proplines
[i
]) > plen
+ 1
1781 && proplines
[i
][plen
] == '='
1782 && uprv_strncmp(proplines
[i
], prop
, plen
) == 0) {
1783 val
= &(proplines
[i
][plen
+1]);
1791 * Hey, Emacs, please set the following:
1794 * indent-tabs-mode: nil