michael@0: /* michael@0: ********************************************************************** michael@0: * Copyright (c) 2002-2011, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ********************************************************************** michael@0: */ michael@0: #ifndef _UPERF_H michael@0: #define _UPERF_H michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "unicode/unistr.h" michael@0: #include "unicode/ustring.h" michael@0: michael@0: #include "unicode/testtype.h" michael@0: #include "unicode/utimer.h" michael@0: #include "ucbuf.h" michael@0: michael@0: // Forward declarations from uoptions.h. michael@0: struct UOption; michael@0: typedef struct UOption UOption; michael@0: michael@0: #if !UCONFIG_NO_CONVERSION michael@0: michael@0: U_NAMESPACE_USE michael@0: // Use the TESTCASE macro in subclasses of IntlTest. Define the michael@0: // runIndexedTest method in this fashion: michael@0: // michael@0: //| void MyTest::runIndexedTest(int32_t index, UBool exec, michael@0: //| const char* &name, char* /*par*/) { michael@0: //| switch (index) { michael@0: //| TESTCASE(0,TestSomething); michael@0: //| TESTCASE(1,TestSomethingElse); michael@0: //| TESTCASE(2,TestAnotherThing); michael@0: //| default: michael@0: //| name = ""; michael@0: //| return NULL; michael@0: //| } michael@0: //| } michael@0: #if 0 michael@0: #define TESTCASE(id,test) \ michael@0: case id: \ michael@0: name = #test; \ michael@0: if (exec) { \ michael@0: fprintf(stdout,#test "---"); \ michael@0: fprintf(stdout,"\n"); \ michael@0: return test(); \ michael@0: } \ michael@0: break michael@0: michael@0: #endif michael@0: #define TESTCASE(id,test) \ michael@0: case id: \ michael@0: name = #test; \ michael@0: if (exec) { \ michael@0: return test(); \ michael@0: } \ michael@0: break michael@0: michael@0: /** michael@0: * Subclasses of PerfTest will need to create subclasses of michael@0: * Function that define a call() method which contains the code to michael@0: * be timed. They then call setTestFunction() in their "Test..." michael@0: * method to establish this as the current test functor. michael@0: */ michael@0: class T_CTEST_EXPORT_API UPerfFunction { michael@0: public: michael@0: /** michael@0: * destructor michael@0: */ michael@0: virtual ~UPerfFunction(); michael@0: michael@0: /** michael@0: * Subclasses must implement this method to do the action to be michael@0: * measured. michael@0: */ michael@0: virtual void call(UErrorCode* status)=0; michael@0: michael@0: /** michael@0: * Subclasses must implement this method to return positive michael@0: * integer indicating the number of operations in a single michael@0: * call to this object's call() method. michael@0: */ michael@0: virtual long getOperationsPerIteration()=0; michael@0: /** michael@0: * Subclasses should override this method to return either positive michael@0: * or negative integer indicating the number of events in a single michael@0: * call to this object's call() method, if applicable michael@0: * e.g: Number of breaks / iterations for break iterator michael@0: */ michael@0: virtual long getEventsPerIteration(){ michael@0: return -1; michael@0: } michael@0: /** michael@0: * Call call() n times in a tight loop and return the elapsed michael@0: * milliseconds. If n is small and call() is fast the return michael@0: * result may be zero. Small return values have limited michael@0: * meaningfulness, depending on the underlying CPU and OS. michael@0: */ michael@0: virtual double time(int32_t n, UErrorCode* status) { michael@0: UTimer start, stop; michael@0: utimer_getTime(&start); michael@0: while (n-- > 0) { michael@0: call(status); michael@0: } michael@0: utimer_getTime(&stop); michael@0: return utimer_getDeltaSeconds(&start,&stop); // ms michael@0: } michael@0: michael@0: }; michael@0: michael@0: michael@0: class T_CTEST_EXPORT_API UPerfTest { michael@0: public: michael@0: UBool run(); michael@0: UBool runTest( char* name = NULL, char* par = NULL ); // not to be overidden michael@0: michael@0: virtual void usage( void ) ; michael@0: michael@0: virtual ~UPerfTest(); michael@0: michael@0: void setCaller( UPerfTest* callingTest ); // for internal use only michael@0: michael@0: void setPath( char* path ); // for internal use only michael@0: michael@0: ULine* getLines(UErrorCode& status); michael@0: michael@0: const UChar* getBuffer(int32_t& len,UErrorCode& status); michael@0: michael@0: protected: michael@0: UPerfTest(int32_t argc, const char* argv[], UErrorCode& status); michael@0: michael@0: UPerfTest(int32_t argc, const char* argv[], michael@0: UOption addOptions[], int32_t addOptionsCount, michael@0: const char *addUsage, michael@0: UErrorCode& status); michael@0: michael@0: void init(UOption addOptions[], int32_t addOptionsCount, michael@0: UErrorCode& status); michael@0: michael@0: virtual UPerfFunction* runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide ! michael@0: michael@0: virtual UBool runTestLoop( char* testname, char* par ); michael@0: michael@0: virtual UBool callTest( UPerfTest& testToBeCalled, char* par ); michael@0: michael@0: int32_t _argc; michael@0: const char** _argv; michael@0: const char * _addUsage; michael@0: char* resolvedFileName; michael@0: UCHARBUF* ucharBuf; michael@0: const char* encoding; michael@0: UBool uselen; michael@0: const char* fileName; michael@0: const char* sourceDir; michael@0: int32_t _remainingArgc; michael@0: ULine* lines; michael@0: int32_t numLines; michael@0: UBool line_mode; michael@0: UChar* buffer; michael@0: int32_t bufferLen; michael@0: UBool verbose; michael@0: UBool bulk_mode; michael@0: int32_t passes; michael@0: int32_t iterations; michael@0: int32_t time; michael@0: const char* locale; michael@0: private: michael@0: UPerfTest* caller; michael@0: char* path; // specifies subtests michael@0: michael@0: // static members michael@0: public: michael@0: static UPerfTest* gTest; michael@0: static const char gUsageString[]; michael@0: }; michael@0: michael@0: #endif michael@0: #endif michael@0: