Sun, 20 Mar 2022 17:49:44 +0100
Third Party packages
- upgraded coverage to 6.3.2
8991
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
1 | # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
2 | # For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
3 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
4 | """LCOV reporting for coverage.py.""" |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
5 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
6 | import sys |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
7 | import base64 |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
8 | from hashlib import md5 |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
9 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
10 | from coverage.report import get_analysis_to_report |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
11 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
12 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
13 | class LcovReporter: |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
14 | """A reporter for writing LCOV coverage reports.""" |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
15 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
16 | report_type = "LCOV report" |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
17 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
18 | def __init__(self, coverage): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
19 | self.coverage = coverage |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
20 | self.config = self.coverage.config |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
21 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
22 | def report(self, morfs, outfile=None): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
23 | """Renders the full lcov report. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
24 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
25 | 'morfs' is a list of modules or filenames |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
26 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
27 | outfile is the file object to write the file into. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
28 | """ |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
29 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
30 | self.coverage.get_data() |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
31 | outfile = outfile or sys.stdout |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
32 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
33 | for fr, analysis in get_analysis_to_report(self.coverage, morfs): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
34 | self.get_lcov(fr, analysis, outfile) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
35 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
36 | def get_lcov(self, fr, analysis, outfile=None): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
37 | """Produces the lcov data for a single file. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
38 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
39 | This currently supports both line and branch coverage, |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
40 | however function coverage is not supported. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
41 | """ |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
42 | outfile.write("TN:\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
43 | outfile.write(f"SF:{fr.relative_filename()}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
44 | source_lines = fr.source().splitlines() |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
45 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
46 | for covered in sorted(analysis.executed): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
47 | # Note: Coverage.py currently only supports checking *if* a line |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
48 | # has been executed, not how many times, so we set this to 1 for |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
49 | # nice output even if it's technically incorrect. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
50 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
51 | # The lines below calculate a 64-bit encoded md5 hash of the line |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
52 | # corresponding to the DA lines in the lcov file, for either case |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
53 | # of the line being covered or missed in coverage.py. The final two |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
54 | # characters of the encoding ("==") are removed from the hash to |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
55 | # allow genhtml to run on the resulting lcov file. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
56 | if source_lines: |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
57 | line = source_lines[covered-1].encode("utf-8") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
58 | else: |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
59 | line = b"" |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
60 | hashed = base64.b64encode(md5(line).digest()).decode().rstrip("=") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
61 | outfile.write(f"DA:{covered},1,{hashed}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
62 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
63 | for missed in sorted(analysis.missing): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
64 | assert source_lines |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
65 | line = source_lines[missed-1].encode("utf-8") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
66 | hashed = base64.b64encode(md5(line).digest()).decode().rstrip("=") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
67 | outfile.write(f"DA:{missed},0,{hashed}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
68 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
69 | outfile.write(f"LF:{len(analysis.statements)}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
70 | outfile.write(f"LH:{len(analysis.executed)}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
71 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
72 | # More information dense branch coverage data. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
73 | missing_arcs = analysis.missing_branch_arcs() |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
74 | executed_arcs = analysis.executed_branch_arcs() |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
75 | for block_number, block_line_number in enumerate( |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
76 | sorted(analysis.branch_stats().keys()) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
77 | ): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
78 | for branch_number, line_number in enumerate( |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
79 | sorted(missing_arcs[block_line_number]) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
80 | ): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
81 | # The exit branches have a negative line number, |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
82 | # this will not produce valid lcov. Setting |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
83 | # the line number of the exit branch to 0 will allow |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
84 | # for valid lcov, while preserving the data. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
85 | line_number = max(line_number, 0) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
86 | outfile.write(f"BRDA:{line_number},{block_number},{branch_number},-\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
87 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
88 | # The start value below allows for the block number to be |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
89 | # preserved between these two for loops (stopping the loop from |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
90 | # resetting the value of the block number to 0). |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
91 | for branch_number, line_number in enumerate( |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
92 | sorted(executed_arcs[block_line_number]), |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
93 | start=len(missing_arcs[block_line_number]), |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
94 | ): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
95 | line_number = max(line_number, 0) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
96 | outfile.write(f"BRDA:{line_number},{block_number},{branch_number},1\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
97 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
98 | # Summary of the branch coverage. |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
99 | if analysis.has_arcs(): |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
100 | branch_stats = analysis.branch_stats() |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
101 | brf = sum(t for t, k in branch_stats.values()) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
102 | brh = brf - sum(t - k for t, k in branch_stats.values()) |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
103 | outfile.write(f"BRF:{brf}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
104 | outfile.write(f"BRH:{brh}\n") |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
105 | |
2fc945191992
Third Party packages
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
106 | outfile.write("end_of_record\n") |