348 lines
11 KiB
C
348 lines
11 KiB
C
/**
|
|
* @file test_datarouter.c
|
|
*/
|
|
|
|
#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 {
|
|
dr_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++) dr_port_delete((f)->ports[_i]); } while (0)
|
|
#define FIXTURE_CREATE(f) ({ dr_port_t _p = dr_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 reset_h(void) { _h_cnt = 0; }
|
|
|
|
static int _rx_rtcm;
|
|
static int _rx_cmd;
|
|
void dr_on_recv_rtcm(uint32_t p, const void *d, size_t l)
|
|
{ (void)p; (void)d; (void)l; _rx_rtcm++; }
|
|
void dr_on_recv_command(uint32_t p, const void *d, size_t l)
|
|
{ (void)p; (void)d; (void)l; _rx_cmd++; }
|
|
static void reset_rx(void) { _rx_rtcm = _rx_cmd = 0; }
|
|
|
|
/* ================================================================
|
|
* 1. 未初始化
|
|
* ================================================================ */
|
|
|
|
TEST_START(error_uninit)
|
|
CHECK(dr_send_sensor("d", 1) == -1, "expected -1");
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 2. 端口管理
|
|
* ================================================================ */
|
|
|
|
TEST_START(port_create_basic)
|
|
CHECK(FIXTURE_CREATE(&_fix) >= 0, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(port_create_max)
|
|
int c = 0;
|
|
for (int i = 0; i < 64; i++) {
|
|
dr_port_t p = dr_port_create();
|
|
if (p == DR_INVALID_PORT) break;
|
|
FIXTURE_PUSH(&_fix, p); c++;
|
|
}
|
|
CHECK(c >= 64, "got %d", c);
|
|
CHECK(dr_port_create() == DR_INVALID_PORT, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(port_delete_invalid)
|
|
dr_port_delete(-1); dr_port_delete(999);
|
|
TEST_END()
|
|
|
|
TEST_START(port_default_state)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
CHECK(dr_port_get_send_type(p) == -1, NULL);
|
|
CHECK(dr_port_get_recv_type(p) == -1, NULL);
|
|
CHECK(dr_port_handler_count(p) == 0, NULL);
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 3. send_type / recv_type 与 handler
|
|
* ================================================================ */
|
|
|
|
TEST_START(send_type_set_clear)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
CHECK(dr_port_get_send_type(p) == DR_SEND_sensor, NULL);
|
|
dr_port_set_send_type(p, -1);
|
|
CHECK(dr_port_get_send_type(p) == -1, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(recv_type_set_clear)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_recv_type(p, DR_RECV_rtcm);
|
|
CHECK(dr_port_get_recv_type(p) == DR_RECV_rtcm, NULL);
|
|
dr_port_set_recv_type(p, -1);
|
|
CHECK(dr_port_get_recv_type(p) == -1, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(types_independent)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
dr_port_set_recv_type(p, DR_RECV_command);
|
|
CHECK(dr_port_get_send_type(p) == DR_SEND_sensor, NULL);
|
|
CHECK(dr_port_get_recv_type(p) == DR_RECV_command, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(handler_add_remove)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
CHECK(dr_port_add_handler(p, _h) == 0, NULL);
|
|
CHECK(dr_port_handler_count(p) == 1, NULL);
|
|
CHECK(dr_port_remove_handler(p, _h) == 0, NULL);
|
|
CHECK(dr_port_handler_count(p) == 0, NULL);
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 4. 发送 — 自动广播
|
|
* ================================================================ */
|
|
|
|
TEST_START(send_no_match_port)
|
|
CHECK(dr_send_sensor("d", 1) == -2, "expected -2");
|
|
TEST_END()
|
|
|
|
TEST_START(send_one_port_one_handler)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
dr_port_add_handler(p, _h);
|
|
reset_h();
|
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
|
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
|
TEST_END()
|
|
|
|
TEST_START(send_multi_ports)
|
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
|
dr_port_set_send_type(p2, DR_SEND_sensor);
|
|
dr_port_add_handler(p1, _h);
|
|
dr_port_add_handler(p2, _h);
|
|
reset_h();
|
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
|
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
|
TEST_END()
|
|
|
|
TEST_START(send_type_filter)
|
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
|
dr_port_set_send_type(p2, DR_SEND_status);
|
|
dr_port_add_handler(p1, _h);
|
|
dr_port_add_handler(p2, _h);
|
|
reset_h();
|
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
|
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
|
TEST_END()
|
|
|
|
TEST_START(send_after_delete)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
dr_port_add_handler(p, _h);
|
|
dr_port_delete(p);
|
|
CHECK(dr_send_sensor("d", 1) == -2, "expected -2");
|
|
_fix.count--;
|
|
TEST_END()
|
|
|
|
TEST_START(send_zero_length)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
dr_port_add_handler(p, _h);
|
|
reset_h();
|
|
CHECK(dr_send_sensor("x", 0) == 0, NULL);
|
|
CHECK(_h_cnt == 1, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(send_null_data)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
|
dr_port_add_handler(p, _h);
|
|
reset_h();
|
|
CHECK(dr_send_sensor(NULL, 0) == 0, NULL);
|
|
CHECK(_h_cnt == 1, NULL);
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 5. 接收回调 + dispatch
|
|
* ================================================================ */
|
|
|
|
TEST_START(recv_callback_direct)
|
|
/* 直接调用回调(旧方式) */
|
|
reset_rx();
|
|
dr_on_recv_rtcm(0, "d", 1);
|
|
CHECK(_rx_rtcm == 1, "rtcm=%d", _rx_rtcm);
|
|
dr_on_recv_command(1, "d", 1);
|
|
CHECK(_rx_cmd == 1, "cmd=%d", _rx_cmd);
|
|
TEST_END()
|
|
|
|
TEST_START(dispatch_valid)
|
|
/* dr_port_dispatch 自动路由到对应回调 */
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_recv_type(p, DR_RECV_rtcm);
|
|
|
|
reset_rx();
|
|
dr_port_dispatch(p, "data", 4);
|
|
CHECK(_rx_rtcm == 1, "rtcm should fire: %d", _rx_rtcm);
|
|
CHECK(_rx_cmd == 0, "cmd should not fire: %d", _rx_cmd);
|
|
TEST_END()
|
|
|
|
TEST_START(dispatch_command)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_recv_type(p, DR_RECV_command);
|
|
|
|
reset_rx();
|
|
dr_port_dispatch(p, "data", 4);
|
|
CHECK(_rx_cmd == 1, "cmd should fire: %d", _rx_cmd);
|
|
CHECK(_rx_rtcm == 0, "rtcm should not fire: %d", _rx_rtcm);
|
|
TEST_END()
|
|
|
|
TEST_START(dispatch_unset)
|
|
/* recv_type 为 -1 时 dispatch 不应调用任何回调 */
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
reset_rx();
|
|
dr_port_dispatch(p, "data", 4);
|
|
CHECK(_rx_rtcm == 0, NULL);
|
|
CHECK(_rx_cmd == 0, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(dispatch_invalid_port)
|
|
reset_rx();
|
|
dr_port_dispatch(999, "data", 4);
|
|
dr_port_dispatch(-1, "data", 4);
|
|
CHECK(_rx_rtcm == 0, NULL);
|
|
CHECK(_rx_cmd == 0, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(dispatch_deleted_port)
|
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
|
dr_port_set_recv_type(p, DR_RECV_rtcm);
|
|
dr_port_delete(p);
|
|
reset_rx();
|
|
dr_port_dispatch(p, "data", 4);
|
|
CHECK(_rx_rtcm == 0, "deleted should not fire");
|
|
_fix.count--;
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 6. 能力元数据
|
|
* ================================================================ */
|
|
|
|
TEST_START(send_cap_meta)
|
|
CHECK(dr_send_cap_count() == 2, NULL);
|
|
CHECK(strcmp(dr_send_cap_name(0), "sensor") == 0, NULL);
|
|
CHECK(dr_send_cap_name(-1) == NULL, NULL);
|
|
TEST_END()
|
|
|
|
TEST_START(recv_cap_meta)
|
|
CHECK(dr_recv_cap_count() == 2, NULL);
|
|
CHECK(strcmp(dr_recv_cap_name(0), "rtcm") == 0, NULL);
|
|
CHECK(dr_recv_cap_name(-1) == NULL, NULL);
|
|
TEST_END()
|
|
|
|
/* ================================================================
|
|
* 主函数
|
|
* ================================================================ */
|
|
|
|
#define RUN(name) do { reset_h(); reset_rx(); test_##name(); } while (0)
|
|
|
|
int main(void)
|
|
{
|
|
printf("==== DataRouter Unit Tests ====\n\n");
|
|
|
|
printf("[uninitialized]\n");
|
|
RUN(error_uninit);
|
|
|
|
dr_init();
|
|
|
|
printf("\n[port management]\n");
|
|
RUN(port_create_basic);
|
|
RUN(port_create_max);
|
|
RUN(port_delete_invalid);
|
|
RUN(port_default_state);
|
|
printf("\n");
|
|
|
|
dr_reset(); dr_init();
|
|
printf("[send_type / recv_type / handler]\n");
|
|
RUN(send_type_set_clear);
|
|
RUN(recv_type_set_clear);
|
|
RUN(types_independent);
|
|
RUN(handler_add_remove);
|
|
printf("\n");
|
|
|
|
printf("[send — auto broadcast]\n");
|
|
RUN(send_no_match_port);
|
|
RUN(send_one_port_one_handler);
|
|
RUN(send_multi_ports);
|
|
RUN(send_type_filter);
|
|
RUN(send_after_delete);
|
|
RUN(send_zero_length);
|
|
RUN(send_null_data);
|
|
printf("\n");
|
|
|
|
printf("[receive — dispatch]\n");
|
|
RUN(recv_callback_direct);
|
|
RUN(dispatch_valid);
|
|
RUN(dispatch_command);
|
|
RUN(dispatch_unset);
|
|
RUN(dispatch_invalid_port);
|
|
RUN(dispatch_deleted_port);
|
|
printf("\n");
|
|
|
|
printf("[capability metadata]\n");
|
|
RUN(send_cap_meta);
|
|
RUN(recv_cap_meta);
|
|
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;
|
|
}
|