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