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