diff --git a/analyzer/codechecker_analyzer/makefile.py b/analyzer/codechecker_analyzer/makefile.py index 4ca812e8d6..133f6cd36f 100644 --- a/analyzer/codechecker_analyzer/makefile.py +++ b/analyzer/codechecker_analyzer/makefile.py @@ -40,6 +40,7 @@ def __init__(self, analyzers, output_path, config_map, context, self.__context = context self.__skip_handler = skip_handler self.__pre_analysis = pre_analysis + self.__log_info = "[`date +'%Y-%m-%d %H:%M:%S'`] -" self.__ctu_data = ctu_data self.__ctu_dir = None @@ -195,12 +196,13 @@ def __write_pre_analysis_targets(self, mfile, action, pre_all_target): target = self.__get_target_name(action) mfile.write('{0}:\n' - '\t@echo "Pre-analysis of {3}."\n' + '\t@echo "{4} Pre-analysis of {3}."\n' '{1}\n' '{2}: {0}\n\n'.format('pre_' + target, commands, pre_all_target, - action.source)) + action.source, + self.__log_info)) def __write_post_pre_analysis_targets(self, mfile, pre_all_target): """ Creates targets to post-process pre-analysis results. """ @@ -267,14 +269,15 @@ def __write_analysis_targets(self, mfile, action, post_pre_all_target): command = "@{0} 1>/dev/null".format(' '.join(analyzer_cmd)) mfile.write('{0}: {1}\n' - '\t@echo "{4} analyze {5}."\n' + '\t@echo "{6} {4} analyze {5}."\n' '\t{2}\n' 'all_{3}: {0}\n\n'.format(target, post_pre_all_target, command, analyzer_name, action.analyzer_type, - action.source)) + action.source, + self.__log_info)) def create(self, actions): """ Creates a Makefile from the given actions. """ diff --git a/analyzer/tests/functional/analyze/test_analyze.py b/analyzer/tests/functional/analyze/test_analyze.py index e74898b554..337e8441a1 100644 --- a/analyzer/tests/functional/analyze/test_analyze.py +++ b/analyzer/tests/functional/analyze/test_analyze.py @@ -11,7 +11,7 @@ Test case for the CodeChecker analyze command's direct functionality. """ - +import glob import json import os import re @@ -777,8 +777,60 @@ def test_multiple_invalid_checker_names(self): self.assertTrue("other.missing.checker" in out) errcode = process.returncode + self.assertEqual(errcode, 0) + def test_makefile_generation(self): + """ Test makefile generation. """ + build_json = os.path.join(self.test_workspace, "build_extra_args.json") + analyze_cmd = [self._codechecker_cmd, "analyze", build_json, + "-o", self.report_dir, '--makefile'] + + source_file = os.path.join(self.test_dir, "extra_args.c") + build_log = [{"directory": self.test_workspace, + "command": "gcc -DTIDYARGS -c " + source_file, + "file": source_file + }, + {"directory": self.test_workspace, + "command": "gcc -DSAARGS -DTIDYARGS -c " + source_file, + "file": source_file + }] + + with open(build_json, 'w', + encoding="utf-8", errors="ignore") as outfile: + json.dump(build_log, outfile) + + process = subprocess.Popen( + analyze_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=self.test_dir, + encoding="utf-8", + errors="ignore") + process.communicate() + + errcode = process.returncode + self.assertEqual(errcode, 0) + + # Check the existence of the Makefile. + makefile = os.path.join(self.report_dir, 'Makefile') + self.assertTrue(os.path.exists(makefile)) + + # Run the generated Makefile and check the return code of it. + process = subprocess.Popen(["make"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=self.report_dir, + encoding="utf-8", + errors="ignore") + process.communicate() + + errcode = process.returncode + self.assertEqual(errcode, 0) + + plist_files = glob.glob(os.path.join(self.report_dir, '*.plist')) + self.assertEqual(len(plist_files), 4) + def test_analyzer_and_checker_config(self): """Test analyzer configuration through command line flags.""" build_json = os.path.join(self.test_workspace, "build_success.json") diff --git a/analyzer/tests/functional/ctu/test_ctu.py b/analyzer/tests/functional/ctu/test_ctu.py index fc4a12a0a2..ac9d02abf7 100644 --- a/analyzer/tests/functional/ctu/test_ctu.py +++ b/analyzer/tests/functional/ctu/test_ctu.py @@ -158,3 +158,22 @@ def __check_ctu_analyze(self, output): self.assertIn("no defects in main.c", output) self.assertIn("lib.c:3:", output) self.assertIn("[core.NullDereference]", output) + + def test_ctu_makefile_generation(self): + """ Test makefile generation in CTU mode. """ + if not self.ctu_capable: + self.skipTest(NO_CTU_MESSAGE) + + cmd = [self._codechecker_cmd, 'analyze', '-o', self.report_dir, + '--analyzers', 'clangsa', '--ctu', '--makefile'] + cmd.append(self.buildlog) + call_command(cmd, cwd=self.test_dir, env=self.env) + + call_command(["make"], cwd=self.report_dir, env=self.env) + + # Check the output. + cmd = [self._codechecker_cmd, 'parse', self.report_dir] + output, _ = call_command(cmd, cwd=self.test_dir, env=self.env) + self.assertIn("defect(s) in lib.c", output) + self.assertIn("lib.c:3:", output) + self.assertIn("[core.NullDereference]", output) diff --git a/analyzer/tests/unit/__init__.py b/analyzer/tests/unit/__init__.py index 50969a75db..5e173885e2 100644 --- a/analyzer/tests/unit/__init__.py +++ b/analyzer/tests/unit/__init__.py @@ -18,3 +18,5 @@ sys.path.append(REPO_ROOT) sys.path.append(os.path.join(REPO_ROOT, 'tools', 'codechecker_report_hash')) +sys.path.append(os.path.join(REPO_ROOT, 'analyzer', 'tools', + 'statistics_collector'))