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