/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2008, International Business Machines Corporation and
+ * Copyright (c) 1997-2010, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
#include "cmemory.h"
#include "uoptions.h"
-#include "putilimp.h" // for uprv_getUTCtime()
+#include "putilimp.h" // for uprv_getRawUTCtime()
#include "unicode/locid.h"
-
+#include "unicode/ctest.h" // for str_timeDelta
#ifdef XP_MAC_CONSOLE
#include <console.h>
#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;
}
}
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<const CurrencyAmount*>(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;
return target;
}
+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,
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";
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,
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 )
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];
+ }
}
}
{
execCount--; // correct a previously assumed test-exec, as this only calls a subtest
testToBeCalled.setCaller( this );
- return testToBeCalled.runTest( testPath, 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 )
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;
return dataErrorCount;
}
-UBool IntlTest::runTest( char* name, char* par )
+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) {
}
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;
}
}
-UBool IntlTest::runTestLoop( char* testname, char* par )
+UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
{
int32_t index = 0;
const char* name;
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];
+ sprintf(secs, "%f", (timeStop-timeStart)/1000.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 );
+ 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);
+ str_timeDelta(msg+strlen(msg),timeStop-timeStart);
for(int i=0;i<LL_indentlevel;i++) {
errorList += " ";
index++;
}while(name);
+ *saveBaseLoc = 0;
+
gTest = saveTest;
return rval;
}
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( message, TRUE );
+ 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 */
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);
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;
U_MAIN_INIT_ARGS(argc, argv);
- startTime = uprv_getUTCtime();
+ startTime = uprv_getRawUTCtime();
for (int i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
else if (strcmp("leaks", str) == 0 ||
strcmp("l", str) == 0)
leaks = TRUE;
- else if (strcmp("w", str) == 0) {
+ 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;
}
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:<propery>=<value>, \n"
+ "### threads:<threadCount> (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"
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 );
+ 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, " 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"));
+#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 whether ICU will initialize without forcing the build data directory into
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();
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 );
}
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
if (execCount <= 0) {
fprintf(stdout, "***** Not all called tests actually exist! *****\n");
}
- endTime = uprv_getUTCtime();
+ 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();
}
if(U_FAILURE(err)){
err = U_FILE_ACCESS_ERROR;
- it_dataerrln((UnicodeString)"[DATA] 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);
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;
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;
}
}
}
/*
* 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) {
#define VERBOSE_ASSERTIONS
-UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) {
+UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
if (!condition) {
- errln("FAIL: assertTrue() failed: %s", message);
+ if (possibleDataError) {
+ dataerrln("FAIL: assertTrue() failed: %s", message);
+ } else {
+ errln("FAIL: assertTrue() failed: %s", message);
+ }
} else if (!quiet) {
logln("Ok: %s", message);
}
return !condition;
}
-UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) {
+UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError) {
if (U_FAILURE(ec)) {
- if (ec == U_FILE_ACCESS_ERROR) {
- dataerrln("[DATA] Fail: %s.", message);
+ if (possibleDataError) {
+ dataerrln("FAIL: %s (%s)", message, u_errorName(ec));
} else {
- errln("FAIL: %s (%s)", message, u_errorName(ec));
+ errcheckln(ec, "FAIL: %s (%s)", message, u_errorName(ec));
}
+
return FALSE;
}
return TRUE;
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
}
#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:
*