L1-6 采样有效性校验:adc_health 判定层 + 告警编排 + 31 用例单测 + 台架闭环
新增 App/algo/adc_health.c/h(纯逻辑判定层,零平台依赖免桩单测): - 静默:两侧帧序号连续 >=100ms 无前进(电平位可自愈,flags() 为 L5-4 闭锁预留) - 丢帧:TPAFE 序号一次前进 >1 计 tgap(与 STM32 侧 adc1_gap 对称,边沿事件) - 单调性:序号倒退锁存位;tick/计数差值法 (int32_t)(a-b) 回绕安全 - 错误增量:FRSTDATA / HAL 错误 / STM32 停摆计数增量,事件位与锁存位编号对齐, 消费者按位图做"每类每次开机留痕一次"编排 adc_task.c v2.9 告警编排(判定与编排分离):严重事件/电平上升沿 DBG_ERROR + SYSLOG_SELFTEST(每类每次开机一次防刷屏),下降沿 DBG_INFO 恢复;gap 不告警 (消费者超拍是已知现象,告警会淹没真故障);心跳行增 tgap 观测字段。 主机单测 test/host/adc_health/ 31 用例全绿(100ms 门限两侧 / 边沿语义 / 倒退锁存 / tick 回绕 / NULL 守卫 / init 幂等),登记 adc-health-unit-test 钩子。 台架 @test PASS:零 [ERR](健康不误报)、tgap=1->2 与 adc1_gap 同步可见、 frames 1000.0 Hz;证据 boot_log_data/20261011_prod_adc_health_boot_log.txt。 抬栈:adc_health_report->syslog_post 控制台回显尾使 adcTask 静态最坏链 832->1080 B(512 words 余 968 B < 1024 B ISR 底线)-> 512->640 words, 复测余 1480 B / 57%,堆 min_ever 7152->6640 B(-512 B 符合预算)。 AGENTS/README 任务表、RAM 方案 §2.3、规划文档 §3.1 L1-6 已同步置完成。
This commit is contained in:
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* 模块名称:ADC 采样有效性校验(L1-6)主机侧单元测试
|
||||
* 模块功能:在 PC 上对 App/algo/adc_health.c 做离线验证。
|
||||
*
|
||||
* 被测对象:真实源文件(以 #include 原样纳入,保证测的是生产代码而非副本):
|
||||
* ../../../App/algo/adc_health.c
|
||||
* 本层为**纯逻辑**(仅 stdint.h),**无需任何桩**。
|
||||
*
|
||||
* 为什么要主机侧单测(而不是只用板端闭环):
|
||||
* 1. 静默/倒退/错误增量在健康台架上**不可复现**(复现 = 拔芯片/改驱动),
|
||||
* 板端只能证明"健康时不误报",证不了"故障时必报";
|
||||
* 2. 边界(恰好 100ms 门限 / tick 回绕 / 序号倒退后再前进 / 事件只发一拍)
|
||||
* 只有合成计数序列能精确构造;
|
||||
* 3. 不占 MCU 的 RAM,毫秒级完成。
|
||||
*
|
||||
* 覆盖点(对应 docs/算法/继电保护功能复现规划.md §3.1 L1-6):
|
||||
* TC-AH-001 init + 首拍只建基线(不误报)
|
||||
* TC-AH-002 正常 1 kHz 推进 2000 拍:零故障零事件(健康不误报)
|
||||
* TC-AH-003 TPAFE 静默:99ms 不报 / 100ms 报 / 恢复清除电平位、锁存位留痕
|
||||
* TC-AH-004 STM32 静默:TPAFE 正常时只报 STM32 侧
|
||||
* TC-AH-005 TPAFE 丢帧:d=3 → tgap+=2、事件仅当拍(边沿语义)
|
||||
* TC-AH-006 STM32 gap 计数增量 → 事件(不入锁存:超拍非故障)
|
||||
* TC-AH-007 序号倒退 → SEQ_BACKWARD 锁存(前进后仍留痕)
|
||||
* TC-AH-008 FRSTDATA / STM32_ERR / HW_ERR 增量 → 事件位与锁存位编号一致
|
||||
* TC-AH-009 tick 回绕:跨 0xFFFFFFFF 的正常推进不误报静默;回绕后冻结仍报
|
||||
* TC-AH-010 NULL 守卫:in=NULL 跳过;out=NULL 只更新内部状态
|
||||
* TC-AH-011 init 幂等:故障后 re-init 全清
|
||||
*
|
||||
* 通过:全部 TC PASS(main 返回 0)。
|
||||
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
|
||||
*
|
||||
* 创建日期:2026-10-11
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ===================== 断言 ===================== */
|
||||
static int s_total = 0, s_passed = 0, s_failed = 0;
|
||||
|
||||
#define CHECK(cond, name) do { \
|
||||
s_total++; \
|
||||
if (cond) { s_passed++; printf(" [PASS] %s\n", name); } \
|
||||
else { s_failed++; printf(" [FAIL] %s (line %d)\n", name, __LINE__); } \
|
||||
} while (0)
|
||||
|
||||
/* ===================== 被测代码 ===================== */
|
||||
/* 原样纳入生产源文件(纯逻辑,无需桩) */
|
||||
#include "adc_health.c"
|
||||
|
||||
/* ===================== 工具 ===================== */
|
||||
|
||||
/* 构造一份"健康"计数快照模板:两侧序号同拍号 seq,错误计数全 0 */
|
||||
static adc_health_in_t mk_in(uint32_t seq, uint32_t now_ms) {
|
||||
adc_health_in_t in;
|
||||
|
||||
in.tpafe_seq = seq;
|
||||
in.tpafe_frst_err = 0u;
|
||||
in.stm32_seq = seq;
|
||||
in.stm32_errs = 0u;
|
||||
in.stm32_gaps = 0u;
|
||||
in.stm32_hw_errs = 0u;
|
||||
in.now_ms = now_ms;
|
||||
return in;
|
||||
}
|
||||
|
||||
/* ===================== TC ===================== */
|
||||
|
||||
/* TC-AH-001:init + 首拍只建基线 */
|
||||
static void tc_prime(void) {
|
||||
adc_health_in_t in;
|
||||
adc_health_status_t st;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(12345u, 1000u); /* 开机时序号已非 0 */
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.flags == 0u) && (st.events == 0u) && (st.sticky == 0u) &&
|
||||
(st.tpafe_gaps == 0u),
|
||||
"TC-AH-001 first check only primes: no flags/events/sticky");
|
||||
/* 第二拍序号未动但仅 1ms(< 门限)→ 仍不报 */
|
||||
in.now_ms = 1001u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(st.flags == 0u, "TC-AH-001 1ms without advance is not a stall");
|
||||
}
|
||||
|
||||
/* TC-AH-002:正常 1 kHz 推进 2000 拍零误报 */
|
||||
static void tc_healthy(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
uint32_t seq = 0u, now = 0u;
|
||||
int i, ok = 1;
|
||||
|
||||
adc_health_init();
|
||||
for (i = 0; i < 2000; i++) {
|
||||
in = mk_in(seq, now);
|
||||
adc_health_check(&in, &st);
|
||||
if ((st.flags != 0u) || (st.events != 0u) || (st.sticky != 0u)) {
|
||||
ok = 0;
|
||||
}
|
||||
seq++;
|
||||
now++;
|
||||
}
|
||||
CHECK(ok, "TC-AH-002 healthy 1kHz sweep 2000 beats: zero flags/events");
|
||||
}
|
||||
|
||||
/* TC-AH-003:TPAFE 静默 99/100ms 门限 + 恢复留痕 */
|
||||
static void tc_tpafe_stall(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
uint32_t seq = 500u, now = 500u;
|
||||
int i;
|
||||
|
||||
adc_health_init();
|
||||
/* 先跑 10 拍健康节拍建立"前进中"基线 */
|
||||
for (i = 0; i < 10; i++) {
|
||||
in = mk_in(seq, now);
|
||||
adc_health_check(&in, &st);
|
||||
seq++; now++;
|
||||
}
|
||||
/* 仅 TPAFE 冻结(STM32 继续走):前 100 拍(elapsed 0..99ms)不报。
|
||||
* 注意第 1 拍会消费掉 healthy 循环末尾"未消费的那次 +1",
|
||||
* 故静默计时从 now=510 起算,第 i 拍 elapsed = i。 */
|
||||
for (i = 0; i < 100; i++) {
|
||||
in = mk_in(seq, now);
|
||||
in.stm32_seq = seq + (uint32_t)i + 1u; /* STM32 侧照常前进 */
|
||||
adc_health_check(&in, &st);
|
||||
now++;
|
||||
}
|
||||
CHECK((st.flags & ADC_HF_TPAFE_STALL) == 0u,
|
||||
"TC-AH-003 no TPAFE stall before 100ms");
|
||||
/* 第 100ms:报 */
|
||||
in = mk_in(seq, now);
|
||||
in.stm32_seq = seq + 100u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.flags & ADC_HF_TPAFE_STALL) != 0u,
|
||||
"TC-AH-003 TPAFE stall at 100ms");
|
||||
CHECK((st.sticky & ADC_HF_TPAFE_STALL) != 0u,
|
||||
"TC-AH-003 stall latched into sticky");
|
||||
CHECK(st.tpafe_stall_ms >= ADC_HEALTH_STALL_MS,
|
||||
"TC-AH-003 stall_ms reported >= threshold");
|
||||
/* 恢复:TPAFE 序号重新前进 → 电平位清除、sticky 留痕 */
|
||||
in = mk_in(seq + 1u, now + 1u);
|
||||
in.stm32_seq = seq + 101u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.flags & ADC_HF_TPAFE_STALL) == 0u,
|
||||
"TC-AH-003 stall level clears on recovery");
|
||||
CHECK((adc_health_sticky() & ADC_HF_TPAFE_STALL) != 0u,
|
||||
"TC-AH-003 sticky keeps the fault trace after recovery");
|
||||
}
|
||||
|
||||
/* TC-AH-004:STM32 静默(TPAFE 正常) */
|
||||
static void tc_stm32_stall(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
uint32_t seq = 100u, now = 100u;
|
||||
int i;
|
||||
|
||||
adc_health_init();
|
||||
for (i = 0; i < 10; i++) {
|
||||
in = mk_in(seq, now);
|
||||
adc_health_check(&in, &st);
|
||||
seq++; now++;
|
||||
}
|
||||
/* STM32 冻结(TPAFE 继续走)。⚠ 第 1 拍消费 healthy 循环末尾的"未消费 +1"
|
||||
* 并把静默计时起点重置为该拍 now → 第 i 拍 elapsed = i,需 101 拍才到 100ms */
|
||||
for (i = 0; i < 101; i++) {
|
||||
in = mk_in(seq + (uint32_t)i + 1u, now + (uint32_t)i + 1u);
|
||||
in.stm32_seq = seq; /* 冻结在旧值 */
|
||||
adc_health_check(&in, &st);
|
||||
}
|
||||
CHECK((st.flags & ADC_HF_STM32_STALL) != 0u,
|
||||
"TC-AH-004 STM32 stall at 100ms");
|
||||
CHECK((st.flags & ADC_HF_TPAFE_STALL) == 0u,
|
||||
"TC-AH-004 healthy TPAFE not falsely stalled");
|
||||
}
|
||||
|
||||
/* TC-AH-005:TPAFE 丢帧计数 + 边沿语义 */
|
||||
static void tc_tpafe_gap(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(10u, 10u);
|
||||
adc_health_check(&in, &st); /* 基线 */
|
||||
in.tpafe_seq = 13u; in.stm32_seq = 11u; in.now_ms = 11u; /* TPAFE d=3 */
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.events & ADC_HE_TPAFE_GAP) != 0u,
|
||||
"TC-AH-005 gap event on d>1");
|
||||
CHECK(st.tpafe_gaps == 2u, "TC-AH-005 d=3 accumulates 2 lost points");
|
||||
in.tpafe_seq = 14u; in.stm32_seq = 12u; in.now_ms = 12u; /* 恢复正常 d=1 */
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(st.events == 0u, "TC-AH-005 gap event is edge-only (next beat clean)");
|
||||
CHECK(st.tpafe_gaps == 2u, "TC-AH-005 gap counter is cumulative");
|
||||
}
|
||||
|
||||
/* TC-AH-006:STM32 gap 计数增量 → 事件、不入锁存 */
|
||||
static void tc_stm32_gap(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(1u, 1u);
|
||||
adc_health_check(&in, &st);
|
||||
in.stm32_gaps = 1u; in.tpafe_seq = 2u; in.stm32_seq = 2u; in.now_ms = 2u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.events & ADC_HE_STM32_GAP) != 0u,
|
||||
"TC-AH-006 STM32 gap increment raises event");
|
||||
CHECK((st.sticky & (ADC_HF_FRSTDATA | ADC_HF_STM32_ERR |
|
||||
ADC_HF_HW_ERR)) == 0u,
|
||||
"TC-AH-006 gap does NOT latch sticky (overrun is not a fault)");
|
||||
}
|
||||
|
||||
/* TC-AH-007:序号倒退 → 锁存 */
|
||||
static void tc_backward(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
uint32_t s, t;
|
||||
int i;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(1000u, 100u);
|
||||
adc_health_check(&in, &st);
|
||||
in.tpafe_seq = 995u; in.stm32_seq = 995u; in.now_ms = 101u; /* 倒退 */
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.flags & ADC_HF_SEQ_BACKWARD) != 0u,
|
||||
"TC-AH-007 backward seq raises latched flag");
|
||||
CHECK((st.sticky & ADC_HF_SEQ_BACKWARD) != 0u,
|
||||
"TC-AH-007 backward latched into sticky");
|
||||
/* 恢复正常推进 50 拍:SEQ_BACKWARD 不清(锁存语义) */
|
||||
s = 996u; t = 102u;
|
||||
for (i = 0; i < 50; i++) {
|
||||
in = mk_in(s, t);
|
||||
adc_health_check(&in, &st);
|
||||
s++; t++;
|
||||
}
|
||||
CHECK((adc_health_flags() & ADC_HF_SEQ_BACKWARD) != 0u,
|
||||
"TC-AH-007 SEQ_BACKWARD persists after normal advance");
|
||||
}
|
||||
|
||||
/* TC-AH-008:三类错误计数增量 → 事件位与锁存位编号一致 */
|
||||
static void tc_err_counters(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(1u, 1u);
|
||||
adc_health_check(&in, &st);
|
||||
|
||||
in.tpafe_seq = 2u; in.stm32_seq = 2u; in.now_ms = 2u;
|
||||
in.tpafe_frst_err = 1u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(((st.events & ADC_HE_FRSTDATA) != 0u) &&
|
||||
((st.sticky & ADC_HF_FRSTDATA) != 0u),
|
||||
"TC-AH-008 FRSTDATA increment: event + sticky (same bit number)");
|
||||
|
||||
in.tpafe_seq = 3u; in.stm32_seq = 3u; in.now_ms = 3u;
|
||||
in.stm32_errs = 1u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(((st.events & ADC_HE_STM32_ERR) != 0u) &&
|
||||
((st.sticky & ADC_HF_STM32_ERR) != 0u),
|
||||
"TC-AH-008 STM32 err increment: event + sticky (same bit number)");
|
||||
|
||||
in.tpafe_seq = 4u; in.stm32_seq = 4u; in.now_ms = 4u;
|
||||
in.stm32_hw_errs = 1u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(((st.events & ADC_HE_HW_ERR) != 0u) &&
|
||||
((st.sticky & ADC_HF_HW_ERR) != 0u),
|
||||
"TC-AH-008 HAL err increment: event + sticky (same bit number)");
|
||||
|
||||
/* 计数不再变化 → 事件不再重复触发 */
|
||||
in.tpafe_seq = 5u; in.stm32_seq = 5u; in.now_ms = 5u;
|
||||
adc_health_check(&in, &st);
|
||||
CHECK(st.events == 0u, "TC-AH-008 steady error counters raise no repeat events");
|
||||
}
|
||||
|
||||
/* TC-AH-009:tick 回绕安全 */
|
||||
static void tc_tick_wrap(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
uint32_t seq = 70000u, now = 0xFFFFFF00u;
|
||||
int i, ok = 1;
|
||||
|
||||
adc_health_init();
|
||||
/* 跨 0xFFFFFFFF 正常推进 512 拍:不得误报静默 */
|
||||
for (i = 0; i < 512; i++) {
|
||||
in = mk_in(seq, now);
|
||||
adc_health_check(&in, &st);
|
||||
if (st.flags != 0u) {
|
||||
ok = 0;
|
||||
}
|
||||
seq++; now++; /* uint32 自然回绕 */
|
||||
}
|
||||
CHECK(ok, "TC-AH-009 tick wrap sweep: no false stall");
|
||||
/* 回绕后两侧同时冻结。⚠ 第 1 拍消费 sweep 末尾的"未消费 +1"并重置计时起点
|
||||
* → 第 i 拍 elapsed = i,需 101 拍才到 100ms */
|
||||
for (i = 0; i < 101; i++) {
|
||||
in = mk_in(seq, now);
|
||||
adc_health_check(&in, &st);
|
||||
now++;
|
||||
}
|
||||
CHECK(((st.flags & ADC_HF_TPAFE_STALL) != 0u) &&
|
||||
((st.flags & ADC_HF_STM32_STALL) != 0u),
|
||||
"TC-AH-009 stall still detected after tick wrap");
|
||||
}
|
||||
|
||||
/* TC-AH-010:NULL 守卫 */
|
||||
static void tc_null_guard(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
int i;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(1u, 1u);
|
||||
adc_health_check(&in, &st);
|
||||
st.flags = 0xA5A5A5A5u;
|
||||
adc_health_check(NULL, &st);
|
||||
CHECK(st.flags == 0xA5A5A5A5u, "TC-AH-010 in=NULL leaves out untouched");
|
||||
|
||||
/* out=NULL:内部状态照常更新(两侧冻结 101 拍 → 静默位应出现) */
|
||||
for (i = 0; i < 101; i++) {
|
||||
in = mk_in(1u, (uint32_t)(2 + i));
|
||||
adc_health_check(&in, NULL);
|
||||
}
|
||||
CHECK((adc_health_flags() & ADC_HF_TPAFE_STALL) != 0u,
|
||||
"TC-AH-010 out=NULL still updates internal state");
|
||||
}
|
||||
|
||||
/* TC-AH-011:init 幂等 / 故障后全清 */
|
||||
static void tc_reinit(void) {
|
||||
adc_health_status_t st;
|
||||
adc_health_in_t in;
|
||||
int i;
|
||||
|
||||
adc_health_init();
|
||||
in = mk_in(1u, 1u);
|
||||
adc_health_check(&in, &st);
|
||||
for (i = 0; i < 150; i++) { /* 制造双侧静默 */
|
||||
in = mk_in(1u, (uint32_t)(2 + i));
|
||||
adc_health_check(&in, &st);
|
||||
}
|
||||
CHECK(st.sticky != 0u, "TC-AH-011 pre: sticky non-zero before re-init");
|
||||
adc_health_init();
|
||||
CHECK((adc_health_flags() == 0u) && (adc_health_sticky() == 0u) &&
|
||||
(adc_health_tpafe_gaps() == 0u),
|
||||
"TC-AH-011 re-init clears flags/sticky/gaps");
|
||||
in = mk_in(9u, 9u); /* 序号跳变也无妨:首拍只建基线 */
|
||||
adc_health_check(&in, &st);
|
||||
CHECK((st.flags == 0u) && (st.events == 0u),
|
||||
"TC-AH-011 re-prime after re-init is clean");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("=== ADC Health Tests ===\n");
|
||||
|
||||
printf("-- prime / healthy --\n");
|
||||
tc_prime();
|
||||
tc_healthy();
|
||||
printf("-- stall (TPAFE / STM32) --\n");
|
||||
tc_tpafe_stall();
|
||||
tc_stm32_stall();
|
||||
printf("-- gap / backward / err counters --\n");
|
||||
tc_tpafe_gap();
|
||||
tc_stm32_gap();
|
||||
tc_backward();
|
||||
tc_err_counters();
|
||||
printf("-- tick wrap / guards / re-init --\n");
|
||||
tc_tick_wrap();
|
||||
tc_null_guard();
|
||||
tc_reinit();
|
||||
|
||||
printf("\n=== ADC Health Tests: %d/%d PASSED (failed=%d) ===\n",
|
||||
s_passed, s_total, s_failed);
|
||||
return (s_failed == 0) ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""ADC 采样有效性校验(L1-6)的主机侧单元测试运行器(L0.5,纯标准库)。
|
||||
|
||||
做什么:
|
||||
用本机 MSVC 编译 test/host/adc_health/adc_health_test.c(它以 #include 纳入
|
||||
**生产源文件** App/algo/adc_health.c),在 PC 上离线跑完整的判定逻辑验证:
|
||||
首拍建基线 / 健康不误报 / 静默 100ms 门限与恢复留痕 / 丢帧边沿语义 /
|
||||
序号倒退锁存 / 三类错误计数增量 / tick 回绕 / NULL 守卫 / init 幂等,
|
||||
失败即非 0 退出。零硬件、零烧录、毫秒级。
|
||||
|
||||
工具链探测 / INCLUDE-LIB 拼接 / 编译运行 / 退出码判定全部委托给通用 harness
|
||||
`test/host/common/unit_test_harness.py`(本文件只做声明)。
|
||||
|
||||
为什么要主机侧单测(而不是只用板端闭环):
|
||||
静默/倒退/错误增量在健康台架上不可复现(复现 = 拔芯片/改驱动)——板端只能
|
||||
证明"健康时不误报",证不了"故障时必报";而 100ms 门限、tick 回绕、事件
|
||||
边沿语义这些边界只有合成计数序列能精确构造。
|
||||
|
||||
本层为**纯逻辑**:无寄存器、无 RTOS、无文件/外设依赖,故**不需要任何桩目录**。
|
||||
|
||||
用法(仓库根目录):
|
||||
python test/host/adc_health/run_unit_test.py
|
||||
或统一用 .venv: & '.venv\\Scripts\\python.exe' test/host/adc_health/run_unit_test.py
|
||||
|
||||
退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。
|
||||
|
||||
设计依据:docs/算法/继电保护功能复现规划.md §3.1(L1-6);
|
||||
docs/测试说明/测试开发标准流程.md §4.2(L0.5 主机侧单测)。
|
||||
创建日期:2026-10-11
|
||||
"""
|
||||
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
|
||||
|
||||
# 无桩目录:被测代码为纯逻辑(adc_health.c 仅依赖 stdint.h 与自身头)。
|
||||
BUILD = TestBuild(
|
||||
name="ADC Health Tests",
|
||||
src=os.path.join(HERE, "adc_health_test.c"),
|
||||
include_dirs=[
|
||||
os.path.join(ROOT, "App", "algo"),
|
||||
HERE,
|
||||
],
|
||||
summary_marker="=== ADC Health Tests:",
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_host_unit_test(BUILD))
|
||||
Reference in New Issue
Block a user