added testing of clang-tidy invocation to executor tests / also some cleanups (#5514)

This commit is contained in:
Oliver Stöneberg 2023-10-08 09:06:02 +02:00 committed by GitHub
parent eb076d877b
commit 8dee551cad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 231 additions and 69 deletions

View File

@ -802,7 +802,7 @@ test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/check.h lib/checkpo
test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.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/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/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpreprocessor.cpp
test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.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/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
test/testprocessexecutor.o: test/testprocessexecutor.cpp 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/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/testprocessexecutor.cpp
test/testsettings.o: test/testsettings.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/utils.h test/fixture.h
@ -841,7 +841,7 @@ test/testsuppressions.o: test/testsuppressions.cpp cli/cppcheckexecutor.h cli/ex
test/testsymboldatabase.o: test/testsymboldatabase.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/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsymboldatabase.cpp
test/testthreadexecutor.o: test/testthreadexecutor.cpp cli/executor.h cli/threadexecutor.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/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
test/testthreadexecutor.o: test/testthreadexecutor.cpp 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/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/testthreadexecutor.cpp
test/testtimer.o: test/testtimer.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/timer.h lib/utils.h test/fixture.h

View File

@ -325,9 +325,9 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
returnValue = executor.check();
} else {
#if defined(THREADING_MODEL_THREAD)
ThreadExecutor executor(mFiles, settings, settings.nomsg, *this);
ThreadExecutor executor(mFiles, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
#elif defined(THREADING_MODEL_FORK)
ProcessExecutor executor(mFiles, settings, settings.nomsg, *this);
ProcessExecutor executor(mFiles, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
#endif
returnValue = executor.check();
}

View File

@ -62,8 +62,9 @@ enum class Color;
using std::memset;
ProcessExecutor::ProcessExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger)
ProcessExecutor::ProcessExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand)
: Executor(files, settings, suppressions, errorLogger)
, mExecuteCommand(std::move(executeCommand))
{
assert(mSettings.jobs > 1);
}
@ -272,7 +273,7 @@ unsigned int ProcessExecutor::check()
close(pipes[0]);
PipeWriter pipewriter(pipes[1]);
CppCheck fileChecker(pipewriter, false, CppCheckExecutor::executeCommand);
CppCheck fileChecker(pipewriter, false, mExecuteCommand);
fileChecker.settings() = mSettings;
unsigned int resultOfCheck = 0;

View File

@ -19,6 +19,7 @@
#ifndef PROCESSEXECUTOR_H
#define PROCESSEXECUTOR_H
#include "cppcheck.h"
#include "executor.h"
#include <cstddef>
@ -38,7 +39,7 @@ class Suppressions;
*/
class ProcessExecutor : public Executor {
public:
ProcessExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger);
ProcessExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
ProcessExecutor(const ProcessExecutor &) = delete;
void operator=(const ProcessExecutor &) = delete;
@ -63,6 +64,8 @@ private:
* @param msg The error message
*/
void reportInternalChildErr(const std::string &childname, const std::string &msg);
CppCheck::ExecuteCmdFn mExecuteCommand;
};
/// @}

View File

@ -41,8 +41,9 @@
enum class Color;
ThreadExecutor::ThreadExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger)
ThreadExecutor::ThreadExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand)
: Executor(files, settings, suppressions, errorLogger)
, mExecuteCommand(std::move(executeCommand))
{
assert(mSettings.jobs > 1);
}
@ -82,8 +83,8 @@ private:
class ThreadData
{
public:
ThreadData(ThreadExecutor &threadExecutor, ErrorLogger &errorLogger, const Settings &settings, const std::map<std::string, std::size_t> &files, const std::list<ImportProject::FileSettings> &fileSettings)
: mFiles(files), mFileSettings(fileSettings), mSettings(settings), logForwarder(threadExecutor, errorLogger)
ThreadData(ThreadExecutor &threadExecutor, ErrorLogger &errorLogger, const Settings &settings, const std::map<std::string, std::size_t> &files, const std::list<ImportProject::FileSettings> &fileSettings, CppCheck::ExecuteCmdFn executeCommand)
: mFiles(files), mFileSettings(fileSettings), mSettings(settings), mExecuteCommand(std::move(executeCommand)), logForwarder(threadExecutor, errorLogger)
{
mItNextFile = mFiles.begin();
mItNextFileSettings = mFileSettings.begin();
@ -115,7 +116,7 @@ public:
}
unsigned int check(ErrorLogger &errorLogger, const std::string *file, const ImportProject::FileSettings *fs) const {
CppCheck fileChecker(errorLogger, false, CppCheckExecutor::executeCommand);
CppCheck fileChecker(errorLogger, false, mExecuteCommand);
fileChecker.settings() = mSettings; // this is a copy
unsigned int result;
@ -153,6 +154,7 @@ private:
std::mutex mFileSync;
const Settings &mSettings;
CppCheck::ExecuteCmdFn mExecuteCommand;
public:
SyncLogForwarder logForwarder;
@ -180,7 +182,7 @@ unsigned int ThreadExecutor::check()
std::vector<std::future<unsigned int>> threadFutures;
threadFutures.reserve(mSettings.jobs);
ThreadData data(*this, mErrorLogger, mSettings, mFiles, mSettings.project.fileSettings);
ThreadData data(*this, mErrorLogger, mSettings, mFiles, mSettings.project.fileSettings, mExecuteCommand);
for (unsigned int i = 0; i < mSettings.jobs; ++i) {
try {

View File

@ -19,6 +19,7 @@
#ifndef THREADEXECUTOR_H
#define THREADEXECUTOR_H
#include "cppcheck.h"
#include "executor.h"
#include <cstddef>
@ -37,14 +38,16 @@ class Suppressions;
* all files using threads.
*/
class ThreadExecutor : public Executor {
friend class SyncLogForwarder;
public:
ThreadExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger);
ThreadExecutor(const std::map<std::string, std::size_t> &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
ThreadExecutor(const ThreadExecutor &) = delete;
void operator=(const ThreadExecutor &) = delete;
unsigned int check() override;
friend class SyncLogForwarder;
CppCheck::ExecuteCmdFn mExecuteCommand;
};
/// @}

View File

@ -54,8 +54,8 @@ class CPPCHECKLIB Library {
// TODO: get rid of this
friend class TestSymbolDatabase; // For testing only
friend class TestSingleExecutorBase; // For testing only
friend class TestThreadExecutor; // For testing only
friend class TestProcessExecutor; // For testing only
friend class TestThreadExecutorBase; // For testing only
friend class TestProcessExecutorBase; // For testing only
public:
Library() = default;

View File

@ -34,15 +34,18 @@
#include <utility>
#include <vector>
class TestProcessExecutor : public TestFixture {
class TestProcessExecutorBase : public TestFixture {
public:
TestProcessExecutor() : TestFixture("TestProcessExecutor") {}
TestProcessExecutorBase(const char * const name, bool useFS) : TestFixture(name), useFS(useFS) {}
private:
Settings settings = settingsBuilder().library("std.cfg").build();
bool useFS;
static std::string fprefix()
std::string fprefix() const
{
if (useFS)
return "processfs";
return "process";
}
@ -53,6 +56,10 @@ private:
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr;
std::vector<std::string> filesList;
bool clangTidy = false;
bool executeCommandCalled = false;
std::string exe;
std::vector<std::string> args;
};
/**
@ -63,35 +70,67 @@ private:
errout.str("");
output.str("");
Settings s = settings;
std::map<std::string, std::size_t> filemap;
if (opt.filesList.empty()) {
for (int i = 1; i <= files; ++i) {
std::ostringstream oss;
oss << fprefix() << "_" << i << ".cpp";
filemap[oss.str()] = data.size();
std::string f_s = fprefix() + "_" + std::to_string(i) + ".cpp";
filemap[f_s] = data.size();
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = std::move(f_s);
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
else {
for (const auto& f : opt.filesList)
{
filemap[f] = data.size();
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = f;
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
Settings s = settings;
s.jobs = jobs;
s.showtime = opt.showtime;
settings.quiet = opt.quiet;
s.quiet = opt.quiet;
if (opt.plistOutput)
s.plistOutput = opt.plistOutput;
// TODO: test with settings.project.fileSettings;
ProcessExecutor executor(filemap, s, s.nomsg, *this);
bool executeCommandCalled = false;
std::string exe;
std::vector<std::string> args;
// NOLINTNEXTLINE(performance-unnecessary-value-param)
auto executeFn = [&executeCommandCalled, &exe, &args](std::string e,std::vector<std::string> a,std::string,std::string&){
executeCommandCalled = true;
exe = std::move(e);
args = std::move(a);
return EXIT_SUCCESS;
};
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));
// clear files list so only fileSettings are used
if (useFS)
filemap.clear();
ProcessExecutor executor(filemap, s, s.nomsg, *this, executeFn);
ASSERT_EQUALS(result, executor.check());
ASSERT_EQUALS(opt.executeCommandCalled, executeCommandCalled);
ASSERT_EQUALS(opt.exe, exe);
ASSERT_EQUALS(opt.args.size(), args.size());
for (int i = 0; i < args.size(); ++i)
{
ASSERT_EQUALS(opt.args[i], args[i]);
}
}
void run() override {
@ -106,6 +145,7 @@ private:
TEST_CASE(one_error_less_files);
TEST_CASE(one_error_several_files);
TEST_CASE(markup);
TEST_CASE(clangTidy);
TEST_CASE(showtime_top5_file);
TEST_CASE(showtime_top5_summary);
TEST_CASE(showtime_file);
@ -148,7 +188,7 @@ private:
}
void many_threads_plist() {
const char plistOutput[] = "plist_process/";
const std::string plistOutput = "plist_" + fprefix() + "/";
ScopedFile plistFile("dummy", "", plistOutput);
check(16, 100, 100,
@ -156,7 +196,7 @@ private:
"{\n"
" char *a = malloc(10);\n"
" return 0;\n"
"}", dinit(CheckOptions, $.plistOutput = plistOutput));
"}", dinit(CheckOptions, $.plistOutput = plistOutput.c_str()));
}
void no_errors_more_files() {
@ -241,6 +281,34 @@ private:
settings = settingsOld;
}
void clangTidy() {
// TODO: we currently only invoke it with ImportProject::FileSettings
if (!useFS)
return;
#ifdef _WIN32
const char exe[] = "clang-tidy.exe";
#else
const char exe[] = "clang-tidy";
#endif
(void)exe;
const std::string file = fprefix() + "_1.cpp";
// TODO: the invocation cannot be checked as the code is called in the forked process
check(2, 1, 0,
"int main()\n"
"{\n"
" return 0;\n"
"}",
dinit(CheckOptions,
$.quiet = false,
$.clangTidy = true /*,
$.executeCommandCalled = true,
$.exe = exe,
$.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"}*/));
ASSERT_EQUALS("Checking " + file + " ...\n", output.str());
}
// TODO: provide data which actually shows values above 0
// TODO: should this be logged only once like summary?
@ -303,8 +371,18 @@ private:
TODO_ASSERT(output_s.find("Check time: " + fprefix() + "_2.cpp: ") != std::string::npos);
}
// TODO: test clang-tidy
// TODO: test whole program analysis
};
REGISTER_TEST(TestProcessExecutor)
class TestProcessExecutorFiles : public TestProcessExecutorBase {
public:
TestProcessExecutorFiles() : TestProcessExecutorBase("TestProcessExecutorFiles", false) {}
};
class TestProcessExecutorFS : public TestProcessExecutorBase {
public:
TestProcessExecutorFS() : TestProcessExecutorBase("TestProcessExecutorFS", true) {}
};
REGISTER_TEST(TestProcessExecutorFiles)
REGISTER_TEST(TestProcessExecutorFS)

View File

@ -68,6 +68,7 @@ private:
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr;
std::vector<std::string> filesList;
bool clangTidy = false;
bool executeCommandCalled = false;
std::string exe;
std::vector<std::string> args;
@ -76,17 +77,18 @@ private:
void check(int files, int result, const std::string &data, const CheckOptions& opt = make_default_obj{}) {
errout.str("");
output.str("");
settings.project.fileSettings.clear();
Settings s = settings;
std::map<std::string, std::size_t> filemap;
if (opt.filesList.empty()) {
for (int i = 1; i <= files; ++i) {
const std::string s = fprefix() + "_" + zpad3(i) + ".cpp";
filemap[s] = data.size();
std::string f_s = fprefix() + "_" + zpad3(i) + ".cpp";
filemap[f_s] = data.size();
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = s;
settings.project.fileSettings.emplace_back(std::move(fs));
fs.filename = std::move(f_s);
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
@ -97,15 +99,16 @@ private:
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = f;
settings.project.fileSettings.emplace_back(std::move(fs));
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
settings.showtime = opt.showtime;
settings.quiet = opt.quiet;
s.showtime = opt.showtime;
s.quiet = opt.quiet;
if (opt.plistOutput)
settings.plistOutput = opt.plistOutput;
s.plistOutput = opt.plistOutput;
s.clangTidy = opt.clangTidy;
bool executeCommandCalled = false;
std::string exe;
@ -117,7 +120,7 @@ private:
args = std::move(a);
return EXIT_SUCCESS;
});
cppcheck.settings() = settings;
cppcheck.settings() = s;
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
scopedfiles.reserve(filemap.size());
@ -128,8 +131,7 @@ private:
if (useFS)
filemap.clear();
// TODO: test with settings.project.fileSettings;
SingleExecutor executor(cppcheck, filemap, settings, settings.nomsg, *this);
SingleExecutor executor(cppcheck, filemap, s, s.nomsg, *this);
ASSERT_EQUALS(result, executor.check());
ASSERT_EQUALS(opt.executeCommandCalled, executeCommandCalled);
ASSERT_EQUALS(opt.exe, exe);
@ -274,9 +276,6 @@ private:
if (!useFS)
return;
const Settings settingsOld = settings;
settings.clangTidy = true;
#ifdef _WIN32
const char exe[] = "clang-tidy.exe";
#else
@ -291,11 +290,11 @@ private:
"}",
dinit(CheckOptions,
$.quiet = false,
$.clangTidy = true,
$.executeCommandCalled = true,
$.exe = exe,
$.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"}));
ASSERT_EQUALS("Checking " + file + " ...\n", output.str());
settings = settingsOld;
}
// TODO: provide data which actually shows values above 0

View File

@ -235,7 +235,7 @@ private:
if (!suppression.empty()) {
EXPECT_EQ("", settings.nomsg.addSuppressionLine(suppression));
}
ThreadExecutor executor(files, settings, settings.nomsg, *this);
ThreadExecutor executor(files, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
scopedfiles.reserve(files.size());
for (std::map<std::string, std::size_t>::const_iterator i = files.cbegin(); i != files.cend(); ++i)
@ -263,7 +263,7 @@ private:
if (!suppression.empty()) {
EXPECT_EQ("", settings.nomsg.addSuppressionLine(suppression));
}
ProcessExecutor executor(files, settings, settings.nomsg, *this);
ProcessExecutor executor(files, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
scopedfiles.reserve(files.size());
for (std::map<std::string, std::size_t>::const_iterator i = files.cbegin(); i != files.cend(); ++i)

View File

@ -34,15 +34,18 @@
#include <utility>
#include <vector>
class TestThreadExecutor : public TestFixture {
class TestThreadExecutorBase : public TestFixture {
public:
TestThreadExecutor() : TestFixture("TestThreadExecutor") {}
TestThreadExecutorBase(const char * const name, bool useFS) : TestFixture(name), useFS(useFS) {}
private:
Settings settings = settingsBuilder().library("std.cfg").build();
bool useFS;
static std::string fprefix()
std::string fprefix() const
{
if (useFS)
return "threadfs";
return "thread";
}
@ -53,6 +56,10 @@ private:
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
const char* plistOutput = nullptr;
std::vector<std::string> filesList;
bool clangTidy = false;
bool executeCommandCalled = false;
std::string exe;
std::vector<std::string> args;
};
/**
@ -63,35 +70,68 @@ private:
errout.str("");
output.str("");
Settings s = settings;
std::map<std::string, std::size_t> filemap;
if (opt.filesList.empty()) {
for (int i = 1; i <= files; ++i) {
std::ostringstream oss;
oss << fprefix() << "_" << i << ".cpp";
filemap[oss.str()] = data.size();
std::string f_s = fprefix() + "_" + std::to_string(i) + ".cpp";
filemap[f_s] = data.size();
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = std::move(f_s);
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
else {
for (const auto& f : opt.filesList)
{
filemap[f] = data.size();
if (useFS) {
ImportProject::FileSettings fs;
fs.filename = f;
s.project.fileSettings.emplace_back(std::move(fs));
}
}
}
Settings settings1 = settings;
settings1.jobs = jobs;
settings1.showtime = opt.showtime;
settings1.quiet = opt.quiet;
s.jobs = jobs;
s.showtime = opt.showtime;
s.quiet = opt.quiet;
if (opt.plistOutput)
settings1.plistOutput = opt.plistOutput;
// TODO: test with settings.project.fileSettings;
ThreadExecutor executor(filemap, settings1, settings1.nomsg, *this);
s.plistOutput = opt.plistOutput;
s.clangTidy = opt.clangTidy;
bool executeCommandCalled = false;
std::string exe;
std::vector<std::string> args;
// NOLINTNEXTLINE(performance-unnecessary-value-param)
auto executeFn = [&executeCommandCalled, &exe, &args](std::string e,std::vector<std::string> a,std::string,std::string&){
executeCommandCalled = true;
exe = std::move(e);
args = std::move(a);
return EXIT_SUCCESS;
};
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));
// clear files list so only fileSettings are used
if (useFS)
filemap.clear();
ThreadExecutor executor(filemap, s, s.nomsg, *this, executeFn);
ASSERT_EQUALS(result, executor.check());
ASSERT_EQUALS(opt.executeCommandCalled, executeCommandCalled);
ASSERT_EQUALS(opt.exe, exe);
ASSERT_EQUALS(opt.args.size(), args.size());
for (int i = 0; i < args.size(); ++i)
{
ASSERT_EQUALS(opt.args[i], args[i]);
}
}
void run() override {
@ -105,6 +145,7 @@ private:
TEST_CASE(one_error_less_files);
TEST_CASE(one_error_several_files);
TEST_CASE(markup);
TEST_CASE(clangTidy);
TEST_CASE(showtime_top5_file);
TEST_CASE(showtime_top5_summary);
TEST_CASE(showtime_file);
@ -142,12 +183,11 @@ private:
"{\n"
" char *a = malloc(10);\n"
" return 0;\n"
"}", dinit(CheckOptions,
$.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
"}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
}
void many_threads_plist() {
const char plistOutput[] = "plist_thread/";
const std::string plistOutput = "plist_" + fprefix() + "/";
ScopedFile plistFile("dummy", "", plistOutput);
check(16, 100, 100,
@ -155,8 +195,7 @@ private:
"{\n"
" char *a = malloc(10);\n"
" return 0;\n"
"}", dinit(CheckOptions,
$.plistOutput = plistOutput));
"}", dinit(CheckOptions, $.plistOutput = plistOutput.c_str()));
}
void no_errors_more_files() {
@ -217,7 +256,9 @@ private:
" char *a = malloc(10);\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_ASSERT_EQUALS("Checking " + fprefix() + "_2.cpp ...\n"
"1/4 files checked 25% done\n"
@ -239,6 +280,31 @@ private:
settings = settingsOld;
}
void clangTidy() {
// TODO: we currently only invoke it with ImportProject::FileSettings
if (!useFS)
return;
#ifdef _WIN32
const char exe[] = "clang-tidy.exe";
#else
const char exe[] = "clang-tidy";
#endif
const std::string file = fprefix() + "_1.cpp";
check(2, 1, 0,
"int main()\n"
"{\n"
" return 0;\n"
"}",
dinit(CheckOptions,
$.quiet = false,
$.clangTidy = true,
$.executeCommandCalled = true,
$.exe = exe,
$.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"}));
ASSERT_EQUALS("Checking " + file + " ...\n", output.str());
}
// TODO: provide data which actually shows values above 0
@ -302,8 +368,18 @@ private:
ASSERT(output_s.find("Check time: " + fprefix() + "_2.cpp: ") != std::string::npos);
}
// TODO: test clang-tidy
// TODO: test whole program analysis
};
REGISTER_TEST(TestThreadExecutor)
class TestThreadExecutorFiles : public TestThreadExecutorBase {
public:
TestThreadExecutorFiles() : TestThreadExecutorBase("TestThreadExecutorFiles", false) {}
};
class TestThreadExecutorFS : public TestThreadExecutorBase {
public:
TestThreadExecutorFS() : TestThreadExecutorBase("TestThreadExecutorFS", true) {}
};
REGISTER_TEST(TestThreadExecutorFiles)
REGISTER_TEST(TestThreadExecutorFS)