Skip to content

Commit 9b0ddb8

Browse files
zbelinskbryanb-h2
andauthored
html report functionality extend (#67)
* html report: add packet summary to sidebar header and per-file omit button in Files view Signed-off-by: Zeev Belinsky <zbelinsk@qti.qualcomm.com> * html report: add --min-packets flag to filter trivial functions by packet count Signed-off-by: Zeev Belinsky <zbelinsk@qti.qualcomm.com> --------- Signed-off-by: Zeev Belinsky <zbelinsk@qti.qualcomm.com> Co-authored-by: Bryan Bayerdorffer <bryanb@qti.qualcomm.com>
1 parent 1773088 commit 9b0ddb8

2 files changed

Lines changed: 46 additions & 6 deletions

File tree

scripts/Makefile.coverage

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ COV_FILES = $(patsubst %, $(TEST_BUILD_ROOT)/%/cov.txt, $(SUBDIRS))
2323
# drops these; the cov.html "Omit" button produces an updated copy to commit.
2424
COV_OMIT = $(H2DIR)/scripts/cov_omit_functions
2525

26+
# Minimum packet count threshold: functions with <= N packets are excluded from
27+
# the HTML report (they are too small to produce meaningful coverage signal).
28+
# Override on the command line: make cov TARGET=ref_cov COV_MIN_PACKETS=3
29+
# Default is 1 (only single-packet stubs are filtered).
30+
2631
all:
2732
$(MAKE) -f scripts/Makefile.coverage $(SUBDIRS) TARG=all
2833

@@ -120,7 +125,8 @@ $(INSTALLPATH)/cov.html: $(INSTALLPATH)/cov/cov.rpt $(INSTALLPATH)/cov/cov_files
120125
$(PYTHON) ${H2DIR}/scripts/cov_html_report.py \
121126
--rpt $< --cov $(INSTALLPATH)/cov/cov.txt \
122127
--fn-files $(INSTALLPATH)/cov/cov_files --omit-file $(COV_OMIT) --output $@ \
123-
$(patsubst %,--test-cov %,$(COV_FILES))
128+
$(patsubst %,--test-cov %,$(COV_FILES)) \
129+
$(if $(COV_MIN_PACKETS),--min-packets $(COV_MIN_PACKETS))
124130

125131
# Collect per-test results.txt into a clean PASS/FAIL summary and append to TESTOUT.
126132
# Called after tst completes; each test's full output is in <test-dir>/make.log.

scripts/cov_html_report.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@
137137
.tree-fn.active .tree-label { color: #fff; }
138138
.tree-root { background: #252526; font-weight: bold; border-bottom: 1px solid #444; }
139139
.tree-root .tree-label { color: #ccc; }
140+
.tree-omit-btn {
141+
margin-left: auto; background: transparent; border: none;
142+
color: #a44; font-size: 0.85em; cursor: pointer; padding: 0 4px;
143+
border-radius: 3px; line-height: 1; flex-shrink: 0;
144+
}
145+
.tree-omit-btn:hover { color: #f99; background: #3c2222; }
140146
141147
#detail { flex: 1; overflow: hidden; display: flex; flex-direction: column; padding: 16px 20px; background: #1e1e1e; color: #ccc; }
142148
#detail h2 { font-size: 1em; margin-bottom: 10px; color: #9cdcfe; border-bottom: 1px solid #333; padding-bottom: 6px; flex-shrink: 0; }
@@ -618,14 +624,15 @@
618624
}
619625
620626
// Collapse single-child directory chains (a/b/c → a/b/c) for compactness.
621-
function treeRowHtml(label, pct, depth, kind, key, isOpen, dataAttr) {
627+
function treeRowHtml(label, pct, depth, kind, key, isOpen, dataAttr, extra) {
622628
var pad = 10 + depth * 14;
623629
var arrow = kind === 'leaf' ? '' :
624630
'<span class="tree-arrow">' + (isOpen ? '▾' : '▸') + '</span>';
625631
var badge = '<span class="pct ' + pctClass(pct) + '">' + pct + '%</span>';
626632
return '<div class="tree-row tree-' + kind + '" style="padding-left:' + pad + 'px;" '
627633
+ dataAttr + '>' + arrow + badge
628-
+ '<span class="tree-label">' + escSvg(label) + '</span></div>';
634+
+ '<span class="tree-label">' + escSvg(label) + '</span>'
635+
+ (extra || '') + '</div>';
629636
}
630637
631638
function renderTreeNode(node, depth, out) {
@@ -649,8 +656,11 @@
649656
fileKeys.forEach(function(k) {
650657
var f = node.files[k];
651658
var isOpen = !treeCollapsed[f.path];
659+
var safePath = f.path.replace(/'/g, "\\'");
660+
var omitBtn = '<button class="tree-omit-btn" title="Omit all functions in this file" '
661+
+ 'onclick="event.stopPropagation();omitFile(\'' + safePath + '\')">⊘</button>';
652662
out.push(treeRowHtml(f.name, nodePct(f), depth, 'file', f.path, isOpen,
653-
'onclick="toggleTreeNode(\'' + f.path.replace(/'/g, "\\'") + '\')"'));
663+
'onclick="toggleTreeNode(\'' + safePath + '\')"', omitBtn));
654664
if (isOpen) {
655665
// functions in this file, sorted by pct asc
656666
f.fns.slice().sort(function(a, b) {
@@ -753,6 +763,23 @@
753763
if (nextFn) show(nextFn);
754764
}
755765
766+
// Omit all functions belonging to a given source file path.
767+
function omitFile(filePath) {
768+
var fns = Object.keys(fnSrc).filter(function(fn) { return fnSrc[fn] === filePath; });
769+
var visible = fns.filter(function(fn) { return !isOmitted(fn); });
770+
if (!visible.length) return;
771+
if (!confirm('Omit all ' + visible.length + ' function(s) in ' + filePath + '?')) return;
772+
visible.forEach(function(fn) { localOmit[fn] = 1; });
773+
saveLocalOmit();
774+
refreshOmitUi();
775+
onTestChange();
776+
refreshDetail();
777+
if (currentFunc && isOmitted(currentFunc)) {
778+
var first = document.querySelector('.fn-entry:not([style*="display: none"]):not([style*="display:none"])');
779+
if (first) show(first.dataset.fn);
780+
}
781+
}
782+
756783
// Restore a single session-omitted function (live — no reload needed).
757784
function restoreOmit(fn) {
758785
delete localOmit[fn];
@@ -1027,6 +1054,10 @@ def build_html(funcs, cov_data, test_covs, fn_src, omit_names=None, omit_header=
10271054
execd, total = packet_counts(lines)
10281055
fn_packets[name] = [execd, total]
10291056

1057+
total_exec_pkts = sum(v[0] for v in fn_packets.values())
1058+
total_pkts = sum(v[1] for v in fn_packets.values())
1059+
pkt_pct = round(100 * total_exec_pkts / total_pkts) if total_pkts else 0
1060+
10301061
callees, callers = build_call_graphs(cov_data, tracked_fns)
10311062

10321063
fn_data_js = 'var fnData = {\n' + ',\n'.join(fn_data_entries) + '\n};'
@@ -1149,7 +1180,8 @@ def build_html(funcs, cov_data, test_covs, fn_src, omit_names=None, omit_header=
11491180
'<div id="sidebar">',
11501181
'<div id="sidebar-header">',
11511182
' <strong>Coverage Report</strong><br>',
1152-
f' {total} functions &nbsp;·&nbsp; {covered_any} hit &nbsp;·&nbsp; {covered_100} at 100%',
1183+
f' {total} functions &nbsp;·&nbsp; {covered_any} hit &nbsp;·&nbsp; {covered_100} at 100%<br>',
1184+
f' {total_exec_pkts} / {total_pkts} packets &nbsp;·&nbsp; {pkt_pct}% coverage',
11531185
'</div>',
11541186
test_selector,
11551187
threshold,
@@ -1224,6 +1256,8 @@ def main():
12241256
ap.add_argument('--test-cov', action='append', metavar='FILE', default=[],
12251257
dest='test_covs',
12261258
help='Per-test cov.txt path; may be repeated. Test name derived from path.')
1259+
ap.add_argument('--min-packets', type=int, default=1, metavar='N', dest='min_packets',
1260+
help='Filter functions with <= N packets (default 1).')
12271261
args = ap.parse_args()
12281262

12291263
funcs = parse_rpt(args.rpt)
@@ -1248,7 +1282,7 @@ def main():
12481282
print(f'[cov_html_report] dropped {len(present)} committed-omit functions',
12491283
file=sys.stderr)
12501284

1251-
func_minimal_packet_length = 1
1285+
func_minimal_packet_length = args.min_packets
12521286
trivial = {name for _, name in funcs
12531287
if packet_counts(cov_data.get(name, []))[1] <= func_minimal_packet_length}
12541288
if trivial:

0 commit comments

Comments
 (0)