Skip to content

Commit 3272a2b

Browse files
authored
greatly improved Settings::loadCppcheckCfg() error handling (danmar#5712)
This also fixes the issue that `cppcheck.cfg` is no longer being loaded from executable path. That was introduced by danmar#5704.
1 parent 4182f94 commit 3272a2b

File tree

10 files changed

+278
-44
lines changed

10 files changed

+278
-44
lines changed

.github/workflows/cppcheck-premium.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ jobs:
4040
- name: Check
4141
run: |
4242
cppcheckpremium-${{ env.PREMIUM_VERSION }}/premiumaddon --check-loc-license cppcheck.lic > cppcheck-premium-loc
43-
cppcheckpremium-${{ env.PREMIUM_VERSION }}/cppcheck -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2008 --premium=cert-c++-2016 --error-exitcode=1 lib
43+
cppcheckpremium-${{ env.PREMIUM_VERSION }}/cppcheck -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2008 --premium=cert-c++-2016 --inline-suppr --error-exitcode=1 lib

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ test/testclangimport.o: test/testclangimport.cpp lib/addoninfo.h lib/check.h lib
728728
test/testclass.o: test/testclass.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkclass.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.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
729729
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp
730730

731-
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h
731+
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.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/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h
732732
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp
733733

734734
test/testcolor.o: test/testcolor.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.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
@@ -809,7 +809,7 @@ test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp
809809
test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h
810810
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprocessexecutor.cpp
811811

812-
test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.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
812+
test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
813813
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp
814814

815815
test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.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

cli/cmdlineparser.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[])
282282
// TODO: error out on all missing given files/paths
283283
CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[])
284284
{
285+
mSettings.exename = Path::getCurrentExecutablePath(argv[0]);
286+
285287
if (argc <= 1) {
286288
printHelp();
287289
return Result::Exit;
@@ -307,7 +309,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
307309

308310
// print all possible error messages..
309311
if (std::strcmp(argv[i], "--errorlist") == 0) {
310-
mSettings.loadCppcheckCfg();
312+
if (!loadCppcheckCfg())
313+
return Result::Fail;
311314
{
312315
XMLErrorMessagesLogger xmlLogger;
313316
std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName);
@@ -324,7 +327,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
324327
}
325328

326329
if (std::strcmp(argv[i], "--version") == 0) {
327-
mSettings.loadCppcheckCfg();
330+
if (!loadCppcheckCfg())
331+
return Result::Fail;
328332
if (!mSettings.cppcheckCfgProductName.empty()) {
329333
mLogger.printRaw(mSettings.cppcheckCfgProductName);
330334
} else {
@@ -343,8 +347,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
343347

344348
ImportProject project;
345349

346-
mSettings.exename = Path::getCurrentExecutablePath(argv[0]);
347-
348350
for (int i = 1; i < argc; i++) {
349351
if (argv[i][0] == '-') {
350352
// User define
@@ -1203,7 +1205,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
12031205
}
12041206
}
12051207

1206-
mSettings.loadCppcheckCfg();
1208+
if (!loadCppcheckCfg())
1209+
return Result::Fail;
12071210

12081211
// Default template format..
12091212
if (mSettings.templateFormat.empty()) {
@@ -1609,10 +1612,10 @@ void CmdLineParser::printHelp() const
16091612
mLogger.printRaw(oss.str());
16101613
}
16111614

1612-
bool CmdLineParser::isCppcheckPremium() const {
1613-
if (mSettings.cppcheckCfgProductName.empty())
1614-
mSettings.loadCppcheckCfg();
1615-
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
1615+
bool CmdLineParser::isCppcheckPremium() {
1616+
Settings settings;
1617+
settings.loadCppcheckCfg(); // TODO: how to handle errors?
1618+
return startsWith(settings.cppcheckCfgProductName, "Cppcheck Premium");
16161619
}
16171620

16181621
bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename)
@@ -1701,3 +1704,14 @@ bool CmdLineParser::loadAddons(Settings& settings)
17011704
}
17021705
return result;
17031706
}
1707+
1708+
bool CmdLineParser::loadCppcheckCfg()
1709+
{
1710+
const std::string cfgErr = mSettings.loadCppcheckCfg();
1711+
if (!cfgErr.empty()) {
1712+
mLogger.printError("could not load cppcheck.cfg - " + cfgErr);
1713+
return false;
1714+
}
1715+
return true;
1716+
}
1717+

cli/cmdlineparser.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class CmdLineParser {
111111
void printHelp() const;
112112

113113
private:
114-
bool isCppcheckPremium() const;
114+
static bool isCppcheckPremium();
115115

116116
template<typename T>
117117
bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)
@@ -150,6 +150,8 @@ class CmdLineParser {
150150
*/
151151
bool loadAddons(Settings& settings);
152152

153+
bool loadCppcheckCfg();
154+
153155
CmdLineLogger &mLogger;
154156

155157
std::vector<std::string> mPathNames;

gui/mainwindow.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
119119
{
120120
Settings tempSettings;
121121
tempSettings.exename = QCoreApplication::applicationFilePath().toStdString();
122-
tempSettings.loadCppcheckCfg();
122+
tempSettings.loadCppcheckCfg(); // TODO: how to handle error?
123123
mCppcheckCfgProductName = QString::fromStdString(tempSettings.cppcheckCfgProductName);
124124
mCppcheckCfgAbout = QString::fromStdString(tempSettings.cppcheckCfgAbout);
125125
}
@@ -903,8 +903,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
903903
return true;
904904
}
905905

906-
Settings MainWindow::getCppcheckSettings()
907-
{
906+
Settings MainWindow::getCppcheckSettings() {
908907
saveSettings(); // Save settings
909908

910909
Settings result;
@@ -915,7 +914,11 @@ Settings MainWindow::getCppcheckSettings()
915914
if (!std)
916915
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.").arg("std.cfg"));
917916

918-
result.loadCppcheckCfg();
917+
{
918+
const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg());
919+
if (!cfgErr.isEmpty())
920+
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2").arg("cppcheck.cfg").arg(cfgErr));
921+
}
919922

920923
// If project file loaded, read settings from it
921924
if (mProjectFile) {

lib/settings.cpp

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,40 +40,87 @@ Settings::Settings()
4040
setCheckLevelNormal();
4141
}
4242

43-
// TODO: report error when the config is invalid
44-
void Settings::loadCppcheckCfg()
43+
std::string Settings::loadCppcheckCfg()
4544
{
46-
std::string fileName = Path::getPathFromFilename(exename) + "cppcheck.cfg";
45+
static const std::string cfgFilename = "cppcheck.cfg";
46+
std::string fileName;
4747
#ifdef FILESDIR
48-
if (Path::isFile(FILESDIR "/cppcheck.cfg"))
49-
fileName = FILESDIR "/cppcheck.cfg";
48+
if (Path::isFile(Path::join(FILESDIR, cfgFilename)))
49+
fileName = Path::join(FILESDIR, cfgFilename);
5050
#endif
51+
// cppcheck-suppress knownConditionTrueFalse
52+
if (fileName.empty()) {
53+
fileName = Path::getPathFromFilename(exename) + cfgFilename;
54+
if (!Path::isFile(fileName))
55+
return "";
56+
}
5157

5258
std::ifstream fin(fileName);
5359
if (!fin.is_open())
54-
return;
60+
return "could not open file";
5561
picojson::value json;
5662
fin >> json;
57-
if (!picojson::get_last_error().empty())
58-
return;
59-
picojson::object obj = json.get<picojson::object>();
60-
if (obj.count("productName") && obj["productName"].is<std::string>())
61-
cppcheckCfgProductName = obj["productName"].get<std::string>();
62-
if (obj.count("about") && obj["about"].is<std::string>())
63-
cppcheckCfgAbout = obj["about"].get<std::string>();
64-
if (obj.count("addons") && obj["addons"].is<picojson::array>()) {
65-
for (const picojson::value &v : obj["addons"].get<picojson::array>()) {
66-
const std::string &s = v.get<std::string>();
67-
if (!Path::isAbsolute(s))
68-
addons.emplace(Path::getPathFromFilename(fileName) + s);
69-
else
70-
addons.emplace(s);
63+
{
64+
const std::string& lastErr = picojson::get_last_error();
65+
if (!lastErr.empty())
66+
return "not a valid JSON - " + lastErr;
67+
}
68+
const picojson::object& obj = json.get<picojson::object>();
69+
{
70+
const picojson::object::const_iterator it = obj.find("productName");
71+
if (it != obj.cend()) {
72+
const auto& v = it->second;
73+
if (!v.is<std::string>())
74+
return "'productName' is not a string";
75+
cppcheckCfgProductName = v.get<std::string>();
7176
}
7277
}
73-
if (obj.count("suppressions") && obj["suppressions"].is<picojson::array>()) {
74-
for (const picojson::value &v : obj["suppressions"].get<picojson::array>())
75-
nomsg.addSuppressionLine(v.get<std::string>());
78+
{
79+
const picojson::object::const_iterator it = obj.find("about");
80+
if (it != obj.cend()) {
81+
const auto& v = it->second;
82+
if (!v.is<std::string>())
83+
return "'about' is not a string";
84+
cppcheckCfgAbout = v.get<std::string>();
85+
}
86+
}
87+
{
88+
const picojson::object::const_iterator it = obj.find("addons");
89+
if (it != obj.cend()) {
90+
const auto& entry = it->second;
91+
if (!entry.is<picojson::array>())
92+
return "'addons' is not an array";
93+
for (const picojson::value &v : entry.get<picojson::array>())
94+
{
95+
if (!v.is<std::string>())
96+
return "'addons' array entry is not a string";
97+
const std::string &s = v.get<std::string>();
98+
if (!Path::isAbsolute(s))
99+
addons.emplace(Path::join(Path::getPathFromFilename(fileName), s));
100+
else
101+
addons.emplace(s);
102+
}
103+
}
76104
}
105+
{
106+
const picojson::object::const_iterator it = obj.find("suppressions");
107+
if (it != obj.cend()) {
108+
const auto& entry = it->second;
109+
if (!entry.is<picojson::array>())
110+
return "'suppressions' is not an array";
111+
for (const picojson::value &v : entry.get<picojson::array>())
112+
{
113+
if (!v.is<std::string>())
114+
return "'suppressions' array entry is not a string";
115+
const std::string &s = v.get<std::string>();
116+
const std::string err = nomsg.addSuppressionLine(s);
117+
if (!err.empty())
118+
return "could not parse suppression '" + s + "' - " + err;
119+
}
120+
}
121+
}
122+
123+
return "";
77124
}
78125

79126
std::string Settings::parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity>, SimpleEnableGroup<Checks>> &groups)

lib/settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class CPPCHECKLIB WARN_UNUSED Settings {
9999
public:
100100
Settings();
101101

102-
void loadCppcheckCfg();
102+
std::string loadCppcheckCfg();
103103

104104
/** @brief addons, either filename of python/json file or json data */
105105
std::unordered_set<std::string> addons;

releasenotes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ Other:
3232
- You can suppress all warnings where macro is used using "-macro"
3333
- fixed CMake build with UBSAN and GCC
3434
- Added command-line options "--fsigned-char" and "--funsigned-char" to control the signess of the "char" type. This overrides previously specified "--platform" options and is overrides by following ones.
35+
- An error is now reported when the "cppcheck.cfg" is invalid. The CLI version will also exit with a failure in that case.

test/testcmdlineparser.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "cppcheckexecutor.h"
2323
#include "errortypes.h"
2424
#include "helpers.h"
25+
#include "path.h"
2526
#include "platform.h"
2627
#include "redirect.h"
2728
#include "settings.h"
@@ -125,6 +126,7 @@ class TestCmdlineParser : public TestFixture {
125126
TEST_CASE(version);
126127
TEST_CASE(versionWithCfg);
127128
TEST_CASE(versionExclusive);
129+
TEST_CASE(versionWithInvalidCfg);
128130
TEST_CASE(onefile);
129131
TEST_CASE(onepath);
130132
TEST_CASE(optionwithoutfile);
@@ -268,7 +270,9 @@ class TestCmdlineParser : public TestFixture {
268270
TEST_CASE(showtimeEmpty);
269271
TEST_CASE(showtimeInvalid);
270272
TEST_CASE(errorlist);
273+
TEST_CASE(errorlistWithCfg);
271274
TEST_CASE(errorlistExclusive);
275+
TEST_CASE(errorlistWithInvalidCfg);
272276
TEST_CASE(ignorepathsnopath);
273277
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
274278
TEST_CASE(exceptionhandling);
@@ -360,6 +364,8 @@ class TestCmdlineParser : public TestFixture {
360364
TEST_CASE(cppcheckBuildDirExistent);
361365
TEST_CASE(cppcheckBuildDirNonExistent);
362366
TEST_CASE(cppcheckBuildDirEmpty);
367+
368+
TEST_CASE(invalidCppcheckCfg);
363369
}
364370

365371
void nooptions() {
@@ -412,7 +418,7 @@ class TestCmdlineParser : public TestFixture {
412418

413419
void versionWithCfg() {
414420
REDIRECT;
415-
ScopedFile file("cppcheck.cfg",
421+
ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
416422
"{\n"
417423
"\"productName\": \"The Product\""
418424
"}\n");
@@ -433,6 +439,16 @@ class TestCmdlineParser : public TestFixture {
433439
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
434440
}
435441

442+
void versionWithInvalidCfg() {
443+
REDIRECT;
444+
ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
445+
"{\n");
446+
const char * const argv[] = {"cppcheck", "--version"};
447+
ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
448+
ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str());
449+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
450+
}
451+
436452
void onefile() {
437453
REDIRECT;
438454
const char * const argv[] = {"cppcheck", "file.cpp"};
@@ -1690,11 +1706,19 @@ class TestCmdlineParser : public TestFixture {
16901706
const char * const argv[] = {"cppcheck", "--errorlist"};
16911707
ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
16921708
ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger
1693-
ASSERT(startsWith(GET_REDIRECT_OUTPUT, "<?xml"));
1709+
ASSERT(startsWith(GET_REDIRECT_OUTPUT, ErrorMessage::getXMLHeader("")));
16941710
ASSERT(endsWith(GET_REDIRECT_OUTPUT, "</results>\n"));
16951711
}
16961712

1697-
// TODO: test --errorlist with product name
1713+
void errorlistWithCfg() {
1714+
REDIRECT;
1715+
ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
1716+
R"({"productName": "The Product"}\n)");
1717+
const char * const argv[] = {"cppcheck", "--errorlist"};
1718+
ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
1719+
ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger
1720+
ASSERT(startsWith(GET_REDIRECT_OUTPUT, ErrorMessage::getXMLHeader("The Product")));
1721+
}
16981722

16991723
void errorlistExclusive() {
17001724
REDIRECT;
@@ -1705,6 +1729,16 @@ class TestCmdlineParser : public TestFixture {
17051729
ASSERT(endsWith(GET_REDIRECT_OUTPUT, "</results>\n"));
17061730
}
17071731

1732+
void errorlistWithInvalidCfg() {
1733+
REDIRECT;
1734+
ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
1735+
"{\n");
1736+
const char * const argv[] = {"cppcheck", "--errorlist"};
1737+
ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1738+
ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str());
1739+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
1740+
}
1741+
17081742
void ignorepathsnopath() {
17091743
REDIRECT;
17101744
const char * const argv[] = {"cppcheck", "-i"};
@@ -2309,6 +2343,15 @@ class TestCmdlineParser : public TestFixture {
23092343
ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
23102344
ASSERT_EQUALS("cppcheck: error: Directory '' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str());
23112345
}
2346+
2347+
void invalidCppcheckCfg() {
2348+
REDIRECT;
2349+
ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
2350+
"{\n");
2351+
const char * const argv[] = {"cppcheck", "test.cpp"};
2352+
ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2353+
ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str());
2354+
}
23122355
};
23132356

23142357
REGISTER_TEST(TestCmdlineParser)

0 commit comments

Comments
 (0)