intl/icu/source/tools/ctestfw/ctest.c

changeset 0
6474c204b198
     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 +

mercurial