Skip to content

fixed #13941 - do not overwrite addons from CLI in GUI project import #7603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1292,9 +1292,9 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
} else if (strcmp(name, CppcheckXml::BuildDirElementName) == 0)
temp.buildDir = joinRelativePath(path, empty_if_null(node->GetText()));
else if (strcmp(name, CppcheckXml::IncludeDirElementName) == 0)
temp.includePaths = readXmlStringList(node, path, CppcheckXml::DirElementName, CppcheckXml::DirNameAttrib);
temp.includePaths = readXmlStringList(node, path, CppcheckXml::DirElementName, CppcheckXml::DirNameAttrib); // TODO: append instead of overwrite
else if (strcmp(name, CppcheckXml::DefinesElementName) == 0)
temp.userDefines = join(readXmlStringList(node, "", CppcheckXml::DefineName, CppcheckXml::DefineNameAttrib), ";");
temp.userDefines = join(readXmlStringList(node, "", CppcheckXml::DefineName, CppcheckXml::DefineNameAttrib), ";"); // TODO: append instead of overwrite
else if (strcmp(name, CppcheckXml::UndefinesElementName) == 0) {
for (const std::string &u : readXmlStringList(node, "", CppcheckXml::UndefineName, nullptr))
temp.userUndefs.insert(u);
Expand All @@ -1306,15 +1306,15 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
else if (strcmp(name, CppcheckXml::PathsElementName) == 0)
paths = readXmlStringList(node, path, CppcheckXml::PathName, CppcheckXml::PathNameAttrib);
else if (strcmp(name, CppcheckXml::ExcludeElementName) == 0)
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::ExcludePathName, CppcheckXml::ExcludePathNameAttrib);
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::ExcludePathName, CppcheckXml::ExcludePathNameAttrib); // TODO: append instead of overwrite
else if (strcmp(name, CppcheckXml::FunctionContracts) == 0)
;
else if (strcmp(name, CppcheckXml::VariableContractsElementName) == 0)
;
else if (strcmp(name, CppcheckXml::IgnoreElementName) == 0)
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::IgnorePathName, CppcheckXml::IgnorePathNameAttrib);
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::IgnorePathName, CppcheckXml::IgnorePathNameAttrib); // TODO: append instead of overwrite
else if (strcmp(name, CppcheckXml::LibrariesElementName) == 0)
guiProject.libraries = readXmlStringList(node, "", CppcheckXml::LibraryElementName, nullptr);
guiProject.libraries = readXmlStringList(node, "", CppcheckXml::LibraryElementName, nullptr); // TODO: append instead of overwrite
else if (strcmp(name, CppcheckXml::SuppressionsElementName) == 0) {
for (const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
if (strcmp(child->Name(), CppcheckXml::SuppressionElementName) != 0)
Expand Down Expand Up @@ -1406,13 +1406,14 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
return false;
}
}
settings.basePaths = temp.basePaths;
settings.basePaths = temp.basePaths; // TODO: append instead of overwrite
settings.relativePaths |= temp.relativePaths;
settings.buildDir = temp.buildDir;
settings.includePaths = temp.includePaths;
settings.userDefines = temp.userDefines;
settings.userUndefs = temp.userUndefs;
settings.addons = temp.addons;
settings.includePaths = temp.includePaths; // TODO: append instead of overwrite
settings.userDefines = temp.userDefines; // TODO: append instead of overwrite
settings.userUndefs = temp.userUndefs; // TODO: append instead of overwrite
for (const std::string &addon : temp.addons)
settings.addons.emplace(addon);
settings.clang = temp.clang;
settings.clangTidy = temp.clangTidy;
settings.analyzeAllVsConfigs = temp.analyzeAllVsConfigs;
Expand Down
2 changes: 1 addition & 1 deletion lib/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ bool Platform::set(const std::string& platformstr, std::string& errstr, const st
bool found = false;
for (const std::string& path : paths) {
if (debug)
std::cout << "looking for platform '" + platformstr + "' in '" + path + "'" << std::endl;
std::cout << "looking for platform '" + platformstr + "' relative to '" + path + "'" << std::endl;
if (loadFromFile(path.c_str(), platformstr, debug)) {
found = true;
break;
Expand Down
182 changes: 172 additions & 10 deletions test/cli/lookup_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
import pytest
import shutil
import json

from testutils import cppcheck_ex, cppcheck, __lookup_cppcheck_exe

Expand All @@ -12,6 +13,48 @@ def __remove_std_lookup_log(l : list, exepath):
return l


def __create_gui_project(tmpdir):
file_name = 'test.c'
test_file = os.path.join(tmpdir, file_name)
with open(test_file, 'wt'):
pass

project_file = os.path.join(tmpdir, 'project.cppcheck')
with open(project_file, 'wt') as f:
f.write(
"""<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
<paths>
<dir name="{}"/>
</paths>
</project>""".format(test_file)
)

return project_file, test_file


def __create_compdb(tmpdir):
file_name = 'test.c'
test_file = os.path.join(tmpdir, file_name)
with open(test_file, 'wt'):
pass

compilation_db = [
{
"directory": str(tmpdir),
"command": "c++ -o {}.o -c {}".format(os.path.basename(file_name), file_name),
"file": file_name,
"output": "{}.o".format(os.path.basename(file_name))
}
]

compile_commands = os.path.join(tmpdir, 'compile_commands.json')
with open(compile_commands, 'wt') as f:
f.write(json.dumps(compilation_db))

return compile_commands, test_file


def test_lib_lookup(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
Expand Down Expand Up @@ -71,6 +114,46 @@ def test_lib_lookup_notfound(tmpdir):
]


def test_lib_lookup_notfound_project(tmpdir): # #13938
project_file, _ = __create_gui_project(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=library', '--library=none', '--project={}'.format(project_file)])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 1, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
# TODO: needs to look relative to the project first
# TODO: specify which folder is actually used for lookup here
"looking for library 'none.cfg'",
"looking for library '{}/none.cfg'".format(exepath),
"looking for library '{}/cfg/none.cfg'".format(exepath),
"library not found: 'none'",
"cppcheck: Failed to load library configuration file 'none'. File not found"
]


def test_lib_lookup_notfound_compdb(tmpdir): # #13938
compdb_file, _ = __create_compdb(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=library', '--library=none', '--project={}'.format(compdb_file)])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 1, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
# TODO: needs to look relative to the project first
# TODO: specify which folder is actually used for lookup here
"looking for library 'none.cfg'",
"looking for library '{}/none.cfg'".format(exepath),
"looking for library '{}/cfg/none.cfg'".format(exepath),
"library not found: 'none'",
"cppcheck: Failed to load library configuration file 'none'. File not found"
]


def test_lib_lookup_ext_notfound(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
Expand Down Expand Up @@ -273,7 +356,7 @@ def test_platform_lookup(tmpdir):
assert exitcode == 0, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'avr8' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'avr8' relative to '{}'".format(exepath_bin),
"try to load platform file 'avr8.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=avr8.xml",
"try to load platform file 'platforms/avr8.xml' ... Success",
'Checking {} ...'.format(test_file)
Expand All @@ -294,7 +377,7 @@ def test_platform_lookup_ext(tmpdir):
assert exitcode == 0, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'avr8.xml' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'avr8.xml' relative to '{}'".format(exepath_bin),
"try to load platform file 'avr8.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=avr8.xml",
"try to load platform file 'platforms/avr8.xml' ... Success",
'Checking {} ...'.format(test_file)
Expand All @@ -315,7 +398,51 @@ def test_platform_lookup_notfound(tmpdir):
assert exitcode == 1, stdout
lines = stdout.splitlines()
assert lines == [
"looking for platform 'none' in '{}'".format(exepath_bin), # TODO: this is not the path *of* the executable but the the path *to* the executable
"looking for platform 'none' relative to '{}'".format(exepath_bin),
"try to load platform file 'none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=none.xml",
"try to load platform file 'platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/none.xml",
"try to load platform file '{}/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/none.xml".format(exepath, exepath),
"try to load platform file '{}/platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/platforms/none.xml".format(exepath, exepath),
"cppcheck: error: unrecognized platform: 'none'."
]


def test_platform_lookup_notfound_project(tmpdir): # #13939
project_file, _ = __create_gui_project(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=platform', '--platform=none', '--project={}'.format(project_file)])
exepath = os.path.dirname(exe)
exepath_bin = os.path.join(exepath, 'cppcheck')
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
exepath_bin += '.exe'
assert exitcode == 1, stdout
lines = stdout.splitlines()
assert lines == [
# TODO: needs to look relative to project file first
"looking for platform 'none' relative to '{}'".format(exepath_bin),
"try to load platform file 'none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=none.xml",
"try to load platform file 'platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/none.xml",
"try to load platform file '{}/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/none.xml".format(exepath, exepath),
"try to load platform file '{}/platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/platforms/none.xml".format(exepath, exepath),
"cppcheck: error: unrecognized platform: 'none'."
]


def test_platform_lookup_notfound_compdb(tmpdir): # #13939
compdb_file, _ = __create_compdb(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=platform', '--platform=none', '--project={}'.format(compdb_file)])
exepath = os.path.dirname(exe)
exepath_bin = os.path.join(exepath, 'cppcheck')
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
exepath_bin += '.exe'
assert exitcode == 1, stdout
lines = stdout.splitlines()
assert lines == [
# TODO: needs to look relative to project file first
"looking for platform 'none' relative to '{}'".format(exepath_bin),
"try to load platform file 'none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=none.xml",
"try to load platform file 'platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/none.xml",
"try to load platform file '{}/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/none.xml".format(exepath, exepath),
Expand All @@ -338,7 +465,7 @@ def test_platform_lookup_ext_notfound(tmpdir):
assert exitcode == 1, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'none.xml' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'none.xml' relative to '{}'".format(exepath_bin),
"try to load platform file 'none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=none.xml",
"try to load platform file 'platforms/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/none.xml",
"try to load platform file '{}/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/none.xml".format(exepath, exepath),
Expand All @@ -361,7 +488,7 @@ def test_platform_lookup_relative_notfound(tmpdir):
assert exitcode == 1, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'platform/none.xml' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'platform/none.xml' relative to '{}'".format(exepath_bin),
"try to load platform file 'platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platform/none.xml",
"try to load platform file 'platforms/platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/platform/none.xml",
"try to load platform file '{}/platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/platform/none.xml".format(exepath, exepath),
Expand All @@ -384,7 +511,7 @@ def test_platform_lookup_relative_noext_notfound(tmpdir):
assert exitcode == 1, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'platform/none' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'platform/none' relative to '{}'".format(exepath_bin),
"try to load platform file 'platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platform/none.xml",
"try to load platform file 'platforms/platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=platforms/platform/none.xml",
"try to load platform file '{}/platform/none.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}/platform/none.xml".format(exepath, exepath),
Expand Down Expand Up @@ -412,7 +539,7 @@ def test_platform_lookup_absolute(tmpdir):
assert exitcode == 0, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform '{}' in '{}'".format(platform_file, exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform '{}' relative to '{}'".format(platform_file, exepath_bin),
"try to load platform file '{}' ... Success".format(platform_file),
'Checking {} ...'.format(test_file)
]
Expand All @@ -433,7 +560,7 @@ def test_platform_lookup_absolute_notfound(tmpdir):
assert exitcode == 1, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform '{}' in '{}'".format(platform_file, exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform '{}' relative to '{}'".format(platform_file, exepath_bin),
"try to load platform file '{}' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename={}".format(platform_file, platform_file),
"cppcheck: error: unrecognized platform: '{}'.".format(platform_file)
]
Expand All @@ -457,7 +584,7 @@ def test_platform_lookup_nofile(tmpdir):
assert exitcode == 0, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'avr8' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'avr8' relative to '{}'".format(exepath_bin),
"try to load platform file 'avr8.xml' ... Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=avr8.xml",
"try to load platform file 'platforms/avr8.xml' ... Success",
'Checking {} ...'.format(test_file)
Expand All @@ -481,7 +608,7 @@ def test_platform_lookup_invalid(tmpdir):
assert exitcode == 1, stdout if stdout else stderr
lines = stdout.splitlines()
assert lines == [
"looking for platform 'avr8' in '{}'".format(exepath_bin), # TODO: this not not the path *of* the executable but the the path *to* the executable
"looking for platform 'avr8' relative to '{}'".format(exepath_bin),
"try to load platform file 'avr8.xml' ... Error=XML_ERROR_PARSING_TEXT ErrorID=8 (0x8) Line number=1",
"cppcheck: error: unrecognized platform: 'avr8'."
]
Expand Down Expand Up @@ -541,6 +668,40 @@ def test_addon_lookup_notfound(tmpdir):
]


def test_addon_lookup_notfound_project(tmpdir): # #13940 / #13941
project_file, _ = __create_gui_project(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=addon', '--addon=none', '--project={}'.format(project_file)])
exepath = os.path.dirname(exe)
exepath_sep = exepath + os.path.sep
assert exitcode == 1, stdout
lines = stdout.splitlines()
assert lines == [
# TODO: needs to look relative to the project file first
"looking for addon 'none.py'",
"looking for addon '{}none.py'".format(exepath_sep),
"looking for addon '{}addons/none.py'".format(exepath_sep), # TODO: mixed separators
'Did not find addon none.py'
]


def test_addon_lookup_notfound_compdb(tmpdir): # #13940
compdb_file, _ = __create_compdb(tmpdir)

exitcode, stdout, _, exe = cppcheck_ex(['--debug-lookup=addon', '--addon=none', '--project={}'.format(compdb_file)])
exepath = os.path.dirname(exe)
exepath_sep = exepath + os.path.sep
assert exitcode == 1, stdout
lines = stdout.splitlines()
assert lines == [
# TODO: needs to look relative to the project file first
"looking for addon 'none.py'",
"looking for addon '{}none.py'".format(exepath_sep),
"looking for addon '{}addons/none.py'".format(exepath_sep), # TODO: mixed separators
'Did not find addon none.py'
]


def test_addon_lookup_ext_notfound(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
Expand Down Expand Up @@ -715,6 +876,7 @@ def test_config_lookup_notfound(tmpdir):
'Checking {} ...'.format(test_file)
]


def test_config_invalid(tmpdir):
cppcheck_exe = __lookup_cppcheck_exe()
bin_dir = os.path.dirname(cppcheck_exe)
Expand Down