feat(test): libcomm 单元测试 — 17 项全覆盖
- 7 大测试组: 创建与销毁(4) / 参数校验(7) / TCP回环 / UDP回环 / 状态回调(2) / 错误路径 / 断开重连 - TCP: 127.0.0.1 localhost 回环验证 send/recv 数据一致性 - UDP: sendto/recvfrom 回环验证 - 状态回调: CONNECTED/DISCONNECTED 通知验证 - 参数校验: NULL para/非法type/越界type/非法id/空数据/零长度
This commit is contained in:
parent
16e3efb19c
commit
066dc62916
|
|
@ -0,0 +1,851 @@
|
|||
/**
|
||||
* @file test_comm.cpp
|
||||
* @brief 通讯抽象层模块单元测试
|
||||
* @details 覆盖:生命周期、TCP 回环、UDP 回环、状态回调、
|
||||
* 断连重连、参数校验、错误处理。
|
||||
* 7 项测试,需要 comm_run 在独立线程中运行。
|
||||
*/
|
||||
#include "myComm.h"
|
||||
#include "myBase.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
|
||||
/* ===== 测试辅助宏 ===== */
|
||||
|
||||
static int g_pass = 0;
|
||||
static int g_fail = 0;
|
||||
|
||||
#define TEST(name) \
|
||||
do \
|
||||
{ \
|
||||
printf(" TEST: %s ... ", name); \
|
||||
} while (0)
|
||||
|
||||
#define OK() \
|
||||
do \
|
||||
{ \
|
||||
printf("OK\n"); \
|
||||
g_pass++; \
|
||||
} while (0)
|
||||
|
||||
#define FAIL(msg) \
|
||||
do \
|
||||
{ \
|
||||
printf("FAIL: %s\n", msg); \
|
||||
g_fail++; \
|
||||
} while (0)
|
||||
|
||||
/* ===== 全局测试状态 ===== */
|
||||
|
||||
static std::thread g_event_thread;
|
||||
static std::atomic<bool> g_test_running(false);
|
||||
|
||||
static int g_svr_id = -1;
|
||||
static int g_cli_id = -1;
|
||||
static int g_udp1_id = -1;
|
||||
static int g_udp2_id = -1;
|
||||
static int g_svr_client_fd = -1;
|
||||
static int g_cli_local_fd = -1; /** 客户端本地 fd(从状态回调获取) */
|
||||
static int g_udp_cli_fd = -1; /** UDP 客户端 fd */
|
||||
|
||||
static int g_recv_count = 0;
|
||||
static int g_state_changes = 0;
|
||||
static int g_last_state = -1;
|
||||
static unsigned char g_recv_buf[1024];
|
||||
static int g_recv_len = 0;
|
||||
|
||||
static int g_svr_state_changes = 0;
|
||||
|
||||
/* ===== 回调函数 ===== */
|
||||
|
||||
static void on_cli_state(int id, int fd, int state)
|
||||
{
|
||||
(void)id;
|
||||
g_cli_local_fd = fd;
|
||||
g_last_state = state;
|
||||
g_state_changes++;
|
||||
}
|
||||
|
||||
static void on_svr_state(int id, int fd, int state)
|
||||
{
|
||||
(void)id;
|
||||
(void)fd;
|
||||
(void)state;
|
||||
g_svr_state_changes++;
|
||||
}
|
||||
|
||||
static void on_svr_recv(int id, int fd, const unsigned char *data, int len)
|
||||
{
|
||||
(void)id;
|
||||
(void)fd;
|
||||
|
||||
memcpy(g_recv_buf, data, len);
|
||||
g_recv_len = len;
|
||||
g_recv_count++;
|
||||
|
||||
if (g_svr_client_fd < 0)
|
||||
{
|
||||
g_svr_client_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_udp_cli_state(int id, int fd, int state)
|
||||
{
|
||||
(void)id;
|
||||
(void)state;
|
||||
g_udp_cli_fd = fd;
|
||||
}
|
||||
|
||||
static void on_udp_recv(int id, int fd, const unsigned char *data, int len)
|
||||
{
|
||||
(void)id;
|
||||
(void)fd;
|
||||
|
||||
memcpy(g_recv_buf, data, len);
|
||||
g_recv_len = len;
|
||||
g_recv_count++;
|
||||
}
|
||||
|
||||
/* ===== 辅助函数 ===== */
|
||||
|
||||
static void reset_test_state(void)
|
||||
{
|
||||
g_recv_count = 0;
|
||||
g_state_changes = 0;
|
||||
g_last_state = -1;
|
||||
g_svr_client_fd = -1;
|
||||
g_cli_local_fd = -1;
|
||||
g_udp_cli_fd = -1;
|
||||
g_recv_len = 0;
|
||||
g_svr_state_changes = 0;
|
||||
memset(g_recv_buf, 0, sizeof(g_recv_buf));
|
||||
}
|
||||
|
||||
static void start_event_loop(void)
|
||||
{
|
||||
g_test_running = true;
|
||||
g_event_thread = std::thread([]()
|
||||
{
|
||||
comm_run();
|
||||
});
|
||||
}
|
||||
|
||||
static void stop_event_loop(void)
|
||||
{
|
||||
comm_stop();
|
||||
if (g_event_thread.joinable())
|
||||
{
|
||||
g_event_thread.join();
|
||||
}
|
||||
g_test_running = false;
|
||||
}
|
||||
|
||||
static void msleep(int ms)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 1: 创建与销毁
|
||||
* ================================================================ */
|
||||
static void test_01_create_destroy(void)
|
||||
{
|
||||
TEST("create/destroy TCP server");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.tcp.local_ip, "127.0.0.1");
|
||||
para.tcp.local_port = 19999;
|
||||
|
||||
int id = comm_create(COMM_TYPE_TCP_SERVER, 0, ¶);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
int ret = comm_destroy(id);
|
||||
|
||||
if (ret == COMM_OK)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("destroy failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("create failed");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("create/destroy TCP client");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.tcp.remote_ip, "127.0.0.1");
|
||||
para.tcp.remote_port = 19999;
|
||||
|
||||
int id = comm_create(COMM_TYPE_TCP_CLIENT, 0, ¶);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
int ret = comm_destroy(id);
|
||||
|
||||
if (ret == COMM_OK)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("destroy failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("create failed");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("create/destroy UDP server");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.udp.local_ip, "127.0.0.1");
|
||||
para.udp.local_port = 20000;
|
||||
|
||||
int id = comm_create(COMM_TYPE_UDP_SERVER, 0, ¶);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
int ret = comm_destroy(id);
|
||||
|
||||
if (ret == COMM_OK)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("destroy failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("create failed");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("create/destroy UDP client");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.udp.local_ip, "127.0.0.1");
|
||||
para.udp.local_port = 20001;
|
||||
strcpy(para.udp.remote_ip, "127.0.0.1");
|
||||
para.udp.remote_port = 20000;
|
||||
|
||||
int id = comm_create(COMM_TYPE_UDP_CLIENT, 0, ¶);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
int ret = comm_destroy(id);
|
||||
|
||||
if (ret == COMM_OK)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("destroy failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("create failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 2: 参数校验
|
||||
* ================================================================ */
|
||||
static void test_02_param_validation(void)
|
||||
{
|
||||
TEST("comm_create with NULL para");
|
||||
{
|
||||
int id = comm_create(COMM_TYPE_TCP_SERVER, 0, NULL);
|
||||
|
||||
if (id == COMM_ERR_PARAM)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_PARAM");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_create with invalid type");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
|
||||
int id = comm_create(-1, 0, ¶);
|
||||
|
||||
if (id == COMM_ERR_PARAM)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_PARAM");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_create with out-of-range type");
|
||||
{
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
|
||||
int id = comm_create(99, 0, ¶);
|
||||
|
||||
if (id == COMM_ERR_PARAM)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_PARAM");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_connect invalid id");
|
||||
{
|
||||
int ret = comm_connect(9999);
|
||||
|
||||
if (ret == COMM_ERR_NOT_FOUND)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_NOT_FOUND");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_send NULL data");
|
||||
{
|
||||
int ret = comm_send(1, 0, NULL, 5);
|
||||
|
||||
if (ret == COMM_ERR_PARAM)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_PARAM");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_send zero len");
|
||||
{
|
||||
unsigned char buf[4] = {0};
|
||||
|
||||
int ret = comm_send(1, 0, buf, 0);
|
||||
|
||||
if (ret == COMM_ERR_PARAM)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_PARAM");
|
||||
}
|
||||
}
|
||||
|
||||
TEST("comm_destroy invalid id");
|
||||
{
|
||||
int ret = comm_destroy(9999);
|
||||
|
||||
if (ret == COMM_ERR_NOT_FOUND)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("expected COMM_ERR_NOT_FOUND");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 3: TCP 回环 — 客户端发送,服务器接收
|
||||
* ================================================================ */
|
||||
static void test_03_tcp_loopback(void)
|
||||
{
|
||||
TEST("TCP loopback send/recv");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
/* 创建 TCP 服务器 */
|
||||
union_comm_para svr_para;
|
||||
|
||||
memset(&svr_para, 0, sizeof(svr_para));
|
||||
strcpy(svr_para.tcp.local_ip, "127.0.0.1");
|
||||
svr_para.tcp.local_port = 21001;
|
||||
|
||||
g_svr_id = comm_create(COMM_TYPE_TCP_SERVER, 0, &svr_para);
|
||||
if (g_svr_id < 0)
|
||||
{
|
||||
FAIL("server create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
comm_recv_register(g_svr_id, on_svr_recv);
|
||||
comm_state_register(g_svr_id, on_svr_state);
|
||||
|
||||
if (comm_connect(g_svr_id) != COMM_OK)
|
||||
{
|
||||
FAIL("server connect failed");
|
||||
comm_destroy(g_svr_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 创建 TCP 客户端 */
|
||||
union_comm_para cli_para;
|
||||
|
||||
memset(&cli_para, 0, sizeof(cli_para));
|
||||
strcpy(cli_para.tcp.remote_ip, "127.0.0.1");
|
||||
cli_para.tcp.remote_port = 21001;
|
||||
|
||||
g_cli_id = comm_create(COMM_TYPE_TCP_CLIENT, 0, &cli_para);
|
||||
if (g_cli_id < 0)
|
||||
{
|
||||
FAIL("client create failed");
|
||||
comm_destroy(g_svr_id);
|
||||
return;
|
||||
}
|
||||
|
||||
comm_state_register(g_cli_id, on_cli_state);
|
||||
|
||||
if (comm_connect(g_cli_id) != COMM_OK)
|
||||
{
|
||||
FAIL("client connect failed");
|
||||
comm_destroy(g_cli_id);
|
||||
comm_destroy(g_svr_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 等待连接建立 + accept */
|
||||
msleep(500);
|
||||
|
||||
if (g_state_changes == 0 || g_cli_local_fd < 0)
|
||||
{
|
||||
printf("(state_changes=%d cli_fd=%d svr_states=%d) ",
|
||||
g_state_changes, g_cli_local_fd, g_svr_state_changes);
|
||||
FAIL("no state change on client connect");
|
||||
comm_destroy(g_cli_id);
|
||||
comm_destroy(g_svr_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 发送数据 */
|
||||
const char *msg = "HELLO_MODBUS";
|
||||
int len = (int)strlen(msg);
|
||||
|
||||
{
|
||||
int sent = comm_send(g_cli_id, g_cli_local_fd,
|
||||
(const unsigned char *)msg, len);
|
||||
|
||||
if (sent != len)
|
||||
{
|
||||
printf("(sent=%d expected=%d errno=%d svr_states=%d) ",
|
||||
sent, len, errno, g_svr_state_changes);
|
||||
FAIL("send failed or partial");
|
||||
comm_destroy(g_cli_id);
|
||||
comm_destroy(g_svr_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 等待服务器接收(重试最多 2 秒) */
|
||||
for (int retry = 0; retry < 20 && g_recv_count == 0; retry++)
|
||||
{
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (g_recv_count > 0 && g_recv_len == len
|
||||
&& memcmp(g_recv_buf, msg, len) == 0)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("recv_count=%d recv_len=%d expected_len=%d svr_states=%d cli_states=%d ",
|
||||
g_recv_count, g_recv_len, len,
|
||||
g_svr_state_changes, g_state_changes);
|
||||
FAIL("data mismatch or not received");
|
||||
}
|
||||
|
||||
comm_destroy(g_cli_id);
|
||||
comm_destroy(g_svr_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 4: UDP 回环
|
||||
* ================================================================ */
|
||||
static void test_04_udp_loopback(void)
|
||||
{
|
||||
TEST("UDP loopback send/recv");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
/* 创建 UDP 服务器(接收端) */
|
||||
union_comm_para svr_para;
|
||||
|
||||
memset(&svr_para, 0, sizeof(svr_para));
|
||||
strcpy(svr_para.udp.local_ip, "127.0.0.1");
|
||||
svr_para.udp.local_port = 22001;
|
||||
|
||||
g_udp1_id = comm_create(COMM_TYPE_UDP_SERVER, 0, &svr_para);
|
||||
if (g_udp1_id < 0)
|
||||
{
|
||||
FAIL("UDP server create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
comm_recv_register(g_udp1_id, on_udp_recv);
|
||||
|
||||
if (comm_connect(g_udp1_id) != COMM_OK)
|
||||
{
|
||||
FAIL("UDP server connect failed");
|
||||
comm_destroy(g_udp1_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 创建 UDP 客户端(发送端) */
|
||||
union_comm_para cli_para;
|
||||
|
||||
memset(&cli_para, 0, sizeof(cli_para));
|
||||
strcpy(cli_para.udp.local_ip, "127.0.0.1");
|
||||
cli_para.udp.local_port = 22002;
|
||||
strcpy(cli_para.udp.remote_ip, "127.0.0.1");
|
||||
cli_para.udp.remote_port = 22001;
|
||||
|
||||
g_udp2_id = comm_create(COMM_TYPE_UDP_CLIENT, 0, &cli_para);
|
||||
if (g_udp2_id < 0)
|
||||
{
|
||||
FAIL("UDP client create failed");
|
||||
comm_destroy(g_udp1_id);
|
||||
return;
|
||||
}
|
||||
|
||||
comm_state_register(g_udp2_id, on_udp_cli_state);
|
||||
|
||||
if (comm_connect(g_udp2_id) != COMM_OK)
|
||||
{
|
||||
FAIL("UDP client connect failed");
|
||||
comm_destroy(g_udp2_id);
|
||||
comm_destroy(g_udp1_id);
|
||||
return;
|
||||
}
|
||||
|
||||
msleep(200);
|
||||
|
||||
if (g_udp_cli_fd < 0)
|
||||
{
|
||||
FAIL("UDP client fd not captured");
|
||||
comm_destroy(g_udp2_id);
|
||||
comm_destroy(g_udp1_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 发送数据 */
|
||||
const char *msg = "HELLO_UDP";
|
||||
int len = (int)strlen(msg);
|
||||
|
||||
{
|
||||
int sent = comm_send(g_udp2_id, g_udp_cli_fd,
|
||||
(const unsigned char *)msg, len);
|
||||
|
||||
if (sent != len)
|
||||
{
|
||||
printf("(sent=%d expected=%d) ", sent, len);
|
||||
FAIL("UDP send failed");
|
||||
comm_destroy(g_udp2_id);
|
||||
comm_destroy(g_udp1_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 等待 UDP 接收(重试最多 2 秒) */
|
||||
for (int retry = 0; retry < 20 && g_recv_count == 0; retry++)
|
||||
{
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (g_recv_count > 0 && g_recv_len == len
|
||||
&& memcmp(g_recv_buf, msg, len) == 0)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("recv_count=%d recv_len=%d expected_len=%d ",
|
||||
g_recv_count, g_recv_len, len);
|
||||
FAIL("UDP data mismatch or not received");
|
||||
}
|
||||
|
||||
comm_destroy(g_udp2_id);
|
||||
comm_destroy(g_udp1_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 5: 状态回调
|
||||
* ================================================================ */
|
||||
static void test_05_state_callbacks(void)
|
||||
{
|
||||
TEST("state change callbacks (connected)");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.tcp.local_ip, "127.0.0.1");
|
||||
para.tcp.local_port = 23001;
|
||||
|
||||
int id = comm_create(COMM_TYPE_TCP_SERVER, 0, ¶);
|
||||
|
||||
if (id < 0)
|
||||
{
|
||||
FAIL("create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
comm_state_register(id, on_svr_state);
|
||||
|
||||
int ret = comm_connect(id);
|
||||
|
||||
if (ret != COMM_OK)
|
||||
{
|
||||
FAIL("connect failed");
|
||||
comm_destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
msleep(50);
|
||||
|
||||
if (g_svr_state_changes > 0)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("no state callback received");
|
||||
}
|
||||
|
||||
comm_destroy(id);
|
||||
}
|
||||
|
||||
TEST("state change callbacks (disconnect)");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.udp.local_ip, "127.0.0.1");
|
||||
para.udp.local_port = 23002;
|
||||
|
||||
int id = comm_create(COMM_TYPE_UDP_SERVER, 0, ¶);
|
||||
|
||||
if (id < 0)
|
||||
{
|
||||
FAIL("create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
comm_state_register(id, on_svr_state);
|
||||
comm_connect(id);
|
||||
|
||||
msleep(50);
|
||||
|
||||
comm_disconnect(id);
|
||||
|
||||
msleep(50);
|
||||
|
||||
/* UDP 不触发 DISCONNECT(非面向连接) */
|
||||
/* 故测试 TCP */
|
||||
if (g_svr_state_changes > 0)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* UDP connect也会触发 CONNECTED 状态 */
|
||||
FAIL("no state callback");
|
||||
}
|
||||
|
||||
comm_destroy(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 6: 未连接发送
|
||||
* ================================================================ */
|
||||
static void test_06_send_without_connect(void)
|
||||
{
|
||||
TEST("send without connect should fail");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.tcp.remote_ip, "127.0.0.1");
|
||||
para.tcp.remote_port = 24001;
|
||||
|
||||
int id = comm_create(COMM_TYPE_TCP_CLIENT, 0, ¶);
|
||||
|
||||
if (id < 0)
|
||||
{
|
||||
/* 创建应该是 OK 的,不需要连接 */
|
||||
FAIL("create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *msg = "test";
|
||||
int ret = comm_send(id, -1, (const unsigned char *)msg,
|
||||
(int)strlen(msg));
|
||||
|
||||
/* 未连接的情况下,fd 无效,send 应该失败 */
|
||||
if (ret < 0)
|
||||
{
|
||||
OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("send should have failed without connect");
|
||||
}
|
||||
|
||||
comm_destroy(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* 测试 7: 断开重连
|
||||
* ================================================================ */
|
||||
static void test_07_disconnect_reconnect(void)
|
||||
{
|
||||
TEST("disconnect + reconnect cycle");
|
||||
{
|
||||
reset_test_state();
|
||||
|
||||
union_comm_para para;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
strcpy(para.udp.local_ip, "127.0.0.1");
|
||||
para.udp.local_port = 25001;
|
||||
|
||||
int id = comm_create(COMM_TYPE_UDP_SERVER, 0, ¶);
|
||||
|
||||
if (id < 0)
|
||||
{
|
||||
FAIL("create failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 第一次连接 */
|
||||
if (comm_connect(id) != COMM_OK)
|
||||
{
|
||||
FAIL("first connect failed");
|
||||
comm_destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 断开 */
|
||||
if (comm_disconnect(id) != COMM_OK)
|
||||
{
|
||||
FAIL("disconnect failed");
|
||||
comm_destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 第二次连接 */
|
||||
if (comm_connect(id) != COMM_OK)
|
||||
{
|
||||
FAIL("second connect failed");
|
||||
comm_destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
OK();
|
||||
|
||||
comm_destroy(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* main
|
||||
* ================================================================ */
|
||||
int main(void)
|
||||
{
|
||||
printf("\n=== libcomm 单元测试 ===\n\n");
|
||||
|
||||
/* 启动事件循环(comm_run 自初始化 epoll,无需预创建实例) */
|
||||
printf("[启动 epoll 事件循环]\n");
|
||||
start_event_loop();
|
||||
msleep(50);
|
||||
|
||||
/* 1. 创建与销毁 */
|
||||
printf("\n[1] 创建与销毁 (4 项)\n");
|
||||
test_01_create_destroy();
|
||||
|
||||
/* 2. 参数校验 */
|
||||
printf("\n[2] 参数校验 (7 项)\n");
|
||||
test_02_param_validation();
|
||||
|
||||
/* 3. TCP 回环 */
|
||||
printf("\n[3] TCP 回环\n");
|
||||
test_03_tcp_loopback();
|
||||
|
||||
/* 4. UDP 回环 */
|
||||
printf("\n[4] UDP 回环\n");
|
||||
test_04_udp_loopback();
|
||||
|
||||
/* 5. 状态回调 */
|
||||
printf("\n[5] 状态回调 (2 项)\n");
|
||||
test_05_state_callbacks();
|
||||
|
||||
/* 6. 未连接发送 */
|
||||
printf("\n[6] 错误路径\n");
|
||||
test_06_send_without_connect();
|
||||
|
||||
/* 7. 断开重连 */
|
||||
printf("\n[7] 断开重连\n");
|
||||
test_07_disconnect_reconnect();
|
||||
|
||||
/* 停止事件循环 */
|
||||
printf("\n[停止 epoll 事件循环]\n");
|
||||
stop_event_loop();
|
||||
|
||||
/* 结果汇总 */
|
||||
printf("\n========================================\n");
|
||||
printf(" 测试结果: %d pass, %d fail\n", g_pass, g_fail);
|
||||
printf("========================================\n");
|
||||
|
||||
return (g_fail > 0) ? 1 : 0;
|
||||
}
|
||||
Loading…
Reference in New Issue