Fix #9162 (Invalid --project files do not give any error) (#3177)

This commit is contained in:
Oliver Stöneberg 2021-12-19 12:36:11 +01:00 committed by GitHub
parent bb327be8e8
commit cc24d6fcef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 347 additions and 87 deletions

View File

@ -156,21 +156,39 @@ jobs:
if: contains(matrix.os, 'ubuntu')
run: |
pushd gui
qmake HAVE_QCHART=yes
qmake CONFIG+=debug HAVE_QCHART=yes
make -j$(nproc)
- name: Run GUI tests on ubuntu
if: contains(matrix.os, 'ubuntu')
run: |
pushd gui/test/cppchecklibrarydata
qmake CONFIG+=debug
make -j$(nproc)
./test-cppchecklibrarydata
popd
pushd gui/test/filelist
qmake CONFIG+=debug
make -j$(nproc)
# TODO: requires X session
#./test-filelist
popd
pushd gui/test/projectfile
qmake
qmake CONFIG+=debug
make -j$(nproc)
./test-projectfile
popd
pushd gui/test/cppchecklibrarydata
qmake
pushd gui/test/translationhandler
qmake CONFIG+=debug
make -j$(nproc)
./test-cppchecklibrarydata
# TODO: requires X session
#./test-translationhandler
popd
pushd gui/test/xmlreportv2
qmake CONFIG+=debug
make -j$(nproc)
# TODO: requires X session
#./test-xmlreportv2
- name: Generate Qt help file on ubuntu
if: contains(matrix.os, 'ubuntu')
@ -178,6 +196,19 @@ jobs:
pushd gui/help
qhelpgenerator online-help.qhcp -o online-help.qhc
- name: Build triage on ubuntu
if: matrix.os == 'ubuntu-20.04'
run: |
pushd tools/triage
qmake CONFIG+=debug
make -j$(nproc)
- name: Build Fuzzer
if: matrix.os == 'ubuntu-20.04'
run: |
pushd oss-fuzz
make -j$(nproc) CXX=clang++ CXXFLAGS="-fsanitize=address" fuzz-client translate
- name: Self check (build)
if: matrix.os == 'ubuntu-20.04'
run: |
@ -196,18 +227,4 @@ jobs:
mkdir b2
./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck --cppcheck-build-dir=b2 -D__CPPCHECK__ -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=qt --addon=naming.json -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings gui/*.cpp gui/temp/*.cpp
# self check test and tools
./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli -Igui --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings test/*.cpp tools
- name: Build triage on ubuntu
if: matrix.os == 'ubuntu-20.04'
run: |
pushd tools/triage
qmake
make -j$(nproc)
- name: Build Fuzzer
if: matrix.os == 'ubuntu-20.04'
run: |
pushd oss-fuzz
make -j$(nproc) CXX=clang++ CXXFLAGS="-fsanitize=address" fuzz-client translate
./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ -DQ_MOC_OUTPUT_REVISION=67 --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli -Igui --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings test/*.cpp tools

6
.gitignore vendored
View File

@ -58,6 +58,8 @@ gui/cppcheck-gui
gui/cppcheck-gui.exe
gui/gui.sln
gui/gui.vcproj
gui/help/online-help.qch
gui/help/online-help.qhc
gui/Makefile
gui/Makefile.debug
gui/Makefile.release
@ -66,11 +68,11 @@ gui/test/Makefile
gui/test/*/Makefile
gui/test/*/*/Makefile
gui/test/benchmark/simple/benchmark-simple
gui/test/cppchecklibrarydata/qrc_resources.cpp
gui/test/cppchecklibrarydata/test-cppchecklibrarydata
gui/test/filelist/test-filelist
gui/test/projectfile/test-projectfile
gui/test/translationhandler/test-translationhandler
gui/test/xmlreport/test-xmlreport
gui/test/xmlreportv1/test-xmlreportv1
gui/test/xmlreportv2/test-xmlreportv2
# Doxygen output folder

View File

@ -11,6 +11,7 @@ useStlAlgorithm
simplifyUsing:lib/valueptr.h
symbolDatabaseWarning:gui/temp/moc_*.cpp
simplifyUsing:gui/temp/moc_*.cpp
symbolDatabaseWarning:tools/triage/moc_*.cpp
# debug suppressions
valueFlowBailout

View File

@ -644,13 +644,17 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
}
}
if (projType == ImportProject::Type::MISSING) {
printError("failed to open project '" + projectFile + "'.");
printError("failed to open project '" + projectFile + "'. The file does not exist.");
return false;
}
if (projType == ImportProject::Type::UNKNOWN) {
printError("failed to load project '" + projectFile + "'. The format is unknown.");
return false;
}
if (projType == ImportProject::Type::FAILURE) {
printError("failed to load project '" + projectFile + "'. An error occurred.");
return false;
}
}
// --project-configuration

View File

@ -48,14 +48,6 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
#if QT_VERSION < 0x050000
// Set codecs so that UTF-8 strings in sources are handled correctly.
// This is ONLY needed for Qt versions 4.x.
// Qt 5.x assumes UTF-8 by default.
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cppcheck");
QCoreApplication::setApplicationName("Cppcheck-GUI");

View File

@ -15,10 +15,12 @@ SOURCES += testfilelist.cpp \
../../filelist.cpp \
../../../lib/pathmatch.cpp \
../../../lib/path.cpp \
../../../lib/utils.cpp \
../../../externals/simplecpp/simplecpp.cpp
HEADERS += testfilelist.h \
../../filelist.h \
../../../lib/pathmatch.h \
../../../lib/path.h \
../../../lib/utils.h \
../../../externals/simplecpp/simplecpp.h

View File

@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = test-projectfile
DEPENDPATH += .
INCLUDEPATH += . ../../../externals/simplecpp
INCLUDEPATH += . ../../../externals/simplecpp ../../../externals/tinyxml2 ../../../externals/picojson
OBJECTS_DIR = ../build
MOC_DIR = ../build
QT -= gui
@ -14,11 +14,8 @@ DEFINES += SRCDIR=\\\"$$PWD\\\"
# tests
SOURCES += testprojectfile.cpp \
../../projectfile.cpp \
../../../lib/path.cpp \
../../../externals/simplecpp/simplecpp.cpp
../../projectfile.cpp
HEADERS += testprojectfile.h \
../../projectfile.h \
../../../lib/path.h \
../../../externals/simplecpp/simplecpp.h
../../../externals/picojson/picojson.h

View File

@ -31,6 +31,7 @@ Settings::Settings() : maxCtuDepth(10), maxTemplateRecursion(100) {}
cppcheck::Platform::Platform() {}
Library::Library() {}
ImportProject::ImportProject() {}
bool ImportProject::sourceFileExists(const std::string &/*file*/) { return true; }
void TestProjectFile::loadInexisting()
{

View File

@ -9,6 +9,10 @@ QT += widgets
include(../common.pri)
# tests
SOURCES += testtranslationhandler.cpp
SOURCES += testtranslationhandler.cpp \
../../translationhandler.cpp \
../../common.cpp
HEADERS += testtranslationhandler.h
HEADERS += testtranslationhandler.h \
../../translationhandler.h \
../../common.h

View File

@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = test-xmlreportv2
DEPENDPATH += .
INCLUDEPATH += . ../../../externals/simplecpp ../../../externals/tinyxml
INCLUDEPATH += . ../../../externals/simplecpp
OBJECTS_DIR = ../build
MOC_DIR = ../build

View File

@ -199,28 +199,35 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
settings ? settings->fileFilters : std::vector<std::string>();
if (endsWith(filename, ".json")) {
importCompileCommands(fin);
setRelativePaths(filename);
return ImportProject::Type::COMPILE_DB;
if (importCompileCommands(fin)) {
setRelativePaths(filename);
return ImportProject::Type::COMPILE_DB;
}
} else if (endsWith(filename, ".sln")) {
importSln(fin, mPath, fileFilters);
setRelativePaths(filename);
return ImportProject::Type::VS_SLN;
if (importSln(fin, mPath, fileFilters)) {
setRelativePaths(filename);
return ImportProject::Type::VS_SLN;
}
} else if (endsWith(filename, ".vcxproj")) {
std::map<std::string, std::string, cppcheck::stricmp> variables;
importVcxproj(filename, variables, emptyString, fileFilters);
setRelativePaths(filename);
return ImportProject::Type::VS_VCXPROJ;
if (importVcxproj(filename, variables, emptyString, fileFilters)) {
setRelativePaths(filename);
return ImportProject::Type::VS_VCXPROJ;
}
} else if (endsWith(filename, ".bpr")) {
importBcb6Prj(filename);
setRelativePaths(filename);
return ImportProject::Type::BORLAND;
if (importBcb6Prj(filename)) {
setRelativePaths(filename);
return ImportProject::Type::BORLAND;
}
} else if (settings && endsWith(filename, ".cppcheck")) {
const bool success = importCppcheckGuiProject(fin, settings);
setRelativePaths(filename);
return success ? ImportProject::Type::CPPCHECK_GUI : ImportProject::Type::MISSING;
if (importCppcheckGuiProject(fin, settings)) {
setRelativePaths(filename);
return ImportProject::Type::CPPCHECK_GUI;
}
} else {
return ImportProject::Type::UNKNOWN;
}
return ImportProject::Type::UNKNOWN;
return ImportProject::Type::FAILURE;
}
static std::string readUntil(const std::string &command, std::string::size_type *pos, const char until[])
@ -385,12 +392,14 @@ void ImportProject::FileSettings::parseCommand(std::string command)
setDefines(defs);
}
void ImportProject::importCompileCommands(std::istream &istr)
bool ImportProject::importCompileCommands(std::istream &istr)
{
picojson::value compileCommands;
istr >> compileCommands;
if (!compileCommands.is<picojson::array>())
return;
if (!compileCommands.is<picojson::array>()) {
printError("compilation database is not a JSON array");
return false;
}
for (const picojson::value &fileInfo : compileCommands.get<picojson::array>()) {
picojson::object obj = fileInfo.get<picojson::object>();
@ -412,14 +421,16 @@ void ImportProject::importCompileCommands(std::istream &istr)
}
}
} else {
return;
printError("'arguments' field in compilation database entry is not a JSON array");
return false;
}
} else if (obj.find("command") != obj.end()) {
if (obj["command"].is<std::string>()) {
comm << obj["command"].get<std::string>();
}
} else {
return;
printError("no 'arguments' or 'command' field found in compilation database entry");
return false;
}
const std::string command = comm.str();
@ -441,19 +452,39 @@ void ImportProject::importCompileCommands(std::istream &istr)
#endif
else
fs.filename = Path::simplifyPath(directory + file);
if (!sourceFileExists(fs.filename)) {
printError("'" + fs.filename + "' from compilation database does not exist");
return false;
}
fs.parseCommand(command); // read settings; -D, -I, -U, -std, -m*, -f*
std::map<std::string, std::string, cppcheck::stricmp> variables;
fs.setIncludePaths(directory, fs.includePaths, variables);
fileSettings.push_back(fs);
}
return true;
}
void ImportProject::importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters)
bool ImportProject::importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters)
{
std::string line;
// skip magic word
if (!std::getline(istr,line)) {
printError("Visual Studio solution file is empty");
return false;
}
if (!std::getline(istr, line) || line.find("Microsoft Visual Studio Solution File") != 0) {
printError("Visual Studio solution file header not found");
return false;
}
std::map<std::string,std::string,cppcheck::stricmp> variables;
variables["SolutionDir"] = path;
std::string line;
bool found = false;
while (std::getline(istr,line)) {
if (line.compare(0,8,"Project(")!=0)
continue;
@ -466,8 +497,19 @@ void ImportProject::importSln(std::istream &istr, const std::string &path, const
std::string vcxproj(line.substr(pos1+1, pos-pos1+7));
if (!Path::isAbsolute(vcxproj))
vcxproj = path + vcxproj;
importVcxproj(Path::fromNativeSeparators(vcxproj), variables, emptyString, fileFilters);
if (!importVcxproj(Path::fromNativeSeparators(vcxproj), variables, emptyString, fileFilters)) {
printError("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
}
found = true;
}
if (!found) {
printError("no projects found in Visual Studio solution file");
return false;
}
return true;
}
namespace {
@ -659,7 +701,7 @@ static void loadVisualStudioProperties(const std::string &props, std::map<std::s
}
}
void ImportProject::importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters)
bool ImportProject::importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters)
{
variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));
@ -672,11 +714,15 @@ void ImportProject::importVcxproj(const std::string &filename, std::map<std::str
tinyxml2::XMLDocument doc;
const tinyxml2::XMLError error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_SUCCESS)
return;
if (error != tinyxml2::XML_SUCCESS) {
printError(std::string("Visual Studio project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(error));
return false;
}
const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement();
if (rootnode == nullptr)
return;
if (rootnode == nullptr) {
printError("Visual Studio project file has no XML root node");
return false;
}
for (const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
if (std::strcmp(node->Name(), "ItemGroup") == 0) {
const char *labelAttribute = node->Attribute("Label");
@ -767,17 +813,23 @@ void ImportProject::importVcxproj(const std::string &filename, std::map<std::str
fileSettings.push_back(fs);
}
}
return true;
}
void ImportProject::importBcb6Prj(const std::string &projectFilename)
bool ImportProject::importBcb6Prj(const std::string &projectFilename)
{
tinyxml2::XMLDocument doc;
const tinyxml2::XMLError error = doc.LoadFile(projectFilename.c_str());
if (error != tinyxml2::XML_SUCCESS)
return;
if (error != tinyxml2::XML_SUCCESS) {
printError(std::string("Borland project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(error));
return false;
}
const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement();
if (rootnode == nullptr)
return;
if (rootnode == nullptr) {
printError("Borland project file has no XML root node");
return false;
}
const std::string& projectDir = Path::simplifyPath(Path::getPathFromFilename(projectFilename));
@ -1027,6 +1079,8 @@ void ImportProject::importBcb6Prj(const std::string &projectFilename)
fs.filename = Path::simplifyPath(Path::isAbsolute(c) ? c : projectDir + c);
fileSettings.push_back(fs);
}
return true;
}
static std::string joinRelativePath(const std::string &path1, const std::string &path2)
@ -1069,11 +1123,16 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
{
tinyxml2::XMLDocument doc;
const std::string xmldata = istream_to_string(istr);
if (doc.Parse(xmldata.data(), xmldata.size()) != tinyxml2::XML_SUCCESS)
const tinyxml2::XMLError error = doc.Parse(xmldata.data(), xmldata.size());
if (error != tinyxml2::XML_SUCCESS) {
printError(std::string("Cppcheck GUI project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(error));
return false;
}
const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement();
if (rootnode == nullptr || strcmp(rootnode->Name(), CppcheckXml::ProjectElementName) != 0)
if (rootnode == nullptr || strcmp(rootnode->Name(), CppcheckXml::ProjectElementName) != 0) {
printError("Cppcheck GUI project file has no XML root node");
return false;
}
const std::string &path = mPath;
@ -1211,6 +1270,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
settings->safeChecks = temp.safeChecks;
settings->bugHunting = temp.bugHunting;
settings->functionContracts = temp.functionContracts;
return true;
}
@ -1259,3 +1319,13 @@ void ImportProject::setRelativePaths(const std::string &filename)
includePath = Path::getRelativePath(includePath, basePaths);
}
}
void ImportProject::printError(const std::string &message)
{
std::cout << "cppcheck: error: " << message << std::endl;
}
bool ImportProject::sourceFileExists(const std::string &file)
{
return Path::fileExists(file);
}

View File

@ -52,6 +52,7 @@ public:
enum class Type {
UNKNOWN,
MISSING,
FAILURE,
COMPILE_DB,
VS_SLN,
VS_VCXPROJ,
@ -106,12 +107,15 @@ public:
Type import(const std::string &filename, Settings *settings=nullptr);
protected:
void importCompileCommands(std::istream &istr);
bool importCompileCommands(std::istream &istr);
bool importCppcheckGuiProject(std::istream &istr, Settings *settings);
virtual bool sourceFileExists(const std::string &file);
private:
void importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
void importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters);
void importBcb6Prj(const std::string &projectFilename);
bool importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
bool importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters);
bool importBcb6Prj(const std::string &projectFilename);
void printError(const std::string &message);
void setRelativePaths(const std::string &filename);

146
test/cli/test-project.py Normal file
View File

@ -0,0 +1,146 @@
# python -m pytest test-projects.py
import pytest
import os
import json
from testutils import cppcheck
@pytest.mark.parametrize("project_ext", ["json", "sln", "vcxproj", "bpr", "cppcheck"])
def test_missing_project(project_ext):
project_file = "file.{}".format(project_ext)
ret, stdout, stderr = cppcheck(['--project=' + project_file, '--template=cppcheck1'])
assert 1 == ret
assert "cppcheck: error: failed to open project '{}'. The file does not exist.\n".format(project_file) == stdout
assert "" == stderr
def _test_project_error(tmpdir, ext, content, expected):
project_file = os.path.join(tmpdir, "file.{}".format(ext))
with open(project_file, 'w') as f:
if content is not None:
f.write(content)
ret, stdout, stderr = cppcheck(['--project=' + str(project_file)])
assert 1 == ret
assert "cppcheck: error: " + expected + "\ncppcheck: error: failed to load project '{}'. An error occurred.\n".format(project_file) == stdout
assert "" == stderr
@pytest.mark.parametrize("project_ext, expected", [
("json", "compilation database is not a JSON array"),
("sln", "Visual Studio solution file is empty"),
("vcxproj", "Visual Studio project file is not a valid XML - XML_ERROR_EMPTY_DOCUMENT"),
("bpr", "Borland project file is not a valid XML - XML_ERROR_EMPTY_DOCUMENT"),
("cppcheck", "Cppcheck GUI project file is not a valid XML - XML_ERROR_EMPTY_DOCUMENT")
])
def test_empty_project(tmpdir, project_ext, expected):
_test_project_error(tmpdir, project_ext, None, expected)
def test_json_entry_file_not_found(tmpdir):
compilation_db = [
{"directory": str(tmpdir),
"command": "c++ -o bug1.o -c bug1.cpp",
"file": "bug1.cpp",
"output": "bug1.o"}
]
expected = "'{}' from compilation database does not exist".format(os.path.join(tmpdir, "bug1.cpp"))
_test_project_error(tmpdir, "json", json.dumps(compilation_db), expected)
def test_json_no_arguments(tmpdir):
compilation_db = [
{"directory": str(tmpdir),
"file": "bug1.cpp",
"output": "bug1.o"}
]
expected = "no 'arguments' or 'command' field found in compilation database entry"
_test_project_error(tmpdir, "json", json.dumps(compilation_db), expected)
def test_json_invalid_arguments(tmpdir):
compilation_db = [
{"directory": str(tmpdir),
"arguments": "",
"file": "bug1.cpp",
"output": "bug1.o"}
]
expected = "'arguments' field in compilation database entry is not a JSON array"
_test_project_error(tmpdir, "json", json.dumps(compilation_db), expected)
def test_sln_invalid_file(tmpdir):
content = "some file"
expected = "Visual Studio solution file header not found"
_test_project_error(tmpdir, "sln", content, expected)
def test_sln_no_header(tmpdir):
content = "\xEF\xBB\xBF\r\n" \
"some header"
expected = "Visual Studio solution file header not found"
_test_project_error(tmpdir, "sln", content, expected)
def test_sln_no_projects(tmpdir):
content = "\xEF\xBB\xBF\r\n" \
"Microsoft Visual Studio Solution File, Format Version 12.00\r\n"
expected = "no projects found in Visual Studio solution file"
_test_project_error(tmpdir, "sln", content, expected)
def test_sln_project_file_not_found(tmpdir):
content = "\xEF\xBB\xBF\r\n" \
"Microsoft Visual Studio Solution File, Format Version 12.00\r\n" \
"# Visual Studio Version 16\r\n" \
"VisualStudioVersion = 16.0.29020.237\r\n" \
"MinimumVisualStudioVersion = 10.0.40219.1\r\n" \
'Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "cli\\cli.vcxproj", "{35CBDF51-2456-3EC3-99ED-113C30858883}"\r\n' \
"ProjectSection(ProjectDependencies) = postProject\r\n" \
"{C183DB5B-AD6C-423D-80CA-1F9549555A1A} = {C183DB5B-AD6C-423D-80CA-1F9549555A1A}\r\n" \
"EndProjectSection\r\n" \
"EndProject\r\n"
expected = "Visual Studio project file is not a valid XML - XML_ERROR_FILE_NOT_FOUND\n" \
"cppcheck: error: failed to load '{}' from Visual Studio solution".format(os.path.join(tmpdir, "cli\\cli.vcxproj"))
_test_project_error(tmpdir, "sln", content, expected)
def test_vcxproj_no_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="utf-8"?>'
expected = "Visual Studio project file has no XML root node"
_test_project_error(tmpdir, "vcxproj", content, expected)
def test_bpr_no_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="utf-8"?>'
expected = "Borland project file has no XML root node"
_test_project_error(tmpdir, "bpr", content, expected)
def test_cppcheck_no_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="utf-8"?>'
expected = "Cppcheck GUI project file has no XML root node"
_test_project_error(tmpdir, "cppcheck", content, expected)

View File

@ -4,6 +4,9 @@ import os
import subprocess
# Create Cppcheck project file
import sys
def create_gui_project_file(project_file, root_path=None, import_project=None, paths=None, exclude_paths=None, suppressions=None, addon=None):
cppcheck_xml = ('<?xml version="1.0" encoding="UTF-8"?>\n'
'<project version="1">\n')
@ -40,15 +43,28 @@ def create_gui_project_file(project_file, root_path=None, import_project=None, p
f.close()
def lookup_cppcheck_exe():
# path the script is located in
script_path = os.path.dirname(os.path.realpath(__file__))
exe_name = "cppcheck"
if sys.platform == "win32":
exe_name += ".exe"
for base in (script_path + '/../../', './'):
for path in ('', 'bin/', 'bin/debug/'):
exe_path = base + path + exe_name
if os.path.isfile(exe_path):
return exe_path
return None
# Run Cppcheck with args
def cppcheck(args):
exe = None
for ext in ('', '.exe'):
for base in ('../../', '../../../'):
for path in ('', 'bin/', 'bin/debug/'):
if (exe is None) and os.path.isfile(base + path + 'cppcheck' + ext):
exe = base + path + 'cppcheck' + ext
assert exe is not None
exe = lookup_cppcheck_exe()
assert exe is not None, 'no cppcheck binary found'
logging.info(exe + ' ' + ' '.join(args))
p = subprocess.Popen([exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

View File

@ -28,6 +28,10 @@ class TestImporter : public ImportProject {
public:
using ImportProject::importCompileCommands;
using ImportProject::importCppcheckGuiProject;
bool sourceFileExists(const std::string & /*file*/) OVERRIDE {
return true;
}
};