]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
73c04bcf | 2 | ******************************************************************************** |
b75a7d8f | 3 | * |
73c04bcf | 4 | * Copyright (C) 1996-2006, International Business Machines |
b75a7d8f A |
5 | * Corporation and others. All Rights Reserved. |
6 | * | |
73c04bcf | 7 | ******************************************************************************** |
b75a7d8f A |
8 | */ |
9 | #include <stdio.h> | |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
12 | #include <assert.h> | |
13 | #include <stdarg.h> | |
14 | ||
374ca955 A |
15 | #include "unicode/utrace.h" |
16 | ||
b75a7d8f A |
17 | /* NOTES: |
18 | 3/20/1999 srl - strncpy called w/o setting nulls at the end | |
19 | */ | |
20 | ||
21 | #define MAXTESTNAME 128 | |
22 | #define MAXTESTS 512 | |
23 | #define MAX_TEST_LOG 4096 | |
24 | ||
25 | struct TestNode | |
26 | { | |
27 | char name[MAXTESTNAME]; | |
28 | void (*test)(void); | |
29 | struct TestNode* sibling; | |
30 | struct TestNode* child; | |
31 | }; | |
32 | ||
33 | ||
34 | static const struct TestNode* currentTest; | |
35 | ||
36 | typedef enum { RUNTESTS, SHOWTESTS } TestMode; | |
37 | #define TEST_SEPARATOR '/' | |
38 | ||
39 | #ifndef C_TEST_IMPL | |
40 | #define C_TEST_IMPL | |
41 | #endif | |
42 | ||
43 | #include "unicode/ctest.h" | |
44 | ||
45 | static char ERROR_LOG[MAX_TEST_LOG][MAXTESTNAME]; | |
46 | ||
47 | /* Local prototypes */ | |
48 | static TestNode* addTestNode( TestNode *root, const char *name ); | |
49 | ||
50 | static TestNode* createTestNode(); | |
51 | ||
52 | static int strncmp_nullcheck( const char* s1, | |
53 | const char* s2, | |
54 | int n ); | |
55 | ||
56 | static void getNextLevel( const char* name, | |
57 | int* nameLen, | |
58 | const char** nextName ); | |
59 | ||
60 | static void iterateTestsWithLevel( const TestNode *root, int len, | |
61 | const TestNode** list, | |
62 | TestMode mode); | |
63 | ||
64 | static void help ( const char *argv0 ); | |
65 | ||
66 | /** | |
67 | * Do the work of logging an error. Doesn't increase the error count. | |
68 | * | |
69 | * @prefix optional prefix prepended to message, or NULL. | |
70 | * @param pattern printf style pattern | |
71 | * @param ap vprintf style arg list | |
72 | */ | |
73 | static void vlog_err(const char *prefix, const char *pattern, va_list ap); | |
b75a7d8f A |
74 | static void vlog_verbose(const char *prefix, const char *pattern, va_list ap); |
75 | ||
76 | /* If we need to make the framework multi-thread safe | |
77 | we need to pass around the following vars | |
78 | */ | |
79 | static int ERRONEOUS_FUNCTION_COUNT = 0; | |
80 | static int ERROR_COUNT = 0; /* Count of errors from all tests. */ | |
81 | static int DATA_ERROR_COUNT = 0; /* count of data related errors or warnings */ | |
82 | static int INDENT_LEVEL = 0; | |
83 | int REPEAT_TESTS_INIT = 0; /* Was REPEAT_TESTS initialized? */ | |
84 | int REPEAT_TESTS = 1; /* Number of times to run the test */ | |
85 | int VERBOSITY = 0; /* be No-verbose by default */ | |
86 | int ERR_MSG =1; /* error messages will be displayed by default*/ | |
87 | int QUICK = 1; /* Skip some of the slower tests? */ | |
88 | int WARN_ON_MISSING_DATA = 0; /* Reduce data errs to warnings? */ | |
374ca955 | 89 | UTraceLevel ICU_TRACE = UTRACE_OFF; /* ICU tracing level */ |
b75a7d8f A |
90 | /*-------------------------------------------*/ |
91 | ||
92 | /* strncmp that also makes sure there's a \0 at s2[0] */ | |
93 | static int strncmp_nullcheck( const char* s1, | |
94 | const char* s2, | |
95 | int n ) | |
96 | { | |
97 | if (((int)strlen(s2) >= n) && s2[n] != 0) { | |
98 | return 3; /* null check fails */ | |
99 | } | |
100 | else { | |
101 | return strncmp ( s1, s2, n ); | |
102 | } | |
103 | } | |
104 | ||
105 | static void getNextLevel( const char* name, | |
106 | int* nameLen, | |
107 | const char** nextName ) | |
108 | { | |
109 | /* Get the next component of the name */ | |
110 | *nextName = strchr(name, TEST_SEPARATOR); | |
111 | ||
112 | if( *nextName != 0 ) | |
113 | { | |
114 | char n[255]; | |
115 | *nameLen = (int)((*nextName) - name); | |
116 | (*nextName)++; /* skip '/' */ | |
117 | strncpy(n, name, *nameLen); | |
118 | n[*nameLen] = 0; | |
119 | /*printf("->%s-< [%d] -> [%s]\n", name, *nameLen, *nextName);*/ | |
120 | } | |
121 | else { | |
122 | *nameLen = (int)strlen(name); | |
123 | } | |
124 | } | |
125 | ||
126 | static TestNode *createTestNode( ) | |
127 | { | |
128 | TestNode *newNode; | |
129 | ||
130 | newNode = (TestNode*)malloc ( sizeof ( TestNode ) ); | |
131 | ||
132 | newNode->name[0] = '\0'; | |
133 | newNode->test = NULL; | |
134 | newNode->sibling = NULL; | |
135 | newNode->child = NULL; | |
136 | ||
137 | return newNode; | |
138 | } | |
139 | ||
374ca955 A |
140 | void T_CTEST_EXPORT2 |
141 | cleanUpTestTree(TestNode *tn) | |
142 | { | |
b75a7d8f A |
143 | if(tn->child != NULL) { |
144 | cleanUpTestTree(tn->child); | |
145 | } | |
146 | if(tn->sibling != NULL) { | |
147 | cleanUpTestTree(tn->sibling); | |
148 | } | |
149 | ||
150 | free(tn); | |
151 | } | |
152 | ||
153 | ||
374ca955 A |
154 | void T_CTEST_EXPORT2 |
155 | addTest(TestNode** root, | |
156 | TestFunctionPtr test, | |
157 | const char* name ) | |
b75a7d8f A |
158 | { |
159 | TestNode *newNode; | |
160 | ||
161 | /*if this is the first Test created*/ | |
162 | if (*root == NULL) | |
163 | *root = createTestNode(); | |
164 | ||
165 | newNode = addTestNode( *root, name ); | |
166 | assert(newNode != 0 ); | |
167 | /* printf("addTest: nreName = %s\n", newNode->name );*/ | |
168 | ||
169 | newNode->test = test; | |
170 | } | |
171 | ||
172 | /* non recursive insert function */ | |
173 | static TestNode *addTestNode ( TestNode *root, const char *name ) | |
174 | { | |
175 | const char* nextName; | |
176 | TestNode *nextNode, *curNode; | |
177 | int nameLen; /* length of current 'name' */ | |
178 | ||
179 | /* remove leading slash */ | |
180 | if ( *name == TEST_SEPARATOR ) | |
181 | name++; | |
182 | ||
183 | curNode = root; | |
184 | ||
185 | for(;;) | |
186 | { | |
187 | /* Start with the next child */ | |
188 | nextNode = curNode->child; | |
189 | ||
190 | getNextLevel ( name, &nameLen, &nextName ); | |
191 | ||
192 | /* printf("* %s\n", name );*/ | |
193 | ||
194 | /* if nextNode is already null, then curNode has no children | |
195 | -- add them */ | |
196 | if( nextNode == NULL ) | |
197 | { | |
198 | /* Add all children of the node */ | |
199 | do | |
200 | { | |
201 | curNode->child = createTestNode ( ); | |
202 | ||
203 | /* Get the next component of the name */ | |
204 | getNextLevel ( name, &nameLen, &nextName ); | |
205 | ||
206 | /* update curName to have the next name segment */ | |
207 | strncpy ( curNode->child->name , name, nameLen ); | |
208 | curNode->child->name[nameLen] = 0; | |
209 | /* printf("*** added %s\n", curNode->child->name );*/ | |
210 | curNode = curNode->child; | |
211 | name = nextName; | |
212 | } | |
213 | while( name != NULL ); | |
214 | ||
215 | return curNode; | |
216 | } | |
217 | ||
218 | /* Search across for the name */ | |
219 | while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 ) | |
220 | { | |
221 | curNode = nextNode; | |
222 | nextNode = nextNode -> sibling; | |
223 | ||
224 | if ( nextNode == NULL ) | |
225 | { | |
226 | /* Did not find 'name' on this level. */ | |
227 | nextNode = createTestNode ( ); | |
228 | strncpy( nextNode->name, name, nameLen ); | |
229 | nextNode->name[nameLen] = 0; | |
230 | curNode->sibling = nextNode; | |
231 | break; | |
232 | } | |
233 | } | |
234 | ||
235 | /* nextNode matches 'name' */ | |
236 | ||
237 | if (nextName == NULL) /* end of the line */ | |
238 | { | |
239 | return nextNode; | |
240 | } | |
241 | ||
242 | /* Loop again with the next item */ | |
243 | name = nextName; | |
244 | curNode = nextNode; | |
245 | } | |
246 | } | |
247 | ||
248 | static void iterateTestsWithLevel ( const TestNode* root, | |
249 | int len, | |
250 | const TestNode** list, | |
251 | TestMode mode) | |
252 | { | |
253 | int i; | |
254 | int saveIndent; | |
255 | ||
256 | char pathToFunction[MAXTESTNAME] = ""; | |
257 | char separatorString[2] = { TEST_SEPARATOR, '\0'}; | |
258 | ||
259 | if ( root == NULL ) | |
260 | return; | |
261 | ||
262 | list[len++] = root; | |
263 | ||
264 | for ( i=0;i<(len-1);i++ ) | |
265 | { | |
266 | strcat(pathToFunction, list[i]->name); | |
267 | strcat(pathToFunction, separatorString); | |
268 | } | |
269 | ||
270 | strcat(pathToFunction, list[i]->name); | |
271 | ||
272 | INDENT_LEVEL = len; | |
273 | if ( (mode == RUNTESTS) && (root->test != NULL)) | |
274 | { | |
275 | int myERROR_COUNT = ERROR_COUNT; | |
276 | currentTest = root; | |
277 | root->test(); | |
278 | currentTest = NULL; | |
279 | if (myERROR_COUNT != ERROR_COUNT) | |
280 | { | |
281 | ||
282 | log_info("---[%d ERRORS] ", ERROR_COUNT - myERROR_COUNT); | |
283 | strcpy(ERROR_LOG[ERRONEOUS_FUNCTION_COUNT++], pathToFunction); | |
284 | } | |
285 | else | |
286 | log_info("---[OK] "); | |
287 | } | |
288 | ||
289 | ||
290 | /* we want these messages to be at 0 indent. so just push the indent level breifly. */ | |
291 | saveIndent = INDENT_LEVEL; | |
292 | INDENT_LEVEL = 0; | |
293 | log_info("%s%s%c\n", (list[i]->test||mode==SHOWTESTS)?"---":"",pathToFunction, list[i]->test?' ':TEST_SEPARATOR ); | |
294 | INDENT_LEVEL = saveIndent; | |
295 | ||
296 | iterateTestsWithLevel ( root->child, len, list, mode ); | |
297 | ||
298 | len--; | |
299 | ||
300 | if ( len != 0 ) /* DO NOT iterate over siblings of the root. */ | |
301 | iterateTestsWithLevel ( root->sibling, len, list, mode ); | |
302 | } | |
303 | ||
304 | ||
305 | ||
374ca955 A |
306 | void T_CTEST_EXPORT2 |
307 | showTests ( const TestNode *root ) | |
b75a7d8f A |
308 | { |
309 | /* make up one for them */ | |
310 | const TestNode *aList[MAXTESTS]; | |
311 | ||
312 | if (root == NULL) | |
313 | log_err("TEST CAN'T BE FOUND!"); | |
314 | ||
315 | iterateTestsWithLevel ( root, 0, aList, SHOWTESTS ); | |
316 | ||
317 | } | |
318 | ||
374ca955 A |
319 | void T_CTEST_EXPORT2 |
320 | runTests ( const TestNode *root ) | |
b75a7d8f A |
321 | { |
322 | int i; | |
323 | const TestNode *aList[MAXTESTS]; | |
324 | /* make up one for them */ | |
325 | ||
326 | ||
327 | if (root == NULL) | |
328 | log_err("TEST CAN'T BE FOUND!\n"); | |
329 | ||
330 | ERRONEOUS_FUNCTION_COUNT = ERROR_COUNT = 0; | |
331 | iterateTestsWithLevel ( root, 0, aList, RUNTESTS ); | |
332 | ||
333 | /*print out result summary*/ | |
334 | ||
335 | if (ERROR_COUNT) | |
336 | { | |
337 | log_info("\nSUMMARY:\n******* [Total error count:\t%d]\n Errors in\n", ERROR_COUNT); | |
338 | for (i=0;i < ERRONEOUS_FUNCTION_COUNT; i++) | |
339 | log_info("[%s]\n",ERROR_LOG[i]); | |
340 | } | |
341 | else | |
342 | { | |
343 | log_info("\n[All tests passed successfully...]\n"); | |
344 | } | |
345 | ||
346 | if(DATA_ERROR_COUNT) { | |
347 | if(WARN_ON_MISSING_DATA==0) { | |
348 | log_info("\t*Note* some errors are data-loading related. If the data used is not the \n" | |
349 | "\tstock ICU data (i.e some have been added or removed), consider using\n" | |
350 | "\tthe '-w' option to turn these errors into warnings.\n"); | |
351 | } else { | |
352 | log_info("\t*WARNING* some data-loading errors were ignored by the -w option.\n"); | |
353 | } | |
354 | } | |
355 | } | |
356 | ||
374ca955 A |
357 | const char* T_CTEST_EXPORT2 |
358 | getTestName(void) | |
b75a7d8f A |
359 | { |
360 | if(currentTest != NULL) { | |
361 | return currentTest->name; | |
362 | } else { | |
363 | return NULL; | |
364 | } | |
365 | } | |
366 | ||
374ca955 A |
367 | const TestNode* T_CTEST_EXPORT2 |
368 | getTest(const TestNode* root, const char* name) | |
b75a7d8f A |
369 | { |
370 | const char* nextName; | |
371 | TestNode *nextNode; | |
372 | const TestNode* curNode; | |
373 | int nameLen; /* length of current 'name' */ | |
374 | ||
73c04bcf | 375 | if (root == NULL) { |
b75a7d8f | 376 | log_err("TEST CAN'T BE FOUND!\n"); |
73c04bcf A |
377 | return NULL; |
378 | } | |
b75a7d8f A |
379 | /* remove leading slash */ |
380 | if ( *name == TEST_SEPARATOR ) | |
381 | name++; | |
382 | ||
383 | curNode = root; | |
384 | ||
385 | for(;;) | |
386 | { | |
387 | /* Start with the next child */ | |
388 | nextNode = curNode->child; | |
389 | ||
390 | getNextLevel ( name, &nameLen, &nextName ); | |
391 | ||
392 | /* printf("* %s\n", name );*/ | |
393 | ||
394 | /* if nextNode is already null, then curNode has no children | |
395 | -- add them */ | |
396 | if( nextNode == NULL ) | |
397 | { | |
398 | return NULL; | |
399 | } | |
400 | ||
401 | /* Search across for the name */ | |
402 | while (strncmp_nullcheck ( name, nextNode->name, nameLen) != 0 ) | |
403 | { | |
404 | curNode = nextNode; | |
405 | nextNode = nextNode -> sibling; | |
406 | ||
407 | if ( nextNode == NULL ) | |
408 | { | |
409 | /* Did not find 'name' on this level. */ | |
410 | return NULL; | |
411 | } | |
412 | } | |
413 | ||
414 | /* nextNode matches 'name' */ | |
415 | ||
416 | if (nextName == NULL) /* end of the line */ | |
417 | { | |
418 | return nextNode; | |
419 | } | |
420 | ||
421 | /* Loop again with the next item */ | |
422 | name = nextName; | |
423 | curNode = nextNode; | |
424 | } | |
425 | } | |
426 | ||
427 | static void vlog_err(const char *prefix, const char *pattern, va_list ap) | |
428 | { | |
429 | if( ERR_MSG == FALSE){ | |
430 | return; | |
431 | } | |
432 | fprintf(stderr, "%-*s", INDENT_LEVEL," " ); | |
433 | if(prefix) { | |
73c04bcf | 434 | fputs(prefix, stderr); |
b75a7d8f A |
435 | } |
436 | vfprintf(stderr, pattern, ap); | |
437 | fflush(stderr); | |
438 | va_end(ap); | |
439 | } | |
440 | ||
374ca955 A |
441 | void T_CTEST_EXPORT2 |
442 | vlog_info(const char *prefix, const char *pattern, va_list ap) | |
b75a7d8f A |
443 | { |
444 | fprintf(stdout, "%-*s", INDENT_LEVEL," " ); | |
445 | if(prefix) { | |
73c04bcf | 446 | fputs(prefix, stdout); |
b75a7d8f A |
447 | } |
448 | vfprintf(stdout, pattern, ap); | |
449 | fflush(stdout); | |
450 | va_end(ap); | |
451 | } | |
452 | ||
453 | static void vlog_verbose(const char *prefix, const char *pattern, va_list ap) | |
454 | { | |
455 | if ( VERBOSITY == FALSE ) | |
456 | return; | |
457 | ||
458 | fprintf(stdout, "%-*s", INDENT_LEVEL," " ); | |
459 | if(prefix) { | |
73c04bcf | 460 | fputs(prefix, stdout); |
b75a7d8f A |
461 | } |
462 | vfprintf(stdout, pattern, ap); | |
463 | fflush(stdout); | |
464 | va_end(ap); | |
465 | } | |
466 | ||
374ca955 A |
467 | void T_CTEST_EXPORT2 |
468 | log_err(const char* pattern, ...) | |
b75a7d8f A |
469 | { |
470 | va_list ap; | |
471 | if(strchr(pattern, '\n') != NULL) { | |
472 | /* | |
473 | * Count errors only if there is a line feed in the pattern | |
474 | * so that we do not exaggerate our error count. | |
475 | */ | |
476 | ++ERROR_COUNT; | |
477 | } | |
478 | va_start(ap, pattern); | |
479 | vlog_err(NULL, pattern, ap); | |
480 | } | |
481 | ||
374ca955 A |
482 | void T_CTEST_EXPORT2 |
483 | log_info(const char* pattern, ...) | |
b75a7d8f A |
484 | { |
485 | va_list ap; | |
486 | ||
487 | va_start(ap, pattern); | |
488 | vlog_info(NULL, pattern, ap); | |
489 | } | |
490 | ||
374ca955 A |
491 | void T_CTEST_EXPORT2 |
492 | log_verbose(const char* pattern, ...) | |
b75a7d8f A |
493 | { |
494 | va_list ap; | |
495 | ||
496 | va_start(ap, pattern); | |
497 | vlog_verbose(NULL, pattern, ap); | |
498 | } | |
499 | ||
500 | ||
374ca955 A |
501 | void T_CTEST_EXPORT2 |
502 | log_data_err(const char* pattern, ...) | |
b75a7d8f A |
503 | { |
504 | va_list ap; | |
505 | va_start(ap, pattern); | |
506 | ||
507 | ++DATA_ERROR_COUNT; /* for informational message at the end */ | |
508 | ||
509 | if(WARN_ON_MISSING_DATA == 0) { | |
510 | /* Fatal error. */ | |
511 | if(strchr(pattern, '\n') != NULL) { | |
512 | ++ERROR_COUNT; | |
513 | } | |
514 | vlog_err(NULL, pattern, ap); /* no need for prefix in default case */ | |
515 | } else { | |
516 | vlog_info("[Data] ", pattern, ap); | |
517 | } | |
518 | } | |
519 | ||
520 | ||
374ca955 A |
521 | int T_CTEST_EXPORT2 |
522 | processArgs(const TestNode* root, | |
b75a7d8f A |
523 | int argc, |
524 | const char* const argv[]) | |
525 | { | |
526 | /** | |
527 | * This main will parse the l, v, h, n, and path arguments | |
528 | */ | |
529 | const TestNode* toRun; | |
530 | int i; | |
531 | int doList = FALSE; | |
532 | int subtreeOptionSeen = FALSE; | |
533 | ||
534 | int errorCount = 0; | |
535 | ||
536 | toRun = root; | |
537 | VERBOSITY = FALSE; | |
538 | ERR_MSG = TRUE; | |
539 | ||
540 | for( i=1; i<argc; i++) | |
541 | { | |
542 | if ( argv[i][0] == '/' ) | |
543 | { | |
544 | printf("Selecting subtree '%s'\n", argv[i]); | |
545 | ||
546 | if ( argv[i][1] == 0 ) | |
547 | toRun = root; | |
548 | else | |
549 | toRun = getTest(root, argv[i]); | |
550 | ||
551 | if ( toRun == NULL ) | |
552 | { | |
553 | printf("* Could not find any matching subtree\n"); | |
554 | return -1; | |
555 | } | |
556 | ||
557 | if( doList == TRUE) | |
558 | showTests(toRun); | |
559 | else | |
560 | runTests(toRun); | |
561 | ||
562 | errorCount += ERROR_COUNT; | |
563 | ||
564 | subtreeOptionSeen = TRUE; | |
565 | } | |
566 | else if (strcmp( argv[i], "-v" )==0 || strcmp( argv[i], "-verbose")==0) | |
567 | { | |
568 | VERBOSITY = TRUE; | |
569 | } | |
570 | else if (strcmp( argv[i], "-l" )==0 ) | |
571 | { | |
572 | doList = TRUE; | |
573 | } | |
574 | else if (strcmp( argv[i], "-e1") == 0) | |
575 | { | |
576 | QUICK = -1; | |
577 | } | |
578 | else if (strcmp( argv[i], "-e") ==0) | |
579 | { | |
580 | QUICK = 0; | |
581 | } | |
582 | else if (strcmp( argv[i], "-w") ==0) | |
583 | { | |
584 | WARN_ON_MISSING_DATA = TRUE; | |
585 | } | |
586 | else if(strcmp( argv[i], "-n") == 0 || strcmp( argv[i], "-no_err_msg") == 0) | |
587 | { | |
588 | ERR_MSG = FALSE; | |
589 | } | |
590 | else if (strcmp( argv[i], "-r") == 0) | |
591 | { | |
592 | if (!REPEAT_TESTS_INIT) { | |
593 | REPEAT_TESTS++; | |
594 | } | |
595 | } | |
596 | else if ((strcmp( argv[i], "-a") == 0) || (strcmp(argv[i],"-all") == 0)) | |
597 | { | |
598 | subtreeOptionSeen=FALSE; | |
599 | } | |
374ca955 A |
600 | else if (strcmp( argv[i], "-t_info") == 0) { |
601 | ICU_TRACE = UTRACE_INFO; | |
602 | } | |
603 | else if (strcmp( argv[i], "-t_error") == 0) { | |
604 | ICU_TRACE = UTRACE_ERROR; | |
605 | } | |
606 | else if (strcmp( argv[i], "-t_warn") == 0) { | |
607 | ICU_TRACE = UTRACE_WARNING; | |
608 | } | |
609 | else if (strcmp( argv[i], "-t_verbose") == 0) { | |
610 | ICU_TRACE = UTRACE_VERBOSE; | |
611 | } | |
612 | else if (strcmp( argv[i], "-t_oc") == 0) { | |
613 | ICU_TRACE = UTRACE_OPEN_CLOSE; | |
614 | } | |
615 | else if (strcmp( argv[i], "-h" )==0 || strcmp( argv[i], "--help" )==0) | |
b75a7d8f A |
616 | { |
617 | help( argv[0] ); | |
618 | return 0; | |
619 | } | |
620 | else | |
621 | { | |
622 | printf("* unknown option: %s\n", argv[i]); | |
623 | help( argv[0] ); | |
624 | return -1; | |
625 | } | |
626 | } | |
627 | ||
628 | if( subtreeOptionSeen == FALSE) /* no other subtree given, run the default */ | |
629 | { | |
630 | if( doList == TRUE) | |
631 | showTests(toRun); | |
632 | else | |
633 | runTests(toRun); | |
634 | ||
635 | errorCount += ERROR_COUNT; | |
636 | } | |
637 | else | |
638 | { | |
639 | if( ( doList == FALSE ) && ( errorCount > 0 ) ) | |
640 | printf(" Total errors: %d\n", errorCount ); | |
641 | } | |
642 | ||
643 | REPEAT_TESTS_INIT = 1; | |
644 | ||
645 | return errorCount; /* total error count */ | |
646 | } | |
647 | ||
648 | /** | |
649 | * Display program invocation arguments | |
650 | */ | |
651 | ||
652 | static void help ( const char *argv0 ) | |
653 | { | |
374ca955 A |
654 | printf("Usage: %s [ -l ] [ -v ] [ -verbose] [-a] [ -all] [-n] [ -no_err_msg]\n" |
655 | " [ -h ] [-t_info | -t_error | -t_warn | -t_oc | -t_verbose]" | |
656 | " [ /path/to/test ]\n", | |
b75a7d8f | 657 | argv0); |
374ca955 A |
658 | printf(" -l To get a list of test names\n"); |
659 | printf(" -e to do exhaustive testing\n"); | |
b75a7d8f | 660 | printf(" -verbose To turn ON verbosity\n"); |
374ca955 A |
661 | printf(" -v To turn ON verbosity(same as -verbose)\n"); |
662 | printf(" -h To print this message\n"); | |
663 | printf(" -n To turn OFF printing error messages\n"); | |
664 | printf(" -w Don't fail on data-loading errs, just warn. Useful if\n" | |
b75a7d8f | 665 | " user has reduced/changed the common set of ICU data \n"); |
374ca955 | 666 | printf(" -t_info | -t_error | -t_warn | -t_oc | -t_verbose Enable ICU tracing\n"); |
b75a7d8f | 667 | printf(" -no_err_msg (same as -n) \n"); |
374ca955 A |
668 | printf(" -r repeat tests after calling u_cleanup \n"); |
669 | printf(" -[/subtest] To run a subtest \n"); | |
b75a7d8f A |
670 | printf(" eg: to run just the utility tests type: cintltest /tsutil) \n"); |
671 | } | |
672 |