parent
bb327be8e8
commit
cc24d6fcef
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
TEMPLATE = app
|
||||
TARGET = test-xmlreportv2
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . ../../../externals/simplecpp ../../../externals/tinyxml
|
||||
INCLUDEPATH += . ../../../externals/simplecpp
|
||||
OBJECTS_DIR = ../build
|
||||
MOC_DIR = ../build
|
||||
|
||||
|
|
|
@ -199,29 +199,36 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
|
|||
settings ? settings->fileFilters : std::vector<std::string>();
|
||||
|
||||
if (endsWith(filename, ".json")) {
|
||||
importCompileCommands(fin);
|
||||
if (importCompileCommands(fin)) {
|
||||
setRelativePaths(filename);
|
||||
return ImportProject::Type::COMPILE_DB;
|
||||
}
|
||||
} else if (endsWith(filename, ".sln")) {
|
||||
importSln(fin, mPath, fileFilters);
|
||||
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);
|
||||
if (importVcxproj(filename, variables, emptyString, fileFilters)) {
|
||||
setRelativePaths(filename);
|
||||
return ImportProject::Type::VS_VCXPROJ;
|
||||
}
|
||||
} else if (endsWith(filename, ".bpr")) {
|
||||
importBcb6Prj(filename);
|
||||
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;
|
||||
}
|
||||
} else if (settings && endsWith(filename, ".cppcheck")) {
|
||||
if (importCppcheckGuiProject(fin, settings)) {
|
||||
setRelativePaths(filename);
|
||||
return ImportProject::Type::CPPCHECK_GUI;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -28,6 +28,10 @@ class TestImporter : public ImportProject {
|
|||
public:
|
||||
using ImportProject::importCompileCommands;
|
||||
using ImportProject::importCppcheckGuiProject;
|
||||
|
||||
bool sourceFileExists(const std::string & /*file*/) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue