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