test(host): 断言字面量统一纯 ASCII,30 文件 1535 行
用户裁定「统一」。口径就是 AGENTS 铁律:字符串字面量必须纯 ASCII (无 BOM 文件里奇数个汉字会吞掉结束引号,偶数才侥幸通过),中文只写注释。 四名队友按目录分四组并行、写范围互斥:net_socket 418 行(6 文件)、 console_log/sys_log_mcu/soe_store/cfg_file_store_mcu 268 行(4 文件)、 11 个存量套件 404 行 + adc_input 89 行、iec104 与 lftpd 与 NET 四套等 356 行 (9 文件)。runner 的 .py 文档串不在口径内(Python 源不经 ARMCC 代码页)。 两套口径必须分清:粗口径(按行切引号)普查 = 34 文件 / 1,552 行;严格口径 (状态机剥掉块/行注释与字符常量后再取字符串字面量)= 30 文件 / 1,535 行。 差值那 4 个文件的命中全在注释里(ns_peers.c、net_socket/stub/ns_rtos.h、 common/ch395f_fake.h、common/fatfs_fake.c)——按口径一处都不该改,改了等于 把中文从注释里搬走、正好违背口径。粗口径绝不能当交付判据,否则要么白改 注释、要么留下「这行为什么没改」的悬案。 Lead 独立终检(不采信自报)五条硬判据,结果 30 文件漂移 0:① 每文件 TC 号 集合与 HEAD 逐字相同 ② 断言宏调用点数不变 ③ 行数与 HEAD 完全相等(专抓 整文件回写把尾部含 main() 吃掉的截断,第 1 轮真发生过两次)④ 剥注释后代码区 非 ASCII 字符 = 0 ⑤ 字节卫生(BOM 与 HEAD 一致、无 CR、无 U+FFFD、单尾换行)。 另用「逐行把字面量整体替换成空串后与 HEAD 必须逐行相等」机械证明只改了字面量; 各套 --module 覆盖率与断言数逐字不变(net_socket 887/889·53/53、console_log 199/200·16/16、sys_log_mcu 324/326·13/13、adc_input 103/103、sys_clock 100/100) → 生产码零改动,基线不需重登。 闸拦下一处真实回归(我的验收器没抓到):ns_s6_edges.c 翻译时把一个上一轮 已整改成平实描述的编号又写回了 CHECK 标签。原因很清楚:「只改字面量」并不 等于「只改无害内容」,标签里完全可以带进未登记族的编号形态;而 Lead 的自动 验收器只比对了 TC 形 id 集合,未覆盖 L/E/N/S/TRAP 等族。教训:批量改标签的 守卫必须加一条「新串不得出现任何已登记前缀族之外的编号形态」,且结构不变式 只覆盖自己想到的维度时不能替代真闸。 Lead 自查另清掉 126 处写坏的反斜杠(JS→Python 转义层数翻倍,把 markdown 反引号写成反斜杠+反引号),恰好发生在记录这条教训的那一节里。 文档:docs/测试说明/主机单测覆盖率口径.md §9 新增「第 2 轮」小节(两套口径对照 表、五条终检判据、六条手法含「转换说明符序列必须逐位相同」取代「禁止裸 %」、 三条协作纪律含先改板再派工与临时文件带组前缀、后续项 3 条)+ 变更记录一行。 后续项(本轮不做):把剥注释词法扫描器收进 scripts 当门禁(需用户点头并先定 test/ 是否纳入 coding-standard);iec104 的简写编号归族(牵 id_registry, 不能顺手做);替换器加「编号形态白名单」校验。 gate: pre-commit run --all-files -> 39 hooks, 37 Passed; failed = mem-numbers + mem-budget(受管快照与本树 .map 的漂移,属第 1 轮生产码改动的遗留,非本批 增量)。本批只碰 test/host/**,不进 Keil 编译面也不进模拟器 CMake,**RAM/Flash 增量 = 0**;实测水位 RW_IRAM1 57.4%、RW_CCM 87.9%,均低于 92% 红线。 id-check 0 台账外新账(可判定 84.63% > 基线 82.6%);test-coverage 33/33 全绿; cppcheck / coding-standard / bsp-err / layer-deps / doc-links 全 Passed。 按仓内分支约定 --no-verify 提交,台账 --write 回填留待主工作树合并后。
This commit is contained in:
@@ -189,19 +189,19 @@ static void tc_000_uninitialized(void) {
|
||||
sd2506_time_t t;
|
||||
char buf[32];
|
||||
|
||||
printf("TC-SYSCLK-000 未初始化语义\n");
|
||||
printf("TC-SYSCLK-000 uninitialised semantics\n");
|
||||
/* 注意:本用例不做 sys_clock_init / sys_clock_set */
|
||||
CHECK_EQ_U32(sys_clock_get(), UINT32_MAX, "未初始化 get 返回 UINT32_MAX");
|
||||
CHECK(sys_clock_get_time(&t) == -1, "未初始化 get_time 返回 -1");
|
||||
CHECK_EQ_U32(sys_clock_get(), UINT32_MAX, "get before init returns UINT32_MAX");
|
||||
CHECK(sys_clock_get_time(&t) == -1, "get_time before init returns -1");
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
CHECK(sys_clock_get_str(buf, sizeof(buf)) == buf, "get_str 返回 buf 指针");
|
||||
CHECK(strcmp(buf, "----/--/-- --:--:--") == 0, "get_str 未初始化占位串");
|
||||
CHECK(sys_clock_get_str(buf, sizeof(buf)) == buf, "get_str returns the buf pointer");
|
||||
CHECK(strcmp(buf, "----/--/-- --:--:--") == 0, "get_str placeholder string before init");
|
||||
}
|
||||
|
||||
static void tc_001_init_ok(void) {
|
||||
int rc;
|
||||
printf("TC-SYSCLK-001 init 正常(RTC 合法)\n");
|
||||
printf("TC-SYSCLK-001 init normal (valid RTC)\n");
|
||||
rtc_set(2026, 8, 24, 0, 0, 0);
|
||||
s_rtc_read_rc = BSP_OK;
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
@@ -209,60 +209,60 @@ static void tc_001_init_ok(void) {
|
||||
s_tick = 12345u;
|
||||
|
||||
rc = sys_clock_init();
|
||||
CHECK(rc == 0, "RTC 合法 → init 返回 0");
|
||||
CHECK(rc == 0, "valid RTC -> init returns 0");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 8, 24, 0, 0, 0),
|
||||
"基准 = 2026-08-24 00:00:00 的 Unix 秒");
|
||||
CHECK(s_rtc_set_calls == 0, "合法 RTC 不被写回(无校时)");
|
||||
"base = Unix seconds of 2026-08-24 00:00:00");
|
||||
CHECK(s_rtc_set_calls == 0, "valid RTC is never written back (no time correction)");
|
||||
}
|
||||
|
||||
static void tc_002_init_leap(void) {
|
||||
printf("TC-SYSCLK-002 init 闰年换算\n");
|
||||
printf("TC-SYSCLK-002 init leap-year conversion\n");
|
||||
/* 2024 是闰年:2/29 存在 */
|
||||
rtc_set(2024, 2, 29, 12, 0, 0);
|
||||
s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "2024-02-29 合法");
|
||||
CHECK(sys_clock_init() == 0, "2024-02-29 accepted");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2024, 2, 29, 12, 0, 0),
|
||||
"2024-02-29 12:00:00 换算正确");
|
||||
"2024-02-29 12:00:00 converts correctly");
|
||||
|
||||
/* 2000 是世纪闰年:2/29 存在 */
|
||||
rtc_set(2000, 2, 29, 0, 0, 0);
|
||||
CHECK(sys_clock_init() == 0, "2000-02-29 合法(世纪闰年)");
|
||||
CHECK(sys_clock_init() == 0, "2000-02-29 accepted (century leap year)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2000, 2, 29, 0, 0, 0),
|
||||
"2000-02-29 换算正确");
|
||||
"2000-02-29 converts correctly");
|
||||
|
||||
/* 3 月 1 日:验证闰年 2 月多 1 天被正确累计 */
|
||||
rtc_set(2024, 3, 1, 0, 0, 0);
|
||||
CHECK(sys_clock_init() == 0, "2024-03-01 合法");
|
||||
CHECK(sys_clock_init() == 0, "2024-03-01 accepted");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2024, 3, 1, 0, 0, 0),
|
||||
"2024-03-01 与 2024-02-29 相差恰 1 天");
|
||||
"2024-03-01 is exactly 1 day after 2024-02-29");
|
||||
CHECK_EQ_U32(ref_unix(2024, 3, 1, 0, 0, 0) - ref_unix(2024, 2, 29, 0, 0, 0),
|
||||
86400u, "闰日间隔 = 86400 s");
|
||||
86400u, "leap-day gap = 86400 s");
|
||||
}
|
||||
|
||||
static void tc_003_init_month_end(void) {
|
||||
printf("TC-SYSCLK-003 init 月末边界\n");
|
||||
printf("TC-SYSCLK-003 init end-of-month boundaries\n");
|
||||
rtc_set(2026, 1, 31, 0, 0, 0); s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "1/31 合法");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 1, 31, 0, 0, 0), "1/31 换算");
|
||||
CHECK(sys_clock_init() == 0, "1/31 accepted");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 1, 31, 0, 0, 0), "1/31 conversion");
|
||||
|
||||
rtc_set(2026, 2, 28, 23, 59, 59); s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "2/28 合法(平年)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 2, 28, 23, 59, 59), "2/28 末端换算");
|
||||
CHECK(sys_clock_init() == 0, "2/28 accepted (common year)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 2, 28, 23, 59, 59), "2/28 end-of-day conversion");
|
||||
|
||||
rtc_set(2026, 4, 30, 0, 0, 0); s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "4/30 合法(30 天月)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 4, 30, 0, 0, 0), "4/30 换算");
|
||||
CHECK(sys_clock_init() == 0, "4/30 accepted (30-day month)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2026, 4, 30, 0, 0, 0), "4/30 conversion");
|
||||
|
||||
/* 2/28 → 3/1 间隔恰 1 天(平年) */
|
||||
rtc_set(2026, 2, 28, 0, 0, 0); sys_clock_init();
|
||||
uint32_t a = sys_clock_get();
|
||||
rtc_set(2026, 3, 1, 0, 0, 0); sys_clock_init();
|
||||
uint32_t b = sys_clock_get();
|
||||
CHECK_EQ_U32(b - a, 86400u, "平年 2/28 → 3/1 间隔 = 86400 s");
|
||||
CHECK_EQ_U32(b - a, 86400u, "common year 2/28 -> 3/1 gap = 86400 s");
|
||||
}
|
||||
|
||||
static void tc_004_init_epoch_bounds(void) {
|
||||
printf("TC-SYSCLK-004 init 世纪边界(Unix 下限 / 2038 上限)\n");
|
||||
printf("TC-SYSCLK-004 init century boundaries (Unix lower bound / 2038 upper bound)\n");
|
||||
/*
|
||||
* 注意:init 接受的 RTC 年份范围是 2000~2099(越界即判故障并自愈),
|
||||
* 故"Unix 0(1970-01-01)"**不可能经 init 建立**——1970 会被判越界。
|
||||
@@ -270,46 +270,46 @@ static void tc_004_init_epoch_bounds(void) {
|
||||
* 这里验证 init 可接受的最早年月,以及 uint32 上限。
|
||||
*/
|
||||
rtc_set(2000, 1, 1, 0, 0, 0); s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "2000-01-01 合法(可接受最早年)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2000, 1, 1, 0, 0, 0), "2000-01-01 换算");
|
||||
CHECK(sys_clock_init() == 0, "2000-01-01 accepted (earliest acceptable year)");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(2000, 1, 1, 0, 0, 0), "2000-01-01 conversion");
|
||||
|
||||
/* 2038 上限:2038-01-19 03:14:07 = 0x7FFFFFFF */
|
||||
rtc_set(2038, 1, 19, 3, 14, 7); s_rtc_read_rc = BSP_OK;
|
||||
CHECK(sys_clock_init() == 0, "2038-01-19 合法(uint32 上限内)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 0x7FFFFFFFu, "2038-01-19 03:14:07 → 0x7FFFFFFF");
|
||||
CHECK(sys_clock_init() == 0, "2038-01-19 accepted (within uint32 limit)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 0x7FFFFFFFu, "2038-01-19 03:14:07 -> 0x7FFFFFFF");
|
||||
|
||||
/* Unix 0 经 set 路径显式可达(与 init 的范围限制无关) */
|
||||
clear_obs();
|
||||
CHECK(sys_clock_set(0u, NULL) == 0, "set(0) 合法(Unix 零点)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 0u, "set(0) 后 get == 0(Unix 零点)");
|
||||
CHECK(sys_clock_set(0u, NULL) == 0, "set(0) accepted (Unix epoch)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 0u, "after set(0) get == 0 (Unix epoch)");
|
||||
{
|
||||
sd2506_time_t t;
|
||||
CHECK(sys_clock_get_time(&t) == 0
|
||||
&& t.year == 1970 && t.month == 1 && t.day == 1,
|
||||
"Unix 0 → 1970-01-01(unix_to_sd2506 反向换算)");
|
||||
"Unix 0 -> 1970-01-01 (unix_to_sd2506 reverse conversion)");
|
||||
}
|
||||
}
|
||||
|
||||
static void tc_005_init_rtc_read_fail(void) {
|
||||
printf("TC-SYSCLK-005 init RTC 读失败 → 降级默认时间并返回 -1\n");
|
||||
printf("TC-SYSCLK-005 init RTC read failure -> degrade to default time and return -1\n");
|
||||
s_rtc_read_rc = BSP_ERR_IO; /* 注入读故障 */
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
clear_obs();
|
||||
s_tick = 777u;
|
||||
|
||||
int rc = sys_clock_init();
|
||||
CHECK(rc == -1, "RTC 读失败 → init 返回 -1(报告芯片故障)");
|
||||
CHECK(rc == -1, "RTC read failure -> init returns -1 (reports the chip fault)");
|
||||
/* 降级基准 = 编译期默认 RTC_DEFAULT_*(2026-08-24 00:00:00) */
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(RTC_DEFAULT_YEAR, RTC_DEFAULT_MONTH,
|
||||
RTC_DEFAULT_DAY, RTC_DEFAULT_HOUR,
|
||||
RTC_DEFAULT_MINUTE, RTC_DEFAULT_SECOND),
|
||||
"降级基准 = 编译期默认时间(墙钟仍可用)");
|
||||
CHECK(g_sclk_err_count >= 1, "打了 DBG_ERROR(RTC 异常)");
|
||||
"degraded base = compile-time default time (wall clock still usable)");
|
||||
CHECK(g_sclk_err_count >= 1, "DBG_ERROR emitted (RTC abnormal)");
|
||||
s_rtc_read_rc = BSP_OK; /* 复位注入 */
|
||||
}
|
||||
|
||||
static void tc_006_init_out_of_range_selfheal(void) {
|
||||
printf("TC-SYSCLK-006 init RTC 越界 → 自愈写回默认时间(返回 0)\n");
|
||||
printf("TC-SYSCLK-006 init RTC out of range -> self-heal by writing back the default time (returns 0)\n");
|
||||
/*
|
||||
* RTC_DEFAULT_INIT_ENABLE=1 且 FORCE=0 时:越界值触发"写回默认时间",
|
||||
* 写成功且复读合法 → rtc_ok 恢复为 1 → **返回 0**(自愈,非降级)。
|
||||
@@ -319,23 +319,23 @@ static void tc_006_init_out_of_range_selfheal(void) {
|
||||
s_rtc_read_rc = BSP_OK;
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
clear_obs();
|
||||
CHECK(sys_clock_init() == 0, "year=1999 → 自愈写回成功 → 返回 0");
|
||||
CHECK(s_rtc_set_calls == 1, "越界触发一次写回");
|
||||
CHECK(s_rtc.year == RTC_DEFAULT_YEAR, "阴影 RTC 已修正为默认年");
|
||||
CHECK(sys_clock_init() == 0, "year=1999 -> self-heal write-back ok -> returns 0");
|
||||
CHECK(s_rtc_set_calls == 1, "out-of-range triggers exactly one write-back");
|
||||
CHECK(s_rtc.year == RTC_DEFAULT_YEAR, "shadow RTC corrected to the default year");
|
||||
|
||||
rtc_set(2026, 13, 5, 0, 0, 0); /* month > 12 → 越界 */
|
||||
clear_obs();
|
||||
CHECK(sys_clock_init() == 0, "month=13 → 自愈 → 返回 0");
|
||||
CHECK(s_rtc_set_calls == 1, "越界触发一次写回");
|
||||
CHECK(sys_clock_init() == 0, "month=13 -> self-heal -> returns 0");
|
||||
CHECK(s_rtc_set_calls == 1, "out-of-range triggers exactly one write-back");
|
||||
|
||||
rtc_set(2026, 5, 0, 0, 0, 0); /* day < 1 → 越界 */
|
||||
clear_obs();
|
||||
CHECK(sys_clock_init() == 0, "day=0 → 自愈 → 返回 0");
|
||||
CHECK(s_rtc_set_calls == 1, "越界触发一次写回");
|
||||
CHECK(sys_clock_init() == 0, "day=0 -> self-heal -> returns 0");
|
||||
CHECK(s_rtc_set_calls == 1, "out-of-range triggers exactly one write-back");
|
||||
}
|
||||
|
||||
static void tc_020_init_selfheal_fail_degrades(void) {
|
||||
printf("TC-SYSCLK-020 init 越界且写回失败 → 降级默认时间并返回 -1\n");
|
||||
printf("TC-SYSCLK-020 init out of range and write-back fails -> degrade to default time and return -1\n");
|
||||
/*
|
||||
* 组合故障:读成功但值越界(触发写回),写回失败 → 复读仍越界 →
|
||||
* rtc_ok 清 0 → 走降级分支(启用默认值时建基准 + 返回 -1)。
|
||||
@@ -346,81 +346,81 @@ static void tc_020_init_selfheal_fail_degrades(void) {
|
||||
clear_obs();
|
||||
s_tick = 42u;
|
||||
int rc = sys_clock_init();
|
||||
CHECK(rc == -1, "越界 + 写回失败 → init 返回 -1");
|
||||
CHECK(s_rtc_set_calls == 1, "尝试写回一次(失败)");
|
||||
CHECK(g_sclk_err_count >= 1, "打了 DBG_ERROR");
|
||||
CHECK(rc == -1, "out of range + write-back failure -> init returns -1");
|
||||
CHECK(s_rtc_set_calls == 1, "write-back attempted once (failed)");
|
||||
CHECK(g_sclk_err_count >= 1, "DBG_ERROR emitted");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(RTC_DEFAULT_YEAR, RTC_DEFAULT_MONTH,
|
||||
RTC_DEFAULT_DAY, 0, 0, 0),
|
||||
"降级基准 = 编译期默认时间(墙钟仍可用)");
|
||||
"degraded base = compile-time default time (wall clock still usable)");
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
}
|
||||
|
||||
static void tc_007_init_corrects_rtc(void) {
|
||||
printf("TC-SYSCLK-007 init 越界 → 自动写回默认时间并复验\n");
|
||||
printf("TC-SYSCLK-007 init out of range -> auto write-back of default time and re-verify\n");
|
||||
rtc_set(1999, 1, 1, 0, 0, 0); /* 越界,触发校时写回 */
|
||||
s_rtc_read_rc = BSP_OK;
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
clear_obs();
|
||||
int rc = sys_clock_init();
|
||||
CHECK(s_rtc_set_calls == 1, "越界 → 写回 RTC 一次");
|
||||
CHECK(rc == 0, "写回成功 + 复读合法 → 返回 0(自愈成功,非降级)");
|
||||
CHECK(s_rtc_set_calls == 1, "out of range -> RTC written back once");
|
||||
CHECK(rc == 0, "write-back ok + re-read valid -> returns 0 (self-heal succeeded, not a degrade)");
|
||||
CHECK(s_rtc.year == RTC_DEFAULT_YEAR && s_rtc.month == RTC_DEFAULT_MONTH
|
||||
&& s_rtc.day == RTC_DEFAULT_DAY, "阴影 RTC 已被写入默认时间");
|
||||
&& s_rtc.day == RTC_DEFAULT_DAY, "shadow RTC was written with the default time");
|
||||
CHECK_EQ_U32(sys_clock_get(), ref_unix(RTC_DEFAULT_YEAR, RTC_DEFAULT_MONTH,
|
||||
RTC_DEFAULT_DAY, 0, 0, 0),
|
||||
"基准 = 修正后的默认时间");
|
||||
"base = the corrected default time");
|
||||
}
|
||||
|
||||
static void tc_008_get_advance(void) {
|
||||
printf("TC-SYSCLK-008 get 正常推进(含亚秒截断)\n");
|
||||
printf("TC-SYSCLK-008 get advances normally (sub-second truncation included)\n");
|
||||
base_at(1000000u, 5000u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000000u, "基准时刻 = 基准值");
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000000u, "at the base instant the value equals the base");
|
||||
tick_advance(999u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000000u, "999ms 未满 1s → 不变(截断)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000000u, "999ms is under 1 s -> unchanged (truncated)");
|
||||
tick_advance(1u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000001u, "累计 1000ms → +1s");
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000001u, "accumulated 1000ms -> +1 s");
|
||||
tick_advance(2500u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000003u, "再 +2500ms → 共 +3s(余 500ms 截断)");
|
||||
CHECK_EQ_U32(sys_clock_get(), 1000003u, "another +2500ms -> +3 s total (remaining 500 ms truncated)");
|
||||
}
|
||||
|
||||
static void tc_009_get_no_rebase_below_threshold(void) {
|
||||
printf("TC-SYSCLK-009 未达 30 天阈值不触发再基准化\n");
|
||||
printf("TC-SYSCLK-009 below the 30-day threshold no re-baselining\n");
|
||||
base_at(2000000u, 0u);
|
||||
/* 29 天 < 30 天阈值:线性推进,基准不动 */
|
||||
tick_advance(29u * 24u * 3600u * 1000u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 2000000u + 29u * 24u * 3600u,
|
||||
"29 天线性推进正确(未再基准化)");
|
||||
"29 days advance linearly and correctly (no re-baselining)");
|
||||
}
|
||||
|
||||
static void tc_010_get_rebase_at_threshold(void) {
|
||||
printf("TC-SYSCLK-010 30 天惰性再基准化(窗口清零、值无损、余数结转)\n");
|
||||
printf("TC-SYSCLK-010 30-day lazy re-baselining (window cleared, value lossless, remainder carried over)\n");
|
||||
base_at(3000000u, 0u);
|
||||
|
||||
/* 推进恰好 30 天 + 1500ms(余数 500ms 应结转到新窗) */
|
||||
tick_advance(30u * 24u * 3600u * 1000u + 1500u);
|
||||
uint32_t expect = 3000000u + 30u * 24u * 3600u + 1u; /* 1500ms → +1s,余 500ms */
|
||||
CHECK_EQ_U32(sys_clock_get(), expect, "再基准化后墙钟值无损(+30 天 1 秒)");
|
||||
CHECK_EQ_U32(sys_clock_get(), expect, "after re-baselining the wall clock value is lossless (+30 days 1 second)");
|
||||
|
||||
/* 再推 500ms:结转的余数正好补足,再多 1 秒 */
|
||||
tick_advance(500u);
|
||||
CHECK_EQ_U32(sys_clock_get(), expect + 1u, "亚秒余数已结转(+500ms 补足 1 秒)");
|
||||
CHECK_EQ_U32(sys_clock_get(), expect + 1u, "sub-second remainder carried over (+500 ms completes 1 second)");
|
||||
|
||||
/* 再推一整天:仍线性 */
|
||||
tick_advance(24u * 3600u * 1000u);
|
||||
CHECK_EQ_U32(sys_clock_get(), expect + 1u + 86400u, "再基准化后继续线性推进");
|
||||
CHECK_EQ_U32(sys_clock_get(), expect + 1u + 86400u, "keeps advancing linearly after re-baselining");
|
||||
}
|
||||
|
||||
static void tc_011_get_tick_wrap(void) {
|
||||
printf("TC-SYSCLK-011 tick 回绕(无符号差)安全\n");
|
||||
printf("TC-SYSCLK-011 tick wraparound (unsigned diff) is safe\n");
|
||||
/* 基准设在接近 2^32 处 */
|
||||
base_at(4000000u, 0xFFFFF000u);
|
||||
/* 推进 0x2000 ms(跨越 2^32 回绕):差 = 0x2000 = 8192ms → +8s */
|
||||
tick_advance(0x2000u);
|
||||
CHECK_EQ_U32(sys_clock_get(), 4000000u + 8u, "跨 tick 回绕后差值正确");
|
||||
CHECK_EQ_U32(sys_clock_get(), 4000000u + 8u, "diff is correct across the tick wraparound");
|
||||
}
|
||||
|
||||
static void tc_012_get_long_run_no_drift(void) {
|
||||
printf("TC-SYSCLK-012 多轮再基准化长期不漂移\n");
|
||||
printf("TC-SYSCLK-012 many re-baselining rounds do not drift over time\n");
|
||||
base_at(5000000u, 0u);
|
||||
/*
|
||||
* 惰性再基准化的**正确用法**:周期性调用 get() 让差值窗口始终 < 30 天。
|
||||
@@ -434,44 +434,44 @@ static void tc_012_get_long_run_no_drift(void) {
|
||||
for (i = 1u; i <= 9u; i++) {
|
||||
tick_advance(10u * 86400u * 1000u); /* 每次 +10 天(< 30 天阈值) */
|
||||
CHECK_EQ_U32(sys_clock_get(), base + i * 10u * 86400u,
|
||||
"10 天步进(含 3 轮再基准)线性无漂移");
|
||||
"10-day steps (with 3 re-baseline rounds) stay linear with no drift");
|
||||
}
|
||||
}
|
||||
|
||||
static void tc_013_get_str(void) {
|
||||
printf("TC-SYSCLK-013 get_str 格式化\n");
|
||||
printf("TC-SYSCLK-013 get_str formatting\n");
|
||||
char buf[32];
|
||||
base_at(ref_unix(2026, 10, 2, 13, 4, 5), 0u);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sys_clock_get_str(buf, sizeof(buf));
|
||||
CHECK(strcmp(buf, "2026-10-02 13:04:05") == 0, "格式化 YYYY-MM-DD HH:MM:SS");
|
||||
CHECK(strcmp(buf, "2026-10-02 13:04:05") == 0, "formatted as YYYY-MM-DD HH:MM:SS");
|
||||
|
||||
base_at(ref_unix(2000, 1, 1, 0, 0, 0), 0u);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sys_clock_get_str(buf, sizeof(buf));
|
||||
CHECK(strcmp(buf, "2000-01-01 00:00:00") == 0, "零点补零格式正确");
|
||||
CHECK(strcmp(buf, "2000-01-01 00:00:00") == 0, "zero-padded midnight format is correct");
|
||||
}
|
||||
|
||||
static void tc_014_get_time_fields(void) {
|
||||
printf("TC-SYSCLK-014 get_time 日历字段\n");
|
||||
printf("TC-SYSCLK-014 get_time calendar fields\n");
|
||||
sd2506_time_t t;
|
||||
/* 2026-10-02 是周五(已知) */
|
||||
base_at(ref_unix(2026, 10, 2, 8, 9, 10), 0u);
|
||||
CHECK(sys_clock_get_time(&t) == 0, "get_time 返回 0");
|
||||
CHECK(sys_clock_get_time(&t) == 0, "get_time returns 0");
|
||||
CHECK(t.year == 2026 && t.month == 10 && t.day == 2,
|
||||
"年月日正确");
|
||||
CHECK(t.hour == 8 && t.minute == 9 && t.second == 10, "时分秒正确");
|
||||
CHECK(t.week == 5, "2026-10-02 星期五(week==5,0=周日)");
|
||||
"year/month/day correct");
|
||||
CHECK(t.hour == 8 && t.minute == 9 && t.second == 10, "hour/minute/second correct");
|
||||
CHECK(t.week == 5, "2026-10-02 is Friday (week==5, 0=Sunday)");
|
||||
}
|
||||
|
||||
static void tc_015_get_time_null(void) {
|
||||
printf("TC-SYSCLK-015 get_time NULL 参数被拒\n");
|
||||
printf("TC-SYSCLK-015 get_time rejects a NULL argument\n");
|
||||
base_at(6000000u, 0u);
|
||||
CHECK(sys_clock_get_time(NULL) == -1, "p_time == NULL → 返回 -1");
|
||||
CHECK(sys_clock_get_time(NULL) == -1, "p_time == NULL -> returns -1");
|
||||
}
|
||||
|
||||
static void tc_016_set_writes_rtc(void) {
|
||||
printf("TC-SYSCLK-016 set 更新基准 + 写回 RTC\n");
|
||||
printf("TC-SYSCLK-016 set updates the base + writes back RTC\n");
|
||||
sd2506_time_t sd;
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
sd.year = 2027; sd.month = 3; sd.day = 15;
|
||||
@@ -480,48 +480,48 @@ static void tc_016_set_writes_rtc(void) {
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
clear_obs();
|
||||
s_tick = 100u;
|
||||
CHECK(sys_clock_set(7000000u, &sd) == 0, "set 返回 0");
|
||||
CHECK_EQ_U32(sys_clock_get(), 7000000u, "基准已更新");
|
||||
CHECK(s_rtc_set_calls == 1, "sd_time != NULL → 写回 RTC 一次");
|
||||
CHECK(sys_clock_set(7000000u, &sd) == 0, "set returns 0");
|
||||
CHECK_EQ_U32(sys_clock_get(), 7000000u, "base has been updated");
|
||||
CHECK(s_rtc_set_calls == 1, "sd_time != NULL -> RTC written back once");
|
||||
CHECK(s_rtc.year == 2027 && s_rtc.month == 3 && s_rtc.day == 15
|
||||
&& s_rtc.hour == 6 && s_rtc.minute == 7 && s_rtc.second == 8,
|
||||
"RTC 写入内容与传入一致");
|
||||
"RTC written content equals what was passed in");
|
||||
|
||||
/* 写失败:基准仍更新,但打错误日志 */
|
||||
clear_obs();
|
||||
s_rtc_write_rc = BSP_ERR_IO;
|
||||
sys_clock_set(7000001u, &sd);
|
||||
CHECK_EQ_U32(sys_clock_get(), 7000001u, "RTC 写失败仍更新基准");
|
||||
CHECK(g_sclk_err_count >= 1, "RTC 写失败打 DBG_ERROR");
|
||||
CHECK_EQ_U32(sys_clock_get(), 7000001u, "base is still updated when the RTC write fails");
|
||||
CHECK(g_sclk_err_count >= 1, "DBG_ERROR emitted when the RTC write fails");
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
}
|
||||
|
||||
static void tc_017_set_no_rtc(void) {
|
||||
printf("TC-SYSCLK-017 set sd_time=NULL 不碰 RTC\n");
|
||||
printf("TC-SYSCLK-017 set sd_time=NULL never touches the RTC\n");
|
||||
clear_obs();
|
||||
CHECK(sys_clock_set(8000000u, NULL) == 0, "set(NULL) 返回 0");
|
||||
CHECK(s_rtc_set_calls == 0, "sd_time == NULL → 不写 RTC");
|
||||
CHECK_EQ_U32(sys_clock_get(), 8000000u, "基准更新");
|
||||
CHECK(sys_clock_set(8000000u, NULL) == 0, "set(NULL) returns 0");
|
||||
CHECK(s_rtc_set_calls == 0, "sd_time == NULL -> RTC not written");
|
||||
CHECK_EQ_U32(sys_clock_get(), 8000000u, "base updated");
|
||||
}
|
||||
|
||||
static void tc_018_set_unix_fields(void) {
|
||||
printf("TC-SYSCLK-018 set_unix 写回 RTC 且字段正确\n");
|
||||
printf("TC-SYSCLK-018 set_unix writes back the RTC with correct fields\n");
|
||||
sd2506_time_t expect_week;
|
||||
uint32_t u = ref_unix(2026, 10, 2, 15, 30, 45);
|
||||
clear_obs();
|
||||
s_rtc_write_rc = BSP_OK;
|
||||
s_tick = 0u;
|
||||
CHECK(sys_clock_set_unix(u) == 0, "set_unix 返回 0");
|
||||
CHECK(s_rtc_set_calls == 1, "写回 RTC 一次");
|
||||
CHECK(sys_clock_set_unix(u) == 0, "set_unix returns 0");
|
||||
CHECK(s_rtc_set_calls == 1, "RTC written back once");
|
||||
CHECK(s_rtc.year == 2026 && s_rtc.month == 10 && s_rtc.day == 2
|
||||
&& s_rtc.hour == 15 && s_rtc.minute == 30 && s_rtc.second == 45,
|
||||
"RTC 日历字段与 Unix 秒一致");
|
||||
CHECK(s_rtc.week == 5, "RTC 星期字段 = 5(2026-10-02 周五)");
|
||||
"RTC calendar fields match the Unix seconds");
|
||||
CHECK(s_rtc.week == 5, "RTC weekday field = 5 (2026-10-02 is Friday)");
|
||||
(void)expect_week;
|
||||
}
|
||||
|
||||
static void tc_019_week_known_dates(void) {
|
||||
printf("TC-SYSCLK-019 星期(Zeller)已知日期穷举\n");
|
||||
printf("TC-SYSCLK-019 weekday (Zeller) exhaustive check against known dates\n");
|
||||
/* 期望值经 Python datetime 独立核对(0=周日);
|
||||
* 覆盖 1/2 月(Zeller 需上调为上年 13/14 月的分支)与 3~12 月(2026-10-02
|
||||
* 修正前全部错误),以及世纪闰年、非闰世纪、范围首尾。*/
|
||||
@@ -554,14 +554,14 @@ static void tc_019_week_known_dates(void) {
|
||||
cases[i].y, cases[i].m, cases[i].d, cases[i].w);
|
||||
CHECK(t.week == cases[i].w, nm);
|
||||
} else {
|
||||
CHECK(0, "get_time 失败(用例数据问题)");
|
||||
CHECK(0, "get_time failed (bad test data)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("=== System Clock 主机侧单元测试 ===\n");
|
||||
printf("被测:App/util/sys_clock.c(时间换算 + 墙钟基准)\n\n");
|
||||
printf("=== System Clock host-side unit tests ===\n");
|
||||
printf("Target: App/util/sys_clock.c (time conversion + wall-clock base)\n\n");
|
||||
|
||||
/* tc_000 必须最先(依赖"刚上电"的静态态) */
|
||||
tc_000_uninitialized();
|
||||
|
||||
Reference in New Issue
Block a user