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