diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2023-04-04 17:02:01 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2023-04-04 17:02:01 +0100 |
| commit | 8a712df4d4d736b7fe6441626677bfd271d95b15 (patch) | |
| tree | cfffe53ccb3c6a5365f32d23abae8c3fc26b3587 /scripts/coverage | |
| parent | 992473749f7cf127e71bb8263c02577cca303055 (diff) | |
| parent | c8cb603293fd329f2a62ade76ec9de3f462fc5c3 (diff) | |
| download | focaccia-qemu-8a712df4d4d736b7fe6441626677bfd271d95b15.tar.gz focaccia-qemu-8a712df4d4d736b7fe6441626677bfd271d95b15.zip | |
Merge tag 'pull-for-8.0-040423-2' of https://gitlab.com/stsquad/qemu into staging
Final test and misc fixes: - add basic coverage analysis script - gdbstub only build one of libgdb_user/softmmu - don't break BSD gdb by advertising AUXV feature - add MAINTAINERS section for policy docs - update hexagon toolchain - explicitly invoke iotests with python for BSDs benefit - use system python on NetBSD - add some tests for the new KVM Xen guest support # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmQsOscACgkQ+9DbCVqe # KkSm6Af/X+vvzdlmXgGt3uw2odqV6KMfXEkds5lHZIIqQhsLvV0mrkTcIKTswWhL # JRC7jiPmn5hfwvgDy5WfcczGzELSqfBgqHsm9zqVcboTGgJfr2eMtoUlMCQi6lFR # InomhTb+VzPxuUx82oryufm7bsopG8C+HVr3ZtHNFI3usIrLlscZstkiYMueGUCb # PJ60mykfd7hegaTgwKNbUXqZ+Oy/u4W7UPWBkrR7xJzW623t7S5EWV2ZNbdJgKO6 # utY3VGikir/OcnNKy7NuXp2t3K+5KALFZW3Jbav8hVLy5biMGYUF8886B0FL2m+n # E44J67crEYNJMamtzYJ+FdkGEMrS5Q== # =yCka # -----END PGP SIGNATURE----- # gpg: Signature made Tue 04 Apr 2023 15:57:11 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * tag 'pull-for-8.0-040423-2' of https://gitlab.com/stsquad/qemu: tests/avocado: Test Xen guest support under KVM gitlab: fix typo tests/vm: use the default system python for NetBSD tests/qemu-iotests: explicitly invoke 'check' via 'python' Use hexagon toolchain version 16.0.0 metadata: add .git-blame-ignore-revs MAINTAINERS: add a section for policy documents gdbstub: don't report auxv feature unless on Linux gdbstub: Only build libgdb_user.fa / libgdb_softmmu.fa if necessary scripts/coverage: initial coverage comparison script Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'scripts/coverage')
| -rwxr-xr-x | scripts/coverage/compare_gcov_json.py | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/scripts/coverage/compare_gcov_json.py b/scripts/coverage/compare_gcov_json.py new file mode 100755 index 0000000000..1b92dc2c8c --- /dev/null +++ b/scripts/coverage/compare_gcov_json.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# Compare output of two gcovr JSON reports and report differences. To +# generate the required output first: +# - create two build dirs with --enable-gcov +# - run set of tests in each +# - run make coverage-html in each +# - run gcovr --json --exclude-unreachable-branches \ +# --print-summary -o coverage.json --root ../../ . *.p +# +# Author: Alex Bennée <alex.bennee@linaro.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +import argparse +import json +import sys +from pathlib import Path + +def create_parser(): + parser = argparse.ArgumentParser( + prog='compare_gcov_json', + description='analyse the differences in coverage between two runs') + + parser.add_argument('-a', type=Path, default=None, + help=('First file to check')) + + parser.add_argument('-b', type=Path, default=None, + help=('Second file to check')) + + parser.add_argument('--verbose', action='store_true', default=False, + help=('A minimal verbosity level that prints the ' + 'overall result of the check/wait')) + return parser + + +# See https://gcovr.com/en/stable/output/json.html#json-format-reference +def load_json(json_file_path: Path, verbose = False) -> dict[str, set[int]]: + + with open(json_file_path) as f: + data = json.load(f) + + root_dir = json_file_path.absolute().parent + covered_lines = dict() + + for filecov in data["files"]: + file_path = Path(filecov["file"]) + + # account for generated files - map into src tree + resolved_path = Path(file_path).absolute() + if resolved_path.is_relative_to(root_dir): + file_path = resolved_path.relative_to(root_dir) + # print(f"remapped {resolved_path} to {file_path}") + + lines = filecov["lines"] + + executed_lines = set( + linecov["line_number"] + for linecov in filecov["lines"] + if linecov["count"] != 0 and not linecov["gcovr/noncode"] + ) + + # if this file has any coverage add it to the system + if len(executed_lines) > 0: + if verbose: + print(f"file {file_path} {len(executed_lines)}/{len(lines)}") + covered_lines[str(file_path)] = executed_lines + + return covered_lines + +def find_missing_files(first, second): + """ + Return a list of files not covered in the second set + """ + missing_files = [] + for f in sorted(first): + file_a = first[f] + try: + file_b = second[f] + except KeyError: + missing_files.append(f) + + return missing_files + +def main(): + """ + Script entry point + """ + parser = create_parser() + args = parser.parse_args() + + if not args.a or not args.b: + print("We need two files to compare") + sys.exit(1) + + first_coverage = load_json(args.a, args.verbose) + second_coverage = load_json(args.b, args.verbose) + + first_missing = find_missing_files(first_coverage, + second_coverage) + + second_missing = find_missing_files(second_coverage, + first_coverage) + + a_name = args.a.parent.name + b_name = args.b.parent.name + + print(f"{b_name} missing coverage in {len(first_missing)} files") + for f in first_missing: + print(f" {f}") + + print(f"{a_name} missing coverage in {len(second_missing)} files") + for f in second_missing: + print(f" {f}") + + +if __name__ == '__main__': + main() |