diff --git a/test/cli/whole-program/configs_unused.c b/test/cli/whole-program/configs_unused.c new file mode 100644 index 000000000000..d31df2f632eb --- /dev/null +++ b/test/cli/whole-program/configs_unused.c @@ -0,0 +1,18 @@ +// cppcheck-suppress misra-c2012-2.3 +typedef struct { + int x; // cppcheck-suppress unusedStructMember +} X; + +static void func(void) {}; + +int main(void) { + #ifdef A + X x = {5}; + func(); + return x.x; + + #elif defined(B) + return 0; + #endif + +} \ No newline at end of file diff --git a/test/cli/whole-program_test.py b/test/cli/whole-program_test.py index a256d3d7b288..56106201fc5a 100644 --- a/test/cli/whole-program_test.py +++ b/test/cli/whole-program_test.py @@ -8,16 +8,17 @@ # TODO: use dedicated addon -def __create_compile_commands(dir, entries): +def __create_compile_commands(dir, filePaths, definesList=[[None]]): j = [] - for e in entries: - f = os.path.basename(e) - obj = { - 'directory': os.path.dirname(os.path.abspath(e)), - 'command': 'gcc -c {}'.format(f), - 'file': f - } - print(obj) + for i, fp in enumerate(filePaths): + f = os.path.basename(fp) + + for defines in (definesList[i] if len(definesList) > i else [None]): + obj = { + 'directory': os.path.dirname(os.path.abspath(fp)), + 'command': 'gcc -c {} {}'.format(f, ' '.join('-D{}'.format(define) for define in defines) if defines is not None else ''), + 'file': f + } j.append(obj) compile_commands = os.path.join(dir, 'compile_commmands.json') with open(compile_commands, 'wt') as f: @@ -85,3 +86,98 @@ def test_addon_suppress_inline_project(tmpdir): @pytest.mark.xfail(strict=True) def test_addon_suppress_inline_project_j(tmpdir): __test_addon_suppress_inline_project(tmpdir, ['-j2']) + + + +# @pytest.mark.xfail(strict=True) +def test_unused_A_B(): + args = [ + '-q', + '--addon=misra', + '--template=simple', + '--enable=all', + '--error-exitcode=1', + 'whole-program/configs_unused.c' + ] + + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + lines = stderr.splitlines() + assert lines == [ + "whole-program/configs_unused.c:3:9: style: struct member 'X::x' is never used. [unusedStructMember]", + "whole-program/configs_unused.c:2:1: style: misra violation (use --rule-texts= to get proper output) [misra-c2012-2.3]", + ] + assert stdout == '' + assert ret == 1, stdout + + +@pytest.mark.xfail(strict=True) +def test_unused_with_project_A_and_B(tmpdir): + # A and B config + configs_unused_file = os.path.join(__script_dir, 'whole-program', 'configs_unused.c') + compile_db = __create_compile_commands(tmpdir, [configs_unused_file], + [["A", "B"]] + ) + args = [ + '-q', + '--addon=misra', + '--template=simple', + '--enable=all', + '--error-exitcode=1', + '--project={}'.format(compile_db) + ] + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + lines = stderr.splitlines() + assert lines == [ + # "{}:3:9: style: struct member 'X::x' is never used. [unusedStructMember]".format(configs_unused_file), + # "{}:6:13: style: misra violation (use --rule-texts= to get proper output) [misra-c2012-5.9]".format(configs_unused_file), # this one is due to duplicate ctu-info content + # "{}:2:1: style: misra violation (use --rule-texts= to get proper output) [misra-c2012-2.3]".format(configs_unused_file), + ] + assert stdout == '' + assert ret == 0, stdout + + +def test_unused_with_project_A_or_B(tmpdir): + # A or B configs + configs_unused_file = os.path.join(__script_dir, 'whole-program', 'configs_unused.c') + compile_db = __create_compile_commands(tmpdir, [configs_unused_file], + [["A"], ["B"]] + ) + args = [ + '-q', + '--addon=misra', + '--template=simple', + '--enable=all', + '--error-exitcode=1', + '--project={}'.format(compile_db) + ] + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + lines = stderr.splitlines() + assert lines == [ + ] + assert stdout == '' + assert ret == 0, stdout + +@pytest.mark.xfail(strict=True) +def test_unused_with_project_B_or_A(tmpdir): + # A or B configs + configs_unused_file = os.path.join(__script_dir, 'whole-program', 'configs_unused.c') + compile_db = __create_compile_commands(tmpdir, [configs_unused_file], + [["B"], ["A"]] + ) + args = [ + '-q', + '--addon=misra', + '--template=simple', + '--enable=all', + '--error-exitcode=1', + '--project={}'.format(compile_db) + ] + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + lines = stderr.splitlines() + assert lines == [ + # "{}:3:9: style: struct member 'X::x' is never used. [unusedStructMember]".format(configs_unused_file), + # "{}:6:0: style: The function 'func' is never used. [unusedFunction]".format(configs_unused_file), + # "{}:2:1: style: misra violation (use --rule-texts= to get proper output) [misra-c2012-2.3]".format(configs_unused_file), + ] + assert stdout == '' + assert ret == 0, stdout \ No newline at end of file