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