Skip to content

Commit 9f970d3

Browse files
committed
fix(coverage): exclude failed/partial-coverage tests from coverage map
Fix 1: in build_coverage_map Phase 2, a test with non-empty failures produced only partial .gcda files (crash mid-pipeline). Previously those tests were still added to test_results, and their truncated coverage was cached. A later .fpp change that ran only in the missing stage would be silently skipped. Fix: when failures is non-empty, record in all_failures and continue without adding to test_results — absent entries are conservatively included by select_tests (rung 5). Fix 2: in _parse_gcov_json_output, a mid-stream json.JSONDecodeError returned the partial result set, which is untrustworthy (the truncated JSON stream may be missing coverage for .fpp files that were not yet serialised). Fix: return None on that error path so the caller omits the test from the map entirely. Fix 6 (comment): correct the post_process comment (~line 347) — the regular suite runs post_process only under --test-all (which CI sets), not never.
1 parent 9811cfc commit 9f970d3

1 file changed

Lines changed: 21 additions & 7 deletions

File tree

toolchain/mfc/test/coverage_build.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,13 @@ def _parse_gcov_json_output(raw_bytes: bytes, root_dir: str) -> Optional[set]:
133133
except json.JSONDecodeError:
134134
remaining = len(text) - pos
135135
if remaining > 0:
136-
cons.print(f"[yellow]Warning: gcov JSON parse error at offset {pos} ({remaining} bytes remaining) — partial coverage recorded for this test.[/yellow]")
137-
break
136+
cons.print(f"[yellow]Warning: gcov JSON parse error at offset {pos} ({remaining} bytes remaining) — coverage for this test is untrustworthy, omitting from map.[/yellow]")
137+
# A mid-stream parse error means the JSON stream was truncated or
138+
# corrupted. A partial coverage set is untrustworthy: a .fpp that
139+
# would have been recorded in the missing portion would be silently
140+
# skipped by select_tests on future runs. Return None so the caller
141+
# omits this test from the map entirely (conservatively included).
142+
return None
138143

139144
for file_entry in data.get("files", []):
140145
file_path = file_entry.get("file", "")
@@ -367,10 +372,11 @@ def _prepare_test(case) -> dict:
367372
params["t_stop"] = t_save # n_save = 2: indices 0 and 1
368373

369374
# Heavy 3D tests: remove vorticity output (omega_wrt + fd_order) for
370-
# 3D QBMM tests. Normal test execution never runs post_process (only
371-
# PRE_PROCESS + SIMULATION, never POST_PROCESS), so post_process on
372-
# heavy 3D configs is untested. Vorticity FD computation on large grids
373-
# with many QBMM variables causes post_process to crash (exit code 2).
375+
# 3D QBMM tests. The regular test suite runs post_process only under
376+
# --test-all (which CI sets); heavy 3D QBMM configs are known to crash
377+
# post_process (exit code 2) when vorticity FD is enabled on large grids
378+
# with many QBMM variables. Strip those params here so the coverage
379+
# build does not fail on those tests.
374380
if int(params.get("p", 0)) > 0 and params.get("qbmm", "F") == "T":
375381
for key in POST_PROCESS_3D_PARAMS:
376382
params.pop(key, None)
@@ -478,9 +484,17 @@ def build_coverage_map(
478484
info = futures[future]
479485
cons.print(f" [yellow]Warning: {info['uuid']} failed to run: {exc}[/yellow]")
480486
continue
481-
test_results[uuid] = test_gcda
482487
if failures:
488+
# A test that crashed mid-pipeline produced only partial .gcda
489+
# files (e.g. simulation failed after pre_process ran). That
490+
# truncated coverage is untrustworthy: a later .fpp change that
491+
# ran only in the missing stage would be incorrectly skipped.
492+
# Record the failure for the warning summary but do NOT add this
493+
# test to test_results — absent entries are conservatively
494+
# included by select_tests (rung 5), never skipped.
483495
all_failures[uuid] = failures
496+
continue
497+
test_results[uuid] = test_gcda
484498
if (i + 1) % 50 == 0 or (i + 1) == len(test_infos):
485499
cons.print(f" [{i + 1:3d}/{len(test_infos):3d}] tests completed")
486500

0 commit comments

Comments
 (0)