2019-09-20 13:39:38 +02:00
|
|
|
# Running the test with Python 2:
|
|
|
|
# Be sure to install pytest version 4.6.4 (newer should also work)
|
|
|
|
# Command in cppcheck directory:
|
2019-06-17 21:17:29 +02:00
|
|
|
# python -m pytest addons/test/test-misra.py
|
2019-09-20 13:39:38 +02:00
|
|
|
#
|
|
|
|
# Running the test with Python 3:
|
|
|
|
# Command in cppcheck directory:
|
|
|
|
# PYTHONPATH=./addons python3 -m pytest addons/test/test-misra.py
|
2019-07-26 06:38:03 +02:00
|
|
|
|
2023-11-08 15:23:50 +01:00
|
|
|
import os
|
2019-06-17 21:17:29 +02:00
|
|
|
import pytest
|
2019-07-16 22:32:41 +02:00
|
|
|
import re
|
2019-06-19 21:57:28 +02:00
|
|
|
import sys
|
2023-11-08 15:23:50 +01:00
|
|
|
import tempfile
|
2019-06-19 21:57:28 +02:00
|
|
|
|
2019-07-26 06:38:03 +02:00
|
|
|
from .util import dump_create, dump_remove, convert_json_output
|
2019-06-23 14:08:05 +02:00
|
|
|
|
|
|
|
|
2019-07-26 06:38:03 +02:00
|
|
|
TEST_SOURCE_FILES = ['./addons/test/misra/misra-test.c']
|
2019-06-23 14:08:05 +02:00
|
|
|
|
|
|
|
|
2023-10-28 16:58:59 +02:00
|
|
|
def remove_misra_config(s:str):
|
|
|
|
ret = ''
|
|
|
|
for line in s.splitlines():
|
|
|
|
if '[misra-config]' not in line:
|
|
|
|
ret += line + '\n'
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2019-07-16 22:32:41 +02:00
|
|
|
@pytest.fixture(scope="function")
|
2019-06-17 21:17:29 +02:00
|
|
|
def checker():
|
2021-07-06 22:13:04 +02:00
|
|
|
from addons.misra import MisraChecker, MisraSettings, get_args_parser
|
|
|
|
parser = get_args_parser()
|
|
|
|
args = parser.parse_args([])
|
2019-06-17 21:17:29 +02:00
|
|
|
settings = MisraSettings(args)
|
|
|
|
return MisraChecker(settings)
|
|
|
|
|
|
|
|
|
2023-11-08 15:23:50 +01:00
|
|
|
@pytest.fixture
|
|
|
|
def test_files():
|
|
|
|
for f in TEST_SOURCE_FILES:
|
|
|
|
dump_create(f)
|
|
|
|
yield
|
|
|
|
for f in TEST_SOURCE_FILES:
|
|
|
|
dump_remove(f)
|
|
|
|
|
|
|
|
|
2019-06-17 21:17:29 +02:00
|
|
|
def test_loadRuleTexts_structure(checker):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_structure.txt")
|
2019-06-17 21:17:29 +02:00
|
|
|
assert(checker.ruleTexts.get(101, None) is None)
|
|
|
|
assert(checker.ruleTexts[102].text == "Rule text.")
|
|
|
|
assert(checker.ruleTexts.get(103, None) is None)
|
|
|
|
|
|
|
|
|
|
|
|
def test_loadRuleTexts_empty_lines(checker):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_empty_lines.txt")
|
2019-06-17 21:17:29 +02:00
|
|
|
assert(len(checker.ruleTexts) == 3)
|
|
|
|
assert(len(checker.ruleTexts[102].text) == len("Rule text."))
|
|
|
|
|
|
|
|
|
|
|
|
def test_loadRuleTexts_mutiple_lines(checker):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_multiple_lines.txt")
|
2019-06-17 21:17:29 +02:00
|
|
|
assert(checker.ruleTexts[101].text == "Multiple lines text.")
|
|
|
|
assert(checker.ruleTexts[102].text == "Multiple lines text.")
|
|
|
|
assert(checker.ruleTexts[103].text == "Multiple lines text.")
|
|
|
|
assert(checker.ruleTexts[104].text == "Should")
|
|
|
|
assert(checker.ruleTexts[105].text == "Should")
|
2019-09-09 21:43:44 +02:00
|
|
|
assert(checker.ruleTexts[106].text == "Can contain empty lines.")
|
2019-06-17 21:17:29 +02:00
|
|
|
|
2019-06-19 21:57:28 +02:00
|
|
|
|
2019-07-16 22:32:41 +02:00
|
|
|
def test_verifyRuleTexts(checker, capsys):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt")
|
2019-07-16 22:32:41 +02:00
|
|
|
checker.verifyRuleTexts()
|
|
|
|
captured = capsys.readouterr().out
|
2019-06-19 21:57:28 +02:00
|
|
|
assert("21.3" not in captured)
|
|
|
|
assert("1.3" in captured)
|
2019-06-23 14:08:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_rules_misra_severity(checker):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt")
|
2019-06-23 14:08:05 +02:00
|
|
|
assert(checker.ruleTexts[1004].misra_severity == 'Mandatory')
|
|
|
|
assert(checker.ruleTexts[401].misra_severity == 'Required')
|
|
|
|
assert(checker.ruleTexts[1505].misra_severity == 'Advisory')
|
|
|
|
assert(checker.ruleTexts[2104].misra_severity == '')
|
|
|
|
|
|
|
|
|
2023-11-08 15:23:50 +01:00
|
|
|
def test_json_out(checker, capsys, test_files):
|
2019-06-25 00:42:13 +02:00
|
|
|
sys.argv.append("--cli")
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt")
|
|
|
|
checker.parseDump("./addons/test/misra/misra-test.c.dump")
|
2019-07-16 22:32:41 +02:00
|
|
|
captured = capsys.readouterr()
|
|
|
|
captured = captured.out.splitlines()
|
2019-06-25 00:42:13 +02:00
|
|
|
sys.argv.remove("--cli")
|
2019-07-26 06:38:03 +02:00
|
|
|
json_output = convert_json_output(captured)
|
|
|
|
assert("Mandatory" in json_output['c2012-10.4'][0]['extra'])
|
|
|
|
assert("Required" in json_output['c2012-21.3'][0]['extra'])
|
|
|
|
assert("Advisory" in json_output['c2012-20.1'][0]['extra'])
|
2019-06-25 00:42:13 +02:00
|
|
|
|
|
|
|
|
2023-11-08 15:23:50 +01:00
|
|
|
def test_rules_cppcheck_severity(checker, capsys, test_files):
|
2019-07-26 06:38:03 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt")
|
|
|
|
checker.parseDump("./addons/test/misra/misra-test.c.dump")
|
2019-07-16 22:32:41 +02:00
|
|
|
captured = capsys.readouterr().err
|
2023-10-28 16:58:59 +02:00
|
|
|
assert("(error)" not in remove_misra_config(captured))
|
2019-06-23 14:08:05 +02:00
|
|
|
assert("(warning)" not in captured)
|
|
|
|
assert("(style)" in captured)
|
2019-07-16 22:32:41 +02:00
|
|
|
|
2023-11-08 15:23:50 +01:00
|
|
|
def test_rules_cppcheck_severity_custom(checker, capsys, test_files):
|
2020-06-08 15:58:17 +02:00
|
|
|
checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt")
|
|
|
|
checker.setSeverity("custom-severity")
|
|
|
|
checker.parseDump("./addons/test/misra/misra-test.c.dump")
|
|
|
|
captured = capsys.readouterr().err
|
2023-10-28 16:58:59 +02:00
|
|
|
assert("(error)" not in remove_misra_config(captured))
|
2020-06-08 15:58:17 +02:00
|
|
|
assert("(warning)" not in captured)
|
|
|
|
assert("(style)" not in captured)
|
|
|
|
assert("(custom-severity)" in captured)
|
2019-07-16 22:32:41 +02:00
|
|
|
|
|
|
|
def test_rules_suppression(checker, capsys):
|
2019-07-26 06:38:03 +02:00
|
|
|
test_sources = ["addons/test/misra/misra-suppressions1-test.c",
|
|
|
|
"addons/test/misra/misra-suppressions2-test.c"]
|
2019-07-16 22:32:41 +02:00
|
|
|
|
|
|
|
for src in test_sources:
|
|
|
|
re_suppressed= r"\[%s\:[0-9]+\]" % src
|
|
|
|
dump_remove(src)
|
2019-07-26 06:38:03 +02:00
|
|
|
dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt")
|
2019-07-16 22:32:41 +02:00
|
|
|
checker.parseDump(src + ".dump")
|
|
|
|
captured = capsys.readouterr().err
|
|
|
|
found = re.search(re_suppressed, captured)
|
2020-11-11 20:28:26 +01:00
|
|
|
assert found is None, 'Unexptected output:\n' + captured
|
2019-07-16 22:32:41 +02:00
|
|
|
dump_remove(src)
|
2019-07-24 07:16:48 +02:00
|
|
|
|
|
|
|
def test_arguments_regression():
|
|
|
|
args_ok = ["-generate-table",
|
|
|
|
"--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt",
|
|
|
|
"--verify-rule-texts",
|
|
|
|
"-t=foo", "--template=foo",
|
|
|
|
"--suppress-rules=15.1",
|
|
|
|
"--quiet",
|
|
|
|
"--cli",
|
|
|
|
"--no-summary",
|
|
|
|
"--show-suppressed-rules",
|
2020-06-08 15:58:17 +02:00
|
|
|
"-P=src/", "--file-prefix=src/",
|
|
|
|
"--severity=misra-warning"]
|
2019-07-24 07:16:48 +02:00
|
|
|
# Arguments with expected SystemExit
|
|
|
|
args_exit = ["--non-exists", "--non-exists-param=42", "-h", "--help"]
|
|
|
|
|
2021-07-06 22:13:04 +02:00
|
|
|
from addons.misra import get_args_parser
|
2019-07-24 07:16:48 +02:00
|
|
|
|
2022-07-13 21:09:29 +02:00
|
|
|
# sys.argv contains all pytest arguments - so clear all existing arguments first and restore afterwards
|
|
|
|
sys_argv_old = sys.argv
|
|
|
|
sys.argv = [sys.argv[0]]
|
|
|
|
|
|
|
|
try:
|
|
|
|
for arg in args_exit:
|
|
|
|
sys.argv.append(arg)
|
|
|
|
with pytest.raises(SystemExit):
|
|
|
|
parser = get_args_parser()
|
|
|
|
parser.parse_args()
|
|
|
|
sys.argv.remove(arg)
|
|
|
|
|
|
|
|
for arg in args_ok:
|
|
|
|
sys.argv.append(arg)
|
|
|
|
try:
|
|
|
|
parser = get_args_parser()
|
|
|
|
parser.parse_args()
|
|
|
|
except SystemExit:
|
|
|
|
pytest.fail("Unexpected SystemExit with '%s'" % arg)
|
|
|
|
sys.argv.remove(arg)
|
|
|
|
finally:
|
|
|
|
sys.argv = sys_argv_old
|
2023-11-08 15:23:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
def test_read_ctu_info_line(checker):
|
|
|
|
assert checker.read_ctu_info_line('{') is None
|
|
|
|
assert checker.read_ctu_info_line('{"summary":"123"}') is None
|
|
|
|
assert checker.read_ctu_info_line('{"data":123}') is None
|
|
|
|
assert checker.read_ctu_info_line('{"summary":"123","data":123}') is not None
|