From f005a05882c0f3055c0ee664ef5a655d35377e02 Mon Sep 17 00:00:00 2001 From: dzid26 Date: Sun, 15 Sep 2024 19:14:40 -0700 Subject: [PATCH] Testing for unused objects - whole program analysis and configurations --- test/cli/whole-program/configs_unused.c | 18 +++++ test/cli/whole-program_test.py | 103 ++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 test/cli/whole-program/configs_unused.c diff --git a/test/cli/whole-program/configs_unused.c b/test/cli/whole-program/configs_unused.c new file mode 100644 index 00000000000..d31df2f632e --- /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 54c1f7e93a5..f321964088f 100644 --- a/test/cli/whole-program_test.py +++ b/test/cli/whole-program_test.py @@ -11,15 +11,17 @@ # TODO: test CheckBufferOverrun -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 - } + 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: @@ -295,3 +297,88 @@ def test_checkclass_project_builddir(tmpdir): build_dir = os.path.join(tmpdir, 'b1') os.mkdir(build_dir) __test_checkclass_project(tmpdir, ['-j1', '--cppcheck-build-dir={}'.format(build_dir)]) + +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 == [ + ] + # 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 == [ + ] + assert stdout == '' + assert ret == 0, stdout \ No newline at end of file