From 2ff419d70ea3d7fcdf7f7f7106c1cbbbe709c78b Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Tue, 15 Oct 2024 17:05:25 +0300 Subject: [PATCH 1/5] Fix #13216: Add checkers-report block to xml output --- cli/cmdlineparser.cpp | 8 +-- cli/cppcheckexecutor.cpp | 9 ++- lib/checkersreport.cpp | 136 +++++++++++++++++++++++++++++++++++++++ lib/checkersreport.h | 1 + lib/errorlogger.cpp | 8 +-- lib/errorlogger.h | 4 +- 6 files changed, 154 insertions(+), 12 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 5ec8faafad1..c2ae9aa75cc 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -340,7 +340,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; { XMLErrorMessagesLogger xmlLogger; - std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName, mSettings.xml_version); CppCheck::getErrorMessages(xmlLogger); std::cout << ErrorMessage::getXMLFooter() << std::endl; } @@ -1386,9 +1386,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a int tmp; if (!parseNumberArg(argv[i], 14, tmp)) return Result::Fail; - if (tmp != 2) { - // We only have xml version 2 - mLogger.printError("'--xml-version' can only be 2."); + if (tmp != 2 && tmp != 3) { + // We only have xml version 2 and 3 + mLogger.printError("'--xml-version' can only be 2 or 3."); return Result::Fail; } diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 81253b020d2..13d7a78ae09 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -413,7 +413,7 @@ int CppCheckExecutor::check_internal(const Settings& settings) const stdLogger.resetLatestProgressOutputTime(); if (settings.xml) { - stdLogger.reportErr(ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName)); + stdLogger.reportErr(ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName, settings.xml_version)); } if (!settings.buildDir.empty()) { @@ -466,7 +466,7 @@ int CppCheckExecutor::check_internal(const Settings& settings) const stdLogger.writeCheckersReport(); if (settings.xml) { - stdLogger.reportErr(ErrorMessage::getXMLFooter()); + stdLogger.reportErr(ErrorMessage::getXMLFooter(settings.xml_version)); } if (settings.safety && stdLogger.hasCriticalErrors()) @@ -512,6 +512,11 @@ void StdLogger::writeCheckersReport() if (fout.is_open()) fout << checkersReport.getReport(mCriticalErrors); } + + if (mSettings.xml && mSettings.xml_version == 3) { + reportErr(" \n"); + reportErr(checkersReport.getXmlReport(mCriticalErrors)); + } } #ifdef _WIN32 diff --git a/lib/checkersreport.cpp b/lib/checkersreport.cpp index 4982634f89a..e6d5fee98ce 100644 --- a/lib/checkersreport.cpp +++ b/lib/checkersreport.cpp @@ -280,3 +280,139 @@ std::string CheckersReport::getReport(const std::string& criticalErrors) const return fout.str(); } + +std::string CheckersReport::getXmlReport(const std::string& criticalErrors) const +{ + std::ostringstream fout; + + fout << " "; + if (!criticalErrors.empty()) + fout << criticalErrors << std::endl; + fout << "" << std::endl; + + fout << " " << std::endl; + fout << " " << std::endl; + + std::size_t maxCheckerSize = 0; + for (const auto& checkReq: checkers::allCheckers) { + const std::string& checker = checkReq.first; + maxCheckerSize = std::max(checker.size(), maxCheckerSize); + } + for (const auto& checkReq: checkers::allCheckers) { + fout << " 0; + const std::string& req = checkReq.second; + fout << (active ? "Yes" : "No") << "\"" << " id=\"" << checker << "\""; + if (!active && !req.empty()) + fout << " require=\"" + req << "\""; + fout << "/>" << std::endl; + } + + fout << " " << std::endl; + + const bool cppcheckPremium = isCppcheckPremium(mSettings); + + auto reportSection = [&fout, cppcheckPremium] + (const std::string& title, + const Settings& settings, + const std::set& activeCheckers, + const std::map& premiumCheckers, + const std::string& substring) { + fout << " <" << title << ">"; + if (!cppcheckPremium) { + fout << "Not available, Cppcheck Premium is not used" << std::endl; + return; + } + fout << std::endl; + int maxCheckerSize = 0; + for (const auto& checkReq: premiumCheckers) { + const std::string& checker = checkReq.first; + if (checker.find(substring) != std::string::npos && checker.size() > maxCheckerSize) + maxCheckerSize = checker.size(); + } + for (const auto& checkReq: premiumCheckers) { + const std::string& checker = checkReq.first; + if (checker.find(substring) == std::string::npos) + continue; + std::string req = checkReq.second; + bool active = cppcheckPremium && activeCheckers.count(checker) > 0; + if (substring == "::") { + if (req == "warning") + active &= settings.severity.isEnabled(Severity::warning); + else if (req == "style") + active &= settings.severity.isEnabled(Severity::style); + else if (req == "portability") + active &= settings.severity.isEnabled(Severity::portability); + else if (!req.empty()) + active = false; // FIXME: handle req + } + fout << " " << std::endl; + } + fout << " " << std::endl; + }; + + reportSection("Premium Checkers", mSettings, mActiveCheckers, checkers::premiumCheckers, "::"); + reportSection("Autosar", mSettings, mActiveCheckers, checkers::premiumCheckers, "Autosar: "); + reportSection("Cert C", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C: "); + reportSection("Cert Cpp", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C++: "); + + int misra = 0; + if (mSettings.premiumArgs.find("misra-c-2012") != std::string::npos) + misra = 2012; + else if (mSettings.premiumArgs.find("misra-c-2023") != std::string::npos) + misra = 2023; + else if (mSettings.addons.count("misra")) + misra = 2012; + + if (misra == 0) { + fout << " Misra is not enabled " << std::endl; + } else { + fout << " " << std::endl; + for (const checkers::MisraInfo& info: checkers::misraC2012Directives) { + const std::string directive = "Dir " + std::to_string(info.a) + "." + std::to_string(info.b); + const bool active = isMisraRuleActive(mActiveCheckers, directive); + fout << " = 1) + extra = " amendment=\"" + std::to_string(info.amendment) + "\""; + if (!extra.empty()) + fout << extra; + fout << "/>" << std::endl; + } + for (const checkers::MisraInfo& info: checkers::misraC2012Rules) { + const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b); + const bool active = isMisraRuleActive(mActiveCheckers, rule); + fout << " = 1) + extra = " amendment=\"" + std::to_string(info.amendment) + "\""; + std::string reqs; + if (info.amendment >= 3) + reqs += "premium"; + if (!active && !reqs.empty()) + extra += " require=\"" + reqs + "\""; + if (!extra.empty()) + fout << extra; + fout << "/>" << std::endl; + } + fout << " " << std::endl; + } + + reportSection("Misra C++ 2008", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2008: "); + reportSection("Misra C++ 2023", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2023: "); + + fout << " "; + return fout.str(); +} diff --git a/lib/checkersreport.h b/lib/checkersreport.h index be47cc126e3..b189a7f1ebd 100644 --- a/lib/checkersreport.h +++ b/lib/checkersreport.h @@ -34,6 +34,7 @@ class CPPCHECKLIB CheckersReport { int getAllCheckersCount(); std::string getReport(const std::string& criticalErrors) const; + std::string getXmlReport(const std::string& criticalErrors) const; private: const Settings& mSettings; diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 06901a488de..c6965908fd8 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -423,7 +423,7 @@ void ErrorMessage::deserialize(const std::string &data) } } -std::string ErrorMessage::getXMLHeader(std::string productName) +std::string ErrorMessage::getXMLHeader(std::string productName, int _xmlVersion) { const auto nameAndVersion = Settings::getNameAndVersion(productName); productName = nameAndVersion.first; @@ -437,7 +437,7 @@ std::string ErrorMessage::getXMLHeader(std::string productName) // header printer.OpenElement("results", false); - printer.PushAttribute("version", 2); + printer.PushAttribute("version", _xmlVersion); printer.OpenElement("cppcheck", false); if (!productName.empty()) printer.PushAttribute("product-name", productName.c_str()); @@ -448,9 +448,9 @@ std::string ErrorMessage::getXMLHeader(std::string productName) return std::string(printer.CStr()) + '>'; } -std::string ErrorMessage::getXMLFooter() +std::string ErrorMessage::getXMLFooter(int _xmlVersion) { - return " \n"; + return _xmlVersion == 3? "" : " \n"; } // There is no utf-8 support around but the strings should at least be safe for to tinyxml2. diff --git a/lib/errorlogger.h b/lib/errorlogger.h index c39d242f683..43bca0d9397 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -142,8 +142,8 @@ class CPPCHECKLIB ErrorMessage { */ std::string toXML() const; - static std::string getXMLHeader(std::string productName); - static std::string getXMLFooter(); + static std::string getXMLHeader(std::string productName, int _xmlVersion = 2); + static std::string getXMLFooter(int _xmlVersion = 2); /** * Format the error message into a string. From abe5def357a2f1fd6bcf5e7477d8e6bd6d434f04 Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Wed, 16 Oct 2024 18:06:35 +0300 Subject: [PATCH 2/5] Basic test --- lib/checkersreport.cpp | 26 +++++++++++++------------- test/cli/other_test.py | 18 ++++++++++++++++++ test/testcmdlineparser.cpp | 4 ++-- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/checkersreport.cpp b/lib/checkersreport.cpp index e6d5fee98ce..d2651c9ff32 100644 --- a/lib/checkersreport.cpp +++ b/lib/checkersreport.cpp @@ -285,13 +285,13 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons { std::ostringstream fout; - fout << " "; + fout << " "; if (!criticalErrors.empty()) fout << criticalErrors << std::endl; - fout << "" << std::endl; + fout << "" << std::endl; fout << " " << std::endl; - fout << " " << std::endl; + fout << " " << std::endl; std::size_t maxCheckerSize = 0; for (const auto& checkReq: checkers::allCheckers) { @@ -309,7 +309,7 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons fout << "/>" << std::endl; } - fout << " " << std::endl; + fout << " " << std::endl; const bool cppcheckPremium = isCppcheckPremium(mSettings); @@ -361,10 +361,10 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons fout << " " << std::endl; }; - reportSection("Premium Checkers", mSettings, mActiveCheckers, checkers::premiumCheckers, "::"); - reportSection("Autosar", mSettings, mActiveCheckers, checkers::premiumCheckers, "Autosar: "); - reportSection("Cert C", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C: "); - reportSection("Cert Cpp", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C++: "); + reportSection("premium-checkers", mSettings, mActiveCheckers, checkers::premiumCheckers, "::"); + reportSection("autosar", mSettings, mActiveCheckers, checkers::premiumCheckers, "Autosar: "); + reportSection("cert-c", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C: "); + reportSection("cert-cpp", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C++: "); int misra = 0; if (mSettings.premiumArgs.find("misra-c-2012") != std::string::npos) @@ -375,9 +375,9 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons misra = 2012; if (misra == 0) { - fout << " Misra is not enabled " << std::endl; + fout << " Misra is not enabled " << std::endl; } else { - fout << " " << std::endl; + fout << " " << std::endl; for (const checkers::MisraInfo& info: checkers::misraC2012Directives) { const std::string directive = "Dir " + std::to_string(info.a) + "." + std::to_string(info.b); const bool active = isMisraRuleActive(mActiveCheckers, directive); @@ -407,11 +407,11 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons fout << extra; fout << "/>" << std::endl; } - fout << " " << std::endl; + fout << " " << std::endl; } - reportSection("Misra C++ 2008", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2008: "); - reportSection("Misra C++ 2023", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2023: "); + reportSection("misra-cpp-2008", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2008: "); + reportSection("misra-cpp-2023", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2023: "); fout << " "; return fout.str(); diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 49cf2448110..12f928f078e 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -5,6 +5,7 @@ import sys import pytest import json +import xml.etree.ElementTree as ET from testutils import cppcheck, assert_cppcheck, cppcheck_ex @@ -2229,3 +2230,20 @@ def test_ignore_project_2(tmpdir): exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) assert exitcode == 1, stdout assert stdout.splitlines() == lines_exp + +def test_xml_checkers_report(tmpdir): + test_file = os.path.join(tmpdir, 'test.c') + test_xml = os.path.join(tmpdir, 'results.xml') + with open(test_file, 'wt') as f: + f.write(""" + int main(int argc) + { + } + """) + + args = ['--xml-version=3', '--enable=all', '-j2', "--output-file=" + test_xml, test_file] + + exitcode, _, stderr = cppcheck(args) + assert exitcode == 0 + assert stderr == "" + assert ET.parse(test_xml) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 0ffa3198f3a..cf564273730 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -1807,10 +1807,10 @@ class TestCmdlineParser : public TestFixture { void xmlverunknown() { REDIRECT; - const char * const argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"}; + const char * const argv[] = {"cppcheck", "--xml", "--xml-version=4", "file.cpp"}; // FAils since unknown XML format version ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); - ASSERT_EQUALS("cppcheck: error: '--xml-version' can only be 2.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: '--xml-version' can only be 2 or 3.\n", logger->str()); } void xmlverinvalid() { From 4e21dce3f953a2a9e02621b1fb8e8bfdf30ef2f3 Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Mon, 21 Oct 2024 12:11:15 +0300 Subject: [PATCH 3/5] Work around --- lib/checkersreport.cpp | 104 ++++++++-------------------- lib/errorlogger.cpp | 8 +-- lib/errorlogger.h | 4 +- test/cli/checkers-report_test.py | 17 +++++ test/cli/checkers-testing/test1.cpp | 4 ++ test/cli/other_test.py | 17 ----- 6 files changed, 54 insertions(+), 100 deletions(-) create mode 100644 test/cli/checkers-report_test.py create mode 100644 test/cli/checkers-testing/test1.cpp diff --git a/lib/checkersreport.cpp b/lib/checkersreport.cpp index d2651c9ff32..810ed96915a 100644 --- a/lib/checkersreport.cpp +++ b/lib/checkersreport.cpp @@ -283,82 +283,47 @@ std::string CheckersReport::getReport(const std::string& criticalErrors) const std::string CheckersReport::getXmlReport(const std::string& criticalErrors) const { - std::ostringstream fout; + std::string ret; - fout << " "; + ret += " "; if (!criticalErrors.empty()) - fout << criticalErrors << std::endl; - fout << "" << std::endl; - - fout << " " << std::endl; - fout << " " << std::endl; - - std::size_t maxCheckerSize = 0; - for (const auto& checkReq: checkers::allCheckers) { - const std::string& checker = checkReq.first; - maxCheckerSize = std::max(checker.size(), maxCheckerSize); - } - for (const auto& checkReq: checkers::allCheckers) { - fout << " 0; - const std::string& req = checkReq.second; - fout << (active ? "Yes" : "No") << "\"" << " id=\"" << checker << "\""; - if (!active && !req.empty()) - fout << " require=\"" + req << "\""; - fout << "/>" << std::endl; - } - - fout << " " << std::endl; + ret += criticalErrors + "\n"; + ret += "\n"; + ret += " \n"; const bool cppcheckPremium = isCppcheckPremium(mSettings); - auto reportSection = [&fout, cppcheckPremium] + auto reportSection = [&ret, cppcheckPremium] (const std::string& title, const Settings& settings, const std::set& activeCheckers, const std::map& premiumCheckers, const std::string& substring) { - fout << " <" << title << ">"; + ret += " <" + title + ">"; if (!cppcheckPremium) { - fout << "Not available, Cppcheck Premium is not used" << std::endl; + ret += "Not available, Cppcheck Premium is not used\n"; return; } - fout << std::endl; - int maxCheckerSize = 0; - for (const auto& checkReq: premiumCheckers) { - const std::string& checker = checkReq.first; - if (checker.find(substring) != std::string::npos && checker.size() > maxCheckerSize) - maxCheckerSize = checker.size(); - } + ret += "\n"; for (const auto& checkReq: premiumCheckers) { const std::string& checker = checkReq.first; if (checker.find(substring) == std::string::npos) continue; - std::string req = checkReq.second; bool active = cppcheckPremium && activeCheckers.count(checker) > 0; if (substring == "::") { - if (req == "warning") + if (checkReq.second == "warning") active &= settings.severity.isEnabled(Severity::warning); - else if (req == "style") + else if (checkReq.second == "style") active &= settings.severity.isEnabled(Severity::style); - else if (req == "portability") + else if (checkReq.second == "portability") active &= settings.severity.isEnabled(Severity::portability); - else if (!req.empty()) + else if (!checkReq.second.empty()) active = false; // FIXME: handle req } - fout << " " << std::endl; + ret += " (active ? "Yes" : "No") + "\" id=\"" + checker + "\""; + ret += "/>\n"; } - fout << " " << std::endl; + ret += " \n"; }; reportSection("premium-checkers", mSettings, mActiveCheckers, checkers::premiumCheckers, "::"); @@ -375,44 +340,29 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons misra = 2012; if (misra == 0) { - fout << " Misra is not enabled " << std::endl; + ret += " Misra is not enabled \n"; } else { - fout << " " << std::endl; + ret += " \n"; for (const checkers::MisraInfo& info: checkers::misraC2012Directives) { const std::string directive = "Dir " + std::to_string(info.a) + "." + std::to_string(info.b); const bool active = isMisraRuleActive(mActiveCheckers, directive); - fout << " = 1) - extra = " amendment=\"" + std::to_string(info.amendment) + "\""; - if (!extra.empty()) - fout << extra; - fout << "/>" << std::endl; + ret += " (active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + directive + "\""; + ret += "/>\n"; } for (const checkers::MisraInfo& info: checkers::misraC2012Rules) { const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b); const bool active = isMisraRuleActive(mActiveCheckers, rule); - fout << " = 1) - extra = " amendment=\"" + std::to_string(info.amendment) + "\""; - std::string reqs; - if (info.amendment >= 3) - reqs += "premium"; - if (!active && !reqs.empty()) - extra += " require=\"" + reqs + "\""; - if (!extra.empty()) - fout << extra; - fout << "/>" << std::endl; + ret += " (active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + rule + "\""; + ret += "/>\n"; } - fout << " " << std::endl; + ret += " \n"; } reportSection("misra-cpp-2008", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2008: "); reportSection("misra-cpp-2023", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++ 2023: "); - fout << " "; - return fout.str(); + ret += " "; + return ret; } diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index c6965908fd8..bd907f724c1 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -423,7 +423,7 @@ void ErrorMessage::deserialize(const std::string &data) } } -std::string ErrorMessage::getXMLHeader(std::string productName, int _xmlVersion) +std::string ErrorMessage::getXMLHeader(std::string productName, int xmlVersion) { const auto nameAndVersion = Settings::getNameAndVersion(productName); productName = nameAndVersion.first; @@ -437,7 +437,7 @@ std::string ErrorMessage::getXMLHeader(std::string productName, int _xmlVersion) // header printer.OpenElement("results", false); - printer.PushAttribute("version", _xmlVersion); + printer.PushAttribute("version", xmlVersion); printer.OpenElement("cppcheck", false); if (!productName.empty()) printer.PushAttribute("product-name", productName.c_str()); @@ -448,9 +448,9 @@ std::string ErrorMessage::getXMLHeader(std::string productName, int _xmlVersion) return std::string(printer.CStr()) + '>'; } -std::string ErrorMessage::getXMLFooter(int _xmlVersion) +std::string ErrorMessage::getXMLFooter(int xmlVersion) { - return _xmlVersion == 3? "" : " \n"; + return xmlVersion == 3? "" : " \n"; } // There is no utf-8 support around but the strings should at least be safe for to tinyxml2. diff --git a/lib/errorlogger.h b/lib/errorlogger.h index 43bca0d9397..399853c4815 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -142,8 +142,8 @@ class CPPCHECKLIB ErrorMessage { */ std::string toXML() const; - static std::string getXMLHeader(std::string productName, int _xmlVersion = 2); - static std::string getXMLFooter(int _xmlVersion = 2); + static std::string getXMLHeader(std::string productName, int xmlVersion = 2); + static std::string getXMLFooter(int xmlVersion = 2); /** * Format the error message into a string. diff --git a/test/cli/checkers-report_test.py b/test/cli/checkers-report_test.py new file mode 100644 index 00000000000..1524887f4e0 --- /dev/null +++ b/test/cli/checkers-report_test.py @@ -0,0 +1,17 @@ +# python -m pytest checkers-report_test.py + +import os +import xml.etree.ElementTree as ET + +from testutils import cppcheck + +__script_dir = os.path.dirname(os.path.abspath(__file__)) +__project_dir = os.path.join(__script_dir, 'checkers-testing') + +def test_xml_checkers_report(): + test_file = os.path.join(__project_dir, 'test1.cpp') + args = ['--xml-version=3', '--enable=all', test_file] + + exitcode, _, stderr = cppcheck(args) + assert exitcode == 0 + assert ET.fromstring(stderr) \ No newline at end of file diff --git a/test/cli/checkers-testing/test1.cpp b/test/cli/checkers-testing/test1.cpp new file mode 100644 index 00000000000..27c9e60e9dd --- /dev/null +++ b/test/cli/checkers-testing/test1.cpp @@ -0,0 +1,4 @@ +int main(int argc) +{ + return 0; +} \ No newline at end of file diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 12f928f078e..823d2fe8c13 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -2230,20 +2230,3 @@ def test_ignore_project_2(tmpdir): exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) assert exitcode == 1, stdout assert stdout.splitlines() == lines_exp - -def test_xml_checkers_report(tmpdir): - test_file = os.path.join(tmpdir, 'test.c') - test_xml = os.path.join(tmpdir, 'results.xml') - with open(test_file, 'wt') as f: - f.write(""" - int main(int argc) - { - } - """) - - args = ['--xml-version=3', '--enable=all', '-j2', "--output-file=" + test_xml, test_file] - - exitcode, _, stderr = cppcheck(args) - assert exitcode == 0 - assert stderr == "" - assert ET.parse(test_xml) From f7d4264e66646f9fd6b0ea277f930302d22a1086 Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Tue, 22 Oct 2024 11:01:12 +0300 Subject: [PATCH 4/5] Nits --- lib/checkersreport.cpp | 21 ++++++++++----------- test/cli/checkers-report_test.py | 17 ----------------- test/cli/checkers-testing/test1.cpp | 4 ---- test/cli/helloworld_test.py | 10 ++++++++++ test/cli/other_test.py | 1 - 5 files changed, 20 insertions(+), 33 deletions(-) delete mode 100644 test/cli/checkers-report_test.py delete mode 100644 test/cli/checkers-testing/test1.cpp diff --git a/lib/checkersreport.cpp b/lib/checkersreport.cpp index 810ed96915a..5bcac762c45 100644 --- a/lib/checkersreport.cpp +++ b/lib/checkersreport.cpp @@ -285,10 +285,10 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons { std::string ret; - ret += " "; - if (!criticalErrors.empty()) - ret += criticalErrors + "\n"; - ret += "\n"; + if (!criticalErrors.empty()) { + ret += " " + criticalErrors + "\n \n"; + } else + ret += " \n"; ret += " \n"; const bool cppcheckPremium = isCppcheckPremium(mSettings); @@ -299,12 +299,11 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons const std::set& activeCheckers, const std::map& premiumCheckers, const std::string& substring) { - ret += " <" + title + ">"; if (!cppcheckPremium) { - ret += "Not available, Cppcheck Premium is not used\n"; + ret += "<" + title + "/>\n"; return; } - ret += "\n"; + ret += " <" + title + ">\n"; for (const auto& checkReq: premiumCheckers) { const std::string& checker = checkReq.first; if (checker.find(substring) == std::string::npos) @@ -320,7 +319,7 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons else if (!checkReq.second.empty()) active = false; // FIXME: handle req } - ret += " (active ? "Yes" : "No") + "\" id=\"" + checker + "\""; + ret += " \n"; @@ -340,21 +339,21 @@ std::string CheckersReport::getXmlReport(const std::string& criticalErrors) cons misra = 2012; if (misra == 0) { - ret += " Misra is not enabled \n"; + ret += " \n"; } else { ret += " \n"; for (const checkers::MisraInfo& info: checkers::misraC2012Directives) { const std::string directive = "Dir " + std::to_string(info.a) + "." + std::to_string(info.b); const bool active = isMisraRuleActive(mActiveCheckers, directive); ret += " (active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + directive + "\""; + ret += std::string(active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + directive + "\""; ret += "/>\n"; } for (const checkers::MisraInfo& info: checkers::misraC2012Rules) { const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b); const bool active = isMisraRuleActive(mActiveCheckers, rule); ret += " (active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + rule + "\""; + ret += std::string(active ? "Yes" : "No") + "\" id=\"Misra C " + std::to_string(misra) + ": " + rule + "\""; ret += "/>\n"; } ret += " \n"; diff --git a/test/cli/checkers-report_test.py b/test/cli/checkers-report_test.py deleted file mode 100644 index 1524887f4e0..00000000000 --- a/test/cli/checkers-report_test.py +++ /dev/null @@ -1,17 +0,0 @@ -# python -m pytest checkers-report_test.py - -import os -import xml.etree.ElementTree as ET - -from testutils import cppcheck - -__script_dir = os.path.dirname(os.path.abspath(__file__)) -__project_dir = os.path.join(__script_dir, 'checkers-testing') - -def test_xml_checkers_report(): - test_file = os.path.join(__project_dir, 'test1.cpp') - args = ['--xml-version=3', '--enable=all', test_file] - - exitcode, _, stderr = cppcheck(args) - assert exitcode == 0 - assert ET.fromstring(stderr) \ No newline at end of file diff --git a/test/cli/checkers-testing/test1.cpp b/test/cli/checkers-testing/test1.cpp deleted file mode 100644 index 27c9e60e9dd..00000000000 --- a/test/cli/checkers-testing/test1.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int main(int argc) -{ - return 0; -} \ No newline at end of file diff --git a/test/cli/helloworld_test.py b/test/cli/helloworld_test.py index 6ee09396c40..63bf18a9a35 100644 --- a/test/cli/helloworld_test.py +++ b/test/cli/helloworld_test.py @@ -5,6 +5,7 @@ import re import glob import json +import xml.etree.ElementTree as ET from testutils import create_gui_project_file, cppcheck @@ -338,3 +339,12 @@ def test_sarif(): assert res['runs'][0]['tool']['driver']['rules'][0]['properties']['security-severity'] > 9.5 assert 'security' in res['runs'][0]['tool']['driver']['rules'][0]['properties']['tags'] assert re.match(r'[0-9]+(.[0-9]+)+', res['runs'][0]['tool']['driver']['semanticVersion']) + + +def test_xml_checkers_report(): + test_file = os.path.join(__proj_dir, 'main.c') + args = ['--xml-version=3', '--enable=all', test_file] + + exitcode, _, stderr = cppcheck(args) + assert exitcode == 0 + assert ET.fromstring(stderr) diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 823d2fe8c13..49cf2448110 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -5,7 +5,6 @@ import sys import pytest import json -import xml.etree.ElementTree as ET from testutils import cppcheck, assert_cppcheck, cppcheck_ex From 17d9f241d318d0182cae0bd96db89f0554fa0e6a Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Tue, 22 Oct 2024 11:34:10 +0300 Subject: [PATCH 5/5] Ci --- test/cli/helloworld_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cli/helloworld_test.py b/test/cli/helloworld_test.py index 63bf18a9a35..73cc30647ef 100644 --- a/test/cli/helloworld_test.py +++ b/test/cli/helloworld_test.py @@ -347,4 +347,4 @@ def test_xml_checkers_report(): exitcode, _, stderr = cppcheck(args) assert exitcode == 0 - assert ET.fromstring(stderr) + assert ET.fromstring(stderr) is not None