intl/icu/source/tools/ctestfw/uperf.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /********************************************************************
michael@0 2 * COPYRIGHT:
michael@0 3 * Copyright (c) 2002-2012, International Business Machines Corporation and
michael@0 4 * others. All Rights Reserved.
michael@0 5 ********************************************************************/
michael@0 6
michael@0 7 // Defines _XOPEN_SOURCE for access to POSIX functions.
michael@0 8 // Must be before any other #includes.
michael@0 9 #include "uposixdefs.h"
michael@0 10
michael@0 11 #include "unicode/uperf.h"
michael@0 12 #include "uoptions.h"
michael@0 13 #include "cmemory.h"
michael@0 14 #include <stdio.h>
michael@0 15 #include <stdlib.h>
michael@0 16
michael@0 17 #if !UCONFIG_NO_CONVERSION
michael@0 18
michael@0 19 UPerfFunction::~UPerfFunction() {}
michael@0 20
michael@0 21 static const char delim = '/';
michael@0 22 static int32_t execCount = 0;
michael@0 23 UPerfTest* UPerfTest::gTest = NULL;
michael@0 24 static const int MAXLINES = 40000;
michael@0 25 const char UPerfTest::gUsageString[] =
michael@0 26 "Usage: %s [OPTIONS] [FILES]\n"
michael@0 27 "\tReads the input file and prints out time taken in seconds\n"
michael@0 28 "Options:\n"
michael@0 29 "\t-h or -? or --help this usage text\n"
michael@0 30 "\t-v or --verbose print extra information when processing files\n"
michael@0 31 "\t-s or --sourcedir source directory for files followed by path\n"
michael@0 32 "\t followed by path\n"
michael@0 33 "\t-e or --encoding encoding of source files\n"
michael@0 34 "\t-u or --uselen perform timing analysis on non-null terminated buffer using length\n"
michael@0 35 "\t-f or --file-name file to be used as input data\n"
michael@0 36 "\t-p or --passes Number of passes to be performed. Requires Numeric argument.\n"
michael@0 37 "\t Cannot be used with --time\n"
michael@0 38 "\t-i or --iterations Number of iterations to be performed. Requires Numeric argument\n"
michael@0 39 "\t-t or --time Threshold time for looping until in seconds. Requires Numeric argument.\n"
michael@0 40 "\t Cannot be used with --iterations\n"
michael@0 41 "\t-l or --line-mode The data file should be processed in line mode\n"
michael@0 42 "\t-b or --bulk-mode The data file should be processed in file based.\n"
michael@0 43 "\t Cannot be used with --line-mode\n"
michael@0 44 "\t-L or --locale Locale for the test\n";
michael@0 45
michael@0 46 enum
michael@0 47 {
michael@0 48 HELP1,
michael@0 49 HELP2,
michael@0 50 VERBOSE,
michael@0 51 SOURCEDIR,
michael@0 52 ENCODING,
michael@0 53 USELEN,
michael@0 54 FILE_NAME,
michael@0 55 PASSES,
michael@0 56 ITERATIONS,
michael@0 57 TIME,
michael@0 58 LINE_MODE,
michael@0 59 BULK_MODE,
michael@0 60 LOCALE,
michael@0 61 OPTIONS_COUNT
michael@0 62 };
michael@0 63
michael@0 64
michael@0 65 static UOption options[OPTIONS_COUNT+20]={
michael@0 66 UOPTION_HELP_H,
michael@0 67 UOPTION_HELP_QUESTION_MARK,
michael@0 68 UOPTION_VERBOSE,
michael@0 69 UOPTION_SOURCEDIR,
michael@0 70 UOPTION_ENCODING,
michael@0 71 UOPTION_DEF( "uselen", 'u', UOPT_NO_ARG),
michael@0 72 UOPTION_DEF( "file-name", 'f', UOPT_REQUIRES_ARG),
michael@0 73 UOPTION_DEF( "passes", 'p', UOPT_REQUIRES_ARG),
michael@0 74 UOPTION_DEF( "iterations", 'i', UOPT_REQUIRES_ARG),
michael@0 75 UOPTION_DEF( "time", 't', UOPT_REQUIRES_ARG),
michael@0 76 UOPTION_DEF( "line-mode", 'l', UOPT_NO_ARG),
michael@0 77 UOPTION_DEF( "bulk-mode", 'b', UOPT_NO_ARG),
michael@0 78 UOPTION_DEF( "locale", 'L', UOPT_REQUIRES_ARG)
michael@0 79 };
michael@0 80
michael@0 81 UPerfTest::UPerfTest(int32_t argc, const char* argv[], UErrorCode& status)
michael@0 82 : _argc(argc), _argv(argv), _addUsage(NULL),
michael@0 83 ucharBuf(NULL), encoding(""),
michael@0 84 uselen(FALSE),
michael@0 85 fileName(NULL), sourceDir("."),
michael@0 86 lines(NULL), numLines(0), line_mode(TRUE),
michael@0 87 buffer(NULL), bufferLen(0),
michael@0 88 verbose(FALSE), bulk_mode(FALSE),
michael@0 89 passes(1), iterations(0), time(0),
michael@0 90 locale(NULL) {
michael@0 91 init(NULL, 0, status);
michael@0 92 }
michael@0 93
michael@0 94 UPerfTest::UPerfTest(int32_t argc, const char* argv[],
michael@0 95 UOption addOptions[], int32_t addOptionsCount,
michael@0 96 const char *addUsage,
michael@0 97 UErrorCode& status)
michael@0 98 : _argc(argc), _argv(argv), _addUsage(addUsage),
michael@0 99 ucharBuf(NULL), encoding(""),
michael@0 100 uselen(FALSE),
michael@0 101 fileName(NULL), sourceDir("."),
michael@0 102 lines(NULL), numLines(0), line_mode(TRUE),
michael@0 103 buffer(NULL), bufferLen(0),
michael@0 104 verbose(FALSE), bulk_mode(FALSE),
michael@0 105 passes(1), iterations(0), time(0),
michael@0 106 locale(NULL) {
michael@0 107 init(addOptions, addOptionsCount, status);
michael@0 108 }
michael@0 109
michael@0 110 void UPerfTest::init(UOption addOptions[], int32_t addOptionsCount,
michael@0 111 UErrorCode& status) {
michael@0 112 //initialize the argument list
michael@0 113 U_MAIN_INIT_ARGS(_argc, _argv);
michael@0 114
michael@0 115 resolvedFileName = NULL;
michael@0 116
michael@0 117 // add specific options
michael@0 118 int32_t optionsCount = OPTIONS_COUNT;
michael@0 119 if (addOptionsCount > 0) {
michael@0 120 memcpy(options+optionsCount, addOptions, addOptionsCount*sizeof(UOption));
michael@0 121 optionsCount += addOptionsCount;
michael@0 122 }
michael@0 123
michael@0 124 //parse the arguments
michael@0 125 _remainingArgc = u_parseArgs(_argc, (char**)_argv, optionsCount, options);
michael@0 126
michael@0 127 // copy back values for additional options
michael@0 128 if (addOptionsCount > 0) {
michael@0 129 memcpy(addOptions, options+OPTIONS_COUNT, addOptionsCount*sizeof(UOption));
michael@0 130 }
michael@0 131
michael@0 132 // Now setup the arguments
michael@0 133 if(_argc==1 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
michael@0 134 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 135 return;
michael@0 136 }
michael@0 137
michael@0 138 if(options[VERBOSE].doesOccur) {
michael@0 139 verbose = TRUE;
michael@0 140 }
michael@0 141
michael@0 142 if(options[SOURCEDIR].doesOccur) {
michael@0 143 sourceDir = options[SOURCEDIR].value;
michael@0 144 }
michael@0 145
michael@0 146 if(options[ENCODING].doesOccur) {
michael@0 147 encoding = options[ENCODING].value;
michael@0 148 }
michael@0 149
michael@0 150 if(options[USELEN].doesOccur) {
michael@0 151 uselen = TRUE;
michael@0 152 }
michael@0 153
michael@0 154 if(options[FILE_NAME].doesOccur){
michael@0 155 fileName = options[FILE_NAME].value;
michael@0 156 }
michael@0 157
michael@0 158 if(options[PASSES].doesOccur) {
michael@0 159 passes = atoi(options[PASSES].value);
michael@0 160 }
michael@0 161 if(options[ITERATIONS].doesOccur) {
michael@0 162 iterations = atoi(options[ITERATIONS].value);
michael@0 163 if(options[TIME].doesOccur) {
michael@0 164 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 165 return;
michael@0 166 }
michael@0 167 } else if(options[TIME].doesOccur) {
michael@0 168 time = atoi(options[TIME].value);
michael@0 169 } else {
michael@0 170 iterations = 1000; // some default
michael@0 171 }
michael@0 172
michael@0 173 if(options[LINE_MODE].doesOccur) {
michael@0 174 line_mode = TRUE;
michael@0 175 bulk_mode = FALSE;
michael@0 176 }
michael@0 177
michael@0 178 if(options[BULK_MODE].doesOccur) {
michael@0 179 bulk_mode = TRUE;
michael@0 180 line_mode = FALSE;
michael@0 181 }
michael@0 182
michael@0 183 if(options[LOCALE].doesOccur) {
michael@0 184 locale = options[LOCALE].value;
michael@0 185 }
michael@0 186
michael@0 187 int32_t len = 0;
michael@0 188 if(fileName!=NULL){
michael@0 189 //pre-flight
michael@0 190 ucbuf_resolveFileName(sourceDir, fileName, NULL, &len, &status);
michael@0 191 resolvedFileName = (char*) uprv_malloc(len);
michael@0 192 if(resolvedFileName==NULL){
michael@0 193 status= U_MEMORY_ALLOCATION_ERROR;
michael@0 194 return;
michael@0 195 }
michael@0 196 if(status == U_BUFFER_OVERFLOW_ERROR){
michael@0 197 status = U_ZERO_ERROR;
michael@0 198 }
michael@0 199 ucbuf_resolveFileName(sourceDir, fileName, resolvedFileName, &len, &status);
michael@0 200 ucharBuf = ucbuf_open(resolvedFileName,&encoding,TRUE,FALSE,&status);
michael@0 201
michael@0 202 if(U_FAILURE(status)){
michael@0 203 printf("Could not open the input file %s. Error: %s\n", fileName, u_errorName(status));
michael@0 204 return;
michael@0 205 }
michael@0 206 }
michael@0 207 }
michael@0 208
michael@0 209 ULine* UPerfTest::getLines(UErrorCode& status){
michael@0 210 if (U_FAILURE(status)) {
michael@0 211 return NULL;
michael@0 212 }
michael@0 213 if (lines != NULL) {
michael@0 214 return lines; // don't do it again
michael@0 215 }
michael@0 216 lines = new ULine[MAXLINES];
michael@0 217 int maxLines = MAXLINES;
michael@0 218 numLines=0;
michael@0 219 const UChar* line=NULL;
michael@0 220 int32_t len =0;
michael@0 221 for (;;) {
michael@0 222 line = ucbuf_readline(ucharBuf,&len,&status);
michael@0 223 if(line == NULL || U_FAILURE(status)){
michael@0 224 break;
michael@0 225 }
michael@0 226 lines[numLines].name = new UChar[len];
michael@0 227 lines[numLines].len = len;
michael@0 228 memcpy(lines[numLines].name, line, len * U_SIZEOF_UCHAR);
michael@0 229
michael@0 230 numLines++;
michael@0 231 len = 0;
michael@0 232 if (numLines >= maxLines) {
michael@0 233 maxLines += MAXLINES;
michael@0 234 ULine *newLines = new ULine[maxLines];
michael@0 235 if(newLines == NULL) {
michael@0 236 fprintf(stderr, "Out of memory reading line %d.\n", (int)numLines);
michael@0 237 status= U_MEMORY_ALLOCATION_ERROR;
michael@0 238 delete []lines;
michael@0 239 return NULL;
michael@0 240 }
michael@0 241
michael@0 242 memcpy(newLines, lines, numLines*sizeof(ULine));
michael@0 243 delete []lines;
michael@0 244 lines = newLines;
michael@0 245 }
michael@0 246 }
michael@0 247 return lines;
michael@0 248 }
michael@0 249 const UChar* UPerfTest::getBuffer(int32_t& len, UErrorCode& status){
michael@0 250 if (U_FAILURE(status)) {
michael@0 251 return NULL;
michael@0 252 }
michael@0 253 len = ucbuf_size(ucharBuf);
michael@0 254 buffer = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * (len+1));
michael@0 255 u_strncpy(buffer,ucbuf_getBuffer(ucharBuf,&bufferLen,&status),len);
michael@0 256 buffer[len]=0;
michael@0 257 len = bufferLen;
michael@0 258 return buffer;
michael@0 259 }
michael@0 260 UBool UPerfTest::run(){
michael@0 261 if(_remainingArgc==1){
michael@0 262 // Testing all methods
michael@0 263 return runTest();
michael@0 264 }
michael@0 265 UBool res=FALSE;
michael@0 266 // Test only the specified fucntion
michael@0 267 for (int i = 1; i < _remainingArgc; ++i) {
michael@0 268 if (_argv[i][0] != '-') {
michael@0 269 char* name = (char*) _argv[i];
michael@0 270 if(verbose==TRUE){
michael@0 271 //fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
michael@0 272 //fprintf(stdout, "\n%s:\n", name);
michael@0 273 }
michael@0 274 char* parameter = strchr( name, '@' );
michael@0 275 if (parameter) {
michael@0 276 *parameter = 0;
michael@0 277 parameter += 1;
michael@0 278 }
michael@0 279 execCount = 0;
michael@0 280 res = runTest( name, parameter );
michael@0 281 if (!res || (execCount <= 0)) {
michael@0 282 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
michael@0 283 return FALSE;
michael@0 284 }
michael@0 285 }
michael@0 286 }
michael@0 287 return res;
michael@0 288 }
michael@0 289 UBool UPerfTest::runTest(char* name, char* par ){
michael@0 290 UBool rval;
michael@0 291 char* pos = NULL;
michael@0 292
michael@0 293 if (name)
michael@0 294 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
michael@0 295 if (pos) {
michael@0 296 path = pos+1; // store subpath for calling subtest
michael@0 297 *pos = 0; // split into two strings
michael@0 298 }else{
michael@0 299 path = NULL;
michael@0 300 }
michael@0 301
michael@0 302 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
michael@0 303 rval = runTestLoop( NULL, NULL );
michael@0 304
michael@0 305 }else if (strcmp( name, "LIST" ) == 0) {
michael@0 306 this->usage();
michael@0 307 rval = TRUE;
michael@0 308
michael@0 309 }else{
michael@0 310 rval = runTestLoop( name, par );
michael@0 311 }
michael@0 312
michael@0 313 if (pos)
michael@0 314 *pos = delim; // restore original value at pos
michael@0 315 return rval;
michael@0 316 }
michael@0 317
michael@0 318
michael@0 319 void UPerfTest::setPath( char* pathVal )
michael@0 320 {
michael@0 321 this->path = pathVal;
michael@0 322 }
michael@0 323
michael@0 324 // call individual tests, to be overriden to call implementations
michael@0 325 UPerfFunction* UPerfTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
michael@0 326 {
michael@0 327 // to be overriden by a method like:
michael@0 328 /*
michael@0 329 switch (index) {
michael@0 330 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
michael@0 331 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
michael@0 332 default: name = ""; break;
michael@0 333 }
michael@0 334 */
michael@0 335 fprintf(stderr,"*** runIndexedTest needs to be overriden! ***");
michael@0 336 return NULL;
michael@0 337 }
michael@0 338
michael@0 339
michael@0 340 UBool UPerfTest::runTestLoop( char* testname, char* par )
michael@0 341 {
michael@0 342 int32_t index = 0;
michael@0 343 const char* name;
michael@0 344 UBool run_this_test;
michael@0 345 UBool rval = FALSE;
michael@0 346 UErrorCode status = U_ZERO_ERROR;
michael@0 347 UPerfTest* saveTest = gTest;
michael@0 348 gTest = this;
michael@0 349 int32_t loops = 0;
michael@0 350 double t=0;
michael@0 351 int32_t n = 1;
michael@0 352 long ops;
michael@0 353 do {
michael@0 354 this->runIndexedTest( index, FALSE, name );
michael@0 355 if (!name || (name[0] == 0))
michael@0 356 break;
michael@0 357 if (!testname) {
michael@0 358 run_this_test = TRUE;
michael@0 359 }else{
michael@0 360 run_this_test = (UBool) (strcmp( name, testname ) == 0);
michael@0 361 }
michael@0 362 if (run_this_test) {
michael@0 363 UPerfFunction* testFunction = this->runIndexedTest( index, TRUE, name, par );
michael@0 364 execCount++;
michael@0 365 rval=TRUE;
michael@0 366 if(testFunction==NULL){
michael@0 367 fprintf(stderr,"%s function returned NULL", name);
michael@0 368 return FALSE;
michael@0 369 }
michael@0 370 ops = testFunction->getOperationsPerIteration();
michael@0 371 if (ops < 1) {
michael@0 372 fprintf(stderr, "%s returned an illegal operations/iteration()\n", name);
michael@0 373 return FALSE;
michael@0 374 }
michael@0 375 if(iterations == 0) {
michael@0 376 n = time;
michael@0 377 // Run for specified duration in seconds
michael@0 378 if(verbose==TRUE){
michael@0 379 fprintf(stdout,"= %s calibrating %i seconds \n", name, (int)n);
michael@0 380 }
michael@0 381
michael@0 382 //n *= 1000; // s => ms
michael@0 383 //System.out.println("# " + meth.getName() + " " + n + " sec");
michael@0 384 int32_t failsafe = 1; // last resort for very fast methods
michael@0 385 t = 0;
michael@0 386 while (t < (int)(n * 0.9)) { // 90% is close enough
michael@0 387 if (loops == 0 || t == 0) {
michael@0 388 loops = failsafe;
michael@0 389 failsafe *= 10;
michael@0 390 } else {
michael@0 391 //System.out.println("# " + meth.getName() + " x " + loops + " = " + t);
michael@0 392 loops = (int)((double)n / t * loops + 0.5);
michael@0 393 if (loops == 0) {
michael@0 394 fprintf(stderr,"Unable to converge on desired duration");
michael@0 395 return FALSE;
michael@0 396 }
michael@0 397 }
michael@0 398 //System.out.println("# " + meth.getName() + " x " + loops);
michael@0 399 t = testFunction->time(loops,&status);
michael@0 400 if(U_FAILURE(status)){
michael@0 401 printf("Performance test failed with error: %s \n", u_errorName(status));
michael@0 402 break;
michael@0 403 }
michael@0 404 }
michael@0 405 } else {
michael@0 406 loops = iterations;
michael@0 407 }
michael@0 408
michael@0 409 double min_t=1000000.0, sum_t=0.0;
michael@0 410 long events = -1;
michael@0 411
michael@0 412 for(int32_t ps =0; ps < passes; ps++){
michael@0 413 fprintf(stdout,"= %s begin " ,name);
michael@0 414 if(verbose==TRUE){
michael@0 415 if(iterations > 0) {
michael@0 416 fprintf(stdout, "%i\n", (int)loops);
michael@0 417 } else {
michael@0 418 fprintf(stdout, "%i\n", (int)n);
michael@0 419 }
michael@0 420 } else {
michael@0 421 fprintf(stdout, "\n");
michael@0 422 }
michael@0 423 t = testFunction->time(loops, &status);
michael@0 424 if(U_FAILURE(status)){
michael@0 425 printf("Performance test failed with error: %s \n", u_errorName(status));
michael@0 426 break;
michael@0 427 }
michael@0 428 sum_t+=t;
michael@0 429 if(t<min_t) {
michael@0 430 min_t=t;
michael@0 431 }
michael@0 432 events = testFunction->getEventsPerIteration();
michael@0 433 //print info only in verbose mode
michael@0 434 if(verbose==TRUE){
michael@0 435 if(events == -1){
michael@0 436 fprintf(stdout, "= %s end: %f loops: %i operations: %li \n", name, t, (int)loops, ops);
michael@0 437 }else{
michael@0 438 fprintf(stdout, "= %s end: %f loops: %i operations: %li events: %li\n", name, t, (int)loops, ops, events);
michael@0 439 }
michael@0 440 }else{
michael@0 441 if(events == -1){
michael@0 442 fprintf(stdout,"= %s end %f %i %li\n", name, t, (int)loops, ops);
michael@0 443 }else{
michael@0 444 fprintf(stdout,"= %s end %f %i %li %li\n", name, t, (int)loops, ops, events);
michael@0 445 }
michael@0 446 }
michael@0 447 }
michael@0 448 if(verbose && U_SUCCESS(status)) {
michael@0 449 double avg_t = sum_t/passes;
michael@0 450 if (loops == 0 || ops == 0) {
michael@0 451 fprintf(stderr, "%s did not run\n", name);
michael@0 452 }
michael@0 453 else if(events == -1) {
michael@0 454 fprintf(stdout, "%%= %s avg: %.4g loops: %i avg/op: %.4g ns\n",
michael@0 455 name, avg_t, (int)loops, (avg_t*1E9)/(loops*ops));
michael@0 456 fprintf(stdout, "_= %s min: %.4g loops: %i min/op: %.4g ns\n",
michael@0 457 name, min_t, (int)loops, (min_t*1E9)/(loops*ops));
michael@0 458 }
michael@0 459 else {
michael@0 460 fprintf(stdout, "%%= %s avg: %.4g loops: %i avg/op: %.4g ns avg/event: %.4g ns\n",
michael@0 461 name, avg_t, (int)loops, (avg_t*1E9)/(loops*ops), (avg_t*1E9)/(loops*events));
michael@0 462 fprintf(stdout, "_= %s min: %.4g loops: %i min/op: %.4g ns min/event: %.4g ns\n",
michael@0 463 name, min_t, (int)loops, (min_t*1E9)/(loops*ops), (min_t*1E9)/(loops*events));
michael@0 464 }
michael@0 465 }
michael@0 466 delete testFunction;
michael@0 467 }
michael@0 468 index++;
michael@0 469 }while(name);
michael@0 470
michael@0 471 gTest = saveTest;
michael@0 472 return rval;
michael@0 473 }
michael@0 474
michael@0 475 /**
michael@0 476 * Print a usage message for this test class.
michael@0 477 */
michael@0 478 void UPerfTest::usage( void )
michael@0 479 {
michael@0 480 puts(gUsageString);
michael@0 481 if (_addUsage != NULL) {
michael@0 482 puts(_addUsage);
michael@0 483 }
michael@0 484
michael@0 485 UBool save_verbose = verbose;
michael@0 486 verbose = TRUE;
michael@0 487 fprintf(stdout,"Test names:\n");
michael@0 488 fprintf(stdout,"-----------\n");
michael@0 489
michael@0 490 int32_t index = 0;
michael@0 491 const char* name = NULL;
michael@0 492 do{
michael@0 493 this->runIndexedTest( index, FALSE, name );
michael@0 494 if (!name)
michael@0 495 break;
michael@0 496 fprintf(stdout, "%s\n", name);
michael@0 497 index++;
michael@0 498 }while (name && (name[0] != 0));
michael@0 499 verbose = save_verbose;
michael@0 500 }
michael@0 501
michael@0 502
michael@0 503
michael@0 504
michael@0 505 void UPerfTest::setCaller( UPerfTest* callingTest )
michael@0 506 {
michael@0 507 caller = callingTest;
michael@0 508 if (caller) {
michael@0 509 verbose = caller->verbose;
michael@0 510 }
michael@0 511 }
michael@0 512
michael@0 513 UBool UPerfTest::callTest( UPerfTest& testToBeCalled, char* par )
michael@0 514 {
michael@0 515 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
michael@0 516 testToBeCalled.setCaller( this );
michael@0 517 return testToBeCalled.runTest( path, par );
michael@0 518 }
michael@0 519
michael@0 520 UPerfTest::~UPerfTest(){
michael@0 521 if(lines!=NULL){
michael@0 522 delete[] lines;
michael@0 523 }
michael@0 524 if(buffer!=NULL){
michael@0 525 uprv_free(buffer);
michael@0 526 }
michael@0 527 if(resolvedFileName!=NULL){
michael@0 528 uprv_free(resolvedFileName);
michael@0 529 }
michael@0 530 ucbuf_close(ucharBuf);
michael@0 531 }
michael@0 532
michael@0 533 #endif

mercurial