test/cli: execute addon

This commit is contained in:
Daniel Marjamäki 2019-04-14 15:00:03 +02:00
parent 964c2a237a
commit b94f4176f1
5 changed files with 60 additions and 33 deletions

View File

@ -120,6 +120,8 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
bool def = false;
bool maxconfigs = false;
mSettings->exename = argv[0];
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
if (std::strcmp(argv[i], "--version") == 0) {

View File

@ -59,12 +59,14 @@ static const CWE CWE398(398U); // Indicator of Poor Code Quality
namespace {
struct AddonInfo {
std::string script;
std::string name;
std::string scriptFile;
std::string args;
std::string getAddonInfo(const std::string &fileName) {
std::string getAddonInfo(const std::string &fileName, const std::string &exename) {
if (!endsWith(fileName, ".json", 5)) {
script = fileName;
name = fileName;
scriptFile = Path::getPathFromFilename(exename) + "/addons/" + fileName + ".py";
return "";
}
std::ifstream fin(fileName);
@ -81,12 +83,32 @@ namespace {
for (const picojson::value &v : obj["args"].get<picojson::array>())
args += " " + v.get<std::string>();
}
script = obj["script"].get<std::string>();
name = obj["script"].get<std::string>();
scriptFile = Path::getPathFromFilename(exename) + "/addons/" + fileName + ".py";
return "";
}
};
}
static std::string executeAddon(const AddonInfo &addonInfo, const std::string &dumpFile)
{
const std::string cmd = "python " + addonInfo.scriptFile + " --cli" + addonInfo.args + " " + dumpFile;
#ifdef _WIN32
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
#else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
#endif
if (!pipe)
return "";
char buffer[1024];
std::string result;
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
result += buffer;
}
return result;
}
static std::vector<std::string> split(const std::string &str, const std::string &sep)
{
std::vector<std::string> ret;
@ -553,12 +575,12 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
for (const std::string &addon : mSettings.addons) {
struct AddonInfo addonInfo;
const std::string errmsg = addonInfo.getAddonInfo(addon);
const std::string errmsg = addonInfo.getAddonInfo(addon, mSettings.exename);
if (!errmsg.empty()) {
reportOut(errmsg);
continue;
}
const std::string &results = executeAddon(addonInfo.script, addonInfo.args, dumpFile);
const std::string &results = executeAddon(addonInfo, dumpFile);
for (std::string::size_type pos = 0; pos < results.size();) {
const std::string::size_type pos2 = results.find("\n", pos);
if (pos2 == std::string::npos)
@ -597,7 +619,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
continue;
// line must end with [addon-x]
const std::string::size_type id1 = line.rfind("[" + addonInfo.script + "-");
const std::string::size_type id1 = line.rfind("[" + addonInfo.name + "-");
if (id1 == std::string::npos || id1 < sev2)
continue;
@ -999,26 +1021,6 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
#endif
}
std::string CppCheck::executeAddon(const std::string &addon, const std::string &args, const std::string &dumpFile)
{
const std::string addonFile = "addons/" + addon + ".py";
const std::string cmd = "python " + addonFile + " --cli" + args + " " + dumpFile;
#ifdef _WIN32
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
#else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
#endif
if (!pipe)
return "";
char buffer[1024];
std::string result;
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
result += buffer;
}
return result;
}
Settings &CppCheck::settings()
{
return mSettings;

View File

@ -179,12 +179,6 @@ private:
*/
void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer);
/**
* @brief Execute a given addon
* @return results in std::string
*/
std::string executeAddon(const std::string &addon, const std::string &args, const std::string &dumpFile);
/**
* @brief Errors and warnings are directed here.
*

View File

@ -121,6 +121,9 @@ public:
/** @brief Is --exception-handling given */
bool exceptionHandling;
// argv[0]
std::string exename;
/** @brief If errors are found, this value is returned from main().
Default value is 0. */
int exitCode;

View File

@ -37,6 +37,32 @@ def test_absolute_path():
assert stdout == 'Checking %s/main.c ...\n' % (prjpath)
assert stderr == '[%s/main.c:5]: (error) Division by zero.\n' % (prjpath)
def test_addon_local_path():
cwd = os.getcwd()
os.chdir('1-helloworld')
ret, stdout, stderr = cppcheck('--addon=misra .')
os.chdir(cwd)
assert ret == 0
assert stdout == 'Checking main.c ...\n'
assert stderr == ('[main.c:5]: (error) Division by zero.\n'
'[main.c:1]: (style) misra violation (use --rule-texts=<file> to get proper output)\n')
def test_addon_absolute_path():
prjpath = '%s/1-helloworld' % (os.getcwd())
ret, stdout, stderr = cppcheck('--addon=misra %s' % (prjpath))
assert ret == 0
assert stdout == 'Checking %s/main.c ...\n' % (prjpath)
assert stderr == ('[%s/main.c:5]: (error) Division by zero.\n'
'[%s/main.c:1]: (style) misra violation (use --rule-texts=<file> to get proper output)\n' % (prjpath, prjpath))
def test_addon_relative_path():
prjpath = '1-helloworld'
ret, stdout, stderr = cppcheck('--addon=misra %s' % (prjpath))
assert ret == 0
assert stdout == 'Checking %s/main.c ...\n' % (prjpath)
assert stderr == ('[%s/main.c:5]: (error) Division by zero.\n'
'[%s/main.c:1]: (style) misra violation (use --rule-texts=<file> to get proper output)\n' % (prjpath, prjpath))
def test_basepath_relative_path():
prjpath = '1-helloworld'
ret, stdout, stderr = cppcheck('%s -rp=%s' % (prjpath, prjpath))