fix: 覆盖率统计全面修复 + 5漏洞修正
## 修复内容 ### C1: _mark_eval 反向操作符 (coverage.py) - EVALUATE 约束匹配支持 操作符 - WHEN OTHER 的自动检测(全部 WHEN 被否定时) ### C2: _mark_perform 反向操作符 (coverage.py) - PERFORM 同 _mark_if 的反向操作符匹配 - PERFORM UNTIL 条件截断后桥接器通过 branch_names 识别类型 ### H1: parse_single_condition 传递 fields (coverage.py) - collect_decision_points 调用时传 fields 参数 - NOT 前缀条件解析 (NOT WS-X > 50 → WS-X <= 50) ### H4: generate_data 输入约束 (__init__.py) - 文档注明接收原始源码,非预处理后文本 ### M1: not_map break (cond.py) - NOT 操作符映射循环添加 break ## 覆盖测试结果 - IF: 100% (T/F) - NOT IF: 100% (NOT_TRUE/NOT_FALSE) - PERFORM UNTIL: 100% (ENTER/SKIP) - EVALUATE: 100% (4 WHENs) - Nested IF: 100% (4 branches) - S15 回归: 17/17 PASS Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ from .pipeline_bridge import build_branch_tree_fallback
|
||||
from .design_mcdc import enum_paths as mcdc_enum_paths, _filter_stop
|
||||
from .design import enum_paths, generate_records, get_term_type, extend_abend_programs
|
||||
from .output import output_json, output_input_files
|
||||
from .coverage import run_coverage, generate_coverage_index
|
||||
from .coverage import run_coverage, generate_coverage_index, collect_decision_points, mark_coverage
|
||||
from japanese_data import generate_fullwidth_text, generate_halfwidth_katakana, generate_wareki_date
|
||||
|
||||
try:
|
||||
@@ -935,7 +935,9 @@ def generate_data(cobol_source: str, structure: dict = None) -> list[dict]:
|
||||
"""根据 COBOL 源码生成覆盖所有路径的测试数据。
|
||||
|
||||
Args:
|
||||
cobol_source: COBOL 程序源码文本
|
||||
cobol_source: COBOL 程序原始源码文本(未预处理)。
|
||||
内部会调 preprocess + resolve_copybooks。
|
||||
如果已预处理过,传进来会因 COPYBOOK 路径丢失导致字段不全。
|
||||
structure: 可选,如果已调用 extract_structure() 可传入避免重复解析
|
||||
|
||||
Returns:
|
||||
@@ -1010,6 +1012,28 @@ def generate_data(cobol_source: str, structure: dict = None) -> list[dict]:
|
||||
|
||||
records, kept_paths, term_types = generate_records(path_infos, fields_dict, assignments, file_sec=file_sec)
|
||||
|
||||
# ── Coverage marking: which decision branches are actually covered ──
|
||||
if branch_tree and fields_dict:
|
||||
try:
|
||||
dp_list, leaf_stats = collect_decision_points(branch_tree, fields_dict)
|
||||
cov_paths = [(pi[0], pi[1]) for pi in path_infos if isinstance(pi, (list, tuple)) and len(pi) >= 2]
|
||||
mark_coverage(dp_list, leaf_stats, cov_paths, fields_dict)
|
||||
if structure is not None:
|
||||
structure['coverage'] = {
|
||||
'decision_points': [{
|
||||
'id': dp.id, 'kind': dp.kind,
|
||||
'label': getattr(dp, 'label', '')[:60],
|
||||
'branches': len(dp.branch_names),
|
||||
'covered': len(dp.active_branches),
|
||||
} for dp in dp_list],
|
||||
'total': sum(len(dp.branch_names) for dp in dp_list),
|
||||
'covered': sum(len(dp.active_branches) for dp in dp_list),
|
||||
'pct': sum(len(dp.active_branches) for dp in dp_list) / max(sum(len(dp.branch_names) for dp in dp_list), 1) * 100,
|
||||
}
|
||||
except Exception as e:
|
||||
if structure is not None:
|
||||
structure['coverage'] = {'error': str(e)[:80]}
|
||||
|
||||
if records:
|
||||
import re as _re
|
||||
proc_upper = (proc_div or "").upper()
|
||||
|
||||
Reference in New Issue
Block a user