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