• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2013, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 
7 
8 #include "unicode/utypes.h"
9 
10 /**
11  * IntlTest is a base class for tests.
12  */
13 
14 #include <stdio.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <stdarg.h>
18 #include <stdlib.h>
19 
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"
28 
29 #include "intltest.h"
30 #include "caltztst.h"
31 #include "itmajor.h"
32 #include "cstring.h"
33 #include "umutex.h"
34 #include "uassert.h"
35 #include "cmemory.h"
36 #include "uoptions.h"
37 
38 #include "putilimp.h" // for uprv_getRawUTCtime()
39 #include "unicode/locid.h"
40 #include "unicode/ctest.h" // for str_timeDelta
41 #include "udbgutil.h"
42 
43 #ifdef XP_MAC_CONSOLE
44 #include <console.h>
45 #include "Files.h"
46 #endif
47 
48 
49 static char* _testDataPath=NULL;
50 
51 // Static list of errors found
52 static UnicodeString errorList;
53 static void *knownList = NULL; // known issues
54 static UBool noKnownIssues = FALSE; // if TRUE, don't emit known issues
55 
56 //-----------------------------------------------------------------------------
57 //convenience classes to ease porting code that uses the Java
58 //string-concatenation operator (moved from findword test by rtg)
59 
60 // [LIU] Just to get things working
61 UnicodeString
UCharToUnicodeString(UChar c)62 UCharToUnicodeString(UChar c)
63 { return UnicodeString(c); }
64 
65 // [rtg] Just to get things working
66 UnicodeString
operator +(const UnicodeString & left,long num)67 operator+(const UnicodeString& left,
68       long num)
69 {
70     char buffer[64];    // nos changed from 10 to 64
71     char danger = 'p';  // guard against overrunning the buffer (rtg)
72 
73     sprintf(buffer, "%ld", num);
74     assert(danger == 'p');
75 
76     return left + buffer;
77 }
78 
79 UnicodeString
operator +(const UnicodeString & left,unsigned long num)80 operator+(const UnicodeString& left,
81       unsigned long num)
82 {
83     char buffer[64];    // nos changed from 10 to 64
84     char danger = 'p';  // guard against overrunning the buffer (rtg)
85 
86     sprintf(buffer, "%lu", num);
87     assert(danger == 'p');
88 
89     return left + buffer;
90 }
91 
92 UnicodeString
Int64ToUnicodeString(int64_t num)93 Int64ToUnicodeString(int64_t num)
94 {
95     char buffer[64];    // nos changed from 10 to 64
96     char danger = 'p';  // guard against overrunning the buffer (rtg)
97 
98 #if defined(_MSC_VER)
99     sprintf(buffer, "%I64d", num);
100 #else
101     sprintf(buffer, "%lld", (long long)num);
102 #endif
103     assert(danger == 'p');
104 
105     return buffer;
106 }
107 
108 // [LIU] Just to get things working
109 UnicodeString
operator +(const UnicodeString & left,double num)110 operator+(const UnicodeString& left,
111       double num)
112 {
113     char buffer[64];   // was 32, made it arbitrarily bigger (rtg)
114     char danger = 'p'; // guard against overrunning the buffer (rtg)
115 
116     // IEEE floating point has 52 bits of mantissa, plus one assumed bit
117     //  53*log(2)/log(10) = 15.95
118     // so there is no need to show more than 16 digits. [alan]
119 
120     sprintf(buffer, "%.17g", num);
121     assert(danger == 'p');
122 
123     return left + buffer;
124 }
125 
126 #if 0
127 UnicodeString
128 operator+(const UnicodeString& left,
129           int64_t num) {
130   return left + Int64ToUnicodeString(num);
131 }
132 #endif
133 
134 #if !UCONFIG_NO_FORMATTING
135 
136 /**
137  * Return a string display for this, without surrounding braces.
138  */
_toString(const Formattable & f)139 UnicodeString _toString(const Formattable& f) {
140     UnicodeString s;
141     switch (f.getType()) {
142     case Formattable::kDate:
143         {
144             UErrorCode status = U_ZERO_ERROR;
145             SimpleDateFormat fmt(status);
146             if (U_SUCCESS(status)) {
147                 FieldPosition pos;
148                 fmt.format(f.getDate(), s, pos);
149                 s.insert(0, "Date:");
150             } else {
151                 s = UnicodeString("Error creating date format]");
152             }
153         }
154         break;
155     case Formattable::kDouble:
156         s = UnicodeString("double:") + f.getDouble();
157         break;
158     case Formattable::kLong:
159         s = UnicodeString("long:") + f.getLong();
160         break;
161 
162     case Formattable::kInt64:
163         s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
164         break;
165 
166     case Formattable::kString:
167         f.getString(s);
168         s.insert(0, "String:");
169         break;
170     case Formattable::kArray:
171         {
172             int32_t i, n;
173             const Formattable* array = f.getArray(n);
174             s.insert(0, UnicodeString("Array:"));
175             UnicodeString delim(", ");
176             for (i=0; i<n; ++i) {
177                 if (i > 0) {
178                     s.append(delim);
179                 }
180                 s = s + _toString(array[i]);
181             }
182         }
183         break;
184     case Formattable::kObject: {
185         const CurrencyAmount* c = dynamic_cast<const CurrencyAmount*>(f.getObject());
186         if (c != NULL) {
187             s = _toString(c->getNumber()) + " " + UnicodeString(c->getISOCurrency());
188         } else {
189             s = UnicodeString("Unknown UObject");
190         }
191         break;
192     }
193     default:
194         s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
195         break;
196     }
197     return s;
198 }
199 
200 /**
201  * Originally coded this as operator+, but that makes the expression
202  * + char* ambiguous. - liu
203  */
toString(const Formattable & f)204 UnicodeString toString(const Formattable& f) {
205     UnicodeString s((UChar)91/*[*/);
206     s.append(_toString(f));
207     s.append((UChar)0x5d/*]*/);
208     return s;
209 }
210 
211 #endif
212 
213 // useful when operator+ won't cooperate
toString(int32_t n)214 UnicodeString toString(int32_t n) {
215     return UnicodeString() + (long)n;
216 }
217 
218 
219 
toString(UBool b)220 UnicodeString toString(UBool b) {
221   return b ? UnicodeString("TRUE"):UnicodeString("FALSE");
222 }
223 
224 // stephen - cleaned up 05/05/99
operator +(const UnicodeString & left,char num)225 UnicodeString operator+(const UnicodeString& left, char num)
226 { return left + (long)num; }
operator +(const UnicodeString & left,short num)227 UnicodeString operator+(const UnicodeString& left, short num)
228 { return left + (long)num; }
operator +(const UnicodeString & left,int num)229 UnicodeString operator+(const UnicodeString& left, int num)
230 { return left + (long)num; }
operator +(const UnicodeString & left,unsigned char num)231 UnicodeString operator+(const UnicodeString& left, unsigned char num)
232 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned short num)233 UnicodeString operator+(const UnicodeString& left, unsigned short num)
234 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned int num)235 UnicodeString operator+(const UnicodeString& left, unsigned int num)
236 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,float num)237 UnicodeString operator+(const UnicodeString& left, float num)
238 { return left + (double)num; }
239 
240 //------------------
241 
242 // Append a hex string to the target
243 UnicodeString&
appendHex(uint32_t number,int32_t digits,UnicodeString & target)244 IntlTest::appendHex(uint32_t number,
245             int32_t digits,
246             UnicodeString& target)
247 {
248     static const UChar digitString[] = {
249         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
250         0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
251     }; /* "0123456789ABCDEF" */
252 
253     if (digits < 0) {  // auto-digits
254         digits = 2;
255         uint32_t max = 0xff;
256         while (number > max) {
257             digits += 2;
258             max = (max << 8) | 0xff;
259         }
260     }
261     switch (digits)
262     {
263     case 8:
264         target += digitString[(number >> 28) & 0xF];
265     case 7:
266         target += digitString[(number >> 24) & 0xF];
267     case 6:
268         target += digitString[(number >> 20) & 0xF];
269     case 5:
270         target += digitString[(number >> 16) & 0xF];
271     case 4:
272         target += digitString[(number >> 12) & 0xF];
273     case 3:
274         target += digitString[(number >>  8) & 0xF];
275     case 2:
276         target += digitString[(number >>  4) & 0xF];
277     case 1:
278         target += digitString[(number >>  0) & 0xF];
279         break;
280     default:
281         target += "**";
282     }
283     return target;
284 }
285 
286 UnicodeString
toHex(uint32_t number,int32_t digits)287 IntlTest::toHex(uint32_t number, int32_t digits) {
288     UnicodeString result;
289     appendHex(number, digits, result);
290     return result;
291 }
292 
isPrintable(UChar32 c)293 static inline UBool isPrintable(UChar32 c) {
294     return c <= 0x7E && (c >= 0x20 || c == 9 || c == 0xA || c == 0xD);
295 }
296 
297 // Replace nonprintable characters with unicode escapes
298 UnicodeString&
prettify(const UnicodeString & source,UnicodeString & target)299 IntlTest::prettify(const UnicodeString &source,
300            UnicodeString &target)
301 {
302     int32_t i;
303 
304     target.remove();
305     target += "\"";
306 
307     for (i = 0; i < source.length(); )
308     {
309         UChar32 ch = source.char32At(i);
310         i += U16_LENGTH(ch);
311 
312         if (!isPrintable(ch))
313         {
314             if (ch <= 0xFFFF) {
315                 target += "\\u";
316                 appendHex(ch, 4, target);
317             } else {
318                 target += "\\U";
319                 appendHex(ch, 8, target);
320             }
321         }
322         else
323         {
324             target += ch;
325         }
326     }
327 
328     target += "\"";
329 
330     return target;
331 }
332 
333 // Replace nonprintable characters with unicode escapes
334 UnicodeString
prettify(const UnicodeString & source,UBool parseBackslash)335 IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
336 {
337     int32_t i;
338     UnicodeString target;
339     target.remove();
340     target += "\"";
341 
342     for (i = 0; i < source.length();)
343     {
344         UChar32 ch = source.char32At(i);
345         i += U16_LENGTH(ch);
346 
347         if (!isPrintable(ch))
348         {
349             if (parseBackslash) {
350                 // If we are preceded by an odd number of backslashes,
351                 // then this character has already been backslash escaped.
352                 // Delete a backslash.
353                 int32_t backslashCount = 0;
354                 for (int32_t j=target.length()-1; j>=0; --j) {
355                     if (target.charAt(j) == (UChar)92) {
356                         ++backslashCount;
357                     } else {
358                         break;
359                     }
360                 }
361                 if ((backslashCount % 2) == 1) {
362                     target.truncate(target.length() - 1);
363                 }
364             }
365             if (ch <= 0xFFFF) {
366                 target += "\\u";
367                 appendHex(ch, 4, target);
368             } else {
369                 target += "\\U";
370                 appendHex(ch, 8, target);
371             }
372         }
373         else
374         {
375             target += ch;
376         }
377     }
378 
379     target += "\"";
380 
381     return target;
382 }
383 
384 /*  IntlTest::setICU_DATA  - if the ICU_DATA environment variable is not already
385  *                       set, try to deduce the directory in which ICU was built,
386  *                       and set ICU_DATA to "icu/source/data" in that location.
387  *                       The intent is to allow the tests to have a good chance
388  *                       of running without requiring that the user manually set
389  *                       ICU_DATA.  Common data isn't a problem, since it is
390  *                       picked up via a static (build time) reference, but the
391  *                       tests dynamically load some data.
392  */
setICU_DATA()393 void IntlTest::setICU_DATA() {
394     const char *original_ICU_DATA = getenv("ICU_DATA");
395 
396     if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
397         /*  If the user set ICU_DATA, don't second-guess the person. */
398         return;
399     }
400 
401     // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
402     //              to point to the top of the build hierarchy, which may or
403     //              may not be the same as the source directory, depending on
404     //              the configure options used.  At any rate,
405     //              set the data path to the built data from this directory.
406     //              The value is complete with quotes, so it can be used
407     //              as-is as a string constant.
408 
409 #if defined (U_TOPBUILDDIR)
410     {
411         static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
412         u_setDataDirectory(env_string);
413         return;
414     }
415 
416 #else
417     // Use #else so we don't get compiler warnings due to the return above.
418 
419     /* On Windows, the file name obtained from __FILE__ includes a full path.
420      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
421      *             Change to    "wherever\icu\source\data"
422      */
423     {
424         char p[sizeof(__FILE__) + 10];
425         char *pBackSlash;
426         int i;
427 
428         strcpy(p, __FILE__);
429         /* We want to back over three '\' chars.                            */
430         /*   Only Windows should end up here, so looking for '\' is safe.   */
431         for (i=1; i<=3; i++) {
432             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
433             if (pBackSlash != NULL) {
434                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
435             }
436         }
437 
438         if (pBackSlash != NULL) {
439             /* We found and truncated three names from the path.
440              *  Now append "source\data" and set the environment
441              */
442             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
443             u_setDataDirectory(p);     /*  p is "ICU_DATA=wherever\icu\source\data"    */
444             return;
445         }
446         else {
447             /* __FILE__ on MSVC7 does not contain the directory */
448             u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
449             return;
450         }
451     }
452 #endif
453 
454     /* No location for the data dir was identifiable.
455      *   Add other fallbacks for the test data location here if the need arises
456      */
457 }
458 
459 
460 //--------------------------------------------------------------------------------------
461 
462 static const int32_t indentLevel_offset = 3;
463 static const char delim = '/';
464 
465 IntlTest* IntlTest::gTest = NULL;
466 
467 static int32_t execCount = 0;
468 
it_log(UnicodeString message)469 void it_log( UnicodeString message )
470 {
471     if (IntlTest::gTest)
472         IntlTest::gTest->log( message );
473 }
474 
it_logln(UnicodeString message)475 void it_logln( UnicodeString message )
476 {
477     if (IntlTest::gTest)
478         IntlTest::gTest->logln( message );
479 }
480 
it_logln(void)481 void it_logln( void )
482 {
483     if (IntlTest::gTest)
484         IntlTest::gTest->logln();
485 }
486 
it_info(UnicodeString message)487 void it_info( UnicodeString message )
488 {
489     if (IntlTest::gTest)
490         IntlTest::gTest->info( message );
491 }
492 
it_infoln(UnicodeString message)493 void it_infoln( UnicodeString message )
494 {
495     if (IntlTest::gTest)
496         IntlTest::gTest->infoln( message );
497 }
498 
it_infoln(void)499 void it_infoln( void )
500 {
501     if (IntlTest::gTest)
502         IntlTest::gTest->infoln();
503 }
504 
it_err()505 void it_err()
506 {
507     if (IntlTest::gTest)
508         IntlTest::gTest->err();
509 }
510 
it_err(UnicodeString message)511 void it_err( UnicodeString message )
512 {
513     if (IntlTest::gTest)
514         IntlTest::gTest->err( message );
515 }
516 
it_errln(UnicodeString message)517 void it_errln( UnicodeString message )
518 {
519     if (IntlTest::gTest)
520         IntlTest::gTest->errln( message );
521 }
522 
it_dataerr(UnicodeString message)523 void it_dataerr( UnicodeString message )
524 {
525     if (IntlTest::gTest)
526         IntlTest::gTest->dataerr( message );
527 }
528 
it_dataerrln(UnicodeString message)529 void it_dataerrln( UnicodeString message )
530 {
531     if (IntlTest::gTest)
532         IntlTest::gTest->dataerrln( message );
533 }
534 
IntlTest()535 IntlTest::IntlTest()
536 {
537     caller = NULL;
538     testPath = NULL;
539     LL_linestart = TRUE;
540     errorCount = 0;
541     dataErrorCount = 0;
542     verbose = FALSE;
543     no_time = FALSE;
544     no_err_msg = FALSE;
545     warn_on_missing_data = FALSE;
546     quick = FALSE;
547     leaks = FALSE;
548     threadCount = 1;
549     testoutfp = stdout;
550     LL_indentlevel = indentLevel_offset;
551     numProps = 0;
552     strcpy(basePath, "/");
553     currName[0]=0;
554 }
555 
setCaller(IntlTest * callingTest)556 void IntlTest::setCaller( IntlTest* callingTest )
557 {
558     caller = callingTest;
559     if (caller) {
560         warn_on_missing_data = caller->warn_on_missing_data;
561         verbose = caller->verbose;
562         no_err_msg = caller->no_err_msg;
563         quick = caller->quick;
564         testoutfp = caller->testoutfp;
565         LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
566         numProps = caller->numProps;
567         for (int32_t i = 0; i < numProps; i++) {
568             proplines[i] = caller->proplines[i];
569         }
570     }
571 }
572 
callTest(IntlTest & testToBeCalled,char * par)573 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
574 {
575     execCount--; // correct a previously assumed test-exec, as this only calls a subtest
576     testToBeCalled.setCaller( this );
577     strcpy(testToBeCalled.basePath, this->basePath );
578     UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
579     strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
580     return result;
581 }
582 
setPath(char * pathVal)583 void IntlTest::setPath( char* pathVal )
584 {
585     this->testPath = pathVal;
586 }
587 
setVerbose(UBool verboseVal)588 UBool IntlTest::setVerbose( UBool verboseVal )
589 {
590     UBool rval = this->verbose;
591     this->verbose = verboseVal;
592     return rval;
593 }
594 
setNotime(UBool no_time)595 UBool IntlTest::setNotime( UBool no_time )
596 {
597     UBool rval = this->no_time;
598     this->no_time = no_time;
599     return rval;
600 }
601 
setWarnOnMissingData(UBool warn_on_missing_dataVal)602 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
603 {
604     UBool rval = this->warn_on_missing_data;
605     this->warn_on_missing_data = warn_on_missing_dataVal;
606     return rval;
607 }
608 
setNoErrMsg(UBool no_err_msgVal)609 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
610 {
611     UBool rval = this->no_err_msg;
612     this->no_err_msg = no_err_msgVal;
613     return rval;
614 }
615 
setQuick(UBool quickVal)616 UBool IntlTest::setQuick( UBool quickVal )
617 {
618     UBool rval = this->quick;
619     this->quick = quickVal;
620     return rval;
621 }
622 
setLeaks(UBool leaksVal)623 UBool IntlTest::setLeaks( UBool leaksVal )
624 {
625     UBool rval = this->leaks;
626     this->leaks = leaksVal;
627     return rval;
628 }
629 
setThreadCount(int32_t count)630 int32_t IntlTest::setThreadCount( int32_t count )
631 {
632     int32_t rval = this->threadCount;
633     this->threadCount = count;
634     return rval;
635 }
636 
getErrors(void)637 int32_t IntlTest::getErrors( void )
638 {
639     return errorCount;
640 }
641 
getDataErrors(void)642 int32_t IntlTest::getDataErrors( void )
643 {
644     return dataErrorCount;
645 }
646 
runTest(char * name,char * par,char * baseName)647 UBool IntlTest::runTest( char* name, char* par, char *baseName )
648 {
649     UBool rval;
650     char* pos = NULL;
651 
652     char* baseNameBuffer = NULL;
653 
654     if(baseName == NULL) {
655       baseNameBuffer = (char*)malloc(1024);
656       baseName=baseNameBuffer;
657       strcpy(baseName, "/");
658     }
659 
660     if (name)
661         pos = strchr( name, delim ); // check if name contains path (by looking for '/')
662     if (pos) {
663         testPath = pos+1;   // store subpath for calling subtest
664         *pos = 0;       // split into two strings
665     }else{
666         testPath = NULL;
667     }
668 
669     if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
670       rval = runTestLoop( NULL, par, baseName );
671 
672     }else if (strcmp( name, "LIST" ) == 0) {
673         this->usage();
674         rval = TRUE;
675 
676     }else{
677       rval = runTestLoop( name, par, baseName );
678     }
679 
680     if (pos)
681         *pos = delim;  // restore original value at pos
682     if(baseNameBuffer!=NULL) {
683       free(baseNameBuffer);
684     }
685     return rval;
686 }
687 
688 // call individual tests, to be overriden to call implementations
runIndexedTest(int32_t,UBool,const char * &,char *)689 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
690 {
691     // to be overriden by a method like:
692     /*
693     switch (index) {
694         case 0: name = "First Test"; if (exec) FirstTest( par ); break;
695         case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
696         default: name = ""; break;
697     }
698     */
699     this->errln("*** runIndexedTest needs to be overriden! ***");
700 }
701 
702 
runTestLoop(char * testname,char * par,char * baseName)703 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
704 {
705     int32_t    index = 0;
706     const char*   name;
707     UBool  run_this_test;
708     int32_t    lastErrorCount;
709     UBool  rval = FALSE;
710     UBool   lastTestFailed;
711 
712     if(baseName == NULL) {
713       printf("ERROR: baseName can't be null.\n");
714       return FALSE;
715     } else {
716       if ((char *)this->basePath != baseName) {
717         strcpy(this->basePath, baseName);
718       }
719     }
720 
721     char * saveBaseLoc = baseName+strlen(baseName);
722 
723     IntlTest* saveTest = gTest;
724     gTest = this;
725     do {
726         this->runIndexedTest( index, FALSE, name, par );
727         if (strcmp(name,"skip") == 0) {
728             run_this_test = FALSE;
729         } else {
730             if (!name || (name[0] == 0))
731                 break;
732             if (!testname) {
733                 run_this_test = TRUE;
734             }else{
735                 run_this_test = (UBool) (strcmp( name, testname ) == 0);
736             }
737         }
738         if (run_this_test) {
739             lastErrorCount = errorCount;
740             execCount++;
741             char msg[256];
742             sprintf(msg, "%s {", name);
743             LL_message(msg, TRUE);
744             UDate timeStart = uprv_getRawUTCtime();
745             strcpy(saveBaseLoc,name);
746             strcat(saveBaseLoc,"/");
747 
748             strcpy(currName, name); // set
749             this->runIndexedTest( index, TRUE, name, par );
750             currName[0]=0; // reset
751 
752             UDate timeStop = uprv_getRawUTCtime();
753             rval = TRUE; // at least one test has been called
754             char secs[256];
755             if(!no_time) {
756               sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
757             } else {
758               secs[0]=0;
759             }
760 
761 
762             strcpy(saveBaseLoc,name);
763 
764 
765             ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
766 
767 
768             saveBaseLoc[0]=0; /* reset path */
769 
770             if (lastErrorCount == errorCount) {
771                 sprintf( msg, "   } OK:   %s ", name );
772                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
773                 lastTestFailed = FALSE;
774             }else{
775                 sprintf(msg,  "   } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
776                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
777 
778                 for(int i=0;i<LL_indentlevel;i++) {
779                     errorList += " ";
780                 }
781                 errorList += name;
782                 errorList += "\n";
783                 lastTestFailed = TRUE;
784             }
785             LL_indentlevel -= 3;
786             if (lastTestFailed) {
787                 LL_message( "", TRUE);
788             }
789             LL_message( msg, TRUE);
790             if (lastTestFailed) {
791                 LL_message( "", TRUE);
792             }
793             LL_indentlevel += 3;
794         }
795         index++;
796     }while(name);
797 
798     *saveBaseLoc = 0;
799 
800     gTest = saveTest;
801     return rval;
802 }
803 
804 
805 /**
806 * Adds given string to the log if we are in verbose mode.
807 */
log(const UnicodeString & message)808 void IntlTest::log( const UnicodeString &message )
809 {
810     if( verbose ) {
811         LL_message( message, FALSE );
812     }
813 }
814 
815 /**
816 * Adds given string to the log if we are in verbose mode. Adds a new line to
817 * the given message.
818 */
logln(const UnicodeString & message)819 void IntlTest::logln( const UnicodeString &message )
820 {
821     if( verbose ) {
822         LL_message( message, TRUE );
823     }
824 }
825 
logln(void)826 void IntlTest::logln( void )
827 {
828     if( verbose ) {
829         LL_message( "", TRUE );
830     }
831 }
832 
833 /**
834 * Unconditionally adds given string to the log.
835 */
info(const UnicodeString & message)836 void IntlTest::info( const UnicodeString &message )
837 {
838   LL_message( message, FALSE );
839 }
840 
841 /**
842 * Unconditionally adds given string to the log. Adds a new line to
843 * the given message.
844 */
infoln(const UnicodeString & message)845 void IntlTest::infoln( const UnicodeString &message )
846 {
847   LL_message( message, TRUE );
848 }
849 
infoln(void)850 void IntlTest::infoln( void )
851 {
852   LL_message( "", TRUE );
853 }
854 
IncErrorCount(void)855 int32_t IntlTest::IncErrorCount( void )
856 {
857     errorCount++;
858     if (caller) caller->IncErrorCount();
859     return errorCount;
860 }
861 
IncDataErrorCount(void)862 int32_t IntlTest::IncDataErrorCount( void )
863 {
864     dataErrorCount++;
865     if (caller) caller->IncDataErrorCount();
866     return dataErrorCount;
867 }
868 
err()869 void IntlTest::err()
870 {
871     IncErrorCount();
872 }
873 
err(const UnicodeString & message)874 void IntlTest::err( const UnicodeString &message )
875 {
876     IncErrorCount();
877     if (!no_err_msg) LL_message( message, FALSE );
878 }
879 
errln(const UnicodeString & message)880 void IntlTest::errln( const UnicodeString &message )
881 {
882     IncErrorCount();
883     if (!no_err_msg) LL_message( message, TRUE );
884 }
885 
dataerr(const UnicodeString & message)886 void IntlTest::dataerr( const UnicodeString &message )
887 {
888     IncDataErrorCount();
889 
890     if (!warn_on_missing_data) {
891         IncErrorCount();
892     }
893 
894     if (!no_err_msg) LL_message( message, FALSE );
895 }
896 
dataerrln(const UnicodeString & message)897 void IntlTest::dataerrln( const UnicodeString &message )
898 {
899     int32_t errCount = IncDataErrorCount();
900     UnicodeString msg;
901     if (!warn_on_missing_data) {
902         IncErrorCount();
903         msg = message;
904     } else {
905         msg = UnicodeString("[DATA] " + message);
906     }
907 
908     if (!no_err_msg) {
909       if ( errCount == 1) {
910           LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
911       } else {
912           LL_message( msg , TRUE );
913       }
914     }
915 }
916 
errcheckln(UErrorCode status,const UnicodeString & message)917 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
918     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
919         dataerrln(message);
920     } else {
921         errln(message);
922     }
923 }
924 
925 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)926 void IntlTest::log(const char *fmt, ...)
927 {
928     char buffer[4000];
929     va_list ap;
930 
931     va_start(ap, fmt);
932     /* sprintf it just to make sure that the information is valid */
933     vsprintf(buffer, fmt, ap);
934     va_end(ap);
935     if( verbose ) {
936         log(UnicodeString(buffer, ""));
937     }
938 }
939 
logln(const char * fmt,...)940 void IntlTest::logln(const char *fmt, ...)
941 {
942     char buffer[4000];
943     va_list ap;
944 
945     va_start(ap, fmt);
946     /* sprintf it just to make sure that the information is valid */
947     vsprintf(buffer, fmt, ap);
948     va_end(ap);
949     if( verbose ) {
950         logln(UnicodeString(buffer, ""));
951     }
952 }
953 
logKnownIssue(const char * ticket,const char * fmt,...)954 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
955 {
956     char buffer[4000];
957     va_list ap;
958 
959     va_start(ap, fmt);
960     /* sprintf it just to make sure that the information is valid */
961     vsprintf(buffer, fmt, ap);
962     va_end(ap);
963     return logKnownIssue(ticket, UnicodeString(buffer, ""));
964 }
965 
logKnownIssue(const char * ticket)966 UBool IntlTest::logKnownIssue(const char *ticket) {
967   return logKnownIssue(ticket, UnicodeString());
968 }
969 
logKnownIssue(const char * ticket,const UnicodeString & msg)970 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
971   if(noKnownIssues) return FALSE;
972 
973   char fullpath[2048];
974   strcpy(fullpath, basePath);
975   strcat(fullpath, currName);
976   UnicodeString msg2 =msg;
977   UBool firstForTicket, firstForWhere;
978   knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
979 
980   if(firstForTicket || firstForWhere) {
981     infoln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg);
982   } else {
983     logln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg);
984   }
985 
986   return TRUE;
987 }
988 
989 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)990 void IntlTest::info(const char *fmt, ...)
991 {
992     char buffer[4000];
993     va_list ap;
994 
995     va_start(ap, fmt);
996     /* sprintf it just to make sure that the information is valid */
997     vsprintf(buffer, fmt, ap);
998     va_end(ap);
999     info(UnicodeString(buffer, ""));
1000 }
1001 
infoln(const char * fmt,...)1002 void IntlTest::infoln(const char *fmt, ...)
1003 {
1004     char buffer[4000];
1005     va_list ap;
1006 
1007     va_start(ap, fmt);
1008     /* sprintf it just to make sure that the information is valid */
1009     vsprintf(buffer, fmt, ap);
1010     va_end(ap);
1011     infoln(UnicodeString(buffer, ""));
1012 }
1013 
err(const char * fmt,...)1014 void IntlTest::err(const char *fmt, ...)
1015 {
1016     char buffer[4000];
1017     va_list ap;
1018 
1019     va_start(ap, fmt);
1020     vsprintf(buffer, fmt, ap);
1021     va_end(ap);
1022     err(UnicodeString(buffer, ""));
1023 }
1024 
errln(const char * fmt,...)1025 void IntlTest::errln(const char *fmt, ...)
1026 {
1027     char buffer[4000];
1028     va_list ap;
1029 
1030     va_start(ap, fmt);
1031     vsprintf(buffer, fmt, ap);
1032     va_end(ap);
1033     errln(UnicodeString(buffer, ""));
1034 }
1035 
dataerrln(const char * fmt,...)1036 void IntlTest::dataerrln(const char *fmt, ...)
1037 {
1038     char buffer[4000];
1039     va_list ap;
1040 
1041     va_start(ap, fmt);
1042     vsprintf(buffer, fmt, ap);
1043     va_end(ap);
1044     dataerrln(UnicodeString(buffer, ""));
1045 }
1046 
errcheckln(UErrorCode status,const char * fmt,...)1047 void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...)
1048 {
1049     char buffer[4000];
1050     va_list ap;
1051 
1052     va_start(ap, fmt);
1053     vsprintf(buffer, fmt, ap);
1054     va_end(ap);
1055 
1056     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1057         dataerrln(UnicodeString(buffer, ""));
1058     } else {
1059         errln(UnicodeString(buffer, ""));
1060     }
1061 }
1062 
printErrors()1063 void IntlTest::printErrors()
1064 {
1065      IntlTest::LL_message(errorList, TRUE);
1066 }
1067 
printKnownIssues()1068 UBool IntlTest::printKnownIssues()
1069 {
1070   if(knownList != NULL) {
1071     udbg_knownIssue_print(knownList);
1072     udbg_knownIssue_close(knownList);
1073     return TRUE;
1074   } else {
1075     return FALSE;
1076   }
1077 }
1078 
LL_message(UnicodeString message,UBool newline)1079 void IntlTest::LL_message( UnicodeString message, UBool newline )
1080 {
1081     // string that starts with a LineFeed character and continues
1082     // with spaces according to the current indentation
1083     static const UChar indentUChars[] = {
1084         '\n',
1085         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1086         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1087         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1088         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1089         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1090         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1091         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1092         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1093         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1094         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1095     };
1096     UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
1097 
1098     char buffer[10000];
1099     int32_t length;
1100 
1101     // stream out the indentation string first if necessary
1102     length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1103     if (length > 0) {
1104         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1105     }
1106 
1107     // replace each LineFeed by the indentation string
1108     message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1109 
1110     // stream out the message
1111     length = message.extract(0, message.length(), buffer, sizeof(buffer));
1112     if (length > 0) {
1113         length = length > 10000 ? 10000 : length;
1114         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1115     }
1116 
1117     if (newline) {
1118         char newLine = '\n';
1119         fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1120     }
1121 
1122     // A newline usually flushes the buffer, but
1123     // flush the message just in case of a core dump.
1124     fflush((FILE *)testoutfp);
1125 }
1126 
1127 /**
1128 * Print a usage message for this test class.
1129 */
usage(void)1130 void IntlTest::usage( void )
1131 {
1132     UBool save_verbose = setVerbose( TRUE );
1133     logln("Test names:");
1134     logln("-----------");
1135 
1136     int32_t index = 0;
1137     const char* name = NULL;
1138     do{
1139         this->runIndexedTest( index, FALSE, name );
1140         if (!name) break;
1141         logln(name);
1142         index++;
1143     }while (name && (name[0] != 0));
1144     setVerbose( save_verbose );
1145 }
1146 
1147 
1148 // memory leak reporting software will be able to take advantage of the testsuite
1149 // being run a second time local to a specific method in order to report only actual leaks
1150 UBool
run_phase2(char * name,char * par)1151 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1152 {
1153     UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1154     strLeak->append(" for verifying purify filter");
1155     return this->runTest( name, par );
1156 }
1157 
1158 
1159 #if UCONFIG_NO_LEGACY_CONVERSION
1160 #   define TRY_CNV_1 "iso-8859-1"
1161 #   define TRY_CNV_2 "ibm-1208"
1162 #else
1163 #   define TRY_CNV_1 "iso-8859-7"
1164 #   define TRY_CNV_2 "sjis"
1165 #endif
1166 
1167 int
main(int argc,char * argv[])1168 main(int argc, char* argv[])
1169 {
1170     UBool syntax = FALSE;
1171     UBool all = FALSE;
1172     UBool verbose = FALSE;
1173     UBool no_err_msg = FALSE;
1174     UBool no_time = FALSE;
1175     UBool quick = TRUE;
1176     UBool name = FALSE;
1177     UBool leaks = FALSE;
1178     UBool utf8 = FALSE;
1179     const char *summary_file = NULL;
1180     UBool warnOnMissingData = FALSE;
1181     UBool defaultDataFound = FALSE;
1182     int32_t threadCount = 1;
1183     UErrorCode errorCode = U_ZERO_ERROR;
1184     UConverter *cnv = NULL;
1185     const char *warnOrErr = "Failure";
1186     UDate startTime, endTime;
1187     int32_t diffTime;
1188     const char *props[IntlTest::kMaxProps];
1189     int32_t nProps = 0;
1190 
1191     U_MAIN_INIT_ARGS(argc, argv);
1192 
1193     startTime = uprv_getRawUTCtime();
1194 
1195     for (int i = 1; i < argc; ++i) {
1196         if (argv[i][0] == '-') {
1197             const char* str = argv[i] + 1;
1198             if (strcmp("verbose", str) == 0 ||
1199                 strcmp("v", str) == 0)
1200                 verbose = TRUE;
1201             else if (strcmp("noerrormsg", str) == 0 ||
1202                      strcmp("n", str) == 0)
1203                 no_err_msg = TRUE;
1204             else if (strcmp("exhaustive", str) == 0 ||
1205                      strcmp("e", str) == 0)
1206                 quick = FALSE;
1207             else if (strcmp("all", str) == 0 ||
1208                      strcmp("a", str) == 0)
1209                 all = TRUE;
1210             else if (strcmp("utf-8", str) == 0 ||
1211                      strcmp("u", str) == 0)
1212                 utf8 = TRUE;
1213             else if (strcmp("noknownissues", str) == 0 ||
1214                      strcmp("K", str) == 0)
1215                 noKnownIssues = TRUE;
1216             else if (strcmp("leaks", str) == 0 ||
1217                      strcmp("l", str) == 0)
1218                 leaks = TRUE;
1219             else if (strcmp("notime", str) == 0 ||
1220                      strcmp("T", str) == 0)
1221                 no_time = TRUE;
1222             else if (strncmp("E", str, 1) == 0)
1223                 summary_file = str+1;
1224             else if (strcmp("x", str)==0) {
1225               if(++i>=argc) {
1226                 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1227                 syntax = TRUE;
1228               }
1229               if(ctest_xml_setFileName(argv[i])) { /* set the name */
1230                 return 1; /* error */
1231               }
1232             } else if (strcmp("w", str) == 0) {
1233               warnOnMissingData = TRUE;
1234               warnOrErr = "WARNING";
1235             }
1236             else if (strncmp("threads:", str, 8) == 0) {
1237                 threadCount = atoi(str + 8);
1238             }
1239             else if (strncmp("prop:", str, 5) == 0) {
1240                 if (nProps < IntlTest::kMaxProps) {
1241                     props[nProps] = str + 5;
1242                 }
1243                 nProps++;
1244             }
1245             else {
1246                 syntax = TRUE;
1247             }
1248         }else{
1249             name = TRUE;
1250         }
1251     }
1252 
1253     if (!all && !name) {
1254         all = TRUE;
1255     } else if (all && name) {
1256         syntax = TRUE;
1257     }
1258 
1259     if (syntax) {
1260         fprintf(stdout,
1261                 "### Syntax:\n"
1262                 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1263                 "### \n"
1264                 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1265                 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1266                 "### notime (T), \n"
1267                 "### threads:<threadCount> (Mulithreading must first be \n"
1268                 "###     enabled otherwise this will be ignored. \n"
1269                 "###     The default thread count is 1.),\n"
1270                 "### (Specify either -all (shortcut -a) or a test name). \n"
1271                 "### -all will run all of the tests.\n"
1272                 "### \n"
1273                 "### To get a list of the test names type: intltest LIST \n"
1274                 "### To run just the utility tests type: intltest utility \n"
1275                 "### \n"
1276                 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1277                 "### For example to list the utility tests type: intltest utility/LIST \n"
1278                 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1279                 "### \n"
1280                 "### A parameter can be specified for a test by appending '@' and the value \n"
1281                 "### to the testname. \n\n");
1282         return 1;
1283     }
1284 
1285     if (nProps > IntlTest::kMaxProps) {
1286         fprintf(stdout, "### Too many properties.  Exiting.\n");
1287     }
1288 
1289     MajorTestLevel major;
1290     major.setVerbose( verbose );
1291     major.setNoErrMsg( no_err_msg );
1292     major.setQuick( quick );
1293     major.setLeaks( leaks );
1294     major.setThreadCount( threadCount );
1295     major.setWarnOnMissingData( warnOnMissingData );
1296     major.setNotime (no_time);
1297     for (int32_t i = 0; i < nProps; i++) {
1298         major.setProperty(props[i]);
1299     }
1300 
1301 
1302     fprintf(stdout, "-----------------------------------------------\n");
1303     fprintf(stdout, " IntlTest (C++) Test Suite for                 \n");
1304     fprintf(stdout, "   International Components for Unicode %s\n", U_ICU_VERSION);
1305 
1306 
1307     {
1308 	const char *charsetFamily = "Unknown";
1309         int32_t voidSize = (int32_t)sizeof(void*);
1310         int32_t bits = voidSize * 8;
1311         if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1312            charsetFamily="ASCII";
1313         } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1314            charsetFamily="EBCDIC";
1315         }
1316         fprintf(stdout,
1317                     "   Bits: %d, Byte order: %s, Chars: %s\n",
1318                      bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1319                      charsetFamily);
1320     }
1321     fprintf(stdout, "-----------------------------------------------\n");
1322     fprintf(stdout, " Options:                                       \n");
1323     fprintf(stdout, "   all (a)                  : %s\n", (all?               "On" : "Off"));
1324     fprintf(stdout, "   Verbose (v)              : %s\n", (verbose?           "On" : "Off"));
1325     fprintf(stdout, "   No error messages (n)    : %s\n", (no_err_msg?        "On" : "Off"));
1326     fprintf(stdout, "   Exhaustive (e)           : %s\n", (!quick?            "On" : "Off"));
1327     fprintf(stdout, "   Leaks (l)                : %s\n", (leaks?             "On" : "Off"));
1328     fprintf(stdout, "   utf-8 (u)                : %s\n", (utf8?              "On" : "Off"));
1329     fprintf(stdout, "   notime (T)               : %s\n", (no_time?             "On" : "Off"));
1330     fprintf(stdout, "   noknownissues (K)        : %s\n", (noKnownIssues?      "On" : "Off"));
1331     fprintf(stdout, "   Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1332 #if (ICU_USE_THREADS==0)
1333     fprintf(stdout, "   Threads                  : Disabled\n");
1334 #else
1335     fprintf(stdout, "   Threads                  : %d\n", threadCount);
1336 #endif
1337     for (int32_t i = 0; i < nProps; i++) {
1338         fprintf(stdout, "   Custom property (prop:)  : %s\n", props[i]);
1339     }
1340     fprintf(stdout, "-----------------------------------------------\n");
1341 
1342     if(utf8) {
1343       ucnv_setDefaultName("utf-8");
1344     }
1345     /* Check whether ICU will initialize without forcing the build data directory into
1346      *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1347      *  this test program was run with ICU_DATA set externally.  Failure of this check
1348      *  is normal when ICU data is not packaged into a shared library.
1349      *
1350      *  Whether or not this test succeeds, we want to cleanup and reinitialize
1351      *  with a data path so that data loading from individual files can be tested.
1352      */
1353     u_init(&errorCode);
1354     if (U_FAILURE(errorCode)) {
1355         fprintf(stderr,
1356             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1357         defaultDataFound = FALSE;
1358     }
1359     else {
1360         defaultDataFound = TRUE;
1361     }
1362     u_cleanup();
1363     if(utf8) {
1364       ucnv_setDefaultName("utf-8");
1365     }
1366     errorCode = U_ZERO_ERROR;
1367 
1368     /* Initialize ICU */
1369     if (!defaultDataFound) {
1370         IntlTest::setICU_DATA();   // Must set data directory before u_init() is called.
1371     }
1372     u_init(&errorCode);
1373     if (U_FAILURE(errorCode)) {
1374         fprintf(stderr,
1375             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1376             "*** Check the ICU_DATA environment variable and \n"
1377             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1378             if(warnOnMissingData == 0) {
1379                 fprintf(stderr, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1380                 u_cleanup();
1381                 return 1;
1382             }
1383     }
1384 
1385     // initial check for the default converter
1386     errorCode = U_ZERO_ERROR;
1387     cnv = ucnv_open(0, &errorCode);
1388     if(cnv != 0) {
1389         // ok
1390         ucnv_close(cnv);
1391     } else {
1392         fprintf(stdout,
1393                 "*** %s! The default converter [%s] cannot be opened.\n"
1394                 "*** Check the ICU_DATA environment variable and\n"
1395                 "*** check that the data files are present.\n",
1396                 warnOrErr, ucnv_getDefaultName());
1397         if(!warnOnMissingData) {
1398           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1399           return 1;
1400         }
1401     }
1402 
1403     // try more data
1404     cnv = ucnv_open(TRY_CNV_2, &errorCode);
1405     if(cnv != 0) {
1406         // ok
1407         ucnv_close(cnv);
1408     } else {
1409         fprintf(stdout,
1410                 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1411                 "*** Check the ICU_DATA environment variable and \n"
1412                 "*** check that the data files are present.\n", warnOrErr);
1413         if(!warnOnMissingData) {
1414           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1415           return 1;
1416         }
1417     }
1418 
1419     UResourceBundle *rb = ures_open(0, "en", &errorCode);
1420     ures_close(rb);
1421     if(U_FAILURE(errorCode)) {
1422         fprintf(stdout,
1423                 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1424                 "*** Check the ICU_DATA environment variable and \n"
1425                 "*** check that the data files are present.\n", warnOrErr);
1426         if(!warnOnMissingData) {
1427           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1428           return 1;
1429         }
1430     }
1431 
1432     Locale originalLocale;  // Save the default locale for comparison later on.
1433 
1434     if(ctest_xml_init("intltest"))
1435       return 1;
1436 
1437 
1438     /* TODO: Add option to call u_cleanup and rerun tests. */
1439     if (all) {
1440         major.runTest();
1441         if (leaks) {
1442             major.run_phase2( NULL, NULL );
1443         }
1444     }else{
1445         for (int i = 1; i < argc; ++i) {
1446             if (argv[i][0] != '-') {
1447                 char* name = argv[i];
1448                 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1449 
1450                 char baseName[1024];
1451                 sprintf(baseName, "/%s/", name);
1452 
1453                 char* parameter = strchr( name, '@' );
1454                 if (parameter) {
1455                     *parameter = 0;
1456                     parameter += 1;
1457                 }
1458                 execCount = 0;
1459                 UBool res = major.runTest( name, parameter, baseName );
1460                 if (leaks && res) {
1461                     major.run_phase2( name, parameter );
1462                 }
1463                 if (!res || (execCount <= 0)) {
1464                     fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1465                 }
1466             } else if(!strcmp(argv[i],"-x")) {
1467               i++;
1468             }
1469         }
1470     }
1471 
1472 
1473 #if !UCONFIG_NO_FORMATTING
1474     CalendarTimeZoneTest::cleanup();
1475 #endif
1476 
1477     free(_testDataPath);
1478     _testDataPath = 0;
1479 
1480     Locale lastDefaultLocale;
1481     if (originalLocale != lastDefaultLocale) {
1482         major.errln("FAILURE: A test changed the default locale without resetting it.");
1483     }
1484 
1485     fprintf(stdout, "\n--------------------------------------\n");
1486     if( major.printKnownIssues() ) {
1487       fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1488     }
1489     if (major.getErrors() == 0) {
1490         /* Call it twice to make sure that the defaults were reset. */
1491         /* Call it before the OK message to verify proper cleanup. */
1492         u_cleanup();
1493         u_cleanup();
1494 
1495         fprintf(stdout, "OK: All tests passed without error.\n");
1496 
1497         if (major.getDataErrors() != 0) {
1498             fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1499         }
1500     }else{
1501         fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1502         major.printErrors();
1503 
1504         if(summary_file != NULL) {
1505           FILE *summf = fopen(summary_file, "w");
1506           if( summf != NULL) {
1507             char buf[10000];
1508             int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1509             fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1510             fclose(summf);
1511           }
1512         }
1513 
1514 
1515         if (major.getDataErrors() != 0) {
1516             fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1517                     "\tstock ICU data (i.e some have been added or removed), consider using\n"
1518                     "\tthe '-w' option to turn these errors into warnings.\n");
1519         }
1520 
1521         /* Call afterwards to display errors. */
1522         u_cleanup();
1523     }
1524 
1525     fprintf(stdout, "--------------------------------------\n");
1526 
1527     if (execCount <= 0) {
1528         fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1529     }
1530     if(!no_time) {
1531       endTime = uprv_getRawUTCtime();
1532       diffTime = (int32_t)(endTime - startTime);
1533       printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1534              (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1535              (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1536              (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1537              (int)(diffTime%U_MILLIS_PER_SECOND));
1538     }
1539 
1540     if(ctest_xml_fini())
1541       return 1;
1542 
1543     return major.getErrors();
1544 }
1545 
loadTestData(UErrorCode & err)1546 const char* IntlTest::loadTestData(UErrorCode& err){
1547     if( _testDataPath == NULL){
1548         const char*      directory=NULL;
1549         UResourceBundle* test =NULL;
1550         char* tdpath=NULL;
1551         const char* tdrelativepath;
1552 
1553 #if defined (U_TOPBUILDDIR)
1554         tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1555         directory = U_TOPBUILDDIR;
1556 #else
1557         tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1558         directory = pathToDataDirectory();
1559 #endif
1560 
1561         tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1562 
1563 
1564         /* u_getDataDirectory shoul return \source\data ... set the
1565          * directory to ..\source\data\..\test\testdata\out\testdata
1566          */
1567         strcpy(tdpath, directory);
1568         strcat(tdpath, tdrelativepath);
1569         strcat(tdpath,"testdata");
1570 
1571         test=ures_open(tdpath, "testtypes", &err);
1572 
1573         if(U_FAILURE(err)){
1574             err = U_FILE_ACCESS_ERROR;
1575             it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1576             return "";
1577         }
1578         ures_close(test);
1579         _testDataPath = tdpath;
1580         return _testDataPath;
1581     }
1582     return _testDataPath;
1583 }
1584 
getTestDataPath(UErrorCode & err)1585 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1586     return loadTestData(err);
1587 }
1588 
1589 /* Returns the path to icu/source/test/testdata/ */
getSourceTestData(UErrorCode &)1590 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1591     const char *srcDataDir = NULL;
1592 #ifdef U_TOPSRCDIR
1593     srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1594 #else
1595     srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1596     FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r");
1597     if (f) {
1598         /* We're in icu/source/test/intltest/ */
1599         fclose(f);
1600     }
1601     else {
1602         /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1603         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;
1604     }
1605 #endif
1606     return srcDataDir;
1607 }
1608 
1609 const char* IntlTest::fgDataDir = NULL;
1610 
1611 /* returns the path to icu/source/data */
pathToDataDirectory()1612 const char *  IntlTest::pathToDataDirectory()
1613 {
1614 
1615     if(fgDataDir != NULL) {
1616         return fgDataDir;
1617     }
1618 
1619     /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1620     //              to point to the top of the build hierarchy, which may or
1621     //              may not be the same as the source directory, depending on
1622     //              the configure options used.  At any rate,
1623     //              set the data path to the built data from this directory.
1624     //              The value is complete with quotes, so it can be used
1625     //              as-is as a string constant.
1626     */
1627 #if defined (U_TOPSRCDIR)
1628     {
1629         fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1630     }
1631 #else
1632 
1633     /* On Windows, the file name obtained from __FILE__ includes a full path.
1634      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1635      *             Change to    "wherever\icu\source\data"
1636      */
1637     {
1638         static char p[sizeof(__FILE__) + 10];
1639         char *pBackSlash;
1640         int i;
1641 
1642         strcpy(p, __FILE__);
1643         /* We want to back over three '\' chars.                            */
1644         /*   Only Windows should end up here, so looking for '\' is safe.   */
1645         for (i=1; i<=3; i++) {
1646             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1647             if (pBackSlash != NULL) {
1648                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
1649             }
1650         }
1651 
1652         if (pBackSlash != NULL) {
1653             /* We found and truncated three names from the path.
1654             *  Now append "source\data" and set the environment
1655             */
1656             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1657             fgDataDir = p;
1658         }
1659         else {
1660             /* __FILE__ on MSVC7 does not contain the directory */
1661             FILE *file = fopen(".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1662             if (file) {
1663                 fclose(file);
1664                 fgDataDir = ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1665             }
1666             else {
1667                 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1668             }
1669         }
1670     }
1671 #endif
1672 
1673     return fgDataDir;
1674 
1675 }
1676 
1677 /*
1678  * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1679  * It converts an invariant-character string into a UnicodeString, with
1680  * unescaping \u sequences.
1681  */
CharsToUnicodeString(const char * chars)1682 UnicodeString CharsToUnicodeString(const char* chars){
1683     return UnicodeString(chars, -1, US_INV).unescape();
1684 }
1685 
ctou(const char * chars)1686 UnicodeString ctou(const char* chars) {
1687     return CharsToUnicodeString(chars);
1688 }
1689 
1690 #define RAND_M  (714025)
1691 #define RAND_IA (1366)
1692 #define RAND_IC (150889)
1693 
1694 static int32_t RAND_SEED;
1695 
1696 /**
1697  * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1698  * with care: Does not return all possible values; returns one of
1699  * 714,025 values, uniformly spaced.  However, the period is
1700  * effectively infinite.  See: Numerical Recipes, section 7.1.
1701  *
1702  * @param seedp pointer to seed. Set *seedp to any negative value
1703  * to restart the sequence.
1704  */
random(int32_t * seedp)1705 float IntlTest::random(int32_t* seedp) {
1706     static int32_t iy, ir[98];
1707     static UBool first=TRUE;
1708     int32_t j;
1709     if (*seedp < 0 || first) {
1710         first = FALSE;
1711         if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1712         for (j=1;j<=97;++j) {
1713             *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1714             ir[j]=(*seedp);
1715         }
1716         *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1717         iy=(*seedp);
1718     }
1719     j=(int32_t)(1 + 97.0*iy/RAND_M);
1720     U_ASSERT(j>=1 && j<=97);
1721     iy=ir[j];
1722     *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1723     ir[j]=(*seedp);
1724     return (float) iy/RAND_M;
1725 }
1726 
1727 /**
1728  * Convenience method using a global seed.
1729  */
random()1730 float IntlTest::random() {
1731     return random(&RAND_SEED);
1732 }
1733 
toHex(int32_t i)1734 static inline UChar toHex(int32_t i) {
1735     return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1736 }
1737 
escape(const UnicodeString & s,UnicodeString & result)1738 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1739     for (int32_t i=0; i<s.length(); ++i) {
1740         UChar c = s[i];
1741         if (c <= (UChar)0x7F) {
1742             result += c;
1743         } else {
1744             result += (UChar)0x5c;
1745             result += (UChar)0x75;
1746             result += toHex((c >> 12) & 0xF);
1747             result += toHex((c >>  8) & 0xF);
1748             result += toHex((c >>  4) & 0xF);
1749             result += toHex( c        & 0xF);
1750         }
1751     }
1752     return result;
1753 }
1754 
1755 #define VERBOSE_ASSERTIONS
1756 
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1757 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1758     if (file != NULL) {
1759         if (!condition) {
1760             if (possibleDataError) {
1761                 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1762             } else {
1763                 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1764             }
1765         } else if (!quiet) {
1766             logln("%s:%d: Ok: %s", file, line, message);
1767         }
1768     } else {
1769         if (!condition) {
1770             if (possibleDataError) {
1771                 dataerrln("FAIL: assertTrue() failed: %s", message);
1772             } else {
1773                 errln("FAIL: assertTrue() failed: %s", message);
1774             }
1775         } else if (!quiet) {
1776             logln("Ok: %s", message);
1777         }
1778 
1779     }
1780     return condition;
1781 }
1782 
assertFalse(const char * message,UBool condition,UBool quiet)1783 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1784     if (condition) {
1785         errln("FAIL: assertFalse() failed: %s", message);
1786     } else if (!quiet) {
1787         logln("Ok: %s", message);
1788     }
1789     return !condition;
1790 }
1791 
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1792 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1793     if( file==NULL ) {
1794       file = ""; // prevent failure if no file given
1795     }
1796     if (U_FAILURE(ec)) {
1797         if (possibleDataError) {
1798           dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1799         } else {
1800           errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1801         }
1802         return FALSE;
1803     } else {
1804       logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1805     }
1806     return TRUE;
1807 }
1808 
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1809 UBool IntlTest::assertEquals(const char* message,
1810                              const UnicodeString& expected,
1811                              const UnicodeString& actual,
1812                              UBool possibleDataError) {
1813     if (expected != actual) {
1814         if (possibleDataError) {
1815             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1816                   prettify(actual) +
1817                   "; expected " + prettify(expected));
1818         } else {
1819             errln((UnicodeString)"FAIL: " + message + "; got " +
1820                   prettify(actual) +
1821                   "; expected " + prettify(expected));
1822         }
1823         return FALSE;
1824     }
1825 #ifdef VERBOSE_ASSERTIONS
1826     else {
1827         logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1828     }
1829 #endif
1830     return TRUE;
1831 }
1832 
assertEquals(const char * message,const char * expected,const char * actual)1833 UBool IntlTest::assertEquals(const char* message,
1834                              const char* expected,
1835                              const char* actual) {
1836     if (uprv_strcmp(expected, actual) != 0) {
1837         errln((UnicodeString)"FAIL: " + message + "; got \"" +
1838               actual +
1839               "\"; expected \"" + expected + "\"");
1840         return FALSE;
1841     }
1842 #ifdef VERBOSE_ASSERTIONS
1843     else {
1844         logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1845     }
1846 #endif
1847     return TRUE;
1848 }
1849 
assertEquals(const char * message,int32_t expected,int32_t actual)1850 UBool IntlTest::assertEquals(const char* message,
1851                              int32_t expected,
1852                              int32_t actual) {
1853     if (expected != actual) {
1854         errln((UnicodeString)"FAIL: " + message + "; got " +
1855               actual + "=0x" + toHex(actual) +
1856               "; expected " + expected + "=0x" + toHex(expected));
1857         return FALSE;
1858     }
1859 #ifdef VERBOSE_ASSERTIONS
1860     else {
1861         logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
1862     }
1863 #endif
1864     return TRUE;
1865 }
1866 
assertEquals(const char * message,int64_t expected,int64_t actual)1867 UBool IntlTest::assertEquals(const char* message,
1868                              int64_t expected,
1869                              int64_t actual) {
1870     if (expected != actual) {
1871         errln((UnicodeString)"FAIL: " + message + "; got int64 " +
1872               Int64ToUnicodeString(actual) +
1873               "; expected " + Int64ToUnicodeString(expected) );
1874         return FALSE;
1875     }
1876 #ifdef VERBOSE_ASSERTIONS
1877     else {
1878       logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
1879     }
1880 #endif
1881     return TRUE;
1882 }
1883 
assertEquals(const char * message,UBool expected,UBool actual)1884 UBool IntlTest::assertEquals(const char* message,
1885                              UBool expected,
1886                              UBool actual) {
1887     if (expected != actual) {
1888         errln((UnicodeString)"FAIL: " + message + "; got " +
1889               toString(actual) +
1890               "; expected " + toString(expected));
1891         return FALSE;
1892     }
1893 #ifdef VERBOSE_ASSERTIONS
1894     else {
1895       logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1896     }
1897 #endif
1898     return TRUE;
1899 }
1900 
1901 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)1902 UBool IntlTest::assertEquals(const char* message,
1903                              const Formattable& expected,
1904                              const Formattable& actual,
1905                              UBool possibleDataError) {
1906     if (expected != actual) {
1907         if (possibleDataError) {
1908             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1909                   toString(actual) +
1910                   "; expected " + toString(expected));
1911         } else {
1912             errln((UnicodeString)"FAIL: " + message + "; got " +
1913                   toString(actual) +
1914                   "; expected " + toString(expected));
1915         }
1916         return FALSE;
1917     }
1918 #ifdef VERBOSE_ASSERTIONS
1919     else {
1920         logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1921     }
1922 #endif
1923     return TRUE;
1924 }
1925 #endif
1926 
1927 static char ASSERT_BUF[256];
1928 
extractToAssertBuf(const UnicodeString & message)1929 static const char* extractToAssertBuf(const UnicodeString& message) {
1930     UnicodeString buf;
1931     escape(message, buf);
1932     buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1933     ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1934     return ASSERT_BUF;
1935 }
1936 
assertTrue(const UnicodeString & message,UBool condition,UBool quiet)1937 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1938     return assertTrue(extractToAssertBuf(message), condition, quiet);
1939 }
1940 
assertFalse(const UnicodeString & message,UBool condition,UBool quiet)1941 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1942     return assertFalse(extractToAssertBuf(message), condition, quiet);
1943 }
1944 
assertSuccess(const UnicodeString & message,UErrorCode ec)1945 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1946     return assertSuccess(extractToAssertBuf(message), ec);
1947 }
1948 
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1949 UBool IntlTest::assertEquals(const UnicodeString& message,
1950                              const UnicodeString& expected,
1951                              const UnicodeString& actual,
1952                              UBool possibleDataError) {
1953     return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
1954 }
1955 
assertEquals(const UnicodeString & message,const char * expected,const char * actual)1956 UBool IntlTest::assertEquals(const UnicodeString& message,
1957                              const char* expected,
1958                              const char* actual) {
1959     return assertEquals(extractToAssertBuf(message), expected, actual);
1960 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)1961 UBool IntlTest::assertEquals(const UnicodeString& message,
1962                              UBool expected,
1963                              UBool actual) {
1964     return assertEquals(extractToAssertBuf(message), expected, actual);
1965 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)1966 UBool IntlTest::assertEquals(const UnicodeString& message,
1967                              int32_t expected,
1968                              int32_t actual) {
1969     return assertEquals(extractToAssertBuf(message), expected, actual);
1970 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)1971 UBool IntlTest::assertEquals(const UnicodeString& message,
1972                              int64_t expected,
1973                              int64_t actual) {
1974     return assertEquals(extractToAssertBuf(message), expected, actual);
1975 }
1976 
1977 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)1978 UBool IntlTest::assertEquals(const UnicodeString& message,
1979                              const Formattable& expected,
1980                              const Formattable& actual) {
1981     return assertEquals(extractToAssertBuf(message), expected, actual);
1982 }
1983 #endif
1984 
setProperty(const char * propline)1985 void IntlTest::setProperty(const char* propline) {
1986     if (numProps < kMaxProps) {
1987         proplines[numProps] = propline;
1988     }
1989     numProps++;
1990 }
1991 
getProperty(const char * prop)1992 const char* IntlTest::getProperty(const char* prop) {
1993     const char* val = NULL;
1994     for (int32_t i = 0; i < numProps; i++) {
1995         int32_t plen = uprv_strlen(prop);
1996         if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
1997                 && proplines[i][plen] == '='
1998                 && uprv_strncmp(proplines[i], prop, plen) == 0) {
1999             val = &(proplines[i][plen+1]);
2000             break;
2001         }
2002     }
2003     return val;
2004 }
2005 
2006 /*
2007  * Hey, Emacs, please set the following:
2008  *
2009  * Local Variables:
2010  * indent-tabs-mode: nil
2011  * End:
2012  *
2013  */
2014