diff options
Diffstat (limited to 'mesonbuild/scripts/coverage.py')
-rw-r--r-- | mesonbuild/scripts/coverage.py | 182 |
1 files changed, 109 insertions, 73 deletions
diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 2d1f8c3..dcc9465 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -14,87 +14,123 @@ from mesonbuild import environment -import sys, os, subprocess, pathlib +import argparse, sys, os, subprocess, pathlib + +def coverage(outputs, source_root, build_root, log_dir): + outfiles = [] + exitcode = 0 -def coverage(source_root, build_root, log_dir): (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe) = environment.find_coverage_tools() - if gcovr_exe: - # gcovr >= 3.1 interprets rootdir differently - if gcovr_new_rootdir: - rootdir = build_root - else: - rootdir = source_root - subprocess.check_call([gcovr_exe, - '-x', - '-r', rootdir, - '-o', os.path.join(log_dir, 'coverage.xml'), - ]) - subprocess.check_call([gcovr_exe, - '-r', rootdir, - '-o', os.path.join(log_dir, 'coverage.txt'), - ]) - if lcov_exe and genhtml_exe: - htmloutdir = os.path.join(log_dir, 'coveragereport') - covinfo = os.path.join(log_dir, 'coverage.info') - initial_tracefile = covinfo + '.initial' - run_tracefile = covinfo + '.run' - raw_tracefile = covinfo + '.raw' - subprocess.check_call([lcov_exe, - '--directory', build_root, - '--capture', - '--initial', - '--output-file', - initial_tracefile]) - subprocess.check_call([lcov_exe, - '--directory', build_root, - '--capture', - '--output-file', run_tracefile, - '--no-checksum', - '--rc', 'lcov_branch_coverage=1', - ]) - # Join initial and test results. - subprocess.check_call([lcov_exe, - '-a', initial_tracefile, - '-a', run_tracefile, - '-o', raw_tracefile]) - # Remove all directories outside the source_root from the covinfo - subprocess.check_call([lcov_exe, - '--extract', raw_tracefile, - os.path.join(source_root, '*'), - '--output-file', covinfo]) - subprocess.check_call([genhtml_exe, - '--prefix', build_root, - '--output-directory', htmloutdir, - '--title', 'Code coverage', - '--legend', - '--show-details', - '--branch-coverage', - covinfo]) - elif gcovr_exe and gcovr_new_rootdir: - htmloutdir = os.path.join(log_dir, 'coveragereport') - subprocess.check_call([gcovr_exe, - '--html', - '--html-details', - '-r', build_root, - '-o', os.path.join(htmloutdir, 'index.html'), - ]) - if gcovr_exe: + + # gcovr >= 3.1 interprets rootdir differently + if gcovr_new_rootdir: + gcovr_rootdir = build_root + else: + gcovr_rootdir = source_root + + if not outputs or 'xml' in outputs: + if gcovr_exe: + subprocess.check_call([gcovr_exe, + '-x', + '-r', gcovr_rootdir, + '-o', os.path.join(log_dir, 'coverage.xml'), + ]) + outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml'))) + elif outputs: + print('gcovr needed to generate Xml coverage report') + exitcode = 1 + + if not outputs or 'text' in outputs: + if gcovr_exe: + subprocess.check_call([gcovr_exe, + '-r', gcovr_rootdir, + '-o', os.path.join(log_dir, 'coverage.txt'), + ]) + outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt'))) + elif outputs: + print('gcovr needed to generate text coverage report') + exitcode = 1 + + if not outputs or 'html' in outputs: + if lcov_exe and genhtml_exe: + htmloutdir = os.path.join(log_dir, 'coveragereport') + covinfo = os.path.join(log_dir, 'coverage.info') + initial_tracefile = covinfo + '.initial' + run_tracefile = covinfo + '.run' + raw_tracefile = covinfo + '.raw' + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--initial', + '--output-file', + initial_tracefile]) + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--output-file', run_tracefile, + '--no-checksum', + '--rc', 'lcov_branch_coverage=1', + ]) + # Join initial and test results. + subprocess.check_call([lcov_exe, + '-a', initial_tracefile, + '-a', run_tracefile, + '-o', raw_tracefile]) + # Remove all directories outside the source_root from the covinfo + subprocess.check_call([lcov_exe, + '--extract', raw_tracefile, + os.path.join(source_root, '*'), + '--output-file', covinfo]) + subprocess.check_call([genhtml_exe, + '--prefix', build_root, + '--output-directory', htmloutdir, + '--title', 'Code coverage', + '--legend', + '--show-details', + '--branch-coverage', + covinfo]) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif gcovr_exe and gcovr_new_rootdir: + htmloutdir = os.path.join(log_dir, 'coveragereport') + subprocess.check_call([gcovr_exe, + '--html', + '--html-details', + '-r', build_root, + '-o', os.path.join(htmloutdir, 'index.html'), + ]) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif outputs: + print('lcov/genhtml or gcovr >= 3.1 needed to generate Html coverage report') + exitcode = 1 + + if not outputs and not outfiles: + print('Need gcovr or lcov/genhtml to generate any coverage reports') + exitcode = 1 + + if outfiles: print('') - print('XML coverage report can be found at', - pathlib.Path(log_dir, 'coverage.xml').as_uri()) - print('Text coverage report can be found at', - pathlib.Path(log_dir, 'coverage.txt').as_uri()) - if (lcov_exe and genhtml_exe) or (gcovr_exe and gcovr_new_rootdir): - print('Html coverage report can be found at', - pathlib.Path(htmloutdir, 'index.html').as_uri()) - return 0 + for (filetype, path) in outfiles: + print(filetype + ' coverage report can be found at', path.as_uri()) + + return exitcode def run(args): if not os.path.isfile('build.ninja'): print('Coverage currently only works with the Ninja backend.') return 1 - source_root, build_root, log_dir = args[:] - return coverage(source_root, build_root, log_dir) + parser = argparse.ArgumentParser(description='Generate coverage reports') + parser.add_argument('--text', dest='outputs', action='append_const', + const='text', help='generate Text report') + parser.add_argument('--xml', dest='outputs', action='append_const', + const='xml', help='generate Xml report') + parser.add_argument('--html', dest='outputs', action='append_const', + const='html', help='generate Html report') + parser.add_argument('source_root') + parser.add_argument('build_root') + parser.add_argument('log_dir') + options = parser.parse_args(args) + return coverage(options.outputs, options.source_root, + options.build_root, options.log_dir) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) |