diff --git a/src/engines/python-engine.cc b/src/engines/python-engine.cc index c60803fd..f0836c63 100644 --- a/src/engines/python-engine.cc +++ b/src/engines/python-engine.cc @@ -55,11 +55,21 @@ class PythonEngine : public ScriptEngineBase bool start(IEventListener &listener, const std::string &executable) { + IConfiguration &conf = IConfiguration::getInstance(); + std::string command = conf.keyAsString("python-command"); + std::string kcov_python_pipe_path = IOutputHandler::getInstance().getOutDirectory() + "kcov-python.pipe"; std::string kcov_python_path = IOutputHandler::getInstance().getBaseDirectory() + "python-helper.py"; + if (!executable_exists_in_path(command)) + { + error("Cannot find Python parser '%s'", command.c_str()); + + return false; + } + if (write_file(python_helper_data.data(), python_helper_data.size(), "%s", kcov_python_path.c_str()) < 0) { error("Can't write python helper at %s", kcov_python_path.c_str()); @@ -85,12 +95,11 @@ class PythonEngine : public ScriptEngineBase /* Launch the python helper */ m_child = fork(); if (m_child == 0) { - IConfiguration &conf = IConfiguration::getInstance(); const char **argv = conf.getArgv(); unsigned int argc = conf.getArgc(); std::string s = fmt("%s %s ", - conf.keyAsString("python-command").c_str(), + command.c_str(), kcov_python_path.c_str()); for (unsigned int i = 0; i < argc; i++) s += "'" + std::string(argv[i]) + "' "; diff --git a/src/include/utils.hh b/src/include/utils.hh index 31b44cbc..66904058 100644 --- a/src/include/utils.hh +++ b/src/include/utils.hh @@ -112,6 +112,8 @@ extern std::string dir_concat(const std::string &dir, const std::string &filenam extern bool file_exists(const std::string &path); +extern bool executable_exists_in_path(const std::string &path); + extern uint64_t get_file_timestamp(const std::string &path); extern int concat_files(const char *dst, const char *file_a, const char *file_b); diff --git a/src/utils.cc b/src/utils.cc index b522ea2a..1a3df090 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -288,6 +288,32 @@ bool file_exists(const std::string &path) return out; } +bool executable_exists_in_path(const std::string &executableName) +{ + // Full path to it + if (file_exists(executableName)) + { + return true; + } + + std::string path = getenv("PATH"); + std::vector parts = split_string(path, ":"); + + for (std::vector::iterator it = parts.begin(); + it != parts.end(); + ++it) + { + std::string cur = fmt("%s/%s", it->c_str(), executableName.c_str()); + + if (file_exists(cur)) + { + return true; + } + } + + return false; +} + void mock_read_file(void *(*callback)(size_t *out_size, const char *path)) { mocked_read_callback = callback; diff --git a/tests/tools/python.py b/tests/tools/python.py index dc59b37c..b796d16f 100644 --- a/tests/tools/python.py +++ b/tests/tools/python.py @@ -10,6 +10,20 @@ def runTest(self): assert rv == noKcovRv +class python_can_set_illegal_parser(testbase.KcovTestCase): + def runTest(self): + self.setUp() + rv,o = self.do(testbase.kcov + " --python-parser=python7 " + testbase.outbase + "/kcov " + testbase.sources + "/tests/python/main 5") + + assert o.find("Cannot find Python parser 'python7'") != -1 + +class python_can_set_legal_parser(testbase.KcovTestCase): + def runTest(self): + self.setUp() + rv,o = self.do(testbase.kcov + " --python-parser=python3 " + testbase.outbase + "/kcov " + testbase.sources + "/tests/python/main 5") + + assert o.find("Cannot find Python parser 'python3'") == -1 + class python_unittest(testbase.KcovTestCase): def runTest(self): self.setUp()