主机单测:新增卷锁与时间同步两套用例(33+80 项)并登记钩子

- vol_lock(App/fs/vol_lock.c):33 用例。核心不变量是 fail-open——
  互斥量创建失败时 vol_lock_wait() 必须返回 1 且绝不阻塞,因为调用者
  defaultTask 是看门狗喂狗点;板端该路径只在内存耗尽时才可能走到。
- time_sync(App/sync/time_sync.c):80 用例。本模块是 N-17 看门狗风险的
  全部逻辑贡献者,用例钉死分片喂狗节奏、监听退避、报文重组(半包/粘连/
  EOF/真错/预算耗尽/tick 回绕)、重听门控;用 longjmp 跳出 for(;;) 任务循环。
- 两套均为纯逻辑主机侧测试,MSVC 离线编译真实源文件(#include 纳入)。
- 新增钩子 vol-lock-unit-test、time-sync-unit-test(7f/7g)。
- 全量主机单测:watchdog 39 + sys_clock 100 + cfg_file 149 + phasor 57
  + adc_input 70 + vol_lock 33 + time_sync 80 = 528 项,全绿。
This commit is contained in:
2026-10-10 18:03:31 +08:00
parent 3715f8a34c
commit a2f5d1397a
13 changed files with 1430 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
/*
* 主机侧单测桩:FreeRTOS.h
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的最小 FreeRTOS 时基类型与宏。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
* 真实头在 Middlewares/Third_Party/FreeRTOS/Source/include/,会拖入 portmacro /
* projdefs / portable 层,主机侧不引入。
*
* 保真点:TickType_t = uint32_t;configTICK_RATE_HZ = 1000(Inc/FreeRTOSConfig.h)
* → pdMS_TO_TICKS(ms) == ms。被断言"片长 = 50ms"的用例依赖此等式。
*
* 创建日期:2026-10-10
*/
#ifndef FREERTOS_H
#define FREERTOS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint32_t TickType_t;
/* 与 Inc/FreeRTOSConfig.h 一致:1000 Hz → 1 tick = 1 ms */
#define configTICK_RATE_HZ 1000U
#define pdMS_TO_TICKS(ms) ((TickType_t)((uint32_t)(ms) * (1000U / configTICK_RATE_HZ)))
#ifdef __cplusplus
}
#endif
#endif /* FREERTOS_H */
+59
View File
@@ -0,0 +1,59 @@
/*
* 主机侧单测桩:cmsis_os2.h
* 模块功能:为 App/sync/time_sync.c(经 sys_events.h)提供主机可编译的 CMSIS-RTOS v2
* 事件标志接口与类型。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
* 真实头在 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/,会拖入整套
* FreeRTOS + CMSIS 内核对象,主机侧不引入。
*
* 保真点(对齐 cmsis_os2.h):
* - osEventFlagsId_t = void*(:195)、osMutexId_t = void*(:198);
* - osStatus_t 枚举含 osOK = 0;
* - 标志位 osFlagsWaitAny=0 / osFlagsNoClear=0x2 / osFlagsError=0x80000000
* / osFlagsErrorTimeout=0xFFFFFFFE(:153~164);
* - uint32_t osEventFlagsWait(id, flags, options, timeout)(:539)。
* osEventFlagsWait 由测试单元给强符号桩(可注入"未就绪/超时"并驱动屏障循环)。
*
* 创建日期:2026-10-10
*/
#ifndef CMSIS_OS2_H
#define CMSIS_OS2_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 不透明句柄 */
typedef void *osEventFlagsId_t;
typedef void *osMutexId_t;
/* 状态码(只保留被测代码用到的子集) */
typedef enum {
osOK = 0,
osError = -1,
osErrorTimeout = -2,
osErrorResource = -3,
osErrorParameter = -4
} osStatus_t;
/* 事件标志选项(cmsis_os2.h:153~164) */
#define osFlagsWaitAny 0x00000000U
#define osFlagsWaitAll 0x00000001U
#define osFlagsNoClear 0x00000002U
#define osFlagsError 0x80000000U
#define osFlagsErrorUnknown 0xFFFFFFFFU
#define osFlagsErrorTimeout 0xFFFFFFFEU
#define osFlagsErrorResource 0xFFFFFFFDU
#define osFlagsErrorParameter 0xFFFFFFFCU
uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
#ifdef __cplusplus
}
#endif
#endif /* CMSIS_OS2_H */
+31
View File
@@ -0,0 +1,31 @@
/*
* 主机侧单测桩:dbg_log.h
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的日志宏(映射到计数)。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
*
* 注意:time_sync.c 在 `#include "dbg_log.h"` 之前自行 `#define` 了
* DBG_LINE_BUF_MAX 与 DBG_TAG(真实头会用到它们),故本桩**不得**再定义这两个宏,
* 否则触发 C4005 宏重定义告警(/W4)。
*
* DBG_ERROR / DBG_INFO 计入计数器,供单测断言:
* - "net_socket/bind/listen FAIL"、"open listener FAIL, retry later" → ERROR
* - "no TIME packet in 30s, drop conn"、"wall clock updated"、"network re-init" → INFO
*
* 创建日期:2026-10-10
*/
#ifndef DBG_LOG_H
#define DBG_LOG_H
#include <stdio.h>
/* 计数(在 time_sync_test.c 实现) */
extern int g_tstest_err_count;
extern int g_tstest_info_count;
#define DBG_INFO(fmt, ...) do { g_tstest_info_count++; } while (0)
#define DBG_DEBUG(fmt, ...) do { } while (0)
#define DBG_ERROR(fmt, ...) do { g_tstest_err_count++; } while (0)
#endif /* DBG_LOG_H */
+71
View File
@@ -0,0 +1,71 @@
/*
* 主机侧单测桩:net_socket.h(含内联 net_types.h 子集)
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的网络 Socket API 声明与类型。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
* 真实头(Drivers/BSP/NET/net_socket.h)包含 net_types.h → net_config.h,并经
* FreeRTOS.h / task.h 拖入整套 FreeRTOS;本桩改为包含同名桩头。
*
* 保真点:
* - 地址族/类型/特殊地址常量与 Drivers/BSP/NET/net_types.h 逐字一致;
* - struct net_sockaddr / net_in_addr / net_sockaddr_in 字段与真实头一致
* (被测代码写 sin_family / sin_port / sin_addr.s_addr,桩按同布局读取);
* - 7 个被测代码调用的接口签名与真实头一致(net_socket / net_bind / net_listen /
* net_accept / net_close / net_recv_to / net_get_generation / net_htons)。
* 全部由测试单元给强符号桩(脚本化返回值 + 调用记录)。
*
* 创建日期:2026-10-10
*/
#ifndef NET_SOCKET_H
#define NET_SOCKET_H
#include <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ===== 以下取自 Drivers/BSP/NET/net_types.h(逐字) ===== */
#define NET_AF_INET 2 /* IPv4 */
#define NET_SOCK_STREAM 1 /* TCP */
#define NET_SOCK_DGRAM 2 /* UDP */
#define NET_INADDR_ANY 0 /* 任意地址 */
#define NET_INADDR_NONE 0xFFFFFFFF /* 无效地址 */
struct net_sockaddr {
uint16_t sa_family; /* 地址族 */
char sa_data[14]; /* 地址数据 */
};
struct net_in_addr {
uint32_t s_addr; /* IP 地址(网络字节序) */
};
struct net_sockaddr_in {
uint16_t sin_family; /* 地址族,必须为 AF_INET */
uint16_t sin_port; /* 端口号(网络字节序) */
struct net_in_addr sin_addr; /* IP 地址(网络字节序) */
char sin_zero[8]; /* 填充字节 */
};
/* ===== 被测代码用到的 Socket API(签名与真实头一致) ===== */
int net_socket(int domain, int type);
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
int net_listen(int sockfd);
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
int net_close(int sockfd);
int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms);
uint32_t net_get_generation(void);
uint16_t net_htons(uint16_t hostshort);
#ifdef __cplusplus
}
#endif
#endif /* NET_SOCKET_H */
+29
View File
@@ -0,0 +1,29 @@
/*
* 主机侧单测桩:sys_clock.h
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的墙钟设置接口声明。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
* 真实头(App/util/sys_clock.h)含日历/闰年等无关声明;本桩只保留被测代码
* 真正调用的那一个(签名与真实头逐字一致:int sys_clock_set_unix(uint32_t))。
*
* 由测试单元给强符号桩,记录"是否被调用"与"最后一次的 epoch"。
*
* 创建日期:2026-10-10
*/
#ifndef SYS_CLOCK_H
#define SYS_CLOCK_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int sys_clock_set_unix(uint32_t unix_secs);
#ifdef __cplusplus
}
#endif
#endif /* SYS_CLOCK_H */
+39
View File
@@ -0,0 +1,39 @@
/*
* 主机侧单测桩:sys_events.h
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的系统就绪事件组句柄与事件位。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
* 真实头(App/app/sys_events.h)包含 cmsis_os2.h;本桩改为包含同名桩,
* 避免拖入整套 CMSIS-RTOS/FreeRTOS。
*
* 事件位取值与真实头逐位一致(本模块只用到 SYS_EVT_NET_READY)。
*
* 创建日期:2026-10-10
*/
#ifndef SYS_EVENTS_H
#define SYS_EVENTS_H
#include "cmsis_os2.h"
#ifdef __cplusplus
extern "C" {
#endif
/* 系统就绪事件组句柄(真实工程由 MX_FREERTOS_Init 创建;主机侧由测试单元定义) */
extern osEventFlagsId_t sys_evtHandle;
/* 各子系统"就绪"事件位(与 App/app/sys_events.h 一致) */
#define SYS_EVT_NET_READY (1u << 0)
#define SYS_EVT_STORAGE_READY (1u << 1)
#define SYS_EVT_FTP_READY (1u << 2)
#define SYS_EVT_TIMESYNC_READY (1u << 3)
#define SYS_EVT_NET_RECONFIG (1u << 4)
#define SYS_EVT_CFG_SAVE (1u << 5)
#define SYS_EVT_CONSOLE_TX (1u << 6)
#ifdef __cplusplus
}
#endif
#endif /* SYS_EVENTS_H */
+29
View File
@@ -0,0 +1,29 @@
/*
* 主机侧单测桩:task.h
* 模块功能:为 App/sync/time_sync.c 提供主机可编译的 FreeRTOS 任务时基接口声明。
*
* ⚠ 仅供 test/host/time_sync/ 使用,不参与 MCU 构建。
*
* 两个接口由测试单元给强符号桩:vTaskDelay 记录每片睡眠时长(断言"≤50ms 分片"),
* xTaskGetTickCount 由测试单元提供可控时钟(驱动 30s 预算耗尽与 32 位回绕用例)。
*
* 创建日期:2026-10-10
*/
#ifndef TASK_H
#define TASK_H
#include "FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
void vTaskDelay(TickType_t xTicksToDelay);
TickType_t xTaskGetTickCount(void);
#ifdef __cplusplus
}
#endif
#endif /* TASK_H */