- 修复 orchestrator_db.py: Java Runner 未传递 command_line 参数导致 ABEND - 新增 DB-Java 文件式运行 + DB 表比对功能 - 优化输出目录结构: output/<PROGRAM_ID>/cobol/ - 新增测试文件: test_java_comparison.py, test_java_e2e.py - 更新 AI 使用日志
401 lines
13 KiB
Markdown
401 lines
13 KiB
Markdown
# V3系统目录结构设计文档
|
||
|
||
## 一、目录结构概述
|
||
|
||
V3系统采用统一的目录结构来组织COBOL和Java的输出结果,确保所有程序的输出文件都位于同一个根目录下,便于管理和比较。
|
||
|
||
## 二、目录结构规范
|
||
|
||
### 2.1 标准目录结构
|
||
|
||
```
|
||
output/<PROGRAM_ID>/
|
||
├── cobol/ # COBOL输出(所有组)
|
||
│ ├── main/ # 单轮/默认场景
|
||
│ │ ├── input/ # COBOL输入flat文件
|
||
│ │ ├── output/ # COBOL输出flat文件
|
||
│ │ └── json/ # Java验证用JSON
|
||
│ ├── run_skip/ # 跳过场景
|
||
│ │ ├── input/
|
||
│ │ ├── output/
|
||
│ │ └── json/
|
||
│ ├── run_<scenario_id>/ # 多轮场景
|
||
│ │ ├── input/
|
||
│ │ ├── output/
|
||
│ │ └── json/
|
||
│ └── pre_src/ # 预处理源码
|
||
├── java/ # Java输出(所有组)
|
||
│ ├── main/ # 对应cobol/main的Java输出
|
||
│ │ └── output/
|
||
│ ├── run_skip/ # 对应cobol/run_skip的Java输出
|
||
│ │ └── output/
|
||
│ └── run_<scenario_id>/ # 对应cobol/run_*的Java输出
|
||
│ └── output/
|
||
├── coverage/ # 覆盖率报告(全局)
|
||
├── logs/ # 日志(全局)
|
||
│ ├── main.log
|
||
│ ├── run_skip.log
|
||
│ └── run_<scenario_id>.log
|
||
├── gcov/ # gcov数据(按场景分离)
|
||
│ ├── run_main/
|
||
│ ├── run_skip/
|
||
│ └── run_<scenario_id>/
|
||
├── data/ # SQLite数据库(按场景分离)
|
||
│ ├── kin.db # 单轮场景
|
||
│ └── kin_<scenario_id>.db # 多轮场景
|
||
└── reports/ # 测试报告
|
||
└── <timestamp>/
|
||
├── result.json
|
||
├── report.html
|
||
└── machine.json
|
||
```
|
||
|
||
### 2.2 目录命名规则
|
||
|
||
| 目录 | 命名规则 | 说明 |
|
||
|------|----------|------|
|
||
| `cobol/main/` | 固定名称 | 单轮/默认场景 |
|
||
| `cobol/run_skip/` | 固定名称 | 跳过场景(原 `skip/`) |
|
||
| `cobol/run_<id>/` | `run_` + 场景ID | 多轮场景 |
|
||
| `java/<对应cobol目录>/` | 与cobol目录对应 | Java输出 |
|
||
| `coverage/` | 固定名称 | 覆盖率报告 |
|
||
| `logs/` | 固定名称 | 日志文件 |
|
||
| `gcov/run_<id>/` | `run_` + 场景ID | gcov数据 |
|
||
| `data/` | 固定名称 | SQLite数据库 |
|
||
|
||
### 2.3 文件命名规则
|
||
|
||
| 文件类型 | 命名规则 | 示例 |
|
||
|----------|----------|------|
|
||
| COBOL输入文件 | `<PROGRAM_ID>R<NN>` | `KIN01R01`, `ZAN01R01` |
|
||
| COBOL输出文件 | `<PREFIX>W<NN>` | `KIN01W01`, `ZAN01W01` |
|
||
| JSON中介文件 | `<PROGRAM_ID>.json` | `KIN01INP.json` |
|
||
| 覆盖率报告 | `<PROGRAM_ID>_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/<PROGRAM_ID>/
|
||
├── cobol/
|
||
│ └── main/
|
||
│ ├── input/
|
||
│ ├── output/
|
||
│ └── json/
|
||
├── java/
|
||
│ └── main/
|
||
│ └── output/
|
||
├── coverage/
|
||
├── logs/
|
||
│ └── main.log
|
||
├── gcov/
|
||
│ └── run_main/
|
||
└── data/
|
||
└── kin.db
|
||
```
|
||
|
||
### 3.2 多轮场景
|
||
|
||
**定义**:程序有多次执行,通过YAML配置文件定义场景。
|
||
|
||
**目录结构**:
|
||
```
|
||
output/<PROGRAM_ID>/
|
||
├── 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/<PROGRAM_ID>/
|
||
├── 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_<id>/`。
|
||
|
||
### 4.2 SQLite数据库路径
|
||
|
||
```python
|
||
# 单轮场景
|
||
db_path = data/kin.db
|
||
|
||
# 多轮场景
|
||
db_path = data/kin_<scenario_id>.db
|
||
```
|
||
|
||
### 4.3 gcov数据路径
|
||
|
||
```python
|
||
# 单轮场景
|
||
gcov_dir = gcov/run_main/
|
||
|
||
# 多轮场景
|
||
gcov_dir = gcov/run_<scenario_id>/
|
||
```
|
||
|
||
## 五、向后兼容性
|
||
|
||
### 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/<PROGRAM_ID>_coverage.html` |
|
||
| 测试结果JSON | `orchestrator.run_all()` | `reports/<timestamp>/result.json` |
|
||
| 测试报告HTML | `ReportGenerator.generate_html()` | `reports/<timestamp>/report.html` |
|
||
| 机器可读JSON | `ReportGenerator.generate_machine_json()` | `reports/<timestamp>/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
|