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:
2026-10-24 20:57:46 +08:00
parent 5a806d8a26
commit 924ac3d428
31 changed files with 1626 additions and 1542 deletions
+83 -83
View File
@@ -49,15 +49,15 @@ static void tc_200_unknown_type(void)
msg.sockfd = 0;
msg.caller = (TaskHandle_t)&g_ns_task_caller;
msg.result = 12345; /* 脏值:分派必须覆写它 */
CHECK(ns_rtos_q_put_raw(&msg) == 0, "TC-NETSOCK-200a 原始消息入队");
CHECK(g_ns_notify_calls == 0, "TC-NETSOCK-200b 入队本身不产生通知");
CHECK(ns_rtos_q_put_raw(&msg) == 0, "TC-NETSOCK-200a raw message enqueued");
CHECK(g_ns_notify_calls == 0, "TC-NETSOCK-200b enqueue itself produces no notification");
net_process_messages(); /* 以 netTask 身份跑一轮 */
CHECK(g_ns_notify_calls == 1, "TC-NETSOCK-200c 未知 type 仍必发回执(否则调用方永久悬挂)");
CHECK(g_ns_notify_calls == 1, "TC-NETSOCK-200c unknown type must still send a receipt (else the caller hangs forever)");
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR,
"TC-NETSOCK-200d 未知 type 的通知值 = 本条的精确错误码 NET_ERR(不是上一条残留)");
CHECK(ns_rtos_q_count() == 0, "TC-NETSOCK-200e 本轮队列被排空(非阻塞 while 语义)");
"TC-NETSOCK-200d notify value for unknown type = this message exact code NET_ERR, not a leftover");
CHECK(ns_rtos_q_count() == 0, "TC-NETSOCK-200e queue drained within this round (non-blocking while semantics)");
reset_all();
}
@@ -70,9 +70,9 @@ static void tc_201_ticks_run_before_dispatch(void)
CHECK(g_peers.listener_tick_calls == 1 && g_peers.pending_tick_calls == 1 &&
g_peers.send_tick_calls == 1 && g_peers.reconcile_calls == 1,
"TC-NETSOCK-201a 空队列也要跑满四个自愈 tick(D10/pending×2/对账)");
"TC-NETSOCK-201a even with an empty queue all four self-heal ticks run (D10/pending x2/reconcile)");
CHECK(g_ns_notify_calls == 0 && g_ns_get_calls == 1,
"TC-NETSOCK-201b 空队列:取一次即退,不发通知");
"TC-NETSOCK-201b empty queue: one peek then exit, no notification");
reset_all();
}
@@ -85,7 +85,7 @@ static void tc_202_no_queue_bound(void)
net_process_messages();
CHECK(g_peers.listener_tick_calls == 0 && g_ns_get_calls == 0,
"TC-NETSOCK-202 未绑定队列就调 net_process_messages → 立即返回(不碰芯片也不跑 tick)");
"TC-NETSOCK-202 net_process_messages without a bound queue returns at once (no chip, no ticks)");
reset_all();
}
@@ -103,16 +103,16 @@ static void tc_210_send_end_to_end(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_send(fd, buf, (int)sizeof(buf), 0);
CHECK(rc == (int)sizeof(buf), "TC-NETSOCK-210a net_send 返回实际写入字节数");
CHECK(rc == (int)sizeof(buf), "TC-NETSOCK-210a net_send returns the number of bytes actually written");
CHECK(g_chip.write_calls == 1 && g_chip.last_read_len == (uint16_t)sizeof(buf),
"TC-NETSOCK-210b 一次写满(健康链路不拆块、不进挂起)");
CHECK(s_net_socks[fd].send_bytes == sizeof(buf), "TC-NETSOCK-210c 发送字节统计累计");
"TC-NETSOCK-210b one full write (a healthy path neither chunks nor goes pending)");
CHECK(s_net_socks[fd].send_bytes == sizeof(buf), "TC-NETSOCK-210c sent byte statistic accumulates");
CHECK(g_ns_notify_calls == 1 && g_ns_notify_last_val == (uint32_t)sizeof(buf),
"TC-NETSOCK-210d 结果经通知值回传(32 位整体即结果)");
"TC-NETSOCK-210d result travels back on the notify value (the whole 32 bits are the result)");
CHECK(g_ns_notify_last_to == (TaskHandle_t)&g_ns_task_caller,
"TC-NETSOCK-210e 通知发给**登记的那个 caller**,不是广播");
"TC-NETSOCK-210e notify goes to the REGISTERED caller only, not a broadcast");
CHECK(g_ns_block_waits == 1,
"TC-NETSOCK-210f 零等待没拾到 → 走阻塞分支(两段式拾取的第二段)");
"TC-NETSOCK-210f zero-wait found nothing -> blocking branch (second stage of the two-step peek)");
reset_all();
}
@@ -135,11 +135,11 @@ static void tc_211_send_chunking(void)
rc = net_send(fd, buf, 2500, 0);
CHECK(rc == 2500, "TC-NETSOCK-211a 2500 字节全部交付");
CHECK(g_chip.write_calls == 3, "TC-NETSOCK-211b 按 1024 上界切成 3 块(1024/1024/452)");
CHECK(g_chip.last_read_len == 452U, "TC-NETSOCK-211c 末块只写剩余量");
CHECK(rc == 2500, "TC-NETSOCK-211a all 2500 bytes delivered");
CHECK(g_chip.write_calls == 3, "TC-NETSOCK-211b split into 3 chunks at the 1024 bound (1024/1024/452)");
CHECK(g_chip.last_read_len == 452U, "TC-NETSOCK-211c last chunk writes only the remainder");
CHECK(NET_SEND_CHUNK_MAX == 1024,
"TC-NETSOCK-211d 分块粒度取芯片发送缓冲(不是假件自定的数)");
"TC-NETSOCK-211d chunk size comes from the chip send buffer, not a fake-defined number");
reset_all();
}
@@ -160,24 +160,24 @@ static void tc_212_send_pending_defers_notify(void)
msg.len = (int)sizeof(buf);
msg.caller = (TaskHandle_t)&g_ns_task_caller;
CHECK(ns_rtos_q_put_raw(&msg) == 0, "TC-NETSOCK-212a SEND 消息入队");
CHECK(ns_rtos_q_put_raw(&msg) == 0, "TC-NETSOCK-212a SEND message enqueued");
net_process_messages();
CHECK(g_peers.send_reg_calls == 1,
"TC-NETSOCK-212b 超自旋预算后登记挂起 send(而不是继续占着 netTask 忙等)");
"TC-NETSOCK-212b past the spin budget it registers a pending send instead of busy-waiting in netTask");
CHECK(g_peers.last_snd_fd == fd && g_peers.last_snd_len == (int)sizeof(buf) &&
g_peers.last_snd_sent == 0,
"TC-NETSOCK-212c 登记的进度=已写芯片字节数(此处 0),总长与 caller 一并带走");
"TC-NETSOCK-212c registered progress = bytes already written to the chip (0 here), length and caller travel too");
CHECK(g_ns_notify_calls == 0,
"TC-NETSOCK-212d 登记成功**绝不发即时回执**(否则「登记成功」被当成本次结果)");
"TC-NETSOCK-212d a successful registration NEVER sends an immediate receipt (else it reads as the result)");
CHECK(g_ns_notify_last_to == NULL,
"TC-NETSOCK-212e 一次通知都没发生(0x70000000 哨兵值也没可能漏进通知值)");
"TC-NETSOCK-212e not a single notification (the 0x70000000 sentinel can not leak into a notify value)");
/* 完成时刻:由挂起 send 的 tick 结束(本套由桩脚本模拟"缓冲腾出来了") */
ns_peers_arm_send_pending_done(fd, 64);
net_process_messages();
CHECK(g_ns_notify_calls == 1 && g_ns_notify_last_val == 64U,
"TC-NETSOCK-212f 挂起完成后才发回执,通知值=实际写出字节数");
"TC-NETSOCK-212f receipt only after the pending completes, notify value = bytes actually written");
reset_all();
}
@@ -201,7 +201,7 @@ static void tc_213_send_error_code_roundtrip(void)
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_NOTCONN,
"TC-NETSOCK-213a 未连接的 SEND:通知值=NET_ERR_NOTCONN(精确码回传,供调用方分支)");
"TC-NETSOCK-213a SEND on a not-connected socket: notify value = NET_ERR_NOTCONN (exact code for caller branches)");
/* 端到端:公开 net_send 的 BADF 形态(fd 越界由**分派侧**再判一次) */
reset_all();
@@ -215,16 +215,16 @@ static void tc_213_send_error_code_roundtrip(void)
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_BADF,
"TC-NETSOCK-213b 范围内但未分配的 fd:net_get_sock 判空 → BADF 搭通知值回来");
"TC-NETSOCK-213b in range but unallocated fd: net_get_sock null -> BADF travels on the notify value");
/* 调用方上下文恢复 errno:拿到的必须是"本任务的"精确码 */
reset_all();
bring_up();
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_send(6, buf, 4, 0); /* 6 未分配 → 分派侧 BADF → 通知值 -2 */
CHECK(rc == -1, "TC-NETSOCK-213c 对外保持 BSD 语义:失败一律 -1");
CHECK(rc == -1, "TC-NETSOCK-213c BSD semantics kept for callers: any failure is -1");
CHECK(net_get_errno() == NET_ERR_BADF,
"TC-NETSOCK-213d 调用方在自己的错误码槽里拿到精确码(E-03 + 通知值回传合力)");
"TC-NETSOCK-213d caller reads the exact code from its own errno slot (E-03 plus notify value together)");
reset_all();
}
@@ -243,13 +243,13 @@ static void tc_220_recv_fast_path(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_recv(fd, buf, 10, NET_MSG_DONTWAIT);
CHECK(rc == 10, "TC-NETSOCK-220a 缓冲 1400B、只给 10B 缓冲 → 读满 10(部分读合法)");
CHECK(rc == 10, "TC-NETSOCK-220a chip has 1400B but the caller buffer is 10B -> reads 10 (a partial read is legal)");
CHECK(g_chip.read_calls == 1 && g_chip.last_read_len == 10U,
"TC-NETSOCK-220b 只读调用方给的量(不得按芯片可用量越界写)");
CHECK(s_net_socks[fd].recv_bytes == 10U, "TC-NETSOCK-220c 接收字节统计累计");
"TC-NETSOCK-220b reads only what the caller offered (never the chip available length)");
CHECK(s_net_socks[fd].recv_bytes == 10U, "TC-NETSOCK-220c received byte statistic accumulates");
CHECK(s_net_socks[fd].readable == 0U,
"TC-NETSOCK-220d 读过即清 readable(下一次 RECV_OK 中断再置)");
CHECK(g_peers.pending_reg_calls == 0, "TC-NETSOCK-220e 数据已在手,不该登记挂起");
"TC-NETSOCK-220d reading clears readable (the next RECV_OK interrupt sets it again)");
CHECK(g_peers.pending_reg_calls == 0, "TC-NETSOCK-220e data is already in hand, no pending registration");
reset_all();
}
@@ -266,18 +266,18 @@ static void tc_221_recv_wouldblock(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_recv(fd, buf, (int)sizeof(buf), NET_MSG_DONTWAIT);
CHECK(rc == -1 && net_get_errno() == NET_ERR_WOULDBLOCK,
"TC-NETSOCK-221a DONTWAIT 无数据 → -1 + WOULDBLOCK");
"TC-NETSOCK-221a DONTWAIT with no data -> -1 plus WOULDBLOCK");
CHECK(g_peers.pending_reg_calls == 0,
"TC-NETSOCK-221b 非阻塞绝不登记挂起(否则调用方以为自己在等,实际已被挂住)");
"TC-NETSOCK-221b non-blocking never registers pending (else the caller thinks it waits while it is parked)");
/* 模式属性(net_setblocking(0))与单次标志同判据 */
CHECK(net_setblocking(fd, 0) == 0, "TC-NETSOCK-221c 切非阻塞模式成功");
CHECK(net_setblocking(fd, 0) == 0, "TC-NETSOCK-221c switching to non-blocking mode succeeds");
rc = net_recv(fd, buf, (int)sizeof(buf), 0);
CHECK(rc == -1 && net_get_errno() == NET_ERR_WOULDBLOCK,
"TC-NETSOCK-221d blocking 属性=0 与 NET_MSG_DONTWAIT 等价生效");
"TC-NETSOCK-221d blocking attribute 0 behaves exactly like NET_MSG_DONTWAIT");
CHECK(net_recv_nb(fd, buf, (int)sizeof(buf)) == -1 &&
net_get_errno() == NET_ERR_WOULDBLOCK,
"TC-NETSOCK-221e net_recv_nb 具名入口同路径");
"TC-NETSOCK-221e net_recv_nb named entry takes the same path");
reset_all();
}
@@ -296,12 +296,12 @@ static void tc_222_recv_eof_relisten(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_recv(fd, buf, (int)sizeof(buf), NET_MSG_DONTWAIT);
CHECK(rc == 0, "TC-NETSOCK-222a CLOSED+无数据 → EOF(0),不是错误");
CHECK(rc == 0, "TC-NETSOCK-222a CLOSED with no data -> EOF(0), not an error");
CHECK(g_peers.listener_req_calls == 1 &&
g_peers.last_req_reason == (int)NET_LISTENER_REQ_EOF,
"TC-NETSOCK-222b EOF 登记 REQ_EOF(重建动作交监听层唯一执行者,本层不动芯片)");
"TC-NETSOCK-222b EOF registers REQ_EOF (the rebuild belongs to the listener layer, this layer never touches the chip)");
CHECK(g_chip.open_calls == 0 && g_chip.listen_calls == 0 && g_chip.close_calls == 0,
"TC-NETSOCK-222c 登记路径上**一个芯片事务都不发**(单一所有者不变量 II)");
"TC-NETSOCK-222c the registration path issues NOT ONE chip transaction (single-owner invariant II)");
/* 抢先 relisten 后 state 已回 LISTENING,但会话电平仍是"已结束" */
reset_all();
@@ -313,7 +313,7 @@ static void tc_222_recv_eof_relisten(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_recv(fd, buf, (int)sizeof(buf), NET_MSG_DONTWAIT);
CHECK(rc == 0,
"TC-NETSOCK-222d 已 relisten 回 LISTENING 仍判 EOF(N-32 P1 电平化:否则 EOF 永久失踪)");
"TC-NETSOCK-222d still EOF after relisten moved it back to LISTENING (N-32 P1 level, else EOF vanishes forever)");
/* auto_relisten=0(客户端 fd):EOF 不登记重建,交调用方决定重连 */
reset_all();
@@ -325,7 +325,7 @@ static void tc_222_recv_eof_relisten(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
rc = net_recv(fd, buf, (int)sizeof(buf), NET_MSG_DONTWAIT);
CHECK(rc == 0 && g_peers.listener_req_calls == 0,
"TC-NETSOCK-222e 非监听 fd 的 EOF 不许替调用方擅自重建");
"TC-NETSOCK-222e EOF on a non-listener fd must not rebuild behind the caller back");
reset_all();
}
@@ -351,19 +351,19 @@ static void tc_223_recv_pending_roundtrip(void)
net_process_messages();
CHECK(g_peers.pending_reg_calls == 1 && g_peers.last_pend_fd == fd,
"TC-NETSOCK-223a 阻塞无数据 → 登记挂起 recv(netTask 零占用返回)");
"TC-NETSOCK-223a blocking with no data -> registers a pending recv (netTask returns with zero occupancy)");
CHECK(g_peers.last_pend_to == 250U,
"TC-NETSOCK-223b 调用方的显式预算随登记带走(0=无限,这里必须不是 0)");
"TC-NETSOCK-223b the caller explicit budget travels with the registration (0 means infinite, here it must not be 0)");
CHECK(g_peers.last_pend_caller == (TaskHandle_t)&g_ns_task_caller,
"TC-NETSOCK-223c 完成时要知道通知谁");
"TC-NETSOCK-223c completion must know whom to notify");
CHECK(g_ns_notify_calls == 0,
"TC-NETSOCK-223d 登记即发回执 = 把「登记成功」当结果,本条钉它没发生");
"TC-NETSOCK-223d registering then immediately notifying would pass off registration as the result - pinned absent");
/* 数据到达:由挂起 recv 的 tick 结束(脚本模拟) */
ns_peers_arm_pending_done(fd, 7);
net_process_messages();
CHECK(g_ns_notify_calls == 1 && g_ns_notify_last_val == 7U,
"TC-NETSOCK-223e 数据到达后才回执,通知值=字节数");
"TC-NETSOCK-223e receipt only once data arrives, notify value = byte count");
reset_all();
}
@@ -381,7 +381,7 @@ static void tc_224_recv_to_timeout_code(void)
/* 先造一条"已登记"的挂起,再让 tick 判到点 */
ns_peers_arm_pending_done(fd, NET_ERR_TIMEDOUT);
rc = net_recv_to(fd, buf, (int)sizeof(buf), 30U);
CHECK(rc == -2, "TC-NETSOCK-224a 本片超时 → 独立返回码 -2(与真错误 -1 区分)");
CHECK(rc == -2, "TC-NETSOCK-224a this slice timed out -> dedicated return code -2 (distinct from a real error -1)");
reset_all();
}
@@ -396,21 +396,21 @@ static void tc_225_recv_bad_args(void)
g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller;
CHECK(net_recv_to(0, buf, 4, 0U) == -1 && net_get_errno() == NET_ERR_INVAL,
"TC-NETSOCK-225a net_recv_to(timeout=0) 直接拒——0 在 netTask 侧是「无限等待」,"
"与本接口「有界占用」的存在理由相反");
CHECK(g_ns_put_calls == 0, "TC-NETSOCK-225b 拒绝发生在入队之前");
"TC-NETSOCK-225a net_recv_to(timeout=0) is refused up front - 0 means infinite wait on the netTask side,"
"which contradicts this API whole reason for having a bounded occupancy");
CHECK(g_ns_put_calls == 0, "TC-NETSOCK-225b the refusal happens before enqueue");
CHECK(net_recv(fd, NULL, 4, NET_MSG_DONTWAIT) == -1 &&
net_get_errno() == NET_ERR_INVAL, "TC-NETSOCK-225c buf 为 NULL → INVAL");
net_get_errno() == NET_ERR_INVAL, "TC-NETSOCK-225c buf NULL -> INVAL");
CHECK(net_recv(fd, buf, 0, NET_MSG_DONTWAIT) == -1 &&
net_get_errno() == NET_ERR_INVAL, "TC-NETSOCK-225d len<=0 → INVAL");
net_get_errno() == NET_ERR_INVAL, "TC-NETSOCK-225d len <= 0 -> INVAL");
CHECK(net_send(fd, NULL, 4, 0) == -1 && net_get_errno() == NET_ERR_INVAL,
"TC-NETSOCK-225e send 的 buf 为 NULL → INVAL");
"TC-NETSOCK-225e send with buf NULL -> INVAL");
CHECK(net_send(fd, buf, -1, 0) == -1 && net_get_errno() == NET_ERR_INVAL,
"TC-NETSOCK-225f send 的 len<0 → INVAL");
"TC-NETSOCK-225f send with len < 0 -> INVAL");
CHECK(g_chip.write_calls == 0 && g_chip.read_calls == 0 &&
g_peers.pending_reg_calls == 0 && g_peers.send_reg_calls == 0,
"TC-NETSOCK-225g 参数非法路径上零芯片事务、零挂起登记");
"TC-NETSOCK-225g on the invalid-argument path: zero chip transactions and zero pending registrations");
reset_all();
}
@@ -433,7 +433,7 @@ static void tc_230_close_order_and_peer(void)
(void)ns_rtos_q_put_raw(&msg);
net_process_messages(); /* 走登记路径(不发回执) */
CHECK(g_peers.pending_reg_calls == 1 && g_ns_notify_calls == 0,
"TC-NETSOCK-230a 前置:已登记挂起且未回执");
"TC-NETSOCK-230a precondition: pending registered and no receipt yet");
/* 芯片侧此刻仍是 OPEN:close 才需要真去拆(已 CLOSED 的形态见 TC-NETSOCK-232) */
g_fake.cached_open[fd] = CH395F_SOCKET_OPEN;
@@ -450,19 +450,19 @@ static void tc_230_close_order_and_peer(void)
net_process_messages();
CHECK(g_peers.pending_settle_calls == s_close_base_settle + 1,
"TC-NETSOCK-230b close 必先结算本 fd 的挂起 recv(否则等待方永久悬挂)");
"TC-NETSOCK-230b close must first settle this fd pending recv (else the waiter hangs forever)");
CHECK(g_peers.pending_notified == 1,
"TC-NETSOCK-230c 结算必通知(取消也要通知,不是静默清槽)");
"TC-NETSOCK-230c settling always notifies (a cancel notifies too, not a silent slot clear)");
CHECK(g_chip.close_calls >= 1 && g_fxchip.rst_begin_calls == 1,
"TC-NETSOCK-230d 芯片仍 OPEN → 走 sock_reset 确定性排渣把它拆掉");
"TC-NETSOCK-230d chip still OPEN -> sock_reset deterministically drains and tears it down");
CHECK(g_fxchip.glob_calls == 0,
"TC-NETSOCK-230e close 全程不得读全局中断寄存器(B3:唯一读者=net_poll)");
"TC-NETSOCK-230e close must never read the global interrupt register (B3: sole reader is net_poll)");
CHECK(s_net_socks[fd].in_use == 0U && s_net_socks[fd].last_peer_port == 51999U,
"TC-NETSOCK-230f 控制块清零但 last_peer_port 保留(幽灵甄别基准属芯片 Socket 级)");
"TC-NETSOCK-230f control block cleared but last_peer_port kept (ghost discrimination is chip-socket level)");
CHECK(g_peers.listener_clear_calls == s_close_base_clear + 1,
"TC-NETSOCK-230g close 幂等清理监听重试(关闭即取消待重试,D10)");
"TC-NETSOCK-230g close idempotently clears the listener retry (closing cancels pending retries, D10)");
CHECK(g_peers.pend_active_now[fd] == 0,
"TC-NETSOCK-230h close 后本 fd 不再有挂起 recv(两张表都归零)");
"TC-NETSOCK-230h after close this fd has no pending recv (both tables zeroed)");
reset_all();
}
@@ -479,8 +479,8 @@ static void tc_231_close_badfd(void)
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_BADF,
"TC-NETSOCK-231a close 未分配的 fd → BADF 经通知值回传");
CHECK(g_chip.close_calls == 0, "TC-NETSOCK-231b BADF 不碰芯片");
"TC-NETSOCK-231a close on an unallocated fd -> BADF travels back on the notify value");
CHECK(g_chip.close_calls == 0, "TC-NETSOCK-231b BADF does not touch the chip");
bring_up();
(void)memset(&msg, 0, sizeof(msg));
@@ -490,7 +490,7 @@ static void tc_231_close_badfd(void)
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_INVAL,
"TC-NETSOCK-231c accept 未在用 → INVAL(控制块级校验,不是 fd 越界)");
"TC-NETSOCK-231c accept on an unused fd -> INVAL (control-block check, not fd range)");
reset_all();
}
@@ -508,7 +508,7 @@ static void tc_240_drop_conn_branches(void)
msg.caller = (TaskHandle_t)&g_ns_task_caller;
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_BADF, "TC-NETSOCK-240a 未分配 → BADF");
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_BADF, "TC-NETSOCK-240a unallocated -> BADF");
/* UDP → INVAL */
bring_up();
@@ -520,7 +520,7 @@ static void tc_240_drop_conn_branches(void)
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == (uint32_t)NET_ERR_INVAL,
"TC-NETSOCK-240b 非 TCP 流 → INVAL(本 API 只拆 TCP 会话)");
"TC-NETSOCK-240b not a TCP stream -> INVAL (this API only tears down TCP sessions)");
/* 监听态但无活动会话 → 幂等 0,不动芯片 */
bring_up();
@@ -533,9 +533,9 @@ static void tc_240_drop_conn_branches(void)
msg.caller = (TaskHandle_t)&g_ns_task_caller;
(void)ns_rtos_q_put_raw(&msg);
net_process_messages();
CHECK(g_ns_notify_last_val == 0U, "TC-NETSOCK-240c 无活动会话 → 幂等成功 0");
CHECK(g_ns_notify_last_val == 0U, "TC-NETSOCK-240c no active session -> idempotent success 0");
CHECK(g_chip.close_calls == 0 && g_fxchip.rst_begin_calls == 0,
"TC-NETSOCK-240d 幂等分支不得拆芯片(会把在听的监听毁掉)");
"TC-NETSOCK-240d the idempotent branch must not tear down the chip (it would destroy the live listener)");
/* ESTABLISHED + 监听型 → QUARANTINE 拆除 + 登记重建 */
bring_up();
@@ -549,18 +549,18 @@ static void tc_240_drop_conn_branches(void)
net_process_messages();
CHECK(g_peers.pending_settle_calls == 1 && g_peers.send_cancel_calls == 1,
"TC-NETSOCK-240e 拆会话前先结束两张表的挂起(必通知)");
"TC-NETSOCK-240e both pending tables are ended before dropping the session (with notification)");
CHECK(g_fxchip.rst_begin_calls == 1,
"TC-NETSOCK-240f 拆除走 sock_reset 确定性排渣(不是 close+盲等)");
"TC-NETSOCK-240f teardown uses sock_reset deterministic draining, not close plus blind waiting");
CHECK(g_peers.listener_req_calls == 1 &&
g_peers.last_req_reason == (int)NET_LISTENER_REQ_DROP,
"TC-NETSOCK-240g 监听型 fd 拆完登记 REQ_DROP(重建交监听层,本层不自己 open)");
"TC-NETSOCK-240g listener-type fd registers REQ_DROP after the drop (rebuild belongs to the listener layer)");
CHECK(s_net_socks[fd].state == NET_SOCK_STATE_CLOSED &&
s_net_socks[fd].in_use == 1U && s_net_socks[fd].local_port == 2404U &&
s_net_socks[fd].auto_relisten == 1U,
"TC-NETSOCK-240h 只收口会话簿记:fd 保留、监听属性与端口都留下");
"TC-NETSOCK-240h only session bookkeeping is closed out: fd, listener attribute and port all survive");
CHECK(g_fxchip.glob_calls == 0,
"TC-NETSOCK-240i 拆除路径也只碰本 Socket(F-NET-7:不读全局)");
"TC-NETSOCK-240i teardown only touches its own socket (F-NET-7: never reads the global register)");
reset_all();
}
@@ -577,17 +577,17 @@ static void tc_250_put_fail_busy(void)
rc = net_send(fd, "abc", 3, 0);
CHECK(rc == -1 && net_get_errno() == NET_ERR_BUSY,
"TC-NETSOCK-250a 队列满 → net_send 报 BUSY(不是静默丢弃)");
"TC-NETSOCK-250a queue full -> net_send reports BUSY, it does not silently drop");
CHECK(g_chip.write_calls == 0 && g_ns_notify_calls == 0,
"TC-NETSOCK-250b 入队失败时零芯片事务、零通知(调用方不会误等回执)");
"TC-NETSOCK-250b on enqueue failure: zero chip transactions and zero notifications (caller will not wait in vain)");
CHECK(net_listen(fd) == -1 && net_get_errno() == NET_ERR_BUSY,
"TC-NETSOCK-250c 同一形态对 net_listen 成立");
"TC-NETSOCK-250c the same shape holds for net_listen");
CHECK(net_close(fd) == -1 && net_get_errno() == NET_ERR_BUSY,
"TC-NETSOCK-250d 同一形态对 net_close 成立");
"TC-NETSOCK-250d the same shape holds for net_close");
CHECK(net_drop_conn(fd) == -1 && net_get_errno() == NET_ERR_BUSY,
"TC-NETSOCK-250e 同一形态对 net_drop_conn 成立");
"TC-NETSOCK-250e the same shape holds for net_drop_conn");
CHECK(net_recv_to(fd, (void *)"x", 1, 5U) == -1 && net_get_errno() == NET_ERR_BUSY,
"TC-NETSOCK-250f 同一形态对 net_recv_to 成立");
"TC-NETSOCK-250f the same shape holds for net_recv_to");
reset_all();
}