feat: Phase 3+4 - gcov support + enhanced report
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import subprocess
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def collect_gcov(cobol_src: Path, work_dir: Path) -> dict:
|
||||
try:
|
||||
gcda_files = list(work_dir.glob("*.gcda"))
|
||||
if not gcda_files:
|
||||
logger.warning("[gcov] 未找到 .gcda 文件,可能未启用插桩编译")
|
||||
return {"available": False, "reason": "no_gcda_files"}
|
||||
|
||||
result = subprocess.run(
|
||||
["gcov", cobol_src.name],
|
||||
capture_output=True, text=True, timeout=30,
|
||||
cwd=work_dir,
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.warning(f"[gcov] gcov 执行失败: {result.stderr[:200]}")
|
||||
return {"available": False, "reason": "gcov_failed"}
|
||||
|
||||
gcov_file = work_dir / f"{cobol_src.stem}.cbl.gcov"
|
||||
if not gcov_file.exists():
|
||||
gcov_file = work_dir / f"{cobol_src.stem}.gcov"
|
||||
|
||||
if not gcov_file.exists():
|
||||
logger.warning("[gcov] .gcov 文件未生成")
|
||||
return {"available": False, "reason": "no_gcov_output"}
|
||||
|
||||
total_lines = 0
|
||||
executed_lines = 0
|
||||
with open(gcov_file) as f:
|
||||
for line in f:
|
||||
stripped = line.strip()
|
||||
if stripped and not stripped.startswith("-"):
|
||||
total_lines += 1
|
||||
if not stripped.startswith("#"):
|
||||
executed_lines += 1
|
||||
|
||||
line_rate = executed_lines / max(total_lines, 1)
|
||||
|
||||
return {
|
||||
"available": True,
|
||||
"line_rate": round(line_rate, 4),
|
||||
"total_lines": total_lines,
|
||||
"executed_lines": executed_lines,
|
||||
}
|
||||
|
||||
except FileNotFoundError:
|
||||
logger.warning("[gcov] gcov 命令未找到,降级为仅静态分析")
|
||||
return {"available": False, "reason": "gcov_not_installed"}
|
||||
except Exception as e:
|
||||
logger.warning(f"[gcov] 采集异常: {e}")
|
||||
return {"available": False, "reason": str(e)[:100]}
|
||||
Reference in New Issue
Block a user