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