Files
DataRouter/tests/test_datarouter.c
T

390 lines
14 KiB
C

/**
* @file test_datarouter.c
* @brief 数据路由库单元测试
*
* 覆盖:
* - 端口管理
* - send_type / recv_type 独立设置
* - 多 handler 增删
* - 发送调用(一对多广播)
* - 接收回调
* - 发送/接收能力元数据各自独立
* - 错误处理
*/
#include "datarouter.h"
#include <stdio.h>
#include <string.h>
/* ================================================================
* 测试框架
* ================================================================ */
static int _total_run, _total_pass, _total_fail;
static int _err;
static const char *_cur_name;
#define FIXTURE_MAX 16
typedef struct {
datarouter_port_t ports[FIXTURE_MAX];
int count;
} fixture_t;
#define FIXTURE_INIT(f) memset((f), 0, sizeof(*(f)))
#define FIXTURE_PUSH(f, p) do { if ((f)->count < FIXTURE_MAX) (f)->ports[(f)->count++] = (p); } while (0)
#define FIXTURE_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) datarouter_port_delete((f)->ports[_i]); } while (0)
#define FIXTURE_CREATE(f) ({ datarouter_port_t _p = datarouter_port_create(); FIXTURE_PUSH(f, _p); _p; })
#define TEST_START(name) \
static void test_##name(void) \
{ \
fixture_t _fix; \
FIXTURE_INIT(&_fix); \
_cur_name = #name; \
_err = 0;
#define TEST_END() \
cleanup: \
FIXTURE_CLEAN(&_fix); \
if (_err) { _total_fail++; printf(" FAIL %s\n", _cur_name); } \
else { _total_pass++; printf(" PASS %s\n", _cur_name); } \
_total_run++; \
}
#define CHECK(cond, ...) do { \
if (!(cond)) { \
printf(" %s [line %d]: ", _cur_name, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
_err = 1; \
goto cleanup; \
} \
} while (0)
/* ================================================================
* 测试用 handler
* ================================================================ */
static int _h_cnt;
static void _h(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
static void _h_a(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
static void _h_b(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
static void _h_c(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
static void _h_d(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
static void reset_h(void) { _h_cnt = 0; }
/* ================================================================
* 1. 未初始化
* ================================================================ */
TEST_START(error_uninit)
CHECK(datarouter_send_sensor(0, "d", 1) == -1, "expected -1");
TEST_END()
/* ================================================================
* 2. 端口管理
* ================================================================ */
TEST_START(port_create_basic)
CHECK(FIXTURE_CREATE(&_fix) >= 0, "create failed");
TEST_END()
TEST_START(port_create_max)
int c = 0;
for (int i = 0; i < 64; i++) {
datarouter_port_t p = datarouter_port_create();
if (p == DATAROUTER_INVALID_PORT) break;
FIXTURE_PUSH(&_fix, p); c++;
}
CHECK(c >= 64, "got %d", c);
CHECK(datarouter_port_create() == DATAROUTER_INVALID_PORT, NULL);
TEST_END()
TEST_START(port_delete_invalid)
datarouter_port_delete(-1); datarouter_port_delete(999);
TEST_END()
TEST_START(port_default_state)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
CHECK(datarouter_port_get_send_type(p) == -1, "send_type should be -1");
CHECK(datarouter_port_get_recv_type(p) == -1, "recv_type should be -1");
CHECK(datarouter_port_handler_count(p) == 0, "handler count 0");
TEST_END()
/* ================================================================
* 3. send_type / recv_type 独立设置
* ================================================================ */
TEST_START(send_type_set_get)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
TEST_END()
TEST_START(recv_type_set_get)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_rtcm, NULL);
TEST_END()
TEST_START(types_independent)
/* 一个端口同时设置 send_type 和 recv_type,互不干扰 */
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_set_recv_type(p, DATAROUTER_RECV_command);
CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_command, NULL);
TEST_END()
TEST_START(send_type_clear)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_set_send_type(p, -1);
CHECK(datarouter_port_get_send_type(p) == -1, NULL);
TEST_END()
TEST_START(recv_type_clear)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
datarouter_port_set_recv_type(p, -1);
CHECK(datarouter_port_get_recv_type(p) == -1, NULL);
TEST_END()
TEST_START(types_from_invalid)
CHECK(datarouter_port_get_send_type(-1) == -1, NULL);
CHECK(datarouter_port_get_recv_type(-1) == -1, NULL);
CHECK(datarouter_port_get_send_type(999) == -1, NULL);
CHECK(datarouter_port_get_recv_type(999) == -1, NULL);
TEST_END()
/* ================================================================
* 4. 多 handler
* ================================================================ */
TEST_START(handler_add_remove)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
CHECK(datarouter_port_add_handler(p, _h_a) == 0, NULL);
CHECK(datarouter_port_add_handler(p, _h_b) == 0, NULL);
CHECK(datarouter_port_handler_count(p) == 2, NULL);
CHECK(datarouter_port_remove_handler(p, _h_a) == 0, NULL);
CHECK(datarouter_port_handler_count(p) == 1, NULL);
TEST_END()
TEST_START(handler_clear)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_add_handler(p, _h);
datarouter_port_clear_handlers(p);
CHECK(datarouter_port_handler_count(p) == 0, NULL);
TEST_END()
/* ================================================================
* 5. 发送触发
* ================================================================ */
TEST_START(send_one_handler)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
reset_h();
CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
CHECK(_h_cnt == 1, "handler called %d times", _h_cnt);
TEST_END()
TEST_START(send_multi_handlers)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h_a);
datarouter_port_add_handler(p, _h_b);
datarouter_port_add_handler(p, _h_c);
reset_h();
CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
CHECK(_h_cnt == 3, "handler called %d times", _h_cnt);
TEST_END()
TEST_START(send_type_mismatch)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
reset_h();
CHECK(datarouter_send_status(p, "d", 1) == -3, "expected -3");
CHECK(_h_cnt == 0, NULL);
TEST_END()
TEST_START(send_no_handler)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
TEST_END()
TEST_START(send_no_send_type)
/* 端口只有 recv_type,没有 send_type */
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
CHECK(datarouter_send_sensor(p, "d", 1) == -3, "expected -3 (send_type unset)");
TEST_END()
TEST_START(send_remove_handler)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h_a);
datarouter_port_add_handler(p, _h_b);
reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 2, NULL);
datarouter_port_remove_handler(p, _h_a);
reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 1, NULL);
TEST_END()
TEST_START(send_clear_handlers)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
datarouter_port_clear_handlers(p);
CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
TEST_END()
TEST_START(send_zero_length)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
reset_h();
CHECK(datarouter_send_sensor(p, "x", 0) == 0, NULL);
CHECK(_h_cnt == 1, NULL);
TEST_END()
TEST_START(send_null_data)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
reset_h();
CHECK(datarouter_send_sensor(p, NULL, 0) == 0, NULL);
CHECK(_h_cnt == 1, NULL);
TEST_END()
/* ================================================================
* 6. 接收回调
* ================================================================ */
static int _rx_r, _rx_c;
void datarouter_on_recv_rtcm(uint32_t p, const void *d, size_t l)
{ (void)p; (void)d; (void)l; _rx_r++; }
void datarouter_on_recv_command(uint32_t p, const void *d, size_t l)
{ (void)p; (void)d; (void)l; _rx_c++; }
TEST_START(recv_callbacks)
_rx_r = _rx_c = 0;
datarouter_on_recv_rtcm(0, "d", 1);
CHECK(_rx_r == 1 && _rx_c == 0, "rtcm=%d cmd=%d", _rx_r, _rx_c);
datarouter_on_recv_command(1, "d", 1);
CHECK(_rx_r == 1 && _rx_c == 1, "rtcm=%d cmd=%d", _rx_r, _rx_c);
TEST_END()
/* ================================================================
* 7. 能力元数据(两组独立)
* ================================================================ */
TEST_START(send_cap_meta)
CHECK(datarouter_send_cap_count() == 2, NULL);
CHECK(strcmp(datarouter_send_cap_name(0), "sensor") == 0, NULL);
CHECK(strcmp(datarouter_send_cap_desc(0), "Sensor data report") == 0, NULL);
CHECK(strcmp(datarouter_send_cap_name(1), "status") == 0, NULL);
CHECK(strcmp(datarouter_send_cap_desc(1), "Device status report") == 0, NULL);
CHECK(datarouter_send_cap_name(-1) == NULL, NULL);
CHECK(datarouter_send_cap_name(99) == NULL, NULL);
TEST_END()
TEST_START(recv_cap_meta)
CHECK(datarouter_recv_cap_count() == 2, NULL);
CHECK(strcmp(datarouter_recv_cap_name(0), "rtcm") == 0, NULL);
CHECK(strcmp(datarouter_recv_cap_desc(0), "RTCM correction data") == 0, NULL);
CHECK(strcmp(datarouter_recv_cap_name(1), "command") == 0, NULL);
CHECK(strcmp(datarouter_recv_cap_desc(1), "Remote control command") == 0, NULL);
CHECK(datarouter_recv_cap_name(-1) == NULL, NULL);
CHECK(datarouter_recv_cap_desc(99) == NULL, NULL);
TEST_END()
/* ================================================================
* 8. 错误
* ================================================================ */
TEST_START(error_invalid_port)
CHECK(datarouter_send_sensor(999, "d", 1) == -2, NULL);
CHECK(datarouter_send_sensor(-1, "d", 1) == -2, NULL);
TEST_END()
TEST_START(error_deleted_port)
datarouter_port_t p = FIXTURE_CREATE(&_fix);
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
datarouter_port_add_handler(p, _h);
datarouter_port_delete(p);
CHECK(datarouter_send_sensor(p, "d", 1) == -2, NULL);
_fix.count--;
TEST_END()
/* ================================================================
* 主函数
* ================================================================ */
#define RUN(name) do { reset_h(); test_##name(); } while (0)
int main(void)
{
printf("==== DataRouter Unit Tests ====\n\n");
printf("[uninitialized]\n");
RUN(error_uninit);
datarouter_init();
printf("\n[port management]\n");
RUN(port_create_basic);
RUN(port_create_max);
RUN(port_delete_invalid);
RUN(port_default_state);
printf("\n");
datarouter_reset(); datarouter_init();
printf("[send_type / recv_type]\n");
RUN(send_type_set_get);
RUN(recv_type_set_get);
RUN(types_independent);
RUN(send_type_clear);
RUN(recv_type_clear);
RUN(types_from_invalid);
printf("\n");
printf("[handler add/remove]\n");
RUN(handler_add_remove);
RUN(handler_clear);
printf("\n");
printf("[send trigger]\n");
RUN(send_one_handler);
RUN(send_multi_handlers);
RUN(send_type_mismatch);
RUN(send_no_handler);
RUN(send_no_send_type);
RUN(send_remove_handler);
RUN(send_clear_handlers);
RUN(send_zero_length);
RUN(send_null_data);
printf("\n");
printf("[receive callback]\n");
RUN(recv_callbacks);
printf("\n");
printf("[capability metadata]\n");
RUN(send_cap_meta);
RUN(recv_cap_meta);
printf("\n");
printf("[error handling]\n");
RUN(error_invalid_port);
RUN(error_deleted_port);
printf("\n");
printf("==============================\n");
printf(" total: %d | pass: %d | fail: %d\n\n",
_total_run, _total_pass, _total_fail);
return _total_fail > 0 ? 1 : 0;
}