Skip to content

Commit

Permalink
added verbose logging of library loading
Browse files Browse the repository at this point in the history
  • Loading branch information
firewave committed May 23, 2024
1 parent e853d86 commit 97ac29b
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 51 deletions.
8 changes: 4 additions & 4 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1802,9 +1802,9 @@ bool CmdLineParser::isCppcheckPremium() const {
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
}

bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename)
bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool verbose)
{
const Library::Error err = destination.load(basepath.c_str(), filename);
const Library::Error err = destination.load(basepath.c_str(), filename, verbose);

if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT)
mLogger.printMessage("Found unknown elements in configuration file '" + std::string(filename) + "': " + err.reason); // TODO: print as errors
Expand Down Expand Up @@ -1851,7 +1851,7 @@ bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& base

bool CmdLineParser::loadLibraries(Settings& settings)
{
if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) {
if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg", settings.verbose)) {
const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install.");
#ifdef FILESDIR
const std::string details("The Cppcheck binary was compiled with FILESDIR set to \""
Expand All @@ -1869,7 +1869,7 @@ bool CmdLineParser::loadLibraries(Settings& settings)

bool result = true;
for (const auto& lib : settings.libraries) {
if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) {
if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str(), settings.verbose)) {
result = false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmdlineparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class CmdLineParser {
* Tries to load a library and prints warning/error messages
* @return false, if an error occurred (except unknown XML elements)
*/
bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename);
bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool verbose);

/**
* @brief Load libraries
Expand Down
40 changes: 32 additions & 8 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,35 +836,50 @@ void MainWindow::addIncludeDirs(const QStringList &includeDirs, Settings &result
}
}

Library::Error MainWindow::loadLibrary(Library &library, const QString &filename)
Library::Error MainWindow::loadLibrary(Library &library, const QString &filename, bool verbose)
{
Library::Error ret;

// Try to load the library from the project folder..
if (mProjectFile) {
QString path = QFileInfo(mProjectFile->getFilename()).canonicalPath();
ret = library.load(nullptr, (path+"/"+filename).toLatin1());
QString libpath = path+"/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}

// Try to load the library from the application folder..
const QString appPath = QFileInfo(QCoreApplication::applicationFilePath()).canonicalPath();
ret = library.load(nullptr, (appPath+"/"+filename).toLatin1());
QString libpath = appPath+"/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (appPath+"/cfg/"+filename).toLatin1());
libpath = appPath+"/cfg/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;

#ifdef FILESDIR
// Try to load the library from FILESDIR/cfg..
const QString filesdir = FILESDIR;
if (!filesdir.isEmpty()) {
ret = library.load(nullptr, (filesdir+"/cfg/"+filename).toLatin1());
libpath = filesdir+"/cfg/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (filesdir+filename).toLatin1());
libpath = filesdir+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}
Expand All @@ -873,14 +888,23 @@ Library::Error MainWindow::loadLibrary(Library &library, const QString &filename
// Try to load the library from the cfg subfolder..
const QString datadir = getDataDir();
if (!datadir.isEmpty()) {
ret = library.load(nullptr, (datadir+"/"+filename).toLatin1());
libpath = datadir+"/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (datadir+"/cfg/"+filename).toLatin1());
libpath = datadir+"/cfg/"+filename;
if (verbose)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}

if (verbose)
std::cout << "library not found: '" + filename.toStdString() + "'" << std::endl;

return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion gui/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ private slots:
* @param filename filename (no path)
* @return error code
*/
Library::Error loadLibrary(Library &library, const QString &filename);
Library::Error loadLibrary(Library &library, const QString &filename, bool verbose = false);

/**
* @brief Tries to load library file, prints message on error
Expand Down
19 changes: 17 additions & 2 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <cctype>
#include <climits>
#include <cstring>
#include <iostream>
#include <list>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -65,9 +66,12 @@ static void gettokenlistfromvalid(const std::string& valid, bool cpp, TokenList&
}
}

Library::Error Library::load(const char exename[], const char path[])
Library::Error Library:: load(const char exename[], const char path[], bool verbose)
{
// TODO: remove handling of multiple libraries at once?
if (std::strchr(path,',') != nullptr) {
if (verbose)
std::cout << "handling multiple libraries '" + std::string(path) + "'" << std::endl;
std::string p(path);
for (;;) {
const std::string::size_type pos = p.find(',');
Expand All @@ -86,15 +90,21 @@ Library::Error Library::load(const char exename[], const char path[])
std::string absolute_path;
// open file..
tinyxml2::XMLDocument doc;
if (verbose)
std::cout << "looking for library '" + std::string(path) + "'" << std::endl;
tinyxml2::XMLError error = doc.LoadFile(path);
if (error == tinyxml2::XML_ERROR_FILE_READ_ERROR && Path::getFilenameExtension(path).empty())
{
// Reading file failed, try again...
error = tinyxml2::XML_ERROR_FILE_NOT_FOUND;
}
if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND) {
// failed to open file.. is there no extension?
std::string fullfilename(path);
if (Path::getFilenameExtension(fullfilename).empty()) {
fullfilename += ".cfg";
if (verbose)
std::cout << "looking for library '" + std::string(fullfilename) + "'" << std::endl;
error = doc.LoadFile(fullfilename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(fullfilename);
Expand All @@ -116,6 +126,8 @@ Library::Error Library::load(const char exename[], const char path[])
cfgfolders.pop_back();
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
const std::string filename(cfgfolder + sep + fullfilename);
if (verbose)
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(filename);
Expand All @@ -134,10 +146,13 @@ Library::Error Library::load(const char exename[], const char path[])
return Error(ErrorCode::OK); // ignore duplicates
}

if (verbose)
std::cout << "library not found: '" + std::string(path) + "'" << std::endl;

if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND)
return Error(ErrorCode::FILE_NOT_FOUND);

doc.PrintError();
doc.PrintError(); // TODO
return Error(ErrorCode::BAD_XML);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CPPCHECKLIB Library {
std::string reason;
};

Error load(const char exename[], const char path[]);
Error load(const char exename[], const char path[], bool verbose = false);

struct AllocFunc {
int groupId;
Expand Down
105 changes: 83 additions & 22 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,24 @@
import pytest
import json

from testutils import cppcheck, assert_cppcheck
from testutils import cppcheck, assert_cppcheck, cppcheck_ex


def __remove_std_lookup_log(l : list, exepath):
print(l)
l.remove("looking for library 'std.cfg'")
l.remove("looking for library '{}/std.cfg'".format(exepath))
l.remove("looking for library '{}/../cfg/std.cfg'".format(exepath))
l.remove("looking for library '{}/cfg/std.cfg'".format(exepath))
return l


def __remove_verbose_log(l : list):
l.remove('Defines:')
l.remove('Undefines:')
l.remove('Includes:')
l.remove('Platform:native')
return l


def test_missing_include(tmpdir): # #11283
Expand Down Expand Up @@ -450,15 +467,15 @@ class _clz {

args = ['--addon='+addon_file, '--verbose', '--enable=all', '--disable=unusedFunction', test_file]

exitcode, stdout, stderr = cppcheck(args)
exitcode, stdout, stderr, exe = cppcheck_ex(args)
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0
lines = stdout.splitlines()
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
lines = __remove_verbose_log(lines)
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
lines = [line for line in stderr.splitlines() if line != '']
expect = [
Expand Down Expand Up @@ -582,16 +599,16 @@ def test_addon_namingng_config(tmpdir):

args = ['--addon='+addon_file, '--verbose', '--enable=all', '-j1', test_file]

exitcode, stdout, stderr = cppcheck(args)
exitcode, stdout, stderr, exe = cppcheck_ex(args)
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0

lines = stdout.splitlines()
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
lines = __remove_verbose_log(lines)
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
lines = stderr.splitlines()
# ignore the first line, stating that the addon failed to run properly
Expand Down Expand Up @@ -723,15 +740,15 @@ def test_invalid_addon_py_verbose(tmpdir):

args = ['--addon={}'.format(addon_file), '--enable=all', '--disable=unusedFunction', '--verbose', '-j1', test_file]

exitcode, stdout, stderr = cppcheck(args)
exitcode, stdout, stderr, exe = cppcheck_ex(args)
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0 # TODO: needs to be 1
lines = stdout.splitlines()
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
lines = __remove_verbose_log(lines)
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
"""
/tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/file.cpp:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'addon1' - exitcode is 1: python3 /home/user/CLionProjects/cppcheck/addons/runaddon.py /tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/addon1.py --cli /tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/file.cpp.24762.dump
Expand Down Expand Up @@ -1487,3 +1504,47 @@ def test_markup_lang(tmpdir):

exitcode, stdout, _ = cppcheck(args)
assert exitcode == 0, stdout


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

exitcode, stdout, _, exe = cppcheck_ex(['--library=gnu', '--verbose', test_file])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
lines = __remove_verbose_log(lines)
assert lines == [
"looking for library 'gnu'",
"looking for library 'gnu.cfg'",
"looking for library '{}/gnu.cfg'".format(exepath),
"looking for library '{}/../cfg/gnu.cfg'".format(exepath),
"looking for library '{}/cfg/gnu.cfg'".format(exepath),
'Checking {} ...'.format(test_file)
]


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

exitcode, stdout, _, exe = cppcheck_ex(['--library=none', '--verbose', test_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 == [
"looking for library 'none'",
"looking for library 'none.cfg'",
"looking for library '{}/none.cfg'".format(exepath),
"looking for library '{}/../cfg/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"
]
Loading

0 comments on commit 97ac29b

Please sign in to comment.