forked from platformio/platformio-core
Minor improvements to check tools
- Better handling of unusual macro for PVS-Studio - Fail the analysis if Cppcheck exited with an internal error
This commit is contained in:
@@ -49,6 +49,7 @@ class CppcheckCheckTool(CheckToolBase):
|
|||||||
for msg in (
|
for msg in (
|
||||||
"No C or C++ source files found",
|
"No C or C++ source files found",
|
||||||
"unrecognized command line option",
|
"unrecognized command line option",
|
||||||
|
"there was an internal error",
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
self._bad_input = True
|
self._bad_input = True
|
||||||
|
@@ -53,7 +53,15 @@ class PvsStudioCheckTool(CheckToolBase): # pylint: disable=too-many-instance-at
|
|||||||
)
|
)
|
||||||
|
|
||||||
def tool_output_filter(self, line): # pylint: disable=arguments-differ
|
def tool_output_filter(self, line): # pylint: disable=arguments-differ
|
||||||
if "license was not entered" in line.lower():
|
if any(
|
||||||
|
[
|
||||||
|
err_msg in line.lower()
|
||||||
|
for err_msg in (
|
||||||
|
"license was not entered",
|
||||||
|
"license information is incorrect",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
):
|
||||||
self._bad_input = True
|
self._bad_input = True
|
||||||
return line
|
return line
|
||||||
|
|
||||||
@@ -193,7 +201,7 @@ class PvsStudioCheckTool(CheckToolBase): # pylint: disable=too-many-instance-at
|
|||||||
'"%s"' % self._tmp_preprocessed_file,
|
'"%s"' % self._tmp_preprocessed_file,
|
||||||
]
|
]
|
||||||
cmd.extend([f for f in flags if f])
|
cmd.extend([f for f in flags if f])
|
||||||
cmd.extend(["-D%s" % d for d in self.cpp_defines])
|
cmd.extend(['"-D%s"' % d.replace('"', '\\"') for d in self.cpp_defines])
|
||||||
cmd.append('@"%s"' % self._tmp_cmd_file)
|
cmd.append('@"%s"' % self._tmp_cmd_file)
|
||||||
|
|
||||||
# Explicitly specify C++ as the language used in .ino files
|
# Explicitly specify C++ as the language used in .ino files
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
from os.path import isfile, join
|
from os.path import isfile, join
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -121,6 +122,56 @@ def test_check_tool_defines_passed(clirunner, check_dir):
|
|||||||
assert "__GNUC__" in output
|
assert "__GNUC__" in output
|
||||||
|
|
||||||
|
|
||||||
|
def test_check_tool_complex_defines_handled(
|
||||||
|
clirunner, validate_cliresult, tmpdir_factory
|
||||||
|
):
|
||||||
|
project_dir = tmpdir_factory.mktemp("project_dir")
|
||||||
|
|
||||||
|
project_dir.join("platformio.ini").write(
|
||||||
|
DEFAULT_CONFIG
|
||||||
|
+ R"""
|
||||||
|
check_tool = cppcheck, clangtidy, pvs-studio
|
||||||
|
build_flags =
|
||||||
|
-DEXTERNAL_INCLUDE_FILE=\"test.h\"
|
||||||
|
"-DDEFINE_WITH_SPACE="Hello World!""
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
src_dir = project_dir.mkdir("src")
|
||||||
|
src_dir.join("test.h").write(
|
||||||
|
"""
|
||||||
|
#ifndef TEST_H
|
||||||
|
#define TEST_H
|
||||||
|
#define ARBITRARY_CONST_VALUE 10
|
||||||
|
#endif
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
src_dir.join("main.c").write(
|
||||||
|
PVS_STUDIO_FREE_LICENSE_HEADER
|
||||||
|
+ """
|
||||||
|
#if !defined(EXTERNAL_INCLUDE_FILE)
|
||||||
|
#error "EXTERNAL_INCLUDE_FILE is not declared!"
|
||||||
|
#else
|
||||||
|
#include EXTERNAL_INCLUDE_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/* Index out of bounds */
|
||||||
|
int arr[ARBITRARY_CONST_VALUE];
|
||||||
|
for(int i=0; i < ARBITRARY_CONST_VALUE+1; i++) {
|
||||||
|
arr[i] = 0; /* High */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
default_result = clirunner.invoke(cmd_check, ["--project-dir", str(project_dir)])
|
||||||
|
validate_cliresult(default_result)
|
||||||
|
|
||||||
|
|
||||||
def test_check_language_standard_definition_passed(clirunner, tmpdir):
|
def test_check_language_standard_definition_passed(clirunner, tmpdir):
|
||||||
config = DEFAULT_CONFIG + "\nbuild_flags = -std=c++17"
|
config = DEFAULT_CONFIG + "\nbuild_flags = -std=c++17"
|
||||||
tmpdir.join("platformio.ini").write(config)
|
tmpdir.join("platformio.ini").write(config)
|
||||||
@@ -466,6 +517,38 @@ def test_check_pvs_studio_fails_without_license(clirunner, tmpdir):
|
|||||||
assert "license was not entered" in verbose_result.output.lower()
|
assert "license was not entered" in verbose_result.output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
sys.platform != "win32",
|
||||||
|
reason="For some reason the error message is different on Windows",
|
||||||
|
)
|
||||||
|
def test_check_pvs_studio_fails_broken_license(clirunner, tmpdir):
|
||||||
|
config = (
|
||||||
|
DEFAULT_CONFIG
|
||||||
|
+ """
|
||||||
|
check_tool = pvs-studio
|
||||||
|
check_flags = --lic-file=./pvs-studio.lic
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
tmpdir.join("platformio.ini").write(config)
|
||||||
|
tmpdir.mkdir("src").join("main.c").write(TEST_CODE)
|
||||||
|
tmpdir.join("pvs-studio.lic").write(
|
||||||
|
"""
|
||||||
|
TEST
|
||||||
|
TEST-TEST-TEST-TEST
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
default_result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir)])
|
||||||
|
verbose_result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir), "-v"])
|
||||||
|
|
||||||
|
assert default_result.exit_code != 0
|
||||||
|
assert "failed to perform check" in default_result.output.lower()
|
||||||
|
|
||||||
|
assert verbose_result.exit_code != 0
|
||||||
|
assert "license information is incorrect" in verbose_result.output.lower()
|
||||||
|
|
||||||
|
|
||||||
def test_check_embedded_platform_all_tools(clirunner, validate_cliresult, tmpdir):
|
def test_check_embedded_platform_all_tools(clirunner, validate_cliresult, tmpdir):
|
||||||
config = """
|
config = """
|
||||||
[env:test]
|
[env:test]
|
||||||
|
Reference in New Issue
Block a user