test(NET): net_events 模块(34 条,覆盖 97.8%),NET 三块收官
假 CH395F 的第三批、也是 NET 域最后一块。net_events.c 覆盖 175/179 = 97.8%。共享 假芯片本批补齐**对端六元组**(get_remot_ipp 的 6 字节)与**链路变更计数**( link_change_count / link_up_cached 改为可预置,原来硬编码 0/1)。 钉住的契约(都是真机上会发生、却不能按需复现的那类): - 对端六元组解析:remote_ip 是**低字节在前**拼的(192.168.1.50 -> 0x3201A8C0,与 网络序相反)。钉住它是防止有人"顺手改成大端",让所有按 IP 比对/白名单静默错位。 - 陈旧中断防误判:芯片说 TCP 还 ESTABLISHED 时,迟到的 DISCONNECT 一律忽略并报 ERROR(拆活会话的代价是 104 主站看到莫名掉线);一条数据都没收就报断且芯片接收区 还有字节,判为疑似误报、只置 lost_conn_seen 延后交给对账器。 - 正常断开:优雅级沉降 + session_dead + last_peer_port 记旧端口 + 转 CLOSED + 发事件。 - 超时:ESTABLISHED 走隔离级沉降并置 released_abnormal —— 这正是 net_pending 收尾时 把挂起 recv 报成 CONNRESET 而不是 0 的那条输入(TC-NETPEND-014),**跨文件因果** 只有两边都能离线跑才可测。 - 丢中断自愈:芯片已连上而软件还写着 LISTENING 时补一次 accept;若软件已 CLOSED 则 只留痕不凭空造会话(TC-NETEV-042b 记现状)。 - 对账器:100ms 周期闸门(同一时刻不重复查芯片);链路计数**基线那趟不打日志** (0xFFFF 哨兵,否则每次上电都冒一条假"link up")、变化即留痕;五种不一致形态的 稳定计数分三档(会话死亡要连观 4 次、芯片偷重开监听 2 次、丢 CONNECT 自接 1 次); 动作后 1000ms 冷却内不重复折腾;U11 重同步(软件 CLOSED 而芯片在 LISTEN -> 直接跟 芯片,不做多余重建);不在用的槽位直接跳过。 三条初判失败的复盘(都是**我的期望值/场景写错**,实现是对的):① remote_ip 字节序 我按网络序写了期望;② 自愈场景我用了 CLOSED 态,而 accept 分支只认 LISTENING/ CONNECTING,改场景并补一条现状断言;③ 链路"基线不打日志"我测在非基线场景(s_ link_last 是函数内 static,跨场景本就延续)。对账器的 s_last/s_bad[]/s_cool[] 都是 函数内 static(外部够不着),因此每个形态**各占一个 fd**、时基单调前进,互不串扰。 覆盖率与台账:套件 24 → 25 全绿;files_tested 28 → 29;未触及 .c 38 → 37;分母 3,766 → 3,945 行;line=3472/3945(**88.0%**,连涨两批)、func=263/290(90.7%)。 恒等式 37 = 3(P1 剩) + 5(P2) + 29(P3) 仍咬合。编号补建 TC-HOST-NETEV(游标 058), 族数 18 → 19。 自查:test-cppcheck Passed(含补齐后的假芯片);check_ids --strict 通过;doc-links 35 处(= 存量);16 个新增/改动文件 BOM/CR/U+FFFD/行尾逐项净。零生产代码改动,未跑 @build。--all-files 仍只有 mem-numbers / mem-budget(.map 台账漂移,等 Lead 合并后 统一 --write 回填)与 ui-golden(simulator/tests/ref/*.bin 不入库,新 worktree 没有 黄金参考)三条失败,与本分支改动无关;提交按并行分支约定走 --no-verify。
This commit is contained in:
@@ -31,6 +31,7 @@ void ch395f_fake_reset(void)
|
||||
g_fake.cached_tcp[i] = CH395F_TCP_CLOSED;
|
||||
g_fake.status_byte0[i] = CH395F_SOCKET_CLOSED;
|
||||
g_fake.status_byte1[i] = CH395F_TCP_CLOSED;
|
||||
g_fake.link_up = 1U;
|
||||
g_fake.open_rc[i] = CH395F_ERR_SUCCESS;
|
||||
g_fake.listen_rc[i] = CH395F_ERR_SUCCESS;
|
||||
}
|
||||
@@ -44,6 +45,20 @@ void ch395f_fake_push_recv_len(uint8_t sock, uint16_t v)
|
||||
}
|
||||
}
|
||||
|
||||
void ch395f_fake_set_peer(uint8_t sock, uint8_t b0, uint8_t b1, uint8_t b2,
|
||||
uint8_t b3, uint16_t peer_port)
|
||||
{
|
||||
if (sock >= CH395F_FAKE_SOCK_MAX) {
|
||||
return;
|
||||
}
|
||||
g_fake.remote[sock][0] = b0;
|
||||
g_fake.remote[sock][1] = b1;
|
||||
g_fake.remote[sock][2] = b2;
|
||||
g_fake.remote[sock][3] = b3;
|
||||
g_fake.remote[sock][4] = (uint8_t)(peer_port & 0xFFU);
|
||||
g_fake.remote[sock][5] = (uint8_t)((peer_port >> 8) & 0xFFU);
|
||||
}
|
||||
|
||||
void ch395f_fake_set_listening(uint8_t sock)
|
||||
{
|
||||
if (sock < CH395F_FAKE_SOCK_MAX) {
|
||||
@@ -174,9 +189,13 @@ void ch395f_set_sour_port(uint8_t sock, uint16_t port)
|
||||
|
||||
void ch395f_get_remot_ipp(uint8_t sock, uint8_t *p_buf)
|
||||
{
|
||||
(void)sock;
|
||||
if (p_buf != NULL) {
|
||||
(void)memset(p_buf, 0, 4U);
|
||||
if (p_buf == NULL) {
|
||||
return;
|
||||
}
|
||||
if (sock < CH395F_FAKE_SOCK_MAX) {
|
||||
(void)memcpy(p_buf, g_fake.remote[sock], 6U);
|
||||
} else {
|
||||
(void)memset(p_buf, 0, 6U);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,10 +208,10 @@ void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable)
|
||||
|
||||
uint8_t ch395f_link_up_cached(void)
|
||||
{
|
||||
return 1U;
|
||||
return g_fake.link_up;
|
||||
}
|
||||
|
||||
uint16_t ch395f_link_change_count(void)
|
||||
{
|
||||
return 0U;
|
||||
return g_fake.link_change;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,9 @@ typedef struct {
|
||||
uint16_t recv_len_q[CH395F_FAKE_SOCK_MAX][CH395F_FAKE_QUEUE_LEN];
|
||||
int recv_len_n[CH395F_FAKE_SOCK_MAX];
|
||||
int recv_len_i[CH395F_FAKE_SOCK_MAX];
|
||||
uint8_t remote[CH395F_FAKE_SOCK_MAX][6]; /* get_remot_ipp 的 6 字节:ip[4]+port(小端) */
|
||||
uint16_t link_change; /* link_change_count(链路变更计数) */
|
||||
uint8_t link_up; /* link_up_cached */
|
||||
uint8_t open_rc[CH395F_FAKE_SOCK_MAX]; /* open_socket 返回码 */
|
||||
uint8_t listen_rc[CH395F_FAKE_SOCK_MAX]; /* tcp_listen 返回码 */
|
||||
} ch395f_fake_world_t;
|
||||
@@ -118,7 +121,9 @@ extern ch395f_fake_obs_t g_chip;
|
||||
|
||||
void ch395f_fake_reset(void); /* 全清并把所有 socket 设为"已关闭" */
|
||||
void ch395f_fake_push_recv_len(uint8_t sock, uint16_t v);
|
||||
void ch395f_fake_set_listening(uint8_t sock); /* 缓存:open!=CLOSED 且 tcp=LISTEN */
|
||||
void ch395f_fake_set_listening(uint8_t sock);
|
||||
void ch395f_fake_set_peer(uint8_t sock, uint8_t b0, uint8_t b1, uint8_t b2,
|
||||
uint8_t b3, uint16_t peer_port); /* 预置对端六元组 */ /* 缓存:open!=CLOSED 且 tcp=LISTEN */
|
||||
|
||||
/* —— 假芯片实现(签名与真实 ch395f.h 一字不改)—— */
|
||||
ch395f_sock_state_t ch395f_sock_state_cached(uint8_t sn);
|
||||
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* 模块名称:NET 层事件分发与周期对账(net_events)主机侧单元测试
|
||||
* 模块功能:在 PC 上离线验证 Drivers/BSP/NET/net_events.c 的五个事件入口与周期对账器:
|
||||
* 对端六元组解析、**陈旧中断防误判**(芯片说还在连接就不许拆会话)、疑似
|
||||
* 误报延后交给对账器、超时把会话标成异常释放(喂给 net_pending 收尾报
|
||||
* CONNRESET 的那条输入)、掉线自愈自接,以及对账器的 100ms 周期闸门、
|
||||
* 1000ms 冷却、五种不一致形态的稳定计数(死亡要连观 4 次、重开监听 2 次、
|
||||
* 自接 1 次)与 U11 的 CLOSED->LISTENING 重同步。
|
||||
*
|
||||
* 被测对象:真实源文件 ../../../Drivers/BSP/NET/net_events.c(#include 原样纳入)。
|
||||
* net_events.h / net_types.h / net_pending.h / net_listener.h 全用**真实头**
|
||||
* (net_event_cb_t 回调签名、NET_EVENT_* / NET_SOCK_STATE_* /
|
||||
* net_listener_settle_t / NET_LISTENER_REQ_* 一改即编译期报错)。假件:
|
||||
* 共享假 CH395F(本批补齐对端六元组与链路变更计数)、可控 socket 表
|
||||
* (net_sock_raw 对未在用槽位也返回项,与真实语义一致)、**可观测的事件
|
||||
* 回调**(记 fd / 事件 / arg)、记录型 net_listener_settle/request 与
|
||||
* net_pending_cancel / net_send_pending_cancel、可控时基、dbg_log 计数。
|
||||
*
|
||||
* 为什么要主机侧单测(而不是只靠台架):
|
||||
* 1. CH395F 的中断是**整体读即清**且单连接 socket 复用同一个号,"迟到的 DISCONNECT"
|
||||
* 与"丢了 CONNECT 的已连接"在真机上都会发生,却无法按需复现。误判的代价直接落在
|
||||
* 现场设备上:把还活着的会话拆掉(104 主站看到莫名掉线),或让 socket 永远停在
|
||||
* 已连接假象里不再重开。
|
||||
* 2. 对账器的**稳定计数**(死亡 4 次、重开监听 2 次、自接 1 次)本质是"别拿一次
|
||||
* 采样就把连接折腾死"。真机一次采样 100ms,凑够 4 次要 400ms,且必须一路稳定;
|
||||
* 台架上没法按毫秒喂,也看不出为什么"偶尔不重开"。主机侧把时基做成显式量后,
|
||||
* 第 3 次不该动、第 4 次该动、之后 1000ms 内不许再动,全部可精确断言。
|
||||
* 3. handle_timeout_event 会置 released_abnormal=1,而 net_pending 收尾时正是靠
|
||||
* 这个标志把挂起 recv 报成 CONNRESET 而不是 0(见 test/host/net_pending 的
|
||||
* TC-NETPEND-014)。两个模块之间这条**跨文件因果**,只有两边都能离线跑时才可测。
|
||||
*
|
||||
* 覆盖点:TC-NETEV-001..006 CONNECT;010..014 DISCONNECT(含两条陈旧中断防误判);
|
||||
* 020/021 RECV 与 SEND;030..032 TIMEOUT;040..042 掉线自愈;050..058 周期对账
|
||||
* (周期闸门、链路变更留痕、五种不一致形态、稳定计数、冷却、in_use 兜底)。
|
||||
*
|
||||
* 通过:全部 TC PASS(main 返回 0)。
|
||||
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
|
||||
*
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "net_events.h"
|
||||
#include "net_listener.h"
|
||||
#include "net_pending.h"
|
||||
#include "net_socket.h"
|
||||
#include "ch395f.h"
|
||||
|
||||
#include "ch395f_fake.c"
|
||||
#include "net_events.c"
|
||||
|
||||
static int s_total;
|
||||
static int s_passed;
|
||||
static int s_failed;
|
||||
|
||||
#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)
|
||||
|
||||
/* ===================== dbg_log 计数 ===================== */
|
||||
|
||||
int g_nev_info_count;
|
||||
int g_nev_error_count;
|
||||
int g_nev_debug_count;
|
||||
|
||||
/* ===================== 可观测的事件回调 ===================== */
|
||||
|
||||
static int g_ev_n;
|
||||
static int g_ev_fd[16];
|
||||
static int g_ev_kind[16];
|
||||
static void *g_ev_arg[16];
|
||||
static int g_ev_token;
|
||||
|
||||
static void ev_cb(int sockfd, net_event_t event, void *arg)
|
||||
{
|
||||
if (g_ev_n < (int)(sizeof(g_ev_fd) / sizeof(g_ev_fd[0]))) {
|
||||
g_ev_fd[g_ev_n] = sockfd;
|
||||
g_ev_kind[g_ev_n] = (int)event;
|
||||
g_ev_arg[g_ev_n] = arg;
|
||||
}
|
||||
g_ev_n++;
|
||||
}
|
||||
|
||||
/* ===================== 记录型监听与挂起取消 ===================== */
|
||||
|
||||
static int g_settle_n;
|
||||
static int g_settle_sock;
|
||||
static int g_settle_level;
|
||||
static int g_req_n;
|
||||
static int g_req_sock;
|
||||
static int g_req_reason;
|
||||
static int g_pcan_n;
|
||||
static int g_scan_n;
|
||||
static int g_pcan_err;
|
||||
|
||||
void net_listener_settle(int sockfd, net_listener_settle_t level)
|
||||
{
|
||||
g_settle_n++;
|
||||
g_settle_sock = sockfd;
|
||||
g_settle_level = (int)level;
|
||||
}
|
||||
|
||||
void net_listener_request(int sockfd, net_listener_req_t reason)
|
||||
{
|
||||
g_req_n++;
|
||||
g_req_sock = sockfd;
|
||||
g_req_reason = (int)reason;
|
||||
}
|
||||
|
||||
void net_listener_clear(int sockfd) { (void)sockfd; }
|
||||
void net_listener_tick(void) { }
|
||||
|
||||
void net_pending_cancel(int sockfd, int err)
|
||||
{
|
||||
(void)sockfd;
|
||||
g_pcan_n++;
|
||||
g_pcan_err = err;
|
||||
}
|
||||
|
||||
void net_send_pending_cancel(int sockfd, int err)
|
||||
{
|
||||
(void)sockfd;
|
||||
(void)err;
|
||||
g_scan_n++;
|
||||
}
|
||||
|
||||
/* ===================== 可控时基、errno 与 socket 表 ===================== */
|
||||
|
||||
static uint32_t g_now;
|
||||
static int g_errno_last;
|
||||
|
||||
uint32_t HAL_GetTick(void) { return g_now; }
|
||||
|
||||
int net_set_errno(int err) { g_errno_last = err; return err; }
|
||||
|
||||
uint32_t xTaskGetTickCount(void) { return g_now; }
|
||||
|
||||
static net_sock_t g_tbl[NET_MAX_SOCKETS];
|
||||
|
||||
net_sock_t *net_sock_raw(int sockfd)
|
||||
{
|
||||
if ((sockfd < 0) || (sockfd >= NET_MAX_SOCKETS)) {
|
||||
return NULL;
|
||||
}
|
||||
/* 与真实语义一致:对账循环必须能读到 in_use == 0 的槽位,所以这里不给 NULL */
|
||||
return &g_tbl[sockfd];
|
||||
}
|
||||
|
||||
net_sock_t *net_get_sock(int sockfd)
|
||||
{
|
||||
net_sock_t *p = net_sock_raw(sockfd);
|
||||
|
||||
if ((p == NULL) || (p->in_use == 0u)) {
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void reset_all(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)memset(g_tbl, 0, sizeof(g_tbl));
|
||||
g_now = 1000u;
|
||||
g_errno_last = 0;
|
||||
g_ev_n = 0;
|
||||
g_settle_n = 0;
|
||||
g_settle_sock = -1;
|
||||
g_settle_level = -1;
|
||||
g_req_n = 0;
|
||||
g_req_sock = -1;
|
||||
g_req_reason = -1;
|
||||
g_pcan_n = 0;
|
||||
g_scan_n = 0;
|
||||
g_pcan_err = 0;
|
||||
g_nev_info_count = 0;
|
||||
g_nev_error_count = 0;
|
||||
g_nev_debug_count = 0;
|
||||
ch395f_fake_reset();
|
||||
(void)i;
|
||||
}
|
||||
|
||||
/* 一个"带应用回调的在用槽位",ch395_sock 与数组下标同号 */
|
||||
static net_sock_t *mk(int fd, net_sock_state_t st, uint16_t local_port)
|
||||
{
|
||||
net_sock_t *p = &g_tbl[fd];
|
||||
|
||||
p->in_use = 1u;
|
||||
p->ch395_sock = (uint8_t)fd;
|
||||
p->type = NET_SOCK_STREAM;
|
||||
p->state = st;
|
||||
p->auto_relisten = 1u;
|
||||
p->local_port = local_port;
|
||||
p->event_cb = ev_cb;
|
||||
p->event_arg = (void *)&g_ev_token;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* ===================== CONNECT ===================== */
|
||||
|
||||
static void tc_connect(void)
|
||||
{
|
||||
net_sock_t *p;
|
||||
|
||||
printf("-- TC-NETEV-001..006 CONNECT --\n");
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
ch395f_fake_set_peer(0, 192u, 168u, 1u, 50u, 51234u);
|
||||
handle_connect_event(p);
|
||||
/* remote_ip 是**低字节在前**拼的(remote[0] 落在最低 8 位),与网络序相反:
|
||||
* 192.168.1.50 -> 0x3201A8C0。这是既有实现的字节序,钉住它是防止有人"顺手
|
||||
* 改成大端"导致所有按 IP 比对/白名单的判断静默错位。 */
|
||||
CHECK((p->remote_ip_arr[0] == 192u) && (p->remote_ip_arr[3] == 50u) &&
|
||||
(p->remote_ip == ((192u) | (168u << 8) | (1u << 16) | (50u << 24))) &&
|
||||
(p->remote_port == 51234u),
|
||||
"TC-NETEV-001 对端六元组解析:ip 低字节在前拼 32 位、端口取第 5/6 字节");
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (p->session_dead == 0u) &&
|
||||
(p->lost_conn_seen == 0u) && (p->send_ready == 1u),
|
||||
"TC-NETEV-002 监听口自接后转已连接并立刻可写");
|
||||
CHECK((g_chip.keepalive_calls == 1) && (g_chip.last_keepalive == 1u) &&
|
||||
(g_chip.int_status_calls == 1),
|
||||
"TC-NETEV-003 建链即开 keepalive 并清一次挂起位(读即清)");
|
||||
CHECK((g_ev_n == 1) && (g_ev_kind[0] == (int)NET_EVENT_CONNECTED) &&
|
||||
(g_ev_fd[0] == 0) && (g_ev_arg[0] == (void *)&g_ev_token),
|
||||
"TC-NETEV-004 事件带 fd 与调用方 arg 回调给应用");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CONNECTING, 0u);
|
||||
ch395f_fake_set_peer(0, 10u, 0u, 0u, 1u, 2404u);
|
||||
handle_connect_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (p->send_ready == 0u) &&
|
||||
(g_chip.keepalive_calls == 1) && (g_ev_n == 1),
|
||||
"TC-NETEV-005 主动连接分支同样转已连接,但**不动 send_ready**(与自接有别)");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
handle_connect_event(p);
|
||||
CHECK((g_ev_n == 0) && (p->state == NET_SOCK_STATE_CLOSED),
|
||||
"TC-NETEV-006 其它状态收到 CONNECT 中断一律忽略(不许凭空造会话)");
|
||||
}
|
||||
|
||||
/* ===================== DISCONNECT ===================== */
|
||||
|
||||
static void tc_disconnect(void)
|
||||
{
|
||||
net_sock_t *p;
|
||||
|
||||
printf("-- TC-NETEV-010..014 DISCONNECT --\n");
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
g_fake.status_byte0[0] = CH395F_SOCKET_OPEN;
|
||||
g_fake.status_byte1[0] = CH395F_TCP_ESTABLISHED;
|
||||
handle_disconnect_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (g_ev_n == 0) &&
|
||||
(g_nev_error_count == 1),
|
||||
"TC-NETEV-010 芯片说还在连接:忽略这个陈旧 DISCONNECT(不许拆活会话)");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
g_fake.status_byte0[0] = CH395F_SOCKET_OPEN;
|
||||
g_fake.status_byte1[0] = CH395F_TCP_CLOSED;
|
||||
ch395f_fake_push_recv_len(0, 9u); /* 还有 9 字节没读走 */
|
||||
handle_disconnect_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (p->lost_conn_seen == 1u) &&
|
||||
(g_ev_n == 0) && (g_settle_n == 0),
|
||||
"TC-NETEV-011 疑似误报(一条数据都没收就断):延后交给对账器,不立即拆");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
p->remote_port = 51234u;
|
||||
g_fake.status_byte0[0] = CH395F_SOCKET_OPEN;
|
||||
g_fake.status_byte1[0] = CH395F_TCP_CLOSED;
|
||||
handle_disconnect_event(p);
|
||||
CHECK((g_settle_n == 1) && (g_settle_level == (int)NET_LISTENER_SETTLE_GRACEFUL) &&
|
||||
(p->session_dead == 1u) && (p->released_abnormal == 0u) &&
|
||||
(p->last_peer_port == 51234u) &&
|
||||
(p->state == NET_SOCK_STATE_CLOSED) &&
|
||||
(g_ev_kind[0] == (int)NET_EVENT_DISCONNECTED),
|
||||
"TC-NETEV-012 正常断开:优雅沉降 + 会话标死 + 记旧端口 + 发事件");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
g_fake.status_byte0[0] = CH395F_SOCKET_OPEN;
|
||||
g_fake.status_byte1[0] = CH395F_TCP_LISTEN;
|
||||
handle_disconnect_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_LISTENING) && (g_ev_n == 0) &&
|
||||
(g_nev_info_count == 1) && (g_nev_error_count == 0),
|
||||
"TC-NETEV-013 监听还在:陈旧监听 DISCONNECT 只留痕,不报 ERROR");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
g_fake.status_byte1[0] = CH395F_TCP_CLOSED; /* 芯片说不在 LISTEN */
|
||||
handle_disconnect_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_LISTENING) && (g_ev_n == 0) && (g_req_n == 0),
|
||||
"TC-NETEV-013b 监听丢了也只留痕:重开交给对账器,事件层不越权");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CONNECTING, 0u);
|
||||
handle_disconnect_event(p);
|
||||
CHECK((g_nev_error_count == 1) && (g_ev_kind[0] == (int)NET_EVENT_DISCONNECTED),
|
||||
"TC-NETEV-014 非常规状态收到 DISCONNECT:报 ERROR 但仍要通知应用");
|
||||
}
|
||||
|
||||
/* ===================== RECV / SEND / TIMEOUT ===================== */
|
||||
|
||||
static void tc_recv_send_timeout(void)
|
||||
{
|
||||
net_sock_t *p;
|
||||
|
||||
printf("-- TC-NETEV-020/021/030..032 --\n");
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
handle_recv_event(p);
|
||||
CHECK((p->readable == 1u) && (g_ev_kind[0] == (int)NET_EVENT_DATA_RECEIVED),
|
||||
"TC-NETEV-020 RECV 事件置可读并通知应用");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
p->send_ready = 1u;
|
||||
handle_send_event(p);
|
||||
CHECK((g_ev_kind[0] == (int)NET_EVENT_SEND_COMPLETE) && (p->send_ready == 1u),
|
||||
"TC-NETEV-021 SEND 完成只发事件,字段留给写路径自己管");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CONNECTING, 0u);
|
||||
handle_timeout_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_CREATED) && (g_nev_error_count == 1) &&
|
||||
(g_ev_kind[0] == (int)NET_EVENT_TIMEOUT),
|
||||
"TC-NETEV-030 连接超时:退回 CREATED 并通知应用");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
p->remote_port = 777u;
|
||||
handle_timeout_event(p);
|
||||
CHECK((g_settle_level == (int)NET_LISTENER_SETTLE_QUARANTINE) &&
|
||||
(p->released_abnormal == 1u) && (p->session_dead == 1u) &&
|
||||
(p->last_peer_port == 777u) && (p->state == NET_SOCK_STATE_CLOSED),
|
||||
"TC-NETEV-031 会话超时:隔离级沉降 + 标异常释放(net_pending 收尾据此报 CONNRESET)");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
handle_timeout_event(p);
|
||||
CHECK((p->state == NET_SOCK_STATE_LISTENING) && (g_nev_error_count == 1) &&
|
||||
(g_ev_kind[0] == (int)NET_EVENT_TIMEOUT),
|
||||
"TC-NETEV-032 监听超时只留痕:不改状态,但仍要通知等待方");
|
||||
}
|
||||
|
||||
/* ===================== 掉线自愈 ===================== */
|
||||
|
||||
static void tc_lost_probe(void)
|
||||
{
|
||||
net_sock_t *p;
|
||||
|
||||
printf("-- TC-NETEV-040..042 lost-CONNECT probe --\n");
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
p->lost_conn_seen = 1u;
|
||||
g_fake.cached_tcp[0] = CH395F_TCP_CLOSED;
|
||||
net_lost_connect_probe(p);
|
||||
CHECK((p->lost_conn_seen == 0u) && (g_ev_n == 0),
|
||||
"TC-NETEV-040 芯片不在已连接态:只清标记,不自作主张建会话");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
p->lost_conn_seen = 1u;
|
||||
p->last_peer_port = 51234u;
|
||||
g_fake.cached_tcp[0] = CH395F_TCP_ESTABLISHED;
|
||||
ch395f_fake_set_peer(0, 10u, 0u, 0u, 9u, 51234u);
|
||||
net_lost_connect_probe(p);
|
||||
CHECK((p->lost_conn_seen == 0u) && (g_ev_n == 0),
|
||||
"TC-NETEV-041 对端口与上次相同:认定是自己没看到 CONNECT,不自接第二遍");
|
||||
|
||||
/* 自愈的适用面是软件还写着 LISTENING、芯片其实已经连上——accept 分支只认
|
||||
* LISTENING/CONNECTING。若软件态已被别处改成 CLOSED,本函数打完 INFO 后什么都
|
||||
* 不会发生(现状留痕,见第二断言)。 */
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
p->lost_conn_seen = 1u;
|
||||
p->last_peer_port = 1u;
|
||||
g_fake.cached_tcp[0] = CH395F_TCP_ESTABLISHED;
|
||||
ch395f_fake_set_peer(0, 10u, 0u, 0u, 9u, 55555u);
|
||||
net_lost_connect_probe(p);
|
||||
CHECK((g_ev_n == 1) && (g_ev_kind[0] == (int)NET_EVENT_CONNECTED) &&
|
||||
(p->state == NET_SOCK_STATE_ESTABLISHED) && (p->remote_port == 55555u) &&
|
||||
(p->lost_conn_seen == 0u),
|
||||
"TC-NETEV-042 丢了 CONNECT 中断时自愈:补一次 accept,会话不至于永久失联");
|
||||
|
||||
reset_all();
|
||||
p = mk(0, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
g_fake.cached_tcp[0] = CH395F_TCP_ESTABLISHED;
|
||||
ch395f_fake_set_peer(0, 10u, 0u, 0u, 9u, 55555u);
|
||||
net_lost_connect_probe(p);
|
||||
CHECK((g_ev_n == 0) && (p->state == NET_SOCK_STATE_CLOSED),
|
||||
"TC-NETEV-042b 现状:软件已 CLOSED 时自愈接不上(只留痕,不凭空造会话)");
|
||||
}
|
||||
|
||||
/* ===================== 周期对账 ===================== */
|
||||
|
||||
static void recon_step(uint32_t now)
|
||||
{
|
||||
g_now = now;
|
||||
net_reconcile_tick();
|
||||
}
|
||||
|
||||
static void tc_reconcile(void)
|
||||
{
|
||||
net_sock_t *p;
|
||||
int infos;
|
||||
int c;
|
||||
|
||||
printf("-- TC-NETEV-050..058 reconcile --\n");
|
||||
/* 对账器里的 s_last / s_bad[] / s_cool[] 是函数内 static(外部够不着),
|
||||
* 所以每个形态**各占一个 fd**、时间统一单调前进,互不串扰。 */
|
||||
reset_all();
|
||||
infos = g_nev_info_count;
|
||||
recon_step(1000u); /* priming:链路计数记基线 */
|
||||
CHECK(g_nev_info_count == infos,
|
||||
"TC-NETEV-051a 上电第一趟不因链路计数打日志(0xFFFF 哨兵只记基线)");
|
||||
c = g_chip.cached_calls;
|
||||
recon_step(1000u); /* 同一时刻再调一次 */
|
||||
CHECK(g_chip.cached_calls == c, "TC-NETEV-050 100ms 周期闸门:同一时刻不重复查芯片");
|
||||
|
||||
reset_all();
|
||||
p = mk(1, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
g_fake.cached_open[1] = CH395F_SOCKET_CLOSED;
|
||||
g_fake.cached_tcp[1] = CH395F_TCP_CLOSED;
|
||||
infos = g_nev_info_count;
|
||||
recon_step(1100u);
|
||||
recon_step(1200u);
|
||||
recon_step(1300u);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (g_ev_n == 0) &&
|
||||
(g_nev_info_count == infos),
|
||||
"TC-NETEV-052 会话死亡要**连观 4 次**才动手:前三次保持原状");
|
||||
recon_step(1400u);
|
||||
CHECK((p->state == NET_SOCK_STATE_CLOSED) && (p->session_dead == 1u) &&
|
||||
(g_ev_kind[0] == (int)NET_EVENT_DISCONNECTED),
|
||||
"TC-NETEV-052b 第 4 次稳定后走断开收尾");
|
||||
p->state = NET_SOCK_STATE_ESTABLISHED; /* 假装又活了,验证冷却 */
|
||||
recon_step(1500u);
|
||||
recon_step(1600u);
|
||||
recon_step(1700u);
|
||||
recon_step(1800u);
|
||||
CHECK(g_ev_n == 1, "TC-NETEV-052c 动作后 1000ms 冷却内不再重复折腾(哪怕稳定计数够了)");
|
||||
|
||||
reset_all();
|
||||
p = mk(2, NET_SOCK_STATE_ESTABLISHED, 2404u);
|
||||
g_fake.cached_open[2] = CH395F_SOCKET_OPEN;
|
||||
g_fake.cached_tcp[2] = CH395F_TCP_LISTEN; /* 芯片自己重开监听了,却没发 DISCONNECT */
|
||||
recon_step(2900u);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (g_pcan_n == 0),
|
||||
"TC-NETEV-053 芯片偷偷重开监听:需要 2 次稳定,第一次只累计");
|
||||
recon_step(3000u);
|
||||
CHECK((p->state == NET_SOCK_STATE_LISTENING) && (g_pcan_n == 1) &&
|
||||
(g_scan_n == 1) && (g_pcan_err == NET_ERR_CONNRESET),
|
||||
"TC-NETEV-053b 第 2 次稳定:重同步成监听并**取消两条挂起**(否则任务永远等不到回)");
|
||||
|
||||
reset_all();
|
||||
p = mk(3, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
p->last_peer_port = 1u;
|
||||
g_fake.cached_tcp[3] = CH395F_TCP_ESTABLISHED; /* 连上了却没 CONNECT 中断 */
|
||||
ch395f_fake_set_peer(3, 172u, 16u, 0u, 5u, 40000u);
|
||||
recon_step(4100u);
|
||||
CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (p->remote_port == 40000u) &&
|
||||
(g_ev_kind[0] == (int)NET_EVENT_CONNECTED),
|
||||
"TC-NETEV-054 连接完成但中断丢了:1 次即补 accept");
|
||||
|
||||
reset_all();
|
||||
p = mk(4, NET_SOCK_STATE_LISTENING, 2404u);
|
||||
g_fake.cached_open[4] = CH395F_SOCKET_CLOSED; /* 监听没了 */
|
||||
g_fake.cached_tcp[4] = CH395F_TCP_CLOSED;
|
||||
recon_step(5200u);
|
||||
recon_step(5300u);
|
||||
CHECK((g_req_n == 1) && (g_req_sock == 4) &&
|
||||
(g_req_reason == (int)NET_LISTENER_REQ_RECON),
|
||||
"TC-NETEV-055 监听丢了:2 次稳定后请求重开监听(不自已在事件层里开)");
|
||||
|
||||
reset_all();
|
||||
p = mk(5, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
g_fake.cached_open[5] = CH395F_SOCKET_OPEN; /* 芯片还在 LISTEN */
|
||||
g_fake.cached_tcp[5] = CH395F_TCP_LISTEN;
|
||||
p->remote_port = 999u;
|
||||
p->lost_conn_seen = 1u;
|
||||
recon_step(6400u);
|
||||
CHECK((p->state == NET_SOCK_STATE_LISTENING) && (p->last_peer_port == 999u) &&
|
||||
(p->lost_conn_seen == 0u) && (g_req_n == 0),
|
||||
"TC-NETEV-056 U11 重同步:软件 CLOSED 而芯片在 LISTEN -> 直接跟芯片,不多余重开");
|
||||
|
||||
reset_all();
|
||||
p = mk(6, NET_SOCK_STATE_CLOSED, 2404u);
|
||||
g_fake.cached_open[6] = CH395F_SOCKET_CLOSED;
|
||||
recon_step(7500u);
|
||||
recon_step(7600u);
|
||||
CHECK((g_req_n == 1) && (g_req_sock == 6),
|
||||
"TC-NETEV-057 软件 CLOSED 且芯片也不在监听:请求重开(重建交回监听层)");
|
||||
|
||||
reset_all();
|
||||
(void)memset(&g_tbl[7], 0, sizeof(g_tbl[7])); /* 槽位不在用 */
|
||||
infos = g_nev_info_count;
|
||||
recon_step(8700u);
|
||||
CHECK(g_nev_info_count == infos, "TC-NETEV-058 不在用的槽位直接跳过(不产生任何动作)");
|
||||
|
||||
/* 链路日志:s_link_last 初值 0xFFFF 是哨兵——第一次看到计数只记基线、不打日志
|
||||
* (否则每次上电都会冒一条"链路 up"的假事件);此后计数一变就必须留痕。
|
||||
* 本文件开头那次 priming 就是"基线"那一趟(TC-NETEV-051a),这里是"变化"那一趟。 */
|
||||
reset_all();
|
||||
g_fake.link_change = 7u;
|
||||
infos = g_nev_info_count;
|
||||
recon_step(9800u);
|
||||
CHECK(g_nev_info_count == (infos + 1),
|
||||
"TC-NETEV-051b 链路变更计数一变就留痕(基线那趟已由 051a 验证不打)");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("=== NET Events Tests ===\n");
|
||||
|
||||
tc_connect();
|
||||
tc_disconnect();
|
||||
tc_recv_send_timeout();
|
||||
tc_lost_probe();
|
||||
tc_reconcile();
|
||||
|
||||
printf("\n=== NET Events Tests: %d/%d PASSED (failed=%d) ===\n",
|
||||
s_passed, s_total, s_failed);
|
||||
return (s_failed == 0) ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""NET 层事件分发与周期对账(net_events)主机侧单元测试运行器(L0.5,纯标准库)。
|
||||
|
||||
做什么:
|
||||
用本机 MSVC 编译 test/host/net_events/net_events_test.c(以 #include 纳入生产源
|
||||
Drivers/BSP/NET/net_events.c 与共享假芯片 test/host/common/ch395f_fake.c),在 PC
|
||||
上离线验证五个事件入口与周期对账器:对端六元组解析、陈旧中断防误判、疑似误报延后、
|
||||
超时标异常释放、丢中断自愈,以及对账器的周期闸门、稳定计数(4/2/1 三档)、1000ms
|
||||
冷却、U11 重同步与五种不一致形态。工具链与判定委托 unit_test_harness.py。
|
||||
|
||||
为什么要主机侧单测(而不是只用台架):
|
||||
CH395F 中断整体读即清、单连接 socket 复用同号,"迟到的 DISCONNECT"和"丢了 CONNECT
|
||||
的已连接"真机上都会发生却不能按需复现;误判的代价直接落在现场设备上(拆掉活会话,
|
||||
或让 socket 永久停在已连接假象里不再重开)。对账器的稳定计数本质是"别拿一次采样
|
||||
就把连接折腾死",100ms 一轮、要连观 4 次才动手,台架无法按毫秒喂;主机侧把时基
|
||||
做成显式量后,第 3 次不该动、第 4 次该动、之后 1000ms 内不许再动都能精确断言。
|
||||
另外 handle_timeout_event 置的 released_abnormal 是 net_pending 收尾报 CONNRESET 的
|
||||
输入(见 test/host/net_pending 的 TC-NETPEND-014),这条跨文件因果只有两边都能
|
||||
离线跑才可测。
|
||||
|
||||
桩的边界:net_events.h / net_types.h / net_pending.h / net_listener.h 用真实头;
|
||||
net_socket.h 是桩,但 net_sock_raw 保留"未在用槽位也返回项"的真实语义(对账循环
|
||||
必须能读 in_use==0);ch395f.h 只转发到共享假芯片(本批补齐对端六元组与链路变更
|
||||
计数);事件回调做成可观测假件——应用层能不能收到、收到的是什么事件,是本模块
|
||||
唯一的对外契约。刻意不定义 NET_BENCH_CMD_LOG(压测日志不是被测对象)。
|
||||
|
||||
用法(仓库根目录):
|
||||
python test/host/net_events/run_unit_test.py
|
||||
|
||||
退出码:0=PASS / 1=测试失败 / 2=环境错误。
|
||||
|
||||
设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/网络/Net层阻塞模型架构设计.md、
|
||||
docs/测试说明/主机单测覆盖率口径.md §9
|
||||
创建日期:2026-10-23
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(HERE)))
|
||||
sys.path.insert(0, os.path.join(ROOT, "test", "host", "common"))
|
||||
|
||||
from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402
|
||||
|
||||
BUILD = TestBuild(
|
||||
name="NET Events Tests",
|
||||
src=os.path.join(HERE, "net_events_test.c"),
|
||||
include_dirs=[
|
||||
os.path.join(HERE, "stub"),
|
||||
os.path.join(ROOT, "test", "host", "common"),
|
||||
os.path.join(ROOT, "Drivers", "BSP", "NET"),
|
||||
HERE,
|
||||
],
|
||||
summary_marker="=== NET Events Tests:",
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_host_unit_test(BUILD))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - FreeRTOS.h(net_events 模块专用)
|
||||
* 模块功能:宿主等价类型(TaskHandle_t 等),因为真实 net_pending.h 的原型绕不开。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef FREERTOS_H
|
||||
#define FREERTOS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void *TaskHandle_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef enum {
|
||||
eNoAction = 0,
|
||||
eSetBits = 1,
|
||||
eIncrement = 2,
|
||||
eSetValueWithOverwrite = 3,
|
||||
eSetValueWithoutOverwrite = 4
|
||||
} eNotifyAction;
|
||||
|
||||
#endif /* FREERTOS_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - ch395f.h(net_events 模块入口)
|
||||
* 模块功能:只做转发,真身在 test/host/common/ch395f_fake.h/.c(NET 域共享假芯片)。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef CH395F_H
|
||||
#define CH395F_H
|
||||
#include "ch395f_fake.h"
|
||||
#endif /* CH395F_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - cmsis_os.h(net_events 模块专用)
|
||||
* 模块功能:空壳;net_events.c include 它但不用 CMSIS API(事件直接同步分发)。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef CMSIS_OS_H
|
||||
#define CMSIS_OS_H
|
||||
#include <stdint.h>
|
||||
#endif /* CMSIS_OS_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - dbg_log.h(net_events 模块专用)
|
||||
* 模块功能:DBG_* 计数。注意 net_events.c 在 include 本头之前把 DBG_LINE_BUF_MAX
|
||||
* 抬到 128U(AGENTS:深调用链模块必须抬,否则最长日志行会被截断),
|
||||
* 本桩不关心缓冲大小,只数条数。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef DBG_LOG_H
|
||||
#define DBG_LOG_H
|
||||
|
||||
extern int g_nev_info_count;
|
||||
extern int g_nev_error_count;
|
||||
extern int g_nev_debug_count;
|
||||
|
||||
#define DBG_INFO(fmt, ...) do { (void)(fmt); g_nev_info_count++; } while (0)
|
||||
#define DBG_DEBUG(fmt, ...) do { (void)(fmt); g_nev_debug_count++; } while (0)
|
||||
#define DBG_ERROR(fmt, ...) do { (void)(fmt); g_nev_error_count++; } while (0)
|
||||
|
||||
#endif /* DBG_LOG_H */
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - main.h(net_events 模块专用)
|
||||
* 模块功能:只给 HAL_GetTick(对账周期 100ms 与冷却 1000ms 两条时间轴的唯一致度源)。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
#include <stdint.h>
|
||||
uint32_t HAL_GetTick(void);
|
||||
#endif /* MAIN_H */
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - net_latency_test.h(net_events 模块专用)
|
||||
* 模块功能:空壳。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef NET_LATENCY_TEST_H
|
||||
#define NET_LATENCY_TEST_H
|
||||
#endif /* NET_LATENCY_TEST_H */
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - net_socket.h(NET 域共享形态,见 net_listener 同名文件)
|
||||
* 模块功能:net_events.c 需要两个表项入口——net_sock_raw()(对账循环要能看到 in_use==0
|
||||
* 的槽位,真实头注释就写着"应用层请一律用 net_get_sock(),本函数仅供
|
||||
* net_events.c 的对账循环使用")与 net_get_sock();错误通道照抄真实头同名宏。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef NET_SOCKET_H
|
||||
#define NET_SOCKET_H
|
||||
|
||||
#include "net_types.h"
|
||||
|
||||
net_sock_t *net_get_sock(int sockfd);
|
||||
net_sock_t *net_sock_raw(int sockfd);
|
||||
int net_set_errno(int err);
|
||||
#define NET_ERR_RETURN_1(err) (net_set_errno(err), -1)
|
||||
|
||||
#endif /* NET_SOCKET_H */
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - task.h(net_events 模块专用)
|
||||
* 模块功能:只声明 xTaskGetTickCount——它只在 NET_BENCH_CMD_LOG 打开时用到,本模块
|
||||
* 刻意不开该宏(压测日志不是被测对象),声明留着是为了原型完整。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef TASK_H
|
||||
#define TASK_H
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
uint32_t xTaskGetTickCount(void);
|
||||
|
||||
#endif /* TASK_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 模块名称:主机侧单测桩 - test_config.h(net_events 模块专用)
|
||||
* 模块功能:空壳。**刻意不定义 NET_BENCH_CMD_LOG**:压测命令日志不是被测对象,
|
||||
* 且它依赖真实 tick 序列;不定义即被条件编译整段摘掉。
|
||||
* ⚠ 仅供主机侧单测使用,不参与 MCU 构建。
|
||||
* 创建日期:2026-10-23
|
||||
*/
|
||||
#ifndef TEST_CONFIG_H
|
||||
#define TEST_CONFIG_H
|
||||
#endif /* TEST_CONFIG_H */
|
||||
Reference in New Issue
Block a user