X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b75a7d8f3b4adbae880cab104ce2c6a50eee4db2..48b980fed3435926e0b3a8d72ecb58be703a1c7a:/icuSources/test/intltest/intltest.cpp diff --git a/icuSources/test/intltest/intltest.cpp b/icuSources/test/intltest/intltest.cpp index 5251c66c..9094de90 100644 --- a/icuSources/test/intltest/intltest.cpp +++ b/icuSources/test/intltest/intltest.cpp @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2003, International Business Machines Corporation and + * Copyright (c) 1997-2008, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -22,13 +22,22 @@ #include "unicode/smpdtfmt.h" #include "unicode/ucnv.h" #include "unicode/uclean.h" +#include "unicode/timezone.h" +#include "unicode/curramt.h" +#include "unicode/putil.h" #include "intltest.h" #include "caltztst.h" #include "itmajor.h" -#include "tsmutex.h" - +#include "cstring.h" #include "umutex.h" +#include "uassert.h" +#include "cmemory.h" +#include "uoptions.h" + +#include "putilimp.h" // for uprv_getUTCtime() +#include "unicode/locid.h" + #ifdef XP_MAC_CONSOLE #include @@ -50,16 +59,6 @@ UnicodeString UCharToUnicodeString(UChar c) { return UnicodeString(c); } -// [LIU] Just to get things working -UnicodeString -operator+(const UnicodeString& left, - const UnicodeString& right) -{ - UnicodeString str(left); - str += right; - return str; -} - // [rtg] Just to get things working UnicodeString operator+(const UnicodeString& left, @@ -87,6 +86,22 @@ operator+(const UnicodeString& left, return left + buffer; } +UnicodeString +Int64ToUnicodeString(int64_t num) +{ + char buffer[64]; // nos changed from 10 to 64 + char danger = 'p'; // guard against overrunning the buffer (rtg) + +#ifdef U_WINDOWS + sprintf(buffer, "%I64d", num); +#else + sprintf(buffer, "%lld", (long long)num); +#endif + assert(danger == 'p'); + + return buffer; +} + // [LIU] Just to get things working UnicodeString operator+(const UnicodeString& left, @@ -95,7 +110,11 @@ operator+(const UnicodeString& left, char buffer[64]; // was 32, made it arbitrarily bigger (rtg) char danger = 'p'; // guard against overrunning the buffer (rtg) - sprintf(buffer, "%.30g", num); // nos changed from 99 to 30 + // IEEE floating point has 52 bits of mantissa, plus one assumed bit + // 53*log(2)/log(10) = 15.95 + // so there is no need to show more than 16 digits. [alan] + + sprintf(buffer, "%.17g", num); assert(danger == 'p'); return left + buffer; @@ -104,10 +123,9 @@ operator+(const UnicodeString& left, #if !UCONFIG_NO_FORMATTING /** - * Originally coded this as operator+, but that makes the expression - * + char* ambiguous. - liu + * Return a string display for for this, without surrounding braces. */ -UnicodeString toString(const Formattable& f) { +UnicodeString _toString(const Formattable& f) { UnicodeString s; switch (f.getType()) { case Formattable::kDate: @@ -117,45 +135,75 @@ UnicodeString toString(const Formattable& f) { if (U_SUCCESS(status)) { FieldPosition pos; fmt.format(f.getDate(), s, pos); - s.insert(0, "[Date:"); - s.insert(s.length(), (UChar)0x005d); + s.insert(0, "Date:"); } else { - s = UnicodeString("[Error creating date format]"); + s = UnicodeString("Error creating date format]"); } } break; case Formattable::kDouble: - s = UnicodeString("[Double:") + f.getDouble() + "]"; + s = UnicodeString("double:") + f.getDouble(); break; case Formattable::kLong: - s = UnicodeString("[Long:") + f.getLong() + "]"; + s = UnicodeString("long:") + f.getLong(); break; + + case Formattable::kInt64: + s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64()); + break; + case Formattable::kString: f.getString(s); - s.insert(0, "[String:"); - s.insert(s.length(), (UChar)0x005d); + s.insert(0, "String:"); break; case Formattable::kArray: { int32_t i, n; const Formattable* array = f.getArray(n); - s.insert(0, UnicodeString("[Array:")); + s.insert(0, UnicodeString("Array:")); UnicodeString delim(", "); for (i=0; i 0) { s.append(delim); } - s = s + toString(array[i]); + s = s + _toString(array[i]); } - s.append(UChar(0x005d)); } break; + case Formattable::kObject: + if (f.getObject()->getDynamicClassID() == + CurrencyAmount::getStaticClassID()) { + const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject(); + s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency()); + } else { + s = UnicodeString("Unknown UObject"); + } + break; + default: + s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType(); + break; } return s; } +/** + * Originally coded this as operator+, but that makes the expression + * + char* ambiguous. - liu + */ +UnicodeString toString(const Formattable& f) { + UnicodeString s((UChar)91/*[*/); + s.append(_toString(f)); + s.append((UChar)0x5d/*]*/); + return s; +} + #endif +// useful when operator+ won't cooperate +UnicodeString toString(int32_t n) { + return UnicodeString() + (long)n; +} + // stephen - cleaned up 05/05/99 UnicodeString operator+(const UnicodeString& left, char num) { return left + (long)num; } @@ -297,68 +345,6 @@ IntlTest::prettify(const UnicodeString &source, UBool parseBackslash) return target; } -#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) || defined(OS2) -#define PREV_DIR ".." -#else -#define PREV_DIR "/../" -#endif - -void -IntlTest::pathnameInContext( char* fullname, int32_t maxsize, const char* relPath ) //nosmac -{ - const char* mainDir; - char sepChar; - const char inpSepChar = '|'; - - // So what's going on is that ICU_DATA during tests points to: - // ICU | source | data - //and we want ICU | source | - // - // We'll add | test | testdata - // - // So, just add a .. here - back up one level - - mainDir = u_getDataDirectory(); - sepChar = U_FILE_SEP_CHAR; - char sepString[] = U_FILE_SEP_STRING; - -#if defined(XP_MAC) - Str255 volName; - int16_t volNum; - OSErr err = GetVol( volName, &volNum ); - if (err != noErr) - volName[0] = 0; - mainDir = (char*) &(volName[1]); - mainDir[volName[0]] = 0; -#else - char mainDirBuffer[255]; - if(mainDir!=NULL) { - strcpy(mainDirBuffer, mainDir); - strcat(mainDirBuffer, PREV_DIR); - } else { - mainDirBuffer[0]='\0'; - } - mainDir=mainDirBuffer; -#endif - - if (relPath[0] == '|') - relPath++; - int32_t lenMainDir = strlen(mainDir); - int32_t lenRelPath = strlen(relPath); - if (maxsize < lenMainDir + lenRelPath + 2) { - fullname[0] = 0; - return; - } - strcpy(fullname, mainDir); - strcat(fullname, sepString); - strcat(fullname, relPath); - char* tmp = strchr(fullname, inpSepChar); - while (tmp) { - *tmp = sepChar; - tmp = strchr(tmp+1, inpSepChar); - } -} - /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already * set, try to deduce the directory in which ICU was built, * and set ICU_DATA to "icu/source/data" in that location. @@ -381,7 +367,7 @@ void IntlTest::setICU_DATA() { // may not be the same as the source directory, depending on // the configure options used. At any rate, // set the data path to the built data from this directory. - // The value is complete with quotes, so it can be used + // The value is complete with quotes, so it can be used // as-is as a string constant. #if defined (U_TOPBUILDDIR) @@ -498,56 +484,28 @@ void it_errln( UnicodeString message ) IntlTest::gTest->errln( message ); } -IntlTest& operator<<(IntlTest& test, const UnicodeString& string) +void it_dataerr( UnicodeString message ) { -/* NULL shouldn't happen */ -// if (&test == NULL) -// return *((IntlTest*) NULL); - test.log( string ); - return test; -} - -IntlTest& operator<<(IntlTest& test, const char* string) -{ -/* NULL shouldn't happen */ -// if (&test == NULL) -// return *((IntlTest*) NULL); - test.log( string ); - return test; -} - -IntlTest& operator<<(IntlTest& test, const int32_t num) -{ -/* NULL shouldn't happen */ -// if (&test == NULL) -// return *((IntlTest*) NULL); - char convert[20]; - sprintf(convert, "%li", (long)num); - test.log(convert); - return test; -} - -IntlTest& endl( IntlTest& test ) -{ - test.logln(); - return test; + if (IntlTest::gTest) + IntlTest::gTest->dataerr( message ); } -IntlTest& operator<<(IntlTest& test, IntlTest& ( * _f)(IntlTest&)) +void it_dataerrln( UnicodeString message ) { - (*_f)(test); - return test; + if (IntlTest::gTest) + IntlTest::gTest->dataerrln( message ); } - IntlTest::IntlTest() { caller = NULL; - path = NULL; + testPath = NULL; LL_linestart = TRUE; errorCount = 0; + dataErrorCount = 0; verbose = FALSE; no_err_msg = FALSE; + warn_on_missing_data = FALSE; quick = FALSE; leaks = FALSE; testoutfp = stdout; @@ -558,6 +516,7 @@ void IntlTest::setCaller( IntlTest* callingTest ) { caller = callingTest; if (caller) { + warn_on_missing_data = caller->warn_on_missing_data; verbose = caller->verbose; no_err_msg = caller->no_err_msg; quick = caller->quick; @@ -570,12 +529,12 @@ UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par ) { execCount--; // correct a previously assumed test-exec, as this only calls a subtest testToBeCalled.setCaller( this ); - return testToBeCalled.runTest( path, par ); + return testToBeCalled.runTest( testPath, par ); } void IntlTest::setPath( char* pathVal ) { - this->path = pathVal; + this->testPath = pathVal; } UBool IntlTest::setVerbose( UBool verboseVal ) @@ -585,6 +544,13 @@ UBool IntlTest::setVerbose( UBool verboseVal ) return rval; } +UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal ) +{ + UBool rval = this->warn_on_missing_data; + this->warn_on_missing_data = warn_on_missing_dataVal; + return rval; +} + UBool IntlTest::setNoErrMsg( UBool no_err_msgVal ) { UBool rval = this->no_err_msg; @@ -611,6 +577,11 @@ int32_t IntlTest::getErrors( void ) return errorCount; } +int32_t IntlTest::getDataErrors( void ) +{ + return dataErrorCount; +} + UBool IntlTest::runTest( char* name, char* par ) { UBool rval; @@ -619,14 +590,14 @@ UBool IntlTest::runTest( char* name, char* par ) if (name) pos = strchr( name, delim ); // check if name contains path (by looking for '/') if (pos) { - path = pos+1; // store subpath for calling subtest + testPath = pos+1; // store subpath for calling subtest *pos = 0; // split into two strings }else{ - path = NULL; + testPath = NULL; } if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) { - rval = runTestLoop( NULL, NULL ); + rval = runTestLoop( NULL, par ); }else if (strcmp( name, "LIST" ) == 0) { this->usage(); @@ -669,7 +640,7 @@ UBool IntlTest::runTestLoop( char* testname, char* par ) IntlTest* saveTest = gTest; gTest = this; do { - this->runIndexedTest( index, FALSE, name ); + this->runIndexedTest( index, FALSE, name, par ); if (!name || (name[0] == 0)) break; if (!testname) { @@ -771,7 +742,15 @@ int32_t IntlTest::IncErrorCount( void ) return errorCount; } -void IntlTest::err() { +int32_t IntlTest::IncDataErrorCount( void ) +{ + dataErrorCount++; + if (caller) caller->IncDataErrorCount(); + return dataErrorCount; +} + +void IntlTest::err() +{ IncErrorCount(); } @@ -787,10 +766,32 @@ void IntlTest::errln( const UnicodeString &message ) if (!no_err_msg) LL_message( message, TRUE ); } +void IntlTest::dataerr( const UnicodeString &message ) +{ + IncDataErrorCount(); + + if (!warn_on_missing_data) { + IncErrorCount(); + } + + if (!no_err_msg) LL_message( message, FALSE ); +} + +void IntlTest::dataerrln( const UnicodeString &message ) +{ + IncDataErrorCount(); + + if (!warn_on_missing_data) { + IncErrorCount(); + } + + if (!no_err_msg) LL_message( message, TRUE ); +} + /* convenience functions that include sprintf formatting */ void IntlTest::log(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -804,7 +805,7 @@ void IntlTest::log(const char *fmt, ...) void IntlTest::logln(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -819,7 +820,7 @@ void IntlTest::logln(const char *fmt, ...) /* convenience functions that include sprintf formatting */ void IntlTest::info(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -831,7 +832,7 @@ void IntlTest::info(const char *fmt, ...) void IntlTest::infoln(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -843,7 +844,7 @@ void IntlTest::infoln(const char *fmt, ...) void IntlTest::err(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -854,7 +855,7 @@ void IntlTest::err(const char *fmt, ...) void IntlTest::errln(const char *fmt, ...) { - char buffer[512]; + char buffer[4000]; va_list ap; va_start(ap, fmt); @@ -863,6 +864,17 @@ void IntlTest::errln(const char *fmt, ...) errln(UnicodeString(buffer, "")); } +void IntlTest::dataerrln(const char *fmt, ...) +{ + char buffer[4000]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + dataerrln(UnicodeString(buffer, "")); +} + void IntlTest::printErrors() { IntlTest::LL_message(errorList, TRUE); @@ -893,7 +905,7 @@ void IntlTest::LL_message( UnicodeString message, UBool newline ) // stream out the indentation string first if necessary length = indent.extract(1, indent.length(), buffer, sizeof(buffer)); if (length > 0) { - fwrite(buffer, sizeof(*buffer), length, testoutfp); + fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); } // replace each LineFeed by the indentation string @@ -902,17 +914,18 @@ void IntlTest::LL_message( UnicodeString message, UBool newline ) // stream out the message length = message.extract(0, message.length(), buffer, sizeof(buffer)); if (length > 0) { - fwrite(buffer, sizeof(*buffer), length, testoutfp); + length = length > 10000 ? 10000 : length; + fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); } if (newline) { char newLine = '\n'; - fwrite(&newLine, sizeof(newLine), 1, testoutfp); + fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp); } // A newline usually flushes the buffer, but // flush the message just in case of a core dump. - fflush(testoutfp); + fflush((FILE *)testoutfp); } /** @@ -959,83 +972,66 @@ int main(int argc, char* argv[]) { UBool syntax = FALSE; - UBool all = TRUE; + UBool all = FALSE; UBool verbose = FALSE; UBool no_err_msg = FALSE; UBool quick = TRUE; UBool name = FALSE; UBool leaks = FALSE; UBool warnOnMissingData = FALSE; + UBool defaultDataFound = FALSE; UErrorCode errorCode = U_ZERO_ERROR; UConverter *cnv = NULL; - const char *warnOrErr = "Failure"; - - /* This must be tested before using anything! */ - MutexTest::gMutexInitialized = umtx_isInitialized(NULL); - -#ifdef XP_MAC_CONSOLE - argc = ccommand( &argv ); -#endif + const char *warnOrErr = "Failure"; + UDate startTime, endTime; + int32_t diffTime; - /* try opening the data from dll instead of the dat file */ - cnv = ucnv_open(TRY_CNV_1, &errorCode); - if(cnv != 0) { - /* ok */ - ucnv_close(cnv); - } else { - fprintf(stderr, - "#### WARNING! The converter for " TRY_CNV_1 " cannot be loaded from data dll/so." - "Proceeding to load data from dat file.\n"); - errorCode = U_ZERO_ERROR; + U_MAIN_INIT_ARGS(argc, argv); - } - // If user didn't set ICU_DATA, attempt to generate one. - IntlTest::setICU_DATA(); + startTime = uprv_getUTCtime(); for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-') { const char* str = argv[i] + 1; - if (strcmp("verbose", str) == 0) - verbose = TRUE; - else if (strcmp("v", str) == 0) + if (strcmp("verbose", str) == 0 || + strcmp("v", str) == 0) verbose = TRUE; - else if (strcmp("noerrormsg", str) == 0) + else if (strcmp("noerrormsg", str) == 0 || + strcmp("n", str) == 0) no_err_msg = TRUE; - else if (strcmp("n", str) == 0) - no_err_msg = TRUE; - else if (strcmp("exhaustive", str) == 0) - quick = FALSE; - else if (strcmp("e", str) == 0) + else if (strcmp("exhaustive", str) == 0 || + strcmp("e", str) == 0) quick = FALSE; - else if (strcmp("all", str) == 0) + else if (strcmp("all", str) == 0 || + strcmp("a", str) == 0) all = TRUE; - else if (strcmp("a", str) == 0) - all = TRUE; - else if (strcmp("leaks", str) == 0) - leaks = TRUE; - else if (strcmp("l", str) == 0) + else if (strcmp("leaks", str) == 0 || + strcmp("l", str) == 0) leaks = TRUE; else if (strcmp("w", str) == 0) { warnOnMissingData = TRUE; warnOrErr = "WARNING"; - } else { + } + else { syntax = TRUE; } }else{ name = TRUE; - all = FALSE; } } - if (all && name) syntax = TRUE; - if (!all && !name) syntax = TRUE; + if (!all && !name) { + all = TRUE; + } else if (all && name) { + syntax = TRUE; + } if (syntax) { fprintf(stdout, "### Syntax:\n" "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" "### where options are: verbose (v), all (a), noerrormsg (n), \n" - "### exhaustive (e) and leaks (l). \n" + "### exhaustive (e), leaks (l)" "### (Specify either -all (shortcut -a) or a test name). \n" "### -all will run all of the tests.\n" "### \n" @@ -1057,31 +1053,55 @@ main(int argc, char* argv[]) major.setNoErrMsg( no_err_msg ); major.setQuick( quick ); major.setLeaks( leaks ); + major.setWarnOnMissingData( warnOnMissingData ); fprintf(stdout, "-----------------------------------------------\n"); fprintf(stdout, " IntlTest (C++) Test Suite for \n"); fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); fprintf(stdout, "-----------------------------------------------\n"); fprintf(stdout, " Options: \n"); - fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); - fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); - fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); - fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); - fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); + fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off")); + fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off")); + fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off")); + fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); + fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); + fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); fprintf(stdout, "-----------------------------------------------\n"); - // Check that u_init() works + /* Check whether ICU will initialize without forcing the build data directory into + * the ICU_DATA path. Success here means either the data dll contains data, or that + * this test program was run with ICU_DATA set externally. Failure of this check + * is normal when ICU data is not packaged into a shared library. + * + * Whether or not this test succeeds, we want to cleanup and reinitialize + * with a data path so that data loading from individual files can be tested. + */ + u_init(&errorCode); + if (U_FAILURE(errorCode)) { + fprintf(stderr, + "#### Note: ICU Init without build-specific setDataDirectory() failed.\n"); + defaultDataFound = FALSE; + } + else { + defaultDataFound = TRUE; + } + u_cleanup(); errorCode = U_ZERO_ERROR; + + /* Initialize ICU */ + if (!defaultDataFound) { + IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. + } u_init(&errorCode); if (U_FAILURE(errorCode)) { - fprintf(stdout, - "*** u_init() failed with error code = %s\n" - "*** Check the ICU_DATA environment variable and\n" - "*** check that the data files are present.\n", - u_errorName(errorCode)); - if(!warnOnMissingData) { - fprintf(stdout, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); - return 1; - } + fprintf(stderr, + "#### ERROR! %s: u_init() failed with status = \"%s\".\n" + "*** Check the ICU_DATA environment variable and \n" + "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); + if(warnOnMissingData == 0) { + fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + u_cleanup(); + return 1; + } } @@ -1098,7 +1118,7 @@ main(int argc, char* argv[]) "*** check that the data files are present.\n", warnOrErr, ucnv_getDefaultName()); if(!warnOnMissingData) { - fprintf(stdout, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); return 1; } } @@ -1114,7 +1134,7 @@ main(int argc, char* argv[]) "*** Check the ICU_DATA environment variable and \n" "*** check that the data files are present.\n", warnOrErr); if(!warnOnMissingData) { - fprintf(stdout, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); return 1; } } @@ -1127,11 +1147,13 @@ main(int argc, char* argv[]) "*** Check the ICU_DATA environment variable and \n" "*** check that the data files are present.\n", warnOrErr); if(!warnOnMissingData) { - fprintf(stdout, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); return 1; } } + Locale originalLocale; // Save the default locale for comparison later on. + /* TODO: Add option to call u_cleanup and rerun tests. */ if (all) { major.runTest(); @@ -1168,39 +1190,50 @@ main(int argc, char* argv[]) free(_testDataPath); _testDataPath = 0; + Locale lastDefaultLocale; + if (originalLocale != lastDefaultLocale) { + major.errln("FAILURE: A test changed the default locale without resetting it."); + } + fprintf(stdout, "\n--------------------------------------\n"); if (major.getErrors() == 0) { /* Call it twice to make sure that the defaults were reset. */ /* Call it before the OK message to verify proper cleanup. */ u_cleanup(); - u_cleanup(); + u_cleanup(); fprintf(stdout, "OK: All tests passed without error.\n"); + + if (major.getDataErrors() != 0) { + fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n"); + } }else{ fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors()); major.printErrors(); + + if (major.getDataErrors() != 0) { + fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n" + "\tstock ICU data (i.e some have been added or removed), consider using\n" + "\tthe '-w' option to turn these errors into warnings.\n"); + } + /* Call afterwards to display errors. */ u_cleanup(); } fprintf(stdout, "--------------------------------------\n"); - if (!MutexTest::gMutexInitialized) { - fprintf(stderr, - "#### WARNING!\n" - " The global mutex was not initialized during C++ static initialization.\n" - " You must use an ICU API in a single thread, like ucnv_open() or\n" - " uloc_countAvailable(), before using ICU in multiple threads.\n" - " Most ICU API functions will initialize the global mutex for you.\n" - " If you are using ICU in a single threaded application, please ignore this\n" - " warning.\n" - "#### WARNING!\n" - ); - } if (execCount <= 0) { fprintf(stdout, "***** Not all called tests actually exist! *****\n"); } + endTime = uprv_getUTCtime(); + diffTime = (int32_t)(endTime - startTime); + printf("Elapsed Time: %02d:%02d:%02d.%03d\n", + (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), + (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), + (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), + (int)(diffTime%U_MILLIS_PER_SECOND)); return major.getErrors(); } @@ -1225,7 +1258,7 @@ const char* IntlTest::loadTestData(UErrorCode& err){ /* u_getDataDirectory shoul return \source\data ... set the * directory to ..\source\data\..\test\testdata\out\testdata */ - strcpy(tdpath, directory); + strcpy(tdpath, directory); strcat(tdpath, tdrelativepath); strcat(tdpath,"testdata"); @@ -1233,7 +1266,7 @@ const char* IntlTest::loadTestData(UErrorCode& err){ if(U_FAILURE(err)){ err = U_FILE_ACCESS_ERROR; - it_errln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); + it_dataerrln((UnicodeString)"[DATA] Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); return ""; } ures_close(test); @@ -1243,6 +1276,30 @@ const char* IntlTest::loadTestData(UErrorCode& err){ return _testDataPath; } +const char* IntlTest::getTestDataPath(UErrorCode& err) { + return loadTestData(err); +} + +/* Returns the path to icu/source/test/testdata/ */ +const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) { + const char *srcDataDir = NULL; +#ifdef U_TOPSRCDIR + srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; +#else + srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; + FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r"); + if (f) { + /* We're in icu/source/test/intltest/ */ + fclose(f); + } + else { + /* We're in icu/source/test/intltest/(Debug|Release) */ + srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; + } +#endif + return srcDataDir; +} + const char* IntlTest::fgDataDir = NULL; /* returns the path to icu/source/data */ @@ -1295,14 +1352,14 @@ const char * IntlTest::pathToDataDirectory() } else { /* __FILE__ on MSVC7 does not contain the directory */ - FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); - if (file) { - fclose(file); - fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; - } - else { - fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; - } + FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); + if (file) { + fclose(file); + fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; + } + else { + fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; + } } } #endif @@ -1322,6 +1379,212 @@ UnicodeString CharsToUnicodeString(const char* chars) return str.unescape(); } +UnicodeString ctou(const char* chars) { + return CharsToUnicodeString(chars); +} + +#define RAND_M (714025) +#define RAND_IA (1366) +#define RAND_IC (150889) + +static int32_t RAND_SEED; + +/** + * Returns a uniform random value x, with 0.0 <= x < 1.0. Use + * with care: Does not return all possible values; returns one of + * 714,025 values, uniformly spaced. However, the period is + * effectively infinite. See: Numerical Recipes, section 7.1. + * + * @param seedp pointer to seed. Set *seedp to any negative value + * to restart the sequence. + */ +float IntlTest::random(int32_t* seedp) { + static int32_t iy, ir[98]; + static UBool first=TRUE; + int32_t j; + if (*seedp < 0 || first) { + first = FALSE; + if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp); + for (j=1;j<=97;++j) { + *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; + ir[j]=(*seedp); + } + *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; + iy=(*seedp); + } + j=(int32_t)(1 + 97.0*iy/RAND_M); + U_ASSERT(j>=1 && j<=97); + iy=ir[j]; + *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M; + ir[j]=(*seedp); + return (float) iy/RAND_M; +} + +/** + * Convenience method using a global seed. + */ +float IntlTest::random() { + return random(&RAND_SEED); +} + +static inline UChar toHex(int32_t i) { + return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); +} + +static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) { + for (int32_t i=0; i> 12) & 0xF); + result += toHex((c >> 8) & 0xF); + result += toHex((c >> 4) & 0xF); + result += toHex( c & 0xF); + } + } + return result; +} + +#define VERBOSE_ASSERTIONS + +UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) { + if (!condition) { + errln("FAIL: assertTrue() failed: %s", message); + } else if (!quiet) { + logln("Ok: %s", message); + } + return condition; +} + +UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { + if (condition) { + errln("FAIL: assertFalse() failed: %s", message); + } else if (!quiet) { + logln("Ok: %s", message); + } + return !condition; +} + +UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) { + if (U_FAILURE(ec)) { + if (ec == U_FILE_ACCESS_ERROR) { + dataerrln("[DATA] Fail: %s.", message); + } else { + errln("FAIL: %s (%s)", message, u_errorName(ec)); + } + return FALSE; + } + return TRUE; +} + +UBool IntlTest::assertEquals(const char* message, + const UnicodeString& expected, + const UnicodeString& actual) { + if (expected != actual) { + errln((UnicodeString)"FAIL: " + message + "; got " + + prettify(actual) + + "; expected " + prettify(expected)); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual)); + } +#endif + return TRUE; +} + +UBool IntlTest::assertEquals(const char* message, + const char* expected, + const char* actual) { + if (uprv_strcmp(expected, actual) != 0) { + errln((UnicodeString)"FAIL: " + message + "; got \"" + + actual + + "\"; expected \"" + expected + "\""); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\""); + } +#endif + return TRUE; +} + +#if !UCONFIG_NO_FORMATTING +UBool IntlTest::assertEquals(const char* message, + const Formattable& expected, + const Formattable& actual) { + if (expected != actual) { + errln((UnicodeString)"FAIL: " + message + "; got " + + toString(actual) + + "; expected " + toString(expected)); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + logln((UnicodeString)"Ok: " + message + "; got " + toString(actual)); + } +#endif + return TRUE; +} +#endif + +static char ASSERT_BUF[256]; + +static const char* extractToAssertBuf(const UnicodeString& message) { + UnicodeString buf; + escape(message, buf); + buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0); + ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0; + return ASSERT_BUF; +} + +UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) { + return assertTrue(extractToAssertBuf(message), condition, quiet); +} + +UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) { + return assertFalse(extractToAssertBuf(message), condition, quiet); +} + +UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) { + return assertSuccess(extractToAssertBuf(message), ec); +} + +UBool IntlTest::assertEquals(const UnicodeString& message, + const UnicodeString& expected, + const UnicodeString& actual) { + return assertEquals(extractToAssertBuf(message), expected, actual); +} + +UBool IntlTest::assertEquals(const UnicodeString& message, + const char* expected, + const char* actual) { + return assertEquals(extractToAssertBuf(message), expected, actual); +} +//-------------------------------------------------------------------- +// Time bomb - allows temporary behavior that expires at a given +// release +//-------------------------------------------------------------------- + +UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) { + UVersionInfo v; + u_getVersion(v); + return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0); +} + +#if !UCONFIG_NO_FORMATTING +UBool IntlTest::assertEquals(const UnicodeString& message, + const Formattable& expected, + const Formattable& actual) { + return assertEquals(extractToAssertBuf(message), expected, actual); +} +#endif + /* * Hey, Emacs, please set the following: * @@ -1330,4 +1593,3 @@ UnicodeString CharsToUnicodeString(const char* chars) * End: * */ -