90db528032
W1-0 台账三件套:scripts/ram_baseline.py(四模式)+ ram_baseline.tsv 趋势 + docs/内存管理/RAM预算台账.md + pre-commit mem-budget 钩子(RW_IRAM1/RW_CCM >92% 即 FAIL + Top-10 附表);审查报告 §5.5 三条闭环。 B4 IEC 60870-5-104 上行(被控站,TCP 2404):App/protocol/iec104/ 三模块 (asdu 编解码 / pts 点表+数据源 vtable / link APCI+FSM,纯逻辑零 I/O)+ App/task/iec104_serv.c(iec104Task,NET_READY 屏障 100ms 分片喂位)。 82 断言 L0.5 全绿 + iec104-unit-test 钩子(第 31 钩子); 设计说明 docs/子系统设计/IEC104上行设计说明.md 全量回填。 B5 protectTask(L3 板端接线):App/task/protect_task.c——20ms 判据节拍 prot_elm_run + L5-4 采样故障闭锁(adc_health 电平位→元件复位)+ L5-1 定值 校验和巡检;新增 prot_elm_request_reset() 收口跨上下文复归(104 YK11 落请求、 eval 头部消费);定值/元件初始化移入 app_main_init(内核前)。TC-PE-010 (prot_elm 28 用例)。 门禁与内存:TASK_WD_PROTECT=8 入 required_mask(产品 0x77→0x1F7、HW 层 0x1F5,看门狗单测 39 断言同步);FreeRTOS 堆 48→56KB(.ioc L1 参数 + FreeRTOSConfig.h 同步,RAM预算台账 §6 登记配额 48→56KB)。 ZI 144,008→152,204(+8,196 B = 堆 +8KB,B5 扩容);Code=204,348。 stack_report:protectTask 512 words 静态链 872 B/余 57%、iec104Task 640 words 1456 B/余 43% 均 PASS;RW_IRAM1 73.1% / RW_CCM 87.9%(<92%)。 验证:@build 0 错 0 警;ci_local 全绿(31 钩子 + 13 主机侧单测); doc-links 135 文档 PASS。登记簿 B4/B5 销项、W1 波次完成;保护规划/看门狗 说明/AGENTS(9 任务)/RAM 三文档全部同步。 遗留(验收窗口,非代码空洞):台架第三方 104 主站往返(送检窗口)、 标准源注入动作判据、@test PROT 锚点 + protect 栈水位 + 新堆 min_ever 复测。
125 lines
8.9 KiB
Markdown
125 lines
8.9 KiB
Markdown
# test/host/ — 主机端测试脚本
|
||
|
||
> PC 侧的测试驱动与判读脚本(Python,跑在开发机上,经串口/网络与目标板交互)。
|
||
|
||
## 文件一览
|
||
|
||
### 流程与判读
|
||
|
||
| 脚本 | 作用 |
|
||
|---|---|
|
||
| `run_boot_test.py` | **`@test` 一键闭环**:开串口+清日志 → 烧录 → wait-idle → `verify_log` 校验(退出码 0=PASS) |
|
||
| `verify_log.py` | **日志标记校验**:Required / Forbidden 标记 → PASS / FAIL;可选 `--require-suite-summary` 校验套件汇总行(`=== <名称>: N/M PASSED (failed=0) ===` 且 `N>0`),抓"没跑到汇总行/断言数为 0"的盲区(T-2) |
|
||
| `e02_probe.py` | E-02 专项探针(错误码传播审计) |
|
||
|
||
### 网络 / FTP
|
||
|
||
| 脚本 | 作用 |
|
||
|---|---|
|
||
| `ch395f_socket_test.py` | Socket 通信测试(回显服务器 / 文件收发) |
|
||
| `ftp_test.py` | FTP 基本功能测试 |
|
||
| `ftp_up_dl_test.py` | FTP 上传下载测试 |
|
||
| `ftp_speed_test.py` | FTP 传输速度测试 |
|
||
| `ftp_capture.py` | FTP 流量抓取 |
|
||
| `ftp_regression.py` | FTP 回归套件 |
|
||
|
||
### 时间 / 时延
|
||
|
||
| 脚本 | 作用 |
|
||
|---|---|
|
||
| `latency_peer.py` | 链路时延测试的 PC 对端(peer) |
|
||
| `time_sync_server.py` | 时间同步推送服务(对时源) |
|
||
|
||
### 主机侧单元测试(纯逻辑,无硬件)
|
||
|
||
| 文件 | 作用 |
|
||
|---|---|
|
||
| `common/unit_test_harness.py` | **通用单测 harness**(L0.5):探测 MSVC → 拼 `INCLUDE`/`LIB` → 编译 → 运行 → 判定退出码。各模块运行器只做**声明式**配置(`TestBuild`),不含工具链细节 |
|
||
| `watchdog/run_unit_test.py` | **看门狗判定状态机单测**:声明 `TestBuild` 后调 harness,用 MSVC 离线编译真实 `App/util/task_watchdog.c`(可观测桩驱动),39 用例穷举边界。零硬件、秒级(退出码 0=PASS/1=FAIL/2=环境错误) |
|
||
| `watchdog/watchdog_test.c` | 测试单元本体(`#include` 生产源码 + 平台钩子桩) |
|
||
| `watchdog/stub/` | 桩头文件(`main.h`/`iwdg.h`/`dbg_log.h`),覆盖 MCU 版以在 PC 上编译 |
|
||
| `sys_clock/run_unit_test.py` | **系统时钟换算单测**:离线编译真实 `App/util/sys_clock.c`,以可控时钟 + 阴影 RTC 桩驱动,100 断言点覆盖闰年/月末/世纪/2038 上限/星期/30 天惰性再基准化/RTC 故障降级 |
|
||
| `sys_clock/sys_clock_test.c` | 测试单元本体(`#include` 生产源码 + 强符号桩;**不改生产代码**) |
|
||
| `sys_clock/stub/` | 桩头文件(`main.h`/`FreeRTOS.h`/`task.h`/`dbg_log.h`),覆盖 MCU 版以在 PC 上编译 |
|
||
| `cfg_file/run_unit_test.py` | **配置引擎单测**:离线编译真实 `App/cfg/cfg_file.c`,以**内存虚拟文件系统**桩驱动,149 断言点覆盖 INI 解析/四种值类型编解码/段注册校验/load-save-poll 契约/超长守卫/故障注入 |
|
||
| `cfg_file/cfg_file_test.c` | 测试单元本体(`#include` 生产源码 + `cfg_store_*` 内存 FS 后端桩;**不改生产代码**) |
|
||
| `cfg_file/stub/` | 桩头文件(`dbg_log.h`),覆盖 MCU 版以在 PC 上编译 |
|
||
| `phasor/run_unit_test.py` | **相量层(L2)单测**:离线编译真实 `App/algo/phasor.c` + `sample_ring.c`(**无需任何桩**,纯算法),57 用例覆盖傅氏系数表 / 幅值·相位 / 谐波抑制与提取 / 频偏 / 采样环 / 双区原子交换 |
|
||
| `phasor/phasor_test.c` | 测试单元本体(`#include` 两个生产源码 + 合成任意波形) |
|
||
| `adc_input/run_unit_test.py` | **ADC 输入层(L1)单测**:离线编译真实 `App/algo/adc_input.c`,**101** 用例给每个 Rank 注入互异码值**逐通道钉死映射**,并覆盖 DMA 挂载失败 / **乒乓半区选择(撕裂帧防线)** / 超拍丢帧 / 停摆 / HAL 回调句柄守卫 / **停摆拍陈旧帧** / 参数错等真机难复现分支 |
|
||
| `adc_input/adc_input_test.c` | 测试单元本体(`#include` 生产源码 + HAL / TPAFE 可注入桩) |
|
||
| `adc_input/stub/` | 桩头文件(`adc.h` / `tpafe5160.h`) |
|
||
| `vol_lock/run_unit_test.py` | **卷锁单测**:离线编译真实 `App/fs/vol_lock.c`,33 断言点覆盖创建 / 获取 / 释放契约(**fail-open 不变量**:创建失败仍返回 1 且零阻塞)/ 幂等 / 超时透传 |
|
||
| `vol_lock/vol_lock_test.c` | 测试单元本体(`#include` 生产源码 + CMSIS 互斥桩) |
|
||
| `vol_lock/stub/` | 桩头文件(`cmsis_os.h`) |
|
||
| `time_sync/run_unit_test.py` | **时间同步单测**:离线编译真实 `App/sync/time_sync.c`,80 断言点覆盖分片喂狗延时 / 监听退避 / 时间包重组(半包·粘连·EOF·真错·预算耗尽·tick 回绕)/ 任务主循环(**N-17 的全部逻辑贡献者**) |
|
||
| `time_sync/time_sync_test.c` | 测试单元本体(`#include` 生产源码 + 网络 / 事件 / RTOS 可脚本化桩 + `longjmp` 跳出 `for(;;)` 任务循环) |
|
||
| `time_sync/stub/` | 桩头文件(`FreeRTOS.h` / `task.h` / `cmsis_os2.h` / `net_socket.h` / `sys_clock.h` / `sys_events.h` / `dbg_log.h`) |
|
||
| `iec104/run_unit_test.py` | **IEC 60870-5-104 协议栈单测(B4)**:离线编译真实 `App/protocol/iec104/` 三模块 + 数据源(prot_set/prot_elm/phasor/sample_ring),**82** 用例覆盖 CP56 往返 / APCI 半帧·粘帧·坏帧 / STARTDT 握手 / 总召分片+RBT / COV 死区 / k=12 窗满 / w=8 触发 S / t1·t2·t3 / N(R) 倒退判故障 / 遥控·定值两段式与 PN / C_CS / 未知类型·地址错误应答 |
|
||
|
||
> 详见 `docs/测试说明/看门狗单元测试说明.md`、`docs/测试说明/系统时钟单元测试说明.md`、
|
||
> `docs/测试说明/配置文件单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md`、
|
||
> `docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/卷锁单元测试说明.md`、
|
||
> `docs/测试说明/时间同步单元测试说明.md`;
|
||
> harness 用法见 [`common/README.md`](common/README.md)。
|
||
> 已挂 pre-commit 钩子 `watchdog-unit-test`、`sys-clock-unit-test`、`cfg-file-unit-test`、
|
||
> `phasor-unit-test`、`adc-input-unit-test`、`vol-lock-unit-test`、`time-sync-unit-test`。
|
||
|
||
## 运行方式
|
||
|
||
```bash
|
||
# @test 一键闭环(推荐,需真机)
|
||
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py
|
||
|
||
# 测试套件构建的回归:要求套件跑到汇总行且断言数 > 0(T-2)
|
||
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py `
|
||
--required "=== Storage Tests:" --forbidden "ERROR;HardFault;[ERR]" `
|
||
--require-suite-summary "Storage Tests"
|
||
|
||
# 看门狗判定状态机单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/watchdog/run_unit_test.py
|
||
|
||
# 系统时钟换算单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/sys_clock/run_unit_test.py
|
||
|
||
# 配置引擎单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/cfg_file/run_unit_test.py
|
||
|
||
# 相量层(L2)单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/phasor/run_unit_test.py
|
||
|
||
# ADC 输入层(L1)单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/adc_input/run_unit_test.py
|
||
|
||
# 卷锁单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/vol_lock/run_unit_test.py
|
||
|
||
# 时间同步单测(纯逻辑,无需真机)
|
||
& '.venv\Scripts\python.exe' test/host/time_sync/run_unit_test.py
|
||
```
|
||
|
||
> 串口端口配置在 `.serialtest/config.json`(单一配置源,当前 COM6/115200)。
|
||
|
||
## ⚠️ 注意
|
||
|
||
- **PYTHONPATH/路径敏感**:脚本按仓库根相对路径读写,**从仓库根执行**
|
||
- 本目录**被 pre-commit 门禁的 cppcheck / 代码规范排除**(`test/` 豁免);
|
||
但各模块的 `run_unit_test.py` 自身**作为独立钩子**参与门禁(见上,共 7 个)
|
||
- 台架探针族(TCP 复连 / FTP 中止等)在 `MDK-ARM/*.py`,与本目录分工不同
|
||
- 全部主机侧单测(`watchdog/`、`sys_clock/`、`cfg_file/`、`phasor/`、`adc_input/`、
|
||
`vol_lock/`、`time_sync/`)都需要本机装有 MSVC(VS2019/2022/2026 的 C++ 工具链);
|
||
无则脚本报环境错误(退出码 2)
|
||
|
||
## 相关文档
|
||
|
||
- `docs/测试说明/自动化测试流程.md` — `@test` 细节与失败模式
|
||
- `docs/测试说明/测试开发标准流程.md` — 测试分层与门禁
|
||
- `docs/测试说明/看门狗单元测试说明.md` — 主机侧单测(用例 / 平台层 / 扩展方法)
|
||
- `docs/测试说明/系统时钟单元测试说明.md` — 系统时钟换算单测(用例 / 桩 / Zeller 缺陷记录)
|
||
- `docs/测试说明/配置文件单元测试说明.md` — 配置引擎单测(内存 FS 桩 / 抓出的 P0)
|
||
- `docs/测试说明/ADC输入层单元测试说明.md` — ADC 输入层单测(逐 Rank 钉死映射)
|
||
- `docs/测试说明/相量层单元测试说明.md` — 相量层单测(傅氏系数 / 双区交换)
|
||
- `docs/测试说明/卷锁单元测试说明.md` — 卷锁单测(fail-open 不变量)
|
||
- `docs/测试说明/时间同步单元测试说明.md` — 时间同步单测(N-17 逻辑贡献者)
|
||
- `docs/测试说明/CH395F_Test_Guide.md`、`FTP_Test_Guide.md`
|