Files
STM32F4-Base/test/host/lftpd_io/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

63 lines
3.2 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 -*-
"""FTP 文件 IO 层(lftpd_io + lftpd_string)的主机侧单元测试运行器(L0.5,纯标准库)。
做什么:
用本机 MSVC 编译 test/host/lftpd_io/lftpd_io_test.c(同时纳入生产源
Drivers/BSP/NET/lftpd/lftpd_io.c 与 lftpd_string.c),在 PC 上离线验证路径规范化
(含 ".." 越权钳位)、FatFs 路径映射、单文件槽守卫、卷锁获取/释放时机、等锁期间
喂狗、分配失败返回 NULL 且不泄漏,以及 FTP 命令行 trim。失败即非 0 退出。
工具链与判定委托 test/host/common/unit_test_harness.py。
为什么要主机侧单测(而不是只用台架):
越权钳位是安全属性(FTP 客户端可发任意带 ".." 的路径),真机上没有第二个文件系统
可逃、测不出来;卷锁"成功不释放、失败必释放"写反了就是 defaultTask 永远拿不到卷
或传输中途卷被人改;等锁循环漏喂狗就是整机复位——三条都只在真机偶发、日志看不出
根因。分配失败分支更只有假堆能构造(模拟器宿主 CRT 永不失败)。
桩的边界:ff.h / vol_lock.h / lftpd.h / private/*.h 全用**真实头**(FRESULT、FA_*、
函数签名一律原汁);FreeRTOS.h 与 dbg_log.h 用本目录桩;f_open、卷锁、喂狗、
pvPortMalloc/vPortFree 由测试单元给可控实现(假堆可注入分配失败)。
read/write/close/stat/unlink/readdir 未列入本批:要先把假 FIL/FILINFO 的字段语义
做实,否则断言落在假件自己写的规则上(详见测试单元文件头"未覆盖")。
用法(仓库根目录):
python test/host/lftpd_io/run_unit_test.py
退出码:0=PASS / 1=测试失败 / 2=环境错误。
设计依据:docs/内存管理/RAM使用分析与优化方案.md §4.2.1、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)))
sys.path.insert(0, os.path.join(ROOT, "test", "host", "common"))
from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402
# 顺序敏感:stub 必须最先(覆盖 FreeRTOS.h / dbg_log.h)。
# lftpd_io.c 里 include 的是 "private/lftpd_io.h" 与 "lftpd.h",故给出 lftpd 目录;
# vol_lock.h 在 App/fs,ff.h 在 Lib/FatFs(与 test/host/nand_port 同一份真实头)。
BUILD = TestBuild(
name="LFTPD IO Tests",
src=os.path.join(HERE, "lftpd_io_test.c"),
include_dirs=[
os.path.join(HERE, "stub"),
os.path.join(ROOT, "Drivers", "BSP", "NET", "lftpd"),
os.path.join(ROOT, "App", "fs"),
os.path.join(ROOT, "Lib", "FatFs"),
HERE,
],
# /D_CRT_SECURE_NO_WARNINGS:生产 lftpd_io.c 里的 strcpy/strcat/strncpy 在
# MSVC 下刷 C4996 弃用告警(ARMCC 不报,且 lftpd 不在 coding-standard 范围内),
# 这是纯主机侧噪音;关掉它才能让本模块的编译输出保持可读。
extra_flags=["/D_CRT_SECURE_NO_WARNINGS"],
summary_marker="=== LFTPD IO Tests:",
)
if __name__ == "__main__":
sys.exit(run_host_unit_test(BUILD))