From d29d9dbce3ef13eea3c9c6495615f8b08b817f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 13 Mar 2024 11:19:29 +0100 Subject: [PATCH 1/3] Fix #12505 (cli: Add option --check-version to pin cppcheck version) --- cli/cmdlineparser.cpp | 31 ++++++++++++++++++++++--------- releasenotes.txt | 3 ++- test/testcmdlineparser.cpp | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 59cf67847fa..a3919c872d0 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -117,6 +117,15 @@ static bool addPathsToSet(const std::string& fileName, std::set& se return true; } +static std::string getVersion(const Settings& settings) { + if (!settings.cppcheckCfgProductName.empty()) + return settings.cppcheckCfgProductName; + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != '\0') + return std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'; + return std::string("Cppcheck ") + CppCheck::version(); +} + namespace { class XMLErrorMessagesLogger : public ErrorLogger { @@ -356,15 +365,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (std::strcmp(argv[i], "--version") == 0) { if (!loadCppcheckCfg()) return Result::Fail; - if (!mSettings.cppcheckCfgProductName.empty()) { - mLogger.printRaw(mSettings.cppcheckCfgProductName); - } else { - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != '\0') - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); - else - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); - } + const std::string version = getVersion(mSettings); + mLogger.printRaw(version); return Result::Exit; } } @@ -488,6 +490,17 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.checkLibrary = true; } + else if (std::strncmp(argv[i], "--check-version=", 16) == 0) { + if (!loadCppcheckCfg()) + return Result::Fail; + const std::string actualVersion = getVersion(mSettings); + const std::string wantedVersion = argv[i] + 16; + if (actualVersion != wantedVersion) { + mLogger.printError("--check-version check failed. Aborting."); + return Result::Fail; + } + } + else if (std::strncmp(argv[i], "--checkers-report=", 18) == 0) mSettings.checkersReportFilename = argv[i] + 18; diff --git a/releasenotes.txt b/releasenotes.txt index f68333b7075..56c7500bc41 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -26,4 +26,5 @@ Other: - Added CMake option 'DISALLOW_THREAD_EXECUTOR' to control the inclusion of the executor which performs the analysis within a thread of the main process. - Removed CMake option 'USE_THREADS' in favor of 'DISALLOW_THREAD_EXECUTOR'. - Fixed crash with '--rule-file=' if some data was missing. -- '--rule-file' will now bail out if a rule could not be added or a file contains unexpected data. \ No newline at end of file +- '--rule-file' will now bail out if a rule could not be added or a file contains unexpected data. +- Add option '--check-version', you can use it to pin the cppcheck version in a script. diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 60a56efbccc..7ea8d48cee2 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -119,6 +119,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(versionWithCfg); TEST_CASE(versionExclusive); TEST_CASE(versionWithInvalidCfg); + TEST_CASE(checkVersion); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -471,6 +472,23 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 2 near: \n", logger->str()); } + void checkVersion() { + REDIRECT; + // get version + const char * const argv1[] = {"cppcheck", "--version"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv1)); + std::string version = logger->str(); + version.erase(version.find('\n')); + const std::string checkCorrectVersion = "--check-version=" + version; + // check version: correct version + const char * const argv2[] = {"cppcheck", checkCorrectVersion.c_str(), "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv2)); + // check version: incorrect version + const char * const argv3[] = {"cppcheck", "--check-version=Cppcheck 2.0", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv3)); + ASSERT_EQUALS("cppcheck: error: --check-version check failed. Aborting.\n", logger->str()); + } + void onefile() { REDIRECT; const char * const argv[] = {"cppcheck", "file.cpp"}; From 6a947495a8695d79684b3e27d73e7d1cfe9ac993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 13 Mar 2024 14:41:53 +0100 Subject: [PATCH 2/3] review: split testfunction --- cli/cmdlineparser.cpp | 22 +++++++++++----------- cli/cmdlineparser.h | 5 +++++ test/testcmdlineparser.cpp | 29 ++++++++++++++--------------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index a3919c872d0..9051d4fad59 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -117,15 +117,6 @@ static bool addPathsToSet(const std::string& fileName, std::set& se return true; } -static std::string getVersion(const Settings& settings) { - if (!settings.cppcheckCfgProductName.empty()) - return settings.cppcheckCfgProductName; - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != '\0') - return std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'; - return std::string("Cppcheck ") + CppCheck::version(); -} - namespace { class XMLErrorMessagesLogger : public ErrorLogger { @@ -365,7 +356,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (std::strcmp(argv[i], "--version") == 0) { if (!loadCppcheckCfg()) return Result::Fail; - const std::string version = getVersion(mSettings); + const std::string version = getVersion(); mLogger.printRaw(version); return Result::Exit; } @@ -493,7 +484,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strncmp(argv[i], "--check-version=", 16) == 0) { if (!loadCppcheckCfg()) return Result::Fail; - const std::string actualVersion = getVersion(mSettings); + const std::string actualVersion = getVersion(); const std::string wantedVersion = argv[i] + 16; if (actualVersion != wantedVersion) { mLogger.printError("--check-version check failed. Aborting."); @@ -1749,6 +1740,15 @@ void CmdLineParser::printHelp() const mLogger.printRaw(oss.str()); } +std::string CmdLineParser::getVersion() const { + if (!mSettings.cppcheckCfgProductName.empty()) + return mSettings.cppcheckCfgProductName; + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != '\0') + return std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'; + return std::string("Cppcheck ") + CppCheck::version(); +} + bool CmdLineParser::isCppcheckPremium() const { if (mSettings.cppcheckCfgProductName.empty()) Settings::loadCppcheckCfg(mSettings, mSettings.supprs); diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index 4e41094ee10..6f3a2738932 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -102,6 +102,11 @@ class CmdLineParser { return mIgnoredPaths; } + /** + * Get Cppcheck version + */ + std::string getVersion() const; + protected: /** diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 7ea8d48cee2..64417c2f6bf 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -119,7 +119,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(versionWithCfg); TEST_CASE(versionExclusive); TEST_CASE(versionWithInvalidCfg); - TEST_CASE(checkVersion); + TEST_CASE(checkVersionCorrect); + TEST_CASE(checkVersionIncorrect); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -472,20 +473,18 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 2 near: \n", logger->str()); } - void checkVersion() { - REDIRECT; - // get version - const char * const argv1[] = {"cppcheck", "--version"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv1)); - std::string version = logger->str(); - version.erase(version.find('\n')); - const std::string checkCorrectVersion = "--check-version=" + version; - // check version: correct version - const char * const argv2[] = {"cppcheck", checkCorrectVersion.c_str(), "file.cpp"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv2)); - // check version: incorrect version - const char * const argv3[] = {"cppcheck", "--check-version=Cppcheck 2.0", "file.cpp"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv3)); + void checkVersionCorrect() { + REDIRECT; + const std::string version = parser->getVersion(); + const std::string checkVersion = "--check-version=" + version; + const char * const argv[] = {"cppcheck", checkVersion.c_str(), "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + } + + void checkVersionIncorrect() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--check-version=Cppcheck 2.0", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --check-version check failed. Aborting.\n", logger->str()); } From db9bd63d0a333a656b4f3fc909e01496e205b2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 28 Mar 2024 22:28:31 +0100 Subject: [PATCH 3/3] Fix self check --- test/testcmdlineparser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 64417c2f6bf..8e4298f27ee 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -475,8 +475,8 @@ class TestCmdlineParser : public TestFixture { void checkVersionCorrect() { REDIRECT; - const std::string version = parser->getVersion(); - const std::string checkVersion = "--check-version=" + version; + const std::string currentVersion = parser->getVersion(); + const std::string checkVersion = "--check-version=" + currentVersion; const char * const argv[] = {"cppcheck", checkVersion.c_str(), "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); }