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