Files
cobol-java-v3/docs/v3-理解文档.md

22 KiB
Raw Permalink Blame History

COBOL→Java/Spark 迁移验证平台 v3 理解文档

1. 系统概述

COBOL→Java/Spark 迁移验证平台。核心使命:给定 COBOL 源码及其迁移后的 Java/Spark 实现,自动生成覆盖所有分支路径的测试数据,分别运行两个版本,逐字段比对输出,判定迁移正确性并生成验证报告。

系统并非单一测试数据生成器,而是一条包含静态分析 → 测试数据生成 → 程序分类 → 编译运行 → 结果比对 → 诊断报告的完整自动化验证管道。


2. 架构总览

CLI (main.py) / Web (api.py)
        │
        ▼
orchestrator.py  ────────── 管道调度中枢
        │
  ┌─────┼─────────┬──────────────┬──────────────┐
  ▼     ▼         ▼              ▼              ▼
cobol_testgen  hina    agents    runners     comparator
(测试数据生成) (分类/门禁) (LLM智能体) (编译运行引擎) (比对引擎)
                  │                              │
                  ▼                              ▼
              storage/report                data/ (模型层)
              (存储/报告)                    config/ (配置层)

关键设计决策: 系统有两套平行的数据产出路径——

  • cobol_testgen 用规则引擎/Lark 语法解析生成覆盖全分支的测试数据(确定性)
  • agents/Agent2Data 用 LLM 从 FieldTree 生成测试数据设计(AI 辅助) 最终在 orchestrator.py:110-112 处以 complete_testscobol_testgen + hina 输出)覆盖 Agent2Data 的 suite.test_cases

3. 目录结构

cobol-java-v3/
├── main.py                  ← CLI 入口(argparse → run_pipeline
├── orchestrator.py          ← 管道编排(核心调度器,~200 行)
├── preprocessor.py          ← COPYBOOK 展开工具(独立类)
├── japanese_data.py         ← 日文测试数据生成(全角/半角/和历日期)
│
├── cobol_testgen/           ← COBOL 测试数据生成引擎
│   ├── __init__.py          ← 入口: main() + extract_structure/generate_data/incremental_supplement
│   ├── __main__.py          ← python -m 入口
│   ├── read.py              ← INPUT层: 预处理/COPYBOOK解决/DATA DIVISION解析/Lark
│   ├── core.py              ← CORE层: PROCEDURE DIVISION解析→分支树→数据流追踪(~2000行)
│   ├── cond.py              ← COND层: 条件解析+MC/DC枚举+约束合并
│   ├── design.py            ← DESIGN层: 路径枚举+约束应用+值生成(~1350行)
│   ├── design_mcdc.py       ← MC/DC 路径枚举变体
│   ├── coverage.py          ← 覆盖率: 决策点收集+标记+中文HTML报告(~1300行)
│   ├── output.py            ← 输出层: JSON(按FD分组入/出力+WS
│   ├── models.py            ← 共享数据模型
│   ├── pipeline_bridge.py   ← 新旧解析器桥接(新 parser 主+旧 parser 超时回退)
│   ├── procedure_parser.py  ← 新 PROCEDURE DIVISION 解析器(快速确定性)
│   ├── grammar.lark         ← DATA DIVISION Lark 语法
│   ├── procedure_grammar.lark ← PROCEDURE DIVISION Lark 语法
│   ├── flatfile.py          ← 平面文件工具
│   └── gcov.py              ← gcov 覆盖率采集
│
├── hina/                    ← 程序分类与质量门禁
│   ├── pipeline/pipeline.py ← 完整类型判定管道(关键词/规则/LLM 三路)
│   ├── classifier.py
│   ├── confidence.py
│   ├── gate.py              ← 质量门禁判定
│   ├── strategy.py          ← 策略补充
│   ├── retry.py             ← 分层重试
│   └── gcov_collector.py
│
├── agents/                  ← LLM 智能体
│   ├── llm.py               ← LLMClienthttpx + 磁盘缓存 + 重试)
│   ├── agent1_parser.py     ← COPYBOOK → FieldTreeLLM json
│   ├── agent2_data.py       ← FieldTree → TestSuiteLLM json
│   └── agent3_diagnostic.py ← FieldResult → 诊断建议(LLM json
│
├── comparator/              ← 对比引擎
│   ├── aligner.py           ← COBOL↔Java 记录对齐(CUST-ID 键)
│   ├── field_compare.py     ← 字段级比较(decimal/string
│   ├── cobol_binary_reader.py ← 二进制 COBOL 输出解析
│   ├── normalizer.py        ← COMP-3/EBCDIC 解码
│   └── rounding_detect.py   ← 舍入检测
│
├── runners/                 ← 编译运行引擎
│   ├── runner.py            ← 抽象基类 Runner + BuildResult/RunResult
│   ├── cobol_runner.py      ← cobc 编译+运行
│   ├── native_java_runner.py ← mvn + java -jar
│   ├── spark_java_runner.py ← spark-submit
│   └── data_writer.py       ← 测试数据写入(二进制/JSON)
│
├── data/                    ← 数据模型层
│   ├── field_tree.py        ← Field / FieldTree
│   ├── test_case.py         ← TestCase / TestSuite / SparkConfig
│   └── diff_result.py       ← FieldResult / VerificationRun
│
├── config/                  ← 配置
│   ├── __init__.py          ← Config dataclassToml 加载)
│   └── mapping.py           ← MappingConfig / FieldMapping
│
├── report/
│   └── generator.py         ← JSON / HTML / machine JSON 报告
│
├── storage/
│   ├── bundle.py            ← TestDataBundle 路径管理
│   └── store.py
│
├── web/                     ← Web 接口
│   ├── api.py               ← FastAPI202+ polling
│   ├── worker.py            ← 后台 worker
│   ├── static/
│   └── templates/
│
├── tests/                   ← 测试套件
├── test-data/               ← 测试数据
├── benchmark-programs/      ← 58 电信基准程序
├── data/                    ← 运行时数据
├── config/                  ← 运行时配置
│
├── pyproject.toml           ← 项目元数据(verify-cli 0.1.0
├── requirements.txt         ← Python 依赖
├── DESIGN.md                ← Web UI 设计规范
├── CLAUDE.md                ← 项目指令
└── AGENTS.md                ← AI Agent 指令(含修复历史)

4. 核心管道流程

4.1 CLI 入口 (main.py)

main.py --copybook <cpy> --cobol-src <cbl> --java-src <dir> --mapping <yaml>
         [--runner native|spark] [--coverage boundary|branch]
         [--tolerance 0.01] [--quality-gate-mode warn|off] [--gcov]

必选参数 4 个:copybook、cobol 源码、java 源码目录、映射文件。支持 --dry-run 前置校验路径存在性。

4.2 管道调度 (orchestrator.py:run_pipeline)

Phase 0 — 前置解析

copybook.cpy ─→ Agent1Parser (LLM) ─→ FieldTree(字段树)

Phase 1 — COBOL 测试数据生成 (cobol_testgen)

cobol.cbl ─→ preprocess() → resolve_copybooks() → parse_data_division()
          ─→ parse_procedure_division() → build_branch_tree()
          ─→ enum_paths() → generate_records() → base_records[]

Phase 2 — HINA 分类 + 策略补充 + 质量门禁

base_records[] ─→ classify_program() → category/confidence
               ─→ strategy supplement → 追加标记记录
               ─→ quality gate loop (最多 4 次 retry):
                    check_coverage() → gate_check()
                    if gaps: incremental_supplement() → 补充数据 → recheck

Phase 3 — LLM 测试数据设计 (Agent2Data)

FieldTree + complete_tests[] → Agent2Data (LLM) → TestSuite
注意: suite.test_cases 被 complete_tests 覆盖替换(行 112

Phase 4 — 编译运行

TestSuite ─→ DataWriter → cobol_input.bin / spark_input.json
COBOL: cobol_runner.compile() → cobol_runner.run() → cobol_out.bin
Java:  native/spark_runner.compile() → runner.run() → java_out records

Phase 5 — 对比 & 报告

cobol_out.bin ─→ CobolBinaryReader → dict[]
java_out      ─→ JSON → dict[]
align_records(key="CUST-ID") → compare_field() → FieldResult[]
Agent3Diagnostic (LLM) → suggestion for MISMATCH
ReportGenerator → result.json / report.html / machine.json

4.3 数据流全图

copybook.cpy
    │ Agent1Parser (LLM)
    ▼
FieldTree ────────────────────────┐
    │                             │
    │ Agent2Data (LLM)            │ cobol_testgen
    ▼                             ▼
TestSuite (被覆盖)          structure + base_records[]
    │                             │
    │ DataWriter                  │ HINA classify + quality gate
    ▼                             ▼
cobol_input.bin / json     complete_tests[]
    │
    ├── CobolRunner ──→ cobol_out.bin ──┐
    └── JavaRunner  ──→ java_out  ──────┤
                                         ▼
                                   align_records()
                                         │
                                         ▼
                                   compare_field() ──→ FieldResult[]
                                         │
                                         ▼
                                   Agent3Diagnostic (LLM) → suggestion
                                         │
                                         ▼
                                   ReportGenerator → result.json/html

5. 核心模块详解

5.1 cobol_testgen(测试数据生成引擎)

Layer 架构4 层独立,每层单一职责):

文件 职责
INPUT read.py 预处理器(固定/自由格式检测、COPYBOOK 展开、SQL/CICS EXEC 剥离)、Lark 语法解析 DATA DIVISION
CORE core.py 解析 PROCEDURE DIVISION 为分支树(BrIf/BrEval/BrPerform/Assign/CallNode/GoTo/ExitNode)、数据流追踪(trace_to_root/propagate_assignments
COND cond.py COBOL 条件解析(parse_single_condition/parse_compound_condition)、MC/DC 枚举(mcdc_sets)、约束合并(merge_field_constraints)、边界值求解(satisfying_value
DESIGN design.py 路径枚举(enum_paths,LLM 优先 → 规则引擎回退)、记录生成(generate_records,约束应用到字段值)
OUTPUT output.py JSON 输出(输入/期望输出/工作存储区,按 FD 分组)
COVERAGE coverage.py 决策点收集(collect_decision_points)→ 标记覆盖(mark_coverage)→ 中文 HTML 报告

关键数据模型 (models.py)

  • BrSeq — 序列容器
  • BrIf — IF 分支(condition + cond_tree + true_seq + false_seq
  • BrEval — EVALUATEsubjects + when_list + other_seq
  • BrPerform — PERFORMperf_type + condition + body_seq
  • BrSearch — SEARCHat_end_seq + when_list
  • Assign — 赋值节点(target + source_info
  • CondLeaf / CondAnd / CondOr / CondNot — 条件树

路径枚举策略

  1. 尝试 LLM 生成路径(DEEPSEEK_API_KEY
  2. LLM 失败/无 key 则回退规则引擎(_cap_paths 限制 10000 条)
  3. MC/DC 变体(design_mcdc.py:enum_paths)用于 generate_data() 入口

基于旧 parser 的路径去重_filter_stop 处理哨兵标记(__STOP__/__ABEND__),与覆盖率标记中的 _is_eof_path 过滤配合使用。

OCCURS 展开机制 (expand_occurs)

  • 递归展开 occurs > 0 的字段,生成 WS-CELL(1)WS-CELL(1,1) 等下标签记副本
  • 88-level 的 parent 也会跟随展开

PREV 连锁机制 (_chain_prev)

  • 多 WRITE 场景下的跨记录约束满足
  • 处理 WRK-PREV-xxx 前值比较的字段传递
  • 判断 W02(正常)或 overlap(重疊)路径

5.2 hina(程序分类与质量门禁)

分类管道(三路径并行):

  1. 关键词匹配 — 从源码中识别对应银行业务模式的关键词
  2. 规则引擎 — 基于 IF 类型统计、变量命名模式、OPEN/CLOSE 模式的规则判定
  3. LLM 辅助 — 低确信度时调用 LLM 二次确认

质量门禁 (gate.py:check)

  • 检查决策点覆盖率、段落覆盖率是否达到阈值(Config 中 quality_gate_decision_threshold 默认 0.90
  • 未通过时触发 incremental_supplement 补充未覆盖决策点的数据
  • 最大尝试次数:max_quality_retries = 4

5.3 agentsLLM 智能体)

三个 Agent 定位清晰:

Agent 输入 处理 输出
Agent1Parser COPYBOOK 源码文本 LLM 解析为 JSON FieldTree
Agent2Data FieldTree 字段列表 LLM 生成边界测试用例 TestSuite
Agent3Diagnostic FieldResult (field_name + 双方值) LLM 诊断 mismatch 原因 suggestion 文本

LLMClient (agents/llm.py)

  • 通用 HTTP 客户端(httpx),兼容 OpenAI API / DeepSeek
  • 磁盘缓存(SHA256 散列键值,.cache/llm/{hash}.json
  • 1 次重试 + 异常冒泡
  • 环境变量:LLM_API_KEY / OPENAI_API_KEY, LLM_API_BASE

5.4 comparator(对比引擎)

CobolBinaryReader → dict[]      java JSON → dict[]
                    │
                    ▼
          align_records(key_field="CUST-ID")
                    │
                    ▼
          (cobol_rec, java_rec, status) tuples
                    │
                    ▼
          compare_field(name, c_val, j_val, type, tolerance)
                    │
                    ▼
          FieldResult(PASS/TOLERATED/MISMATCH/NOT_SET)
  • 对齐策略:基于 CUST-ID 字段做记录级别匹配
  • 比较模式:decimal 用容忍度比较,string 用精确字符串比较
  • 字段类型判定:tree.get_by_name(k).usage != "COMP-3" → string(不合理:COMP-3 是数值存储格式,但此处用 != 判断,DISPLAY 和 COMP 等也会被归为 decimal

5.5 runners(编译运行引擎)

Runner 编译 运行 输入格式
CobolRunner cobc -x 直接执行二进制 input.bin (二进制)
NativeJavaRunner mvn package java -jar input.json
SparkJavaRunner mvn package spark-submit spark input/

5.6 webWeb 接口)

  • FastAPI + 202 Accepted 异步轮询模式
  • 文件上传 → uploads/{task_id}/tasks/{task_id}.json 状态文件
  • 无数据库,纯文件系统状态管理
  • worker.py 后台轮询处理队列
  • HTML 模板使用字符串替换(因 Jinja2 兼容性考虑)

6. 数据模型关系

FieldDef (cobol_testgen/models.py) ← Lark grammar 解析 DATA DIVISION 的结果
    │
    ▼
FieldTree + Field (data/field_tree.py) ← Agent1Parser LLM 解析 COPYBOOK 的结果
    │
    ├───▶ TestCase + TestSuite (data/test_case.py) ← 测试数据载体
    │
    └───▶ VerificationRun + FieldResult (data/diff_result.py) ← 管道运行结果

两套字段定义体系并存

  • cobol_testgen/models.py:FieldDef — 带 pic_infoPicInfo 对象)、occurs_countis_88redefines 等 COBOL 细节
  • data/field_tree.py:Field — 简洁版,含 pic 字符串、offsetlengthchildren 嵌套结构
  • 两者在 orchestrator 中互不交换数据(Agent1Parser 产生 FieldTree → Agent2Datacobol_testgen 产生自己的 fields_dict

7. 依赖关系

外部 Python 库

依赖 版本 用途
httpx >=0.27 LLM API HTTP 调用
pyyaml >=6.0 映射文件解析
lark >=1.1.0 DATA DIVISION 语法解析(Earley + dynamic lexer
fastapi / uvicorn Web API
python-multipart 文件上传解析
pytest 测试框架

外部非 Python 工具

工具 用途
cobc (GnuCOBOL) COBOL 编译运行
java + mvn Java 编译运行
spark-submit Spark 模式运行(可选)
gcov 覆盖率采集(可选)

外部 API

API 用途 环境变量
OpenAI / LLM API Agent 智能体调用 LLM_API_KEY / OPENAI_API_KEY
DeepSeek API cobol_testgen LLM 路径生成 DEEPSEEK_API_KEY

8. 关键注意事项

8.1 设计层面的注意事项

  1. 两套配置系统割裂cobol_testgen/__init__.py:CONFIG(含 abend_programs 列表)与 config/__init__.py:Config(从 aurak.toml 加载)完全不互通。修改 Config 参数不会影响 cobol_testgen 的行为。

  2. 两套字段定义体系并存cobol_testgen 内部使用 FieldDef + fields_dictlist of dict),orchestrator 上层使用 data/field_tree.py:Field + FieldTree。两者不共享,debug["field_tree"] 从 FieldTree 取,cobol_testgen 的数据从 fields_dict 取。

  3. LLM 同步阻塞且无流控LLMClient.call() 同步调用且超时仅 15s,大 COPYBOOK 易超时。Agent1ParserAgent2Data 无降级路径(JSON 解析失败则返回空结构)。

  4. Web 模式的响应式任务模型脆弱 — 使用文件 tasks/{task_id}.json 做状态管理,重启丢失所有未完成任务。worker 轮询无锁机制,并发安全未保证。

  5. 新旧 parser 并存隐患pipeline_bridge.py 中旧 parser 的 3s 超时用 threading.Thread.daemon=True + join(3.0),超时后线程仍在后台运行(daemon 虽会在主进程退出时终止,但 3s 内可能已占用大量资源)。

8.2 代码层面的不合理之处(只标注,不修改)

  1. 字段类型判断逻辑有疑orchestrator.py:163 处:

    ft = "string" if m and m.usage != "COMP-3" else "decimal"
    

    COMP-3(压缩十进制)是 decimal 类型,但此逻辑意味着所有非 COMP-3 字段都被视为 string,包括 COMP、BINARY、PACKED-DECIMAL 等数值类型。

  2. Agent2Data 的输出被无条件覆盖orchestrator.py:112

    suite.test_cases = complete_tests
    

    Agent2Data.design() 的 LLM 调用结果被 complete_tests 完全替换,该 LLM 调用除了产生 spark_config 外没有实际用途。LLM 费用被浪费。

  3. 硬编码 LLM 成本orchestrator.py:30,111vr.llm_cost += 0.002(固定 $0.002/次),与实际模型(Config 中 gpt-4o-mini)的 token 计费无关。

  4. cobol_testgen/generate_data() 中的条件值强制相等cobol_testgen/__init__.py:1069-1077

    for m in re.finditer(r'IF\s+(\w[\w-]*)\s*[=<>]\s*(\w[\w-]*)', proc_upper):
        ...
        rec[rhs] = rec[lhs]  # 强制 rhs 等于 lhs
    

    对所有形如 IF A > B 的字段对比较,前一半记录的 rhs 被强制为 lhs 的值。这会破坏原有路径约束生成的精确值,且仅影响前一半记录——逻辑意图不明。

  5. generate_data()_resolve_field() 的字段匹配逻辑 — 路径过滤时使用解析后的字段名去匹配 _fdict_names。对形如 WS-PLAN-CODE(WS-PLAN-IDX) 的字段,解析为 WS-PLAN-CODE 后只检查 base 名是否存在,忽略了实际有下标的字段名(如 WS-PLAN-CODE(1))已存在于 fields_dict 中。

  6. COBOL_SCOPE_ENDERS 硬编码列表core.py:12-16 中的 scope enders 列表缺少 END-ACCEPTEND-DISPLAY 等,可能导致非预期解析提前结束。

  7. cobol_testgen/core.py:29-60 段落扫描中的空白处理 — 第 37 行 re.match(r'^([A-Z0-9][A-Z0-9-]*)\.\s*$', line) 要求段落名后紧跟 . 且只有空白,但 COBOL 允许在段落名后跟多语句,如 PARA-A. MOVE A TO B

8.3 边界情况与隐藏假设

  1. 假设 CUST-ID 是对齐键align_records() 硬编码 key_field="CUST-ID",非此字段名的 FD 无法正确对齐。

  2. 假设 COPYBOOK 不含 88-level VALUE — AGENTS.md 明确指出目标程序不应有 88-level VALUE 子句,解析器对 88-level 值的依赖微乎其微。

  3. 假设 target 程序不含 INSPECT/STRING/UNSTRINGextract_structure 虽然检测 has_inspecthas_string,但整个管道没有对这些语句做特殊处理或断言。

  4. 覆盖率补充依赖 branch_tree_objorchestrator.py:86 质量门禁 gap 补充要求 structure.get("branch_tree_obj") 存在,但 extract_structure 成功执行且 proc_div 存在时才可能有。

  5. --gcov 模式需要运行二进制 COBOL — gcov 覆盖率采集依赖真实执行 COBOL 二进制文件,需要编译环境和实际运行平台(GnuCOBOL),在仅做静态分析时不可用。


9. 修复历史总结(AGENTS.md

Fix 内容 涉及模块
1 COMPUTE ROUNDED 正则修复 core.py
2 OCCURS 下标 MOVE 目标保持 core.py
3 DIVIDE REMAINDER 支持 core.py
4 EVALUATE ALSO 多主体 core.py, design.py
5 READ AT END 跳过 core.py
6 WRITE/REWRITE 无 FROM core.py
7 PERFORM UNTIL 复合条件路径 design.py
8 IF 复合条件覆盖率标记修复 coverage.py
9 pi_map 用未解析 key 查询 design.py
10 变量下标约束应用 design.py
11 多行 COMPUTE 表达式 core.py
12 多行 PERFORM VARYING core.py
13 _mark_perform 复合条件标记 coverage.py
14 EVALUATE TRUE prior_false 笛卡尔积 coverage.py
15 SEARCH _non_match_for 下标匹配 coverage.py
16 移除 _infer_implied 桩函数 coverage.py
17 PERFORM VARYING 末次 + 字母数字边界 + 零保护 design.py, cond.py

文档版本: v1.0 | 生成日期: 2026-06-27