b8c6a3dab0
BREAKING CHANGE: 删除公开 API net_relisten / net_resync_listen / net_can_accept 与消息类型 NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN。 生产调用者为零(仅看门狗文档与 iec104 门控),应用侧无迁移成本; 如有外部消费者须改用对账/pump 自动机制(见下)。 1. 对账①扩展为①②⑤(F-NET-2 缺口,先补缺口再删 API) net_reconcile_tick 新增 bad=5:本层 ESTABLISHED 且芯片 0x05/0x01 (Socket OPEN + TCP LISTEN,静默回收回监听、不发 DISCONNECT) → RESYNC 语义只修本层(state→LISTENING + last_peer_port 转登 + lost_conn_seen 清零 + 取消挂起 recv),**不发任何芯片命令** (纪律同 pump③ U11,run8 实证重下发会 170s 永拒)。 原判据①要求 TCP==CLOSED、②要求本层 LISTENING,均不命中此形态 ——此前生产无人认领(仅手动 API 能修)。 2. 删 net_relisten(net_socket.c 函数 + 消息分派 + 头文件声明) footgun:对健康监听器无条件 open→USE→close 自毁 ~1s(原注释自认); 与 pump(100ms)/D10(30ms) 完全重叠。 3. 删 net_resync_listen(同上;语义并入第 1 条) 4. 删 net_can_accept(net_socket.c + net_socket.h + sim 三处) 只认 ESTABLISHED 的旧门控把"监听器在服役、待 CONNECT"窗口全挡掉, :2404 丢 CONNECT 探针因此从不运行;iec104 门控迁 net_listener_armed。 5. timeSync :8888 会话收尾不再 net_close(同 fd 续 accept,监听跨会话 常驻;原 close→重建每会话一个 Trap 09 沉降窗)。server 脚本注释同步 新契约(PC 侧 2s 宽限后自行关闭)。 6. lftpd 应用层阻塞重试退役:lftpd_inet_listen 5 轮(500ms/2000ms,最坏 10s 阻塞 ftpTask) → 单次 + 失败即 425;cmd_pasv 3×200ms 同删。 就绪屏障已消除 Trap 09 启动形态,客户端自带传输重试语义。 台架实证修正(本提交内二次修复,务必留痕): - net_listener_armed 补齐 **ESTABLISHED 放行**。首版迁移只放行 LISTENING/CLOSED+残留,漏了 ESTABLISHED=单连接模型的"待 accept"电平 → iec104 200ms 任务周期抢不过对账② 的 ~400ms 去抖,对账②先 standalone accept 转 ESTABLISHED 后 armed=0 → 应用整场不 accept,18/18 检查全 FAIL (设备日志证据:sock1 standalone accept 后无 i104 accepted,直至对端 FIN 才由 closed-with-data 救回)。补放行后 18/18 PASS,且耗时 127s→8.3s。 该态 accept 必返 fd,无 RPC 风暴风险。 - 期间顺带验证 M3 无辜:sock1 suspect DISCONNECT on live conn 命中后 defer→对账①→closed-with-data accept 把未 accept 的 RX 数据救回, 正是 M3 设计意图(资产门保护)。 验证(全绿):@build 0/0(Code=209580;含 CH395F 套件+Phase13 全量重编 0/0 的编译验证);@test PASS(回读无差异);iec104 18/18(8.3s); n30 0/50;:21 @0ms 50/50 p50=512;:7003 50/50 p50=517;ftp_regression 11/11;Trap23 RST 5/5 + FIN 5/5;time_sync :8888 连续推送正常(RTC 更新、 无 [ERR])。文档同步:BSD 指南(§3.3/3.6/10.1/10.2/12 + 变更记录)、 函数调用关系、监听生命周期设计说明、IEC104 上行设计说明、模拟器差距 清单、链路延迟测试说明。 门禁说明:doc-links 工作树 junction 伪影按既定口径 SKIP;mem-budget 分支 .map 漂移同前;cppcheck/coding-standard 手跑 Passed。
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 回归套件 |
iec104_master.py |
IEC 60870-5-104 主站客户端(B6/B7):连设备 :2404 跑 STARTDT → 总召(actcon/四组背景扫描/actterm)→ 经 C_SE 两段写临时压低 OC1 定值确定性触发 YX16 变位(COT=3)→ 恢复 → YK11 两段式 → C_RD 读回;B7 持久化模式 --b7-pre/--b7-post/--b7-mark/--b7-check(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、定值与压板态跨复位保持(含非默认 7.5 往返);纯标准库,输出纯 ASCII 可直接重定向归档为台架证据(判据 exit 0/1/2) |
时间 / 时延
| 脚本 | 作用 |
|---|---|
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。 已挂 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。
运行方式
# @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