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