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