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