/* * 模块名称:NET 层兄弟模块桩(net_socket 主机侧单测专用) * 模块功能:net_socket.c 依赖的三个兄弟模块(net_listener / net_pending / net_events) * 在这里**按边界契约打桩**,让本套单测只测 net_socket.c 自己那部分决策。 * * ⚠ 仅供 test/host/net_socket/ 使用,不参与 MCU 构建。 * * 为什么打桩而不是 #include 真实源(而不是"越真越好"): * 1. 那三个模块**已各有自己的主机单测**(net_listener 34 条、net_events 34 条、 * net_pending 43 条),本套再跑一遍不增加任何对 net_socket.c 的判别力, * 只会把"谁的红"变成糊账; * 2. 本套真正要钉的是**边界契约**——net_socket.c 在什么条件下把什么 reason 登记给 * 监听层、什么条件下把挂起请求登记给 pending 层、以及"登记了就不能再自己发回执"。 * 桩把这些变成可断言的记录,比让真实 tick 在背后默默跑更有判别力; * 3. 原型一律取**真实头**(net_listener.h / net_pending.h / net_events.h), * 兄弟模块改签名 → 本套编译期就红。 * * 桩的取值纪律(不自己发明语义,全部按真实头的函数说明): * - net_pending_register / net_send_pending_register 返回 NET_PENDING_REGISTERED, * 与真实实现一致(登记成功=哨兵,供分派跳过即时通知);可注入 -1 测登记被拒; * - net_pending_tick 支持"下一轮把脚本里的结果当作数据到达,通知登记时的 caller", * 复刻真实 tick 的"数据到达即通知"契约; * - 其余全为纯记录(次数 + 最近一次入参),供"不该登记/必须登记"的断言。 * * 创建日期:2026-10-24 */ #include #include #include #include "net_listener.h" #include "net_pending.h" #include "net_events.h" #include "net_socket.h" #include "ns_peers.h" #include "ns_rtos.h" ns_peers_obs_t g_peers; /* 桩内部"完成/取消"要发通知:转给假内核,这样测试能断言通知次数与通知值 */ void ns_peers_note_notify(TaskHandle_t to, uint32_t v) { ns_rtos_post_notify(to, v); } /* 挂起登记簿(只记一条,够本套断言用) */ static int s_pend_active[NET_MAX_SOCKETS]; static void *s_pend_buf[NET_MAX_SOCKETS]; static int s_pend_len[NET_MAX_SOCKETS]; static TaskHandle_t s_pend_caller[NET_MAX_SOCKETS]; static int s_snd_active[NET_MAX_SOCKETS]; static TaskHandle_t s_snd_caller[NET_MAX_SOCKETS]; /* tick 完成脚本:fd -> 结果值(一次生效) */ static int s_pend_done_armed[NET_MAX_SOCKETS]; static int s_pend_done_val[NET_MAX_SOCKETS]; static int s_snd_done_armed[NET_MAX_SOCKETS]; static int s_snd_done_val[NET_MAX_SOCKETS]; void ns_peers_reset(void) { (void)memset(&g_peers, 0, sizeof(g_peers)); (void)memset(s_pend_active, 0, sizeof(s_pend_active)); (void)memset(s_pend_buf, 0, sizeof(s_pend_buf)); (void)memset(s_pend_len, 0, sizeof(s_pend_len)); (void)memset(s_pend_caller, 0, sizeof(s_pend_caller)); (void)memset(s_snd_active, 0, sizeof(s_snd_active)); (void)memset(s_snd_caller, 0, sizeof(s_snd_caller)); (void)memset(s_pend_done_armed, 0, sizeof(s_pend_done_armed)); (void)memset(s_pend_done_val, 0, sizeof(s_pend_done_val)); (void)memset(s_snd_done_armed, 0, sizeof(s_snd_done_armed)); (void)memset(s_snd_done_val, 0, sizeof(s_snd_done_val)); g_peers.pend_register_rc = NET_PENDING_REGISTERED; g_peers.send_register_rc = NET_PENDING_REGISTERED; } void ns_peers_arm_pending_done(int sockfd, int result) { if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_pend_done_armed[sockfd] = 1; s_pend_done_val[sockfd] = result; } } void ns_peers_arm_send_pending_done(int sockfd, int result) { if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_snd_done_armed[sockfd] = 1; s_snd_done_val[sockfd] = result; } } /* ================= net_listener.h ================= */ void net_listener_request(int sockfd, net_listener_req_t reason) { g_peers.listener_req_calls++; g_peers.last_req_fd = sockfd; g_peers.last_req_reason = (int)reason; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { g_peers.req_armed[sockfd] = 1; g_peers.req_reason[sockfd] = (int)reason; } } void net_listener_clear(int sockfd) { g_peers.listener_clear_calls++; g_peers.last_clear_fd = sockfd; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { g_peers.req_armed[sockfd] = 0; } } void net_listener_tick(void) { g_peers.listener_tick_calls++; } void net_listener_settle(int sockfd, net_listener_settle_t level) { g_peers.listener_settle_calls++; g_peers.last_settle_fd = sockfd; g_peers.last_settle_level = (int)level; } /* ================= net_pending.h(recv 侧) ================= */ void net_pending_capture_owner(void) { g_peers.pending_capture_calls++; } int net_pending_register(int sockfd, void *buf, int len, uint32_t to_ms, TaskHandle_t caller) { g_peers.pending_reg_calls++; g_peers.last_pend_fd = sockfd; g_peers.last_pend_to = to_ms; g_peers.last_pend_caller = caller; if (g_peers.pend_register_rc != NET_PENDING_REGISTERED) { return g_peers.pend_register_rc; /* 测"登记被拒"分支 */ } if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_pend_active[sockfd] = 1; s_pend_buf[sockfd] = buf; s_pend_len[sockfd] = len; s_pend_caller[sockfd] = caller; g_peers.pend_active_now[sockfd] = 1; } return NET_PENDING_REGISTERED; } void net_pending_tick(net_sock_t *p_socks) { int i; g_peers.pending_tick_calls++; (void)p_socks; /* 复刻真实 tick 的主用例:数据到达 → 按登记时的 caller 通知 → 清槽 */ for (i = 0; i < NET_MAX_SOCKETS; i++) { if ((s_pend_active[i] != 0) && (s_pend_done_armed[i] != 0)) { s_pend_done_armed[i] = 0; s_pend_active[i] = 0; g_peers.pend_active_now[i] = 0; g_peers.pending_notified++; ns_peers_note_notify(s_pend_caller[i], (uint32_t)s_pend_done_val[i]); } } } void net_pending_clear(int sockfd) { g_peers.pending_clear_calls++; g_peers.last_pend_clear_fd = sockfd; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_pend_active[sockfd] = 0; g_peers.pend_active_now[sockfd] = 0; } } void net_pending_cancel(int sockfd, int err) { g_peers.pending_cancel_calls++; g_peers.last_pend_cancel_err = err; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_pend_active[sockfd] = 0; g_peers.pend_active_now[sockfd] = 0; } } void net_pending_cancel_all(int err) { int i; g_peers.pending_cancel_all_calls++; g_peers.last_pend_cancel_err = err; for (i = 0; i < NET_MAX_SOCKETS; i++) { if (s_pend_active[i] != 0) { g_peers.pending_notified++; ns_peers_note_notify(s_pend_caller[i], (uint32_t)err); } s_pend_active[i] = 0; g_peers.pend_active_now[i] = 0; } } void net_pending_settle_close(int sockfd, net_sock_t *p_sock) { g_peers.pending_settle_calls++; g_peers.last_pend_fd = sockfd; (void)p_sock; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS) && (s_pend_active[sockfd] != 0)) { /* 真实实现:有数据先送达,无数据按 CONNRESET 取消——两者都**必通知** */ s_pend_active[sockfd] = 0; g_peers.pend_active_now[sockfd] = 0; g_peers.pending_notified++; ns_peers_note_notify(s_pend_caller[sockfd], (uint32_t)NET_ERR_CONNRESET); } } int net_pending_active(int sockfd) { if ((sockfd < 0) || (sockfd >= NET_MAX_SOCKETS)) { return 0; } return s_pend_active[sockfd]; } /* ================= net_pending.h(send 侧) ================= */ /* 会话是否已断(net_send_locked / net_send_pending 的共用判据,真实实现按 type 分流)。 * 桩**必须复刻分流**:写死 TCP 语义的话,UDP 挂起 send 的"会话断了要中止"分支 * 在本套里永远测不到(2026-11-03 UDP 队列化改造新增边界)。 */ int net_send_state_down(const net_sock_t *p_sock) { g_peers.state_down_calls++; if (p_sock == NULL) { return 1; } if (p_sock->type == NET_SOCK_DGRAM) { return (p_sock->state != NET_SOCK_STATE_UDP_OPEN) ? 1 : 0; } return (p_sock->state != NET_SOCK_STATE_ESTABLISHED) ? 1 : 0; } int net_send_pending_register(int sockfd, const void *buf, int len, int sent, TaskHandle_t caller) { g_peers.send_reg_calls++; g_peers.last_snd_fd = sockfd; g_peers.last_snd_sent = sent; g_peers.last_snd_len = len; (void)buf; if (g_peers.send_register_rc != NET_PENDING_REGISTERED) { return g_peers.send_register_rc; } /* 真实实现的硬前置:sent >= len 视为参数非法拒收(末块边界) */ if (sent >= len) { return -1; } if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_snd_active[sockfd] = 1; s_snd_caller[sockfd] = caller; } return NET_PENDING_REGISTERED; } void net_send_pending_tick(net_sock_t *p_socks) { int i; g_peers.send_tick_calls++; (void)p_socks; for (i = 0; i < NET_MAX_SOCKETS; i++) { if ((s_snd_active[i] != 0) && (s_snd_done_armed[i] != 0)) { s_snd_done_armed[i] = 0; s_snd_active[i] = 0; g_peers.send_notified++; ns_peers_note_notify(s_snd_caller[i], (uint32_t)s_snd_done_val[i]); } } } void net_send_pending_clear(int sockfd) { g_peers.send_clear_calls++; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS)) { s_snd_active[sockfd] = 0; } } void net_send_pending_cancel(int sockfd, int err) { g_peers.send_cancel_calls++; g_peers.last_snd_cancel_err = err; if ((sockfd >= 0) && (sockfd < NET_MAX_SOCKETS) && (s_snd_active[sockfd] != 0)) { s_snd_active[sockfd] = 0; g_peers.send_notified++; ns_peers_note_notify(s_snd_caller[sockfd], (uint32_t)err); } } void net_send_pending_cancel_all(int err) { int i; g_peers.send_cancel_all_calls++; g_peers.last_snd_cancel_err = err; for (i = 0; i < NET_MAX_SOCKETS; i++) { if (s_snd_active[i] != 0) { g_peers.send_notified++; ns_peers_note_notify(s_snd_caller[i], (uint32_t)err); } s_snd_active[i] = 0; } } int net_send_pending_active(int sockfd) { if ((sockfd < 0) || (sockfd >= NET_MAX_SOCKETS)) { return 0; } return s_snd_active[sockfd]; } /* ================= net_events.h(事件面与对账) ================= */ /* 事件处理桩:按真实头注释的效果改控制块(CONNECT→ESTABLISHED + 记对端等), * 让 net_poll 的"中断 → 状态机"分派可断言;同时计数。 */ void handle_connect_event(net_sock_t *p_sock) { g_peers.evt_connect_calls++; if (p_sock != NULL) { p_sock->state = NET_SOCK_STATE_ESTABLISHED; p_sock->readable = 0U; p_sock->released_abnormal = 0U; p_sock->session_dead = 0U; } } void handle_disconnect_event(net_sock_t *p_sock) { g_peers.evt_disconnect_calls++; if (p_sock != NULL) { p_sock->last_peer_port = p_sock->remote_port; p_sock->state = NET_SOCK_STATE_CLOSED; p_sock->session_dead = 1U; } } void handle_recv_event(net_sock_t *p_sock) { g_peers.evt_recv_calls++; if (p_sock != NULL) { p_sock->readable = 1U; } } void handle_send_event(net_sock_t *p_sock) { g_peers.evt_send_calls++; if (p_sock != NULL) { p_sock->send_ready = 1U; } } void handle_timeout_event(net_sock_t *p_sock) { g_peers.evt_timeout_calls++; if (p_sock != NULL) { p_sock->last_peer_port = p_sock->remote_port; p_sock->state = NET_SOCK_STATE_CLOSED; p_sock->released_abnormal = 1U; p_sock->session_dead = 1U; } } void net_reconcile_tick(void) { g_peers.reconcile_calls++; } void net_lost_connect_probe(net_sock_t *p_sock) { g_peers.lost_probe_calls++; g_peers.last_probe_state = (p_sock != NULL) ? (int)p_sock->state : -1; if ((p_sock != NULL) && (g_peers.lost_probe_hit != 0)) { /* 脚本:探针命中 → 直接转 ESTABLISHED(复刻补 accept 的净效果) */ p_sock->state = NET_SOCK_STATE_ESTABLISHED; p_sock->lost_conn_seen = 0U; } }