X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/374ca955a76ecab1204ca8bfa63ff9238d998416..e4f10fab0c078f399c9deef476d9c9b73b47dff8:/icuSources/test/intltest/intltest.cpp diff --git a/icuSources/test/intltest/intltest.cpp b/icuSources/test/intltest/intltest.cpp index 26d2b6a2..6d08af15 100644 --- a/icuSources/test/intltest/intltest.cpp +++ b/icuSources/test/intltest/intltest.cpp @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2004, International Business Machines Corporation and + * Copyright (c) 1997-2013, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -33,6 +33,11 @@ #include "umutex.h" #include "uassert.h" #include "cmemory.h" +#include "uoptions.h" + +#include "putilimp.h" // for uprv_getRawUTCtime() +#include "unicode/locid.h" +#include "unicode/ctest.h" // for str_timeDelta #ifdef XP_MAC_CONSOLE #include @@ -87,10 +92,10 @@ Int64ToUnicodeString(int64_t num) char buffer[64]; // nos changed from 10 to 64 char danger = 'p'; // guard against overrunning the buffer (rtg) -#ifdef WIN32 +#if defined(_MSC_VER) sprintf(buffer, "%I64d", num); #else - sprintf(buffer, "%lld", num); + sprintf(buffer, "%lld", (long long)num); #endif assert(danger == 'p'); @@ -109,7 +114,7 @@ operator+(const UnicodeString& left, // 53*log(2)/log(10) = 15.95 // so there is no need to show more than 16 digits. [alan] - sprintf(buffer, "%.16g", num); + sprintf(buffer, "%.17g", num); assert(danger == 'p'); return left + buffer; @@ -118,7 +123,7 @@ operator+(const UnicodeString& left, #if !UCONFIG_NO_FORMATTING /** - * Return a string display for for this, without surrounding braces. + * Return a string display for this, without surrounding braces. */ UnicodeString _toString(const Formattable& f) { UnicodeString s; @@ -165,15 +170,15 @@ UnicodeString _toString(const Formattable& f) { } } break; - case Formattable::kObject: - if (f.getObject()->getDynamicClassID() == - CurrencyAmount::getStaticClassID()) { - const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject(); - s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency()); + case Formattable::kObject: { + const CurrencyAmount* c = dynamic_cast(f.getObject()); + if (c != NULL) { + s = _toString(c->getNumber()) + " " + UnicodeString(c->getISOCurrency()); } else { s = UnicodeString("Unknown UObject"); } break; + } default: s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType(); break; @@ -228,6 +233,14 @@ IntlTest::appendHex(uint32_t number, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0 }; /* "0123456789ABCDEF" */ + if (digits < 0) { // auto-digits + digits = 2; + uint32_t max = 0xff; + while (number > max) { + digits += 2; + max = (max << 8) | 0xff; + } + } switch (digits) { case 8: @@ -253,6 +266,17 @@ IntlTest::appendHex(uint32_t number, return target; } +UnicodeString +IntlTest::toHex(uint32_t number, int32_t digits) { + UnicodeString result; + appendHex(number, digits, result); + return result; +} + +static inline UBool isPrintable(UChar32 c) { + return c <= 0x7E && (c >= 0x20 || c == 9 || c == 0xA || c == 0xD); +} + // Replace nonprintable characters with unicode escapes UnicodeString& IntlTest::prettify(const UnicodeString &source, @@ -266,9 +290,9 @@ IntlTest::prettify(const UnicodeString &source, for (i = 0; i < source.length(); ) { UChar32 ch = source.char32At(i); - i += UTF_CHAR_LENGTH(ch); + i += U16_LENGTH(ch); - if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E) + if (!isPrintable(ch)) { if (ch <= 0xFFFF) { target += "\\u"; @@ -301,9 +325,9 @@ IntlTest::prettify(const UnicodeString &source, UBool parseBackslash) for (i = 0; i < source.length();) { UChar32 ch = source.char32At(i); - i += UTF_CHAR_LENGTH(ch); + i += U16_LENGTH(ch); - if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E) + if (!isPrintable(ch)) { if (parseBackslash) { // If we are preceded by an odd number of backslashes, @@ -340,68 +364,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. @@ -541,30 +503,52 @@ void it_errln( UnicodeString message ) IntlTest::gTest->errln( message ); } +void it_dataerr( UnicodeString message ) +{ + if (IntlTest::gTest) + IntlTest::gTest->dataerr( message ); +} + +void it_dataerrln( UnicodeString message ) +{ + 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_time = FALSE; no_err_msg = FALSE; + warn_on_missing_data = FALSE; quick = FALSE; leaks = FALSE; + threadCount = 1; testoutfp = stdout; LL_indentlevel = indentLevel_offset; + numProps = 0; + strcpy(basePath, "/"); } 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; testoutfp = caller->testoutfp; LL_indentlevel = caller->LL_indentlevel + indentLevel_offset; + numProps = caller->numProps; + for (int32_t i = 0; i < numProps; i++) { + proplines[i] = caller->proplines[i]; + } } } @@ -572,12 +556,15 @@ 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 ); + strcpy(testToBeCalled.basePath, this->basePath ); + UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath ); + strcpy(testToBeCalled.basePath, this->basePath ); // reset it. + return result; } void IntlTest::setPath( char* pathVal ) { - this->path = pathVal; + this->testPath = pathVal; } UBool IntlTest::setVerbose( UBool verboseVal ) @@ -587,6 +574,20 @@ UBool IntlTest::setVerbose( UBool verboseVal ) return rval; } +UBool IntlTest::setNotime( UBool no_time ) +{ + UBool rval = this->no_time; + this->no_time = no_time; + 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; @@ -608,43 +609,66 @@ UBool IntlTest::setLeaks( UBool leaksVal ) return rval; } +int32_t IntlTest::setThreadCount( int32_t count ) +{ + int32_t rval = this->threadCount; + this->threadCount = count; + return rval; +} + int32_t IntlTest::getErrors( void ) { return errorCount; } -UBool IntlTest::runTest( char* name, char* par ) +int32_t IntlTest::getDataErrors( void ) +{ + return dataErrorCount; +} + +UBool IntlTest::runTest( char* name, char* par, char *baseName ) { UBool rval; char* pos = NULL; + char* baseNameBuffer = NULL; + + if(baseName == NULL) { + baseNameBuffer = (char*)malloc(1024); + baseName=baseNameBuffer; + strcpy(baseName, "/"); + } + 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, par ); + rval = runTestLoop( NULL, par, baseName ); }else if (strcmp( name, "LIST" ) == 0) { this->usage(); rval = TRUE; }else{ - rval = runTestLoop( name, par ); + rval = runTestLoop( name, par, baseName ); } if (pos) *pos = delim; // restore original value at pos + if(baseNameBuffer!=NULL) { + free(baseNameBuffer); + } return rval; } // call individual tests, to be overriden to call implementations -void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par ) +void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ ) { // to be overriden by a method like: /* @@ -655,11 +679,10 @@ void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, cha } */ this->errln("*** runIndexedTest needs to be overriden! ***"); - name = ""; exec = exec; index = index; par = par; } -UBool IntlTest::runTestLoop( char* testname, char* par ) +UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName ) { int32_t index = 0; const char* name; @@ -668,28 +691,69 @@ UBool IntlTest::runTestLoop( char* testname, char* par ) UBool rval = FALSE; UBool lastTestFailed; + if(baseName == NULL) { + printf("ERROR: baseName can't be null.\n"); + return FALSE; + } else { + if ((char *)this->basePath != baseName) { + strcpy(this->basePath, baseName); + } + } + + char * saveBaseLoc = baseName+strlen(baseName); + IntlTest* saveTest = gTest; gTest = this; do { this->runIndexedTest( index, FALSE, name, par ); - if (!name || (name[0] == 0)) - break; - if (!testname) { - run_this_test = TRUE; - }else{ - run_this_test = (UBool) (strcmp( name, testname ) == 0); + if (strcmp(name,"skip") == 0) { + run_this_test = FALSE; + } else { + if (!name || (name[0] == 0)) + break; + if (!testname) { + run_this_test = TRUE; + }else{ + run_this_test = (UBool) (strcmp( name, testname ) == 0); + } } if (run_this_test) { lastErrorCount = errorCount; execCount++; + char msg[256]; + sprintf(msg, "%s {", name); + LL_message(msg, TRUE); + UDate timeStart = uprv_getRawUTCtime(); + strcpy(saveBaseLoc,name); + strcat(saveBaseLoc,"/"); + this->runIndexedTest( index, TRUE, name, par ); + + UDate timeStop = uprv_getRawUTCtime(); rval = TRUE; // at least one test has been called - char msg[256]; + char secs[256]; + if(!no_time) { + sprintf(secs, "%f", (timeStop-timeStart)/1000.0); + } else { + secs[0]=0; + } + + + strcpy(saveBaseLoc,name); + + + ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL); + + + saveBaseLoc[0]=0; /* reset path */ + if (lastErrorCount == errorCount) { - sprintf( msg, "---OK: %s", name ); + sprintf( msg, " } OK: %s ", name ); + if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); lastTestFailed = FALSE; }else{ - sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name); + sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name); + if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart); for(int i=0;iIncDataErrorCount(); + return dataErrorCount; +} + +void IntlTest::err() +{ IncErrorCount(); } @@ -789,6 +863,39 @@ 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(); + UnicodeString msg; + if (!warn_on_missing_data) { + IncErrorCount(); + msg = message; + } else { + msg = UnicodeString("[DATA] " + message); + } + + if (!no_err_msg) LL_message( msg + " - (Are you missing data?)", TRUE ); +} + +void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) { + if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { + dataerrln(message); + } else { + errln(message); + } +} + /* convenience functions that include sprintf formatting */ void IntlTest::log(const char *fmt, ...) { @@ -865,6 +972,33 @@ 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::errcheckln(UErrorCode status, const char *fmt, ...) +{ + char buffer[4000]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) { + dataerrln(UnicodeString(buffer, "")); + } else { + errln(UnicodeString(buffer, "")); + } +} + void IntlTest::printErrors() { IntlTest::LL_message(errorList, TRUE); @@ -904,6 +1038,7 @@ void IntlTest::LL_message( UnicodeString message, UBool newline ) // stream out the message length = message.extract(0, message.length(), buffer, sizeof(buffer)); if (length > 0) { + length = length > 10000 ? 10000 : length; fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp); } @@ -964,31 +1099,24 @@ main(int argc, char* argv[]) UBool all = FALSE; UBool verbose = FALSE; UBool no_err_msg = FALSE; + UBool no_time = FALSE; UBool quick = TRUE; UBool name = FALSE; UBool leaks = FALSE; UBool warnOnMissingData = FALSE; + UBool defaultDataFound = FALSE; + int32_t threadCount = 1; UErrorCode errorCode = U_ZERO_ERROR; UConverter *cnv = NULL; const char *warnOrErr = "Failure"; + UDate startTime, endTime; + int32_t diffTime; + const char *props[IntlTest::kMaxProps]; + int32_t nProps = 0; -#ifdef XP_MAC_CONSOLE - argc = ccommand( &argv ); -#endif - - /* Initialize ICU */ - IntlTest::setICU_DATA(); // Must set data directory before u_init() is called. - u_init(&errorCode); - if (U_FAILURE(errorCode)) { - fprintf(stderr, - "#### %s: u_init() failed, error is \"%s\".\n" - "#### Most commonly indicates that the ICU data is not accesible.\n" - "#### Check setting of ICU_DATA, or check that ICU data library is available\n" - "#### ICU_DATA is currently set to \"%s\"\n", argv[0], u_errorName(errorCode), u_getDataDirectory()); - u_cleanup(); - return 1; - } + U_MAIN_INIT_ARGS(argc, argv); + startTime = uprv_getRawUTCtime(); for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-') { @@ -1008,10 +1136,30 @@ main(int argc, char* argv[]) else if (strcmp("leaks", str) == 0 || strcmp("l", str) == 0) leaks = TRUE; - else if (strcmp("w", str) == 0) { + else if (strcmp("notime", str) == 0 || + strcmp("T", str) == 0) + no_time = TRUE; + else if (strcmp("x", str)==0) { + if(++i>=argc) { + printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n"); + syntax = TRUE; + } + if(ctest_xml_setFileName(argv[i])) { /* set the name */ + return 1; /* error */ + } + } else if (strcmp("w", str) == 0) { warnOnMissingData = TRUE; warnOrErr = "WARNING"; } + else if (strncmp("threads:", str, 8) == 0) { + threadCount = atoi(str + 8); + } + else if (strncmp("prop:", str, 5) == 0) { + if (nProps < IntlTest::kMaxProps) { + props[nProps] = str + 5; + } + nProps++; + } else { syntax = TRUE; } @@ -1030,8 +1178,13 @@ main(int argc, char* argv[]) fprintf(stdout, "### Syntax:\n" "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n" - "### where options are: verbose (v), all (a), noerrormsg (n), \n" - "### exhaustive (e), leaks (l)" + "### \n" + "### Options are: verbose (v), all (a), noerrormsg (n), \n" + "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:=, \n" + "### notime (T), \n" + "### threads: (Mulithreading must first be \n" + "### enabled otherwise this will be ignored. \n" + "### The default thread count is 1.),\n" "### (Specify either -all (shortcut -a) or a test name). \n" "### -all will run all of the tests.\n" "### \n" @@ -1047,37 +1200,97 @@ main(int argc, char* argv[]) return 1; } + if (nProps > IntlTest::kMaxProps) { + fprintf(stdout, "### Too many properties. Exiting.\n"); + } + UBool all_tests_exist = TRUE; MajorTestLevel major; major.setVerbose( verbose ); major.setNoErrMsg( no_err_msg ); major.setQuick( quick ); major.setLeaks( leaks ); + major.setThreadCount( threadCount ); + major.setWarnOnMissingData( warnOnMissingData ); + major.setNotime (no_time); + for (int32_t i = 0; i < nProps; i++) { + major.setProperty(props[i]); + } + + fprintf(stdout, "-----------------------------------------------\n"); fprintf(stdout, " IntlTest (C++) Test Suite for \n"); fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION); + + + { + const char *charsetFamily = "Unknown"; + int32_t voidSize = (int32_t)sizeof(void*); + int32_t bits = voidSize * 8; + if(U_CHARSET_FAMILY==U_ASCII_FAMILY) { + charsetFamily="ASCII"; + } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) { + charsetFamily="EBCDIC"; + } + fprintf(stdout, + " Bits: %d, Byte order: %s, Chars: %s\n", + bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian", + charsetFamily); + } 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, " notime (T) : %s\n", (no_time? "On" : "Off")); + fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); +#if (ICU_USE_THREADS==0) + fprintf(stdout, " Threads : Disabled\n"); +#else + fprintf(stdout, " Threads : %d\n", threadCount); +#endif + for (int32_t i = 0; i < nProps; i++) { + fprintf(stdout, " Custom property (prop:) : %s\n", props[i]); + } 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, "*** Exiting. 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; + } } @@ -1128,6 +1341,12 @@ main(int argc, char* argv[]) } } + Locale originalLocale; // Save the default locale for comparison later on. + + if(ctest_xml_init("intltest")) + return 1; + + /* TODO: Add option to call u_cleanup and rerun tests. */ if (all) { major.runTest(); @@ -1139,13 +1358,17 @@ main(int argc, char* argv[]) if (argv[i][0] != '-') { char* name = argv[i]; fprintf(stdout, "\n=== Handling test: %s: ===\n", name); + + char baseName[1024]; + sprintf(baseName, "/%s/", name); + char* parameter = strchr( name, '@' ); if (parameter) { *parameter = 0; parameter += 1; } execCount = 0; - UBool res = major.runTest( name, parameter ); + UBool res = major.runTest( name, parameter, baseName ); if (leaks && res) { major.run_phase2( name, parameter ); } @@ -1153,10 +1376,13 @@ main(int argc, char* argv[]) fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name); all_tests_exist = FALSE; } + } else if(!strcmp(argv[i],"-x")) { + i++; } } } + #if !UCONFIG_NO_FORMATTING CalendarTimeZoneTest::cleanup(); #endif @@ -1164,18 +1390,34 @@ 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(); } @@ -1185,6 +1427,19 @@ main(int argc, char* argv[]) if (execCount <= 0) { fprintf(stdout, "***** Not all called tests actually exist! *****\n"); } + if(!no_time) { + endTime = uprv_getRawUTCtime(); + 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)); + } + + if(ctest_xml_fini()) + return 1; + return major.getErrors(); } @@ -1196,10 +1451,10 @@ const char* IntlTest::loadTestData(UErrorCode& err){ const char* tdrelativepath; #if defined (U_TOPBUILDDIR) - tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; + tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; directory = U_TOPBUILDDIR; #else - tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; + tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; directory = pathToDataDirectory(); #endif @@ -1217,7 +1472,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)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err)); return ""; } ures_close(test); @@ -1235,17 +1490,17 @@ const char* IntlTest::getTestDataPath(UErrorCode& err) { 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; + 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"); + 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; + /* We're in icu/source/test/intltest/Platform/(Debug|Release) */ + srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata"U_FILE_SEP_STRING; } #endif return srcDataDir; @@ -1303,13 +1558,13 @@ 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"); + 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; + 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; + fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; } } } @@ -1321,13 +1576,11 @@ const char * IntlTest::pathToDataDirectory() /* * This is a variant of cintltst/ccolltst.c:CharsToUChars(). - * It converts a character string into a UnicodeString, with + * It converts an invariant-character string into a UnicodeString, with * unescaping \u sequences. */ -UnicodeString CharsToUnicodeString(const char* chars) -{ - UnicodeString str(chars, ""); // Invariant conversion - return str.unescape(); +UnicodeString CharsToUnicodeString(const char* chars){ + return UnicodeString(chars, -1, US_INV).unescape(); } UnicodeString ctou(const char* chars) { @@ -1401,11 +1654,28 @@ static UnicodeString& escape(const UnicodeString& s, UnicodeString& 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); +UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) { + if (file != NULL) { + if (!condition) { + if (possibleDataError) { + dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); + } else { + errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message); + } + } else if (!quiet) { + logln("%s:%d: Ok: %s", file, line, message); + } + } else { + if (!condition) { + if (possibleDataError) { + dataerrln("FAIL: assertTrue() failed: %s", message); + } else { + errln("FAIL: assertTrue() failed: %s", message); + } + } else if (!quiet) { + logln("Ok: %s", message); + } + } return condition; } @@ -1419,9 +1689,14 @@ UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) { return !condition; } -UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) { +UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError) { if (U_FAILURE(ec)) { - errln("FAIL: %s (%s)", message, u_errorName(ec)); + if (possibleDataError) { + dataerrln("FAIL: %s (%s)", message, u_errorName(ec)); + } else { + errcheckln(ec, "FAIL: %s (%s)", message, u_errorName(ec)); + } + return FALSE; } return TRUE; @@ -1429,11 +1704,18 @@ UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) { UBool IntlTest::assertEquals(const char* message, const UnicodeString& expected, - const UnicodeString& actual) { + const UnicodeString& actual, + UBool possibleDataError) { if (expected != actual) { - errln((UnicodeString)"FAIL: " + message + "; got " + - prettify(actual) + - "; expected " + prettify(expected)); + if (possibleDataError) { + dataerrln((UnicodeString)"FAIL: " + message + "; got " + + prettify(actual) + + "; expected " + prettify(expected)); + } else { + errln((UnicodeString)"FAIL: " + message + "; got " + + prettify(actual) + + "; expected " + prettify(expected)); + } return FALSE; } #ifdef VERBOSE_ASSERTIONS @@ -1461,6 +1743,23 @@ UBool IntlTest::assertEquals(const char* message, return TRUE; } +UBool IntlTest::assertEquals(const char* message, + int32_t expected, + int32_t actual) { + if (expected != actual) { + errln((UnicodeString)"FAIL: " + message + "; got " + + actual + "=0x" + toHex(actual) + + "; expected " + expected + "=0x" + toHex(expected)); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual)); + } +#endif + return TRUE; +} + #if !UCONFIG_NO_FORMATTING UBool IntlTest::assertEquals(const char* message, const Formattable& expected, @@ -1518,10 +1817,11 @@ UBool IntlTest::assertEquals(const UnicodeString& message, // release //-------------------------------------------------------------------- -UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) { - UVersionInfo v; - u_getVersion(v); - return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0); +UBool IntlTest::isICUVersionBefore(int major, int minor, int milli) { + UVersionInfo iv; + UVersionInfo ov = { (uint8_t)major, (uint8_t)minor, (uint8_t)milli, 0 }; + u_getVersion(iv); + return uprv_memcmp(iv, ov, U_MAX_VERSION_LENGTH) < 0; } #if !UCONFIG_NO_FORMATTING @@ -1532,6 +1832,27 @@ UBool IntlTest::assertEquals(const UnicodeString& message, } #endif +void IntlTest::setProperty(const char* propline) { + if (numProps < kMaxProps) { + proplines[numProps] = propline; + } + numProps++; +} + +const char* IntlTest::getProperty(const char* prop) { + const char* val = NULL; + for (int32_t i = 0; i < numProps; i++) { + int32_t plen = uprv_strlen(prop); + if ((int32_t)uprv_strlen(proplines[i]) > plen + 1 + && proplines[i][plen] == '=' + && uprv_strncmp(proplines[i], prop, plen) == 0) { + val = &(proplines[i][plen+1]); + break; + } + } + return val; +} + /* * Hey, Emacs, please set the following: *