extracted single job execution into `SingleExecutor` / improved testing / do not unconditionally apply colors to output (#4882)
* added `Settings::useSingleJob()` and use it instead of checking `jobs` or `jointSuppressionReport` * extracted single job execution into `SingleExecutor` * moved `reportStatus()` from `CppCheckExecutor` to Èxecutor * TestSingleExecutor: improved tests * added testing of markup extension handling in executors * cleaned up includes based on `include-what-you-use` * testsingleexecutor.cpp: suppress `performance-unnecessary-value-param` clang-tidy warnings * ProcessExecutor: send color via pipe instead of applying it beforehand * do not unconditionally apply colors to output / disable all colors in tests / adjusted tests for changed output behavior * fixed precision loss in `Executor::reportStatus()` * fixed `naming-varname` selfcheck warnings
This commit is contained in:
parent
ba168474f2
commit
1f2b49142e
12
Makefile
12
Makefile
|
@ -261,6 +261,7 @@ CLIOBJ = cli/cmdlineparser.o \
|
|||
cli/filelister.o \
|
||||
cli/main.o \
|
||||
cli/processexecutor.o \
|
||||
cli/singleexecutor.o \
|
||||
cli/stacktrace.o \
|
||||
cli/threadexecutor.o
|
||||
|
||||
|
@ -310,6 +311,7 @@ TESTOBJ = test/fixture.o \
|
|||
test/testsimplifytokens.o \
|
||||
test/testsimplifytypedef.o \
|
||||
test/testsimplifyusing.o \
|
||||
test/testsingleexecutor.o \
|
||||
test/testsizeof.o \
|
||||
test/teststl.o \
|
||||
test/teststring.o \
|
||||
|
@ -342,7 +344,7 @@ cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)
|
|||
|
||||
all: cppcheck testrunner
|
||||
|
||||
testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/executor.o cli/processexecutor.o cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/cppcheckexecutorseh.o cli/cppcheckexecutorsig.o cli/stacktrace.o cli/filelister.o
|
||||
testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/executor.o cli/processexecutor.o cli/singleexecutor.o cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/cppcheckexecutorseh.o cli/cppcheckexecutorsig.o cli/stacktrace.o cli/filelister.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) $(LDFLAGS) $(RDYNAMIC)
|
||||
|
||||
test: all
|
||||
|
@ -634,7 +636,7 @@ $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathli
|
|||
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h 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/path.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/cmdlineparser.cpp
|
||||
|
||||
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.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/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
|
||||
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.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/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp
|
||||
|
||||
cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h lib/utils.h
|
||||
|
@ -655,6 +657,9 @@ cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/color.h lib/config.h lib/err
|
|||
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
|
||||
$(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
|
||||
$(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
|
||||
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/stacktrace.cpp
|
||||
|
||||
|
@ -799,6 +804,9 @@ test/testsimplifytypedef.o: test/testsimplifytypedef.cpp externals/simplecpp/sim
|
|||
test/testsimplifyusing.o: test/testsimplifyusing.cpp 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/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h
|
||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifyusing.cpp
|
||||
|
||||
test/testsingleexecutor.o: test/testsingleexecutor.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/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h test/redirect.h
|
||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsingleexecutor.cpp
|
||||
|
||||
test/testsizeof.o: test/testsizeof.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checksizeof.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/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h
|
||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsizeof.cpp
|
||||
|
||||
|
|
|
@ -435,6 +435,7 @@
|
|||
<ClInclude Include="executor.h" />
|
||||
<ClInclude Include="filelister.h" />
|
||||
<ClInclude Include="processexecutor.h" />
|
||||
<ClInclude Include="singleexecutor.h" />
|
||||
<ClInclude Include="stacktrace.h" />
|
||||
<ClInclude Include="threadexecutor.h" />
|
||||
</ItemGroup>
|
||||
|
@ -461,6 +462,7 @@
|
|||
<ClCompile Include="filelister.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="processexecutor.cpp" />
|
||||
<ClCompile Include="singleexecutor.cpp" />
|
||||
<ClCompile Include="stacktrace.cpp" />
|
||||
<ClCompile Include="threadexecutor.cpp" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -30,8 +30,10 @@
|
|||
#include "path.h"
|
||||
#include "pathmatch.h"
|
||||
#include "settings.h"
|
||||
#include "singleexecutor.h"
|
||||
#include "suppressions.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "checkunusedfunctions.h"
|
||||
|
||||
#if defined(THREADING_MODEL_THREAD)
|
||||
|
@ -51,7 +53,6 @@
|
|||
#include <sstream> // IWYU pragma: keep
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
|
||||
#ifdef USE_UNIX_SIGNAL_HANDLING
|
||||
#include "cppcheckexecutorsig.h"
|
||||
|
@ -242,7 +243,7 @@ bool CppCheckExecutor::reportSuppressions(const Settings &settings, bool unusedF
|
|||
return false;
|
||||
|
||||
bool err = false;
|
||||
if (settings.jointSuppressionReport) {
|
||||
if (settings.useSingleJob()) {
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = files.cbegin(); i != files.cend(); ++i) {
|
||||
err |= errorLogger.reportUnmatchedSuppressions(
|
||||
settings.nomsg.getUnmatchedLocalSuppressions(i->first, unusedFunctionCheckEnabled));
|
||||
|
@ -310,54 +311,10 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
|
|||
}
|
||||
|
||||
unsigned int returnValue = 0;
|
||||
if (settings.jobs == 1) {
|
||||
if (settings.useSingleJob()) {
|
||||
// Single process
|
||||
settings.jointSuppressionReport = true;
|
||||
|
||||
const std::size_t totalfilesize = std::accumulate(mFiles.cbegin(), mFiles.cend(), std::size_t(0), [](std::size_t v, const std::pair<std::string, std::size_t>& f) {
|
||||
return v + f.second;
|
||||
});
|
||||
|
||||
std::size_t processedsize = 0;
|
||||
unsigned int c = 0;
|
||||
if (settings.project.fileSettings.empty()) {
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = mFiles.cbegin(); i != mFiles.cend(); ++i) {
|
||||
if (!settings.library.markupFile(i->first)
|
||||
|| !settings.library.processMarkupAfterCode(i->first)) {
|
||||
returnValue += cppcheck.check(i->first);
|
||||
processedsize += i->second;
|
||||
if (!settings.quiet)
|
||||
reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// filesettings
|
||||
// check all files of the project
|
||||
for (const ImportProject::FileSettings &fs : settings.project.fileSettings) {
|
||||
returnValue += cppcheck.check(fs);
|
||||
++c;
|
||||
if (!settings.quiet)
|
||||
reportStatus(c, settings.project.fileSettings.size(), c, settings.project.fileSettings.size());
|
||||
if (settings.clangTidy)
|
||||
cppcheck.analyseClangTidy(fs);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: not performed when multiple jobs are being used
|
||||
// second loop to parse all markup files which may not work until all
|
||||
// c/cpp files have been parsed and checked
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = mFiles.cbegin(); i != mFiles.cend(); ++i) {
|
||||
if (settings.library.markupFile(i->first) && settings.library.processMarkupAfterCode(i->first)) {
|
||||
returnValue += cppcheck.check(i->first);
|
||||
processedsize += i->second;
|
||||
if (!settings.quiet)
|
||||
reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
if (cppcheck.analyseWholeProgram())
|
||||
returnValue++;
|
||||
SingleExecutor executor(cppcheck, mFiles, settings, *this);
|
||||
returnValue = executor.check();
|
||||
} else {
|
||||
#if defined(THREADING_MODEL_THREAD)
|
||||
ThreadExecutor executor(mFiles, settings, *this);
|
||||
|
@ -423,8 +380,10 @@ void CppCheckExecutor::reportErr(const std::string &errmsg)
|
|||
|
||||
void CppCheckExecutor::reportOut(const std::string &outmsg, Color c)
|
||||
{
|
||||
// TODO: do not unconditionally apply colors
|
||||
std::cout << c << ansiToOEM(outmsg, true) << Color::Reset << std::endl;
|
||||
if (c == Color::Reset)
|
||||
std::cout << ansiToOEM(outmsg, true) << std::endl;
|
||||
else
|
||||
std::cout << toString(c) << ansiToOEM(outmsg, true) << toString(Color::Reset) << std::endl;
|
||||
}
|
||||
|
||||
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
|
||||
|
@ -450,19 +409,6 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st
|
|||
}
|
||||
}
|
||||
|
||||
void CppCheckExecutor::reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal)
|
||||
{
|
||||
if (filecount > 1) {
|
||||
std::ostringstream oss;
|
||||
const long percentDone = (sizetotal > 0) ? static_cast<long>(static_cast<long double>(sizedone) / sizetotal * 100) : 0;
|
||||
oss << fileindex << '/' << filecount
|
||||
<< " files checked " << percentDone
|
||||
<< "% done";
|
||||
// TODO: do not unconditionally print in color
|
||||
std::cout << Color::FgBlue << oss.str() << Color::Reset << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CppCheckExecutor::reportErr(const ErrorMessage &msg)
|
||||
{
|
||||
if (mShowAllErrors) {
|
||||
|
|
|
@ -81,16 +81,6 @@ public:
|
|||
|
||||
void reportProgress(const std::string &filename, const char stage[], const std::size_t value) override;
|
||||
|
||||
/**
|
||||
* Information about how many files have been checked
|
||||
*
|
||||
* @param fileindex This many files have been checked.
|
||||
* @param filecount This many files there are in total.
|
||||
* @param sizedone The sum of sizes of the files checked.
|
||||
* @param sizetotal The total sizes of the files.
|
||||
*/
|
||||
static void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal);
|
||||
|
||||
/**
|
||||
* @param exceptionOutput Output file
|
||||
*/
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
|
||||
#include "executor.h"
|
||||
|
||||
#include "color.h"
|
||||
#include "errorlogger.h"
|
||||
#include "settings.h"
|
||||
#include "suppressions.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
#include <utility>
|
||||
|
||||
Executor::Executor(const std::map<std::string, std::size_t> &files, Settings &settings, ErrorLogger &errorLogger)
|
||||
|
@ -47,3 +50,15 @@ bool Executor::hasToLog(const ErrorMessage &msg)
|
|||
return false;
|
||||
}
|
||||
|
||||
void Executor::reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal)
|
||||
{
|
||||
if (filecount > 1) {
|
||||
std::ostringstream oss;
|
||||
const unsigned long percentDone = (sizetotal > 0) ? (100 * sizedone) / sizetotal : 0;
|
||||
oss << fileindex << '/' << filecount
|
||||
<< " files checked " << percentDone
|
||||
<< "% done";
|
||||
mErrorLogger.reportOut(oss.str(), Color::FgBlue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,16 @@ public:
|
|||
|
||||
virtual unsigned int check() = 0;
|
||||
|
||||
/**
|
||||
* Information about how many files have been checked
|
||||
*
|
||||
* @param fileindex This many files have been checked.
|
||||
* @param filecount This many files there are in total.
|
||||
* @param sizedone The sum of sizes of the files checked.
|
||||
* @param sizetotal The total sizes of the files.
|
||||
*/
|
||||
void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Check if message is being suppressed and unique.
|
||||
|
|
|
@ -73,8 +73,7 @@ public:
|
|||
explicit PipeWriter(int pipe) : mWpipe(pipe) {}
|
||||
|
||||
void reportOut(const std::string &outmsg, Color c) override {
|
||||
// TODO: do not unconditionally apply colors
|
||||
writeToPipe(REPORT_OUT, ::toString(c) + outmsg + ::toString(Color::Reset));
|
||||
writeToPipe(REPORT_OUT, static_cast<char>(c) + outmsg);
|
||||
}
|
||||
|
||||
void reportErr(const ErrorMessage &msg) override {
|
||||
|
@ -178,7 +177,9 @@ bool ProcessExecutor::handleRead(int rpipe, unsigned int &result, const std::str
|
|||
|
||||
bool res = true;
|
||||
if (type == PipeWriter::REPORT_OUT) {
|
||||
mErrorLogger.reportOut(buf);
|
||||
// the first charcater is the color
|
||||
const Color c = static_cast<Color>(buf[0]);
|
||||
mErrorLogger.reportOut(buf + 1, c);
|
||||
} else if (type == PipeWriter::REPORT_ERROR) {
|
||||
ErrorMessage msg;
|
||||
try {
|
||||
|
@ -328,7 +329,7 @@ unsigned int ProcessExecutor::check()
|
|||
fileCount++;
|
||||
processedsize += size;
|
||||
if (!mSettings.quiet)
|
||||
CppCheckExecutor::reportStatus(fileCount, mFiles.size() + mSettings.project.fileSettings.size(), processedsize, totalfilesize);
|
||||
Executor::reportStatus(fileCount, mFiles.size() + mSettings.project.fileSettings.size(), processedsize, totalfilesize);
|
||||
|
||||
close(*rp);
|
||||
rp = rpipes.erase(rp);
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2023 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "singleexecutor.h"
|
||||
|
||||
#include "cppcheck.h"
|
||||
#include "importproject.h"
|
||||
#include "library.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <list>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
class ErrorLogger;
|
||||
|
||||
SingleExecutor::SingleExecutor(CppCheck &cppcheck, const std::map<std::string, std::size_t> &files, Settings &settings, ErrorLogger &errorLogger)
|
||||
: Executor(files, settings, errorLogger)
|
||||
, mCppcheck(cppcheck)
|
||||
{}
|
||||
|
||||
SingleExecutor::~SingleExecutor()
|
||||
{}
|
||||
|
||||
// TODO: markup handling is not performed with multiple jobs
|
||||
unsigned int SingleExecutor::check()
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
const std::size_t totalfilesize = std::accumulate(mFiles.cbegin(), mFiles.cend(), std::size_t(0), [](std::size_t v, const std::pair<std::string, std::size_t>& f) {
|
||||
return v + f.second;
|
||||
});
|
||||
|
||||
std::size_t processedsize = 0;
|
||||
unsigned int c = 0;
|
||||
if (mSettings.project.fileSettings.empty()) {
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = mFiles.cbegin(); i != mFiles.cend(); ++i) {
|
||||
if (!mSettings.library.markupFile(i->first)
|
||||
|| !mSettings.library.processMarkupAfterCode(i->first)) {
|
||||
result += mCppcheck.check(i->first);
|
||||
processedsize += i->second;
|
||||
if (!mSettings.quiet)
|
||||
reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// filesettings
|
||||
// check all files of the project
|
||||
for (const ImportProject::FileSettings &fs : mSettings.project.fileSettings) {
|
||||
result += mCppcheck.check(fs);
|
||||
++c;
|
||||
if (!mSettings.quiet)
|
||||
reportStatus(c, mSettings.project.fileSettings.size(), c, mSettings.project.fileSettings.size());
|
||||
if (mSettings.clangTidy)
|
||||
mCppcheck.analyseClangTidy(fs);
|
||||
}
|
||||
}
|
||||
|
||||
// second loop to parse all markup files which may not work until all
|
||||
// c/cpp files have been parsed and checked
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = mFiles.cbegin(); i != mFiles.cend(); ++i) {
|
||||
if (mSettings.library.markupFile(i->first) && mSettings.library.processMarkupAfterCode(i->first)) {
|
||||
result += mCppcheck.check(i->first);
|
||||
processedsize += i->second;
|
||||
if (!mSettings.quiet)
|
||||
reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
if (mCppcheck.analyseWholeProgram())
|
||||
result++;
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2023 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SINGLEEXECUTOR_H
|
||||
#define SINGLEEXECUTOR_H
|
||||
|
||||
#include "executor.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class ErrorLogger;
|
||||
class Settings;
|
||||
class CppCheck;
|
||||
|
||||
class SingleExecutor : public Executor
|
||||
{
|
||||
public:
|
||||
SingleExecutor(CppCheck &cppcheck, const std::map<std::string, std::size_t> &files, Settings &settings, ErrorLogger &errorLogger);
|
||||
SingleExecutor(const SingleExecutor &) = delete;
|
||||
~SingleExecutor() override;
|
||||
void operator=(const SingleExecutor &) = delete;
|
||||
|
||||
unsigned int check() override;
|
||||
|
||||
private:
|
||||
CppCheck &mCppcheck;
|
||||
};
|
||||
|
||||
#endif // SINGLEEXECUTOR_H
|
|
@ -69,7 +69,7 @@ public:
|
|||
|
||||
void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal) {
|
||||
std::lock_guard<std::mutex> lg(mReportSync);
|
||||
CppCheckExecutor::reportStatus(fileindex, filecount, sizedone, sizetotal);
|
||||
mThreadExecutor.reportStatus(fileindex, filecount, sizedone, sizetotal);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -360,7 +360,7 @@ Check::FileInfo *CheckUnusedFunctions::getFileInfo(const Tokenizer *tokenizer, c
|
|||
{
|
||||
if (!settings->checks.isEnabled(Checks::unusedFunction))
|
||||
return nullptr;
|
||||
if (settings->jobs == 1 && settings->buildDir.empty())
|
||||
if (settings->useSingleJob() && settings->buildDir.empty())
|
||||
instance.parseTokens(*tokenizer, tokenizer->list.getFiles().front().c_str(), settings);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -24,14 +24,17 @@
|
|||
#include <cstddef>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
|
||||
bool gDisableColors = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
std::ostream& operator<<(std::ostream& os, const Color& /*c*/)
|
||||
{
|
||||
#else
|
||||
std::ostream& operator<<(std::ostream & os, const Color& c)
|
||||
{
|
||||
static const bool use_color = isatty(STDOUT_FILENO);
|
||||
if (use_color)
|
||||
// TODO: handle piping into file as well as other pipes like stderr
|
||||
static const bool s_is_tty = isatty(STDOUT_FILENO);
|
||||
if (!gDisableColors && s_is_tty)
|
||||
return os << "\033[" << static_cast<std::size_t>(c) << "m";
|
||||
#endif
|
||||
return os;
|
||||
|
|
|
@ -40,6 +40,8 @@ enum class Color {
|
|||
};
|
||||
CPPCHECKLIB std::ostream& operator<<(std::ostream& os, const Color& c);
|
||||
|
||||
std::string toString(const Color& c);
|
||||
CPPCHECKLIB std::string toString(const Color& c);
|
||||
|
||||
extern CPPCHECKLIB bool gDisableColors; // for testing
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1026,7 +1026,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
|
|||
|
||||
// In jointSuppressionReport mode, unmatched suppressions are
|
||||
// collected after all files are processed
|
||||
if (!mSettings.jointSuppressionReport && (mSettings.severity.isEnabled(Severity::information) || mSettings.checkConfiguration)) {
|
||||
if (!mSettings.useSingleJob() && (mSettings.severity.isEnabled(Severity::information) || mSettings.checkConfiguration)) {
|
||||
reportUnmatchedSuppressions(mSettings.nomsg.getUnmatchedLocalSuppressions(filename, isUnusedFunctionCheckEnabled()));
|
||||
}
|
||||
|
||||
|
@ -1111,12 +1111,12 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
|
|||
return;
|
||||
|
||||
|
||||
if (mSettings.jobs == 1 || !mSettings.buildDir.empty()) {
|
||||
if (mSettings.useSingleJob() || !mSettings.buildDir.empty()) {
|
||||
// Analyse the tokens..
|
||||
|
||||
CTU::FileInfo *fi1 = CTU::getFileInfo(&tokenizer);
|
||||
if (fi1) {
|
||||
if (mSettings.jobs == 1)
|
||||
if (mSettings.useSingleJob())
|
||||
mFileInfo.push_back(fi1);
|
||||
if (!mSettings.buildDir.empty())
|
||||
mAnalyzerInformation.setFileInfo("ctu", fi1->toString());
|
||||
|
@ -1128,7 +1128,7 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
|
|||
|
||||
Check::FileInfo *fi = check->getFileInfo(&tokenizer, &mSettings);
|
||||
if (fi != nullptr) {
|
||||
if (mSettings.jobs == 1)
|
||||
if (mSettings.useSingleJob())
|
||||
mFileInfo.push_back(fi);
|
||||
if (!mSettings.buildDir.empty())
|
||||
mAnalyzerInformation.setFileInfo(check->name(), fi->toString());
|
||||
|
@ -1652,9 +1652,6 @@ void CppCheck::reportProgress(const std::string &filename, const char stage[], c
|
|||
mErrorLogger.reportProgress(filename, stage, value);
|
||||
}
|
||||
|
||||
void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, std::size_t /*sizedone*/, std::size_t /*sizetotal*/)
|
||||
{}
|
||||
|
||||
void CppCheck::getErrorMessages()
|
||||
{
|
||||
Settings s(mSettings);
|
||||
|
@ -1837,7 +1834,7 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<s
|
|||
|
||||
bool CppCheck::isUnusedFunctionCheckEnabled() const
|
||||
{
|
||||
return (mSettings.jobs == 1 && mSettings.checks.isEnabled(Checks::unusedFunction));
|
||||
return (mSettings.useSingleJob() && mSettings.checks.isEnabled(Checks::unusedFunction));
|
||||
}
|
||||
|
||||
void CppCheck::removeCtuInfoFiles(const std::map<std::string, std::size_t> &files)
|
||||
|
|
|
@ -112,8 +112,6 @@ public:
|
|||
*/
|
||||
static const char * extraVersion();
|
||||
|
||||
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, std::size_t sizedone, std::size_t sizetotal);
|
||||
|
||||
/**
|
||||
* @brief Call all "getErrorMessages" in all registered Check classes.
|
||||
* Also print out XML header and footer.
|
||||
|
|
|
@ -51,7 +51,11 @@ namespace tinyxml2 {
|
|||
* @brief Library definitions handling
|
||||
*/
|
||||
class CPPCHECKLIB Library {
|
||||
// TODO: get rid of this
|
||||
friend class TestSymbolDatabase; // For testing only
|
||||
friend class TestSingleExecutor; // For testing only
|
||||
friend class TestThreadExecutor; // For testing only
|
||||
friend class TestProcessExecutor; // For testing only
|
||||
|
||||
public:
|
||||
Library();
|
||||
|
|
|
@ -59,7 +59,6 @@ Settings::Settings()
|
|||
force(false),
|
||||
inlineSuppressions(false),
|
||||
jobs(1),
|
||||
jointSuppressionReport(false),
|
||||
loadAverage(0),
|
||||
maxConfigs(12),
|
||||
maxCtuDepth(2),
|
||||
|
|
|
@ -216,11 +216,6 @@ public:
|
|||
time. Default is 1. (-j N) */
|
||||
unsigned int jobs;
|
||||
|
||||
/** @brief Collect unmatched suppressions in one run.
|
||||
* This delays the reporting until all files are checked.
|
||||
* It is needed by checks that analyse the whole code base. */
|
||||
bool jointSuppressionReport;
|
||||
|
||||
/** @brief --library= */
|
||||
std::list<std::string> libraries;
|
||||
|
||||
|
@ -439,6 +434,10 @@ public:
|
|||
|
||||
void loadSummaries();
|
||||
|
||||
bool useSingleJob() const {
|
||||
return jobs == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity::SeverityType>, SimpleEnableGroup<Checks>> &groups);
|
||||
std::string applyEnabled(const std::string &str, bool enable);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "color.h"
|
||||
#include "options.h"
|
||||
#include "preprocessor.h"
|
||||
#include "fixture.h"
|
||||
|
@ -30,6 +31,7 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
|
||||
Preprocessor::macroChar = '$'; // While macroChar is char(1) per default outside test suite, we require it to be a human-readable character here.
|
||||
gDisableColors = true;
|
||||
|
||||
options args(argc, argv);
|
||||
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#include "fixture.h"
|
||||
#include "helpers.h"
|
||||
#include "timer.h"
|
||||
#include "library.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -43,15 +45,23 @@ private:
|
|||
* Execute check using n jobs for y files which are have
|
||||
* identical data, given within data.
|
||||
*/
|
||||
void check(unsigned int jobs, int files, int result, const std::string &data, SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE, const char* const plistOutput = nullptr) {
|
||||
void check(unsigned int jobs, int files, int result, const std::string &data, SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE, const char* const plistOutput = nullptr, const std::vector<std::string>& filesList = {}) {
|
||||
errout.str("");
|
||||
output.str("");
|
||||
|
||||
std::map<std::string, std::size_t> filemap;
|
||||
for (int i = 1; i <= files; ++i) {
|
||||
std::ostringstream oss;
|
||||
oss << "file_" << i << ".cpp";
|
||||
filemap[oss.str()] = data.size();
|
||||
if (filesList.empty()) {
|
||||
for (int i = 1; i <= files; ++i) {
|
||||
std::ostringstream oss;
|
||||
oss << "file_" << i << ".cpp";
|
||||
filemap[oss.str()] = data.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const auto& f : filesList)
|
||||
{
|
||||
filemap[f] = data.size();
|
||||
}
|
||||
}
|
||||
|
||||
settings.jobs = jobs;
|
||||
|
@ -81,6 +91,7 @@ private:
|
|||
TEST_CASE(no_errors_equal_amount_files);
|
||||
TEST_CASE(one_error_less_files);
|
||||
TEST_CASE(one_error_several_files);
|
||||
TEST_CASE(markup);
|
||||
#endif // !WIN32
|
||||
}
|
||||
|
||||
|
@ -120,7 +131,6 @@ private:
|
|||
const char plistOutput[] = "plist";
|
||||
ScopedFile plistFile("dummy", plistOutput);
|
||||
|
||||
SUPPRESS;
|
||||
check(16, 100, 100,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
|
@ -170,6 +180,44 @@ private:
|
|||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
|
||||
void markup() {
|
||||
const Settings settingsOld = settings;
|
||||
settings.library.mMarkupExtensions.emplace(".cp1");
|
||||
settings.library.mProcessAfterCode.emplace(".cp1", true);
|
||||
|
||||
const std::vector<std::string> files = {
|
||||
"file_1.cp1", "file_2.cpp", "file_3.cp1", "file_4.cpp"
|
||||
};
|
||||
|
||||
check(2, 4, 4,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}",
|
||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
||||
// TODO: order of "Checking" and "checked" is affected by thread
|
||||
/*TODO_ASSERT_EQUALS("Checking file_2.cpp ...\n"
|
||||
"1/4 files checked 25% done\n"
|
||||
"Checking file_4.cpp ...\n"
|
||||
"2/4 files checked 50% done\n"
|
||||
"Checking file_1.cp1 ...\n"
|
||||
"3/4 files checked 75% done\n"
|
||||
"Checking file_3.cp1 ...\n"
|
||||
"4/4 files checked 100% done\n",
|
||||
"Checking file_1.cp1 ...\n"
|
||||
"1/4 files checked 25% done\n"
|
||||
"Checking file_2.cpp ...\n"
|
||||
"2/4 files checked 50% done\n"
|
||||
"Checking file_3.cp1 ...\n"
|
||||
"3/4 files checked 75% done\n"
|
||||
"Checking file_4.cpp ...\n"
|
||||
"4/4 files checked 100% done\n",
|
||||
output.str());*/
|
||||
settings = settingsOld;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestProcessExecutor)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
<ClCompile Include="..\cli\executor.cpp" />
|
||||
<ClCompile Include="..\cli\filelister.cpp" />
|
||||
<ClCompile Include="..\cli\processexecutor.cpp" />
|
||||
<ClCompile Include="..\cli\singleexecutor.cpp" />
|
||||
<ClCompile Include="..\cli\stacktrace.cpp" />
|
||||
<ClCompile Include="..\cli\threadexecutor.cpp" />
|
||||
<ClCompile Include="fixture.cpp">
|
||||
|
@ -84,6 +85,7 @@
|
|||
<ClCompile Include="testsimplifytokens.cpp" />
|
||||
<ClCompile Include="testsimplifytypedef.cpp" />
|
||||
<ClCompile Include="testsimplifyusing.cpp" />
|
||||
<ClCompile Include="testsingleexecutor.cpp" />
|
||||
<ClCompile Include="testsizeof.cpp" />
|
||||
<ClCompile Include="teststl.cpp" />
|
||||
<ClCompile Include="teststring.cpp" />
|
||||
|
@ -114,6 +116,7 @@
|
|||
<ClInclude Include="..\cli\executor.h" />
|
||||
<ClInclude Include="..\cli\filelister.h" />
|
||||
<ClInclude Include="..\cli\processexecutor.h" />
|
||||
<ClInclude Include="..\cli\singleexecutor.h" />
|
||||
<ClInclude Include="..\cli\stacktrace.h" />
|
||||
<ClInclude Include="..\cli\threadexecutor.h" />
|
||||
<ClInclude Include="fixture.h" />
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2023 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cppcheck.h"
|
||||
#include "fixture.h"
|
||||
#include "helpers.h"
|
||||
#include "redirect.h"
|
||||
#include "library.h"
|
||||
#include "settings.h"
|
||||
#include "singleexecutor.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class TestSingleExecutor : public TestFixture {
|
||||
public:
|
||||
TestSingleExecutor() : TestFixture("TestSingleExecutor") {}
|
||||
|
||||
private:
|
||||
Settings settings;
|
||||
|
||||
static std::string zpad3(int i)
|
||||
{
|
||||
if (i < 10)
|
||||
return "00" + std::to_string(i);
|
||||
if (i < 100)
|
||||
return "0" + std::to_string(i);
|
||||
return std::to_string(i);
|
||||
}
|
||||
|
||||
void check(int files, int result, const std::string &data, SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE, const char* const plistOutput = nullptr, const std::vector<std::string>& filesList = {}) {
|
||||
errout.str("");
|
||||
output.str("");
|
||||
|
||||
std::map<std::string, std::size_t> filemap;
|
||||
if (filesList.empty()) {
|
||||
for (int i = 1; i <= files; ++i) {
|
||||
const std::string s = "file_" + zpad3(i) + ".cpp";
|
||||
filemap[s] = data.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const auto& f : filesList)
|
||||
{
|
||||
filemap[f] = data.size();
|
||||
}
|
||||
}
|
||||
|
||||
settings.showtime = showtime;
|
||||
if (plistOutput)
|
||||
settings.plistOutput = plistOutput;
|
||||
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
||||
CppCheck cppcheck(*this, true, [](std::string,std::vector<std::string>,std::string,std::string&){
|
||||
return false;
|
||||
});
|
||||
cppcheck.settings() = settings;
|
||||
// TODO: test with settings.project.fileSettings;
|
||||
SingleExecutor executor(cppcheck, filemap, settings, *this);
|
||||
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
|
||||
scopedfiles.reserve(filemap.size());
|
||||
for (std::map<std::string, std::size_t>::const_iterator i = filemap.cbegin(); i != filemap.cend(); ++i)
|
||||
scopedfiles.emplace_back(new ScopedFile(i->first, data));
|
||||
|
||||
ASSERT_EQUALS(result, executor.check());
|
||||
}
|
||||
|
||||
void run() override {
|
||||
LOAD_LIB_2(settings.library, "std.cfg");
|
||||
|
||||
TEST_CASE(many_files);
|
||||
TEST_CASE(many_files_showtime);
|
||||
TEST_CASE(many_files_plist);
|
||||
TEST_CASE(no_errors_more_files);
|
||||
TEST_CASE(no_errors_less_files);
|
||||
TEST_CASE(no_errors_equal_amount_files);
|
||||
TEST_CASE(one_error_less_files);
|
||||
TEST_CASE(one_error_several_files);
|
||||
TEST_CASE(markup);
|
||||
}
|
||||
|
||||
void many_files() {
|
||||
const Settings settingsOld = settings;
|
||||
settings.quiet = false;
|
||||
|
||||
check(100, 100,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
std::string expected;
|
||||
for (int i = 1; i <= 100; ++i) {
|
||||
expected += "Checking file_" + zpad3(i) + ".cpp ...\n";
|
||||
expected += std::to_string(i) + "/100 files checked " + std::to_string(i) + "% done\n";
|
||||
}
|
||||
ASSERT_EQUALS(expected, output.str());
|
||||
|
||||
settings = settingsOld;
|
||||
}
|
||||
|
||||
void many_files_showtime() {
|
||||
SUPPRESS;
|
||||
check(100, 100,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}", SHOWTIME_MODES::SHOWTIME_SUMMARY);
|
||||
}
|
||||
|
||||
void many_files_plist() {
|
||||
const char plistOutput[] = "plist";
|
||||
ScopedFile plistFile("dummy", plistOutput);
|
||||
|
||||
check(100, 100,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}", SHOWTIME_MODES::SHOWTIME_NONE, plistOutput);
|
||||
}
|
||||
|
||||
void no_errors_more_files() {
|
||||
check(3, 0,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void no_errors_less_files() {
|
||||
check(1, 0,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void no_errors_equal_amount_files() {
|
||||
check(2, 0,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void one_error_less_files() {
|
||||
check(1, 1,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" {char *a = malloc(10);}\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void one_error_several_files() {
|
||||
check(20, 20,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" {char *a = malloc(10);}\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void markup() {
|
||||
const Settings settingsOld = settings;
|
||||
settings.library.mMarkupExtensions.emplace(".cp1");
|
||||
settings.library.mProcessAfterCode.emplace(".cp1", true);
|
||||
|
||||
const std::vector<std::string> files = {
|
||||
"file_1.cp1", "file_2.cpp", "file_3.cp1", "file_4.cpp"
|
||||
};
|
||||
|
||||
check(4, 4,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}",
|
||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
||||
// TODO: filter out the "files checked" messages
|
||||
ASSERT_EQUALS("Checking file_2.cpp ...\n"
|
||||
"1/4 files checked 25% done\n"
|
||||
"Checking file_4.cpp ...\n"
|
||||
"2/4 files checked 50% done\n"
|
||||
"Checking file_1.cp1 ...\n"
|
||||
"3/4 files checked 75% done\n"
|
||||
"Checking file_3.cp1 ...\n"
|
||||
"4/4 files checked 100% done\n", output.str());
|
||||
settings = settingsOld;
|
||||
}
|
||||
|
||||
// TODO: test clang-tidy
|
||||
// TODO: test whole program analysis
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSingleExecutor)
|
|
@ -189,7 +189,7 @@ private:
|
|||
if (suppression == "unusedFunction")
|
||||
settings.checks.setEnabled(Checks::unusedFunction, true);
|
||||
settings.severity.enable(Severity::information);
|
||||
settings.jointSuppressionReport = true;
|
||||
settings.jobs = 1;
|
||||
if (!suppression.empty()) {
|
||||
std::string r = settings.nomsg.addSuppressionLine(suppression);
|
||||
EXPECT_EQ("", r);
|
||||
|
@ -298,7 +298,7 @@ private:
|
|||
" a++;\n"
|
||||
"}\n",
|
||||
"uninitvar:test.cpp"));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
//TODO_ASSERT_EQUALS("", "[test.cpp]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||
|
||||
// TODO: add assert - gives different result with threads/processes
|
||||
// suppress uninitvar for this file only, without error present
|
||||
|
@ -315,7 +315,7 @@ private:
|
|||
" a++;\n"
|
||||
"}\n",
|
||||
"*:test.cpp"));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
//TODO_ASSERT_EQUALS("", "[test.cpp]: (information) Unmatched suppression: *\n", errout.str());
|
||||
|
||||
// TODO: add assert - gives different result with threads/processes
|
||||
// suppress all for this file only, without error present
|
||||
|
@ -341,7 +341,7 @@ private:
|
|||
" b++;\n"
|
||||
"}\n",
|
||||
"uninitvar:test.cpp:3");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||
//TODO_ASSERT_EQUALS("[test.cpp:3]: (information) Unmatched suppression: uninitvar\n", "", errout.str());
|
||||
|
||||
// suppress uninitvar inline
|
||||
ASSERT_EQUALS(0, (this->*check)("void f() {\n"
|
||||
|
@ -472,7 +472,7 @@ private:
|
|||
" b++;\n"
|
||||
"}\n",
|
||||
"");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||
//TODO_ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", "", errout.str());
|
||||
|
||||
// #5746 - exitcode
|
||||
ASSERT_EQUALS(1U,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "settings.h"
|
||||
#include "fixture.h"
|
||||
#include "helpers.h"
|
||||
#include "library.h"
|
||||
#include "threadexecutor.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -43,15 +45,23 @@ private:
|
|||
* Execute check using n jobs for y files which are have
|
||||
* identical data, given within data.
|
||||
*/
|
||||
void check(unsigned int jobs, int files, int result, const std::string &data, SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE, const char* const plistOutput = nullptr) {
|
||||
void check(unsigned int jobs, int files, int result, const std::string &data, SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE, const char* const plistOutput = nullptr, const std::vector<std::string>& filesList = {}) {
|
||||
errout.str("");
|
||||
output.str("");
|
||||
|
||||
std::map<std::string, std::size_t> filemap;
|
||||
for (int i = 1; i <= files; ++i) {
|
||||
std::ostringstream oss;
|
||||
oss << "file_" << i << ".cpp";
|
||||
filemap[oss.str()] = data.size();
|
||||
if (filesList.empty()) {
|
||||
for (int i = 1; i <= files; ++i) {
|
||||
std::ostringstream oss;
|
||||
oss << "file_" << i << ".cpp";
|
||||
filemap[oss.str()] = data.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const auto& f : filesList)
|
||||
{
|
||||
filemap[f] = data.size();
|
||||
}
|
||||
}
|
||||
|
||||
settings.jobs = jobs;
|
||||
|
@ -80,6 +90,7 @@ private:
|
|||
TEST_CASE(no_errors_equal_amount_files);
|
||||
TEST_CASE(one_error_less_files);
|
||||
TEST_CASE(one_error_several_files);
|
||||
TEST_CASE(markup);
|
||||
}
|
||||
|
||||
void deadlock_with_many_errors() {
|
||||
|
@ -118,7 +129,6 @@ private:
|
|||
const char plistOutput[] = "plist";
|
||||
ScopedFile plistFile("dummy", plistOutput);
|
||||
|
||||
SUPPRESS;
|
||||
check(16, 100, 100,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
|
@ -168,6 +178,43 @@ private:
|
|||
" return 0;\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
void markup() {
|
||||
const Settings settingsOld = settings;
|
||||
settings.library.mMarkupExtensions.emplace(".cp1");
|
||||
settings.library.mProcessAfterCode.emplace(".cp1", true);
|
||||
|
||||
const std::vector<std::string> files = {
|
||||
"file_1.cp1", "file_2.cpp", "file_3.cp1", "file_4.cpp"
|
||||
};
|
||||
|
||||
check(2, 4, 4,
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" char *a = malloc(10);\n"
|
||||
" return 0;\n"
|
||||
"}",
|
||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
||||
// TODO: order of "Checking" and "checked" is affected by thread
|
||||
/*TODO_ASSERT_EQUALS("Checking file_2.cpp ...\n"
|
||||
"1/4 files checked 25% done\n"
|
||||
"Checking file_4.cpp ...\n"
|
||||
"2/4 files checked 50% done\n"
|
||||
"Checking file_1.cp1 ...\n"
|
||||
"3/4 files checked 75% done\n"
|
||||
"Checking file_3.cp1 ...\n"
|
||||
"4/4 files checked 100% done\n",
|
||||
"Checking file_1.cp1 ...\n"
|
||||
"1/4 files checked 25% done\n"
|
||||
"Checking file_2.cpp ...\n"
|
||||
"2/4 files checked 50% done\n"
|
||||
"Checking file_3.cp1 ...\n"
|
||||
"3/4 files checked 75% done\n"
|
||||
"Checking file_4.cpp ...\n"
|
||||
"4/4 files checked 100% done\n",
|
||||
output.str());*/
|
||||
settings = settingsOld;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestThreadExecutor)
|
||||
|
|
|
@ -659,7 +659,8 @@ int main(int argc, char **argv)
|
|||
fout << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n";
|
||||
fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) $(LDFLAGS) $(RDYNAMIC)\n\n";
|
||||
fout << "all:\tcppcheck testrunner\n\n";
|
||||
fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/executor.o cli/processexecutor.o cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/cppcheckexecutorseh.o cli/cppcheckexecutorsig.o cli/stacktrace.o cli/filelister.o\n";
|
||||
// TODO: generate from clifiles
|
||||
fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/executor.o cli/processexecutor.o cli/singleexecutor.o cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/cppcheckexecutorseh.o cli/cppcheckexecutorsig.o cli/stacktrace.o cli/filelister.o\n";
|
||||
fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) $(LDFLAGS) $(RDYNAMIC)\n\n";
|
||||
fout << "test:\tall\n";
|
||||
fout << "\t./testrunner\n\n";
|
||||
|
|
Loading…
Reference in New Issue