• 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", static_cast<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=") + static_cast<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(static_cast<char16_t>(91)/*[*/);
226     s.append(_toString(f));
227     s.append(static_cast<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() + static_cast<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 + static_cast<long>(num); }
operator +(const UnicodeString & left,short num)253 UnicodeString operator+(const UnicodeString& left, short num)
254 { return left + static_cast<long>(num); }
operator +(const UnicodeString & left,int num)255 UnicodeString operator+(const UnicodeString& left, int num)
256 { return left + static_cast<long>(num); }
operator +(const UnicodeString & left,unsigned char num)257 UnicodeString operator+(const UnicodeString& left, unsigned char num)
258 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,unsigned short num)259 UnicodeString operator+(const UnicodeString& left, unsigned short num)
260 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,unsigned int num)261 UnicodeString operator+(const UnicodeString& left, unsigned int num)
262 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,float num)263 UnicodeString operator+(const UnicodeString& left, float num)
264 { return left + static_cast<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) == static_cast<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 = static_cast<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 = static_cast<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", static_cast<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, static_cast<FILE*>(testoutfp));
1129         if (isErr) currErr.append(buffer, length);
1130     }
1131 
1132     // replace each LineFeed by the indentation string
1133     message.findAndReplace(UnicodeString(static_cast<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, static_cast<FILE*>(testoutfp));
1140         if (isErr) currErr.append(buffer, length);
1141     }
1142 
1143     if (newline) {
1144         char newLine = '\n';
1145         fwrite(&newLine, sizeof(newLine), 1, static_cast<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(static_cast<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 = static_cast<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", static_cast<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, 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 = static_cast<int32_t>(endTime - startTime);
1565       printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1566              (diffTime % U_MILLIS_PER_DAY) / U_MILLIS_PER_HOUR,
1567              (diffTime % U_MILLIS_PER_HOUR) / U_MILLIS_PER_MINUTE,
1568              (diffTime % U_MILLIS_PER_MINUTE) / U_MILLIS_PER_SECOND,
1569              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 
fileExists(const char * fileName)1599 static bool fileExists(const char* fileName) {
1600     // Test for `srcDataDir` existing by checking for `srcDataDir`/message2/valid-tests.json
1601     U_ASSERT(fileName != nullptr);
1602     FILE *f = fopen(fileName, "r");
1603     if (f) {
1604         fclose(f);
1605         return true;
1606     }
1607     return false;
1608 }
1609 
1610 /**
1611  * Returns the path to icu/testdata/
1612  */
getSharedTestData(UErrorCode & err)1613 const char *IntlTest::getSharedTestData(UErrorCode& err) {
1614 #define SOURCE_TARBALL_TOP U_TOPSRCDIR U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1615 #define REPO_TOP SOURCE_TARBALL_TOP ".." U_FILE_SEP_STRING
1616 #define FILE_NAME U_FILE_SEP_STRING "message2" U_FILE_SEP_STRING "valid-tests.json"
1617     const char *srcDataDir = nullptr;
1618     const char *testFile = nullptr;
1619     if (U_SUCCESS(err)) {
1620 #ifdef U_TOPSRCDIR
1621         // Try U_TOPSRCDIR/../testdata (source tarball)
1622         srcDataDir = SOURCE_TARBALL_TOP "testdata" U_FILE_SEP_STRING;
1623         testFile = SOURCE_TARBALL_TOP "testdata" FILE_NAME;
1624         if (!fileExists(testFile)) {
1625             // If that doesn't exist, try U_TOPSRCDIR/../../testdata (in-repo)
1626             srcDataDir = REPO_TOP "testdata" U_FILE_SEP_STRING;
1627             testFile = REPO_TOP "testdata" FILE_NAME;
1628             if (!fileExists(testFile)) {
1629                 // If neither exists, return null
1630                 err = U_FILE_ACCESS_ERROR;
1631                 srcDataDir = nullptr;
1632             }
1633         }
1634 #else
1635         // Try ../../../../testdata (if we're in icu/source/test/intltest)
1636         // and ../../../../../../testdata (if we're in icu/source/test/intltest/Platform/(Debug|Release)
1637 #define TOP ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1638 #define TOP_TOP ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING TOP
1639         srcDataDir = TOP "testdata" U_FILE_SEP_STRING;
1640         testFile = TOP "testdata" FILE_NAME;
1641         if (!fileExists(testFile)) {
1642             srcDataDir = TOP_TOP "testdata" U_FILE_SEP_STRING;
1643             testFile = TOP_TOP "testdata" FILE_NAME;
1644             if (!fileExists(testFile)) {
1645                 err = U_FILE_ACCESS_ERROR;
1646                 srcDataDir = nullptr;
1647             }
1648         }
1649 #endif
1650     }
1651     return srcDataDir;
1652 }
1653 
getUnidataPath(char path[])1654 char *IntlTest::getUnidataPath(char path[]) {
1655     const int kUnicodeDataTxtLength = 15;  // strlen("UnicodeData.txt")
1656 
1657     // Look inside ICU_DATA first.
1658     strcpy(path, pathToDataDirectory());
1659     strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1660     FILE *f = fopen(path, "r");
1661     if(f != nullptr) {
1662         fclose(f);
1663         *(strchr(path, 0) - kUnicodeDataTxtLength) = 0;  // Remove the basename.
1664         return path;
1665     }
1666 
1667     // As a fallback, try to guess where the source data was located
1668     // at the time ICU was built, and look there.
1669 #   ifdef U_TOPSRCDIR
1670         strcpy(path, U_TOPSRCDIR  U_FILE_SEP_STRING "data");
1671 #   else
1672         UErrorCode errorCode = U_ZERO_ERROR;
1673         const char *testDataPath = loadTestData(errorCode);
1674         if(U_FAILURE(errorCode)) {
1675             it_errln(UnicodeString(
1676                         "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1677                     u_errorName(errorCode));
1678             return nullptr;
1679         }
1680         strcpy(path, testDataPath);
1681         strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1682                      U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1683                      U_FILE_SEP_STRING "data");
1684 #   endif
1685     strcat(path, U_FILE_SEP_STRING);
1686     strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1687     f = fopen(path, "r");
1688     if(f != nullptr) {
1689         fclose(f);
1690         *(strchr(path, 0) - kUnicodeDataTxtLength) = 0;  // Remove the basename.
1691         return path;
1692     }
1693     return nullptr;
1694 }
1695 
1696 /* returns the path to icu/source/data */
pathToDataDirectory()1697 const char *  IntlTest::pathToDataDirectory()
1698 {
1699     return ctest_dataSrcDir();
1700 }
1701 
1702 /*
1703  * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1704  * It converts an invariant-character string into a UnicodeString, with
1705  * unescaping \u sequences.
1706  */
CharsToUnicodeString(const char * chars)1707 UnicodeString CharsToUnicodeString(const char* chars){
1708     return UnicodeString(chars, -1, US_INV).unescape();
1709 }
1710 
ctou(const char * chars)1711 UnicodeString ctou(const char* chars) {
1712     return CharsToUnicodeString(chars);
1713 }
1714 
1715 #define RAND_M  (714025)
1716 #define RAND_IA (1366)
1717 #define RAND_IC (150889)
1718 
1719 static int32_t RAND_SEED;
1720 
1721 /**
1722  * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1723  * with care: Does not return all possible values; returns one of
1724  * 714,025 values, uniformly spaced.  However, the period is
1725  * effectively infinite.  See: Numerical Recipes, section 7.1.
1726  *
1727  * @param seedp pointer to seed. Set *seedp to any negative value
1728  * to restart the sequence.
1729  */
random(int32_t * seedp)1730 float IntlTest::random(int32_t* seedp) {
1731     static int32_t iy, ir[98];
1732     static UBool first=true;
1733     int32_t j;
1734     if (*seedp < 0 || first) {
1735         first = false;
1736         if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1737         for (j=1;j<=97;++j) {
1738             *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1739             ir[j]=(*seedp);
1740         }
1741         *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1742         iy=(*seedp);
1743     }
1744     j = static_cast<int32_t>(1 + 97.0 * iy / RAND_M);
1745     U_ASSERT(j>=1 && j<=97);
1746     iy=ir[j];
1747     *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1748     ir[j]=(*seedp);
1749     return static_cast<float>(iy) / RAND_M;
1750 }
1751 
1752 /**
1753  * Convenience method using a global seed.
1754  */
random()1755 float IntlTest::random() {
1756     return random(&RAND_SEED);
1757 }
1758 
1759 
1760 /*
1761  * Integer random number class implementation.
1762  * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1763  */
icu_rand(uint32_t seed)1764 IntlTest::icu_rand::icu_rand(uint32_t seed) {
1765     seed = seed % 2147483647UL;
1766     if (seed == 0) {
1767         seed = 1;
1768     }
1769     fLast = seed;
1770 }
1771 
~icu_rand()1772 IntlTest::icu_rand::~icu_rand() {}
1773 
seed(uint32_t seed)1774 void IntlTest::icu_rand::seed(uint32_t seed) {
1775     if (seed == 0) {
1776         seed = 1;
1777     }
1778     fLast = seed;
1779 }
1780 
operator ()()1781 uint32_t IntlTest::icu_rand::operator() () {
1782     fLast = (static_cast<uint64_t>(fLast) * 48271UL) % 2147483647UL;
1783     return fLast;
1784 }
1785 
getSeed()1786 uint32_t IntlTest::icu_rand::getSeed() {
1787     return fLast;
1788 }
1789 
1790 
1791 
toHex(int32_t i)1792 static inline char16_t toHex(int32_t i) {
1793     return static_cast<char16_t>(i + (i < 10 ? 0x30 : (0x41 - 10)));
1794 }
1795 
escape(const UnicodeString & s,UnicodeString & result)1796 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1797     for (int32_t i=0; i<s.length(); ++i) {
1798         char16_t c = s[i];
1799         if (c <= static_cast<char16_t>(0x7F)) {
1800             result += c;
1801         } else {
1802             result += static_cast<char16_t>(0x5c);
1803             result += static_cast<char16_t>(0x75);
1804             result += toHex((c >> 12) & 0xF);
1805             result += toHex((c >>  8) & 0xF);
1806             result += toHex((c >>  4) & 0xF);
1807             result += toHex( c        & 0xF);
1808         }
1809     }
1810     return result;
1811 }
1812 
1813 #define VERBOSE_ASSERTIONS
1814 
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1815 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1816     if (file != nullptr) {
1817         if (!condition) {
1818             if (possibleDataError) {
1819                 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1820             } else {
1821                 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1822             }
1823         } else if (!quiet) {
1824             logln("%s:%d: Ok: %s", file, line, message);
1825         }
1826     } else {
1827         if (!condition) {
1828             if (possibleDataError) {
1829                 dataerrln("FAIL: assertTrue() failed: %s", message);
1830             } else {
1831                 errln("FAIL: assertTrue() failed: %s", message);
1832             }
1833         } else if (!quiet) {
1834             logln("Ok: %s", message);
1835         }
1836 
1837     }
1838     return condition;
1839 }
1840 
assertFalse(const char * message,UBool condition,UBool quiet,UBool possibleDataError)1841 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
1842     if (condition) {
1843         if (possibleDataError) {
1844             dataerrln("FAIL: assertFalse() failed: %s", message);
1845         } else {
1846             errln("FAIL: assertFalse() failed: %s", message);
1847         }
1848     } else if (!quiet) {
1849         logln("Ok: %s", message);
1850     }
1851     return !condition;
1852 }
1853 
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1854 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1855     if( file==nullptr ) {
1856       file = ""; // prevent failure if no file given
1857     }
1858     if (U_FAILURE(ec)) {
1859         if (possibleDataError) {
1860           dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1861         } else {
1862           errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1863         }
1864         return false;
1865     } else {
1866       logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1867     }
1868     return true;
1869 }
1870 
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1871 UBool IntlTest::assertEquals(const char* message,
1872                              const UnicodeString& expected,
1873                              const UnicodeString& actual,
1874                              UBool possibleDataError) {
1875     if (expected != actual) {
1876         if (possibleDataError) {
1877             dataerrln(UnicodeString("FAIL: ") + message + "; got " +
1878                   prettify(actual) +
1879                   "; expected " + prettify(expected));
1880         } else {
1881             errln(UnicodeString("FAIL: ") + message + "; got " +
1882                   prettify(actual) +
1883                   "; expected " + prettify(expected));
1884         }
1885         return false;
1886     }
1887 #ifdef VERBOSE_ASSERTIONS
1888     else {
1889         logln(UnicodeString("Ok: ") + message + "; got " + prettify(actual));
1890     }
1891 #endif
1892     return true;
1893 }
1894 
assertEquals(const char * message,const char * expected,const char * actual)1895 UBool IntlTest::assertEquals(const char* message,
1896                              const char* expected,
1897                              const char* actual) {
1898     U_ASSERT(expected != nullptr);
1899     U_ASSERT(actual != nullptr);
1900     if (uprv_strcmp(expected, actual) != 0) {
1901         errln(UnicodeString("FAIL: ") + message + "; got \"" +
1902               actual +
1903               "\"; expected \"" + expected + "\"");
1904         return false;
1905     }
1906 #ifdef VERBOSE_ASSERTIONS
1907     else {
1908         logln(UnicodeString("Ok: ") + message + "; got \"" + actual + "\"");
1909     }
1910 #endif
1911     return true;
1912 }
1913 
assertEquals(const char * message,int32_t expected,int32_t actual)1914 UBool IntlTest::assertEquals(const char* message,
1915                              int32_t expected,
1916                              int32_t actual) {
1917     if (expected != actual) {
1918         errln(UnicodeString("FAIL: ") + message + "; got " +
1919               actual + "=0x" + toHex(actual) +
1920               "; expected " + expected + "=0x" + toHex(expected));
1921         return false;
1922     }
1923 #ifdef VERBOSE_ASSERTIONS
1924     else {
1925         logln(UnicodeString("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual));
1926     }
1927 #endif
1928     return true;
1929 }
1930 
assertEquals(const char * message,int64_t expected,int64_t actual)1931 UBool IntlTest::assertEquals(const char* message,
1932                              int64_t expected,
1933                              int64_t actual) {
1934     if (expected != actual) {
1935         errln(UnicodeString("FAIL: ") + message + "; got int64 " +
1936               Int64ToUnicodeString(actual) +
1937               "; expected " + Int64ToUnicodeString(expected) );
1938         return false;
1939     }
1940 #ifdef VERBOSE_ASSERTIONS
1941     else {
1942       logln(UnicodeString("Ok: ") + message + "; got int64 " + Int64ToUnicodeString(actual));
1943     }
1944 #endif
1945     return true;
1946 }
1947 
assertEquals(const char * message,double expected,double actual)1948 UBool IntlTest::assertEquals(const char* message,
1949                              double expected,
1950                              double actual) {
1951     bool bothNaN = std::isnan(expected) && std::isnan(actual);
1952     if (expected != actual && !bothNaN) {
1953         errln(UnicodeString("FAIL: ") + message + "; got " +
1954               actual +
1955               "; expected " + expected);
1956         return false;
1957     }
1958 #ifdef VERBOSE_ASSERTIONS
1959     else {
1960         logln(UnicodeString("Ok: ") + message + "; got " + actual);
1961     }
1962 #endif
1963     return true;
1964 }
1965 
assertEquals(const char * message,UBool expected,UBool actual)1966 UBool IntlTest::assertEquals(const char* message,
1967                              UBool expected,
1968                              UBool actual) {
1969     if (expected != actual) {
1970         errln(UnicodeString("FAIL: ") + message + "; got " +
1971               toString(actual) +
1972               "; expected " + toString(expected));
1973         return false;
1974     }
1975 #ifdef VERBOSE_ASSERTIONS
1976     else {
1977       logln(UnicodeString("Ok: ") + message + "; got " + toString(actual));
1978     }
1979 #endif
1980     return true;
1981 }
1982 
1983 
assertEquals(const char * message,UErrorCode expected,UErrorCode actual)1984 UBool IntlTest::assertEquals(const char* message,
1985                              UErrorCode expected,
1986                              UErrorCode actual) {
1987     if (expected != actual) {
1988         errln(UnicodeString("FAIL: ") + message + "; got " +
1989               u_errorName(actual) +
1990               "; expected " + u_errorName(expected));
1991         return false;
1992     }
1993 #ifdef VERBOSE_ASSERTIONS
1994     else {
1995         logln(UnicodeString("Ok: ") + message + "; got " + u_errorName(actual));
1996     }
1997 #endif
1998     return true;
1999 }
2000 
assertEquals(const char * message,const UnicodeSet & expected,const UnicodeSet & actual)2001 UBool IntlTest::assertEquals(const char* message,
2002                              const UnicodeSet& expected,
2003                              const UnicodeSet& actual) {
2004     IcuTestErrorCode status(*this, "assertEqualsUniSet");
2005     if (expected != actual) {
2006         errln(UnicodeString("FAIL: ") + message + "; got " +
2007               toString(actual, status) +
2008               "; expected " + toString(expected, status));
2009         return false;
2010     }
2011 #ifdef VERBOSE_ASSERTIONS
2012     else {
2013         logln(UnicodeString("Ok: ") + message + "; got " + toString(actual, status));
2014     }
2015 #endif
2016     return true;
2017 }
2018 
2019 
2020 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)2021 UBool IntlTest::assertEquals(const char* message,
2022                              const Formattable& expected,
2023                              const Formattable& actual,
2024                              UBool possibleDataError) {
2025     if (expected != actual) {
2026         if (possibleDataError) {
2027             dataerrln(UnicodeString("FAIL: ") + message + "; got " +
2028                   toString(actual) +
2029                   "; expected " + toString(expected));
2030         } else {
2031             errln(UnicodeString("FAIL: ") + message + "; got " +
2032                   toString(actual) +
2033                   "; expected " + toString(expected));
2034         }
2035         return false;
2036     }
2037 #ifdef VERBOSE_ASSERTIONS
2038     else {
2039         logln(UnicodeString("Ok: ") + message + "; got " + toString(actual));
2040     }
2041 #endif
2042     return true;
2043 }
2044 #endif
2045 
vectorToString(const std::vector<std::string> & strings)2046 std::string vectorToString(const std::vector<std::string>& strings) {
2047     std::string result = "{";
2048     bool first = true;
2049     for (auto element : strings) {
2050         if (first) {
2051             first = false;
2052         } else {
2053             result += ", ";
2054         }
2055         result += "\"";
2056         result += element;
2057         result += "\"";
2058     }
2059     result += "}";
2060     return result;
2061 }
2062 
assertEquals(const char * message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2063 UBool IntlTest::assertEquals(const char* message,
2064                              const std::vector<std::string>& expected,
2065                              const std::vector<std::string>& actual) {
2066     if (expected != actual) {
2067         std::string expectedAsString = vectorToString(expected);
2068         std::string actualAsString = vectorToString(actual);
2069         errln(UnicodeString("FAIL: ") + message +
2070             "; got " + actualAsString.c_str() +
2071             "; expected " + expectedAsString.c_str());
2072         return false;
2073     }
2074 #ifdef VERBOSE_ASSERTIONS
2075     else {
2076         logln(UnicodeString("Ok: ") + message + "; got " + vectorToString(actual).c_str());
2077     }
2078 #endif
2079     return true;
2080 }
2081 
assertNotEquals(const char * message,int32_t expectedNot,int32_t actual)2082 UBool IntlTest::assertNotEquals(const char* message,
2083                                 int32_t expectedNot,
2084                                 int32_t actual) {
2085     if (expectedNot == actual) {
2086         errln(UnicodeString("FAIL: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2087               "; expected != " + expectedNot);
2088         return false;
2089     }
2090 #ifdef VERBOSE_ASSERTIONS
2091     else {
2092         logln(UnicodeString("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2093               " != " + expectedNot);
2094     }
2095 #endif
2096     return true;
2097 }
2098 
assertEqualsNear(const char * message,double expected,double actual,double delta)2099 UBool IntlTest::assertEqualsNear(const char* message,
2100                                  double expected,
2101                                  double actual,
2102                                  double delta) {
2103     bool bothNaN = std::isnan(expected) && std::isnan(actual);
2104     bool bothPosInf = uprv_isPositiveInfinity(expected) && uprv_isPositiveInfinity(actual);
2105     bool bothNegInf = uprv_isNegativeInfinity(expected) && uprv_isNegativeInfinity(actual);
2106     if (bothPosInf || bothNegInf || bothNaN) {
2107         // We don't care about delta in these cases
2108         return true;
2109     }
2110     if (std::isnan(delta) || std::isinf(delta)) {
2111         errln(UnicodeString("FAIL: ") + message + "; nonsensical delta " + delta +
2112               " - delta may not be NaN or Inf. (Got " + actual + "; expected " + expected + ".)");
2113         return false;
2114     }
2115     double difference = std::abs(expected - actual);
2116     if (expected != actual && (difference > delta || std::isnan(difference))) {
2117         errln(UnicodeString("FAIL: ") + message + "; got " + actual + "; expected " + expected +
2118               "; acceptable delta " + delta);
2119         return false;
2120     }
2121 #ifdef VERBOSE_ASSERTIONS
2122     else {
2123         logln(UnicodeString("Ok: ") + message + "; got " + actual);
2124     }
2125 #endif
2126     return true;
2127 }
2128 
2129 static char ASSERT_BUF[256];
2130 
extractToAssertBuf(const UnicodeString & message)2131 static const char* extractToAssertBuf(const UnicodeString& message) {
2132     UnicodeString buf;
2133     escape(message, buf);
2134     buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF) - 1, nullptr);
2135     ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
2136     return ASSERT_BUF;
2137 }
2138 
assertTrue(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2139 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2140     return assertTrue(extractToAssertBuf(message), condition, quiet, possibleDataError);
2141 }
2142 
assertFalse(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2143 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2144     return assertFalse(extractToAssertBuf(message), condition, quiet, possibleDataError);
2145 }
2146 
assertSuccess(const UnicodeString & message,UErrorCode ec)2147 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2148     return assertSuccess(extractToAssertBuf(message), ec);
2149 }
2150 
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)2151 UBool IntlTest::assertEquals(const UnicodeString& message,
2152                              const UnicodeString& expected,
2153                              const UnicodeString& actual,
2154                              UBool possibleDataError) {
2155     return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
2156 }
2157 
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2158 UBool IntlTest::assertEquals(const UnicodeString& message,
2159                              const char* expected,
2160                              const char* actual) {
2161     return assertEquals(extractToAssertBuf(message), expected, actual);
2162 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2163 UBool IntlTest::assertEquals(const UnicodeString& message,
2164                              UBool expected,
2165                              UBool actual) {
2166     return assertEquals(extractToAssertBuf(message), expected, actual);
2167 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2168 UBool IntlTest::assertEquals(const UnicodeString& message,
2169                              int32_t expected,
2170                              int32_t actual) {
2171     return assertEquals(extractToAssertBuf(message), expected, actual);
2172 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2173 UBool IntlTest::assertEquals(const UnicodeString& message,
2174                              int64_t expected,
2175                              int64_t actual) {
2176     return assertEquals(extractToAssertBuf(message), expected, actual);
2177 }
assertEquals(const UnicodeString & message,double expected,double actual)2178 UBool IntlTest::assertEquals(const UnicodeString& message,
2179                              double expected,
2180                              double actual) {
2181     return assertEquals(extractToAssertBuf(message), expected, actual);
2182 }
assertEquals(const UnicodeString & message,UErrorCode expected,UErrorCode actual)2183 UBool IntlTest::assertEquals(const UnicodeString& message,
2184                              UErrorCode expected,
2185                              UErrorCode actual) {
2186     return assertEquals(extractToAssertBuf(message), expected, actual);
2187 }
assertEquals(const UnicodeString & message,const UnicodeSet & expected,const UnicodeSet & actual)2188 UBool IntlTest::assertEquals(const UnicodeString& message,
2189                              const UnicodeSet& expected,
2190                              const UnicodeSet& actual) {
2191     return assertEquals(extractToAssertBuf(message), expected, actual);
2192 }
assertEquals(const UnicodeString & message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2193 UBool IntlTest::assertEquals(const UnicodeString& message,
2194                              const std::vector<std::string>& expected,
2195                              const std::vector<std::string>& actual) {
2196     return assertEquals(extractToAssertBuf(message), expected, actual);
2197 }
assertNotEquals(const UnicodeString & message,int32_t expectedNot,int32_t actual)2198 UBool IntlTest::assertNotEquals(const UnicodeString &message,
2199                                 int32_t expectedNot,
2200                                 int32_t actual) {
2201     return assertNotEquals(extractToAssertBuf(message), expectedNot, actual);
2202 }
assertEqualsNear(const UnicodeString & message,double expected,double actual,double delta)2203 UBool IntlTest::assertEqualsNear(const UnicodeString& message,
2204                                  double expected,
2205                                  double actual,
2206                                  double delta) {
2207     return assertEqualsNear(extractToAssertBuf(message), expected, actual, delta);
2208 }
2209 
2210 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2211 UBool IntlTest::assertEquals(const UnicodeString& message,
2212                              const Formattable& expected,
2213                              const Formattable& actual) {
2214     return assertEquals(extractToAssertBuf(message), expected, actual);
2215 }
2216 #endif
2217 
setProperty(const char * propline)2218 void IntlTest::setProperty(const char* propline) {
2219     if (numProps < kMaxProps) {
2220         proplines[numProps] = propline;
2221     }
2222     numProps++;
2223 }
2224 
getProperty(const char * prop)2225 const char* IntlTest::getProperty(const char* prop) {
2226     const char* val = nullptr;
2227     for (int32_t i = 0; i < numProps; i++) {
2228         int32_t plen = static_cast<int32_t>(uprv_strlen(prop));
2229         if (static_cast<int32_t>(uprv_strlen(proplines[i])) > plen + 1
2230                 && proplines[i][plen] == '='
2231                 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2232             val = &(proplines[i][plen+1]);
2233             break;
2234         }
2235     }
2236     return val;
2237 }
2238 
2239 //-------------------------------------------------------------------------------
2240 //
2241 //    ReadAndConvertFile   Read a text data file, convert it to UChars, and
2242 //    return the data in one big char16_t * buffer, which the caller must delete.
2243 //
2244 //    parameters:
2245 //          fileName:   the name of the file, with no directory part.  The test data directory
2246 //                      is assumed.
2247 //          ulen        an out parameter, receives the actual length (in UChars) of the file data.
2248 //          encoding    The file encoding.  If the file contains a BOM, that will override the encoding
2249 //                      specified here.  The BOM, if it exists, will be stripped from the returned data.
2250 //                      Pass nullptr for the system default encoding.
2251 //          status
2252 //    returns:
2253 //                      The file data, converted to char16_t.
2254 //                      The caller must delete this when done with
2255 //                           delete [] theBuffer;
2256 //
2257 //
2258 //--------------------------------------------------------------------------------
ReadAndConvertFile(const char * fileName,int & ulen,const char * encoding,UErrorCode & status)2259 char16_t *IntlTest::ReadAndConvertFile(const char *fileName, int &ulen, const char *encoding, UErrorCode &status) {
2260     char16_t    *retPtr  = nullptr;
2261     char        *fileBuf = nullptr;
2262     UConverter* conv     = nullptr;
2263     FILE        *f       = nullptr;
2264 
2265     ulen = 0;
2266     if (U_FAILURE(status)) {
2267         return retPtr;
2268     }
2269 
2270     //
2271     //  Open the file.
2272     //
2273     f = fopen(fileName, "rb");
2274     if (f == nullptr) {
2275         dataerrln("Error opening test data file %s\n", fileName);
2276         status = U_FILE_ACCESS_ERROR;
2277         return nullptr;
2278     }
2279     //
2280     //  Read it in
2281     //
2282     int   fileSize;
2283     int   amt_read;
2284 
2285     fseek( f, 0, SEEK_END);
2286     fileSize = ftell(f);
2287     fileBuf = new char[fileSize];
2288     fseek(f, 0, SEEK_SET);
2289     amt_read = static_cast<int>(fread(fileBuf, 1, fileSize, f));
2290     if (amt_read != fileSize || fileSize <= 0) {
2291         errln("Error reading test data file.");
2292         goto cleanUpAndReturn;
2293     }
2294 
2295     //
2296     // Look for a Unicode Signature (BOM) on the data just read
2297     //
2298     int32_t        signatureLength;
2299     const char *   fileBufC;
2300     const char*    bomEncoding;
2301 
2302     fileBufC = fileBuf;
2303     bomEncoding = ucnv_detectUnicodeSignature(
2304         fileBuf, fileSize, &signatureLength, &status);
2305     if(bomEncoding!=nullptr ){
2306         fileBufC  += signatureLength;
2307         fileSize  -= signatureLength;
2308         encoding = bomEncoding;
2309     }
2310 
2311     //
2312     // Open a converter to take the rule file to UTF-16
2313     //
2314     conv = ucnv_open(encoding, &status);
2315     if (U_FAILURE(status)) {
2316         goto cleanUpAndReturn;
2317     }
2318 
2319     //
2320     // Convert the rules to char16_t.
2321     //  Preflight first to determine required buffer size.
2322     //
2323     ulen = ucnv_toUChars(conv,
2324         nullptr,           //  dest,
2325         0,              //  destCapacity,
2326         fileBufC,
2327         fileSize,
2328         &status);
2329     if (status == U_BUFFER_OVERFLOW_ERROR) {
2330         // Buffer Overflow is expected from the preflight operation.
2331         status = U_ZERO_ERROR;
2332 
2333         retPtr = new char16_t[ulen+1];
2334         ucnv_toUChars(conv,
2335             retPtr,       //  dest,
2336             ulen+1,
2337             fileBufC,
2338             fileSize,
2339             &status);
2340     }
2341 
2342 cleanUpAndReturn:
2343     fclose(f);
2344     delete []fileBuf;
2345     ucnv_close(conv);
2346     if (U_FAILURE(status)) {
2347         errln("ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status));
2348         delete []retPtr;
2349         retPtr = nullptr;
2350         ulen   = 0;
2351     }
2352     return retPtr;
2353 }
2354 
2355 #if !UCONFIG_NO_BREAK_ITERATION
LSTMDataIsBuilt()2356 UBool LSTMDataIsBuilt() {
2357   // If we can find the LSTM data, the RBBI will use the LSTM engine.
2358   // So we skip the test which depending on the dictionary data.
2359   UErrorCode status = U_ZERO_ERROR;
2360   DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_THAI, status));
2361   UBool thaiDataIsBuilt = U_SUCCESS(status);
2362   status = U_ZERO_ERROR;
2363   DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_MYANMAR, status));
2364   UBool burmeseDataIsBuilt = U_SUCCESS(status);
2365   return thaiDataIsBuilt | burmeseDataIsBuilt;
2366 }
2367 
skipLSTMTest()2368 UBool IntlTest::skipLSTMTest() {
2369    return ! LSTMDataIsBuilt();
2370 }
skipDictionaryTest()2371 UBool IntlTest::skipDictionaryTest() {
2372    return LSTMDataIsBuilt();
2373 }
2374 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */
2375 
2376 /*
2377  * Hey, Emacs, please set the following:
2378  *
2379  * Local Variables:
2380  * indent-tabs-mode: nil
2381  * End:
2382  *
2383  */
2384