Skip to content

Commit

Permalink
Fix a bug in Ericsson#3866 where check didn't respect --no-missing-ch…
Browse files Browse the repository at this point in the history
…ecker-error

'CodeChecker analyze' was correctly turning errors into warnings when
invoked with --no-missing-checker-error, but 'CodeChecker check' wasn't.
  • Loading branch information
Szelethus committed Apr 15, 2024
1 parent 42afcee commit 2a8b6f8
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 54 deletions.
1 change: 1 addition & 0 deletions analyzer/codechecker_analyzer/cmd/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,7 @@ def main(args):
compile_commands = \
compilation_database.gather_compilation_database(args.input)
if compile_commands is None:
LOG.error(f"Found no compilation commands in '{args.input}'")
sys.exit(1)

# Process the skip list if present.
Expand Down
1 change: 1 addition & 0 deletions analyzer/codechecker_analyzer/cmd/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,7 @@ def __update_if_key_exists(source, target, key):
if 'clean' in args:
setattr(analyze_args, 'clean', True)
__update_if_key_exists(args, analyze_args, 'verbose')
__update_if_key_exists(args, analyze_args, 'no_missing_checker_error')

import codechecker_analyzer.cmd.analyze as analyze_module
LOG.debug("Calling ANALYZE with args:")
Expand Down
173 changes: 119 additions & 54 deletions analyzer/tests/functional/analyze/test_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import re
import shutil
import subprocess
import shlex
import unittest
import zipfile

Expand Down Expand Up @@ -62,8 +63,11 @@ def setup_method(self, method):
self.__old_pwd = os.getcwd()
os.chdir(self.test_dir)

self.missing_checker_regex = re.compile(
r"No checker\(s\) with these names was found")
self.warn_missing_checker_regex = re.compile(
r"WARNING.*No checker\(s\) with these names was found")

self.err_missing_checker_regex = re.compile(
r"ERROR.*No checker\(s\) with these names was found")

self.disabling_modeling_checker_regex = re.compile(
r"analyzer-disable-checker=.*unix.cstring.CStringModeling.*")
Expand Down Expand Up @@ -781,24 +785,11 @@ def test_compile_uniqueing(self):
self.assertFalse(os.path.isdir(failed_dir))
self.check_unique_compilation_db(unique_json, 3, True, True, True)

def __run_with_invalid_enabled_checker_name(self, extra_args):
build_json = os.path.join(self.test_workspace, "build_success.json")
analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "clangsa", "-o", self.report_dir,
"-e", "non-existing-checker-name"]
analyze_cmd.extend(extra_args)

source_file = os.path.join(self.test_dir, "success.c")
build_log = [{"directory": self.test_workspace,
"command": "gcc -c " + source_file,
"file": source_file
}]
def __run_with_invalid_checker_name(self, codechecker_subcommand,
extra_args):
analyze_cmd = codechecker_subcommand + extra_args

with open(build_json, 'w',
encoding="utf-8", errors="ignore") as outfile:
json.dump(build_log, outfile)

print(analyze_cmd)
print(shlex.join(analyze_cmd))
process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
Expand All @@ -809,11 +800,54 @@ def __run_with_invalid_enabled_checker_name(self, extra_args):
out, err = process.communicate()
return out, err, process.returncode

def __run_with_invalid_enabled_checker_name_common(self,
codechecker_subcommand,
extra_args):
return self.__run_with_invalid_checker_name(
codechecker_subcommand + ["--analyzers", "clangsa", "-o",
self.report_dir, "-c", "-e",
"non-existing-checker-name"], extra_args)

def __get_build_json(self):
build_json = os.path.join(self.test_workspace, "build_success.json")
source_file = os.path.join(self.test_dir, "success.c")
build_log = [{
"directory": self.test_workspace,
"command": "gcc -c " + source_file,
"file": source_file}]
with open(build_json, 'w',
encoding="utf-8", errors="ignore") as outfile:
json.dump(build_log, outfile)
return build_json

def __run_with_invalid_enabled_checker_name_check(self, extra_args):
codechecker_subcommand = [self._codechecker_cmd, "check", "-l",
self.__get_build_json()]
return self.__run_with_invalid_enabled_checker_name_common(
codechecker_subcommand, extra_args)

def __run_with_invalid_enabled_checker_name_analyze(self, extra_args):
build_json = os.path.join(self.test_workspace, "build_success.json")
codechecker_subcommand = [self._codechecker_cmd, "analyze",
self.__get_build_json()]
return self.__run_with_invalid_enabled_checker_name_common(
codechecker_subcommand, extra_args)

def test_invalid_enabled_checker_name(self):
"""Error out in case of an invalid enabled checker."""
out, _, errcode = self.__run_with_invalid_enabled_checker_name([])
out, err, errcode = \
self.__run_with_invalid_enabled_checker_name_check([])

match = self.err_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

self.assertEqual(errcode, 1)

match = self.missing_checker_regex.search(out)
out, _, errcode = \
self.__run_with_invalid_enabled_checker_name_analyze([])

match = self.err_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

Expand All @@ -824,15 +858,29 @@ def test_invalid_enabled_checker_name_warn(self):
Warn in case of an invalid enabled checker when using
--no-missing-checker-error.
"""
out, _, errcode = self.__run_with_invalid_enabled_checker_name(
out, _, errcode = self.__run_with_invalid_enabled_checker_name_analyze(
['--no-missing-checker-error'])

match = self.missing_checker_regex.search(out)
match = self.warn_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

self.assertEqual(errcode, 0)

out, _, errcode = self.__run_with_invalid_enabled_checker_name_check(
['--no-missing-checker-error'])

print(out)
match = self.warn_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

# FIXME: Interestingly, CodeChecker analyze doesn't find the bug in the
# code, but CodeChecker check does, so the return value is 2 here
# instead of 0. Lets just check that its not a CodeChecker error (which
# would be a return code of 1).
self.assertNotEqual(errcode, 1)

def test_disable_all_warnings(self):
"""Test disabling warnings as checker groups."""
build_json = os.path.join(self.test_workspace, "build.json")
Expand Down Expand Up @@ -865,39 +913,42 @@ def test_disable_all_warnings(self):
self.assertIn("unused variable 'i' [clang-diagnostic-unused-variable]",
out)

def __run_with_invalid_disabled_checker_name(self, extra_args):
def __run_with_invalid_disabled_checker_name_common(self,
codechecker_subcommand,
extra_args):
return self.__run_with_invalid_checker_name(
codechecker_subcommand + ["--analyzers", "clangsa", "-o",
self.report_dir, "-c", "-d",
"non-existing-checker-name"], extra_args)

def __run_with_invalid_disabled_checker_name_check(self, extra_args):
codechecker_subcommand = [self._codechecker_cmd, "check", "-l",
self.__get_build_json()]
return self.__run_with_invalid_disabled_checker_name_common(
codechecker_subcommand, extra_args)

def __run_with_invalid_disabled_checker_name_analyze(self, extra_args):
build_json = os.path.join(self.test_workspace, "build_success.json")
analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "clangsa", "-o", self.report_dir,
"-d", "non-existing-checker-name"]
analyze_cmd.extend(extra_args)
codechecker_subcommand = [self._codechecker_cmd, "analyze",
self.__get_build_json()]
return self.__run_with_invalid_disabled_checker_name_common(
codechecker_subcommand, extra_args)

source_file = os.path.join(self.test_dir, "success.c")
build_log = [{"directory": self.test_workspace,
"command": "gcc -c " + source_file,
"file": source_file
}]
def test_invalid_disabled_checker_name(self):
"""Error out in case of an invalid disabled checker."""
out, _, errcode = \
self.__run_with_invalid_disabled_checker_name_analyze([])

with open(build_json, 'w',
encoding="utf-8", errors="ignore") as outfile:
json.dump(build_log, outfile)
match = self.err_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

print(analyze_cmd)
process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, err = process.communicate()
return out, err, process.returncode
self.assertEqual(errcode, 1)

def test_invalid_disabled_checker_name(self):
"""Error out in case of an invalid disabled checker."""
out, _, errcode = self.__run_with_invalid_disabled_checker_name([])
out, _, errcode = \
self.__run_with_invalid_disabled_checker_name_check([])

match = self.missing_checker_regex.search(out)
match = self.err_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

Expand All @@ -908,15 +959,29 @@ def test_invalid_disabled_checker_name_warn(self):
Warn in case of an invalid disabled checker when using
--no-missing-checker-error.
"""
out, _, errcode = self.__run_with_invalid_disabled_checker_name(
['--no-missing-checker-error'])
out, _, errcode = \
self.__run_with_invalid_disabled_checker_name_analyze(
['--no-missing-checker-error'])

match = self.missing_checker_regex.search(out)
match = self.warn_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

self.assertEqual(errcode, 0)

out, _, errcode = self.__run_with_invalid_disabled_checker_name_check(
['--no-missing-checker-error'])

match = self.warn_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)

# FIXME: Interestingly, CodeChecker analyze doesn't find the bug in the
# code, but CodeChecker check does, so the return value is 2 here
# instead of 0. Lets just check that its not a CodeChecker error (which
# would be a return code of 1).
self.assertNotEqual(errcode, 1)

def test_disabling_clangsa_modeling_checkers(self):
"""Warn in case a modeling checker is disabled from clangsa"""
build_json = os.path.join(self.test_workspace, "build_success.json")
Expand Down Expand Up @@ -980,7 +1045,7 @@ def test_multiple_invalid_checker_names(self):
errors="ignore")
out, _ = process.communicate()

match = self.missing_checker_regex.search(out)
match = self.warn_missing_checker_regex.search(out)
self.assertIsNotNone(match)
self.assertTrue("non-existing-checker-name" in out)
self.assertTrue("non-existing-checker" in out)
Expand Down

0 comments on commit 2a8b6f8

Please sign in to comment.