feat(runner): add run_external_groups for black-box datasets

This commit is contained in:
2026-09-13 15:00:19 +08:00
parent bc83a3b8ac
commit a11fde9de5
+111
View File
@@ -995,6 +995,117 @@ def run_all(program_name: str, outdir: str, temp_dir: str,
return results, merged_gcov
# ── 外部(黑盒)数据组执行 ──
def run_external_groups(program_name: str, outdir: str, temp_dir: str,
fields_dict: list[dict], fd_fields: dict,
select_info: dict, open_dir: dict,
roles: dict, field_to_fd: dict,
groups: list, source_dir: str,
data_fields: list[dict] | None = None,
multi_write_fds: set | None = None,
java_src_dir: str | None = None
) -> tuple[list, list[dict]]:
"""跑外部(黑盒)数据组:编译一次 → 逐组写输入/执行/Java 比对。
groups: list[BlackBoxGroup](具备 label/records/term_types 属性)。
Returns: (results, java_reports)
"""
from .output import output_input_files
fd_field_dicts = _build_fd_field_dicts(fd_fields, fields_dict)
log_dir = os.path.join(outdir, 'logs')
work_dir = Path(temp_dir).resolve()
work_dir.mkdir(parents=True, exist_ok=True)
sub_dir = _resolve_sub_dir(source_dir)
cpy_dir = _resolve_cpy_dir(source_dir)
sub_o = compile_sub_modules(sub_dir, str(work_dir), cpy_dir, log_dir=log_dir)
exe_path = compile_program(program_name, source_dir, str(work_dir), sub_o,
cpy_dir, log_dir=log_dir)
java_cfg = None
if str(os.environ.get('COBOL_JAVA_RUN', '1')).lower() not in ('0', 'off', 'false'):
_jsrc = (java_src_dir
or os.environ.get('COBOL_JAVA_SRC_DIR')
or str(Path(source_dir).parent / 'JavaSrc'))
java_cfg = _discover_java(_jsrc, program_name)
if java_cfg:
logger.info(f" 发现 Java 对应程序: {java_cfg['main_class']}")
else:
logger.info(f" 未发现 Java 对应程序({_jsrc}),跳过 Java 运行/比对")
results = []
java_reports = []
for grp in groups:
label = grp.label
records = grp.records or []
term_types = grp.term_types or ['normal'] * len(records)
if not records:
logger.warning(f" 黑盒组 {label}: 无记录,跳过")
continue
base = Path(outdir) / 'black_box' / label
src_in_dir = base / 'cobol' / 'input'
dst_out_dir = base / 'cobol' / 'output'
if src_in_dir.exists():
shutil.rmtree(str(src_in_dir), ignore_errors=True)
output_input_files(
records, src_in_dir, f'{program_name}_{label}', roles,
fd_fields, field_to_fd, open_dir,
term_types=term_types,
data_fields=data_fields or fields_dict,
select_info=select_info,
drop_secondary_tail=False,
)
if src_in_dir.is_dir():
for src in sorted(src_in_dir.iterdir()):
if src.is_file() and src.suffix.lower() != '.json':
shutil.copy2(str(src), str(work_dir / src.name))
_clean_gcda(str(work_dir))
group = GroupInfo(
name=f'{program_name}_black_box_{label}',
records=records,
expected_outputs=[{}] * len(records),
fd_field_dicts=fd_field_dicts,
open_dir=open_dir,
select_info=select_info,
multi_write_fds=multi_write_fds or set(),
)
r = run_group(group, exe_path, str(work_dir), log_dir=log_dir)
results.append(r)
logger.info(f"'{group.name}': returncode={r.returncode}, "
f"{'' if r.passed else ''}")
dst_out_dir.mkdir(parents=True, exist_ok=True)
for fd_name in fd_field_dicts:
if (open_dir or {}).get(fd_name, '') not in ('OUTPUT', 'I-O'):
continue
sel = select_info.get(fd_name, {})
assign = sel.get('assign', fd_name) if isinstance(sel, dict) else fd_name
src = os.path.join(str(work_dir), assign)
if os.path.exists(src):
shutil.copy2(src, str(dst_out_dir / assign))
if java_cfg:
jrep = _run_java_scene(
program_name, label,
base / 'java' / 'output',
str(work_dir),
src_in_dir, dst_out_dir,
fd_field_dicts, open_dir, select_info,
java_cfg, log_dir=log_dir, label=label,
)
jrep['section'] = 'black_box'
java_reports.append(jrep)
return results, java_reports
# ── run_and_compare(被 --run 调用,SOURCE 兼容)──