]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/coverage/parse_gcov_output.py
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / coverage / parse_gcov_output.py
CommitLineData
f67539c2
TL
1#!/usr/bin/env python2
2# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
7c673cae
FG
3import re
4import sys
5
6from optparse import OptionParser
7
8# the gcov report follows certain pattern. Each file will have two lines
9# of report, from which we can extract the file name, total lines and coverage
10# percentage.
11def parse_gcov_report(gcov_input):
12 per_file_coverage = {}
13 total_coverage = None
14
15 for line in sys.stdin:
16 line = line.strip()
17
18 # --First line of the coverage report (with file name in it)?
19 match_obj = re.match("^File '(.*)'$", line)
20 if match_obj:
21 # fetch the file name from the first line of the report.
22 current_file = match_obj.group(1)
23 continue
24
25 # -- Second line of the file report (with coverage percentage)
26 match_obj = re.match("^Lines executed:(.*)% of (.*)", line)
27
28 if match_obj:
29 coverage = float(match_obj.group(1))
30 lines = int(match_obj.group(2))
31
32 if current_file is not None:
33 per_file_coverage[current_file] = (coverage, lines)
34 current_file = None
35 else:
36 # If current_file is not set, we reach the last line of report,
37 # which contains the summarized coverage percentage.
38 total_coverage = (coverage, lines)
39 continue
40
41 # If the line's pattern doesn't fall into the above categories. We
42 # can simply ignore them since they're either empty line or doesn't
43 # find executable lines of the given file.
44 current_file = None
45
46 return per_file_coverage, total_coverage
47
48def get_option_parser():
49 usage = "Parse the gcov output and generate more human-readable code " +\
50 "coverage report."
51 parser = OptionParser(usage)
52
53 parser.add_option(
54 "--interested-files", "-i",
55 dest="filenames",
56 help="Comma separated files names. if specified, we will display " +
57 "the coverage report only for interested source files. " +
58 "Otherwise we will display the coverage report for all " +
59 "source files."
60 )
61 return parser
62
63def display_file_coverage(per_file_coverage, total_coverage):
64 # To print out auto-adjustable column, we need to know the longest
65 # length of file names.
66 max_file_name_length = max(
67 len(fname) for fname in per_file_coverage.keys()
68 )
69
70 # -- Print header
71 # size of separator is determined by 3 column sizes:
72 # file name, coverage percentage and lines.
73 header_template = \
74 "%" + str(max_file_name_length) + "s\t%s\t%s"
75 separator = "-" * (max_file_name_length + 10 + 20)
11fdf7f2 76 print header_template % ("Filename", "Coverage", "Lines") # noqa: E999 T25377293 Grandfathered in
7c673cae
FG
77 print separator
78
79 # -- Print body
80 # template for printing coverage report for each file.
81 record_template = "%" + str(max_file_name_length) + "s\t%5.2f%%\t%10d"
82
83 for fname, coverage_info in per_file_coverage.items():
84 coverage, lines = coverage_info
85 print record_template % (fname, coverage, lines)
86
87 # -- Print footer
88 if total_coverage:
89 print separator
90 print record_template % ("Total", total_coverage[0], total_coverage[1])
91
92def report_coverage():
93 parser = get_option_parser()
94 (options, args) = parser.parse_args()
95
96 interested_files = set()
97 if options.filenames is not None:
98 interested_files = set(f.strip() for f in options.filenames.split(','))
99
100 # To make things simple, right now we only read gcov report from the input
101 per_file_coverage, total_coverage = parse_gcov_report(sys.stdin)
102
103 # Check if we need to display coverage info for interested files.
104 if len(interested_files):
105 per_file_coverage = dict(
106 (fname, per_file_coverage[fname]) for fname in interested_files
107 if fname in per_file_coverage
108 )
109 # If we only interested in several files, it makes no sense to report
110 # the total_coverage
111 total_coverage = None
112
113 if not len(per_file_coverage):
114 print >> sys.stderr, "Cannot find coverage info for the given files."
115 return
116 display_file_coverage(per_file_coverage, total_coverage)
117
118if __name__ == "__main__":
119 report_coverage()