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