/** * How may columns to indent the 'OK' markers.
*/ #define FLAG_INDENT 45 /** * How many lines of scrollage can go by before we need to remind the user what the test is.
*/ #define PAGE_SIZE_LIMIT 25
#ifndef SHOW_TIMES #define SHOW_TIMES 1 #endif
struct TestNode
{ void (*test)(void); struct TestNode* sibling; struct TestNode* child; char name[1]; /* This is dynamically allocated off the end with malloc. */
};
/** * Do the work of logging an error. Doesn't increase the error count. * * @prefix optional prefix prepended to message, or NULL. * @param pattern printf style pattern * @param ap vprintf style arg list
*/ staticvoid vlog_err(constchar *prefix, constchar *pattern, va_list ap); staticvoid vlog_verbose(constchar *prefix, constchar *pattern, va_list ap); static UBool vlog_knownIssue(constchar *ticket, constchar *pattern, va_list ap);
/** * Log test structure, with indent * @param pattern printf pattern
*/ staticvoid log_testinfo_i(constchar *pattern, ...);
/** * Log test structure, NO indent * @param pattern printf pattern
*/ staticvoid log_testinfo(constchar *pattern, ...);
/* If we need to make the framework multi-thread safe we need to pass around the following vars
*/ staticint ERRONEOUS_FUNCTION_COUNT = 0; staticint ERROR_COUNT = 0; /* Count of errors from all tests. */ staticint ONE_ERROR = 0; /* were there any other errors? */ staticint DATA_ERROR_COUNT = 0; /* count of data related errors or warnings */ staticint INDENT_LEVEL = 0; static UBool NO_KNOWN = false; staticvoid *knownList = NULL; staticchar gTestName[1024] = ""; static UBool ON_LINE = false; /* are we on the top line with our test name? */ static UBool HANGING_OUTPUT = false; /* did the user leave us without a trailing \n ? */ staticint GLOBAL_PRINT_COUNT = 0; /* global count of printouts */ int REPEAT_TESTS_INIT = 0; /* Was REPEAT_TESTS initialized? */ int REPEAT_TESTS = 1; /* Number of times to run the test */ int VERBOSITY = 0; /* be No-verbose by default */ int ERR_MSG =1; /* error messages will be displayed by default*/ int QUICK = 1; /* Skip some of the slower tests? */ int WARN_ON_MISSING_DATA = 0; /* Reduce data errs to warnings? */
UTraceLevel ICU_TRACE = UTRACE_OFF; /* ICU tracing level */ int WRITE_GOLDEN_DATA = 0; /* Overwrite golden data files? */
size_t MINIMUM_MEMORY_SIZE_FAILURE = (size_t)-1; /* Minimum library memory allocation window that will fail. */
size_t MAXIMUM_MEMORY_SIZE_FAILURE = (size_t)-1; /* Maximum library memory allocation window that will fail. */ staticconstchar *ARGV_0 = "[ALL]"; staticconstchar *XML_FILE_NAME=NULL; staticchar XML_PREFIX[256]; staticconstchar *SUMMARY_FILE = NULL;
FILE *XML_FILE = NULL; /*-------------------------------------------*/
/* strncmp that also makes sure there's a \0 at s2[0] */ staticint strncmp_nullcheck( constchar* s1, constchar* s2, int n )
{ if (((int)strlen(s2) >= n) && s2[n] != 0) { return 3; /* null check fails */
} else { return strncmp ( s1, s2, n );
}
}
staticvoid getNextLevel( constchar* name, int* nameLen, constchar** nextName )
{ /* Get the next component of the name */
*nextName = strchr(name, TEST_SEPARATOR);
/* non recursive insert function */ static TestNode *addTestNode ( TestNode *root, constchar *name )
{ constchar* nextName;
TestNode *nextNode, *curNode; int nameLen; /* length of current 'name' */
/* remove leading slash */ if ( *name == TEST_SEPARATOR )
name++;
curNode = root;
for(;;)
{ /* Start with the next child */
nextNode = curNode->child;
getNextLevel ( name, &nameLen, &nextName );
/* printf("* %s\n", name );*/
/* if nextNode is already null, then curNode has no children
-- add them */ if( nextNode == NULL )
{ /* Add all children of the node */ do
{ /* Get the next component of the name */
getNextLevel(name, &nameLen, &nextName);
/* update curName to have the next name segment */
curNode->child = createTestNode(name, nameLen); /* printf("*** added %s\n", curNode->child->name );*/
curNode = curNode->child;
name = nextName;
} while( name != NULL );
return curNode;
}
/* Search across for the name */ while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 )
{
curNode = nextNode;
nextNode = nextNode -> sibling;
if ( nextNode == NULL )
{ /* Did not find 'name' on this level. */
nextNode = createTestNode(name, nameLen);
curNode->sibling = nextNode; break;
}
}
/* nextNode matches 'name' */
if (nextName == NULL) /* end of the line */
{ return nextNode;
}
/* Loop again with the next item */
name = nextName;
curNode = nextNode;
}
}
/** * Log the time taken. May not output anything. * @param deltaTime change in time
*/ void T_CTEST_EXPORT2 str_timeDelta(char *str, UDate deltaTime) { if (deltaTime > 110000.0 ) { double mins = uprv_floor(deltaTime/60000.0);
sprintf(str, "[(%.0fm %.1fs)]", mins, (deltaTime-(mins*60000.0))/1000.0);
} elseif (deltaTime > 1500.0) {
sprintf(str, "((%.1fs))", deltaTime/1000.0);
} elseif(deltaTime>900.0) {
sprintf(str, "( %.2fs )", deltaTime/1000.0);
} elseif(deltaTime > 5.0) {
sprintf(str, " (%.0fms) ", deltaTime);
} else {
str[0]=0; /* at least terminate it. */
}
}
/** * Run or list tests (according to mode) in a subtree. * * @param root root of the subtree to operate on * @param depth The depth of this tree (0=root) * @param nodeList an array of MAXTESTS depth that's used for keeping track of where we are. nodeList[depth] points to the 'parent' at depth depth. * @param mode what mode we are operating in.
*/ staticvoid iterateTestsWithLevel ( const TestNode* root, int depth, const TestNode** nodeList,
TestMode mode)
{ int i;
/* record the current root node, and increment depth. */
nodeList[depth++] = root; /* depth is now the depth of root's children. */
/* Collect the 'path' to the current subtree. */ for ( i=0;i<(depth-1);i++ )
{
strcat(pathToFunction, nodeList[i]->name);
strcat(pathToFunction, separatorString);
}
strcat(pathToFunction, nodeList[i]->name); /* including 'root' */
/* print test name and space. */
INDENT_LEVEL = depth-1; if(root->name[0]) {
log_testinfo_i("%s ", root->name);
} else {
log_testinfo_i("(%s) ", ARGV_0);
}
ON_LINE = true; /* we are still on the line with the test name */
if ( (mode == RUNTESTS) &&
(root->test != NULL)) /* if root is a leaf node, run it */
{ int myERROR_COUNT = ERROR_COUNT; int myGLOBAL_PRINT_COUNT = GLOBAL_PRINT_COUNT; #if SHOW_TIMES
UDate startTime, stopTime; char timeDelta[256]; char timeSeconds[256]; #else constchar timeDelta[] = "(unknown)"; constchar timeSeconds[] = "0.000"; #endif
currentTest = root;
INDENT_LEVEL = depth; /* depth of subitems */
ONE_ERROR=0;
HANGING_OUTPUT=false; #if SHOW_TIMES
startTime = uprv_getRawUTCtime(); #endif
strcpy(gTestName, pathToFunction);
root->test(); /* PERFORM THE TEST ************************/ #if SHOW_TIMES
stopTime = uprv_getRawUTCtime(); #endif if(HANGING_OUTPUT) {
log_testinfo("\n");
HANGING_OUTPUT=false;
}
INDENT_LEVEL = depth-1; /* depth of root */
currentTest = NULL; if((ONE_ERROR>0)&&(ERROR_COUNT==0)) {
ERROR_COUNT++; /* There was an error without a newline */
}
ONE_ERROR=0;
/* we want these messages to be at 0 indent. so just push the indent level briefly. */ if(mode==SHOWTESTS) {
log_testinfo("---%s%c\n",pathToFunction, nodeList[i]->test?' ':TEST_SEPARATOR );
}
INDENT_LEVEL = depth;
if(root->child) { int myERROR_COUNT = ERROR_COUNT; int myGLOBAL_PRINT_COUNT = GLOBAL_PRINT_COUNT; if(mode!=SHOWTESTS) {
INDENT_LEVEL=depth-1;
log_testinfo("{\n");
INDENT_LEVEL=depth;
}
if(DATA_ERROR_COUNT) { if(WARN_ON_MISSING_DATA==0) {
log_testinfo("\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");
} else {
log_testinfo("\t*WARNING* some data-loading errors were ignored by the -w option.\n");
}
}
}
const TestNode* T_CTEST_EXPORT2
getTest(const TestNode* root, constchar* name)
{ constchar* nextName;
TestNode *nextNode; const TestNode* curNode; int nameLen; /* length of current 'name' */
if (root == NULL) {
log_err("TEST CAN'T BE FOUND!\n"); return NULL;
} /* remove leading slash */ if ( *name == TEST_SEPARATOR )
name++;
curNode = root;
for(;;)
{ /* Start with the next child */
nextNode = curNode->child;
getNextLevel ( name, &nameLen, &nextName );
/* printf("* %s\n", name );*/
/* if nextNode is already null, then curNode has no children
-- add them */ if( nextNode == NULL )
{ return NULL;
}
/* Search across for the name */ while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 )
{
curNode = nextNode;
nextNode = nextNode -> sibling;
if ( nextNode == NULL )
{ /* Did not find 'name' on this level. */ return NULL;
}
}
/* nextNode matches 'name' */
if (nextName == NULL) /* end of the line */
{ return nextNode;
}
/* Loop again with the next item */
name = nextName;
curNode = nextNode;
}
}
void T_CTEST_EXPORT2
log_err(constchar* pattern, ...)
{
va_list ap;
first_line_err(); if(strchr(pattern, '\n') != NULL) { /* * Count errors only if there is a line feed in the pattern * so that we do not exaggerate our error count.
*/
++ERROR_COUNT;
} else { /* Count at least one error. */
ONE_ERROR=1;
}
va_start(ap, pattern);
vlog_err(NULL, pattern, ap);
va_end(ap);
}
int T_CTEST_EXPORT2
runTestRequest(const TestNode* root, int argc, constchar* const argv[])
{ /** * This main will parse the l, v, h, n, and path arguments
*/ const TestNode* toRun; int i; int doList = false; int subtreeOptionSeen = false;
int errorCount = 0;
toRun = root;
if(ctest_xml_init(ARGV_0)) { return 1; /* couldn't fire up XML thing */
}
if( subtreeOptionSeen == false) /* no other subtree given, run the default */
{
ON_LINE=false; /* just in case */ if( doList == true)
showTests(toRun); else
runTests(toRun);
ON_LINE=false; /* just in case */
staticvoid help ( constchar *argv0 )
{
printf("Usage: %s [ -l ] [ -v ] [ -verbose] [-a] [ -all] [-n] [ -no_err_msg]\n" " [ -h ] [-t_info | -t_error | -t_warn | -t_oc | -t_verbose] [-m n[-q] ]\n" " [ /path/to/test ]\n",
argv0);
printf(" -l To get a list of test names\n");
printf(" -e to do exhaustive testing\n");
printf(" -verbose To turn ON verbosity\n");
printf(" -v To turn ON verbosity(same as -verbose)\n");
printf(" -x file.xml Write junit format output to file.xml\n");
printf(" -h To print this message\n");
printf(" -K to turn OFF suppressing known issues\n");
printf(" -n To turn OFF printing error messages\n");
printf(" -w Don't fail on data-loading errs, just warn. Useful if\n" " user has reduced/changed the common set of ICU data \n");
printf(" -t_info | -t_error | -t_warn | -t_oc | -t_verbose Enable ICU tracing\n");
printf(" -no_err_msg (same as -n) \n");
printf(" -m n[-q] Min-Max memory size that will cause an allocation failure.\n");
printf(" The default is the maximum value of size_t. Max is optional.\n");
printf(" -r Repeat tests after calling u_cleanup \n");
printf(" -G Write golden data files \n");
printf(" [/subtest] To run a subtest \n");
printf(" eg: to run just the utility tests type: cintltest /tsutil) \n");
}
int32_t T_CTEST_EXPORT2
getTestOption ( int32_t testOption ) { switch (testOption) { case VERBOSITY_OPTION: return VERBOSITY; case WARN_ON_MISSING_DATA_OPTION: return WARN_ON_MISSING_DATA; case QUICK_OPTION: return QUICK; case REPEAT_TESTS_OPTION: return REPEAT_TESTS; case ERR_MSG_OPTION: return ERR_MSG; case ICU_TRACE_OPTION: return ICU_TRACE; case WRITE_GOLDEN_DATA_OPTION: return WRITE_GOLDEN_DATA; default : return 0;
}
}
void T_CTEST_EXPORT2
setTestOption ( int32_t testOption, int32_t value) { if (value == DECREMENT_OPTION_VALUE) {
value = getTestOption(testOption);
--value;
} switch (testOption) { case VERBOSITY_OPTION:
VERBOSITY = value; break; case WARN_ON_MISSING_DATA_OPTION:
WARN_ON_MISSING_DATA = value; break; case QUICK_OPTION:
QUICK = value; break; case REPEAT_TESTS_OPTION:
REPEAT_TESTS = value; break; case ICU_TRACE_OPTION:
ICU_TRACE = (UTraceLevel)value; break; case WRITE_GOLDEN_DATA_OPTION:
WRITE_GOLDEN_DATA = value; default : break;
}
}
/* * ================== JUnit support ================================
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.