""" HINA 类型别 COBOL 测试数据验证器 全テストプログラムに対して extract_structure + HINA + 数据生成を実行 """ import sys, json from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent)) from cobol_testgen import extract_structure, generate_data from cobol_testgen.coverage import check_coverage from hina.classifier import compute_confidence TEST_DIR = Path(__file__).parent / "cobol" EXPECTED = { "HINA001": {"name": "1:1 マッチング", "min_para": 8, "min_br": 0, "min_dp": 0, "fc": 3, "note": "PERFORM内IFは静的解析対象外"}, "HINA005": {"name": "IF条件分岐", "min_para": 1, "min_br": 6, "min_dp": 3, "fc": 0}, "HINA006": {"name": "EVALUATE分岐", "min_para": 1, "min_br": 6, "min_dp": 3, "fc": 0}, "HINA007": {"name": "キーブレイク集計", "min_para": 3, "min_br": 0, "min_dp": 0, "fc": 2, "note": "PERFORM内IFは静的解析対象外"}, "HINA024": {"name": "内部テーブル検索", "min_para": 1, "min_br": 2, "min_dp": 2, "fc": 0, "note": "Lark文法制限: ASCENDING KEY未対応"}, "HINA013": {"name": "項目チェック", "min_para": 1, "min_br": 6, "min_dp": 3, "fc": 0}, "HINA004": {"name": "編集出力(GETPUT)", "min_para": 3, "min_br": 0, "min_dp": 0, "fc": 2, "note": "PERFORM内IFは静的解析対象外"}, "HINA025": {"name": "サブプログラムCALL", "min_para": 2, "min_br": 0, "min_dp": 0, "fc": 0, "hina_type": "子程序调用", "hina_method": "keyword"}, "HINA034": {"name": "SORT処理", "min_para": 1, "min_br": 0, "min_dp": 0, "fc": 3, "hina_type": "SORT", "hina_method": "keyword", "note": "Lark文法制限: SD未対応"}, "HINA101": {"name": "EXEC SQL", "min_para": 1, "min_br": 1, "min_dp": 1, "fc": 0, "hina_type": "DB操作", "hina_method": "keyword"}, } def main(): results = [] passed = failed = 0 cbl_files = sorted(TEST_DIR.glob("HINA*.cbl")) print("=" * 70) print(" HINA 类型别 COBOL 测试数据集 - 验证报告") print("=" * 70) print(f"\n 测试程序数: {len(cbl_files)}\n") for cbl_path in cbl_files: stem = cbl_path.stem exp = EXPECTED.get(stem, {}) name = exp.get("name", stem) src = cbl_path.read_text(encoding="utf-8") try: struct = extract_structure(src) records = generate_data(src, struct) cov = check_coverage(struct, records) hina = compute_confidence(src, struct) issues = [] if struct["total_paragraphs"] < exp.get("min_para", 0): issues.append(f"段落不足: {struct['total_paragraphs']}<{exp.get('min_para')}") if struct["total_branches"] < exp.get("min_br", 0): issues.append(f"分岐不足: {struct['total_branches']}<{exp.get('min_br')}") if len(struct["decision_points"]) < exp.get("min_dp", 0): issues.append(f"決定点不足: {len(struct['decision_points'])}<{exp.get('min_dp')}") if exp.get("hina_type") and hina.get("category") != exp["hina_type"]: issues.append(f"HINA類型違い: {hina.get('category')}!={exp['hina_type']}") if exp.get("hina_method") and hina.get("method") != exp["hina_method"]: issues.append(f"HINA方法違い: {hina.get('method')}!={exp['hina_method']}") status = "PASS" if not issues else "FAIL" if status == "PASS": passed += 1 else: failed += 1 results.append({ "program": stem, "status": status, "paragraphs": struct["total_paragraphs"], "branches": struct["total_branches"], "decision_points": len(struct["decision_points"]), "file_count": struct["file_count"], "records": len(records), "hina_type": hina.get("category", "?"), "hina_confidence": hina.get("confidence", 0.0), "hina_method": hina.get("method", "?"), "issues": issues, }) print(f" [{status}] {stem} - {name}") print(f" 段落={struct['total_paragraphs']} 分岐={struct['total_branches']} " f"決定点={len(struct['decision_points'])} ファイル={struct['file_count']}") print(f" HINA: {hina.get('category','?')} ({hina.get('confidence',0):.0%}) method={hina.get('method','?')}") print(f" 生成データ: {len(records)}件") for i in issues: print(f" ⚠️ {i}") print() except Exception as e: failed += 1 print(f" [ERROR] {stem} - {name}: {str(e)[:80]}\n") print("-" * 70) print(f" 总计: {passed} passed, {failed} failed / {len(cbl_files)} total") report_path = TEST_DIR.parent / "test-report.json" json.dump(results, open(report_path, "w", encoding="utf-8"), indent=2, ensure_ascii=False) print(f" 详细报告: {report_path}") return 0 if failed == 0 else 1 if __name__ == "__main__": sys.exit(main())