[scan-build-py] Add sarif-html support in scan-build-py

Update scan-build-py to be able to trigger sarif-html output format in clang static analyzer.

NOTE: testcase `test_sarif_and_html_creates_sarif_and_html_reports` will fail if the default clang does not have change https://reviews.llvm.org/D96389 . This can be remediated by pointing the default clang in arguments.py to a locally built clang. I was unable to figure out where these particular tests for scan-build-py are being invoked (aside from manually), so any help there would be greatly appreciated.

Reviewed By: aabbaabb, xazax.hun

Differential Revision: https://reviews.llvm.org/D96570
This commit is contained in:
Daniel Hwang 2021-02-23 14:36:49 -08:00 committed by Marco Vanotti
parent 4691405ba9
commit 97a304cc8f
4 changed files with 53 additions and 9 deletions

View File

@ -356,11 +356,14 @@ def report_directory(hint, keep, output_format):
yield name
finally:
if os.listdir(name):
if output_format != 'sarif':
if output_format not in ['sarif', 'sarif-html']: # FIXME:
# 'scan-view' currently does not support sarif format.
msg = "Run 'scan-view %s' to examine bug reports."
elif output_format == 'sarif-html':
msg = "Run 'scan-view %s' to examine bug reports or see " \
"merged sarif results at %s/results-merged.sarif."
else:
msg = "View result at %s/results-merged.sarif."
msg = "View merged sarif results at %s/results-merged.sarif."
keep = True
else:
if keep:
@ -438,7 +441,7 @@ def require(required):
'direct_args', # arguments from command line
'force_debug', # kill non debug macros
'output_dir', # where generated report files shall go
'output_format', # it's 'plist', 'html', 'plist-html', 'plist-multi-file', or 'sarif'
'output_format', # it's 'plist', 'html', 'plist-html', 'plist-multi-file', 'sarif', or 'sarif-html'
'output_failures', # generate crash reports or not
'ctu']) # ctu control options
def run(opts):
@ -542,7 +545,9 @@ def run_analyzer(opts, continuation=report_failure):
dir=opts['output_dir'])
os.close(handle)
return name
elif opts['output_format'] == 'sarif':
elif opts['output_format'] in {
'sarif',
'sarif-html'}:
(handle, name) = tempfile.mkstemp(prefix='result-',
suffix='.sarif',
dir=opts['output_dir'])

View File

@ -252,6 +252,14 @@ def create_analyze_parser(from_build_command):
default='html',
action='store_const',
help="""Cause the results as a result.sarif file.""")
format_group.add_argument(
'--sarif-html',
'-sarif-html',
dest='output_format',
const='sarif-html',
default='html',
action='store_const',
help="""Cause the results as a result.sarif file and .html files.""")
advanced = parser.add_argument_group('advanced options')
advanced.add_argument(

View File

@ -26,8 +26,8 @@ __all__ = ['document']
def document(args):
""" Generates cover report and returns the number of bugs/crashes. """
html_reports_available = args.output_format in {'html', 'plist-html'}
sarif_reports_available = args.output_format in {'sarif'}
html_reports_available = args.output_format in {'html', 'plist-html', 'sarif-html'}
sarif_reports_available = args.output_format in {'sarif', 'sarif-html'}
logging.debug('count crashes and bugs')
crash_count = sum(1 for _ in read_crashes(args.output))

View File

@ -102,7 +102,11 @@ class OutputFormatTest(unittest.TestCase):
def get_plist_count(directory):
return len(glob.glob(os.path.join(directory, 'report-*.plist')))
def test_default_creates_html_report(self):
@staticmethod
def get_sarif_count(directory):
return len(glob.glob(os.path.join(directory, 'result-*.sarif')))
def test_default_only_creates_html_report(self):
with libear.TemporaryDirectory() as tmpdir:
cdb = prepare_cdb('regular', tmpdir)
exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
@ -110,8 +114,9 @@ class OutputFormatTest(unittest.TestCase):
os.path.exists(os.path.join(reportdir, 'index.html')))
self.assertEqual(self.get_html_count(reportdir), 2)
self.assertEqual(self.get_plist_count(reportdir), 0)
self.assertEqual(self.get_sarif_count(reportdir), 0)
def test_plist_and_html_creates_html_report(self):
def test_plist_and_html_creates_html_and_plist_reports(self):
with libear.TemporaryDirectory() as tmpdir:
cdb = prepare_cdb('regular', tmpdir)
exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist-html'])
@ -119,8 +124,9 @@ class OutputFormatTest(unittest.TestCase):
os.path.exists(os.path.join(reportdir, 'index.html')))
self.assertEqual(self.get_html_count(reportdir), 2)
self.assertEqual(self.get_plist_count(reportdir), 5)
self.assertEqual(self.get_sarif_count(reportdir), 0)
def test_plist_does_not_creates_html_report(self):
def test_plist_only_creates_plist_report(self):
with libear.TemporaryDirectory() as tmpdir:
cdb = prepare_cdb('regular', tmpdir)
exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist'])
@ -128,6 +134,31 @@ class OutputFormatTest(unittest.TestCase):
os.path.exists(os.path.join(reportdir, 'index.html')))
self.assertEqual(self.get_html_count(reportdir), 0)
self.assertEqual(self.get_plist_count(reportdir), 5)
self.assertEqual(self.get_sarif_count(reportdir), 0)
def test_sarif_only_creates_sarif_result(self):
with libear.TemporaryDirectory() as tmpdir:
cdb = prepare_cdb('regular', tmpdir)
exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif'])
self.assertFalse(
os.path.exists(os.path.join(reportdir, 'index.html')))
self.assertTrue(
os.path.exists(os.path.join(reportdir, 'results-merged.sarif')))
self.assertEqual(self.get_html_count(reportdir), 0)
self.assertEqual(self.get_plist_count(reportdir), 0)
self.assertEqual(self.get_sarif_count(reportdir), 5)
def test_sarif_and_html_creates_sarif_and_html_reports(self):
with libear.TemporaryDirectory() as tmpdir:
cdb = prepare_cdb('regular', tmpdir)
exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif-html'])
self.assertTrue(
os.path.exists(os.path.join(reportdir, 'index.html')))
self.assertTrue(
os.path.exists(os.path.join(reportdir, 'results-merged.sarif')))
self.assertEqual(self.get_html_count(reportdir), 2)
self.assertEqual(self.get_plist_count(reportdir), 0)
self.assertEqual(self.get_sarif_count(reportdir), 5)
class FailureReportTest(unittest.TestCase):