00001 //////////////////////////////////////////////////////////////////////////////// 00002 /// 00003 /// \file 00004 /// \author Gerald Fahrnholz 00005 /// 00006 /// \defgroup GrpRunner Using Runner 00007 /// @{ 00008 /// \ingroup GrpTestUtils 00009 /// \brief 00010 /// Class Runner executes a user defined set of test functions 00011 /// containing arbitrary test cases. 00012 /// 00013 /// The test functions have to be declared within 00014 /// macros \ref TTB_TEST_FUNC or \ref TTB_TEST_FUNC_DESC. 00015 /// 00016 /// <b>\n Supported features</b> 00017 /// 00018 /// - provides a controlling main function, users have only to define the 00019 /// test functions (similar to automatic test cases within Boost::Test) 00020 /// 00021 /// - possibility to select and sort the test functions for execution 00022 /// 00023 /// - relevant test events and results are written to logfiles 00024 /// - Report YourTestApp.rpt: overview of test cases and results 00025 /// - Protocol YourTestApp.out: more detailed log file, usable for analysis of 00026 /// test errors 00027 /// 00028 /// - optional time controlled repeated execution of test functions 00029 /// for long duration tests with check of performance counters 00030 /// (e.g. consumption of memory) 00031 /// 00032 /// - check for memory leaks 00033 /// 00034 /// - any error detected during testing (e.g. memory leak) will result in 00035 /// an exit code different from 0 00036 /// 00037 /// 00038 /// <b>\n Example for a simple test application</b> 00039 /// 00040 /// \code 00041 /// #include "TestToolBox/RunnerImpl.h" // includes also implementation code 00042 /// 00043 /// //include headers of your specific test object 00044 /// #include ... 00045 /// 00046 /// // Define name of this component for simple trace utility and set initial trace level 00047 /// TTB_TRC_DEF_GLOBALS ("TestRunner", TL_VAL_DEBUG); 00048 /// 00049 /// // automatic execution of main with execution of all test functions 00050 /// // via TestToolBox::TestRunner 00051 /// TTB_USE_DEFAULT_TEST_RUNNER(); 00052 /// 00053 /// // here follows your first test function 00054 /// TTB_TEST_FUNC (YourFirstTestFunc) 00055 /// { 00056 /// // The name of the test function implicitly is the name of the first test case. 00057 /// 00058 /// // Instantiate the object to test and prepare for testing 00059 /// YourObjectUnderTest yourObject; 00060 /// ... 00061 /// 00062 /// // Call some interface of your object under test 00063 /// yourObject.DoSomething(); 00064 /// ... 00065 /// 00066 /// // Here we assume, that the reaction somehow arrives within 00067 /// // TestToolBox::TestEvents (e.g. through synchronous or 00068 /// // asynchronous callback; the callback object may simply generate 00069 /// // one or more entries within TestEvents which can be immediately 00070 /// // verified). 00071 /// 00072 /// // Check the received result 00073 /// TTB_EXP("CallBack-Result: 14"); 00074 /// 00075 /// // optionally proceed with further interactions with your object under test 00076 /// ... 00077 /// } 00078 /// 00079 /// // here follows your second test function 00080 /// TTB_TEST_FUNC (YourSecondTestFunc) 00081 /// { 00082 /// ... 00083 /// } 00084 /// \endcode 00085 /// 00086 /// Hint: It may be a good advise to always use a new test function when you need a 00087 /// new test case. 00088 /// 00089 /// 00090 /// <b>\n Example of a test report file</b> 00091 /// 00092 /// \code 00093 /// Generic test protocol template / TestToolBox (TTB) 2010 00094 /// 00095 /// 00096 /// T E S T P R O T O C O L 00097 /// 00098 /// Date : 30.05.2010 16:36:33 00099 /// Test application : c:\My Target\Debug\TestRunner.exe 00100 /// Test protocol : c:\My Target\Debug\TestRunner.out 00101 /// Test report : c:\My Target\Debug\TestRunner.rpt 00102 /// Source path : c:\userdata\gerald\sw\c\testtoolbox 00103 /// Command line args : "-checkForMemLeaks" "AT_SHUTDOWN" 00104 /// Run on computer : SIRIUS 00105 /// Run by : Gerald 00106 /// ________________________________________________________________________________ 00107 /// 00108 /// Executing 9 of 9 specified test functions 00109 /// 00110 /// Test: YourFirstTestFunc 00111 /// Test: YourSecondTestFunc 00112 /// ... 00113 /// ________________________________________________________________________________ 00114 /// 00115 /// Test started : 30.05.2010 16:36:33 00116 /// Test ended : 30.05.2010 16:36:33 00117 /// Duration : 00:00:00,016 00118 /// 00119 /// Tests performed : 9 00120 /// Tests failed : 0 00121 /// 00122 /// No error detected! 00123 /// \endcode 00124 /// 00125 /// 00126 /// <b>\n Snippet from a test protocol file</b> 00127 /// 00128 /// \code 00129 /// ... 00130 /// ================================================================================ 00131 /// Test: WaitForSingleAsyncAnswer 00132 /// ================================================================================ 00133 /// 00134 /// Calling CalcAsync(7) 00135 /// (Waiting for asynchronous result via callback) 00136 /// 00137 /// >CallBack-Result: 14 00138 /// 00139 /// ================================================================================ 00140 /// Test: Waiting for multiple sync answers 00141 /// ================================================================================ 00142 /// 00143 /// 00144 /// <so.CalcSync 2 00145 /// >CallBack-Result: 4 00146 /// 00147 /// <so.CalcSync 33 00148 /// >CallBack-Result: 66 00149 /// 00150 /// <so.CalcSync 99 00151 /// >CallBack-Result: 198 00152 /// ... 00153 /// \endcode 00154 /// 00155 /// 00156 /// <b>\n Recommendations for organizing and running your tests</b> 00157 /// 00158 /// - initialization and cleanup for your test environment or for single test functions 00159 /// is possible by providing an <b>extension class</b> derived from \ref 00160 /// TestToolBox::RunnerExtensionPoints and using macro \ref TTB_USE_TEST_RUNNER_WITH_EXTENSIONS 00161 /// 00162 /// - you should organize your test functions in several source files, e.g.: 00163 /// - YourTestApp.cpp: setup your test environment (e.g. define your extension 00164 /// class, define global data used within your tests) 00165 /// - YourTestTopicA.cpp, YourTestTopicB.cpp: implement test functions/test 00166 /// cases and group them 00167 /// - you can use command line option <b>-selectTestFile</b> to execute tests 00168 /// from only one or more source files 00169 /// 00170 /// - you can define additional test cases within your test functions using macro 00171 /// \ref TTB_TEST_CASE 00172 /// 00173 /// - to improve the information written to test protocol file you can use macros 00174 /// \ref TTB_INFO, \ref TTB_SECTION, \ref TTB_CMD, TTB_CMD1,...<br> 00175 /// For more information see \ref TestEvents.h and \ref GrpTestEvents 00176 /// 00177 /// - for handling asynchronous reactions you should use macros 00178 /// \ref TTB_INIT_SYNC, \ref TTB_WAIT_SYNC, \ref TTB_SYNC, \ref TTB_SET_SYNC_TIMEOUT<br> 00179 /// For more information see \ref TestToolBox::Synchronizer and \ref GrpSynchronizer 00180 /// 00181 /// - for checking the observed results within your test use macros \ref TTB_EXP, 00182 /// TTB_SEQ and TTB_EXP_VAR<br> 00183 /// For more information see \ref TestToolBox::TestEvents and \ref TestEvents.h 00184 /// 00185 /// 00186 /// <b>\n Command line arguments</b> 00187 /// 00188 /// Help about possible arguments is available through param "-?": 00189 /// 00190 /// \code 00191 /// >MyTestApp.exe -? 00192 /// 00193 /// TestRunner / TestToolBox (TTB) 2010 00194 /// 00195 /// 00196 /// Commandline Syntax 00197 /// 00198 /// -outputLevel SILENT | FATAL | ERROR | REGULAR | VERBOUS 00199 /// 00200 /// adjust amount of output written to stdout 00201 /// 00202 /// SILENT : no output at all 00203 /// FATAL : display only fatal execution errors 00204 /// ERROR : display also regular errors detected 00205 /// within test cases 00206 /// REGULAR (default) : medium level of output, show progress 00207 /// of test cases just executing 00208 /// VERBOUS : maximum level of output, shows more 00209 /// details about execution, also rises amount 00210 /// of output written to protocol file 00211 /// 00212 /// -selectTestFunc <expr1>,<expr2>,... 00213 /// 00214 /// allows filtering of the test functions to execute, 00215 /// you can combine several filter conditions by separating them 00216 /// with ",". The filter expression will be compared with the 00217 /// name of the test function as defined within TTB_TEST_FUNC and 00218 /// TTB_TEST_FUNC_DESC (in the last case the long name is used) 00219 /// 00220 /// Example: Assume a test func has the name "MySpecialTest" 00221 /// Then the expressions "My*", "*ialTest", "*eci*" and 00222 /// "MySpecialTest" will match and "My", "Test" and "*Z*" 00223 /// will not match 00224 /// 00225 /// Default: no filter set, i.e. all test functions are selected 00226 /// for execution 00227 /// 00228 /// -selectTestFile <expr1>,<expr2>,... 00229 /// 00230 /// allows filtering of the test functions by selecting the file, 00231 /// name where the test is implemented. 00232 /// For more details of defining filter expressions see description 00233 /// of option "-selectTestFunc" 00234 /// The filter conditions of both options are combined via logical 00235 /// AND 00236 /// 00237 /// -sort ALPHABETICAL 00238 /// 00239 /// execute the test functions in alphabetical order of their names 00240 /// 00241 /// -loopTimeSec <numSeconds> 00242 /// 00243 /// repeat the execution of test cases until the specified amount 00244 /// of time has elapsed 00245 /// performance data will be recorded within logfile and written to stdout 00246 /// 00247 /// -perfDataIntervalSec <numSeconds> 00248 /// 00249 /// record performance data every time the given period 00250 /// has elapsed 00251 /// 00252 /// -perfCounterConfig XpEnglish | XpGerman 00253 /// 00254 /// the name of the performance counters is set according to the 00255 /// windows system 00256 /// Default: XpGerman 00257 /// 00258 /// -prefixForReceivedTestEvents <MyPrefix> 00259 /// 00260 /// generates modified output of test events to support direct copying 00261 /// to test script. E.g. setting prefix 'TTB_EXP' generates output 00262 /// 'TTB_EXP("some result: 42");' instead of '>some result: 42' 00263 /// 00264 /// -checkForMemLeaks OFF | AT_MAIN_EXIT | AT_SHUTDOWN 00265 /// | AT_MAIN_EXIT+AT_SHUTDOWN 00266 /// 00267 /// OFF : no check for memory leaks 00268 /// AT_MAIN_EXIT : check if all data on heap has been released 00269 /// when main() has finished. A detected memory 00270 /// leak will cause an exit code of 1 00271 /// AT_SHUTDOWN : check if all data allocated since program 00272 /// startup has been released at time of shutting down. 00273 /// Startup and shutdown is defined by creation and 00274 /// destruction of an internal static object residing within a 00275 /// compiler segment of type 'lib'. A detected memory 00276 /// leak will cause an exit code of 3 and a fatal system 00277 /// message (which can be ignored) 00278 /// 00279 /// Hint: static and global data of your specific test environment may 00280 /// also have an effect on memory allocation and deallocation both before 00281 /// and after execution of main function. 00282 /// Default: AT_MAIN_EXIT+AT_SHUTDOWN 00283 /// 00284 /// -breakAtMemAlloc <N> 00285 /// 00286 /// break program execution when the given memory allocation is executed. 00287 /// the number to specify can be derived from memory leak reports. 00288 /// Works only when running within debugger. 00289 /// 00290 /// -? or -help 00291 /// 00292 /// show these infos and exit test application 00293 /// \endcode 00294 /// 00295 /// \sa Runner.h (File documentation) 00296 /// \sa TestToolBox::Runner (class documentation) 00297 /// 00298 //////////////////////////////////////////////////////////////////////////////// 00299 00300 #pragma once 00301 00302 #include <vector> 00303 00304 #include "TestToolBox/ErrorEventsImpl.h" // template code requires include of implementation 00305 #include "TestToolBox/TestEvents.h" 00306 00307 #ifdef USE_TEST_INSTANCE_DLL 00308 # include "TestToolBox/TestInstanceDll.h" 00309 #endif 00310 00311 namespace TestToolBox 00312 { 00313 typedef void VoidFunc(void); 00314 namespace 00315 { 00316 class PerformanceLogger; 00317 } 00318 00319 /// Info struct for a test function 00320 struct FuncInfo 00321 { 00322 FuncInfo ( 00323 std::string const & in_funcName, 00324 std::string const & in_fileName, 00325 int in_lineNum, 00326 VoidFunc in_pFunc); 00327 00328 /// name of the function 00329 std::string m_funcName; 00330 00331 /// file where the function is defined 00332 std::string m_fileName; 00333 00334 /// line number where the function is defined 00335 int m_lineNum; 00336 00337 /// pointer to the function 00338 VoidFunc* m_pFunc; 00339 }; 00340 /// Vector of test functions 00341 typedef std::vector<FuncInfo> FuncInfos; 00342 00343 00344 //***************************************************************************** 00345 //***************************************************************************** 00346 00347 00348 // You have to adjust the template error class to the specific 00349 // types you are using in your project 00350 00351 // example how to define an enum range as error category: 00352 // enum MyCategory {GENERAL, CONTROL, USER, COMMUNICATION}; 00353 // typedef ErrorEvents<MyCategory,long> MyErrorEvents; 00354 // but often the default settings may be sufficient, i.e. error category 00355 // and error id are defined as long, error severity is enum DefaultSeverity 00356 ///\cond 00357 typedef ErrorEvents<> MyErrorEvents; 00358 00359 __declspec(selectany) MyErrorEvents* MyErrorEvents::s_pErrorEvents = 0; 00360 ///\endcond 00361 00362 00363 //***************************************************************************** 00364 //***************************************************************************** 00365 00366 00367 /// Base class for your specific extension class 00368 class RunnerExtensionPoints 00369 { 00370 public: 00371 00372 virtual ~RunnerExtensionPoints(void) {}; 00373 00374 /// Called before or after excution of a test function 00375 virtual void BeforeCallOfTestFunction(FuncInfo const &){} 00376 00377 /// Called after excution of a test function 00378 virtual void AfterCallOfTestFunction(FuncInfo const &){} 00379 00380 }; // class RunnerExtensionPoints 00381 00382 00383 //***************************************************************************** 00384 //***************************************************************************** 00385 00386 00387 /// \brief This class runs user defined test functions and organizes 00388 /// their execution. 00389 /// 00390 /// \nosubgrouping 00391 /// \sa Runner.h (File documentation) 00392 /// \sa GrpRunner (Usage documentation) 00393 class Runner 00394 { 00395 public: 00396 00397 /// Helper class to register a user defined test function 00398 struct Register 00399 { 00400 /// \brief Constructor adding the given test function to the list of 00401 /// stored test functions within singleton instance of \ref Runner 00402 Register( 00403 char const * in_funcName, 00404 char const * in_fileName, 00405 int in_lineNum, 00406 VoidFunc in_pFunc); 00407 }; 00408 00409 private: 00410 ///\cond 00411 00412 /// Constructor 00413 explicit Runner(void); 00414 ///\endcond 00415 00416 public: 00417 ///\cond 00418 00419 /// Destructor 00420 virtual ~Runner(); 00421 00422 00423 // Get the pointer to the only instance of this class 00424 #ifdef USE_TEST_INSTANCE_DLL 00425 static Runner* Get (void) 00426 {return TTB_GetInstance_Runner();} 00427 static Runner* s_pRunner; 00428 static void Cleanup (void) 00429 {TTB_CleanupInstance_Runner();} 00430 #else 00431 static Runner* Get (void) 00432 {if (!s_pRunner) s_pRunner = new Runner; 00433 return s_pRunner;} 00434 static Runner* s_pRunner; 00435 static void Cleanup (void) 00436 {delete s_pRunner; s_pRunner = 0;} 00437 #endif 00438 00439 ///\endcond 00440 00441 /// \brief Executes all test functions according to the given command line 00442 /// params. 00443 /// You can specify your extension class (derived from \ref RunnerExtensionPoints) 00444 /// to add code for initialization and cleanup of test functions. This funmction 00445 /// is called from within macros \ref TTB_USE_DEFAULT_TEST_RUNNER and 00446 /// \ref TTB_USE_TEST_RUNNER_WITH_EXTENSIONS 00447 template<class YOUR_CLASS_TYPE> 00448 static int RunMain ( 00449 char const * in_contextInfo, 00450 char const * in_fileName, 00451 long const & in_lineNum); 00452 00453 /// Automatically execute the defined test functions 00454 int Execute(RunnerExtensionPoints* in_pExtensionPoints = 0); 00455 00456 private: 00457 00458 typedef enum 00459 { 00460 BEFORE_CALL_OF_TEST_FUNC, 00461 AFTER_CALL_OF_TEST_FUNC 00462 } CallType; 00463 00464 00465 /// The stored test functions 00466 FuncInfos m_funcInfos; 00467 00468 private: 00469 00470 /// Store the given test function for later execution. 00471 void AddTestFunc(FuncInfo const & in_funcInfo) 00472 {m_funcInfos.push_back(in_funcInfo);} 00473 00474 /// Display info about possible commandline args 00475 void DisplayCommandlineSyntax (void); 00476 00477 /// \brief Select and sort the test functions according to the given 00478 /// command line params 00479 FuncInfos ArrangeTestSequence (void); 00480 00481 /// Call a single test function and catch possible exceptions 00482 void CallTestFunc( 00483 VoidFunc* in_pVoidFunc, 00484 std::string const & in_info, 00485 int & io_numExceptionsCaught); 00486 00487 /// Call an extension function and catch possible exceptions 00488 void CallExtensionPoints ( 00489 RunnerExtensionPoints* in_pExtensionPoints, 00490 CallType in_callType, 00491 FuncInfo const & in_rFuncInfo, 00492 std::string const & in_info, 00493 int & io_numExceptionsCaught); 00494 00495 /// \brief Starts logging of performance data if required from command line. 00496 /// Returns 0 if no data collecting is needed. 00497 PerformanceLogger* StartPerformanceLoggingIfRequired ( 00498 double & out_loopTimeSec); 00499 00500 /// \brief Finishes logging of performance data. 00501 void FinishPerformanceLoggingIfRequired ( 00502 PerformanceLogger* in_pPerformanceLogger); 00503 00504 }; // class Runner 00505 00506 00507 //***************************************************************************** 00508 //***************************************************************************** 00509 00510 ///\cond do not document 00511 00512 template<class YOUR_CLASS_TYPE> 00513 int Runner::RunMain ( 00514 char const * in_contextInfo, 00515 char const * in_fileName, 00516 long const & in_lineNum) 00517 { 00518 TRCF("Runner-RunMain") 00519 TRC(TL_DEBUG, "Begin"); 00520 00521 00522 //----- Check command line whether memory check shall be executed ----- 00523 00524 bool checkForMemLeaks = false; 00525 TestToolBox::Environment* pEnv = TestToolBox::TheEnvironment(); 00526 if (!pEnv->IsExistingCommandLineOption("-checkForMemLeaks")) 00527 { 00528 checkForMemLeaks = true; 00529 } 00530 std::string checkMode = pEnv->GetCommandLineOption("-checkForMemLeaks"); 00531 if (checkMode.find("AT_MAIN_EXIT")!=checkMode.npos) 00532 { 00533 TRC(TL_DEBUG, "Checking for memleaks at end of main function"); 00534 checkForMemLeaks = true; 00535 } 00536 00537 00538 //----- Execute test functions and check test results ----- 00539 00540 int exitCodeTest = 0; 00541 { 00542 { 00543 YOUR_CLASS_TYPE yourExtensionClass; 00544 00545 // Execute all test functions 00546 exitCodeTest = TestToolBox::Runner::Get()->Execute(&yourExtensionClass); 00547 00548 } // destructor of YOUR_CLASS_TYPE 00549 00550 TestToolBox::TestEvents::Get()->CheckForUnexpectedEvents( 00551 in_contextInfo,in_fileName,in_lineNum); 00552 if ((exitCodeTest == 0) && (!TestToolBox::TestEvents::Get()->AllTestsHaveSucceeded())) 00553 { 00554 exitCodeTest = 1; 00555 } 00556 TestToolBox::Runner::Get()->Cleanup(); 00557 } 00558 00559 00560 //----- Optional check for memory leaks ----- 00561 00562 int exitCodeMemCheck = 0; 00563 00564 if (checkForMemLeaks) 00565 { 00566 // Remark: here it is not possible to work with memory check points 00567 // at begin and end of this function because before this function 00568 // (and main() itself) is called, there will be automatic calls to register 00569 // test fucntions. This means that parts of the TTB environment are 00570 // created before main. But by calling Runner::Cleanup() the whole environment 00571 // will be released. So memory check will always detect unbalanced states. 00572 // Therefore we simply check if all objects are relased. 00573 // If you could not guarantee the complete release of objects 00574 // deactivate this check via command line params 00575 exitCodeMemCheck = _CrtDumpMemoryLeaks(); 00576 if (exitCodeMemCheck !=0) 00577 { 00578 TRC(TL_DEBUG, "ERROR: memory leaks detected (at end of Runner::RunMain, see above)!"); 00579 std::cout << "ERROR: memory leaks detected (at end of Runner::RunMain, see above)!\n"; 00580 } 00581 } 00582 00583 00584 //----- Build final exit code ----- 00585 00586 int exitCode = exitCodeTest != 0 ? exitCodeTest : exitCodeMemCheck; 00587 TRC(TL_DEBUG, "End returning %d", exitCode); 00588 return exitCode; 00589 00590 } // Runner::RunMain 00591 00592 00593 #ifndef USE_TEST_INSTANCE_DLL 00594 __declspec(selectany) Runner* Runner::s_pRunner = 0; 00595 #endif 00596 00597 ///\endcond 00598 00599 00600 //***************************************************************************** 00601 // Free functions for shorter notation within test script 00602 //***************************************************************************** 00603 00604 namespace ShortNames 00605 { 00606 /// Access/create the singleton instance of Runner 00607 inline Runner* TestRunner (void) 00608 {return Runner::Get();} 00609 00610 /// Short form for TestEvents::Get()->Act() 00611 void Act (const char* in_actualEvent, ...); 00612 00613 /// Short form for MyErrorEvents::Get()->ReportStoredErrors(); 00614 void ReportStoredErrors (void); 00615 00616 /// Short form for MyErrorEvents::Get()->DeleteStoredErrors(); 00617 void DeleteStoredErrors (void); 00618 00619 /// \brief Short form for MyErrorEvents::Get()->SetNotificationActionForErrorMsgNum( 00620 /// msgNum, ACTION_IGNORE/ACTION_NOT_SPECIFIED); 00621 void SetIgnoreError ( 00622 long in_errorMsgNum, 00623 bool in_ignore); 00624 00625 /// \brief Short form for MyErrorEvents::Get()->IgnoreErrorContainingTextPattern() 00626 void IgnoreErrorContainingTextPattern( 00627 std::string const & in_text); 00628 00629 /// \brief Short form for MyErrorEvents::Get()->ClearStoredTextPatterns() 00630 void ClearStoredErrorTextPatterns(void); 00631 00632 /// \brief Short form for MyErrorEvents::Get()->SetErrorSync() 00633 void SetErrorSync ( 00634 bool in_syncOnError); 00635 00636 /// \brief Short form for MyErrorEvents::Get()->SetImmediateErrorLog() 00637 void SetImmediateErrorLog ( 00638 bool in_immediateLog); 00639 00640 /// \brief Short form for MyErrorEvents::Get()->ErrorOk() 00641 bool ErrorOk (long in_extErrorId); 00642 } 00643 00644 }; // namespace TestToolBox 00645 00646 00647 //***************************************************************************** 00648 // M A C R O S 00649 //***************************************************************************** 00650 00651 /// \brief Macro to define a test function to be executed under control of 00652 /// TestToolBox::TestRunner() 00653 /// 00654 /// The trick for automatic registration is a simplified variant of methods 00655 /// used within BOOST::Test (http://www.boost.org/doc/libs/1_43_0/libs/test/doc/html/index.html) 00656 /// 00657 /// First there will be created an additional execution function which 00658 /// checks for test errors (of preceding activities), defines a test case with 00659 /// the name of your test function and finally calls your test function. 00660 /// 00661 /// Second a special (file global) register object is instantiated for each 00662 /// test function. The register object is constructed before main() will 00663 /// be called. Within the constructor the test function is registered 00664 /// within the TestToolBox::Runner singleton instance. When main starts 00665 /// the Runner instance can call all registered test functions. 00666 #define TTB_TEST_FUNC(param_name) \ 00667 static void TestFunc_##param_name(); \ 00668 static void ExecuteTestFunc_##param_name() \ 00669 { \ 00670 TestToolBox::TestEvents::Get()->CheckForUnexpectedEvents ( \ 00671 "next test func", __FILE__,__LINE__); \ 00672 TestToolBox::TestEvents::Get()->StartNewTestCase(#param_name); \ 00673 TestFunc_##param_name(); \ 00674 }; \ 00675 TestToolBox::Runner::Register regTestFunc_##param_name(#param_name, \ 00676 __FILE__,__LINE__, &ExecuteTestFunc_##param_name); \ 00677 static void TestFunc_##param_name() 00678 00679 00680 /// \brief Same as \ref TTB_TEST_FUNC but with possibility to assign an 00681 /// arbitrary descriptive text to the test function 00682 /// 00683 /// The descriptive text is used to identify the test function e.g. 00684 /// when filtering or sorting test functions via command line options 00685 /// -selectTestFunc and -sort. 00686 #define TTB_TEST_FUNC_DESC(param_name,param_description) \ 00687 static void TestFunc_##param_name(); \ 00688 static void ExecuteTestFunc_##param_name() \ 00689 { \ 00690 TestToolBox::TestEvents::Get()->CheckForUnexpectedEvents ( \ 00691 "next test func", __FILE__,__LINE__); \ 00692 TestToolBox::TestEvents::Get()->StartNewTestCase(param_description); \ 00693 TestFunc_##param_name(); \ 00694 }; \ 00695 TestToolBox::Runner::Register regTestFunc_##param_name(##param_description, \ 00696 __FILE__,__LINE__, &ExecuteTestFunc_##param_name); \ 00697 static void TestFunc_##param_name() 00698 00699 00700 //***************************************************************************** 00701 00702 /// \brief Macro to define a test case. 00703 /// 00704 /// By default TTB_TEST_FUNC and TTB_TEST_FUNC_DESC define a test function 00705 /// which automatically defines a test case. If you need further partitioning 00706 /// you can define additional test cases within your test function with use of 00707 /// macro TTB_TEST_CASE. 00708 #define TTB_TEST_CASE(DESC) \ 00709 TestToolBox::TestEvents::Get()->CheckForUnexpectedEvents ("next test case", __FILE__,__LINE__); \ 00710 TestToolBox::TestEvents::Get()->StartNewTestCase(DESC); 00711 00712 00713 //***************************************************************************** 00714 00715 00716 /// \brief Macro to define the default implementation of main function 00717 /// executing all test cases with TestToolBox::TestRunner() 00718 /// 00719 /// The test application will execute the following steps: 00720 /// - TestRunner::Execute (execution of all test functions you have defined) 00721 /// - final check for test results 00722 /// - optional check for memory leaks 00723 /// - main will return an exit code of 1 if an error is detected within the tests 00724 /// or a memory leak was detected otherwise 0 00725 #define TTB_USE_DEFAULT_TEST_RUNNER() \ 00726 int _tmain(int argc, _TCHAR* argv[]) \ 00727 { \ 00728 return TestToolBox::Runner::RunMain<TestToolBox::RunnerExtensionPoints> \ 00729 ("main",__FILE__,__LINE__); \ 00730 } 00731 00732 00733 //***************************************************************************** 00734 00735 00736 /// \brief Defines main(argc,argv) which executes all test functions 00737 /// via TestToolBox::TestRunner. Specific initializations can be 00738 /// embedded in the test sequence by providing your own extension 00739 /// class. 00740 /// 00741 /// The test application will execute the following steps: 00742 /// - constructor of YOUR_EXTENSION_CLASS_TYPE 00743 /// - TestRunner::Execute (execution of all test functions you have defined) 00744 /// - before each test function the extension method BeforeCallOfTestFunction() 00745 /// of your extension class is called 00746 /// - after each test function the extension method AfterCallOfTestFunction() 00747 /// of your extension class is called 00748 /// - destructor of YOUR_EXTENSION_CLASS_TYPE 00749 /// - final check for test results 00750 /// - optional check for memory leaks 00751 /// - main will return an exit code of 1 if an error is detected within the tests 00752 /// or a memory leak was detected otherwise 0 00753 /// 00754 /// Hint: it is allowed to define test cases (e.g. by using TTB_TEST_CASE) also 00755 /// within constructor and destructor of YOUR_EXTENSION_CLASS_TYPE 00756 #define TTB_USE_TEST_RUNNER_WITH_EXTENSIONS(YOUR_EXTENSION_CLASS_TYPE) \ 00757 int _tmain(int argc, _TCHAR* argv[]) \ 00758 { \ 00759 return TestToolBox::Runner::RunMain<YOUR_EXTENSION_CLASS_TYPE> \ 00760 ("main",__FILE__,__LINE__); \ 00761 } 00762 00763 00764 //***************************************************************************** 00765 //***************************************************************************** 00766 00767 /// @} // endGrpRunner