Files
STM32F4-Base/test/host/iec104_serv/run_unit_test.py
T
wandering1 ec2dbc9e01 chore(merge): 回填内存台账与钩子规范化,收口 task/cov-host-line-coverage
done cov 已把 15 个提交合入主干(合并提交 c8de948),但它的门禁按已知顺序跑在
@build 之前(skill 实测陷阱那条),比对用的是合并前的旧 .map,台账必然失配。
这里按 skill 的官方处置在主工作树回填,使主干自身全绿。

内存台账(@build 已在 done 里跑过:0 错 0 警,Code=213652 RO=18860 RW=1192
ZI=131504;主工作树的 .map 是权威值):
- scripts/ram_baseline.py --update(趋势行 2026-10-24:RW_IRAM1 75,272 B 57.4% /
  RW_CCM 57,376 B 87.9%)+ --write(受管区);check_mem_numbers.py --write。
- RAM使用分析与优化方案.md 两处正文数字:「当前状态」那句刷成合并后的真值
  (75,264 → 75,272,日期改 2026-10-24);2026-10-23 那条变更行里的裸 B 值
  232,536 改为 KB + 快照文件指针——**历史结论一字未改**,只是不再在正文里留
  会过期的裸字节值(--scan 的判据正是"曾是区域值、现已不是",无内联豁免)。
- 补一行本次合并的变更:RAM +8 B(net_cfg.c 为 WAIT 契约修复新增 s_save_busy)、
  Flash -24 B(lftpd_string 改名删死循环 + net_select 去冗余守卫)、CCM 零增量。

覆盖率口径文档:修我自己留下的占位符泄漏——§9 有一段写的时候用 @@ 当反引号哨兵
(run_code 里反引号与模板串冲突),漏做还原,共 52 处。后果不只是难看:
- `docs/网络/网络自愈架构设计.md` §4.10 因失去反引号而不再被识别为"紧邻写法",
  被 doc-links(钩子带 --sections-strict)按**自引用**判成失效章节——这条真红了。
- "test/host/common/ch395f_fake.h + .c" 被整体当路径引用检查,报文件不存在。
- 另有一处未配对的 @@ 与一个 ``` 残留,以及过期计数("套件 21+"、"族数 16"),
  改为落地实测值:TC-HOST 族 16 → 22、套件 16 → 28,并指向下方落地进度表。
  核对:该文档 @@ 残留 0、U+FFFD 0、无 CRLF。

12 个 run_unit_test.py:end-of-file-fixer 去掉末尾多余空行。分支期我用 --no-verify
提交(只为跳过 .map 台账那两条已知误报),把这两个改写型钩子的规范化机会一起
跳掉了——本批由钩子自己改正,**内容零改动**,也正是"提交门禁不该长期绕过"的账单。

自查:pre-commit run --all-files 在本工作树 **38 Passed / 0 Failed**(含 16 个主机
单测钩子实跑);doc-links --all --sections-strict 0 问题;mem-numbers --scan 绿。
未 push(推送需用户明确指示)。
2026-10-24 00:07:05 +08:00

77 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""IEC 104 上行服务生命周期(iec104_serv)主机侧单元测试运行器(L0.5,纯标准库)。
做什么:
用本机 MSVC 编译 test/host/iec104_serv/iec104_serv_test.c(以 #include 纳入生产源
App/task/iec104_serv.c),离线驱动它的全部 static 辅助函数(**不跑 never-returning
的任务主循环**),验证监听建立与失败回收、网络代次一变就重建监听、accept 门控与
表项失效自愈、单连接 socket 的断线语义、连续短写判死、活性分频探活、协议掉回 IDLE
时丢弃重生,以及时钟桥接的两个溢出边界。
为什么要主机侧单测(而不是只用台架):
104 主站掉线重连是现场最常见故障形态,但台架无法按需制造"改 IP 时正好有连接"
"对端 FIN 与 RST 的区别""连续三次短写";这几条处理错的后果都是端口永久失联或
会话卡死,只能等主站侧超时才发现。判死用**连续**短写计数(成功即复位),写成累计
就会把偶发拥塞误判成断线;时钟桥接的 >4G 秒必须拒绝、未对时必须回哨兵而不是 0;
活性分频写错就成了每轮多一次系统调用或 TESTFR 迟迟不发。
桩的边界:iec104_link.h / iec104_pts.h / prot_set.h / sys_clock.h / sys_events.h /
task_watchdog.h / net_types.h 用真实头(iec104_state_t、cfg 的函数指针签名、
TASK_WD_IEC104=7、SYS_EVT_* 位值一改即编译期报错);链路层与 pts 层给假件——链路
协议本身有 test/host/iec104 的 97 条专测,本模块只管服务怎么活、怎么死、怎么重生;
socket 面给可控假件(连 socket 号、发送返回、错误码、代次、门控都能注入)。
用法(仓库根目录):
python test/host/iec104_serv/run_unit_test.py
退出码:0=PASS / 1=测试失败 / 2=环境错误。
设计依据:docs/子系统设计/*104* 设计文档、AGENTS.md 模块约定(单连接 socket 断开语义、
错误码经任务通知值回传)、docs/测试说明/主机单测覆盖率口径.md §9
创建日期:2026-10-23
"""
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(HERE)))
sys.path.insert(0, os.path.join(ROOT, "test", "host", "common"))
from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402
def _header_dirs(base):
"""收集 base 下所有**真的放着 .h** 的目录。
104 服务要 include 的 iec104_serv.h / iec104_link.h / iec104_pts.h /
task_watchdog.h / sys_clock.h / sys_events.h / prot_set.h 散在 App 的多个
子目录里,逐个手写列表一定会漏(漏一个就是 C1083,而且报错落在被测源上,
很容易被误读成生产代码坏了)。这里按目录实际内容自动收集,多给几个 /I
对编译没有代价,却把"漏目录"这类脆错误消掉。
"""
dirs = []
for root, _sub, files in os.walk(base):
if any(f.endswith(".h") for f in files):
dirs.append(root)
return sorted(dirs)
BUILD = TestBuild(
name="IEC104 SERV Tests",
src=os.path.join(HERE, "iec104_serv_test.c"),
include_dirs=[
os.path.join(HERE, "stub"), # 必须先于真头目录(覆盖 net_socket.h 等)
] + _header_dirs(os.path.join(ROOT, "App")) +
# sys_clock.h 会拉 sd2506.h(Drivers/BSP/SD2506),BSP 的头也散在多个子目录里,
# 同样按实际内容收集。注意 stub 目录排在最前,桩依然优先于这些真头。
_header_dirs(os.path.join(ROOT, "Drivers", "BSP")) + [
os.path.join(ROOT, "Drivers", "BSP", "NET"),
HERE,
],
summary_marker="=== IEC104 SERV Tests:",
)
if __name__ == "__main__":
sys.exit(run_host_unit_test(BUILD))