feat: SQL between/hostvar-key alignment, class-condition parsing, gcov merge across scenario runs
This commit is contained in:
+36
-7
@@ -31,6 +31,7 @@ class GroupInfo:
|
||||
select_info: dict = field(default_factory=dict)
|
||||
overlap_mask: list[bool] = field(default_factory=list)
|
||||
multi_write_fds: set = field(default_factory=set)
|
||||
command_args: list = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -335,7 +336,7 @@ def run_group(group: GroupInfo, exe_path: str, temp_dir: str,
|
||||
try:
|
||||
os.chdir(str(work_dir))
|
||||
result = subprocess.run(
|
||||
[str(exe)], capture_output=True, text=True,
|
||||
[str(exe)] + list(group.command_args or []), capture_output=True, text=True,
|
||||
encoding='utf-8', errors='replace', timeout=60,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
@@ -434,26 +435,36 @@ def run_all(program_name: str, outdir: str, temp_dir: str,
|
||||
gcov_root = work_dir / "gcov"
|
||||
|
||||
for scene_id, scene_recs, scene_terms, scene_expected, src_in_dir, dst_out_dir in scenes:
|
||||
# ── 3a. 入力ファイル配置 ──
|
||||
# ── 3a. 入力ファイル配置(主程序 + 被调子程序的输入文件全部复制)──
|
||||
# 仅复制 assign_names 会漏掉子程序输入文件(测试驱动调用读文件自程序时
|
||||
# 会 OPEN 失败 ABEND)。复制目录内全部非 JSON 文件(.json 为 V3 元数据)。
|
||||
if src_in_dir.is_dir():
|
||||
for assign in assign_names:
|
||||
src = src_in_dir / assign
|
||||
if src.exists():
|
||||
shutil.copy2(str(src), str(work_dir / assign))
|
||||
for src in sorted(src_in_dir.iterdir()):
|
||||
if not src.is_file() or src.suffix.lower() == '.json':
|
||||
continue
|
||||
shutil.copy2(str(src), str(work_dir / src.name))
|
||||
|
||||
# ── 3b. 清理旧 gcda ──
|
||||
_clean_gcda(str(work_dir))
|
||||
|
||||
# ── 3c. 过滤 non-abend ──
|
||||
filtered_exp = []
|
||||
normal_recs = []
|
||||
abend_pairs = [] # (rec, command_args)
|
||||
for i, rec in enumerate(scene_expected):
|
||||
term = scene_terms[i] if i < len(scene_terms) else 'normal'
|
||||
if term != 'abend':
|
||||
filtered_exp.append(rec)
|
||||
for i, rec in enumerate(scene_recs):
|
||||
term = scene_terms[i] if i < len(scene_terms) else 'normal'
|
||||
if term == 'abend':
|
||||
abend_pairs.append((rec, list((rec.get('__CLI_ARGS__') or {}).values())))
|
||||
else:
|
||||
normal_recs.append(rec)
|
||||
|
||||
group = GroupInfo(
|
||||
name=f"{program_name}_{scene_id}",
|
||||
records=scene_recs,
|
||||
records=normal_recs,
|
||||
expected_outputs=filtered_exp,
|
||||
expected_returncode=0,
|
||||
fd_field_dicts=fd_field_dicts,
|
||||
@@ -469,6 +480,23 @@ def run_all(program_name: str, outdir: str, temp_dir: str,
|
||||
status = '✓' if r.passed else '✗'
|
||||
logger.info(f" 组 '{group.name}': returncode={r.returncode}, {status}")
|
||||
|
||||
# ── 3d-2. abend 记录单独执行(带命令行参数,触发 ABEND/异常返回)──
|
||||
for ab_idx, (ab_rec, ab_args) in enumerate(abend_pairs):
|
||||
ab_group = GroupInfo(
|
||||
name=f"{program_name}_{scene_id}_abend_{ab_idx + 1}",
|
||||
records=[ab_rec], expected_outputs=[],
|
||||
expected_returncode=1,
|
||||
fd_field_dicts=fd_field_dicts,
|
||||
open_dir=open_dir,
|
||||
select_info=select_info,
|
||||
multi_write_fds=multi_write_fds,
|
||||
command_args=ab_args,
|
||||
)
|
||||
r2 = run_group(ab_group, exe_path, str(work_dir), log_dir=log_dir)
|
||||
results.append(r2)
|
||||
status2 = '✓' if r2.passed else '✗'
|
||||
logger.info(f" 组 '{ab_group.name}': returncode={r2.returncode}, {status2}")
|
||||
|
||||
# ── 3e. 出力保存 ──
|
||||
dst_out_dir.mkdir(parents=True, exist_ok=True)
|
||||
for fd_name in fd_field_dicts:
|
||||
@@ -579,6 +607,7 @@ def run_and_compare(program_name: str, outdir: str,
|
||||
expected_returncode=1,
|
||||
fd_field_dicts=fd_field_dicts, open_dir=open_dir,
|
||||
select_info=select_info,
|
||||
command_args=list((rec.get('__CLI_ARGS__') or {}).values()),
|
||||
)
|
||||
r = run_group(group, exe_path, temp_dir, log_dir=log_dir)
|
||||
if r.returncode != 0:
|
||||
|
||||
Reference in New Issue
Block a user