66 lines
2.8 KiB
Python
66 lines
2.8 KiB
Python
r"""子程序 gcov 行号不得并入主程序 gcov 字典的回归测试。
|
||
|
||
Bug:`generate_coverage_report` 用 `gcov_data.update(sub_merged)` 把子程序
|
||
(SUB*.cbl) 的 gcov 行计数并入主程序行号字典。主程序与子程序的行号都是纯
|
||
整数,直接碰撞——SUB04CHK 的第 167 行(count=0)覆盖了 SHA02MNC 主程序
|
||
第 167 行(count=25,主循环 PERFORM 已进入),导致 #10 Enter 分支被误判为
|
||
未覆盖(SHA02MNC 覆盖率从应有的水平被拉低)。
|
||
|
||
修复:子程序 gcov 按子程序名独立保存(`_sub_gcov_data`),不并入主程序
|
||
`gcov_data`。`_merge_run_dirs_gcov` 对单个程序跨 run 目录合并。
|
||
"""
|
||
|
||
import sys, os
|
||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||
from pathlib import Path
|
||
from cobol_testgen.gcov import parse_cbl_gcov
|
||
from orchestrator_db import _merge_run_dirs_gcov
|
||
|
||
|
||
def _write_fake_gcov(dirpath: Path, name: str, counts: dict[int, int]):
|
||
lines = []
|
||
for ln in sorted(counts):
|
||
cnt = counts[ln]
|
||
marker = "#####" if cnt == 0 else f"{cnt}*"
|
||
lines.append(f"{marker}:{ln}: dummy source line\n")
|
||
(dirpath / f"{name}.cbl.gcov").write_text("".join(lines), encoding="utf-8")
|
||
|
||
|
||
def _fake_gcov_func(name: str, d: str):
|
||
return parse_cbl_gcov(os.path.join(d, f"{name}.cbl.gcov"))
|
||
|
||
|
||
def test_sub_gcov_line_collision_does_not_corrupt_main(tmp_path):
|
||
run_normal = tmp_path / "run_normal"; run_normal.mkdir()
|
||
run_fail = tmp_path / "run_fail"; run_fail.mkdir()
|
||
|
||
# 主程序:line 167 在 normal 场景执行 25 次(主循环进入)
|
||
_write_fake_gcov(run_normal, "MAIN", {167: 25, 265: 1})
|
||
_write_fake_gcov(run_fail, "MAIN", {167: 0, 265: 1})
|
||
# 子程序:line 167 从未执行(count=0)——与主程序行号碰撞
|
||
_write_fake_gcov(run_normal, "SUB", {167: 0, 10: 1})
|
||
_write_fake_gcov(run_fail, "SUB", {167: 0, 10: 1})
|
||
|
||
main = _merge_run_dirs_gcov(tmp_path, "MAIN", gcov_func=_fake_gcov_func)
|
||
sub = _merge_run_dirs_gcov(tmp_path, "SUB", gcov_func=_fake_gcov_func)
|
||
|
||
# 合并后主程序 167 必须保持 25
|
||
assert main[167] == 25, f"main line 167 corrupted: {main[167]}"
|
||
assert sub[167] == 0
|
||
|
||
# 旧 bug 行为演示:若把子程序并入主程序字典,167 会被覆盖为 0
|
||
buggy = dict(main)
|
||
buggy.update(sub)
|
||
assert buggy[167] == 0, "demonstrates the corruption the fix avoids"
|
||
# 修复不变量:子程序数据独立保存,主程序字典完好
|
||
assert main[167] == 25
|
||
|
||
|
||
def test_merge_run_dirs_takes_max_count(tmp_path):
|
||
r1 = tmp_path / "run_a"; r1.mkdir()
|
||
r2 = tmp_path / "run_b"; r2.mkdir()
|
||
_write_fake_gcov(r1, "MAIN", {167: 25})
|
||
_write_fake_gcov(r2, "MAIN", {167: 3})
|
||
merged = _merge_run_dirs_gcov(tmp_path, "MAIN", gcov_func=_fake_gcov_func)
|
||
assert merged[167] == 25
|