@@ -0,0 +1,467 @@
/*
* 模块名称:NET 层挂起 recv / 挂起 send( net_pending)主机侧单元测试
* 模块功能:在 PC 上离线验证 Drivers/BSP/NET/net_pending.c 的两条挂起队列:注册闸门
* (越界/重复/执行任务自己发起)、**错误码经任务通知值回传**这条跨上下文
* 契约、收数据到达与截断、超时、会话塌掉的四种收尾分支(不丢尾包 / 干净
* 结束报 0 / 异常释放报 CONNRESET / 槽位消失报 CONNRESET)、settle_close 的
* 收尾语义,以及发送侧的分块上限、停滞判定、deadline 续期与取消语义。
*
* 被测对象:真实源文件 ../../../Drivers/BSP/NET/net_pending.c( #include 原样纳入)。
* net_pending.h / net_types.h / net_config.h / net_listener.h 全用**真实头**
* ( TaskHandle_t 入参、NET_PENDING_REGISTERED、NET_SEND_TIMEOUT_MS、
* net_listener_req_t 枚举一改就编译期报错)。假件:
* - 假 CH395F 芯片(test/host/common/ch395f_fake.h/.c,含与真实头同构转抄
* 的缓冲尺寸宏链,NET_SEND_CHUNK_MAX 因此是真值 1024 而非假件自造);
* - **可观测的 xTaskNotify**(记目标句柄与通知值)与固定句柄的
* xTaskGetCurrentTaskHandle;
* - 记录型 net_listener_request;可控时基;可控 socket 表数组(tick 入参);
* 可控"芯片此刻还有多少字节可读"; dbg_log 计数;net_set_errno 记录。
*
* 为什么要主机侧单测(而不是只靠台架):
* 1. AGENTS 模块约定写着:net_* 公开 API 的错误码经**任务通知值**回传,因为 net_msg_t
* 是**按值拷入队列**的,netTask 改的是自己那份副本,调用方永远看不到;也**勿给
* net_msg_t 加回传字段**(加了只会让调用方读到栈垃圾)。这条契约在真机上表现为
* "偶发拿到 0 或正数却不知道为什么",日志无痕;在 PC 上必须把 xTaskNotify 做成
* 可观测的才谈得上验证——台架根本读不到通知值。
* 2. 挂起 recv 的收尾有**四条**分支(还有尾包 / 干净结束报 0 / 异常释放报 CONNRESET /
* 槽位没了报 CONNRESET),差一条就是"对端已断而我方任务还挂着"或"最后一包数据
* 被丢掉"。真机要凑齐"关闭瞬间芯片接收区还剩字节"这种窗口极难。
* 3. 发送侧分块上限 = min(芯片发送缓冲, SPI DMA 上界):一次写太多会踩芯片 FIFO,
* 表现为"大包发送偶发数据错位";而 deadline 每写一轮就续期,写错就会把**长文件
* 在传输中途掐死**(FTP 上传大文件最容易撞)。两者都要能精确数着字节测。
*
* 覆盖点:TC-NETPEND-001..006 注册闸门;007..018 到达/截断/超时/四条收尾/取消与清理;
* 019..021 settle_close; 030..040 挂起发送(参数校验、分块、续期、停滞、取消)。
*
* 通过:全部 TC PASS( main 返回 0)。
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
*
* 创建日期:2026-10-23
*/
# include <stdio.h>
# include <string.h>
# include "net_pending.h"
# include "net_listener.h"
# include "net_socket.h"
# include "ch395f.h"
# include "ch395f_fake.c"
# include "net_pending.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)
int g_npd_info_count ;
int g_npd_error_count ;
int g_npd_debug_count ;
/* ============ 可观测的任务通知(本模块最重要的一条契约靠它才测得到) ============ */
static int g_owner_obj ;
static int g_caller_obj ;
static int g_notify_n ;
static void * g_notify_target [ 16 ] ;
static uint32_t g_notify_value [ 16 ] ;
TaskHandle_t xTaskGetCurrentTaskHandle ( void )
{
return ( TaskHandle_t ) & g_owner_obj ;
}
BaseType_t xTaskNotify ( TaskHandle_t xTaskToNotify , uint32_t ulValue , eNotifyAction eAction )
{
( void ) eAction ;
if ( g_notify_n < ( int ) ( sizeof ( g_notify_target ) / sizeof ( g_notify_target [ 0 ] ) ) ) {
g_notify_target [ g_notify_n ] = ( void * ) xTaskToNotify ;
g_notify_value [ g_notify_n ] = ulValue ;
}
g_notify_n + + ;
return 1 ;
}
/* ============ 记录型监听请求 ============ */
static int g_lis_req_n ;
static int g_lis_req_sock ;
static int g_lis_req_reason ;
void net_listener_request ( int sockfd , net_listener_req_t reason )
{
g_lis_req_n + + ;
g_lis_req_sock = sockfd ;
g_lis_req_reason = ( int ) reason ;
}
void net_listener_settle ( int sockfd , net_listener_settle_t level ) { ( void ) sockfd ; ( void ) level ; }
void net_listener_clear ( int sockfd ) { ( void ) sockfd ; }
void net_listener_tick ( void ) { }
/* ============ 可控时基与 errno ============ */
static uint32_t g_now ;
static int g_errno_last ;
static int g_errno_calls ;
uint32_t HAL_GetTick ( void ) { return g_now ; }
int net_set_errno ( int err )
{
g_errno_last = err ;
g_errno_calls + + ;
return err ;
}
/* ============ 可控 socket 表(tick 的入参) ============ */
static net_sock_t g_socks [ NET_MAX_SOCKETS ] ;
static uint8_t g_rbuf [ 64 ] ;
static uint8_t g_wbuf [ 4096 ] ;
static void mk_sock ( int fd , net_sock_state_t st )
{
g_socks [ fd ] . in_use = 1u ;
g_socks [ fd ] . state = st ;
g_socks [ fd ] . type = NET_SOCK_STREAM ;
g_socks [ fd ] . auto_relisten = 1u ;
g_socks [ fd ] . local_port = 2404u ;
}
static void reset_all ( void )
{
int i ;
( void ) memset ( g_socks , 0 , sizeof ( g_socks ) ) ;
( void ) memset ( g_rbuf , 0 , sizeof ( g_rbuf ) ) ;
g_now = 1000u ;
g_errno_last = 0 ;
g_errno_calls = 0 ;
g_notify_n = 0 ;
g_lis_req_n = 0 ;
g_lis_req_sock = - 1 ;
g_lis_req_reason = - 1 ;
g_npd_info_count = 0 ;
g_npd_error_count = 0 ;
g_npd_debug_count = 0 ;
ch395f_fake_reset ( ) ;
/* 被测模块自己的 static 必须复位:两张挂起表 + 属主句柄
( net_listener 批次在这里红过 9 条,同样的坑不踩第二遍)。 */
for ( i = 0 ; i < NET_MAX_SOCKETS ; i + + ) {
s_net_pending [ i ] . active = 0u ;
s_net_send [ i ] . active = 0u ;
}
s_owner_task = ( TaskHandle_t ) & g_owner_obj ;
}
static void tc_recv_register ( void )
{
int rc ;
printf ( " -- TC-NETPEND-001..006 recv register -- \n " ) ;
reset_all ( ) ;
rc = net_pending_register ( - 1 , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BADF ) , " TC-NETPEND-001 下越界 fd 报 BADF " ) ;
rc = net_pending_register ( NET_MAX_SOCKETS , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BADF ) , " TC-NETPEND-001b 上越界同样拦下 " ) ;
reset_all ( ) ;
rc = net_pending_register ( 0 , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( rc = = NET_PENDING_REGISTERED , " TC-NETPEND-005 注册成功回 0x70000000 标记 " ) ;
rc = net_pending_register ( 0 , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BUSY ) ,
" TC-NETPEND-002 同 fd 已有挂起就拒绝(一条 socket 只挂一个 recv) " ) ;
reset_all ( ) ;
rc = net_pending_register ( 0 , g_rbuf , 10 , 100u , NULL ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BUSY ) ,
" TC-NETPEND-003 caller 为空拒绝(没有回传目标就别挂起) " ) ;
rc = net_pending_register ( 0 , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_owner_obj ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BUSY ) ,
" TC-NETPEND-004 属主任务自己发起被拒(自己等自己 = 死锁 netTask) " ) ;
reset_all ( ) ;
/* 必须先把槽位置成"在用且已建立":否则 tick 第一条兜底(in_use == 0 →
* CONNRESET)就会把挂起收掉,测的就不是时间轴了。 */
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 0u , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( s_net_pending [ 0 ] . infinite = = 1u ) & & ( s_net_pending [ 0 ] . deadline = = 0u ) ,
" TC-NETPEND-006 to_ms=0 记为无限等(不置 deadline) " ) ;
g_now = 999999u ;
net_pending_tick ( g_socks ) ;
CHECK ( ( s_net_pending [ 0 ] . active = = 1u ) & & ( g_notify_n = = 0 ) ,
" TC-NETPEND-006b 无限等不被时间掐掉(也不会偷偷发通知) " ) ;
}
static void tc_recv_paths ( void )
{
printf ( " -- TC-NETPEND-007..018 recv completion -- \n " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
g_socks [ 0 ] . readable = 1u ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
ch395f_fake_push_recv_len ( 0 , 5u ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_n = = 1 ) & & ( g_notify_value [ 0 ] = = 5u ) & &
( g_notify_target [ 0 ] = = ( void * ) & g_caller_obj ) & &
( g_socks [ 0 ] . recv_bytes = = 5u ) & & ( g_socks [ 0 ] . readable = = 0u ) & &
( s_net_pending [ 0 ] . active = = 0u ) ,
" TC-NETPEND-007 数据到达:字节数经通知值回传给发起任务 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
g_socks [ 0 ] . readable = 1u ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
ch395f_fake_push_recv_len ( 0 , 100u ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = 10u ) & & ( g_chip . last_read_len = = 10u ) ,
" TC-NETPEND-008 读量钳在调用方缓冲内(绝不越界写别人的 buf) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
g_socks [ 0 ] . readable = 1u ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_n = = 0 ) & & ( g_socks [ 0 ] . readable = = 0u ) & &
( s_net_pending [ 0 ] . active = = 1u ) ,
" TC-NETPEND-009 空 readable:清标志继续等,不误交 0 字节 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 100u , ( TaskHandle_t ) & g_caller_obj ) ;
g_now = 1100u ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = ( uint32_t ) NET_ERR_TIMEDOUT ) & &
( g_errno_last = = NET_ERR_TIMEDOUT ) & & ( s_net_pending [ 0 ] . active = = 0u ) ,
" TC-NETPEND-010 超时:错误码同时进通知值与 errno(跨上下文拿得到) " ) ;
reset_all ( ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
g_socks [ 0 ] . in_use = 0u ;
net_pending_tick ( g_socks ) ;
CHECK ( g_notify_value [ 0 ] = = ( uint32_t ) NET_ERR_CONNRESET ,
" TC-NETPEND-011 槽位消失报 CONNRESET(不能让任务熬到超时才发现) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
ch395f_fake_push_recv_len ( 0 , 12u ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = 12u ) & & ( g_socks [ 0 ] . recv_bytes = = 12u ) & &
( g_lis_req_n = = 0 ) ,
" TC-NETPEND-012 关闭但有残留:先把最后一包读走再收尾(不丢尾包) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = 0u ) & & ( g_lis_req_n = = 1 ) & & ( g_lis_req_sock = = 0 ) & &
( g_lis_req_reason = = ( int ) NET_LISTENER_REQ_PENDING ) ,
" TC-NETPEND-013 干净结束:报 0 并请求重开监听(单连接 socket 必须回 LISTEN) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
g_socks [ 0 ] . auto_relisten = 0u ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = 0u ) & & ( g_lis_req_n = = 0 ) ,
" TC-NETPEND-013b 不自动重开的 socket 不会被偷偷要求重建监听 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
g_socks [ 0 ] . released_abnormal = 1u ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_tick ( g_socks ) ;
CHECK ( g_notify_value [ 0 ] = = ( uint32_t ) NET_ERR_CONNRESET ,
" TC-NETPEND-014 异常释放报 CONNRESET 而不是 0(调用方要能分辨好坏收尾) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
g_socks [ 0 ] . session_dead = 1u ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_n = = 1 ) & & ( g_lis_req_n = = 1 ) ,
" TC-NETPEND-015 session_dead 与 CLOSED 同路(状态滞后时仍能收口) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_cancel ( 0 , NET_ERR_CONNRESET ) ;
CHECK ( ( g_notify_value [ 0 ] = = ( uint32_t ) NET_ERR_CONNRESET ) & &
( g_errno_last = = NET_ERR_CONNRESET ) & & ( s_net_pending [ 0 ] . active = = 0u ) ,
" TC-NETPEND-016 取消:错误码经通知值送达并解除挂起 " ) ;
net_pending_cancel ( 0 , NET_ERR_CONNRESET ) ;
CHECK ( g_notify_n = = 1 , " TC-NETPEND-016b 重复取消幂等(不给同一任务发两次通知) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
mk_sock ( 2 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
( void ) net_pending_register ( 2 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_cancel_all ( NET_ERR_CONNRESET ) ;
CHECK ( ( g_notify_n = = 2 ) & & ( s_net_pending [ 0 ] . active = = 0u ) & &
( s_net_pending [ 2 ] . active = = 0u ) ,
" TC-NETPEND-017 cancel_all 只通知挂着的那两个(网络整体复位时用) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 10 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_clear ( 0 ) ;
CHECK ( ( s_net_pending [ 0 ] . active = = 0u ) & & ( g_notify_n = = 0 ) ,
" TC-NETPEND-018 clear 只解除挂起、不发通知(不给调用方假答复) " ) ;
}
static void tc_settle_close ( void )
{
int before ;
printf ( " -- TC-NETPEND-019..021 settle_close -- \n " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
before = g_chip . read_calls + g_chip . get_status_calls ;
net_pending_settle_close ( 0 , & g_socks [ 0 ] ) ;
CHECK ( ( g_chip . read_calls + g_chip . get_status_calls ) = = before ,
" TC-NETPEND-019 没挂起时直接返回(不打扰芯片) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
ch395f_fake_push_recv_len ( 0 , 7u ) ;
net_pending_settle_close ( 0 , & g_socks [ 0 ] ) ;
CHECK ( ( g_notify_value [ 0 ] = = 7u ) & & ( g_socks [ 0 ] . recv_bytes = = 7u ) & &
( g_socks [ 0 ] . readable = = 0u ) ,
" TC-NETPEND-020 收尾时把剩余字节读走并交还字节数(收口不丢数据) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
( void ) net_pending_register ( 0 , g_rbuf , 20 , 500u , ( TaskHandle_t ) & g_caller_obj ) ;
net_pending_settle_close ( 0 , & g_socks [ 0 ] ) ;
CHECK ( g_notify_value [ 0 ] = = ( uint32_t ) NET_ERR_CONNRESET ,
" TC-NETPEND-021 无残留则报 CONNRESET(关闭收尾不该被当成读到 0 字节) " ) ;
}
static void tc_send_paths ( void )
{
int rc ;
printf ( " -- TC-NETPEND-030..040 send pending -- \n " ) ;
reset_all ( ) ;
rc = net_send_pending_register ( - 1 , g_wbuf , 100 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( rc = = - 1 ) & & ( g_errno_last = = NET_ERR_BADF ) , " TC-NETPEND-030 越界 fd 报 BADF " ) ;
rc = net_send_pending_register ( 0 , NULL , 100 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( g_errno_last = = NET_ERR_INVAL , " TC-NETPEND-030b buf 为空报 INVAL " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 0 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( g_errno_last = = NET_ERR_INVAL , " TC-NETPEND-030c len 非正报 INVAL " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , - 1 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( g_errno_last = = NET_ERR_INVAL , " TC-NETPEND-030d sent 为负报 INVAL " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , 100 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( ( g_errno_last = = NET_ERR_INVAL ) & & ( s_net_send [ 0 ] . active = = 0u ) ,
" TC-NETPEND-030e sent>=len 报 INVAL(已发完的不必挂) " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , 50 , NULL ) ;
CHECK ( g_errno_last = = NET_ERR_BUSY , " TC-NETPEND-031 caller 为空报 BUSY " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , 50 , ( TaskHandle_t ) & g_owner_obj ) ;
CHECK ( g_errno_last = = NET_ERR_BUSY , " TC-NETPEND-031b 属主自己发报 BUSY " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , 50 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( rc = = NET_PENDING_REGISTERED , " TC-NETPEND-032 挂起发送注册成功 " ) ;
rc = net_send_pending_register ( 0 , g_wbuf , 100 , 50 , ( TaskHandle_t ) & g_caller_obj ) ;
CHECK ( g_errno_last = = NET_ERR_BUSY , " TC-NETPEND-031c 同 fd 只允许一条挂起发送 " ) ;
reset_all ( ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 700 , ( TaskHandle_t ) & g_caller_obj ) ;
g_socks [ 0 ] . in_use = 0u ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_n = = 1 ) & & ( g_notify_value [ 0 ] = = 700u ) ,
" TC-NETPEND-033 槽位消失回**已发字节数**(不是错误码,调用方据此算进度) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_CLOSED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 700 , ( TaskHandle_t ) & g_caller_obj ) ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_npd_error_count = = 1 ) & & ( g_errno_last = = NET_ERR_CONNRESET ) & &
( g_notify_value [ 0 ] = = 700u ) ,
" TC-NETPEND-034 会话塌了:留 ERROR + 报 CONNRESET,但仍把已发字节交回去 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
g_socks [ 0 ] . send_ready = 1u ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_chip . write_calls = = 1 ) & &
( g_chip . last_read_len = = ( uint16_t ) NET_SEND_CHUNK_MAX ) & &
( g_socks [ 0 ] . send_bytes = = ( uint32_t ) NET_SEND_CHUNK_MAX ) & &
( g_socks [ 0 ] . send_ready = = 0u ) & & ( s_net_send [ 0 ] . active = = 1u ) ,
" TC-NETPEND-035 单次写入钳在 NET_SEND_CHUNK_MAX(芯片发送缓冲上界) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
g_socks [ 0 ] . send_ready = 1u ;
net_send_pending_tick ( g_socks ) ;
g_socks [ 0 ] . send_ready = 1u ;
net_send_pending_tick ( g_socks ) ;
g_socks [ 0 ] . send_ready = 1u ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_notify_value [ 0 ] = = 3000u ) & & ( s_net_send [ 0 ] . active = = 0u ) & &
( g_chip . write_calls = = 3 ) ,
" TC-NETPEND-036 分三块发完 3000 字节后交还总长度 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
g_now = 1900u ;
g_socks [ 0 ] . send_ready = 1u ;
net_send_pending_tick ( g_socks ) ;
g_now = 2800u ;
g_socks [ 0 ] . send_ready = 1u ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_npd_error_count = = 0 ) & & ( s_net_send [ 0 ] . active = = 1u ) & &
( g_chip . write_calls = = 2 ) ,
" TC-NETPEND-038 每写一轮续期 deadline:还在推进就不该被 1000ms 掐死 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 3000 , 0 , ( TaskHandle_t ) & g_caller_obj ) ;
g_now = 2000u ;
net_send_pending_tick ( g_socks ) ;
CHECK ( ( g_npd_error_count = = 1 ) & & ( g_errno_last = = NET_ERR_TIMEDOUT ) & &
( g_notify_value [ 0 ] = = 0u ) ,
" TC-NETPEND-037 停滞超时报 TIMEDOUT(对端不收时不能永久占着发送通道) " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 100 , 40 , ( TaskHandle_t ) & g_caller_obj ) ;
net_send_pending_cancel ( 0 , NET_ERR_CONNRESET ) ;
CHECK ( ( g_npd_error_count = = 1 ) & & ( g_errno_last = = NET_ERR_CONNRESET ) & &
( g_notify_value [ 0 ] = = 40u ) & & ( s_net_send [ 0 ] . active = = 0u ) ,
" TC-NETPEND-039 取消挂起发送:留痕 + 交还已发字节 " ) ;
net_send_pending_cancel ( 0 , NET_ERR_CONNRESET ) ;
CHECK ( g_notify_n = = 1 , " TC-NETPEND-039b 重复取消幂等 " ) ;
reset_all ( ) ;
mk_sock ( 0 , NET_SOCK_STATE_ESTABLISHED ) ;
( void ) net_send_pending_register ( 0 , g_wbuf , 100 , 40 , ( TaskHandle_t ) & g_caller_obj ) ;
net_send_pending_clear ( 0 ) ;
CHECK ( ( s_net_send [ 0 ] . active = = 0u ) & & ( g_notify_n = = 0 ) ,
" TC-NETPEND-040 clear 不发通知(与 recv 侧同一条纪律) " ) ;
}
int main ( void )
{
printf ( " === NET Pending Tests === \n " ) ;
tc_recv_register ( ) ;
tc_recv_paths ( ) ;
tc_settle_close ( ) ;
tc_send_paths ( ) ;
printf ( " \n === NET Pending Tests: %d/%d PASSED (failed=%d) === \n " ,
s_passed , s_total , s_failed ) ;
return ( s_failed = = 0 ) ? 0 : 1 ;
}