From 3a523eec7814dfbed2361da298849a5b5964318a Mon Sep 17 00:00:00 2001 From: Betsy McPhail Date: Fri, 4 Nov 2016 16:51:42 -0400 Subject: ctest_memcheck: Add DEFECT_COUNT option to capture defect count --- Auxiliary/vim/syntax/cmake.vim | 2 +- Help/command/ctest_memcheck.rst | 8 +++++- Help/release/dev/ctest_memcheck_defect_count.rst | 5 ++++ Source/CTest/cmCTestHandlerCommand.cxx | 5 ++++ Source/CTest/cmCTestHandlerCommand.h | 2 ++ Source/CTest/cmCTestMemCheckCommand.cxx | 20 ++++++++++++++ Source/CTest/cmCTestMemCheckCommand.h | 10 ++++++- Source/CTest/cmCTestMemCheckHandler.cxx | 13 +++++++-- Source/CTest/cmCTestMemCheckHandler.h | 3 +++ .../DummyLeakSanitizerPrintDefects-result.txt | 1 + .../DummyLeakSanitizerPrintDefects-stderr.txt | 1 + .../DummyLeakSanitizerPrintDefects-stdout.txt | 3 +++ .../DummyValgrindNoDefects-result.txt | 1 + .../DummyValgrindNoDefects-stderr.txt | 1 + .../DummyValgrindNoDefects-stdout.txt | 6 +++++ Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake | 31 +++++++++++++++++++++- Tests/RunCMake/ctest_memcheck/test.cmake.in | 4 ++- 17 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/ctest_memcheck_defect_count.rst create mode 100644 Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-result.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stderr.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stdout.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-result.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stderr.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 11b0fcb..fabf9c1 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -128,7 +128,7 @@ syn keyword cmakeKWctest_coverage \ contained syn keyword cmakeKWctest_memcheck - \ APPEND BUILD END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD + \ APPEND BUILD DEFECT_COUNT END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD \ contained syn keyword cmakeKWctest_run_script diff --git a/Help/command/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst index 29bdf7d..a983d68 100644 --- a/Help/command/ctest_memcheck.rst +++ b/Help/command/ctest_memcheck.rst @@ -18,6 +18,7 @@ Perform the :ref:`CTest MemCheck Step` as a :ref:`Dashboard Client`. [SCHEDULE_RANDOM ] [STOP_TIME ] [RETURN_VALUE ] + [DEFECT_COUNT ] [QUIET] ) @@ -26,4 +27,9 @@ Run tests with a dynamic analysis tool and store results in ``MemCheck.xml`` for submission with the :command:`ctest_submit` command. -The options are the same as those for the :command:`ctest_test` command. +Most options are the same as those for the :command:`ctest_test` command. + +The options unique to this command are: + +``DEFECT_COUNT `` + Store in the ```` the number of defects found. diff --git a/Help/release/dev/ctest_memcheck_defect_count.rst b/Help/release/dev/ctest_memcheck_defect_count.rst new file mode 100644 index 0000000..70061c1 --- /dev/null +++ b/Help/release/dev/ctest_memcheck_defect_count.rst @@ -0,0 +1,5 @@ +ctest_memcheck_defect_count +--------------------------- + +* The :command:`ctest_memcheck` command gained a ``DEFECT_COUNT `` + option to capture the number of memory defects detected. diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 2e5b56a..a989b12 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -226,6 +226,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], str.str().c_str()); } + this->ProcessAdditionalValues(handler); // log the error message if there was an error if (capureCMakeError) { const char* returnString = "0"; @@ -246,6 +247,10 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, return true; } +void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*) +{ +} + bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg) { // Look for non-value arguments common to all commands. diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index 92748af..c86841f 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -45,6 +45,8 @@ public: protected: virtual cmCTestGenericHandler* InitializeHandler() = 0; + virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler); + // Command argument handling. virtual bool CheckArgumentKeyword(std::string const& arg); virtual bool CheckArgumentValue(std::string const& arg); diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index 05d0a53..5e4c5ae 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -4,6 +4,15 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" +#include "cmCTestMemCheckHandler.h" +#include "cmMakefile.h" + +cmCTestMemCheckCommand::cmCTestMemCheckCommand() +{ + this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT"; + this->Arguments[ctm_LAST] = CM_NULLPTR; + this->Last = ctm_LAST; +} cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() { @@ -28,3 +37,14 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() handler->SetQuiet(this->Quiet); return handler; } + +void cmCTestMemCheckCommand::ProcessAdditionalValues( + cmCTestGenericHandler* handler) +{ + if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) { + std::ostringstream str; + str << static_cast(handler)->GetDefectCount(); + this->Makefile->AddDefinition(this->Values[ctm_DEFECT_COUNT], + str.str().c_str()); + } +} diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 30d9e2b..458ebb0 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -20,7 +20,7 @@ class cmCommand; class cmCTestMemCheckCommand : public cmCTestTestCommand { public: - cmCTestMemCheckCommand() {} + cmCTestMemCheckCommand(); /** * This is a virtual constructor for the command. @@ -40,6 +40,14 @@ public: protected: cmCTestGenericHandler* InitializeActualHandler() CM_OVERRIDE; + + void ProcessAdditionalValues(cmCTestGenericHandler* handler) CM_OVERRIDE; + + enum + { + ctm_DEFECT_COUNT = ctt_LAST, + ctm_LAST + }; }; #endif diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 0052a16..c18e20c 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -127,6 +127,7 @@ void cmCTestMemCheckHandler::Initialize() this->MemoryTesterOptions.clear(); this->MemoryTesterStyle = UNKNOWN; this->MemoryTesterOutputFile = ""; + this->DefectCount = 0; } int cmCTestMemCheckHandler::PreProcessHandler() @@ -279,6 +280,11 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile* mf) this->Quiet); } +int cmCTestMemCheckHandler::GetDefectCount() +{ + return this->DefectCount; +} + void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { @@ -702,6 +708,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput( ostr << *i << std::endl; } log = ostr.str(); + this->DefectCount += defects; return defects == 0; } bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( @@ -743,6 +750,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( } log = ostr.str(); + this->DefectCount += defects; return defects == 0; } @@ -878,6 +886,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( << (cmSystemTools::GetTime() - sttime) << std::endl, this->Quiet); log = ostr.str(); + this->DefectCount += defects; return defects == 0; } @@ -923,9 +932,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( // only put the output of Bounds Checker if there were // errors or leaks detected log = parser.Log; - return false; } - return true; + this->DefectCount += defects; + return defects == 0; } // PostProcessTest memcheck results diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index b12da28..5faace0 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -30,6 +30,8 @@ public: void Initialize() CM_OVERRIDE; + int GetDefectCount(); + protected: int PreProcessHandler() CM_OVERRIDE; int PostProcessHandler() CM_OVERRIDE; @@ -105,6 +107,7 @@ private: std::vector ResultStringsLong; std::vector GlobalResults; bool LogWithPID; // does log file add pid + int DefectCount; std::vector::size_type FindOrAddWarning(const std::string& warning); // initialize the ResultStrings and ResultStringsLong for diff --git a/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-result.txt b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stderr.txt b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stderr.txt new file mode 100644 index 0000000..d4b71ae --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stderr.txt @@ -0,0 +1 @@ +Defect count: 3 diff --git a/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stdout.txt new file mode 100644 index 0000000..97a8a9b --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stdout.txt @@ -0,0 +1,3 @@ +Memory checking results: +Direct leak - 2 +Indirect leak - 1 diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-result.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stderr.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stderr.txt new file mode 100644 index 0000000..ad28645 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stderr.txt @@ -0,0 +1 @@ +Defect count: 0 diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt new file mode 100644 index 0000000..dabb004 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt @@ -0,0 +1,6 @@ +1/1 MemCheck #1: RunCMake \.+ Passed +[0-9]+.[0-9]+ sec + +100% tests passed, 0 tests failed out of 1 +.* +-- Processing memory checking output:( ) +Memory checking results: diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake index 5ad6511..212bfdb 100644 --- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake @@ -12,6 +12,8 @@ endfunction() unset(CTEST_EXTRA_CONFIG) unset(CTEST_EXTRA_CODE) +unset(CTEST_SUFFIX_CODE) +unset(CTEST_MEMCHECK_ARGS) unset(CMAKELISTS_EXTRA_CODE) #----------------------------------------------------------------------------- @@ -132,4 +134,31 @@ run_mc_test(DummyValgrindNoLogFile "${PSEUDO_VALGRIND_NOLOG}") run_mc_test(DummyBCNoLogFile "${PSEUDO_BC_NOLOG}") run_mc_test(NotExist "\${CTEST_BINARY_DIRECTORY}/no-memcheck-exe") run_mc_test(Unknown "\${CMAKE_COMMAND}") -run_mc_test(DummyQuiet "${PSEUDO_VALGRIND}" -DMEMCHECK_ARGS=QUIET) + +#---------------------------------------------------------------------------- +set(CTEST_MEMCHECK_ARGS QUIET) +run_mc_test(DummyQuiet "${PSEUDO_VALGRIND}") +unset(CTEST_MEMCHECK_ARGS) + +#----------------------------------------------------------------------------- +set(CTEST_SUFFIX_CODE "message(\"Defect count: \${defect_count}\")") +set(CTEST_MEMCHECK_ARGS "DEFECT_COUNT defect_count") +run_mc_test(DummyValgrindNoDefects "${PSEUDO_VALGRIND}") +unset(CTEST_MEMCHECK_ARGS) +unset(CTEST_SUFFIX_CODE) + +#----------------------------------------------------------------------------- +set(CTEST_SUFFIX_CODE "message(\"Defect count: \${defect_count}\")") +set(CTEST_MEMCHECK_ARGS "DEFECT_COUNT defect_count") +set(CTEST_EXTRA_CODE +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +") +set(CMAKELISTS_EXTRA_CODE +"add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" +-P \"${RunCMake_SOURCE_DIR}/testLeakSanitizer.cmake\") +") +run_mc_test(DummyLeakSanitizerPrintDefects "" -DMEMCHECK_TYPE=AddressSanitizer) +unset(CMAKELISTS_EXTRA_CODE) +unset(CTEST_EXTRA_CODE) +unset(CTEST_MEMCHECK_ARGS) +unset(CTEST_SUFFIX_CODE) diff --git a/Tests/RunCMake/ctest_memcheck/test.cmake.in b/Tests/RunCMake/ctest_memcheck/test.cmake.in index 8431fa6..50b4b6a 100644 --- a/Tests/RunCMake/ctest_memcheck/test.cmake.in +++ b/Tests/RunCMake/ctest_memcheck/test.cmake.in @@ -21,4 +21,6 @@ set(CTEST_MEMORYCHECK_TYPE "${MEMCHECK_TYPE}") CTEST_START(Experimental) CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res ${MEMCHECK_ARGS}) +CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res @CTEST_MEMCHECK_ARGS@) + +@CTEST_SUFFIX_CODE@ -- cgit v0.12