# V3系统目录结构设计文档 ## 一、目录结构概述 V3系统采用统一的目录结构来组织COBOL和Java的输出结果,确保所有程序的输出文件都位于同一个根目录下,便于管理和比较。 ## 二、目录结构规范 ### 2.1 标准目录结构 ``` output// ├── cobol/ # COBOL输出(所有组) │ ├── main/ # 单轮/默认场景 │ │ ├── input/ # COBOL输入flat文件 │ │ ├── output/ # COBOL输出flat文件 │ │ └── json/ # Java验证用JSON │ ├── run_skip/ # 跳过场景 │ │ ├── input/ │ │ ├── output/ │ │ └── json/ │ ├── run_/ # 多轮场景 │ │ ├── input/ │ │ ├── output/ │ │ └── json/ │ └── pre_src/ # 预处理源码 ├── java/ # Java输出(所有组) │ ├── main/ # 对应cobol/main的Java输出 │ │ └── output/ │ ├── run_skip/ # 对应cobol/run_skip的Java输出 │ │ └── output/ │ └── run_/ # 对应cobol/run_*的Java输出 │ └── output/ ├── coverage/ # 覆盖率报告(全局) ├── logs/ # 日志(全局) │ ├── main.log │ ├── run_skip.log │ └── run_.log ├── gcov/ # gcov数据(按场景分离) │ ├── run_main/ │ ├── run_skip/ │ └── run_/ ├── data/ # SQLite数据库(按场景分离) │ ├── kin.db # 单轮场景 │ └── kin_.db # 多轮场景 └── reports/ # 测试报告 └── / ├── result.json ├── report.html └── machine.json ``` ### 2.2 目录命名规则 | 目录 | 命名规则 | 说明 | |------|----------|------| | `cobol/main/` | 固定名称 | 单轮/默认场景 | | `cobol/run_skip/` | 固定名称 | 跳过场景(原 `skip/`) | | `cobol/run_/` | `run_` + 场景ID | 多轮场景 | | `java/<对应cobol目录>/` | 与cobol目录对应 | Java输出 | | `coverage/` | 固定名称 | 覆盖率报告 | | `logs/` | 固定名称 | 日志文件 | | `gcov/run_/` | `run_` + 场景ID | gcov数据 | | `data/` | 固定名称 | SQLite数据库 | ### 2.3 文件命名规则 | 文件类型 | 命名规则 | 示例 | |----------|----------|------| | COBOL输入文件 | `R` | `KIN01R01`, `ZAN01R01` | | COBOL输出文件 | `W` | `KIN01W01`, `ZAN01W01` | | JSON中介文件 | `.json` | `KIN01INP.json` | | 覆盖率报告 | `_coverage.html` | `KIN01INP_coverage.html` | | 运行日志 | `<场景ID>.log` | `main.log`, `run_normal.log` | | gcov数据 | 按场景ID分目录 | `gcov/run_main/`, `gcov/run_skip/` | | SQLite数据库 | `kin_<场景ID>.db` | `kin.db`, `kin_normal.db` | ## 三、场景映射规则 ### 3.1 单轮场景 **定义**:程序只有一次执行,无多场景配置。 **目录结构**: ``` output// ├── cobol/ │ └── main/ │ ├── input/ │ ├── output/ │ └── json/ ├── java/ │ └── main/ │ └── output/ ├── coverage/ ├── logs/ │ └── main.log ├── gcov/ │ └── run_main/ └── data/ └── kin.db ``` ### 3.2 多轮场景 **定义**:程序有多次执行,通过YAML配置文件定义场景。 **目录结构**: ``` output// ├── cobol/ │ ├── run_normal/ │ │ ├── input/ │ │ ├── output/ │ │ └── json/ │ ├── run_insert_error/ │ │ ├── input/ │ │ ├── output/ │ │ └── json/ │ └── run_sql_delete_error/ │ ├── input/ │ ├── output/ │ └── json/ ├── java/ │ ├── run_normal/ │ │ └── output/ │ ├── run_insert_error/ │ │ └── output/ │ └── run_sql_delete_error/ │ └── output/ ├── coverage/ ├── logs/ │ ├── run_normal.log │ ├── run_insert_error.log │ └── run_sql_delete_error.log ├── gcov/ │ ├── run_normal/ │ ├── run_insert_error/ │ └── run_sql_delete_error/ └── data/ ├── kin_normal.db ├── kin_insert_error.db └── kin_sql_delete_error.db ``` ### 3.3 跳过场景 **定义**:程序有跳过主FD输入的场景(旧版 `skip/` 目录)。 **目录结构**: ``` output// ├── cobol/ │ ├── main/ │ │ ├── input/ │ │ ├── output/ │ │ └── json/ │ └── run_skip/ │ ├── input/ │ ├── output/ │ └── json/ ├── java/ │ ├── main/ │ │ └── output/ │ └── run_skip/ │ └── output/ ├── coverage/ ├── logs/ │ ├── main.log │ └── run_skip.log ├── gcov/ │ ├── run_main/ │ └── run_skip/ └── data/ ├── kin.db └── kin_skip.db ``` ## 四、路径依赖说明 ### 4.1 env_overrides 路径 COBOL运行时通过环境变量映射文件路径: ```python # 输入文件 env_overrides[fname] = os.path.join("input", fname) # 输出文件 env_overrides[fname] = os.path.join("output", fname) ``` **注意**:这些是相对于CWD的路径,CWD为 `cobol/main/` 或 `cobol/run_/`。 ### 4.2 SQLite数据库路径 ```python # 单轮场景 db_path = data/kin.db # 多轮场景 db_path = data/kin_.db ``` ### 4.3 gcov数据路径 ```python # 单轮场景 gcov_dir = gcov/run_main/ # 多轮场景 gcov_dir = gcov/run_/ ``` ## 五、向后兼容性 ### 5.1 旧版目录迁移 | 旧版目录 | 新版目录 | 迁移方式 | |----------|----------|----------| | `main/input/` | `cobol/main/input/` | 移动文件 | | `main/output/` | `cobol/main/output/` | 移动文件 | | `main/json/` | `cobol/main/json/` | 移动文件 | | `skip/input/` | `cobol/run_skip/input/` | 重命名+移动 | | `skip/output/` | `cobol/run_skip/output/` | 重命名+移动 | | `skip/json/` | `cobol/run_skip/json/` | 重命名+移动 | | `pre_src/` | `cobol/pre_src/` | 移动文件 | | `coverage/` | `coverage/` | 保持不变 | | `logs/` | `logs/` | 保持不变 | | `gcov/` | `gcov/` | 保持不变 | | `data/` | `data/` | 保持不变 | ### 5.2 兼容性处理 ```python def _ensure_cobol_dir_structure(runtime_dir): """确保cobol目录结构存在,兼容旧版""" cobol_dir = runtime_dir / "cobol" if not cobol_dir.exists(): # 检查是否是旧版结构(main/直接在runtime_dir下) old_main = runtime_dir / "main" if old_main.exists(): # 迁移到新结构 shutil.move(str(old_main), str(cobol_dir / "main")) ``` ## 六、黑盒测试映射 ### 6.1 YAML配置示例 ```yaml # config/programs/KIN08DBU.yaml runs: - id: normal sysin: - { dd: KIN08S01, content: "..." } - id: no_period sysin: - { dd: KIN08S01, content: "..." } - id: insert_error inject_duplicate_pk: true sysin: - { dd: KIN08S01, content: "..." } - id: sql_delete_error sysin: - { dd: KIN08S01, content: "..." } - id: sql_select_error sysin: - { dd: KIN08S01, content: "..." } ``` ### 6.2 目录映射 | 场景ID | COBOL目录 | Java目录 | 日志文件 | gcov目录 | 数据库文件 | |--------|-----------|----------|----------|----------|------------| | normal | `cobol/run_normal/` | `java/run_normal/output/` | `logs/run_normal.log` | `gcov/run_normal/` | `data/kin_normal.db` | | no_period | `cobol/run_no_period/` | `java/run_no_period/output/` | `logs/run_no_period.log` | `gcov/run_no_period/` | `data/kin_no_period.db` | | insert_error | `cobol/run_insert_error/` | `java/run_insert_error/output/` | `logs/run_insert_error.log` | `gcov/run_insert_error/` | `data/kin_insert_error.db` | | sql_delete_error | `cobol/run_sql_delete_error/` | `java/run_sql_delete_error/output/` | `logs/run_sql_delete_error.log` | `gcov/run_sql_delete_error/` | `data/kin_sql_delete_error.db` | | sql_select_error | `cobol/run_sql_select_error/` | `java/run_sql_select_error/output/` | `logs/run_sql_select_error.log` | `gcov/run_sql_select_error/` | `data/kin_sql_select_error.db` | ### 6.3 黑盒测试执行流程 1. **编译阶段**:编译一次,全场景共享 `.exe` 和 `.gcno` 2. **场景执行**:对每个场景独立执行 - 生成场景特定输入数据 - 初始化场景特定DB - 运行COBOL程序 - 收集场景特定gcov数据 3. **Java执行**:使用最后一个场景的DB结果 4. **验证比对**:比较COBOL和Java输出 5. **覆盖率合并**:合并多轮gcov数据,生成覆盖率报告 ### 6.4 测试报告生成 | 报告类型 | 生成方式 | 输出位置 | |----------|----------|----------| | 覆盖率HTML报告 | `orchestrator_db.generate_coverage_report()` | `coverage/_coverage.html` | | 测试结果JSON | `orchestrator.run_all()` | `reports//result.json` | | 测试报告HTML | `ReportGenerator.generate_html()` | `reports//report.html` | | 机器可读JSON | `ReportGenerator.generate_machine_json()` | `reports//machine.json` | ## 七、代码修改清单 ### 7.1 orchestrator_db.py | 行号 | 修改内容 | 说明 | |------|----------|------| | 103 | `runtime_dir = v3_root / "output" / program_id / "cobol"` | 添加cobol子目录 | | 594-596 | `run_label = "main" if not scenario else f"run_{scenario.id}"` | 统一场景目录命名 | | 626-628 | `env_overrides` 路径改为 `"input"` 和 `"output"` | 移除main/层级 | | 686 | `log_dir = self.runtime_dir.parent / "logs"` | 日志目录移到根目录 | | 700 | `gcda_dst_dir = gcov_dir / run_label` | 统一gcov目录命名 | | 769 | `output_dir = v3_root / "output" / self.program_id / "coverage"` | 覆盖率报告移到根目录 | | 779 | `gcov_dir = self.runtime_dir.parent / "gcov"` | gcov目录移到根目录 | | 975 | `java_out = self.runtime_dir.parent / "java" / run_label / "output"` | Java输出目录 | | 1016 | `self.java_output_path = self.runtime_dir.parent / "java" / run_label / "output"` | Java输出路径 | ### 7.2 cobol_testgen/__init__.py | 行号 | 修改内容 | 说明 | |------|----------|------| | 1759 | `outpath = prog_outdir / 'cobol' / 'main' / 'json'` | JSON输出路径 | | 1769 | `prog_outdir / 'cobol' / 'main' / 'input'` | 输入文件路径 | | 1776 | `prog_outdir / 'cobol' / 'main' / 'input'` | 子程序输入路径 | | 1796 | `prog_outdir / 'cobol' / 'run_skip' / 'json'` | Skip JSON路径 | | 1802 | `prog_outdir / 'cobol' / 'run_skip' / 'input'` | Skip输入路径 | ### 7.3 cobol_testgen/runner.py | 行号 | 修改内容 | 说明 | |------|----------|------| | 425-426 | `Path(outdir) / 'cobol' / 'main' / 'input'` | 主场景输入路径 | | 425-426 | `Path(outdir) / 'cobol' / 'main' / 'output'` | 主场景输出路径 | | 430-431 | `Path(outdir) / 'cobol' / 'run_skip' / 'input'` | Skip场景输入路径 | | 430-431 | `Path(outdir) / 'cobol' / 'run_skip' / 'output'` | Skip场景输出路径 | ### 7.4 runners/gixsql_runner.py | 行号 | 修改内容 | 说明 | |------|----------|------| | 308 | `debug_dir = ... / "cobol" / "pre_src"` | 预处理源码路径 | ### 7.5 orchestrator.py | 行号 | 修改内容 | 说明 | |------|----------|------| | 142 | `co = Path(f"output/{cfg.program}/cobol/main/output/cobol_out.bin")` | COBOL输出路径 | | 159 | `java_out_dir = Path("output") / cfg.program / "java" / "main" / "output"` | Java输出路径 | | 200 | `rd = Path(f"output/{vr.program}/reports") / vr.timestamp` | 报告输出路径 | ## 八、测试验证 ### 8.1 单元测试 运行现有单元测试确保向后兼容: ```bash python -m pytest tests/ -v ``` ### 8.2 集成测试 运行黑盒测试验证目录结构: ```bash cd test-data python s15_coverage_verification.py python s30_db_e2e.py ``` ### 8.3 手动验证 检查目录结构是否正确: ```bash # 检查单轮程序 ls -la output/KIN01INP/ ls -la output/KIN01INP/cobol/main/ ls -la output/KIN01INP/java/main/output/ # 检查多轮程序 ls -la output/KIN08DBU/ ls -la output/KIN08DBU/cobol/run_normal/ ls -la output/KIN08DBU/java/run_normal/output/ ``` ## 九、注意事项 1. **env_overrides 路径**:修改后需要确保COBOL运行时能找到正确的文件 2. **SQLite数据库路径**:多轮场景的DB文件需要按场景命名 3. **gcov数据合并**:多轮场景的gcov数据需要正确合并 4. **向后兼容**:需要处理旧版目录结构的迁移 5. **测试覆盖**:修改后需要运行所有测试确保功能正常 --- **文档版本**:v1.0 **创建日期**:2026-09-05 **最后更新**:2026-09-05