refactor(编号): 16 个测试模块码单词化 + 门禁识别面连带放宽

批 2(用户授权改名 + 「新名要一眼看懂」裁定)
- 16 个有歧义模块码单词化,共 1,146 处随 scripts/rename_ids.py 改写:
  AI→ADCIN、AH→ADCHEALTH、PS→PROTSET、PE→PROTELEM、PH→PHASOR、
  TS→TIMESYNC、VL→VOLLOCK、NP→NANDPORT、CFG→CONFIG、CLK→SYSCLK、
  WD→WATCHDOG、STO→STORAGE、SH→SHA256、FA→FTPAUTH、FR→FREQ、104→IEC104
- 不动 NET/GD5F/RTC/SOE/UI/ADC/LOG/RS485/TOOL(已是单词、芯片名或业界通用词,
  改了纯属 churn)
- 别名按全局登记:这批字面量已完全限定(TC-<码>-<nnn>),不存在裸形多义
- 映射表存档 scripts/rename_maps/batch2.json 作审计轨迹;§6 模块码表同步

连带修门禁(关键教训)
- 模块码涨到 9 位(ADCHEALTH/WATCHDOG)后,候选正则与族正则的 {0,4} 上界
  会让改名后的号**整批从门禁眼里消失**:实测编号字面量从 8271 掉到 7315、
  悬空假降 490 处。已放宽到 {0,9} 并写进 §6 注记
- 结论:改名批次必须连带复核识别面,只改数据不改判据 = 静默放行;
  这次是靠「可判定比例跌破基线即失败」那条线拦下来的

现状与遗留
- 校验 1 未登记前缀 0 处;可判定比例 82.71%(基线 82.6%,只涨不跌成立)
- 遗留:7 个模块的「单元测试说明.md」仍缺(PROTSET 116、NANDPORT 109、
  PROTELEM 65、FREQ 48、FTPAUTH 45、SHA256 25、SOE 14 处悬空)——改名不解决
  缺文档,处置方式待议
- 遗留:T-2/T-3/T-4/T-6 历史任务号悬空(别名表未收全,属本工具批次漏项)
- 未改任何 C/H 可编译语义(仅注释与宏名内的编号),故不需 @build
This commit is contained in:
2026-10-21 09:53:28 +08:00
parent 301c3e5183
commit bda7ab2b50
45 changed files with 3706 additions and 1295 deletions
+112 -112
View File
@@ -5,22 +5,22 @@
* 被测对象:真实源文件(#include 原样纳入)。纯逻辑,无需桩。
*
* 覆盖点(docs/算法/继电保护功能复现规划.md §5.2 / §3.4 L5-1):
* TC-PS-001 init:默认值装载、越界位图 0、selfcheck 通过、未闭锁
* TC-PS-002 set:范围内写入生效;越界拒写且原值不动
* TC-PS-003 校验和封存语义:set 后未 seal → selfcheck 失败并闭锁;
* TC-PROTSET-001 init:默认值装载、越界位图 0、selfcheck 通过、未闭锁
* TC-PROTSET-002 set:范围内写入生效;越界拒写且原值不动
* TC-PROTSET-003 校验和封存语义:set 后未 seal → selfcheck 失败并闭锁;
* seal → 通过并解锁(L5-1 核心闭环)
* TC-PS-004 load_raw:合法整表装载并封存;含越界项 → 整表不装载 +
* TC-PROTSET-004 load_raw:合法整表装载并封存;含越界项 → 整表不装载 +
* bad_mask 指认越界项(定值一致性:宁可全旧不可半新)
* TC-PS-005 Q10 往返精度(±1 LSB)
* TC-PS-006 元数据表自检:min<=max、投退项 0..1、非零通讯地址不重复
* TC-PS-007 越界编号守卫(get/set)
* TC-PS-008 全局软压板 PS_GLOBAL_EN(B7):默认投入、set_sealed 原子写
* TC-PROTSET-005 Q10 往返精度(±1 LSB)
* TC-PROTSET-006 元数据表自检:min<=max、投退项 0..1、非零通讯地址不重复
* TC-PROTSET-007 越界编号守卫(get/set)
* TC-PROTSET-008 全局软压板 PS_GLOBAL_EN(B7):默认投入、set_sealed 原子写
* 不破坏 selfcheck、脏标志三件套(peek/take/mark)
* TC-PS-009 持久化 blob 往返:serialize → init 清场 → parse 恢复
* TC-PROTSET-009 持久化 blob 往返:serialize → init 清场 → parse 恢复
* (位精确 + 封存自洽 + parse 不置脏)
* TC-PS-010 损坏 blob 整表拒绝(all-or-nothing):值区位翻转/坏 magic/
* TC-PROTSET-010 损坏 blob 整表拒绝(all-or-nothing):值区位翻转/坏 magic/
* 截断/超长/坏版本/伪造自洽越界 → 全部拒绝且活跃值区一字不动
* TC-PS-011 OF/UF 定值行(B8):40 项 / blob 版本 2 / 本地项地址 0 /
* TC-PROTSET-011 OF/UF 定值行(B8):40 项 / blob 版本 2 / 本地项地址 0 /
* 默认值与范围 / 返回系数独立性 / 64 位 bad_mask(bit 39)/
* B7 旧档(32 项)换代拒绝
*
@@ -40,46 +40,46 @@ static int s_total = 0, s_passed = 0, s_failed = 0;
#include "prot_set.c"
/* TC-PS-001 */
/* TC-PROTSET-001 */
static void tc_init(void) {
prot_set_init();
CHECK(prot_set_bad_mask() == 0u, "TC-PS-001 init: no bad items");
CHECK(prot_set_selfcheck() == 0, "TC-PS-001 init: selfcheck pass");
CHECK(prot_set_locked() == 0u, "TC-PS-001 init: not locked");
CHECK(prot_set_bad_mask() == 0u, "TC-PROTSET-001 init: no bad items");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-001 init: selfcheck pass");
CHECK(prot_set_locked() == 0u, "TC-PROTSET-001 init: not locked");
CHECK(prot_set_get_f(PS_OC1_CUR) > 9.99f && prot_set_get_f(PS_OC1_CUR) < 10.01f,
"TC-PS-001 default OC1 current = 10.0 A");
"TC-PROTSET-001 default OC1 current = 10.0 A");
CHECK(prot_set_get_ctl(PS_OC3_TRIP) == 0u,
"TC-PS-001 default OC3 = alarm (trip off)");
"TC-PROTSET-001 default OC3 = alarm (trip off)");
}
/* TC-PS-002 */
/* TC-PROTSET-002 */
static void tc_set_range(void) {
prot_set_init();
CHECK(prot_set_set(PS_OC2_CUR, PROT_SET_Q10(7.5)) == 0,
"TC-PS-002 in-range set accepted");
"TC-PROTSET-002 in-range set accepted");
CHECK(prot_set_get_f(PS_OC2_CUR) > 7.49f && prot_set_get_f(PS_OC2_CUR) < 7.51f,
"TC-PS-002 value readable after set");
"TC-PROTSET-002 value readable after set");
CHECK(prot_set_set(PS_OC2_CUR, PROT_SET_Q10(101.0)) == -1,
"TC-PS-002 over-max set rejected");
"TC-PROTSET-002 over-max set rejected");
CHECK(prot_set_get_f(PS_OC2_CUR) > 7.49f && prot_set_get_f(PS_OC2_CUR) < 7.51f,
"TC-PS-002 rejected set leaves value unchanged");
"TC-PROTSET-002 rejected set leaves value unchanged");
CHECK(prot_set_set(PS_OC1_EN, PROT_SET_Q10(2)) == -1,
"TC-PS-002 ctl item rejects value 2");
"TC-PROTSET-002 ctl item rejects value 2");
}
/* TC-PS-003 */
/* TC-PROTSET-003 */
static void tc_seal_selfcheck(void) {
prot_set_init();
CHECK(prot_set_set(PS_OC1_CUR, PROT_SET_Q10(8.0)) == 0, "TC-PS-003 set ok");
CHECK(prot_set_set(PS_OC1_CUR, PROT_SET_Q10(8.0)) == 0, "TC-PROTSET-003 set ok");
CHECK(prot_set_selfcheck() == -1,
"TC-PS-003 set-without-seal => selfcheck FAIL (tamper detect)");
CHECK(prot_set_locked() == 1u, "TC-PS-003 selfcheck failure latches lock");
"TC-PROTSET-003 set-without-seal => selfcheck FAIL (tamper detect)");
CHECK(prot_set_locked() == 1u, "TC-PROTSET-003 selfcheck failure latches lock");
prot_set_seal();
CHECK(prot_set_selfcheck() == 0, "TC-PS-003 seal => selfcheck pass");
CHECK(prot_set_locked() == 0u, "TC-PS-003 seal clears lock");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-003 seal => selfcheck pass");
CHECK(prot_set_locked() == 0u, "TC-PROTSET-003 seal clears lock");
}
/* TC-PS-004 */
/* TC-PROTSET-004 */
static void tc_load_raw(void) {
int32_t tbl[PS_ID_COUNT];
uint32_t i;
@@ -89,38 +89,38 @@ static void tc_load_raw(void) {
tbl[i] = prot_set_get((prot_set_id_t)i);
}
tbl[PS_OL_CUR] = PROT_SET_Q10(1.5);
CHECK(prot_set_load_raw(tbl) == 0, "TC-PS-004 valid table loads");
CHECK(prot_set_load_raw(tbl) == 0, "TC-PROTSET-004 valid table loads");
CHECK(prot_set_get_f(PS_OL_CUR) > 1.49f && prot_set_get_f(PS_OL_CUR) < 1.51f,
"TC-PS-004 loaded value visible");
CHECK(prot_set_selfcheck() == 0, "TC-PS-004 load_raw auto-seals");
"TC-PROTSET-004 loaded value visible");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-004 load_raw auto-seals");
tbl[PS_OC3_DLY] = PROT_SET_Q10(60001.0); /* 越上限 */
tbl[PS_OL_CUR] = PROT_SET_Q10(2.5); /* 合法改动 */
CHECK(prot_set_load_raw(tbl) == -1, "TC-PS-004 bad table rejected");
CHECK(prot_set_load_raw(tbl) == -1, "TC-PROTSET-004 bad table rejected");
CHECK(prot_set_bad_mask() == (1uLL << PS_OC3_DLY),
"TC-PS-004 bad_mask points at the offending item");
"TC-PROTSET-004 bad_mask points at the offending item");
CHECK(prot_set_get_f(PS_OL_CUR) > 1.49f && prot_set_get_f(PS_OL_CUR) < 1.51f,
"TC-PS-004 rejected load keeps OLD table (all-or-nothing)");
CHECK(prot_set_load_raw(0) == -1, "TC-PS-004 NULL table rejected");
"TC-PROTSET-004 rejected load keeps OLD table (all-or-nothing)");
CHECK(prot_set_load_raw(0) == -1, "TC-PROTSET-004 NULL table rejected");
}
/* TC-PS-005 */
/* TC-PROTSET-005 */
static void tc_q10_roundtrip(void) {
float v = 12.345f;
int32_t q;
prot_set_init();
q = PROT_SET_Q10(v);
CHECK(prot_set_set(PS_OC1_CUR, q) == 0, "TC-PS-005 set ok");
CHECK(prot_set_set(PS_OC1_CUR, q) == 0, "TC-PROTSET-005 set ok");
{
float back = prot_set_get_f(PS_OC1_CUR);
float err = back - v;
if (err < 0.0f) { err = -err; }
CHECK(err < 0.001f, "TC-PS-005 Q10 roundtrip error < 1 LSB");
CHECK(err < 0.001f, "TC-PROTSET-005 Q10 roundtrip error < 1 LSB");
}
}
/* TC-PS-006 */
/* TC-PROTSET-006 */
static void tc_meta_sanity(void) {
uint32_t i, j;
int ok_range = 1, ok_ctl = 1, ok_addr = 1;
@@ -136,40 +136,40 @@ static void tc_meta_sanity(void) {
if (g_prot_set_meta[j].comm_addr == m->comm_addr) { ok_addr = 0; }
}
}
CHECK(ok_range, "TC-PS-006 meta: min<=def<=max for all items");
CHECK(ok_ctl, "TC-PS-006 meta: ctl items are 0..1");
CHECK(ok_addr, "TC-PS-006 meta: comm addresses unique");
CHECK((uint32_t)PS_ID_COUNT <= 64u, "TC-PS-006 item count fits 64-bit bad_mask (B8: 40)");
CHECK(ok_range, "TC-PROTSET-006 meta: min<=def<=max for all items");
CHECK(ok_ctl, "TC-PROTSET-006 meta: ctl items are 0..1");
CHECK(ok_addr, "TC-PROTSET-006 meta: comm addresses unique");
CHECK((uint32_t)PS_ID_COUNT <= 64u, "TC-PROTSET-006 item count fits 64-bit bad_mask (B8: 40)");
}
/* TC-PS-007 */
/* TC-PROTSET-007 */
static void tc_id_guard(void) {
prot_set_init();
CHECK(prot_set_get(PS_ID_COUNT) == 0, "TC-PS-007 get out-of-range id -> 0");
CHECK(prot_set_set(PS_ID_COUNT, 0) == -1, "TC-PS-007 set out-of-range id -> -1");
CHECK(prot_set_set_sealed(PS_ID_COUNT, 0) == -1, "TC-PS-007 set_sealed id guard");
CHECK(prot_set_get(PS_ID_COUNT) == 0, "TC-PROTSET-007 get out-of-range id -> 0");
CHECK(prot_set_set(PS_ID_COUNT, 0) == -1, "TC-PROTSET-007 set out-of-range id -> -1");
CHECK(prot_set_set_sealed(PS_ID_COUNT, 0) == -1, "TC-PROTSET-007 set_sealed id guard");
}
/* TC-PS-008(B7:全局软压板 + 原子写 + 脏标志) */
/* TC-PROTSET-008(B7:全局软压板 + 原子写 + 脏标志) */
static void tc_global_plate_dirty(void) {
prot_set_init();
CHECK(prot_set_dirty_peek() == 0u, "TC-PS-008 init not dirty");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-PS-008 global plate default IN");
CHECK(prot_set_set(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PS-008 plate rejects 2");
CHECK(prot_set_set_sealed(PS_GLOBAL_EN, 0) == 0, "TC-PS-008 plate OUT via set_sealed");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-008 plate OUT readable");
CHECK(prot_set_selfcheck() == 0, "TC-PS-008 set_sealed leaves selfcheck PASS (no unsealed window)");
CHECK(prot_set_locked() == 0u, "TC-PS-008 set_sealed no lock");
CHECK(prot_set_dirty_peek() == 1u, "TC-PS-008 set_sealed marks dirty");
CHECK(prot_set_dirty_take() == 1u, "TC-PS-008 dirty take consumes");
CHECK(prot_set_dirty_peek() == 0u, "TC-PS-008 dirty cleared after take");
CHECK(prot_set_dirty_peek() == 0u, "TC-PROTSET-008 init not dirty");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-PROTSET-008 global plate default IN");
CHECK(prot_set_set(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PROTSET-008 plate rejects 2");
CHECK(prot_set_set_sealed(PS_GLOBAL_EN, 0) == 0, "TC-PROTSET-008 plate OUT via set_sealed");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PROTSET-008 plate OUT readable");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-008 set_sealed leaves selfcheck PASS (no unsealed window)");
CHECK(prot_set_locked() == 0u, "TC-PROTSET-008 set_sealed no lock");
CHECK(prot_set_dirty_peek() == 1u, "TC-PROTSET-008 set_sealed marks dirty");
CHECK(prot_set_dirty_take() == 1u, "TC-PROTSET-008 dirty take consumes");
CHECK(prot_set_dirty_peek() == 0u, "TC-PROTSET-008 dirty cleared after take");
prot_set_dirty_mark();
CHECK(prot_set_dirty_peek() == 1u, "TC-PS-008 dirty mark re-arms (write-fail retry)");
CHECK(prot_set_set_sealed(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PS-008 set_sealed range check");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-008 rejected set_sealed keeps value");
CHECK(prot_set_dirty_peek() == 1u, "TC-PROTSET-008 dirty mark re-arms (write-fail retry)");
CHECK(prot_set_set_sealed(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PROTSET-008 set_sealed range check");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PROTSET-008 rejected set_sealed keeps value");
}
/* TC-PS-009(B7:blob 往返) */
/* TC-PROTSET-009(B7:blob 往返) */
static void tc_store_roundtrip(void) {
uint8_t blob[PROT_SET_BLOB_SZ];
uint32_t len = 0u;
@@ -180,15 +180,15 @@ static void tc_store_roundtrip(void) {
(void)prot_set_set_sealed(PS_GLOBAL_EN, 0);
(void)prot_set_dirty_take();
cur = prot_set_get(PS_OC1_CUR);
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PS-009 serialize ok");
CHECK(len == (uint32_t)PROT_SET_BLOB_SZ, "TC-PS-009 blob exact size");
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PROTSET-009 serialize ok");
CHECK(len == (uint32_t)PROT_SET_BLOB_SZ, "TC-PROTSET-009 blob exact size");
prot_set_init();
CHECK(prot_set_get(PS_OC1_CUR) != cur, "TC-PS-009 init wiped to defaults");
CHECK(prot_set_store_parse(blob, len) == 0, "TC-PS-009 parse ok");
CHECK(prot_set_get(PS_OC1_CUR) == cur, "TC-PS-009 value round-trip bit-exact");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-009 plate state round-trip");
CHECK(prot_set_selfcheck() == 0, "TC-PS-009 parsed table sealed");
CHECK(prot_set_dirty_peek() == 0u, "TC-PS-009 parse does not mark dirty");
CHECK(prot_set_get(PS_OC1_CUR) != cur, "TC-PROTSET-009 init wiped to defaults");
CHECK(prot_set_store_parse(blob, len) == 0, "TC-PROTSET-009 parse ok");
CHECK(prot_set_get(PS_OC1_CUR) == cur, "TC-PROTSET-009 value round-trip bit-exact");
CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PROTSET-009 plate state round-trip");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-009 parsed table sealed");
CHECK(prot_set_dirty_peek() == 0u, "TC-PROTSET-009 parse does not mark dirty");
}
/* 伪造辅助:按 blob 值区重算尾部 sum/sumn(构造"自洽但越界"的对抗样本) */
@@ -205,7 +205,7 @@ static void s_forge_tail(uint8_t *b, uint32_t len) {
s_put32(b + len - 4u, inv);
}
/* TC-PS-010(B7:损坏 blob 整表拒绝,all-or-nothing) */
/* TC-PROTSET-010(B7:损坏 blob 整表拒绝,all-or-nothing) */
static void tc_store_corrupt(void) {
uint8_t blob[PROT_SET_BLOB_SZ];
uint32_t len = 0u;
@@ -214,36 +214,36 @@ static void tc_store_corrupt(void) {
prot_set_init();
(void)prot_set_set_sealed(PS_OC2_CUR, PROT_SET_Q10(6.0));
keep = prot_set_get(PS_OC2_CUR);
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PS-010 serialize ok");
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PROTSET-010 serialize ok");
blob[PROT_SET_BLOB_HDR_SZ] ^= 0x01u; /* 值区一位翻转:sum 对不符 */
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 flipped value byte rejected (sum pair)");
CHECK(prot_set_get(PS_OC2_CUR) == keep, "TC-PS-010 reject leaves values untouched");
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PROTSET-010 flipped value byte rejected (sum pair)");
CHECK(prot_set_get(PS_OC2_CUR) == keep, "TC-PROTSET-010 reject leaves values untouched");
(void)prot_set_store_serialize(blob, sizeof(blob), &len);
blob[0] ^= 0xFFu; /* magic 破坏 */
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 bad magic rejected");
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PROTSET-010 bad magic rejected");
(void)prot_set_store_serialize(blob, sizeof(blob), &len);
CHECK(prot_set_store_parse(blob, len - 4u) == -1, "TC-PS-010 truncated blob rejected");
CHECK(prot_set_store_parse(blob, len + 4u) == -1, "TC-PS-010 oversized blob rejected");
CHECK(prot_set_store_parse(blob, len - 4u) == -1, "TC-PROTSET-010 truncated blob rejected");
CHECK(prot_set_store_parse(blob, len + 4u) == -1, "TC-PROTSET-010 oversized blob rejected");
(void)prot_set_store_serialize(blob, sizeof(blob), &len);
blob[5] ^= 0x02u; /* version 高字节:1 -> 0x200 */
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 version mismatch rejected");
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PROTSET-010 version mismatch rejected");
/* 对抗样本:越限定值 + 重算 sum 对(校验全过、范围必拦) */
(void)prot_set_store_serialize(blob, sizeof(blob), &len);
s_put32(blob + PROT_SET_BLOB_HDR_SZ + 4u * (uint32_t)PS_OC1_CUR,
(uint32_t)(g_prot_set_meta[PS_OC1_CUR].max + 1));
s_forge_tail(blob, len);
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 forged consistent out-of-range rejected");
CHECK(prot_set_bad_mask() == (1uLL << PS_OC1_CUR), "TC-PS-010 bad_mask points at item");
CHECK(prot_set_get(PS_OC1_CUR) == PROT_SET_Q10(10.0), "TC-PS-010 defaults still intact");
CHECK(prot_set_selfcheck() == 0, "TC-PS-010 active table still self-consistent after all rejects");
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PROTSET-010 forged consistent out-of-range rejected");
CHECK(prot_set_bad_mask() == (1uLL << PS_OC1_CUR), "TC-PROTSET-010 bad_mask points at item");
CHECK(prot_set_get(PS_OC1_CUR) == PROT_SET_Q10(10.0), "TC-PROTSET-010 defaults still intact");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-010 active table still self-consistent after all rejects");
}
/* TC-PS-011(B8:OF/UF 定值行 + 40 项 + 64 位 bad_mask + 换代拒绝) */
/* TC-PROTSET-011(B8:OF/UF 定值行 + 40 项 + 64 位 bad_mask + 换代拒绝) */
static void tc_of_uf_meta(void) {
uint8_t blob[PROT_SET_BLOB_SZ];
uint32_t len = 0u;
@@ -251,10 +251,10 @@ static void tc_of_uf_meta(void) {
prot_set_init();
/* 结构:40 项、blob 版本 2、尺寸随项数自适应 */
CHECK((uint32_t)PS_ID_COUNT == 40u, "TC-PS-011 PS_ID_COUNT == 40 (32 + 8 OF/UF)");
CHECK(PROT_SET_BLOB_VER == 2u, "TC-PS-011 blob version bumped to 2 (B8)");
CHECK((uint32_t)PS_ID_COUNT == 40u, "TC-PROTSET-011 PS_ID_COUNT == 40 (32 + 8 OF/UF)");
CHECK(PROT_SET_BLOB_VER == 2u, "TC-PROTSET-011 blob version bumped to 2 (B8)");
CHECK((uint32_t)PROT_SET_BLOB_SZ == (PROT_SET_BLOB_HDR_SZ + 4u * 40u + 8u),
"TC-PS-011 blob size = hdr + 4*40 + tail");
"TC-PROTSET-011 blob size = hdr + 4*40 + tail");
/* 地址:参考逐项地址不在本仓库 -> 8 项全部本地项(comm_addr=0,104 不可寻址) */
CHECK((g_prot_set_meta[PS_OF_EN].comm_addr == 0u)
@@ -265,60 +265,60 @@ static void tc_of_uf_meta(void) {
&& (g_prot_set_meta[PS_UF_DLY].comm_addr == 0u)
&& (g_prot_set_meta[PS_RET_OF].comm_addr == 0u)
&& (g_prot_set_meta[PS_RET_UF].comm_addr == 0u),
"TC-PS-011 OF/UF items all local (comm_addr=0, pending reference table)");
"TC-PROTSET-011 OF/UF items all local (comm_addr=0, pending reference table)");
/* 投退 = ctl 项(0/1),其余 = 模拟量 Q10 */
CHECK((g_prot_set_meta[PS_OF_EN].is_ctl == 1u) && (g_prot_set_meta[PS_UF_EN].is_ctl == 1u)
&& (g_prot_set_meta[PS_OF_HZ].is_ctl == 0u) && (g_prot_set_meta[PS_RET_UF].is_ctl == 0u),
"TC-PS-011 EN items are ctl, HZ/DLY/RET are Q10 analog");
"TC-PROTSET-011 EN items are ctl, HZ/DLY/RET are Q10 analog");
/* 出厂默认(拟定值)与范围 */
CHECK(prot_set_get(PS_OF_EN) == PROT_SET_Q10(1.0), "TC-PS-011 OF EN default 1");
CHECK(prot_set_get(PS_UF_EN) == PROT_SET_Q10(1.0), "TC-PS-011 UF EN default 1");
CHECK(prot_set_get(PS_OF_HZ) == PROT_SET_Q10(51.0), "TC-PS-011 OF default 51.0 Hz");
CHECK(prot_set_get(PS_UF_HZ) == PROT_SET_Q10(49.0), "TC-PS-011 UF default 49.0 Hz");
CHECK(prot_set_get(PS_OF_DLY) == PROT_SET_Q10(1000.0), "TC-PS-011 OF default 1000 ms");
CHECK(prot_set_get(PS_UF_DLY) == PROT_SET_Q10(1000.0), "TC-PS-011 UF default 1000 ms");
CHECK(prot_set_get(PS_RET_OF) == PROT_SET_Q10(0.99), "TC-PS-011 RET_OF default 0.99");
CHECK(prot_set_get(PS_RET_UF) == PROT_SET_Q10(1.01), "TC-PS-011 RET_UF default 1.01");
CHECK(prot_set_get(PS_OF_EN) == PROT_SET_Q10(1.0), "TC-PROTSET-011 OF EN default 1");
CHECK(prot_set_get(PS_UF_EN) == PROT_SET_Q10(1.0), "TC-PROTSET-011 UF EN default 1");
CHECK(prot_set_get(PS_OF_HZ) == PROT_SET_Q10(51.0), "TC-PROTSET-011 OF default 51.0 Hz");
CHECK(prot_set_get(PS_UF_HZ) == PROT_SET_Q10(49.0), "TC-PROTSET-011 UF default 49.0 Hz");
CHECK(prot_set_get(PS_OF_DLY) == PROT_SET_Q10(1000.0), "TC-PROTSET-011 OF default 1000 ms");
CHECK(prot_set_get(PS_UF_DLY) == PROT_SET_Q10(1000.0), "TC-PROTSET-011 UF default 1000 ms");
CHECK(prot_set_get(PS_RET_OF) == PROT_SET_Q10(0.99), "TC-PROTSET-011 RET_OF default 0.99");
CHECK(prot_set_get(PS_RET_UF) == PROT_SET_Q10(1.01), "TC-PROTSET-011 RET_UF default 1.01");
CHECK((g_prot_set_meta[PS_OF_HZ].min == PROT_SET_Q10(50.0))
&& (g_prot_set_meta[PS_OF_HZ].max == PROT_SET_Q10(55.0)),
"TC-PS-011 OF range 50.0~55.0 Hz");
"TC-PROTSET-011 OF range 50.0~55.0 Hz");
CHECK((g_prot_set_meta[PS_UF_HZ].min == PROT_SET_Q10(45.0))
&& (g_prot_set_meta[PS_UF_HZ].max == PROT_SET_Q10(50.0)),
"TC-PS-011 UF range 45.0~50.0 Hz");
"TC-PROTSET-011 UF range 45.0~50.0 Hz");
/* 频率返回系数与电气量系数独立:返回**门槛** = 定值×系数(Q10 乘积
* /1024)——OF 门槛 < 动作门槛、UF 门槛 > 动作门槛(方向相反) */
CHECK(((int64_t)prot_set_get(PS_OF_HZ) * (int64_t)prot_set_get(PS_RET_OF)) / 1024
< (int64_t)prot_set_get(PS_OF_HZ),
"TC-PS-011 OF return threshold (set x 0.99) below pickup");
"TC-PROTSET-011 OF return threshold (set x 0.99) below pickup");
CHECK(((int64_t)prot_set_get(PS_UF_HZ) * (int64_t)prot_set_get(PS_RET_UF)) / 1024
> (int64_t)prot_set_get(PS_UF_HZ),
"TC-PS-011 UF return threshold (set x 1.01) above pickup");
"TC-PROTSET-011 UF return threshold (set x 1.01) above pickup");
/* 投退可经 set_sealed 投/退(YK 口径同 GLOBAL_EN;Q10(2)=2048 越界拒) */
CHECK(prot_set_set_sealed(PS_OF_EN, 0) == 0, "TC-PS-011 OF EN set_sealed OK");
CHECK(prot_set_get_ctl(PS_OF_EN) == 0u, "TC-PS-011 OF EN readable after seal");
CHECK(prot_set_set_sealed(PS_OF_EN, PROT_SET_Q10(2)) == -1, "TC-PS-011 OF EN rejects Q10(2)");
CHECK(prot_set_selfcheck() == 0, "TC-PS-011 no lock after OF/UF seal ops");
CHECK(prot_set_set_sealed(PS_OF_EN, 0) == 0, "TC-PROTSET-011 OF EN set_sealed OK");
CHECK(prot_set_get_ctl(PS_OF_EN) == 0u, "TC-PROTSET-011 OF EN readable after seal");
CHECK(prot_set_set_sealed(PS_OF_EN, PROT_SET_Q10(2)) == -1, "TC-PROTSET-011 OF EN rejects Q10(2)");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-011 no lock after OF/UF seal ops");
/* 64 位 bad_mask:末项(bit 39 > 31)越界可指认 */
(void)prot_set_set_sealed(PS_OC1_CUR, PROT_SET_Q10(11.0));
(void)prot_set_dirty_take();
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PS-011 serialize ok");
CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PROTSET-011 serialize ok");
s_put32(blob + PROT_SET_BLOB_HDR_SZ + 4u * (uint32_t)PS_RET_UF,
(uint32_t)(g_prot_set_meta[PS_RET_UF].max + 1));
s_forge_tail(blob, len);
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-011 out-of-range RET_UF rejected");
CHECK(prot_set_store_parse(blob, len) == -1, "TC-PROTSET-011 out-of-range RET_UF rejected");
CHECK(prot_set_bad_mask() == (1uLL << PS_RET_UF),
"TC-PS-011 bad_mask bit 39 addressable (64-bit mask, B8)");
CHECK(prot_set_get(PS_RET_UF) == PROT_SET_Q10(1.01), "TC-PS-011 default RET_UF intact");
"TC-PROTSET-011 bad_mask bit 39 addressable (64-bit mask, B8)");
CHECK(prot_set_get(PS_RET_UF) == PROT_SET_Q10(1.01), "TC-PROTSET-011 default RET_UF intact");
/* 换代语义:B7 旧档(ver=1 / 32 项 = 144 B)在新固件必被拒 -> 出厂默认 */
CHECK(prot_set_store_parse(blob, 8u + 4u * 32u + 8u) == -1,
"TC-PS-011 legacy 32-item blob length rejected");
CHECK(prot_set_selfcheck() == 0, "TC-PS-011 active table intact after legacy reject");
"TC-PROTSET-011 legacy 32-item blob length rejected");
CHECK(prot_set_selfcheck() == 0, "TC-PROTSET-011 active table intact after legacy reject");
}
int main(void) {