1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/ctestfw/ctest.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1309 @@ 1.4 +/* 1.5 +******************************************************************************** 1.6 +* 1.7 +* Copyright (C) 1996-2013, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************** 1.11 +*/ 1.12 +#include <stdio.h> 1.13 +#include <stdlib.h> 1.14 +#include <string.h> 1.15 +#include <assert.h> 1.16 +#include <stdarg.h> 1.17 +#include <ctype.h> 1.18 + 1.19 +#include "unicode/utrace.h" 1.20 +#include "unicode/uclean.h" 1.21 +#include "putilimp.h" 1.22 +#include "udbgutil.h" 1.23 + 1.24 +/* NOTES: 1.25 + 3/20/1999 srl - strncpy called w/o setting nulls at the end 1.26 + */ 1.27 + 1.28 +#define MAXTESTNAME 128 1.29 +#define MAXTESTS 512 1.30 +#define MAX_TEST_LOG 4096 1.31 + 1.32 +/** 1.33 + * How may columns to indent the 'OK' markers. 1.34 + */ 1.35 +#define FLAG_INDENT 45 1.36 +/** 1.37 + * How many lines of scrollage can go by before we need to remind the user what the test is. 1.38 + */ 1.39 +#define PAGE_SIZE_LIMIT 25 1.40 + 1.41 +#ifndef SHOW_TIMES 1.42 +#define SHOW_TIMES 1 1.43 +#endif 1.44 + 1.45 +struct TestNode 1.46 +{ 1.47 + void (*test)(void); 1.48 + struct TestNode* sibling; 1.49 + struct TestNode* child; 1.50 + char name[1]; /* This is dynamically allocated off the end with malloc. */ 1.51 +}; 1.52 + 1.53 + 1.54 +static const struct TestNode* currentTest; 1.55 + 1.56 +typedef enum { RUNTESTS, SHOWTESTS } TestMode; 1.57 +#define TEST_SEPARATOR '/' 1.58 + 1.59 +#ifndef C_TEST_IMPL 1.60 +#define C_TEST_IMPL 1.61 +#endif 1.62 + 1.63 +#include "unicode/ctest.h" 1.64 + 1.65 +static char ERROR_LOG[MAX_TEST_LOG][MAXTESTNAME]; 1.66 + 1.67 +/* Local prototypes */ 1.68 +static TestNode* addTestNode( TestNode *root, const char *name ); 1.69 + 1.70 +static TestNode *createTestNode(const char* name, int32_t nameLen); 1.71 + 1.72 +static int strncmp_nullcheck( const char* s1, 1.73 + const char* s2, 1.74 + int n ); 1.75 + 1.76 +static void getNextLevel( const char* name, 1.77 + int* nameLen, 1.78 + const char** nextName ); 1.79 + 1.80 +static void iterateTestsWithLevel( const TestNode *root, int depth, 1.81 + const TestNode** nodeList, 1.82 + TestMode mode); 1.83 + 1.84 +static void help ( const char *argv0 ); 1.85 + 1.86 +/** 1.87 + * Do the work of logging an error. Doesn't increase the error count. 1.88 + * 1.89 + * @prefix optional prefix prepended to message, or NULL. 1.90 + * @param pattern printf style pattern 1.91 + * @param ap vprintf style arg list 1.92 + */ 1.93 +static void vlog_err(const char *prefix, const char *pattern, va_list ap); 1.94 +static void vlog_verbose(const char *prefix, const char *pattern, va_list ap); 1.95 +static UBool vlog_knownIssue(const char *ticket, const char *pattern, va_list ap); 1.96 + 1.97 +/** 1.98 + * Log test structure, with indent 1.99 + * @param pattern printf pattern 1.100 + */ 1.101 +static void log_testinfo_i(const char *pattern, ...); 1.102 + 1.103 +/** 1.104 + * Log test structure, NO indent 1.105 + * @param pattern printf pattern 1.106 + */ 1.107 +static void log_testinfo(const char *pattern, ...); 1.108 + 1.109 +/* If we need to make the framework multi-thread safe 1.110 + we need to pass around the following vars 1.111 +*/ 1.112 +static int ERRONEOUS_FUNCTION_COUNT = 0; 1.113 +static int ERROR_COUNT = 0; /* Count of errors from all tests. */ 1.114 +static int ONE_ERROR = 0; /* were there any other errors? */ 1.115 +static int DATA_ERROR_COUNT = 0; /* count of data related errors or warnings */ 1.116 +static int INDENT_LEVEL = 0; 1.117 +static UBool NO_KNOWN = FALSE; 1.118 +static void *knownList = NULL; 1.119 +static char gTestName[1024] = ""; 1.120 +static UBool ON_LINE = FALSE; /* are we on the top line with our test name? */ 1.121 +static UBool HANGING_OUTPUT = FALSE; /* did the user leave us without a trailing \n ? */ 1.122 +static int GLOBAL_PRINT_COUNT = 0; /* global count of printouts */ 1.123 +int REPEAT_TESTS_INIT = 0; /* Was REPEAT_TESTS initialized? */ 1.124 +int REPEAT_TESTS = 1; /* Number of times to run the test */ 1.125 +int VERBOSITY = 0; /* be No-verbose by default */ 1.126 +int ERR_MSG =1; /* error messages will be displayed by default*/ 1.127 +int QUICK = 1; /* Skip some of the slower tests? */ 1.128 +int WARN_ON_MISSING_DATA = 0; /* Reduce data errs to warnings? */ 1.129 +UTraceLevel ICU_TRACE = UTRACE_OFF; /* ICU tracing level */ 1.130 +size_t MINIMUM_MEMORY_SIZE_FAILURE = (size_t)-1; /* Minimum library memory allocation window that will fail. */ 1.131 +size_t MAXIMUM_MEMORY_SIZE_FAILURE = (size_t)-1; /* Maximum library memory allocation window that will fail. */ 1.132 +static const char *ARGV_0 = "[ALL]"; 1.133 +static const char *XML_FILE_NAME=NULL; 1.134 +static char XML_PREFIX[256]; 1.135 +static const char *SUMMARY_FILE = NULL; 1.136 +FILE *XML_FILE = NULL; 1.137 +/*-------------------------------------------*/ 1.138 + 1.139 +/* strncmp that also makes sure there's a \0 at s2[0] */ 1.140 +static int strncmp_nullcheck( const char* s1, 1.141 + const char* s2, 1.142 + int n ) 1.143 +{ 1.144 + if (((int)strlen(s2) >= n) && s2[n] != 0) { 1.145 + return 3; /* null check fails */ 1.146 + } 1.147 + else { 1.148 + return strncmp ( s1, s2, n ); 1.149 + } 1.150 +} 1.151 + 1.152 +static void getNextLevel( const char* name, 1.153 + int* nameLen, 1.154 + const char** nextName ) 1.155 +{ 1.156 + /* Get the next component of the name */ 1.157 + *nextName = strchr(name, TEST_SEPARATOR); 1.158 + 1.159 + if( *nextName != 0 ) 1.160 + { 1.161 + char n[255]; 1.162 + *nameLen = (int)((*nextName) - name); 1.163 + (*nextName)++; /* skip '/' */ 1.164 + strncpy(n, name, *nameLen); 1.165 + n[*nameLen] = 0; 1.166 + /*printf("->%s-< [%d] -> [%s]\n", name, *nameLen, *nextName);*/ 1.167 + } 1.168 + else { 1.169 + *nameLen = (int)strlen(name); 1.170 + } 1.171 +} 1.172 + 1.173 +static TestNode *createTestNode(const char* name, int32_t nameLen) 1.174 +{ 1.175 + TestNode *newNode; 1.176 + 1.177 + newNode = (TestNode*)malloc(sizeof(TestNode) + (nameLen + 1)); 1.178 + 1.179 + newNode->test = NULL; 1.180 + newNode->sibling = NULL; 1.181 + newNode->child = NULL; 1.182 + 1.183 + strncpy( newNode->name, name, nameLen ); 1.184 + newNode->name[nameLen] = 0; 1.185 + 1.186 + return newNode; 1.187 +} 1.188 + 1.189 +void T_CTEST_EXPORT2 1.190 +cleanUpTestTree(TestNode *tn) 1.191 +{ 1.192 + if(tn->child != NULL) { 1.193 + cleanUpTestTree(tn->child); 1.194 + } 1.195 + if(tn->sibling != NULL) { 1.196 + cleanUpTestTree(tn->sibling); 1.197 + } 1.198 + 1.199 + free(tn); 1.200 + 1.201 +} 1.202 + 1.203 + 1.204 +void T_CTEST_EXPORT2 1.205 +addTest(TestNode** root, 1.206 + TestFunctionPtr test, 1.207 + const char* name ) 1.208 +{ 1.209 + TestNode *newNode; 1.210 + 1.211 + /*if this is the first Test created*/ 1.212 + if (*root == NULL) 1.213 + *root = createTestNode("", 0); 1.214 + 1.215 + newNode = addTestNode( *root, name ); 1.216 + assert(newNode != 0 ); 1.217 + /* printf("addTest: nreName = %s\n", newNode->name );*/ 1.218 + 1.219 + newNode->test = test; 1.220 +} 1.221 + 1.222 +/* non recursive insert function */ 1.223 +static TestNode *addTestNode ( TestNode *root, const char *name ) 1.224 +{ 1.225 + const char* nextName; 1.226 + TestNode *nextNode, *curNode; 1.227 + int nameLen; /* length of current 'name' */ 1.228 + 1.229 + /* remove leading slash */ 1.230 + if ( *name == TEST_SEPARATOR ) 1.231 + name++; 1.232 + 1.233 + curNode = root; 1.234 + 1.235 + for(;;) 1.236 + { 1.237 + /* Start with the next child */ 1.238 + nextNode = curNode->child; 1.239 + 1.240 + getNextLevel ( name, &nameLen, &nextName ); 1.241 + 1.242 + /* printf("* %s\n", name );*/ 1.243 + 1.244 + /* if nextNode is already null, then curNode has no children 1.245 + -- add them */ 1.246 + if( nextNode == NULL ) 1.247 + { 1.248 + /* Add all children of the node */ 1.249 + do 1.250 + { 1.251 + /* Get the next component of the name */ 1.252 + getNextLevel(name, &nameLen, &nextName); 1.253 + 1.254 + /* update curName to have the next name segment */ 1.255 + curNode->child = createTestNode(name, nameLen); 1.256 + /* printf("*** added %s\n", curNode->child->name );*/ 1.257 + curNode = curNode->child; 1.258 + name = nextName; 1.259 + } 1.260 + while( name != NULL ); 1.261 + 1.262 + return curNode; 1.263 + } 1.264 + 1.265 + /* Search across for the name */ 1.266 + while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 ) 1.267 + { 1.268 + curNode = nextNode; 1.269 + nextNode = nextNode -> sibling; 1.270 + 1.271 + if ( nextNode == NULL ) 1.272 + { 1.273 + /* Did not find 'name' on this level. */ 1.274 + nextNode = createTestNode(name, nameLen); 1.275 + curNode->sibling = nextNode; 1.276 + break; 1.277 + } 1.278 + } 1.279 + 1.280 + /* nextNode matches 'name' */ 1.281 + 1.282 + if (nextName == NULL) /* end of the line */ 1.283 + { 1.284 + return nextNode; 1.285 + } 1.286 + 1.287 + /* Loop again with the next item */ 1.288 + name = nextName; 1.289 + curNode = nextNode; 1.290 + } 1.291 +} 1.292 + 1.293 +/** 1.294 + * Log the time taken. May not output anything. 1.295 + * @param deltaTime change in time 1.296 + */ 1.297 +void T_CTEST_EXPORT2 str_timeDelta(char *str, UDate deltaTime) { 1.298 + if (deltaTime > 110000.0 ) { 1.299 + double mins = uprv_floor(deltaTime/60000.0); 1.300 + sprintf(str, "[(%.0fm %.1fs)]", mins, (deltaTime-(mins*60000.0))/1000.0); 1.301 + } else if (deltaTime > 1500.0) { 1.302 + sprintf(str, "((%.1fs))", deltaTime/1000.0); 1.303 + } else if(deltaTime>900.0) { 1.304 + sprintf(str, "( %.2fs )", deltaTime/1000.0); 1.305 + } else if(deltaTime > 5.0) { 1.306 + sprintf(str, " (%.0fms) ", deltaTime); 1.307 + } else { 1.308 + str[0]=0; /* at least terminate it. */ 1.309 + } 1.310 +} 1.311 + 1.312 +static void print_timeDelta(UDate deltaTime) { 1.313 + char str[256]; 1.314 + str_timeDelta(str, deltaTime); 1.315 + if(str[0]) { 1.316 + printf("%s", str); 1.317 + } 1.318 +} 1.319 + 1.320 +/** 1.321 + * Run or list tests (according to mode) in a subtree. 1.322 + * 1.323 + * @param root root of the subtree to operate on 1.324 + * @param depth The depth of this tree (0=root) 1.325 + * @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. 1.326 + * @param mode what mode we are operating in. 1.327 + */ 1.328 +static void iterateTestsWithLevel ( const TestNode* root, 1.329 + int depth, 1.330 + const TestNode** nodeList, 1.331 + TestMode mode) 1.332 +{ 1.333 + int i; 1.334 + 1.335 + char pathToFunction[MAXTESTNAME] = ""; 1.336 + char separatorString[2] = { TEST_SEPARATOR, '\0'}; 1.337 +#if SHOW_TIMES 1.338 + UDate allStartTime = -1, allStopTime = -1; 1.339 +#endif 1.340 + 1.341 + if(depth<2) { 1.342 + allStartTime = uprv_getRawUTCtime(); 1.343 + } 1.344 + 1.345 + if ( root == NULL ) 1.346 + return; 1.347 + 1.348 + /* record the current root node, and increment depth. */ 1.349 + nodeList[depth++] = root; 1.350 + /* depth is now the depth of root's children. */ 1.351 + 1.352 + /* Collect the 'path' to the current subtree. */ 1.353 + for ( i=0;i<(depth-1);i++ ) 1.354 + { 1.355 + strcat(pathToFunction, nodeList[i]->name); 1.356 + strcat(pathToFunction, separatorString); 1.357 + } 1.358 + strcat(pathToFunction, nodeList[i]->name); /* including 'root' */ 1.359 + 1.360 + /* print test name and space. */ 1.361 + INDENT_LEVEL = depth-1; 1.362 + if(root->name[0]) { 1.363 + log_testinfo_i("%s ", root->name); 1.364 + } else { 1.365 + log_testinfo_i("(%s) ", ARGV_0); 1.366 + } 1.367 + ON_LINE = TRUE; /* we are still on the line with the test name */ 1.368 + 1.369 + 1.370 + if ( (mode == RUNTESTS) && 1.371 + (root->test != NULL)) /* if root is a leaf node, run it */ 1.372 + { 1.373 + int myERROR_COUNT = ERROR_COUNT; 1.374 + int myGLOBAL_PRINT_COUNT = GLOBAL_PRINT_COUNT; 1.375 +#if SHOW_TIMES 1.376 + UDate startTime, stopTime; 1.377 + char timeDelta[256]; 1.378 + char timeSeconds[256]; 1.379 +#else 1.380 + const char timeDelta[] = "(unknown)"; 1.381 + const char timeSeconds[] = "0.000"; 1.382 +#endif 1.383 + currentTest = root; 1.384 + INDENT_LEVEL = depth; /* depth of subitems */ 1.385 + ONE_ERROR=0; 1.386 + HANGING_OUTPUT=FALSE; 1.387 +#if SHOW_TIMES 1.388 + startTime = uprv_getRawUTCtime(); 1.389 +#endif 1.390 + strcpy(gTestName, pathToFunction); 1.391 + root->test(); /* PERFORM THE TEST ************************/ 1.392 +#if SHOW_TIMES 1.393 + stopTime = uprv_getRawUTCtime(); 1.394 +#endif 1.395 + if(HANGING_OUTPUT) { 1.396 + log_testinfo("\n"); 1.397 + HANGING_OUTPUT=FALSE; 1.398 + } 1.399 + INDENT_LEVEL = depth-1; /* depth of root */ 1.400 + currentTest = NULL; 1.401 + if((ONE_ERROR>0)&&(ERROR_COUNT==0)) { 1.402 + ERROR_COUNT++; /* There was an error without a newline */ 1.403 + } 1.404 + ONE_ERROR=0; 1.405 + 1.406 +#if SHOW_TIMES 1.407 + str_timeDelta(timeDelta, stopTime-startTime); 1.408 + sprintf(timeSeconds, "%f", (stopTime-startTime)/1000.0); 1.409 +#endif 1.410 + ctest_xml_testcase(pathToFunction, pathToFunction, timeSeconds, (myERROR_COUNT!=ERROR_COUNT)?"error":NULL); 1.411 + 1.412 + if (myERROR_COUNT != ERROR_COUNT) { 1.413 + log_testinfo_i("} ---[%d ERRORS in %s] ", ERROR_COUNT - myERROR_COUNT, pathToFunction); 1.414 + strcpy(ERROR_LOG[ERRONEOUS_FUNCTION_COUNT++], pathToFunction); 1.415 + } else { 1.416 + if(!ON_LINE) { /* had some output */ 1.417 + int spaces = FLAG_INDENT-(depth-1); 1.418 + log_testinfo_i("} %*s[OK] ", spaces, "---"); 1.419 + if((GLOBAL_PRINT_COUNT-myGLOBAL_PRINT_COUNT)>PAGE_SIZE_LIMIT) { 1.420 + log_testinfo(" %s ", pathToFunction); /* in case they forgot. */ 1.421 + } 1.422 + } else { 1.423 + /* put -- out at 30 sp. */ 1.424 + int spaces = FLAG_INDENT-(strlen(root->name)+depth); 1.425 + if(spaces<0) spaces=0; 1.426 + log_testinfo(" %*s[OK] ", spaces,"---"); 1.427 + } 1.428 + } 1.429 + 1.430 +#if SHOW_TIMES 1.431 + if(timeDelta[0]) printf("%s", timeDelta); 1.432 +#endif 1.433 + 1.434 + ON_LINE = TRUE; /* we are back on-line */ 1.435 + } 1.436 + 1.437 + INDENT_LEVEL = depth-1; /* root */ 1.438 + 1.439 + /* we want these messages to be at 0 indent. so just push the indent level breifly. */ 1.440 + if(mode==SHOWTESTS) { 1.441 + log_testinfo("---%s%c\n",pathToFunction, nodeList[i]->test?' ':TEST_SEPARATOR ); 1.442 + } 1.443 + 1.444 + INDENT_LEVEL = depth; 1.445 + 1.446 + if(root->child) { 1.447 + int myERROR_COUNT = ERROR_COUNT; 1.448 + int myGLOBAL_PRINT_COUNT = GLOBAL_PRINT_COUNT; 1.449 + if(mode!=SHOWTESTS) { 1.450 + INDENT_LEVEL=depth-1; 1.451 + log_testinfo("{\n"); 1.452 + INDENT_LEVEL=depth; 1.453 + } 1.454 + 1.455 + iterateTestsWithLevel ( root->child, depth, nodeList, mode ); 1.456 + 1.457 + if(mode!=SHOWTESTS) { 1.458 + INDENT_LEVEL=depth-1; 1.459 + log_testinfo_i("} "); /* TODO: summarize subtests */ 1.460 + if((depth>1) && (ERROR_COUNT > myERROR_COUNT)) { 1.461 + log_testinfo("[%d %s in %s] ", ERROR_COUNT-myERROR_COUNT, (ERROR_COUNT-myERROR_COUNT)==1?"error":"errors", pathToFunction); 1.462 + } else if((GLOBAL_PRINT_COUNT-myGLOBAL_PRINT_COUNT)>PAGE_SIZE_LIMIT || (depth<1)) { 1.463 + if(pathToFunction[0]) { 1.464 + log_testinfo(" %s ", pathToFunction); /* in case they forgot. */ 1.465 + } else { 1.466 + log_testinfo(" / (%s) ", ARGV_0); 1.467 + } 1.468 + } 1.469 + 1.470 + ON_LINE=TRUE; 1.471 + } 1.472 + } 1.473 + depth--; 1.474 + 1.475 +#if SHOW_TIMES 1.476 + if(depth<2) { 1.477 + allStopTime = uprv_getRawUTCtime(); 1.478 + print_timeDelta(allStopTime-allStartTime); 1.479 + } 1.480 +#endif 1.481 + 1.482 + if(mode!=SHOWTESTS && ON_LINE) { 1.483 + log_testinfo("\n"); 1.484 + } 1.485 + 1.486 + if ( depth != 0 ) { /* DO NOT iterate over siblings of the root. TODO: why not? */ 1.487 + iterateTestsWithLevel ( root->sibling, depth, nodeList, mode ); 1.488 + } 1.489 +} 1.490 + 1.491 + 1.492 + 1.493 +void T_CTEST_EXPORT2 1.494 +showTests ( const TestNode *root ) 1.495 +{ 1.496 + /* make up one for them */ 1.497 + const TestNode *nodeList[MAXTESTS]; 1.498 + 1.499 + if (root == NULL) 1.500 + log_err("TEST CAN'T BE FOUND!"); 1.501 + 1.502 + iterateTestsWithLevel ( root, 0, nodeList, SHOWTESTS ); 1.503 + 1.504 +} 1.505 + 1.506 +void T_CTEST_EXPORT2 1.507 +runTests ( const TestNode *root ) 1.508 +{ 1.509 + int i; 1.510 + const TestNode *nodeList[MAXTESTS]; 1.511 + /* make up one for them */ 1.512 + 1.513 + 1.514 + if (root == NULL) 1.515 + log_err("TEST CAN'T BE FOUND!\n"); 1.516 + 1.517 + ERRONEOUS_FUNCTION_COUNT = ERROR_COUNT = 0; 1.518 + iterateTestsWithLevel ( root, 0, nodeList, RUNTESTS ); 1.519 + 1.520 + /*print out result summary*/ 1.521 + 1.522 + ON_LINE=FALSE; /* just in case */ 1.523 + 1.524 + if(knownList != NULL) { 1.525 + if( udbg_knownIssue_print(knownList) ) { 1.526 + fprintf(stdout, "(To run suppressed tests, use the -K option.) \n\n"); 1.527 + } 1.528 + udbg_knownIssue_close(knownList); 1.529 + } 1.530 + 1.531 + if (ERROR_COUNT) 1.532 + { 1.533 + fprintf(stdout,"\nSUMMARY:\n"); 1.534 + fflush(stdout); 1.535 + fprintf(stdout,"******* [Total error count:\t%d]\n", ERROR_COUNT); 1.536 + fflush(stdout); 1.537 + fprintf(stdout, " Errors in\n"); 1.538 + for (i=0;i < ERRONEOUS_FUNCTION_COUNT; i++) 1.539 + fprintf(stdout, "[%s]\n",ERROR_LOG[i]); 1.540 + if(SUMMARY_FILE != NULL) { 1.541 + FILE *summf = fopen(SUMMARY_FILE, "w"); 1.542 + if(summf!=NULL) { 1.543 + for (i=0;i < ERRONEOUS_FUNCTION_COUNT; i++) 1.544 + fprintf(summf, "%s\n",ERROR_LOG[i]); 1.545 + fclose(summf); 1.546 + } 1.547 + } 1.548 + } 1.549 + else 1.550 + { 1.551 + log_testinfo("\n[All tests passed successfully...]\n"); 1.552 + } 1.553 + 1.554 + if(DATA_ERROR_COUNT) { 1.555 + if(WARN_ON_MISSING_DATA==0) { 1.556 + log_testinfo("\t*Note* some errors are data-loading related. If the data used is not the \n" 1.557 + "\tstock ICU data (i.e some have been added or removed), consider using\n" 1.558 + "\tthe '-w' option to turn these errors into warnings.\n"); 1.559 + } else { 1.560 + log_testinfo("\t*WARNING* some data-loading errors were ignored by the -w option.\n"); 1.561 + } 1.562 + } 1.563 +} 1.564 + 1.565 +const char* T_CTEST_EXPORT2 1.566 +getTestName(void) 1.567 +{ 1.568 + if(currentTest != NULL) { 1.569 + return currentTest->name; 1.570 + } else { 1.571 + return NULL; 1.572 + } 1.573 +} 1.574 + 1.575 +const TestNode* T_CTEST_EXPORT2 1.576 +getTest(const TestNode* root, const char* name) 1.577 +{ 1.578 + const char* nextName; 1.579 + TestNode *nextNode; 1.580 + const TestNode* curNode; 1.581 + int nameLen; /* length of current 'name' */ 1.582 + 1.583 + if (root == NULL) { 1.584 + log_err("TEST CAN'T BE FOUND!\n"); 1.585 + return NULL; 1.586 + } 1.587 + /* remove leading slash */ 1.588 + if ( *name == TEST_SEPARATOR ) 1.589 + name++; 1.590 + 1.591 + curNode = root; 1.592 + 1.593 + for(;;) 1.594 + { 1.595 + /* Start with the next child */ 1.596 + nextNode = curNode->child; 1.597 + 1.598 + getNextLevel ( name, &nameLen, &nextName ); 1.599 + 1.600 + /* printf("* %s\n", name );*/ 1.601 + 1.602 + /* if nextNode is already null, then curNode has no children 1.603 + -- add them */ 1.604 + if( nextNode == NULL ) 1.605 + { 1.606 + return NULL; 1.607 + } 1.608 + 1.609 + /* Search across for the name */ 1.610 + while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 ) 1.611 + { 1.612 + curNode = nextNode; 1.613 + nextNode = nextNode -> sibling; 1.614 + 1.615 + if ( nextNode == NULL ) 1.616 + { 1.617 + /* Did not find 'name' on this level. */ 1.618 + return NULL; 1.619 + } 1.620 + } 1.621 + 1.622 + /* nextNode matches 'name' */ 1.623 + 1.624 + if (nextName == NULL) /* end of the line */ 1.625 + { 1.626 + return nextNode; 1.627 + } 1.628 + 1.629 + /* Loop again with the next item */ 1.630 + name = nextName; 1.631 + curNode = nextNode; 1.632 + } 1.633 +} 1.634 + 1.635 +/* =========== io functions ======== */ 1.636 + 1.637 +static void go_offline_with_marker(const char *mrk) { 1.638 + UBool wasON_LINE = ON_LINE; 1.639 + 1.640 + if(ON_LINE) { 1.641 + log_testinfo(" {\n"); 1.642 + ON_LINE=FALSE; 1.643 + } 1.644 + 1.645 + if(!HANGING_OUTPUT || wasON_LINE) { 1.646 + if(mrk != NULL) { 1.647 + fputs(mrk, stdout); 1.648 + } 1.649 + } 1.650 +} 1.651 + 1.652 +static void go_offline() { 1.653 + go_offline_with_marker(NULL); 1.654 +} 1.655 + 1.656 +static void go_offline_err() { 1.657 + go_offline(); 1.658 +} 1.659 + 1.660 +static void first_line_verbose() { 1.661 + go_offline_with_marker("v"); 1.662 +} 1.663 + 1.664 +static void first_line_err() { 1.665 + go_offline_with_marker("!"); 1.666 +} 1.667 + 1.668 +static void first_line_info() { 1.669 + go_offline_with_marker("\""); 1.670 +} 1.671 + 1.672 +static void first_line_test() { 1.673 + fputs(" ", stdout); 1.674 +} 1.675 + 1.676 + 1.677 +static void vlog_err(const char *prefix, const char *pattern, va_list ap) 1.678 +{ 1.679 + if( ERR_MSG == FALSE){ 1.680 + return; 1.681 + } 1.682 + fputs("!", stdout); /* col 1 - bang */ 1.683 + fprintf(stdout, "%-*s", INDENT_LEVEL,"" ); 1.684 + if(prefix) { 1.685 + fputs(prefix, stdout); 1.686 + } 1.687 + vfprintf(stdout, pattern, ap); 1.688 + fflush(stdout); 1.689 + va_end(ap); 1.690 + if((*pattern==0) || (pattern[strlen(pattern)-1]!='\n')) { 1.691 + HANGING_OUTPUT=1; 1.692 + } else { 1.693 + HANGING_OUTPUT=0; 1.694 + } 1.695 + GLOBAL_PRINT_COUNT++; 1.696 +} 1.697 + 1.698 +static UBool vlog_knownIssue(const char *ticket, const char *pattern, va_list ap) 1.699 +{ 1.700 + char buf[2048]; 1.701 + UBool firstForTicket; 1.702 + UBool firstForWhere; 1.703 + 1.704 + if(NO_KNOWN) return FALSE; 1.705 + if(pattern==NULL) pattern=""; 1.706 + 1.707 + vsprintf(buf, pattern, ap); 1.708 + knownList = udbg_knownIssue_open(knownList, ticket, gTestName, buf, 1.709 + &firstForTicket, &firstForWhere); 1.710 + 1.711 + if(firstForTicket || firstForWhere) { 1.712 + log_info("(Known issue #%s) %s", ticket, buf); 1.713 + } else { 1.714 + log_verbose("(Known issue #%s) %s", ticket, buf); 1.715 + } 1.716 + 1.717 + return TRUE; 1.718 +} 1.719 + 1.720 + 1.721 +void T_CTEST_EXPORT2 1.722 +vlog_info(const char *prefix, const char *pattern, va_list ap) 1.723 +{ 1.724 + first_line_info(); 1.725 + fprintf(stdout, "%-*s", INDENT_LEVEL,"" ); 1.726 + if(prefix) { 1.727 + fputs(prefix, stdout); 1.728 + } 1.729 + vfprintf(stdout, pattern, ap); 1.730 + fflush(stdout); 1.731 + va_end(ap); 1.732 + if((*pattern==0) || (pattern[strlen(pattern)-1]!='\n')) { 1.733 + HANGING_OUTPUT=1; 1.734 + } else { 1.735 + HANGING_OUTPUT=0; 1.736 + } 1.737 + GLOBAL_PRINT_COUNT++; 1.738 +} 1.739 +/** 1.740 + * Log test structure, with indent 1.741 + */ 1.742 +static void log_testinfo_i(const char *pattern, ...) 1.743 +{ 1.744 + va_list ap; 1.745 + first_line_test(); 1.746 + fprintf(stdout, "%-*s", INDENT_LEVEL,"" ); 1.747 + va_start(ap, pattern); 1.748 + vfprintf(stdout, pattern, ap); 1.749 + fflush(stdout); 1.750 + va_end(ap); 1.751 + GLOBAL_PRINT_COUNT++; 1.752 +} 1.753 +/** 1.754 + * Log test structure (no ident) 1.755 + */ 1.756 +static void log_testinfo(const char *pattern, ...) 1.757 +{ 1.758 + va_list ap; 1.759 + va_start(ap, pattern); 1.760 + first_line_test(); 1.761 + vfprintf(stdout, pattern, ap); 1.762 + fflush(stdout); 1.763 + va_end(ap); 1.764 + GLOBAL_PRINT_COUNT++; 1.765 +} 1.766 + 1.767 + 1.768 +static void vlog_verbose(const char *prefix, const char *pattern, va_list ap) 1.769 +{ 1.770 + if ( VERBOSITY == FALSE ) 1.771 + return; 1.772 + 1.773 + first_line_verbose(); 1.774 + fprintf(stdout, "%-*s", INDENT_LEVEL,"" ); 1.775 + if(prefix) { 1.776 + fputs(prefix, stdout); 1.777 + } 1.778 + vfprintf(stdout, pattern, ap); 1.779 + fflush(stdout); 1.780 + va_end(ap); 1.781 + GLOBAL_PRINT_COUNT++; 1.782 + if((*pattern==0) || (pattern[strlen(pattern)-1]!='\n')) { 1.783 + HANGING_OUTPUT=1; 1.784 + } else { 1.785 + HANGING_OUTPUT=0; 1.786 + } 1.787 +} 1.788 + 1.789 +void T_CTEST_EXPORT2 1.790 +log_err(const char* pattern, ...) 1.791 +{ 1.792 + va_list ap; 1.793 + first_line_err(); 1.794 + if(strchr(pattern, '\n') != NULL) { 1.795 + /* 1.796 + * Count errors only if there is a line feed in the pattern 1.797 + * so that we do not exaggerate our error count. 1.798 + */ 1.799 + ++ERROR_COUNT; 1.800 + } else { 1.801 + /* Count at least one error. */ 1.802 + ONE_ERROR=1; 1.803 + } 1.804 + va_start(ap, pattern); 1.805 + vlog_err(NULL, pattern, ap); 1.806 +} 1.807 + 1.808 +UBool T_CTEST_EXPORT2 1.809 +log_knownIssue(const char *ticket, const char *pattern, ...) { 1.810 + va_list ap; 1.811 + va_start(ap, pattern); 1.812 + return vlog_knownIssue(ticket, pattern, ap); 1.813 +} 1.814 + 1.815 +void T_CTEST_EXPORT2 1.816 +log_err_status(UErrorCode status, const char* pattern, ...) 1.817 +{ 1.818 + va_list ap; 1.819 + va_start(ap, pattern); 1.820 + 1.821 + if ((status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR)) { 1.822 + ++DATA_ERROR_COUNT; /* for informational message at the end */ 1.823 + 1.824 + if (WARN_ON_MISSING_DATA == 0) { 1.825 + first_line_err(); 1.826 + /* Fatal error. */ 1.827 + if (strchr(pattern, '\n') != NULL) { 1.828 + ++ERROR_COUNT; 1.829 + } else { 1.830 + ++ONE_ERROR; 1.831 + } 1.832 + vlog_err(NULL, pattern, ap); /* no need for prefix in default case */ 1.833 + } else { 1.834 + vlog_info("[DATA] ", pattern, ap); 1.835 + } 1.836 + } else { 1.837 + first_line_err(); 1.838 + /* Fatal error. */ 1.839 + if(strchr(pattern, '\n') != NULL) { 1.840 + ++ERROR_COUNT; 1.841 + } else { 1.842 + ++ONE_ERROR; 1.843 + } 1.844 + vlog_err(NULL, pattern, ap); /* no need for prefix in default case */ 1.845 + } 1.846 +} 1.847 + 1.848 +void T_CTEST_EXPORT2 1.849 +log_info(const char* pattern, ...) 1.850 +{ 1.851 + va_list ap; 1.852 + 1.853 + va_start(ap, pattern); 1.854 + vlog_info(NULL, pattern, ap); 1.855 +} 1.856 + 1.857 +void T_CTEST_EXPORT2 1.858 +log_verbose(const char* pattern, ...) 1.859 +{ 1.860 + va_list ap; 1.861 + 1.862 + va_start(ap, pattern); 1.863 + vlog_verbose(NULL, pattern, ap); 1.864 +} 1.865 + 1.866 + 1.867 +void T_CTEST_EXPORT2 1.868 +log_data_err(const char* pattern, ...) 1.869 +{ 1.870 + va_list ap; 1.871 + va_start(ap, pattern); 1.872 + 1.873 + go_offline_err(); 1.874 + ++DATA_ERROR_COUNT; /* for informational message at the end */ 1.875 + 1.876 + if(WARN_ON_MISSING_DATA == 0) { 1.877 + /* Fatal error. */ 1.878 + if(strchr(pattern, '\n') != NULL) { 1.879 + ++ERROR_COUNT; 1.880 + } 1.881 + vlog_err(NULL, pattern, ap); /* no need for prefix in default case */ 1.882 + } else { 1.883 + vlog_info("[DATA] ", pattern, ap); 1.884 + } 1.885 +} 1.886 + 1.887 + 1.888 +/* 1.889 + * Tracing functions. 1.890 + */ 1.891 +static int traceFnNestingDepth = 0; 1.892 +U_CDECL_BEGIN 1.893 +static void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) { 1.894 + char buf[500]; 1.895 + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber)); buf[sizeof(buf)-1]=0; 1.896 + fputs(buf, stdout); 1.897 + traceFnNestingDepth++; 1.898 +} 1.899 + 1.900 +static void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) { char buf[500]; 1.901 + 1.902 + if (traceFnNestingDepth>0) { 1.903 + traceFnNestingDepth--; 1.904 + } 1.905 + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber)); buf[sizeof(buf)-1]=0; 1.906 + fputs(buf, stdout); 1.907 + utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); 1.908 + buf[sizeof(buf)-1]=0; 1.909 + fputs(buf, stdout); 1.910 + putc('\n', stdout); 1.911 +} 1.912 + 1.913 +static void U_CALLCONV TraceData(const void *context, int32_t fnNumber, 1.914 + int32_t level, const char *fmt, va_list args) { 1.915 + char buf[500]; 1.916 + utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); 1.917 + buf[sizeof(buf)-1]=0; 1.918 + fputs(buf, stdout); 1.919 + putc('\n', stdout); 1.920 +} 1.921 + 1.922 +static void *U_CALLCONV ctest_libMalloc(const void *context, size_t size) { 1.923 + /*if (VERBOSITY) { 1.924 + printf("Allocated %ld\n", (long)size); 1.925 + }*/ 1.926 + if (MINIMUM_MEMORY_SIZE_FAILURE <= size && size <= MAXIMUM_MEMORY_SIZE_FAILURE) { 1.927 + return NULL; 1.928 + } 1.929 + return malloc(size); 1.930 +} 1.931 +static void *U_CALLCONV ctest_libRealloc(const void *context, void *mem, size_t size) { 1.932 + /*if (VERBOSITY) { 1.933 + printf("Reallocated %ld\n", (long)size); 1.934 + }*/ 1.935 + if (MINIMUM_MEMORY_SIZE_FAILURE <= size && size <= MAXIMUM_MEMORY_SIZE_FAILURE) { 1.936 + /*free(mem);*/ /* Realloc doesn't free on failure. */ 1.937 + return NULL; 1.938 + } 1.939 + return realloc(mem, size); 1.940 +} 1.941 +static void U_CALLCONV ctest_libFree(const void *context, void *mem) { 1.942 + free(mem); 1.943 +} 1.944 + 1.945 +int T_CTEST_EXPORT2 1.946 +initArgs( int argc, const char* const argv[], ArgHandlerPtr argHandler, void *context) 1.947 +{ 1.948 + int i; 1.949 + int argSkip = 0; 1.950 + 1.951 + VERBOSITY = FALSE; 1.952 + ERR_MSG = TRUE; 1.953 + 1.954 + ARGV_0=argv[0]; 1.955 + 1.956 + for( i=1; i<argc; i++) 1.957 + { 1.958 + if ( argv[i][0] == '/' ) 1.959 + { 1.960 + /* We don't run the tests here. */ 1.961 + continue; 1.962 + } 1.963 + else if ((strcmp( argv[i], "-a") == 0) || (strcmp(argv[i],"-all") == 0)) 1.964 + { 1.965 + /* We don't run the tests here. */ 1.966 + continue; 1.967 + } 1.968 + else if (strcmp( argv[i], "-v" )==0 || strcmp( argv[i], "-verbose")==0) 1.969 + { 1.970 + VERBOSITY = TRUE; 1.971 + } 1.972 + else if (strcmp( argv[i], "-l" )==0 ) 1.973 + { 1.974 + /* doList = TRUE; */ 1.975 + } 1.976 + else if (strcmp( argv[i], "-e1") == 0) 1.977 + { 1.978 + QUICK = -1; 1.979 + } 1.980 + else if (strcmp( argv[i], "-e") ==0) 1.981 + { 1.982 + QUICK = 0; 1.983 + } 1.984 + else if (strcmp( argv[i], "-K") ==0) 1.985 + { 1.986 + NO_KNOWN = 1; 1.987 + } 1.988 + else if (strncmp( argv[i], "-E",2) ==0) 1.989 + { 1.990 + SUMMARY_FILE=argv[i]+2; 1.991 + } 1.992 + else if (strcmp( argv[i], "-w") ==0) 1.993 + { 1.994 + WARN_ON_MISSING_DATA = TRUE; 1.995 + } 1.996 + else if (strcmp( argv[i], "-m") ==0) 1.997 + { 1.998 + UErrorCode errorCode = U_ZERO_ERROR; 1.999 + if (i+1 < argc) { 1.1000 + char *endPtr = NULL; 1.1001 + i++; 1.1002 + MINIMUM_MEMORY_SIZE_FAILURE = (size_t)strtol(argv[i], &endPtr, 10); 1.1003 + if (endPtr == argv[i]) { 1.1004 + printf("Can't parse %s\n", argv[i]); 1.1005 + help(argv[0]); 1.1006 + return 0; 1.1007 + } 1.1008 + if (*endPtr == '-') { 1.1009 + char *maxPtr = endPtr+1; 1.1010 + endPtr = NULL; 1.1011 + MAXIMUM_MEMORY_SIZE_FAILURE = (size_t)strtol(maxPtr, &endPtr, 10); 1.1012 + if (endPtr == argv[i]) { 1.1013 + printf("Can't parse %s\n", argv[i]); 1.1014 + help(argv[0]); 1.1015 + return 0; 1.1016 + } 1.1017 + } 1.1018 + } 1.1019 + /* Use the default value */ 1.1020 + u_setMemoryFunctions(NULL, ctest_libMalloc, ctest_libRealloc, ctest_libFree, &errorCode); 1.1021 + if (U_FAILURE(errorCode)) { 1.1022 + printf("u_setMemoryFunctions returned %s\n", u_errorName(errorCode)); 1.1023 + return 0; 1.1024 + } 1.1025 + } 1.1026 + else if(strcmp( argv[i], "-n") == 0 || strcmp( argv[i], "-no_err_msg") == 0) 1.1027 + { 1.1028 + ERR_MSG = FALSE; 1.1029 + } 1.1030 + else if (strcmp( argv[i], "-r") == 0) 1.1031 + { 1.1032 + if (!REPEAT_TESTS_INIT) { 1.1033 + REPEAT_TESTS++; 1.1034 + } 1.1035 + } 1.1036 + else if (strcmp( argv[i], "-x") == 0) 1.1037 + { 1.1038 + if(++i>=argc) { 1.1039 + printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n"); 1.1040 + return 0; 1.1041 + } 1.1042 + if(ctest_xml_setFileName(argv[i])) { /* set the name */ 1.1043 + return 0; 1.1044 + } 1.1045 + } 1.1046 + else if (strcmp( argv[i], "-t_info") == 0) { 1.1047 + ICU_TRACE = UTRACE_INFO; 1.1048 + } 1.1049 + else if (strcmp( argv[i], "-t_error") == 0) { 1.1050 + ICU_TRACE = UTRACE_ERROR; 1.1051 + } 1.1052 + else if (strcmp( argv[i], "-t_warn") == 0) { 1.1053 + ICU_TRACE = UTRACE_WARNING; 1.1054 + } 1.1055 + else if (strcmp( argv[i], "-t_verbose") == 0) { 1.1056 + ICU_TRACE = UTRACE_VERBOSE; 1.1057 + } 1.1058 + else if (strcmp( argv[i], "-t_oc") == 0) { 1.1059 + ICU_TRACE = UTRACE_OPEN_CLOSE; 1.1060 + } 1.1061 + else if (strcmp( argv[i], "-h" )==0 || strcmp( argv[i], "--help" )==0) 1.1062 + { 1.1063 + help( argv[0] ); 1.1064 + return 0; 1.1065 + } 1.1066 + else if (argHandler != NULL && (argSkip = argHandler(i, argc, argv, context)) > 0) 1.1067 + { 1.1068 + i += argSkip - 1; 1.1069 + } 1.1070 + else 1.1071 + { 1.1072 + printf("* unknown option: %s\n", argv[i]); 1.1073 + help( argv[0] ); 1.1074 + return 0; 1.1075 + } 1.1076 + } 1.1077 + if (ICU_TRACE != UTRACE_OFF) { 1.1078 + utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData); 1.1079 + utrace_setLevel(ICU_TRACE); 1.1080 + } 1.1081 + 1.1082 + return 1; /* total error count */ 1.1083 +} 1.1084 + 1.1085 +int T_CTEST_EXPORT2 1.1086 +runTestRequest(const TestNode* root, 1.1087 + int argc, 1.1088 + const char* const argv[]) 1.1089 +{ 1.1090 + /** 1.1091 + * This main will parse the l, v, h, n, and path arguments 1.1092 + */ 1.1093 + const TestNode* toRun; 1.1094 + int i; 1.1095 + int doList = FALSE; 1.1096 + int subtreeOptionSeen = FALSE; 1.1097 + 1.1098 + int errorCount = 0; 1.1099 + 1.1100 + toRun = root; 1.1101 + 1.1102 + if(ctest_xml_init(ARGV_0)) { 1.1103 + return 1; /* couldn't fire up XML thing */ 1.1104 + } 1.1105 + 1.1106 + for( i=1; i<argc; i++) 1.1107 + { 1.1108 + if ( argv[i][0] == '/' ) 1.1109 + { 1.1110 + printf("Selecting subtree '%s'\n", argv[i]); 1.1111 + 1.1112 + if ( argv[i][1] == 0 ) 1.1113 + toRun = root; 1.1114 + else 1.1115 + toRun = getTest(root, argv[i]); 1.1116 + 1.1117 + if ( toRun == NULL ) 1.1118 + { 1.1119 + printf("* Could not find any matching subtree\n"); 1.1120 + return -1; 1.1121 + } 1.1122 + 1.1123 + ON_LINE=FALSE; /* just in case */ 1.1124 + 1.1125 + if( doList == TRUE) 1.1126 + showTests(toRun); 1.1127 + else 1.1128 + runTests(toRun); 1.1129 + 1.1130 + ON_LINE=FALSE; /* just in case */ 1.1131 + 1.1132 + errorCount += ERROR_COUNT; 1.1133 + 1.1134 + subtreeOptionSeen = TRUE; 1.1135 + } else if ((strcmp( argv[i], "-a") == 0) || (strcmp(argv[i],"-all") == 0)) { 1.1136 + subtreeOptionSeen=FALSE; 1.1137 + } else if (strcmp( argv[i], "-l") == 0) { 1.1138 + doList = TRUE; 1.1139 + } 1.1140 + /* else option already handled by initArgs */ 1.1141 + } 1.1142 + 1.1143 + if( subtreeOptionSeen == FALSE) /* no other subtree given, run the default */ 1.1144 + { 1.1145 + ON_LINE=FALSE; /* just in case */ 1.1146 + if( doList == TRUE) 1.1147 + showTests(toRun); 1.1148 + else 1.1149 + runTests(toRun); 1.1150 + ON_LINE=FALSE; /* just in case */ 1.1151 + 1.1152 + errorCount += ERROR_COUNT; 1.1153 + } 1.1154 + else 1.1155 + { 1.1156 + if( ( doList == FALSE ) && ( errorCount > 0 ) ) 1.1157 + printf(" Total errors: %d\n", errorCount ); 1.1158 + } 1.1159 + 1.1160 + REPEAT_TESTS_INIT = 1; 1.1161 + 1.1162 + if(ctest_xml_fini()) { 1.1163 + errorCount++; 1.1164 + } 1.1165 + 1.1166 + return errorCount; /* total error count */ 1.1167 +} 1.1168 + 1.1169 +/** 1.1170 + * Display program invocation arguments 1.1171 + */ 1.1172 + 1.1173 +static void help ( const char *argv0 ) 1.1174 +{ 1.1175 + printf("Usage: %s [ -l ] [ -v ] [ -verbose] [-a] [ -all] [-n] [ -no_err_msg]\n" 1.1176 + " [ -h ] [-t_info | -t_error | -t_warn | -t_oc | -t_verbose] [-m n[-q] ]\n" 1.1177 + " [ /path/to/test ]\n", 1.1178 + argv0); 1.1179 + printf(" -l To get a list of test names\n"); 1.1180 + printf(" -e to do exhaustive testing\n"); 1.1181 + printf(" -verbose To turn ON verbosity\n"); 1.1182 + printf(" -v To turn ON verbosity(same as -verbose)\n"); 1.1183 + printf(" -x file.xml Write junit format output to file.xml\n"); 1.1184 + printf(" -h To print this message\n"); 1.1185 + printf(" -K to turn OFF suppressing known issues\n"); 1.1186 + printf(" -n To turn OFF printing error messages\n"); 1.1187 + printf(" -w Don't fail on data-loading errs, just warn. Useful if\n" 1.1188 + " user has reduced/changed the common set of ICU data \n"); 1.1189 + printf(" -t_info | -t_error | -t_warn | -t_oc | -t_verbose Enable ICU tracing\n"); 1.1190 + printf(" -no_err_msg (same as -n) \n"); 1.1191 + printf(" -m n[-q] Min-Max memory size that will cause an allocation failure.\n"); 1.1192 + printf(" The default is the maximum value of size_t. Max is optional.\n"); 1.1193 + printf(" -r Repeat tests after calling u_cleanup \n"); 1.1194 + printf(" [/subtest] To run a subtest \n"); 1.1195 + printf(" eg: to run just the utility tests type: cintltest /tsutil) \n"); 1.1196 +} 1.1197 + 1.1198 +int32_t T_CTEST_EXPORT2 1.1199 +getTestOption ( int32_t testOption ) { 1.1200 + switch (testOption) { 1.1201 + case VERBOSITY_OPTION: 1.1202 + return VERBOSITY; 1.1203 + case WARN_ON_MISSING_DATA_OPTION: 1.1204 + return WARN_ON_MISSING_DATA; 1.1205 + case QUICK_OPTION: 1.1206 + return QUICK; 1.1207 + case REPEAT_TESTS_OPTION: 1.1208 + return REPEAT_TESTS; 1.1209 + case ERR_MSG_OPTION: 1.1210 + return ERR_MSG; 1.1211 + case ICU_TRACE_OPTION: 1.1212 + return ICU_TRACE; 1.1213 + default : 1.1214 + return 0; 1.1215 + } 1.1216 +} 1.1217 + 1.1218 +void T_CTEST_EXPORT2 1.1219 +setTestOption ( int32_t testOption, int32_t value) { 1.1220 + if (value == DECREMENT_OPTION_VALUE) { 1.1221 + value = getTestOption(testOption); 1.1222 + --value; 1.1223 + } 1.1224 + switch (testOption) { 1.1225 + case VERBOSITY_OPTION: 1.1226 + VERBOSITY = value; 1.1227 + break; 1.1228 + case WARN_ON_MISSING_DATA_OPTION: 1.1229 + WARN_ON_MISSING_DATA = value; 1.1230 + break; 1.1231 + case QUICK_OPTION: 1.1232 + QUICK = value; 1.1233 + break; 1.1234 + case REPEAT_TESTS_OPTION: 1.1235 + REPEAT_TESTS = value; 1.1236 + break; 1.1237 + case ICU_TRACE_OPTION: 1.1238 + ICU_TRACE = (UTraceLevel)value; 1.1239 + break; 1.1240 + default : 1.1241 + break; 1.1242 + } 1.1243 +} 1.1244 + 1.1245 + 1.1246 +/* 1.1247 + * ================== JUnit support ================================ 1.1248 + */ 1.1249 + 1.1250 +int32_t 1.1251 +T_CTEST_EXPORT2 1.1252 +ctest_xml_setFileName(const char *name) { 1.1253 + XML_FILE_NAME=name; 1.1254 + return 0; 1.1255 +} 1.1256 + 1.1257 + 1.1258 +int32_t 1.1259 +T_CTEST_EXPORT2 1.1260 +ctest_xml_init(const char *rootName) { 1.1261 + if(!XML_FILE_NAME) return 0; 1.1262 + XML_FILE = fopen(XML_FILE_NAME,"w"); 1.1263 + if(!XML_FILE) { 1.1264 + perror("fopen"); 1.1265 + fprintf(stderr," Error: couldn't open XML output file %s\n", XML_FILE_NAME); 1.1266 + return 1; 1.1267 + } 1.1268 + while(*rootName&&!isalnum((int)*rootName)) { 1.1269 + rootName++; 1.1270 + } 1.1271 + strcpy(XML_PREFIX,rootName); 1.1272 + { 1.1273 + char *p = XML_PREFIX+strlen(XML_PREFIX); 1.1274 + for(p--;*p&&p>XML_PREFIX&&!isalnum((int)*p);p--) { 1.1275 + *p=0; 1.1276 + } 1.1277 + } 1.1278 + /* write prefix */ 1.1279 + fprintf(XML_FILE, "<testsuite name=\"%s\">\n", XML_PREFIX); 1.1280 + 1.1281 + return 0; 1.1282 +} 1.1283 + 1.1284 +int32_t 1.1285 +T_CTEST_EXPORT2 1.1286 +ctest_xml_fini(void) { 1.1287 + if(!XML_FILE) return 0; 1.1288 + 1.1289 + fprintf(XML_FILE, "</testsuite>\n"); 1.1290 + fclose(XML_FILE); 1.1291 + printf(" ( test results written to %s )\n", XML_FILE_NAME); 1.1292 + XML_FILE=0; 1.1293 + return 0; 1.1294 +} 1.1295 + 1.1296 + 1.1297 +int32_t 1.1298 +T_CTEST_EXPORT2 1.1299 +ctest_xml_testcase(const char *classname, const char *name, const char *timeSeconds, const char *failMsg) { 1.1300 + if(!XML_FILE) return 0; 1.1301 + 1.1302 + fprintf(XML_FILE, "\t<testcase classname=\"%s:%s\" name=\"%s:%s\" time=\"%s\"", XML_PREFIX, classname, XML_PREFIX, name, timeSeconds); 1.1303 + if(failMsg) { 1.1304 + fprintf(XML_FILE, ">\n\t\t<failure type=\"err\" message=\"%s\"/>\n\t</testcase>\n", failMsg); 1.1305 + } else { 1.1306 + fprintf(XML_FILE, "/>\n"); 1.1307 + } 1.1308 + 1.1309 + return 0; 1.1310 +} 1.1311 + 1.1312 +