testrunner: use structs with designated initialization to pass options (#4975)
I need to add parameters to some `check()` functions in the tests and things are already pretty messy with having to specify all the default values - readability aside. I found this on https://stackoverflow.com/a/49572324/532627 - apparently the CC BY-SA license by StackOverflow allows the usage within GPL.
This commit is contained in:
parent
4aae670b45
commit
5d201c4e87
|
@ -35,6 +35,10 @@ if (BUILD_TESTS)
|
||||||
target_compile_definitions(testrunner PRIVATE CPPCHECKLIB_IMPORT SIMPLECPP_IMPORT)
|
target_compile_definitions(testrunner PRIVATE CPPCHECKLIB_IMPORT SIMPLECPP_IMPORT)
|
||||||
target_link_libraries(testrunner cppcheck-core)
|
target_link_libraries(testrunner cppcheck-core)
|
||||||
endif()
|
endif()
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
# $ is used in dinit() dessignated initialization helper
|
||||||
|
target_compile_options_safe(testrunner -Wno-dollar-in-identifier-extension)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
||||||
target_precompile_headers(testrunner PRIVATE precompiled.h)
|
target_precompile_headers(testrunner PRIVATE precompiled.h)
|
||||||
|
|
|
@ -92,4 +92,31 @@ 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* designated initialization helper
|
||||||
|
Usage:
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto s = dinit(S,
|
||||||
|
$.i = 1
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
#define dinit(T, ...) \
|
||||||
|
([&] { T ${}; __VA_ARGS__; return $; }())
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__)
|
||||||
|
// work around Clang compilation error
|
||||||
|
// error: default member initializer for 'y' needed within definition of enclosing class 'X' outside of member functions
|
||||||
|
// work around GCC compilation error
|
||||||
|
// error: default member initializer for ‘x::y::z’ required before the end of its enclosing class
|
||||||
|
// see https://stackoverflow.com/questions/53408962
|
||||||
|
#define DINIT_NOEXCEPT noexcept
|
||||||
|
#else
|
||||||
|
// work around GCC 4.8 compilation error
|
||||||
|
// error: function 'x()' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'x()'
|
||||||
|
#define DINIT_NOEXCEPT
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // helpersH
|
#endif // helpersH
|
||||||
|
|
|
@ -46,16 +46,24 @@ private:
|
||||||
return "process";
|
return "process";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CheckOptions
|
||||||
|
{
|
||||||
|
CheckOptions() DINIT_NOEXCEPT = default;
|
||||||
|
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
|
||||||
|
const char* plistOutput = nullptr;
|
||||||
|
std::vector<std::string> filesList;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute check using n jobs for y files which are have
|
* Execute check using n jobs for y files which are have
|
||||||
* identical data, given within data.
|
* 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, const std::vector<std::string>& filesList = {}) {
|
void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions &opt = {}) {
|
||||||
errout.str("");
|
errout.str("");
|
||||||
output.str("");
|
output.str("");
|
||||||
|
|
||||||
std::map<std::string, std::size_t> filemap;
|
std::map<std::string, std::size_t> filemap;
|
||||||
if (filesList.empty()) {
|
if (opt.filesList.empty()) {
|
||||||
for (int i = 1; i <= files; ++i) {
|
for (int i = 1; i <= files; ++i) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << fprefix() << "_" << i << ".cpp";
|
oss << fprefix() << "_" << i << ".cpp";
|
||||||
|
@ -63,16 +71,16 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (const auto& f : filesList)
|
for (const auto& f : opt.filesList)
|
||||||
{
|
{
|
||||||
filemap[f] = data.size();
|
filemap[f] = data.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.jobs = jobs;
|
settings.jobs = jobs;
|
||||||
settings.showtime = showtime;
|
settings.showtime = opt.showtime;
|
||||||
if (plistOutput)
|
if (opt.plistOutput)
|
||||||
settings.plistOutput = plistOutput;
|
settings.plistOutput = opt.plistOutput;
|
||||||
// TODO: test with settings.project.fileSettings;
|
// TODO: test with settings.project.fileSettings;
|
||||||
ProcessExecutor executor(filemap, settings, *this);
|
ProcessExecutor executor(filemap, settings, *this);
|
||||||
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
|
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
|
||||||
|
@ -127,7 +135,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_SUMMARY);
|
"}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void many_threads_plist() {
|
void many_threads_plist() {
|
||||||
|
@ -139,7 +147,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_NONE, plistOutput);
|
"}", dinit(CheckOptions, $.plistOutput = plistOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
void no_errors_more_files() {
|
void no_errors_more_files() {
|
||||||
|
@ -184,7 +192,6 @@ private:
|
||||||
"}");
|
"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void markup() {
|
void markup() {
|
||||||
const Settings settingsOld = settings;
|
const Settings settingsOld = settings;
|
||||||
settings.library.mMarkupExtensions.emplace(".cp1");
|
settings.library.mMarkupExtensions.emplace(".cp1");
|
||||||
|
@ -201,7 +208,7 @@ private:
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}",
|
"}",
|
||||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
dinit(CheckOptions, $.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"
|
||||||
|
|
|
@ -61,13 +61,21 @@ private:
|
||||||
return 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 = {}) {
|
struct CheckOptions
|
||||||
|
{
|
||||||
|
CheckOptions() DINIT_NOEXCEPT = default;
|
||||||
|
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
|
||||||
|
const char* plistOutput = nullptr;
|
||||||
|
std::vector<std::string> filesList;
|
||||||
|
};
|
||||||
|
|
||||||
|
void check(int files, int result, const std::string &data, const CheckOptions &opt = {}) {
|
||||||
errout.str("");
|
errout.str("");
|
||||||
output.str("");
|
output.str("");
|
||||||
settings.project.fileSettings.clear();
|
settings.project.fileSettings.clear();
|
||||||
|
|
||||||
std::map<std::string, std::size_t> filemap;
|
std::map<std::string, std::size_t> filemap;
|
||||||
if (filesList.empty()) {
|
if (opt.filesList.empty()) {
|
||||||
for (int i = 1; i <= files; ++i) {
|
for (int i = 1; i <= files; ++i) {
|
||||||
const std::string s = fprefix() + "_" + zpad3(i) + ".cpp";
|
const std::string s = fprefix() + "_" + zpad3(i) + ".cpp";
|
||||||
filemap[s] = data.size();
|
filemap[s] = data.size();
|
||||||
|
@ -79,7 +87,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (const auto& f : filesList)
|
for (const auto& f : opt.filesList)
|
||||||
{
|
{
|
||||||
filemap[f] = data.size();
|
filemap[f] = data.size();
|
||||||
if (useFS) {
|
if (useFS) {
|
||||||
|
@ -90,9 +98,9 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.showtime = showtime;
|
settings.showtime = opt.showtime;
|
||||||
if (plistOutput)
|
if (opt.plistOutput)
|
||||||
settings.plistOutput = plistOutput;
|
settings.plistOutput = opt.plistOutput;
|
||||||
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
||||||
CppCheck cppcheck(*this, true, [](std::string,std::vector<std::string>,std::string,std::string&){
|
CppCheck cppcheck(*this, true, [](std::string,std::vector<std::string>,std::string,std::string&){
|
||||||
return false;
|
return false;
|
||||||
|
@ -152,7 +160,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_SUMMARY);
|
"}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void many_files_plist() {
|
void many_files_plist() {
|
||||||
|
@ -164,7 +172,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_NONE, plistOutput);
|
"}", dinit(CheckOptions, $.plistOutput = plistOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
void no_errors_more_files() {
|
void no_errors_more_files() {
|
||||||
|
@ -225,7 +233,7 @@ private:
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}",
|
"}",
|
||||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
dinit(CheckOptions, $.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"
|
||||||
|
|
|
@ -46,16 +46,24 @@ private:
|
||||||
return "thread";
|
return "thread";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CheckOptions
|
||||||
|
{
|
||||||
|
CheckOptions() DINIT_NOEXCEPT = default;
|
||||||
|
SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE;
|
||||||
|
const char* plistOutput = nullptr;
|
||||||
|
std::vector<std::string> filesList;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute check using n jobs for y files which are have
|
* Execute check using n jobs for y files which are have
|
||||||
* identical data, given within data.
|
* 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, const std::vector<std::string>& filesList = {}) {
|
void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions &opt = {}) {
|
||||||
errout.str("");
|
errout.str("");
|
||||||
output.str("");
|
output.str("");
|
||||||
|
|
||||||
std::map<std::string, std::size_t> filemap;
|
std::map<std::string, std::size_t> filemap;
|
||||||
if (filesList.empty()) {
|
if (opt.filesList.empty()) {
|
||||||
for (int i = 1; i <= files; ++i) {
|
for (int i = 1; i <= files; ++i) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << fprefix() << "_" << i << ".cpp";
|
oss << fprefix() << "_" << i << ".cpp";
|
||||||
|
@ -63,7 +71,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (const auto& f : filesList)
|
for (const auto& f : opt.filesList)
|
||||||
{
|
{
|
||||||
filemap[f] = data.size();
|
filemap[f] = data.size();
|
||||||
}
|
}
|
||||||
|
@ -71,9 +79,9 @@ private:
|
||||||
|
|
||||||
Settings settings1 = settings;
|
Settings settings1 = settings;
|
||||||
settings1.jobs = jobs;
|
settings1.jobs = jobs;
|
||||||
settings1.showtime = showtime;
|
settings1.showtime = opt.showtime;
|
||||||
if (plistOutput)
|
if (opt.plistOutput)
|
||||||
settings1.plistOutput = plistOutput;
|
settings1.plistOutput = opt.plistOutput;
|
||||||
// TODO: test with settings.project.fileSettings;
|
// TODO: test with settings.project.fileSettings;
|
||||||
ThreadExecutor executor(filemap, settings1, *this);
|
ThreadExecutor executor(filemap, settings1, *this);
|
||||||
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
|
std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
|
||||||
|
@ -126,7 +134,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_SUMMARY);
|
"}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void many_threads_plist() {
|
void many_threads_plist() {
|
||||||
|
@ -138,7 +146,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", SHOWTIME_MODES::SHOWTIME_NONE, plistOutput);
|
"}", dinit(CheckOptions, $.plistOutput = plistOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
void no_errors_more_files() {
|
void no_errors_more_files() {
|
||||||
|
@ -199,7 +207,7 @@ private:
|
||||||
" char *a = malloc(10);\n"
|
" char *a = malloc(10);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}",
|
"}",
|
||||||
SHOWTIME_MODES::SHOWTIME_NONE, nullptr, files);
|
dinit(CheckOptions, $.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"
|
||||||
|
|
Loading…
Reference in New Issue