-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmcdcReport.py
More file actions
169 lines (132 loc) · 5.55 KB
/
mcdcReport.py
File metadata and controls
169 lines (132 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import argparse
import pathlib
import sys
import os
from vector.apps.DataAPI.unit_test_api import UnitTestApi
from vector.apps.DataAPI.cover_api import CoverApi
from pythonUtilities import monkeypatch_custom_css, get_api_context
def parse_args():
"""
Simple argument parser
"""
# Create the argument parser
parser = argparse.ArgumentParser(
description="Process environment, unit, and line arguments."
)
# Add the arguments
parser.add_argument(
"-e", "--env", required=True, help="VectorCAST environment to process"
)
parser.add_argument("-u", "--unit", help="Unit name (no extension)")
parser.add_argument("-l", "--line", type=int, help="Line number")
parser.add_argument("-o", "--output", help="Output location")
# Parse the arguments
return parser.parse_args()
def get_mcdc_lines(env):
all_lines_with_data = {}
# Check if normal env or Cover --> Different API
ApiClass, entity_attr = get_api_context(env)
with ApiClass(env) as api:
sourceObjects = api.SourceFile.all()
for sourceObject in sourceObjects:
unit_file = sourceObject.cover_data.name
unit = os.path.splitext(unit_file)[0]
if sourceObject.is_instrumented:
for mcdc_dec in sourceObject.cover_data.mcdc_decisions:
if not mcdc_dec.num_conditions:
continue
if unit not in all_lines_with_data:
all_lines_with_data[unit] = []
if mcdc_dec.start_line not in all_lines_with_data[unit]:
all_lines_with_data[unit].append(mcdc_dec.start_line)
return all_lines_with_data
def generate_mcdc_report(env, unit_filter, line_filter, output):
"""
Generates the our custom report for all of the MCDC decisions on a given
line (in a given unit, in a given environment).
File gets written to output
"""
# Calculate the location of our custom folder
source_root = pathlib.Path(__file__).parent.resolve()
custom_dir = source_root / "custom"
# What's the path to our custom CSS?
custom_css = custom_dir / "vscode.css"
# Patch get_option to use our CSS without setting the CFG option
monkeypatch_custom_css(custom_css)
# We have to check whether env is the path to a "Normal" env or to a "Cover Project"
# and therefore use a different API
ApiClass, entity_attr = get_api_context(env)
with ApiClass(env) as api:
sourceObjects = api.SourceFile.all()
unit_found = False
for sourceObject in sourceObjects:
# Find and check for our unit
unit_file = sourceObject.cover_data.name
unit_name = os.path.splitext(unit_file)[0]
if unit_name != unit_filter:
continue
unit_found = True
# Spin through all MCDC decisions looking for the one on our line
line_found = False
for mcdc_dec in sourceObject.cover_data.mcdc_decisions:
# If it has no conditions, then it generates an empty report
#
# TODO: do we want to just generate an empty MCDC report?
if not mcdc_dec.num_conditions:
continue
# If the line is not the line we're looking for, continue
if mcdc_dec.start_line != line_filter:
continue
# Mark that we've found our line
line_found = True
# Record in the API instance the line number we're interested
# in
#
# NOTE: custom/sections/per_line_mcdc.py reads this attribute
# to know what to filter!
#
# If the decision lives in a different instrumented file
# (e.g. template instantiations across TUs), filter by
# line only so all instantiations are included.
if mcdc_dec.function.instrumented_file.name == unit_filter:
api.mcdc_filter = {"unit": unit_filter, "line": line_filter}
else:
api.mcdc_filter = {"line": line_filter}
# Generate our report
api.report(
report_type="per_line_mcdc_report",
formats=["HTML"],
output_file=output,
customization_dir=str(custom_dir),
)
break
if unit_found:
# If we don't find our line, report an error
if not line_found:
raise RuntimeError(f"Could not find line {line_filter} in unit {unit_filter}")
break
if not unit_found:
raise RuntimeError(
f"Could not find unit {unit_filter}"
)
def main():
"""
Entry point
"""
# Calculate the location of our custom folder
source_root = pathlib.Path(__file__).parent.resolve()
custom_dir = source_root / "custom"
# Parse the arguments
args = parse_args()
# If only env is defined --> We only want the MCDC lines for that env and not the report
if not args.unit and not args.line and not args.output:
mcdc_set = get_mcdc_lines(args.env)
print(mcdc_set)
else:
# Generate the report
generate_mcdc_report(args.env, args.unit, args.line, args.output)
# Error handling is via exceptions, so we're all good here
return 0
if __name__ == "__main__":
sys.exit(main())
# EOF