refs #4452 / refs #11705 - improved `--showtime=` behavior and testing (#4876)

This is a step onto leveraging the `ThreadExecutor` implementation for
`ProcessExecutor` which is a follow-up to #4870. We need to have the
proper test coverage and the existing implementations working as
expected before we move to the shared code.

Fixes:
- added `--showtime=` tests for all executor implementations
- only print `--showtime=summary` once at the end
- prevents `--showtime=` by multiple threads to be written at the same
time - essentially breaking the output
- reset the timer results before each test
- deprecated `top5` in favor of `top5_file`
- fixed printing for all executors except `ProcessExecutor`
This commit is contained in:
Oliver Stöneberg 2023-10-05 19:04:06 +02:00 committed by GitHub
parent f1f740883f
commit fc700b68eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 453 additions and 52 deletions

View File

@ -384,10 +384,6 @@ jobs:
env: env:
STRICT: 1 STRICT: 1
- name: Run showtimetop5 tests
run: |
./tools/test_showtimetop5.sh
- name: Run --dump test - name: Run --dump test
run: | run: |
./cppcheck test/testpreprocessor.cpp --dump ./cppcheck test/testpreprocessor.cpp --dump
@ -470,7 +466,7 @@ jobs:
- name: Self check - name: Self check
run: | run: |
selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5 -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings --check-level=exhaustive" selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5_summary -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings --check-level=exhaustive"
ec=0 ec=0
# TODO: add --check-config # TODO: add --check-config

View File

@ -89,7 +89,7 @@ jobs:
- name: Self check - name: Self check
if: false if: false
run: | run: |
selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5 -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=cppcheck-lib --library=gnu -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings" selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5_summary -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=cppcheck-lib --library=gnu -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings"
ec=0 ec=0
./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json cli lib || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json cli lib || ec=1
./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1

View File

@ -89,7 +89,7 @@ jobs:
- name: Self check - name: Self check
if: false if: false
run: | run: |
selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5 -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=0 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings" selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5_summary -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=0 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings"
ec=0 ec=0
./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json -DCHECK_INTERNAL cli lib || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json -DCHECK_INTERNAL cli lib || ec=1
./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1

View File

@ -85,7 +85,7 @@ jobs:
# TODO: only fail the step on sanitizer issues - since we use processes it will only fail the underlying process which will result in an cppcheckError # TODO: only fail the step on sanitizer issues - since we use processes it will only fail the underlying process which will result in an cppcheckError
- name: Self check - name: Self check
run: | run: |
selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5 -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings" selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5_summary -D__CPPCHECK__ -D__GNUC__ -DCHECK_INTERNAL -DHAVE_RULES --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings"
ec=0 ec=0
./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json cli lib || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options --addon=naming.json cli lib || ec=1
./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1

View File

@ -664,19 +664,19 @@ cli/filelister.o: cli/filelister.cpp cli/filelister.h lib/config.h lib/path.h li
cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/main.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/main.cpp
cli/processexecutor.o: cli/processexecutor.cpp cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h cli/processexecutor.o: cli/processexecutor.cpp cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/processexecutor.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/processexecutor.cpp
cli/singleexecutor.o: cli/singleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h cli/singleexecutor.o: cli/singleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/singleexecutor.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/singleexecutor.cpp
cli/stacktrace.o: cli/stacktrace.cpp cli/stacktrace.h lib/config.h lib/utils.h cli/stacktrace.o: cli/stacktrace.cpp cli/stacktrace.h lib/config.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/stacktrace.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/stacktrace.cpp
cli/threadexecutor.o: cli/threadexecutor.cpp cli/cppcheckexecutor.h cli/executor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h cli/threadexecutor.o: cli/threadexecutor.cpp cli/cppcheckexecutor.h cli/executor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/threadexecutor.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/threadexecutor.cpp
test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h test/options.h test/redirect.h test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h test/options.h test/redirect.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/fixture.cpp $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/fixture.cpp
test/helpers.o: test/helpers.cpp cli/filelister.h externals/simplecpp/simplecpp.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/helpers.h test/helpers.o: test/helpers.cpp cli/filelister.h externals/simplecpp/simplecpp.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/helpers.h

View File

@ -817,12 +817,22 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL; mSettings.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL;
else if (showtimeMode == "summary") else if (showtimeMode == "summary")
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY; mSettings.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY;
else if (showtimeMode == "top5") else if (showtimeMode == "top5") {
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5; mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE;
else if (showtimeMode.empty()) mLogger.printMessage("--showtime=top5 is deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.");
}
else if (showtimeMode == "top5_file")
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE;
else if (showtimeMode == "top5_summary")
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY;
else if (showtimeMode == "none")
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE; mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE;
else if (showtimeMode.empty()) {
mLogger.printError("no mode provided for --showtime");
return false;
}
else { else {
mLogger.printError("unrecognized showtime mode: \"" + showtimeMode + "\". Supported modes: file, file-total, summary, top5."); mLogger.printError("unrecognized --showtime mode: '" + showtimeMode + "'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary.");
return false; return false;
} }
} }
@ -1268,6 +1278,22 @@ void CmdLineParser::printHelp()
" --rule-file=<file> Use given rule file. For more information, see:\n" " --rule-file=<file> Use given rule file. For more information, see:\n"
" http://sourceforge.net/projects/cppcheck/files/Articles/\n" " http://sourceforge.net/projects/cppcheck/files/Articles/\n"
#endif #endif
" --showtime=<mode> Show timing information.\n"
" The available modes are:\n"
" * none\n"
" Show nothing (default)\n"
" * file\n"
" Show for each processed file\n"
" * file-total\n"
" Show total time only for each processed file\n"
" * summary\n"
" Show a summary at the end\n"
" * top5_file\n"
" Show the top 5 for each processed file\n"
" * top5_summary\n"
" Show the top 5 summary at the end\n"
" * top5\n"
" Alias for top5_file (deprecated)\n"
" --std=<id> Set standard.\n" " --std=<id> Set standard.\n"
" The available options are:\n" " The available options are:\n"
" * c89\n" " * c89\n"

View File

@ -28,6 +28,7 @@
#include "importproject.h" #include "importproject.h"
#include "settings.h" #include "settings.h"
#include "suppressions.h" #include "suppressions.h"
#include "timer.h"
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
@ -375,6 +376,9 @@ unsigned int ProcessExecutor::check()
} }
} }
// TODO: wee need to get the timing information from the subprocess
if (mSettings.showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY || mSettings.showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)
CppCheck::printTimerResults(mSettings.showtime);
return result; return result;
} }

View File

@ -22,6 +22,7 @@
#include "importproject.h" #include "importproject.h"
#include "library.h" #include "library.h"
#include "settings.h" #include "settings.h"
#include "timer.h"
#include <cassert> #include <cassert>
#include <list> #include <list>
@ -110,5 +111,8 @@ unsigned int SingleExecutor::check()
if (mCppcheck.analyseWholeProgram()) if (mCppcheck.analyseWholeProgram())
result++; result++;
if (mSettings.showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY || mSettings.showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)
CppCheck::printTimerResults(mSettings.showtime);
return result; return result;
} }

View File

@ -24,6 +24,7 @@
#include "errorlogger.h" #include "errorlogger.h"
#include "importproject.h" #include "importproject.h"
#include "settings.h" #include "settings.h"
#include "timer.h"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -191,7 +192,12 @@ unsigned int ThreadExecutor::check()
} }
} }
return std::accumulate(threadFutures.begin(), threadFutures.end(), 0U, [](unsigned int v, std::future<unsigned int>& f) { unsigned int result = std::accumulate(threadFutures.begin(), threadFutures.end(), 0U, [](unsigned int v, std::future<unsigned int>& f) {
return v + f.get(); return v + f.get();
}); });
if (mSettings.showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY || mSettings.showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)
CppCheck::printTimerResults(mSettings.showtime);
return result;
} }

View File

@ -468,7 +468,6 @@ CppCheck::~CppCheck()
delete mFileInfo.back(); delete mFileInfo.back();
mFileInfo.pop_back(); mFileInfo.pop_back();
} }
s_timerResults.showResults(mSettings.showtime);
if (mPlistFile.is_open()) { if (mPlistFile.is_open()) {
mPlistFile << ErrorLogger::plistFooter(); mPlistFile << ErrorLogger::plistFooter();
@ -1101,6 +1100,9 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
mErrorList.clear(); mErrorList.clear();
if (mSettings.showtime == SHOWTIME_MODES::SHOWTIME_FILE || mSettings.showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE)
printTimerResults(mSettings.showtime);
return mExitCode; return mExitCode;
} }
@ -1904,3 +1906,14 @@ void CppCheck::removeCtuInfoFiles(const std::map<std::string, std::size_t> &file
} }
} }
} }
// cppcheck-suppress unusedFunction - only used in tests
void CppCheck::resetTimerResults()
{
s_timerResults.reset();
}
void CppCheck::printTimerResults(SHOWTIME_MODES mode)
{
s_timerResults.showResults(mode);
}

View File

@ -143,6 +143,9 @@ public:
/** Remove *.ctu-info files */ /** Remove *.ctu-info files */
void removeCtuInfoFiles(const std::map<std::string, std::size_t>& files); // cppcheck-suppress functionConst // has side effects void removeCtuInfoFiles(const std::map<std::string, std::size_t>& files); // cppcheck-suppress functionConst // has side effects
static void resetTimerResults();
static void printTimerResults(SHOWTIME_MODES mode);
private: private:
#ifdef HAVE_RULES #ifdef HAVE_RULES
/** Are there "simple" rules */ /** Are there "simple" rules */

View File

@ -24,13 +24,6 @@
#include <iostream> #include <iostream>
#include <utility> #include <utility>
#include <vector> #include <vector>
/*
TODO:
- rename "file" to "single"
- add unit tests
- for --showtime (needs input file)
- for Timer* classes
*/
namespace { namespace {
using dataElementType = std::pair<std::string, struct TimerResultsData>; using dataElementType = std::pair<std::string, struct TimerResultsData>;
@ -38,24 +31,34 @@ namespace {
{ {
return lhs.second.seconds() > rhs.second.seconds(); return lhs.second.seconds() > rhs.second.seconds();
} }
// TODO: remove and print through (synchronized) ErrorLogger instead
std::mutex stdCoutLock;
} }
// TODO: this does not include any file context when SHOWTIME_FILE thus rendering it useless - should we include the logging with the progress logging?
// that could also get rid of the broader locking
void TimerResults::showResults(SHOWTIME_MODES mode) const void TimerResults::showResults(SHOWTIME_MODES mode) const
{ {
if (mode == SHOWTIME_MODES::SHOWTIME_NONE || mode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) if (mode == SHOWTIME_MODES::SHOWTIME_NONE || mode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL)
return; return;
std::cout << std::endl;
TimerResultsData overallData; TimerResultsData overallData;
std::vector<dataElementType> data; std::vector<dataElementType> data;
{ {
std::lock_guard<std::mutex> l(mResultsSync); std::lock_guard<std::mutex> l(mResultsSync);
data.reserve(mResults.size()); data.reserve(mResults.size());
data.insert(data.begin(), mResults.cbegin(), mResults.cend()); data.insert(data.begin(), mResults.cbegin(), mResults.cend());
} }
std::sort(data.begin(), data.end(), more_second_sec); std::sort(data.begin(), data.end(), more_second_sec);
// lock the whole logging operation to avoid multiple threads printing their results at the same time
std::lock_guard<std::mutex> l(stdCoutLock);
std::cout << std::endl;
size_t ordinal = 1; // maybe it would be nice to have an ordinal in output later! size_t ordinal = 1; // maybe it would be nice to have an ordinal in output later!
for (std::vector<dataElementType>::const_iterator iter=data.cbegin(); iter!=data.cend(); ++iter) { for (std::vector<dataElementType>::const_iterator iter=data.cbegin(); iter!=data.cend(); ++iter) {
const double sec = iter->second.seconds(); const double sec = iter->second.seconds();
@ -75,7 +78,7 @@ void TimerResults::showResults(SHOWTIME_MODES mode) const
} }
if (!hasParent) if (!hasParent)
overallData.mClocks += iter->second.mClocks; overallData.mClocks += iter->second.mClocks;
if ((mode != SHOWTIME_MODES::SHOWTIME_TOP5) || (ordinal<=5)) { if ((mode != SHOWTIME_MODES::SHOWTIME_TOP5_FILE && mode != SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY) || (ordinal<=5)) {
std::cout << iter->first << ": " << sec << "s (avg. " << secAverage << "s - " << iter->second.mNumberOfResults << " result(s))" << std::endl; std::cout << iter->first << ": " << sec << "s (avg. " << secAverage << "s - " << iter->second.mNumberOfResults << " result(s))" << std::endl;
} }
++ordinal; ++ordinal;
@ -93,6 +96,12 @@ void TimerResults::addResults(const std::string& str, std::clock_t clocks)
mResults[str].mNumberOfResults++; mResults[str].mNumberOfResults++;
} }
void TimerResults::reset()
{
std::lock_guard<std::mutex> l(mResultsSync);
mResults.clear();
}
Timer::Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf* timerResults) Timer::Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf* timerResults)
: mStr(std::move(str)) : mStr(std::move(str))
, mTimerResults(timerResults) , mTimerResults(timerResults)
@ -119,9 +128,11 @@ void Timer::stop()
if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE) { if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE) {
const double sec = (double)diff / CLOCKS_PER_SEC; const double sec = (double)diff / CLOCKS_PER_SEC;
std::lock_guard<std::mutex> l(stdCoutLock);
std::cout << mStr << ": " << sec << "s" << std::endl; std::cout << mStr << ": " << sec << "s" << std::endl;
} else if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) { } else if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) {
const double sec = (double)diff / CLOCKS_PER_SEC; const double sec = (double)diff / CLOCKS_PER_SEC;
std::lock_guard<std::mutex> l(stdCoutLock);
std::cout << "Check time: " << mStr << ": " << sec << "s" << std::endl; std::cout << "Check time: " << mStr << ": " << sec << "s" << std::endl;
} else { } else {
if (mTimerResults) if (mTimerResults)

View File

@ -32,7 +32,8 @@ enum class SHOWTIME_MODES {
SHOWTIME_FILE, SHOWTIME_FILE,
SHOWTIME_FILE_TOTAL, SHOWTIME_FILE_TOTAL,
SHOWTIME_SUMMARY, SHOWTIME_SUMMARY,
SHOWTIME_TOP5 SHOWTIME_TOP5_SUMMARY,
SHOWTIME_TOP5_FILE
}; };
class CPPCHECKLIB TimerResultsIntf { class CPPCHECKLIB TimerResultsIntf {
@ -59,6 +60,8 @@ public:
void showResults(SHOWTIME_MODES mode) const; void showResults(SHOWTIME_MODES mode) const;
void addResults(const std::string& str, std::clock_t clocks) override; void addResults(const std::string& str, std::clock_t clocks) override;
void reset();
private: private:
std::map<std::string, struct TimerResultsData> mResults; std::map<std::string, struct TimerResultsData> mResults;
mutable std::mutex mResultsSync; mutable std::mutex mResultsSync;

View File

@ -189,6 +189,9 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<arg choice="opt"> <arg choice="opt">
<option>--rule-file=&lt;file&gt;</option> <option>--rule-file=&lt;file&gt;</option>
</arg> </arg>
<arg choice="opt">
<option>--showtime=&lt;mode&gt;</option>
</arg>
<arg choice="opt"> <arg choice="opt">
<option>--std=&lt;id&gt;</option> <option>--std=&lt;id&gt;</option>
</arg> </arg>
@ -543,6 +546,16 @@ There are false positives with this option. Each result must be carefully invest
<para>Use given rule XML file. See https://sourceforge.net/projects/cppcheck/files/Articles/ for more info about the syntax. This command is only available if cppcheck was compiled with HAVE_RULES=yes.</para> <para>Use given rule XML file. See https://sourceforge.net/projects/cppcheck/files/Articles/ for more info about the syntax. This command is only available if cppcheck was compiled with HAVE_RULES=yes.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>--showtime=&lt;mode&gt;</option>
</term>
<listitem>
<para>Show timing information. The available mode are:
<glosslist><glossentry><glossterm>none</glossterm><glossdef><para>Show nothing (default)</para></glossdef></glossentry><glossentry><glossterm>file</glossterm><glossdef><para>Show for each processed file</para></glossdef></glossentry><glossentry><glossterm>file-total</glossterm><glossdef><para>Show total time only for each processed file</para></glossdef></glossentry><glossentry><glossterm>summary</glossterm><glossdef><para>Show a summary at the end</para></glossdef></glossentry><glossentry><glossterm>top5_file</glossterm><glossdef><para>Show the top 5 for each processed file</para></glossdef></glossentry><glossentry><glossterm>top5_summary</glossterm><glossdef><para>Show the top 5 summary at the end</para></glossdef></glossentry><glossentry><glossterm>top5</glossterm><glossdef><para>Alias for top5_file (deprecated)</para></glossdef></glossentry></glosslist>
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>--std=&lt;id&gt;</option> <option>--std=&lt;id&gt;</option>

View File

@ -12,6 +12,11 @@ GUI:
Changed interface: Changed interface:
- -
Deprecations:
- "--showtime=top5" has been deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.
Other: Other:
- Windows builds now default to the `native` platform instead of `win32A` or `win64`. Please specify it explicitly if you depedent on it. - Windows builds now default to the `native` platform instead of `win32A` or `win64`. Please specify it explicitly if you depedent on it.
- The undocumented and deprecated command-line options `--template <template>` and `--template-format <template>` has been removed. Please use `--template=` and `--template-format=` instead. - The undocumented and deprecated command-line options `--template <template>` and `--template-format <template>` has been removed. Please use `--template=` and `--template-format=` instead.
- "--showtime=summary" will now show a single summary at the end instead of showing it after each file when using the thread execution (default on Windows)
- added "--showtime=none" to disable any previously specified showtime report. "--showtime=" without parameter is no longer valid.

View File

@ -531,3 +531,26 @@ def test_unused_function_include(tmpdir):
_, _, stderr = cppcheck(args) _, _, stderr = cppcheck(args)
assert stderr == "{}:4:0: style: The function 'f' is never used. [unusedFunction]\n".format(test_h_file) assert stderr == "{}:4:0: style: The function 'f' is never used. [unusedFunction]\n".format(test_h_file)
# TODO: test with -j and all other types
def test_showtime_top5_file(tmpdir):
test_file = os.path.join(tmpdir, 'test.cpp')
with open(test_file, 'wt') as f:
f.write("""
int main(int argc)
{
}
""")
args = ['--showtime=top5_file', '--quiet', test_file]
exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0 # TODO: needs to be 1
lines = stdout.splitlines()
assert len(lines) == 7
assert lines[0] == ''
for i in range(1, 5):
assert lines[i].endswith(' - 1 result(s))')
assert lines[6].startswith('Overall time:')
assert stderr == ''

View File

@ -18,6 +18,7 @@
#include "fixture.h" #include "fixture.h"
#include "cppcheck.h"
#include "errortypes.h" #include "errortypes.h"
#include "options.h" #include "options.h"
#include "redirect.h" #include "redirect.h"
@ -90,6 +91,7 @@ bool TestFixture::prepareTest(const char testname[])
mVerbose = false; mVerbose = false;
mTemplateFormat.clear(); mTemplateFormat.clear();
mTemplateLocation.clear(); mTemplateLocation.clear();
CppCheck::resetTimerResults();
prepareTestInternal(); prepareTestInternal();

View File

@ -92,6 +92,19 @@ public:
static std::string getcode(Preprocessor &preprocessor, const std::string &filedata, const std::string &cfg, const std::string &filename, Suppressions *inlineSuppression = nullptr); static std::string getcode(Preprocessor &preprocessor, const std::string &filedata, const std::string &cfg, const std::string &filename, Suppressions *inlineSuppression = nullptr);
}; };
namespace cppcheck {
template<typename T>
std::size_t count_all_of(const std::string& str, T sub) {
std::size_t n = 0;
std::string::size_type pos = 0;
while ((pos = str.find(sub, pos)) != std::string::npos) {
++pos;
++n;
}
return n;
}
}
/* designated initialization helper /* designated initialization helper
Usage: Usage:
struct S struct S

View File

@ -234,7 +234,14 @@ private:
TEST_CASE(xmlverunknown); TEST_CASE(xmlverunknown);
TEST_CASE(xmlverinvalid); TEST_CASE(xmlverinvalid);
TEST_CASE(doc); TEST_CASE(doc);
TEST_CASE(showtime); TEST_CASE(showtimeFile);
TEST_CASE(showtimeFileTotal);
TEST_CASE(showtimeTop5);
TEST_CASE(showtimeTop5File);
TEST_CASE(showtimeTop5Summary);
TEST_CASE(showtimeNone);
TEST_CASE(showtimeEmpty);
TEST_CASE(showtimeInvalid);
TEST_CASE(errorlist1); TEST_CASE(errorlist1);
TEST_CASE(errorlistverbose1); TEST_CASE(errorlistverbose1);
TEST_CASE(errorlistverbose2); TEST_CASE(errorlistverbose2);
@ -1569,7 +1576,7 @@ private:
ASSERT_EQUALS("", logger->str()); ASSERT_EQUALS("", logger->str());
} }
void showtime() { void showtimeSummary() {
REDIRECT; REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"}; const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
@ -1578,6 +1585,74 @@ private:
ASSERT_EQUALS("", logger->str()); ASSERT_EQUALS("", logger->str());
} }
void showtimeFile() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=file", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE);
ASSERT_EQUALS("", logger->str());
}
void showtimeFileTotal() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=file-total", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL);
ASSERT_EQUALS("", logger->str());
}
void showtimeTop5() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=top5", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE);
ASSERT_EQUALS("cppcheck: --showtime=top5 is deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.\n", logger->str());
}
void showtimeTop5File() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=top5_file", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE);
ASSERT_EQUALS("", logger->str());
}
void showtimeTop5Summary() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=top5_summary", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY);
ASSERT_EQUALS("", logger->str());
}
void showtimeNone() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=none", "file.cpp"};
settings->showtime = SHOWTIME_MODES::SHOWTIME_FILE;
ASSERT(parser->parseFromArgs(3, argv));
ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_NONE);
ASSERT_EQUALS("", logger->str());
}
void showtimeEmpty() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: no mode provided for --showtime\n", logger->str());
}
void showtimeInvalid() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--showtime=top10", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: unrecognized --showtime mode: 'top10'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary.\n", logger->str());
}
void errorlist1() { void errorlist1() {
REDIRECT; REDIRECT;
const char * const argv[] = {"cppcheck", "--errorlist"}; const char * const argv[] = {"cppcheck", "--errorlist"};

View File

@ -49,6 +49,7 @@ private:
struct CheckOptions struct CheckOptions
{ {
CheckOptions() = default; CheckOptions() = default;
bool quiet = true;
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr; const char* plistOutput = nullptr;
std::vector<std::string> filesList; std::vector<std::string> filesList;
@ -80,6 +81,7 @@ private:
Settings s = settings; Settings s = settings;
s.jobs = jobs; s.jobs = jobs;
s.showtime = opt.showtime; s.showtime = opt.showtime;
settings.quiet = opt.quiet;
if (opt.plistOutput) if (opt.plistOutput)
s.plistOutput = opt.plistOutput; s.plistOutput = opt.plistOutput;
// TODO: test with settings.project.fileSettings; // TODO: test with settings.project.fileSettings;
@ -104,6 +106,11 @@ private:
TEST_CASE(one_error_less_files); TEST_CASE(one_error_less_files);
TEST_CASE(one_error_several_files); TEST_CASE(one_error_several_files);
TEST_CASE(markup); TEST_CASE(markup);
TEST_CASE(showtime_top5_file);
TEST_CASE(showtime_top5_summary);
TEST_CASE(showtime_file);
TEST_CASE(showtime_summary);
TEST_CASE(showtime_file_total);
#endif // !WIN32 #endif // !WIN32
} }
@ -119,6 +126,7 @@ private:
check(2, 3, 3, oss.str()); check(2, 3, 3, oss.str());
} }
// TODO: check the output
void many_threads() { void many_threads() {
check(16, 100, 100, check(16, 100, 100,
"int main()\n" "int main()\n"
@ -209,7 +217,9 @@ private:
" char *a = malloc(10);\n" " char *a = malloc(10);\n"
" return 0;\n" " return 0;\n"
"}", "}",
dinit(CheckOptions, $.filesList = files)); dinit(CheckOptions,
$.quiet = false,
$.filesList = files));
// TODO: order of "Checking" and "checked" is affected by thread // TODO: order of "Checking" and "checked" is affected by thread
/*TODO_ASSERT_EQUALS("Checking " + fprefix() + "_2.cpp ...\n" /*TODO_ASSERT_EQUALS("Checking " + fprefix() + "_2.cpp ...\n"
"1/4 files checked 25% done\n" "1/4 files checked 25% done\n"
@ -231,6 +241,68 @@ private:
settings = settingsOld; settings = settingsOld;
} }
// TODO: provide data which actually shows values above 0
// TODO: should this be logged only once like summary?
void showtime_top5_file() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE));
// for each file: top5 results + overall + empty line
const std::string output_s = GET_REDIRECT_OUTPUT;
// for each file: top5 results + overall + empty line
TODO_ASSERT_EQUALS(static_cast<long long>(5 + 1 + 1) * 2, 0, cppcheck::count_all_of(output_s, '\n'));
}
void showtime_top5_summary() {
REDIRECT;
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// once: top5 results + overall + empty line
TODO_ASSERT_EQUALS(5 + 1 + 1, 2, cppcheck::count_all_of(output_s, '\n'));
// should only report the top5 once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
TODO_ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE));
const std::string output_s = GET_REDIRECT_OUTPUT;
TODO_ASSERT_EQUALS(2, 0, cppcheck::count_all_of(output_s, "Overall time:"));
}
void showtime_summary() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// should only report the actual summary once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
TODO_ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file_total() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL));
const std::string output_s = GET_REDIRECT_OUTPUT;
TODO_ASSERT(output_s.find("Check time: " + fprefix() + "_1.cpp: ") != std::string::npos);
TODO_ASSERT(output_s.find("Check time: " + fprefix() + "_2.cpp: ") != std::string::npos);
}
// TODO: test clang-tidy // TODO: test clang-tidy
// TODO: test whole program analysis // TODO: test whole program analysis
}; };

View File

@ -64,6 +64,7 @@ private:
struct CheckOptions struct CheckOptions
{ {
CheckOptions() = default; CheckOptions() = default;
bool quiet = true;
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr; const char* plistOutput = nullptr;
std::vector<std::string> filesList; std::vector<std::string> filesList;
@ -102,6 +103,7 @@ private:
} }
settings.showtime = opt.showtime; settings.showtime = opt.showtime;
settings.quiet = opt.quiet;
if (opt.plistOutput) if (opt.plistOutput)
settings.plistOutput = opt.plistOutput; settings.plistOutput = opt.plistOutput;
@ -149,26 +151,27 @@ private:
TEST_CASE(one_error_several_files); TEST_CASE(one_error_several_files);
TEST_CASE(markup); TEST_CASE(markup);
TEST_CASE(clangTidy); TEST_CASE(clangTidy);
TEST_CASE(showtime_top5_file);
TEST_CASE(showtime_top5_summary);
TEST_CASE(showtime_file);
TEST_CASE(showtime_summary);
TEST_CASE(showtime_file_total);
} }
void many_files() { void many_files() {
const Settings settingsOld = settings;
settings.quiet = false;
check(100, 100, check(100, 100,
"int main()\n" "int main()\n"
"{\n" "{\n"
" char *a = malloc(10);\n" " char *a = malloc(10);\n"
" return 0;\n" " return 0;\n"
"}"); "}", dinit(CheckOptions,
$.quiet = false));
std::string expected; std::string expected;
for (int i = 1; i <= 100; ++i) { for (int i = 1; i <= 100; ++i) {
expected += "Checking " + fprefix() + "_" + zpad3(i) + ".cpp ...\n"; expected += "Checking " + fprefix() + "_" + zpad3(i) + ".cpp ...\n";
expected += std::to_string(i) + "/100 files checked " + std::to_string(i) + "% done\n"; expected += std::to_string(i) + "/100 files checked " + std::to_string(i) + "% done\n";
} }
ASSERT_EQUALS(expected, output.str()); ASSERT_EQUALS(expected, output.str());
settings = settingsOld;
} }
void many_files_showtime() { void many_files_showtime() {
@ -251,7 +254,9 @@ private:
" char *a = malloc(10);\n" " char *a = malloc(10);\n"
" return 0;\n" " return 0;\n"
"}", "}",
dinit(CheckOptions, $.filesList = files)); dinit(CheckOptions,
$.quiet = false,
$.filesList = files));
// TODO: filter out the "files checked" messages // TODO: filter out the "files checked" messages
ASSERT_EQUALS("Checking " + fprefix() + "_2.cpp ...\n" ASSERT_EQUALS("Checking " + fprefix() + "_2.cpp ...\n"
"1/4 files checked 25% done\n" "1/4 files checked 25% done\n"
@ -285,13 +290,74 @@ private:
" return 0;\n" " return 0;\n"
"}", "}",
dinit(CheckOptions, dinit(CheckOptions,
$.executeCommandCalled = true, $.quiet = false,
$.executeCommandCalled = true,
$.exe = exe, $.exe = exe,
$.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"})); $.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"}));
ASSERT_EQUALS("Checking " + file + " ...\n", output.str()); ASSERT_EQUALS("Checking " + file + " ...\n", output.str());
settings = settingsOld; settings = settingsOld;
} }
// TODO: provide data which actually shows values above 0
void showtime_top5_file() {
REDIRECT;
check(2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE));
const std::string output_s = GET_REDIRECT_OUTPUT;
// for each file: top5 results + overall + empty line
ASSERT_EQUALS((5 + 1 + 1) * 2, cppcheck::count_all_of(output_s, '\n'));
}
void showtime_top5_summary() {
REDIRECT;
check(2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// once: top5 results + overall + empty line
ASSERT_EQUALS(5 + 1 + 1, cppcheck::count_all_of(output_s, '\n'));
// should only report the top5 once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file() {
REDIRECT;
check(2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE));
const std::string output_s = GET_REDIRECT_OUTPUT;
ASSERT_EQUALS(2, cppcheck::count_all_of(output_s, "Overall time:"));
}
void showtime_summary() {
REDIRECT;
check(2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// should only report the actual summary once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file_total() {
REDIRECT;
check(2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL));
const std::string output_s = GET_REDIRECT_OUTPUT;
ASSERT(output_s.find("Check time: " + fprefix() + "_" + zpad3(1) + ".cpp: ") != std::string::npos);
ASSERT(output_s.find("Check time: " + fprefix() + "_" + zpad3(2) + ".cpp: ") != std::string::npos);
}
// TODO: test whole program analysis // TODO: test whole program analysis
}; };

View File

@ -49,6 +49,7 @@ private:
struct CheckOptions struct CheckOptions
{ {
CheckOptions() = default; CheckOptions() = default;
bool quiet = true;
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr; const char* plistOutput = nullptr;
std::vector<std::string> filesList; std::vector<std::string> filesList;
@ -80,6 +81,7 @@ private:
Settings settings1 = settings; Settings settings1 = settings;
settings1.jobs = jobs; settings1.jobs = jobs;
settings1.showtime = opt.showtime; settings1.showtime = opt.showtime;
settings1.quiet = opt.quiet;
if (opt.plistOutput) if (opt.plistOutput)
settings1.plistOutput = opt.plistOutput; settings1.plistOutput = opt.plistOutput;
// TODO: test with settings.project.fileSettings; // TODO: test with settings.project.fileSettings;
@ -103,6 +105,11 @@ private:
TEST_CASE(one_error_less_files); TEST_CASE(one_error_less_files);
TEST_CASE(one_error_several_files); TEST_CASE(one_error_several_files);
TEST_CASE(markup); TEST_CASE(markup);
TEST_CASE(showtime_top5_file);
TEST_CASE(showtime_top5_summary);
TEST_CASE(showtime_file);
TEST_CASE(showtime_summary);
TEST_CASE(showtime_file_total);
} }
void deadlock_with_many_errors() { void deadlock_with_many_errors() {
@ -117,6 +124,7 @@ private:
check(2, 3, 3, oss.str()); check(2, 3, 3, oss.str());
} }
// TODO: check the output
void many_threads() { void many_threads() {
check(16, 100, 100, check(16, 100, 100,
"int main()\n" "int main()\n"
@ -134,7 +142,8 @@ private:
"{\n" "{\n"
" char *a = malloc(10);\n" " char *a = malloc(10);\n"
" return 0;\n" " return 0;\n"
"}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); "}", dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
} }
void many_threads_plist() { void many_threads_plist() {
@ -146,7 +155,8 @@ private:
"{\n" "{\n"
" char *a = malloc(10);\n" " char *a = malloc(10);\n"
" return 0;\n" " return 0;\n"
"}", dinit(CheckOptions, $.plistOutput = plistOutput)); "}", dinit(CheckOptions,
$.plistOutput = plistOutput));
} }
void no_errors_more_files() { void no_errors_more_files() {
@ -229,6 +239,69 @@ private:
settings = settingsOld; settings = settingsOld;
} }
// TODO: provide data which actually shows values above 0
// TODO: should this be logged only once like summary?
void showtime_top5_file() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE));
// for each file: top5 results + overall + empty line
const std::string output_s = GET_REDIRECT_OUTPUT;
// for each file: top5 results + overall + empty line
ASSERT_EQUALS((5 + 1 + 1) * 2, cppcheck::count_all_of(output_s, '\n'));
}
void showtime_top5_summary() {
REDIRECT;
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// once: top5 results + overall + empty line
ASSERT_EQUALS(5 + 1 + 1, cppcheck::count_all_of(output_s, '\n'));
// should only report the top5 once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE));
const std::string output_s = GET_REDIRECT_OUTPUT;
ASSERT_EQUALS(2, cppcheck::count_all_of(output_s, "Overall time:"));
}
void showtime_summary() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
const std::string output_s = GET_REDIRECT_OUTPUT;
// should only report the actual summary once
ASSERT(output_s.find("1 result(s)") == std::string::npos);
ASSERT(output_s.find("2 result(s)") != std::string::npos);
}
void showtime_file_total() {
REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized
check(2, 2, 0,
"int main() {}",
dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL));
const std::string output_s = GET_REDIRECT_OUTPUT;
ASSERT(output_s.find("Check time: " + fprefix() + "_1.cpp: ") != std::string::npos);
ASSERT(output_s.find("Check time: " + fprefix() + "_2.cpp: ") != std::string::npos);
}
// TODO: test clang-tidy // TODO: test clang-tidy
// TODO: test whole program analysis // TODO: test whole program analysis
}; };

View File

@ -440,9 +440,10 @@ def scan_package(cppcheck_path, source_path, libraries, capture_callstack=True):
dir_to_scan = source_path dir_to_scan = source_path
# TODO: temporarily disabled timing information - use --showtime=top5_summary when next version is released
# TODO: remove missingInclude disabling when it no longer is implied by --enable=information # TODO: remove missingInclude disabling when it no longer is implied by --enable=information
# Reference for GNU C: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html # Reference for GNU C: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
options = libs + ' --showtime=top5 --check-library --inconclusive --enable=style,information --inline-suppr --disable=missingInclude --suppress=unmatchedSuppression --template=daca2' options = libs + ' --showtime=none --check-library --inconclusive --enable=style,information --inline-suppr --disable=missingInclude --suppress=unmatchedSuppression --template=daca2'
options += ' --debug-warnings --suppress=autoNoType --suppress=valueFlowBailout --suppress=bailoutUninitVar --suppress=symbolDatabaseWarning' options += ' --debug-warnings --suppress=autoNoType --suppress=valueFlowBailout --suppress=bailoutUninitVar --suppress=symbolDatabaseWarning'
options += ' -D__GNUC__ --platform=unix64' options += ' -D__GNUC__ --platform=unix64'
options_rp = options + ' -rp={}'.format(dir_to_scan) options_rp = options + ' -rp={}'.format(dir_to_scan)

View File

@ -1,8 +0,0 @@
#!/bin/bash
# "gwc" is a GNU compatible of "wc" on MacOS
WC_CMD=$(command -v gwc || command -v wc)
output=$(./cppcheck --showtime=top5 cli/cmdlineparser.h --language=c++ --quiet)
echo "$output"
if [[ "$(echo "$output" | $WC_CMD -l)" != 7 ]] ; then
false
fi