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