00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #pragma once
00012
00013 #include "TestToolBox/CommonSources/CommonDefinitions.h"
00014 #include "TestToolBox/Runner.h"
00015 #include "TestToolBox/Environment.h"
00016 #include "TestToolBox/TestEvents.h"
00017 #include "TestToolBox/Synchronizer.h"
00018 #include "TestToolBox/ErrorEvents.h"
00019 #include "TestToolBox/TestTime.h"
00020 #include "TestToolBox/Protocol.h"
00021 #include "TestToolBox/PerformanceDataSet.h"
00022 #include <iostream>
00023 #include <iomanip>
00024 #include <algorithm>
00025
00026
00027
00028 #pragma warning( push )
00029 #pragma warning( disable : 4996 ) // vsprintf declared deprecated
00030
00031 namespace TestToolBox
00032 {
00033
00034
00035
00036
00037
00038
00039 namespace
00040 {
00041
00042 class PerformanceLogger
00043 {
00044 public:
00045
00046
00047 PerformanceLogger(
00048 long in_checkTimeIntervalSec);
00049
00050
00051 ~PerformanceLogger();
00052
00053
00054
00055 void CheckPerformance (
00056 int in_testCycle = 0,
00057 bool in_forceChecking = false);
00058
00059 private:
00060
00061 static const int COL_WIDTH = 20;
00062
00063
00064 PerformanceDataSet m_perfDataSet;
00065
00066
00067 std::vector<std::string> m_counterNames;
00068
00069
00070 std::vector<double> m_counterValues;
00071
00072
00073
00074 long m_lastValPrivateBytes;
00075
00076
00077 long m_lastCheckTimeSec;
00078
00079
00080 long m_checkTimeIntervalSec;
00081
00082
00083 long m_lastTestCycle;
00084
00085
00086 std::ofstream m_logFile;
00087
00088 private:
00089 void PrepareLogging (void);
00090 void OpenLogFile (
00091 std::string const & in_perfCounterConfig);
00092 void CloseLogFile (void);
00093
00094 };
00095
00096
00097
00098
00099
00100
00101 TTB_INLINE PerformanceLogger::PerformanceLogger(
00102 long in_checkTimeIntervalSec)
00103 : m_lastValPrivateBytes (0)
00104 , m_lastCheckTimeSec (0)
00105 , m_checkTimeIntervalSec (in_checkTimeIntervalSec)
00106 , m_lastTestCycle (0)
00107 {
00108 TRCF("PerformanceLogger");
00109 TRC(TL_DEBUG, "Constructor");
00110 PrepareLogging();
00111 }
00112
00113
00114
00115 TTB_INLINE PerformanceLogger::~PerformanceLogger(void)
00116 {
00117 TRCF("~PerformanceLogger");
00118 TRC(TL_DEBUG, "Destructor");
00119 CloseLogFile();
00120 }
00121
00122
00123
00124 TTB_INLINE void PerformanceLogger::PrepareLogging(void)
00125 {
00126 TRCF("PerformanceLogger::StartLogging");
00127 TRC(TL_DEBUG, "Executing");
00128
00129 std::string computerName = TheEnvironment()->GetNameOfComputer();
00130 std::string appName = TheEnvironment()->GetAppName();
00131
00132 std::string perfCounterConfig = TheEnvironment()->GetCommandLineOption(
00133 "-perfCounterConfig");
00134 if (perfCounterConfig.empty())
00135 {
00136 perfCounterConfig = "XpGerman";
00137 }
00138
00139 if (perfCounterConfig == "XpGerman")
00140 {
00141 m_counterNames.push_back("\\\\" + computerName + "\\Prozess("
00142 + appName + ")\\Prozessorzeit (%)");
00143 m_counterNames.push_back("\\\\" + computerName + "\\Prozess("
00144 + appName + ")\\Handleanzahl");
00145 m_counterNames.push_back("\\\\" + computerName + "\\Prozess("
00146 + appName + ")\\Threadanzahl");
00147 m_counterNames.push_back("\\\\" + computerName + "\\Prozess("
00148 + appName + ")\\Private Bytes");
00149 }
00150 else if (perfCounterConfig == "XpEnglish")
00151 {
00152 m_counterNames.push_back("\\\\" + computerName + "\\process("
00153 + appName + ")\\Processor Time (%)");
00154 m_counterNames.push_back("\\\\" + computerName + "\\process("
00155 + appName + ")\\Handle Count");
00156 m_counterNames.push_back("\\\\" + computerName + "\\process("
00157 + appName + ")\\Thread Count");
00158 m_counterNames.push_back("\\\\" + computerName + "\\process("
00159 + appName + ")\\Private Bytes");
00160 }
00161 else
00162 {
00163 std::cout << "Invalid config name for '-perfCounterConfig' : "
00164 << perfCounterConfig << std::endl << std::endl;
00165 abort();
00166 }
00167
00168 std::cout << "Trying to access the specified performance counters:\n\n";
00169
00170 for (std::vector<std::string>::iterator it = m_counterNames.begin();
00171 it!=m_counterNames.end();++it)
00172 {
00173 std::cout << *it << std::endl;
00174 }
00175
00176 std::cout << "\nIn case of incorrect names it may need some time to detect "
00177 "the error...";
00178 bool initSucceeded = m_perfDataSet.InitPerfCounters (m_counterNames);
00179
00180 if (!initSucceeded)
00181 {
00182 std::cout << "\n\nERROR: Check the name of your computer and the names of the performance counters\n"
00183 << "on your system (e.g. with utility ScanPerfCounters), correct the sample code\n"
00184 << "and try again! (see also the trace hints for invalid counter names) \n\n"
00185 << std::endl;
00186 exit (1);
00187 }
00188 else
00189 {
00190 std::cout << "\nInitialization was successful! Recording is started...\n\n";
00191
00192 OpenLogFile(perfCounterConfig);
00193
00194 std::ostringstream oss;
00195 oss
00196 << std::setw(COL_WIDTH) << "Test time sec"
00197 << std::setw(COL_WIDTH) << "Test cycle"
00198 << std::setw(COL_WIDTH) << "Processortime in %"
00199 << std::setw(COL_WIDTH) << "Handles"
00200 << std::setw(COL_WIDTH) << "Threads"
00201 << std::setw(COL_WIDTH) << "Private bytes"
00202 << std::setw(COL_WIDTH) << "Bytes changed by"
00203 << std::setw(COL_WIDTH) << "Changes per cycle"
00204 << std::endl;
00205 m_logFile << oss.str();
00206 std::cout << oss.str();
00207 }
00208
00209 }
00210
00211
00212
00213 TTB_INLINE void PerformanceLogger::OpenLogFile (
00214 std::string const & in_perfCounterConfig)
00215 {
00216 std::string nameLogfile = TheEnvironment()->GetOutputDir() + "\\" +
00217 TheEnvironment()->GetAppName() + ".PerformanceData.log";
00218 m_logFile.open(nameLogfile.c_str());
00219
00220 m_logFile <<" P E R F O R M A N C E D A T A"
00221 << std::endl << std::endl
00222 << "Test application : " << TheEnvironment()->GetExeFileFullPath()<< std::endl
00223 << "Source path : " << TheEnvironment()->GetSourceDir()<< std::endl
00224 << "Command line args : " << TheEnvironment()->GetArgsStr()<< std::endl
00225 << "Run on computer : " << TheEnvironment()->GetNameOfComputer()<< std::endl
00226 << "Run by : " << TheEnvironment()->GetNameOfUser()<< std::endl
00227 << "Using configuration : " << in_perfCounterConfig << " with following counters" << std::endl;
00228
00229 for (std::vector<std::string>::iterator it = m_counterNames.begin();
00230 it!=m_counterNames.end();++it)
00231 {
00232 m_logFile << " : " << *it << std::endl;
00233 }
00234
00235 m_logFile
00236 << Protocol::Get()->S_SEPARATOR_LINE << std::endl
00237 << "\nRecording started : " << TestTime::Get()->GetStartTimeDateStr()
00238 << std::endl << std::endl;
00239
00240 }
00241
00242
00243
00244 TTB_INLINE void PerformanceLogger::CloseLogFile (void)
00245 {
00246 m_logFile
00247 << std::endl << std::endl
00248 << "Recording finished: " << TestTime::Get()->GetCurTimeDateStr();
00249 m_logFile.close();
00250
00251 }
00252
00253
00254
00255 TTB_INLINE void PerformanceLogger::CheckPerformance (
00256 int in_testCycle,
00257 bool in_forceChecking)
00258 {
00259 long curTestTimeSec = TestTime::Get()->GetCurTimeSec();
00260
00261 if ( in_forceChecking
00262 || (curTestTimeSec - m_lastCheckTimeSec >= m_checkTimeIntervalSec))
00263 {
00264
00265 m_counterValues = m_perfDataSet.GetCurrentCounterValues();
00266
00267
00268 long curNumPrivateBytes = static_cast<long>(m_counterValues[3]);
00269
00270 double byteChanges = (m_lastValPrivateBytes == 0) ? 0
00271 : (curNumPrivateBytes-m_lastValPrivateBytes);
00272 double changesPerTestCycle = (m_lastTestCycle == in_testCycle) ? 0
00273 : (1.0*(curNumPrivateBytes-m_lastValPrivateBytes)/(in_testCycle-m_lastTestCycle));
00274
00275
00276 std::ostringstream oss;
00277 oss
00278 << std::setw(COL_WIDTH) << curTestTimeSec
00279 << std::setw(COL_WIDTH) << in_testCycle
00280 << std::setw(COL_WIDTH) << std::setprecision(2) << std::fixed
00281 << m_counterValues[0]
00282 << std::setw(COL_WIDTH) << std::setprecision(0) << m_counterValues[1]
00283 << std::setw(COL_WIDTH) << std::setprecision(0) << m_counterValues[2]
00284 << std::setw(COL_WIDTH) << std::setprecision(0) << m_counterValues[3]
00285 << std::setw(COL_WIDTH) << std::setprecision(0)
00286 << byteChanges
00287 << std::setw(COL_WIDTH) << std::setprecision(0)
00288 << changesPerTestCycle
00289 << std::endl;
00290
00291 m_logFile << oss.str();
00292 std::cout << oss.str();
00293
00294 m_lastCheckTimeSec = curTestTimeSec;
00295 m_lastValPrivateBytes = curNumPrivateBytes;
00296 m_lastTestCycle = in_testCycle;
00297 }
00298
00299 }
00300
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 TTB_INLINE FuncInfo::FuncInfo (
00310 std::string const & in_funcName,
00311 std::string const & in_fileName,
00312 int in_lineNum,
00313 VoidFunc in_pFunc)
00314 : m_funcName (in_funcName)
00315 , m_fileName (in_fileName)
00316 , m_lineNum (in_lineNum)
00317 , m_pFunc (in_pFunc)
00318 {
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 TTB_INLINE Runner::Register::Register(
00328 char const * in_funcName,
00329 char const * in_fileName,
00330 int in_lineNum,
00331 VoidFunc in_pFunc)
00332 {
00333 TRCF("Runner::Register");
00334 TRC(TL_DEBUG, "Constructor in_funcName=%s", in_funcName);
00335
00336 std::string fileName (in_fileName);
00337
00338 std::string::size_type pos = fileName.find_last_of("\\/");
00339 if (pos!=std::string::npos)
00340 {
00341 fileName = fileName.substr(pos+1, fileName.length()-1);
00342 }
00343
00344 TestToolBox::Runner::Get()->AddTestFunc(FuncInfo(
00345 in_funcName, fileName, in_lineNum, in_pFunc));
00346
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 TTB_INLINE Runner::Runner(void)
00356 : m_funcInfos ()
00357 {
00358 TRCF("Runner");
00359 TRC(TL_DEBUG, "Constructor");
00360
00361
00362
00363
00364 OutputLevel::Enum outputLevel = OutputLevel::eREGULAR;
00365 TestToolBox::Environment* pEnv = TestToolBox::TheEnvironment();
00366 if (pEnv->IsExistingCommandLineOption("-outputLevel"))
00367 {
00368 std::string outputLevelStr = pEnv->GetCommandLineOption("-outputLevel");
00369 if (outputLevelStr=="SILENT")
00370 {
00371 outputLevel = OutputLevel::eSILENT;
00372 }
00373 else if (outputLevelStr=="FATAL")
00374 {
00375 outputLevel = OutputLevel::eFATAL;
00376 }
00377 else if (outputLevelStr=="ERROR")
00378 {
00379 outputLevel = OutputLevel::eERROR;
00380 }
00381 else if (outputLevelStr=="REGULAR")
00382 {
00383 outputLevel = OutputLevel::eREGULAR;
00384 }
00385 else if (outputLevelStr=="VERBOUS")
00386 {
00387 outputLevel = OutputLevel::eVERBOUS;
00388 }
00389 else
00390 {
00391 std::cout << "!!WRONG COMMANDLINE SYNTAX, invalid param for -outputMode: "
00392 << outputLevel << std::endl;
00393 }
00394 }
00395
00396 if ( (pEnv->IsExistingCommandLineOption("-?"))
00397 || (pEnv->IsExistingCommandLineOption("-help")))
00398 {
00399 DisplayCommandlineSyntax();
00400 exit (0);
00401 }
00402
00403
00404 Protocol::Get(
00405 OutputMode::M_STDOUT | OutputMode::M_OUTFILE | OutputMode::M_RPTFILE,
00406 outputLevel);
00407
00408 TestEvents::Get()->ConnectWithProtocol (Protocol::Get());
00409 TestEvents::Get()->SetDetailedLog(
00410 true,
00411 pEnv->GetCommandLineOption("-prefixForReceivedTestEvents"));
00412 TestEvents::Get()->SetDetailedCheckLog(true);
00413 Synchronizer::Get()->ConnectWithEventReceiver(TestEvents::Get());
00414
00415 }
00416
00417
00418
00419
00420
00421
00422 TTB_INLINE Runner::~Runner()
00423 {
00424 TRCF("~Runner");
00425 TRC(TL_DEBUG, "Destructor: Begin");
00426
00427 Synchronizer::Cleanup();
00428 TestEvents::Cleanup();
00429 MyErrorEvents::Cleanup();
00430 Protocol::Cleanup();
00431 TestTime::Cleanup();
00432 Environment::Cleanup();
00433
00434 TRC(TL_DEBUG, "Destructor: End");
00435
00436 }
00437
00438
00439
00440
00441
00442
00443 TTB_INLINE int Runner::Execute(
00444 RunnerExtensionPoints* in_pExtensionPoints)
00445 {
00446 TRCF("Runner-Execute");
00447 TRC(TL_DEBUG, "Begin");
00448
00449 int retVal = 0;
00450 int numExceptionsCaught = 0;
00451 double loopTimeSec = 0.0;
00452 bool loopTimeElapsed = false;
00453 long executionCounter = 0;
00454
00455 FuncInfos funcInfos = ArrangeTestSequence();
00456 int numberOfTestFuncs = static_cast<int>(funcInfos.size());
00457
00458 PerformanceLogger* pPerfLogger = StartPerformanceLoggingIfRequired(
00459 loopTimeSec);
00460
00461 bool repeatLoop = false;
00462 do
00463 {
00464 ++executionCounter;
00465 if (executionCounter > 1)
00466 {
00467
00468
00469
00470
00471
00472 static int prefixCounter = 0;
00473 ++prefixCounter;
00474 if (prefixCounter > 2)
00475 {
00476 prefixCounter = 1;
00477 }
00478 TestToolBox::Protocol::Get()->SwitchLogfiles(ToString(prefixCounter),
00479 "---- Loop-Execution: File closed when starting execution "
00480 + ToString(executionCounter),
00481 "---- Loop-Execution: File opened when starting execution "
00482 + ToString(executionCounter));
00483 }
00484
00485
00486 for (FuncInfos::iterator it = funcInfos.begin();
00487 it != funcInfos.end(); ++it)
00488 {
00489 int numCurTestFunc = static_cast<int>(std::distance(funcInfos.begin(), it) + 1);
00490
00491 std::string info = "TestFunc " + ToString(numCurTestFunc) + "/"
00492 + ToString(numberOfTestFuncs) + " " + it->m_funcName + " ("
00493 + it->m_fileName + ", " + ToString(it->m_lineNum) + ")";
00494
00495 CallExtensionPoints(in_pExtensionPoints,
00496 BEFORE_CALL_OF_TEST_FUNC, *it, info,
00497 numExceptionsCaught);
00498
00499 CallTestFunc((*it).m_pFunc, info, numExceptionsCaught);
00500
00501 CallExtensionPoints(in_pExtensionPoints,
00502 AFTER_CALL_OF_TEST_FUNC, *it, info,
00503 numExceptionsCaught);
00504 }
00505
00506 TestEvents::Get()->CheckForUnexpectedEvents("Runner::Execute", __FILE__,__LINE__);
00507
00508 if ((numExceptionsCaught > 0) || !TestEvents::Get()->AllTestsHaveSucceeded())
00509 {
00510 retVal = 1;
00511 }
00512
00513 loopTimeElapsed = (loopTimeSec > 0)
00514 ? (TestToolBox::TestTime::Get()->GetCurTimeSec() >= loopTimeSec)
00515 : true;
00516
00517
00518 repeatLoop = (retVal == 0 && !loopTimeElapsed);
00519
00520 if (pPerfLogger)
00521 {
00522
00523 pPerfLogger->CheckPerformance(executionCounter, !repeatLoop);
00524 }
00525
00526 } while (repeatLoop);
00527
00528
00529
00530 FinishPerformanceLoggingIfRequired(pPerfLogger);
00531
00532 if (retVal != 0)
00533 {
00534 Protocol::Get()->Writeln(OutputLevel::eERROR, OutputMode::M_OUTFILE,
00535 "!!ERROR: Runner::Execute return code is " + ToString(retVal));
00536 }
00537 TRC(TL_DEBUG, "End retVal=%d", retVal);
00538 return retVal;
00539
00540 }
00541
00542
00543
00544
00545
00546
00547 TTB_INLINE void Runner::DisplayCommandlineSyntax (void)
00548 {
00549 std::cout << "TestRunner / TestToolBox (TTB) 2010\n\n"
00550 << "\nCommandline Syntax\n" << std::endl;
00551
00552 std::cout << "-outputLevel SILENT | FATAL | ERROR | REGULAR | VERBOUS\n" << std::endl
00553 << " adjust amount of output written to stdout\n\n"
00554 << " SILENT : no output at all\n"
00555 << " FATAL : display only fatal execution errors\n"
00556 << " ERROR : display also regular errors detected\n"
00557 << " within test cases\n"
00558 << " REGULAR (default) : medium level of output, show progress\n"
00559 << " of test cases just executing\n"
00560 << " VERBOUS : maximum level of output, shows more\n"
00561 << " details about execution, also rises amount\n"
00562 << " of output written to protocol file\n";
00563
00564 std::cout << "\n-selectTestFunc <expr1>,<expr2>,...\n\n"
00565 << " allows filtering of the test functions to execute,\n"
00566 << " you can combine several filter conditions by separating them\n"
00567 << " with \",\". The filter expression will be compared with the\n"
00568 << " name of the test function as defined within TTB_TEST_FUNC and\n"
00569 << " TTB_TEST_FUNC_DESC (in the last case the long name is used)\n\n"
00570 << " Example: Assume a test func has the name \"MySpecialTest\"\n"
00571 << " Then the expressions \"My*\", \"*ialTest\", \"*eci*\" and\n"
00572 << " \"MySpecialTest\" will match and \"My\", \"Test\" and \"*Z*\"\n"
00573 << " will not match\n\n"
00574 << " Default: no filter set, i.e. all test functions are selected\n"
00575 << " for execution\n";
00576
00577 std::cout << "\n-selectTestFile <expr1>,<expr2>,...\n\n"
00578 << " allows filtering of the test functions by selecting the file,\n"
00579 << " name where the test is implemented.\n"
00580 << " For more details of defining filter expressions see description\n"
00581 << " of option \"-selectTestFunc\"\n"
00582 << " The filter conditions of both options are combined via logical\n"
00583 << " AND\n";
00584
00585 std::cout << "\n-sort ALPHABETICAL\n\n"
00586 << " execute the test functions in alphabetical order of their names\n";
00587
00588 std::cout << "\n-loopTimeSec <numSeconds>\n\n"
00589 << " repeat the execution of test cases until the specified amount\n"
00590 << " of time has elapsed\n"
00591 << " performance data will be recorded within logfile and written to stdout\n";
00592
00593 std::cout << "\n-perfDataIntervalSec <numSeconds>\n\n"
00594 << " record performance data every time the given period\n"
00595 << " has elapsed\n";
00596
00597 std::cout << "\n-perfCounterConfig XpEnglish | XpGerman\n\n"
00598 << " the name of the performance counters is set according to the\n"
00599 << " windows system\n"
00600 << " Default: XpGerman\n";
00601
00602 std::cout << "\n-prefixForReceivedTestEvents <MyPrefix>\n\n"
00603 << " generates modified output of test events to support direct copying\n"
00604 << " to test script. E.g. setting prefix 'TTB_EXP' generates output\n"
00605 << " 'TTB_EXP(\"some result: 42\");' instead of '>some result: 42'\n";
00606
00607 std::cout << "\n-checkForMemLeaks OFF | CRT_CONTROLLED | AT_MAIN_EXIT | AT_SHUTDOWN\n"
00608 << " | AT_MAIN_EXIT+AT_SHUTDOWN\n\n"
00609 << " OFF : no check for memory leaks\n"
00610 << " CRT_CONTROLLED : standard procedure, C runtime checks for leaks\n"
00611 << " at prog shutdown, exit code is NOT influenced by\n"
00612 << " leak detection, use this option if you have problems\n"
00613 << " with releasing memory within main()\n"
00614 << " AT_MAIN_EXIT : check if all data on heap has been released\n"
00615 << " when main() has finished. A detected memory\n"
00616 << " leak will cause an exit code of 1\n"
00617 << " AT_SHUTDOWN : check if all data allocated since program\n"
00618 << " startup has been released at time of shutting down.\n"
00619 << " Startup and shutdown is defined by creation and\n"
00620 << " destruction of an internal static object residing within a\n"
00621 << " compiler segment of type 'lib'. A detected memory\n"
00622 << " leak will cause an exit code of 3 and a fatal system\n"
00623 << " message (which can be ignored)\n\n"
00624 << " Hint: static and global data of your specific test environment may\n"
00625 << " also have an effect on memory allocation and deallocation both before\n"
00626 << " and after execution of main function.\n"
00627 << " Default: AT_MAIN_EXIT+AT_SHUTDOWN\n";
00628
00629 std::cout << "\n-breakAtMemAlloc <N>\n\n"
00630 << " break program execution when the given memory allocation is executed.\n"
00631 << " the number to specify can be derived from memory leak reports.\n"
00632 << " Works only when running within debugger.\n";
00633
00634 std::cout << "\n-? or -help" << std::endl
00635 << "\n show these infos and exit test application\n";
00636
00637 }
00638
00639
00640
00641
00642
00643 namespace
00644 {
00645
00646
00647
00648
00649 TTB_INLINE bool FilterMatches (
00650 std::string const & in_filter,
00651 std::string const & in_stringToCompare)
00652 {
00653 std::string filter = in_filter;
00654 if (filter.length()==0)
00655 {
00656 return true;
00657 }
00658
00659 bool startMustMatch = true;
00660 bool endMustMatch = true;
00661
00662 if (filter[0] == '*')
00663 {
00664 startMustMatch = false;
00665 filter.erase(0,1);
00666 }
00667
00668 if (filter.length()==0)
00669 {
00670 return true;
00671 }
00672
00673 if (filter[filter.length()-1] == '*')
00674 {
00675 endMustMatch = false;
00676 filter.erase(filter.length()-1,1);
00677 }
00678
00679 if (filter.length()==0)
00680 {
00681 return true;
00682 }
00683
00684
00685 size_t pos = in_stringToCompare.find(filter);
00686 if (pos == std::string::npos)
00687 {
00688
00689 return false;
00690 }
00691
00692
00693
00694
00695 if (startMustMatch && pos > 0)
00696 {
00697
00698 return false;
00699 }
00700
00701 if (endMustMatch && pos != in_stringToCompare.length()-filter.length())
00702 {
00703
00704 return false;
00705 }
00706
00707
00708 return true;
00709
00710 }
00711
00712
00713
00714
00715
00716 struct FuncNameDoesNotMatchFilter
00717 {
00718 FuncNameDoesNotMatchFilter (std::vector<std::string> in_filterConditions)
00719 : m_filterConditions(in_filterConditions)
00720 {}
00721
00722 bool operator() (FuncInfo const& in_funcInfo)
00723 {
00724 TRCF("Runner-FuncNameDoesNotMatchFilter");
00725
00726 bool match = false;
00727 for (std::vector<std::string>::iterator itFilterCond =
00728 m_filterConditions.begin();
00729 itFilterCond != m_filterConditions.end(); ++itFilterCond)
00730 {
00731 std::string filter = *itFilterCond;
00732 if (FilterMatches(filter, in_funcInfo.m_funcName))
00733 {
00734 match = true;
00735 break;
00736 }
00737 }
00738 bool retVal = !match;
00739 TRC(TL_DEBUG, "return %d for funcName %s", retVal, in_funcInfo.m_funcName.c_str());
00740 return retVal;
00741 }
00742
00743 std::vector<std::string> m_filterConditions;
00744 };
00745
00746
00747
00748
00749
00750 struct FileNameDoesNotMatchFilter
00751 {
00752 FileNameDoesNotMatchFilter (std::vector<std::string> in_filterConditions)
00753 : m_filterConditions(in_filterConditions)
00754 {}
00755
00756 bool operator() (FuncInfo const& in_funcInfo)
00757 {
00758 TRCF("Runner-FileNameDoesNotMatchFilter");
00759
00760 bool match = false;
00761 for (std::vector<std::string>::iterator itFilterCond =
00762 m_filterConditions.begin();
00763 itFilterCond != m_filterConditions.end(); ++itFilterCond)
00764 {
00765 std::string filter = *itFilterCond;
00766 if (FilterMatches(filter, in_funcInfo.m_fileName))
00767 {
00768 match = true;
00769 break;
00770 }
00771 }
00772 bool retVal = !match;
00773 TRC(TL_DEBUG, "return %d for funcName %s", retVal, in_funcInfo.m_funcName.c_str());
00774 return retVal;
00775 }
00776
00777 std::vector<std::string> m_filterConditions;
00778 };
00779
00780
00781
00782
00783
00784 struct CompareAlphabetical
00785 {
00786 bool operator() (FuncInfo const& in_lhs, FuncInfo const& in_rhs )
00787 {
00788 return in_lhs.m_funcName < in_rhs.m_funcName;
00789 }
00790 };
00791 }
00792
00793
00794
00795
00796
00797 TTB_INLINE FuncInfos Runner::ArrangeTestSequence (void)
00798 {
00799 TRCF("Runner-ArrangeTestSequence");
00800 size_t numTestFuncsSpecified = m_funcInfos.size();
00801 TRC(TL_DEBUG, "Begin numTestFuncsSpecified=%d", m_funcInfos.size());
00802
00803
00804 FuncInfos funcInfos = m_funcInfos;
00805
00806 TestToolBox::Environment* pEnv = TestToolBox::TheEnvironment();
00807
00808
00809 if (pEnv->IsExistingCommandLineOption("-selectTestFunc"))
00810 {
00811 std::vector<std::string> filterConditions =
00812 SplitString(pEnv->GetCommandLineOption("-selectTestFunc"));
00813 if (filterConditions.size()>0)
00814 {
00815
00816 funcInfos.erase(std::remove_if(funcInfos.begin(), funcInfos.end(),
00817 FuncNameDoesNotMatchFilter(filterConditions)), funcInfos.end());
00818 }
00819 }
00820
00821
00822 if (pEnv->IsExistingCommandLineOption("-selectTestFile"))
00823 {
00824 std::vector<std::string> filterConditions =
00825 SplitString(pEnv->GetCommandLineOption("-selectTestFile"));
00826 if (filterConditions.size()>0)
00827 {
00828
00829 funcInfos.erase(std::remove_if(funcInfos.begin(), funcInfos.end(),
00830 FileNameDoesNotMatchFilter(filterConditions)), funcInfos.end());
00831 }
00832 }
00833
00834
00835 if (pEnv->IsExistingCommandLineOption("-sort"))
00836 {
00837 std::string optionStr = pEnv->GetCommandLineOption("-sort");
00838 if (optionStr=="ALPHABETICAL")
00839 {
00840 std::sort (funcInfos.begin(), funcInfos.end(), CompareAlphabetical());
00841 }
00842
00843
00844 }
00845
00846 size_t numTestFuncsSelectedForExecution = funcInfos.size();
00847 std::ostringstream oss;
00848 oss
00849 << "\nExecuting " << numTestFuncsSelectedForExecution << " of "
00850 << numTestFuncsSpecified << " specified test functions\n";
00851 Protocol::Get()->Writeln(OutputLevel::eREGULAR, OutputMode::M_ALL, oss.str());
00852
00853 TRC(TL_DEBUG, "End numTestFuncsSelectedForExecution=%d", numTestFuncsSelectedForExecution);
00854 return funcInfos;
00855
00856 }
00857
00858
00859
00860
00861
00862
00863 TTB_INLINE void Runner::CallTestFunc(
00864 VoidFunc* in_pVoidFunc,
00865 std::string const & in_info,
00866 int & io_numExceptionsCaught)
00867 {
00868 try
00869 {
00870 Protocol::Get()->Writeln(OutputLevel::eVERBOUS,
00871 OutputMode::M_STDOUT | OutputMode::M_OUTFILE, in_info + ": Begin");
00872
00873 in_pVoidFunc();
00874
00875 Protocol::Get()->Writeln(OutputLevel::eVERBOUS,
00876 OutputMode::M_STDOUT | OutputMode::M_OUTFILE, in_info + ": End");
00877 }
00878 catch(std::exception& e)
00879 {
00880 ++io_numExceptionsCaught;
00881 {
00882 std::ostringstream oss;
00883 oss
00884 << "!!EXCEPTION: \"" << e.what() << "\", "
00885 << in_info;
00886 Protocol::Get()->Writeln(OutputLevel::eFATAL, OutputMode::M_ALL, oss.str());
00887 }
00888 }
00889 catch(...)
00890 {
00891 ++io_numExceptionsCaught;
00892 {
00893 std::ostringstream oss;
00894 oss << "!!UNKNOWN EXCEPTION, "
00895 << in_info;
00896 Protocol::Get()->Writeln(OutputLevel::eFATAL, OutputMode::M_ALL, oss.str());
00897 }
00898 }
00899
00900 }
00901
00902
00903
00904
00905
00906
00907 TTB_INLINE void Runner::CallExtensionPoints (
00908 RunnerExtensionPoints* in_pExtensionPoints,
00909 CallType in_callType,
00910 FuncInfo const & in_rFuncInfo,
00911 std::string const & in_info,
00912 int & io_numExceptionsCaught)
00913 {
00914 if (!in_pExtensionPoints)
00915 {
00916
00917 return;
00918 }
00919
00920 std::string info = in_callType == BEFORE_CALL_OF_TEST_FUNC
00921 ? "RunnerExtensionPoints::BeforeCallOfTestFunction"
00922 : "RunnerExtensionPoints::AfterCallOfTestFunction";
00923 info += " " + in_info;
00924
00925 try
00926 { if (in_callType == BEFORE_CALL_OF_TEST_FUNC)
00927 {
00928 in_pExtensionPoints->BeforeCallOfTestFunction(in_rFuncInfo);
00929 }
00930 else
00931 {
00932 in_pExtensionPoints->AfterCallOfTestFunction(in_rFuncInfo);
00933 }
00934 }
00935
00936 catch(std::exception& e)
00937 {
00938 ++io_numExceptionsCaught;
00939 {
00940 std::ostringstream oss;
00941 oss
00942 << "!!EXCEPTION: \"" << e.what() << "\", "
00943 << info;
00944 Protocol::Get()->Writeln(OutputLevel::eFATAL, OutputMode::M_ALL, oss.str());
00945 }
00946 }
00947 catch(...)
00948 {
00949 ++io_numExceptionsCaught;
00950 {
00951 std::ostringstream oss;
00952 oss << "!!UNKNOWN EXCEPTION, "
00953 << info;
00954 Protocol::Get()->Writeln(OutputLevel::eFATAL, OutputMode::M_ALL, oss.str());
00955 }
00956 }
00957
00958 }
00959
00960
00961
00962
00963
00964
00965 TTB_INLINE PerformanceLogger* Runner::StartPerformanceLoggingIfRequired (
00966 double & out_loopTimeSec)
00967 {
00968 PerformanceLogger* pPerfLogger = 0;
00969
00970 TestToolBox::Environment* pEnv = TestToolBox::TheEnvironment();
00971 bool checkPerfData = pEnv->IsExistingCommandLineOption("-loopTimeSec");
00972 double loopTimeSec = pEnv->GetCommandLineOptionVal<double>("-loopTimeSec");
00973 long perfDataIntervalSec = 0;
00974 if (pEnv->IsExistingCommandLineOption("-perfDataIntervalSec"))
00975 {
00976 perfDataIntervalSec = pEnv->GetCommandLineOptionVal<long>("-perfDataIntervalSec");
00977 }
00978 else
00979 {
00980 if (loopTimeSec <= 15)
00981 {
00982 perfDataIntervalSec = 1;
00983 }
00984 else if (loopTimeSec <= 60)
00985 {
00986 perfDataIntervalSec = 5;
00987 }
00988 else if (loopTimeSec <= 300)
00989 {
00990 perfDataIntervalSec = 10;
00991 }
00992 else if (loopTimeSec < 1800 )
00993 {
00994 perfDataIntervalSec = 30;
00995 }
00996 else
00997 {
00998 perfDataIntervalSec = 60;
00999 }
01000 }
01001 out_loopTimeSec = loopTimeSec;
01002
01003 if (checkPerfData)
01004 {
01005 TestToolBox::Protocol::Get()->Writeln(
01006 TestToolBox::OutputLevel::eREGULAR,
01007 TestToolBox::OutputMode::M_STDOUT,
01008 "\n---- Loop-Execution: now deactivating regular output for the next " + ToString(loopTimeSec) + " seconds...\n");
01009 TestToolBox::Protocol::Get()->SetOutputLevelForStdOut(TestToolBox::OutputLevel::eERROR);
01010 pPerfLogger = new PerformanceLogger (perfDataIntervalSec);
01011 pPerfLogger->CheckPerformance(0, true);
01012 }
01013
01014 return pPerfLogger;
01015
01016 }
01017
01018
01019
01020
01021
01022
01023 TTB_INLINE void Runner::FinishPerformanceLoggingIfRequired (
01024 PerformanceLogger* in_pPerformanceLogger)
01025 {
01026 if (in_pPerformanceLogger)
01027 {
01028 TestToolBox::Protocol::Get()->SetOutputLevelForStdOut(
01029 TestToolBox::OutputLevel::eREGULAR);
01030 TestToolBox::Protocol::Get()->Writeln(
01031 TestToolBox::OutputLevel::eREGULAR,
01032 TestToolBox::OutputMode::M_STDOUT,
01033 "\n---- Loop-Execution: ...output is activated again\n");
01034
01035 delete in_pPerformanceLogger;
01036 }
01037
01038 }
01039
01040
01041
01042
01043
01044
01045
01046 #pragma warning(disable: 4073) // Initialisierungen stehen im Initialisierungsbereich einer Bibliothek
01047 #pragma init_seg(lib) // create before other objects
01048
01049
01050 class AutoMemCheck
01051 {
01052 public:
01053 AutoMemCheck(void)
01054 : m_checkForMemLeaks (false)
01055 {
01056 TRCF("AutoMemCheck");
01057 TRC(TL_DEBUG, "Constructor");
01058
01059
01060 _CrtMemCheckpoint(&m_memStateStartup);
01061
01062
01063 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
01064 _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
01065 _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
01066 _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
01067 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
01068 _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
01069
01070
01071 TestToolBox::Environment* pEnv = TestToolBox::TheEnvironment();
01072 int allocNum = pEnv->GetCommandLineOptionVal<int>("-breakAtMemAlloc");
01073 if (allocNum!=0)
01074 {
01075 TRC(TL_DEBUG, "TRYING TO BREAK AT MEMORY ALLOCATION %d", allocNum);
01076 _CrtSetBreakAlloc(allocNum);
01077 }
01078
01079
01080 if (!pEnv->IsExistingCommandLineOption("-checkForMemLeaks"))
01081 {
01082
01083 m_checkForMemLeaks = true;
01084 }
01085 std::string checkMode = pEnv->GetCommandLineOption("-checkForMemLeaks");
01086 if (checkMode.find("AT_SHUTDOWN")!=checkMode.npos)
01087 {
01088 TRC(TL_DEBUG, "Checking for memleaks when shutting down was activated");
01089 m_checkForMemLeaks = true;
01090 }
01091 if (checkMode.find("CRT_CONTROLLED")!=checkMode.npos)
01092 {
01093 SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
01094 }
01095
01096 if ( (pEnv->IsExistingCommandLineOption("-?"))
01097 || (pEnv->IsExistingCommandLineOption("-help")))
01098 {
01099
01100 m_checkForMemLeaks = false;
01101 }
01102 }
01103
01104 ~AutoMemCheck( )
01105 {
01106 TRCF("~AutoMemCheck");
01107 TRC(TL_DEBUG, "Destructor");
01108
01109 if (m_checkForMemLeaks)
01110 {
01111 #ifdef _DEBUG
01112
01113 _CrtMemState memStateShutdown,diffState;
01114 #endif
01115 _CrtMemCheckpoint(&memStateShutdown);
01116 if (_CrtMemDifference(&diffState,&m_memStateStartup,&memStateShutdown))
01117 {
01118 TRC(TL_DEBUG, "ERROR: Detected memory leaks when shutting down (see below)");
01119 std::cout << "ERROR: memory leaks detected when shutting down (TTB::AutoMemCheck destructor, see below)!\n";
01120
01121 _CrtMemDumpAllObjectsSince(&m_memStateStartup);
01122
01123
01124
01125 abort();
01126 }
01127 }
01128 }
01129 private:
01130
01131 _CrtMemState m_memStateStartup;
01132 bool m_checkForMemLeaks;
01133
01134 };
01135 #pragma warning(default: 4073) // restore the warning
01136
01137
01138 static AutoMemCheck g_AutoMemCheck;
01139
01140
01141
01142
01143
01144
01145 namespace ShortNames
01146 {
01147
01148 TTB_INLINE void Act (const char* in_actualEvent, ...)
01149 {
01150 UTIL_GET_FORMATTED_LINE_NO_NEWLINE (in_actualEvent);
01151 TestEvents::Get()->Act(formattedLine);
01152
01153 }
01154
01155
01156
01157
01158
01159
01160 TTB_INLINE void ReportStoredErrors (void)
01161 {
01162 MyErrorEvents::Get()->ReportStoredErrors();
01163
01164 }
01165
01166
01167
01168 TTB_INLINE void DeleteStoredErrors (void)
01169 {
01170 MyErrorEvents::Get()->DeleteStoredErrors();
01171
01172 }
01173
01174
01175
01176 TTB_INLINE void SetIgnoreError (
01177 long in_errorMsgNum,
01178 bool in_ignore)
01179 {
01180 MyErrorEvents::Get()->SetNotificationActionForErrorMsgNum(
01181 in_errorMsgNum, in_ignore ? ACTION_IGNORE : ACTION_NOT_SPECIFIED);
01182
01183 }
01184
01185
01186
01187 TTB_INLINE void IgnoreErrorContainingTextPattern(
01188 std::string const & in_text)
01189 {
01190 MyErrorEvents::Get()->IgnoreErrorContainingTextPattern(in_text);
01191
01192 }
01193
01194
01195
01196 TTB_INLINE void ClearStoredErrorTextPatterns (void)
01197 {
01198 MyErrorEvents::Get()->ClearStoredTextPatterns();
01199
01200 }
01201
01202
01203
01204 TTB_INLINE void SetErrorSync (
01205 bool in_syncOnError)
01206 {
01207 MyErrorEvents::Get()->SetErrorSync(in_syncOnError);
01208
01209 }
01210
01211
01212
01213 TTB_INLINE void SetImmediateErrorLog (
01214 bool in_immediateLog)
01215 {
01216 MyErrorEvents::Get()->SetImmediateErrorLog(in_immediateLog);
01217
01218 }
01219
01220
01221
01222
01223 TTB_INLINE bool ErrorOk (
01224 long in_extErrorId)
01225 {
01226 return MyErrorEvents::Get()->ErrorOk(in_extErrorId);
01227
01228 }
01229
01230
01231
01232
01233
01234 };
01235
01236 };
01237
01238 #pragma warning( pop )
01239
01240
01241