#!/usr/bin/env python3 # -*- coding: utf-8 -*- """网络配置(net_cfg)的主机侧纯逻辑单元测试运行器(纯标准库)。 做什么: 用本机 MSVC 编译 test/host/net_cfg/net_cfg_test.c(它以 #include 纳入 **生产源文件** Drivers/BSP/NETCFG/net_cfg.c),在 PC 上离线跑出厂默认、 注册幂等、load/save 错误通道、跨任务保存交接状态机、MAC 三态优先级、 IPv4 定长格式化,失败即非 0 退出。零硬件、零烧录、毫秒级。 工具链探测 / INCLUDE-LIB 拼接 / 编译运行 / 退出码判定全部委托给通用 harness `test/host/common/unit_test_harness.py`(本文件只做声明)。 为什么要主机侧单测(而不是只用台架): 保存链跨三个任务(uiTask 投递 → defaultTask 写盘 → netTask 重建网络): "写盘期间又投递一次"与"写盘失败却重建网络"这两条真机上要靠手速 + 故障注入 才碰得到,错了就是"改 IP 不生效 / 保存失败网络被无端重建";MAC 三态优先级 写错会静默用错 MAC(同网段冲突,只表现为偶发丢包);net_cfg_fmt_ipv4 的定长 11 字符是 UI 光标按固定偏移定位的前提。三条都在 PC 上钉死,且不占 MCU RAM。 桩的边界(细节见测试单元文件头): 配置文件引擎用**真实头**(接口原汁)+ 测试单元内的可控实现;[ftp] 段的 ftp_cfg_register 只计数——它归 test/host/ftp_cfg/ 模块,两边不互相顶包。 sntp_cfg.c 是分层门禁后的纯数据本体,随 net_cfg.c 一并编译入 TU, [sntp] 段描述符(键表/偏移/工厂默认)由假引擎截获断言——段注册契约 的机器钉在本模块(TC-NETCFG-005/006b..d/007)。 用法(仓库根目录): python test/host/net_cfg/run_unit_test.py 或统一用 .venv: & '.venv\Scripts\python.exe' test/host/net_cfg/run_unit_test.py 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 设计依据:docs/子系统设计/网络配置说明.md、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期: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))) # harness 位于 test/host/common/ sys.path.insert(0, os.path.join(ROOT, "test", "host", "common")) from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402 # 顺序敏感:stub 必须**先于**生产目录,才能覆盖 dbg_log.h。cfg_file.h 用真实头 # (接口契约原汁,引擎改签名即编译期报错),net_cfg.h / ftp_cfg.h 亦用真实头。 BUILD = TestBuild( name="NET Config Tests", src=os.path.join(HERE, "net_cfg_test.c"), include_dirs=[ os.path.join(HERE, "stub"), os.path.join(ROOT, "Drivers", "BSP", "NETCFG"), os.path.join(ROOT, "App", "cfg"), HERE, ], summary_marker="=== NET Config Tests:", ) if __name__ == "__main__": sys.exit(run_host_unit_test(BUILD))