* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
* K-NET is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <stdint.h>
#include "knet_atomic.h"
#include "knet_pkt.h"
#include "knet_sal_func.h"
#include "knet_rand.h"
#include "knet_transmission.h"
#include "knet_fmm.h"
#include "dp_mem_api.h"
#include "dp_mp_api.h"
#include "dp_rand_api.h"
#include "dp_show_api.h"
#include "dp_pbuf_api.h"
#include "dp_worker_api.h"
#include "dp_fib4tbl_api.h"
#include "dp_netdev_api.h"
#include "dp_addr_ext_api.h"
#include "dp_hashtbl_api.h"
#include "dp_debug_api.h"
#include "dp_clock_api.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
#include <signal.h>
#include <pthread.h>
#include "securec.h"
#include "knet_lock.h"
#include "knet_tcp_symbols.h"
#include "knet_hash_table.h"
#include "knet_sal_func.h"
#include "knet_sal_tcp.h"
#include "knet_dpdk_init.h"
#include "knet_sal_inner.h"
#include "common.h"
#include "mock.h"
#include "rte_hash.h"
#include "knet_mock.h"
#include "knet_tun.h"
#include "knet_sal_mp.h"
#include "knet_sal_func.h"
#include <dlfcn.h>
#define VALID_IP inet_addr("192.168.0.1")
#define VALID_PORT 8080
#define INVALID_TYPE 999
#define INVALID_PROTO (-1)
static union KNET_CfgValue g_cfg = {.intValue = 1};
static union KNET_CfgValue *MockKnetGetCfg(enum KNET_ConfKey key)
{
(void)memset_s(&g_cfg, sizeof(g_cfg), 0, sizeof(g_cfg));
g_cfg.intValue = 1;
return &g_cfg;
}
extern "C" {
extern int KnetConfigureStackNetdev(DP_Netdev_t *netdev, const char *ifname);
extern int KnetInitDpNetdev(void);
extern int KNET_ACC_HashTblDestroy(DP_HashTbl_t hTableId);
extern int KNET_ACC_HashTblInsertEntry(DP_HashTbl_t hTableId, const uint8_t *pu8Key, const void *pData);
extern int KNET_ACC_HashTblModifyEntry(DP_HashTbl_t hTableId, const uint8_t *pu8Key, const void *pData);
extern int KNET_ACC_HashTblDelEntry(DP_HashTbl_t hTableId, const uint8_t *pu8Key);
extern int KNET_ACC_HashTblLookupEntry(DP_HashTbl_t hTableId, const uint8_t *pu8Key, void *pData);
extern int KNET_ACC_HashTblEntryGetFirst(DP_HashTbl_t hTableId, uint8_t *pu8Key, void *pData);
extern int KNET_ACC_HashTblEntryGetNext(DP_HashTbl_t hTableId, uint8_t *pu8Key, void *pData, uint8_t *pu8NextKey);
extern uint32_t KNET_ACC_Rand(void);
extern uint32_t KNET_TimeHook(DP_ClockId_E clockId, int64_t *seconds, int64_t *nanoseconds);
extern int KNET_ACC_EventNotify(DP_AddrEventType_t type, const DP_AddrEvent_t *addrEvent);
extern int KNET_ACC_PreBind(void* userData, const struct DP_Sockaddr* addr, DP_Socklen_t addrlen);
extern int KNET_ACC_HashTblCreate(DP_HashTblCfg_t *pstHashTblCfg, DP_HashTbl_t *phTableId);
extern uint32_t SemWaitNonblock(DP_Sem_t sem);
extern uint32_t KNET_SemWaitHook(DP_Sem_t sem, int timeout);
extern uint32_t KNET_SemPostHook(DP_Sem_t sem);
extern int KNET_ACC_HashTblGetInfo(DP_HashTbl_t hTableId, DP_HashTblSummaryInfo_t *pstHashSummaryInfo);
extern int CheckFlowCfgValid(uint32_t dstIp, uint16_t dstPort, int32_t proto);
extern int KNET_ACC_DelayInputEnque(void* pbuf, int cpdRingId);
extern int KnetSetInterFace(void);
extern int KnetSetDpRtCfg(void);
extern KNET_ACC_DelayInputDeque(void** pbuf, unsigned int burstSize, int cpdRingId);
int32_t MpHandleCtrlCreate(const DP_Mempool handler, const uint32_t type);
void MpHandleCtrlDestroy(const DP_Mempool handler);
extern int g_needFlowRule;
}
static int KNET_PktPoolCreateMock(const KNET_PktPoolCfg *cfg, uint32_t *poolId)
{
if (poolId != NULL) {
*poolId = 1;
}
return 0;
}
struct rte_mbuf mbuf_mock;
static struct rte_mbuf *KNET_PktAllocMock(uint32_t poolId)
{
mbuf_mock.buf_addr = NULL;
mbuf_mock.buf_len = 0;
mbuf_mock.refcnt = 1;
return &mbuf_mock;
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_REG_MEM_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(DP_MemHookReg, TEST_GetFuncRetPositive(0));
ret = KnetRegMem();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_MemHookReg);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_REG_MBUF_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(DP_MempoolHookReg, TEST_GetFuncRetPositive(0));
ret = KnetRegMbufMemPool();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_MempoolHookReg);
DeleteMock(Mock);
}
KNET_STATIC int32_t MpHandleCtrlCreate(const DP_Mempool handler, const uint32_t type);
KNET_STATIC void MpHandleCtrlDestroy(const DP_Mempool handler);
DTEST_CASE_F(SAL_FUN, TEST_SAL_ACC_CREATE_NORMAL, NULL, NULL)
{
int32_t ret = 0;
int bufsize = 32;
DP_MempoolCfg_S cfg = {0};
cfg.type = DP_MEMPOOL_TYPE_PBUF;
cfg.name = "cfg";
DP_Mempool handler = {0};
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(strncpy_s, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_PktPoolCreate, TEST_GetFuncRetPositive(1));
Mock->Create(rte_mempool_lookup, mock_rte_mempool_lookup);
ret = KNET_ACC_CreateMbufMemPool(&cfg, NULL, NULL);
DT_ASSERT_EQUAL(ret, -1);
Mock->Create(KNET_PktPoolCreate, KNET_PktPoolCreateMock);
ret = KNET_ACC_CreateMbufMemPool(&cfg, NULL, &handler);
DT_ASSERT_EQUAL(ret, 0);
Mock->Create(KNET_FmmCreatePool, TEST_GetFuncRetPositive(1));
cfg.type = DP_MEMPOOL_TYPE_FIXED_MEM;
ret = KNET_ACC_CreateMbufMemPool(&cfg, NULL, &handler);
DT_ASSERT_EQUAL(ret, -1);
Mock->Delete(KNET_FmmCreatePool);
cfg.type = DP_MEMPOOL_TYPE_EBUF;
cfg.size = bufsize;
cfg.count = 1;
Mock->Create(KNET_FmmCreatePool, TEST_GetFuncRetPositive(0));
Mock->Create(MpHandleCtrlCreate, TEST_GetFuncRetPositive(0));
ret = KNET_ACC_CreateMbufMemPool(&cfg, NULL, &handler);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(MpHandleCtrlCreate);
Mock->Delete(KNET_PktPoolCreate);
Mock->Delete(strncpy_s);
Mock->Delete(rte_mempool_lookup);
Mock->Delete(KNET_FmmCreatePool);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_ACC_DESTROY_MBUF_MEMPOOL_NORMAL, NULL, NULL)
{
uint32_t type = DP_MEMPOOL_TYPE_PBUF;
DP_Mempool mp = {0};
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_PktPoolDestroy, TEST_GetFuncRetPositive(0));
KNET_ACC_DestroyMbufMemPool(mp);
DT_ASSERT_EQUAL(mp, NULL);
Mock->Delete(KNET_PktPoolDestroy);
DeleteMock(Mock);
}
uint32_t KNET_FmmAllocMock(uint32_t poolId, void **obj)
{
static char buf[1024] = {0};
*obj = buf;
return KNET_OK;
}
* @brief KNET_ACC_MbufMemPoolAlloc 函数,内存池分配正常测试
* 测试步骤:
* 1.入参mp为0,预期结果为空
* 2.入参mp为128,大于KNET_MEM_POOL_ID_OFFSET,
打桩KNET_FmmAlloc提供足够地址操作空间,预期结果非空
*/
DTEST_CASE_F(SAL_FUN, TEST_ACC_MBUF_MEMPOOL_ALLOC_NORMAL, NULL, NULL)
{
uint32_t type = DP_MEMPOOL_TYPE_PBUF;
DP_Mempool mp = {0};
DT_ASSERT_EQUAL(MpHandleCtrlCreate(mp, type), KNET_OK);
void *retPtr = NULL;
int poolIdGT32 = 128;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_PktAlloc, TEST_GetFuncRetPositive(0));
retPtr = KNET_ACC_MbufMemPoolAlloc(mp);
DT_ASSERT_EQUAL(retPtr, NULL);
Mock->Delete(KNET_PktAlloc);
Mock->Create(KNET_PktAlloc, KNET_PktAllocMock);
retPtr = KNET_ACC_MbufMemPoolAlloc(mp);
DT_ASSERT_NOT_EQUAL(retPtr, NULL);
MpHandleCtrlDestroy(mp);
mp = (void *)poolIdGT32;
DT_ASSERT_EQUAL(MpHandleCtrlCreate(mp, type), KNET_OK);
Mock->Create(KNET_FmmAlloc, KNET_FmmAllocMock);
retPtr = KNET_ACC_MbufMemPoolAlloc(mp);
DT_ASSERT_NOT_EQUAL(retPtr, NULL);
MpHandleCtrlDestroy(mp);
Mock->Delete(KNET_FmmAlloc);
Mock->Delete(KNET_PktAlloc);
DeleteMock(Mock);
}
void KNET_PktFreeMock(struct rte_mbuf *mbuf)
{
DP_Pbuf_t *pbuf = KNET_Mbuf2Pkt(mbuf);
pbuf->offset = 0;
}
DTEST_CASE_F(SAL_FUN, TEST_ACC_MBUF_MEMPOOL_FREE_NORMAL, NULL, NULL)
{
uint32_t type = DP_MEMPOOL_TYPE_PBUF;
DP_Mempool mp = {0};
DT_ASSERT_EQUAL(MpHandleCtrlCreate(mp, type), KNET_OK);
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
uint32_t mbuf_len = sizeof(struct rte_mbuf) + KNET_PKT_DBG_SIZE + sizeof(DP_Pbuf_t);
struct rte_mbuf *mbuf = malloc(mbuf_len);
memset(mbuf, 0, mbuf_len);
DP_Pbuf_t *pbuf = KNET_Mbuf2Pkt(mbuf);
pbuf->ref = 1;
pbuf->offset = 1;
Mock->Create(KNET_PktFree, KNET_PktFreeMock);
KNET_ACC_MbufMemPoolFree(0, pbuf);
DT_ASSERT_EQUAL(pbuf->offset, 0);
MpHandleCtrlDestroy(mp);
Mock->Delete(KNET_PktFree);
free(mbuf);
DeleteMock(Mock);
}
typedef struct {
void* handle;
int ref_count;
} Handle;
static Handle g_handles[10] = {0};
static int g_handle_index = 0;
void* dlopen_mock(const char* filename, int flag) {
if (g_handle_index >= 10) {
return NULL;
}
Handle* handle = &g_handles[g_handle_index];
handle->handle = (void*)(uintptr_t)(0x1000 + g_handle_index);
handle->ref_count = 1;
g_handle_index++;
return handle->handle;
}
void* dlsym_mock(void* handle, const char* symbol) {
return 0xdeadbeaf;
}
int dlclose_mock(void* handle) {
for (int i = 0; i < g_handle_index; i++) {
if (g_handles[i].handle == handle) {
g_handles[i].ref_count--;
if (g_handles[i].ref_count <= 0) {
g_handles[i].handle = NULL;
}
return 0;
}
}
return -1;
}
DTEST_CASE_F(SAL_FUN, TEST_SYMBOLS_INIT_DEINIT, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(dlopen, dlopen_mock);
Mock->Create(dlsym, dlsym_mock);
Mock->Create(dlclose, dlclose_mock);
int ret = KnetInitDpSymbols();
DT_ASSERT_EQUAL(ret, 0);
KnetDeinitDpSymbols();
Mock->Delete(dlclose);
Mock->Delete(dlsym);
Mock->Delete(dlopen);
DeleteMock(Mock);
KnetInitDpSymbols();
KnetRegRand();
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_ACC_RAND_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetRandomNum, TEST_GetFuncRetNegative(1));
ret = KNET_ACC_Rand();
DT_ASSERT_EQUAL(ret, KNET_INVALID_RAND);
Mock->Create(KNET_GetRandomNum, TEST_GetFuncRetPositive(0));
ret = KNET_ACC_Rand();
DT_ASSERT_EQUAL(ret, KNET_INVALID_RAND);
Mock->Delete(KNET_GetRandomNum);
DeleteMock(Mock);
}
void SalCallBackTest(void)
{
printf("CallBackTest\n");
return;
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_HANDLE_INIT_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
ret = KnetHandleInit();
DT_ASSERT_EQUAL(ret, KNET_OK);
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_REG_FUNC_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KnetRegMem, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegMbufMemPool, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegRand, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegTime, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegHashTable, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegDebug, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegFdir, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegBind, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegSem, TEST_GetFuncRetPositive(0));
Mock->Create(KnetRegDelayCpd, TEST_GetFuncRetPositive(0));
ret = KnetRegFunc();
DT_ASSERT_EQUAL(ret, KNET_OK);
Mock->Delete(KnetRegDelayCpd);
Mock->Delete(KnetRegSem);
Mock->Delete(KnetRegBind);
Mock->Delete(KnetRegFdir);
Mock->Delete(KnetRegDebug);
Mock->Delete(KnetRegHashTable);
Mock->Delete(KnetRegTime);
Mock->Delete(KnetRegRand);
Mock->Delete(KnetRegMbufMemPool);
Mock->Delete(KnetRegMem);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_REG_WORKDER_ID, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(DP_RegGetSelfWorkerIdHook, TEST_GetFuncRetPositive(0));
int32_t ret = KnetRegWorkderId();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_RegGetSelfWorkerIdHook);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_SAL_KNET_TIME_HOOK_NORMAL, NULL, NULL)
{
uint32_t ret = 0;
int64_t seconds;
int64_t nanoseconds;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
ret = KNET_TimeHook(DP_CLOCK_REALTIME, &seconds, &nanoseconds);
DT_ASSERT_EQUAL(ret, KNET_ERROR);
ret = KNET_TimeHook(DP_CLOCK_MONOTONIC_COARSE, NULL, &nanoseconds);
DT_ASSERT_EQUAL(ret, KNET_ERROR);
ret = KNET_TimeHook(DP_CLOCK_MONOTONIC_COARSE, &seconds, NULL);
DT_ASSERT_EQUAL(ret, KNET_ERROR);
Mock->Create(clock_gettime, TEST_GetFuncRetPositive(1));
ret = KNET_TimeHook(DP_CLOCK_MONOTONIC_COARSE, &seconds, &nanoseconds);
DT_ASSERT_EQUAL(ret, KNET_ERROR);
Mock->Delete(clock_gettime);
ret = KNET_TimeHook(DP_CLOCK_MONOTONIC_COARSE, &seconds, &nanoseconds);
DT_ASSERT_EQUAL(ret, KNET_OK);
DeleteMock(Mock);
}
* @brief KNET_ACC_EventNotify 函数,事件通知测试
* 测试步骤:
* 入参type均为 DP_ADDR_EVENT_CREATE
* 1.入参addrEvent为NULL,预期结果为0
* 2.构造入参addrEvent,打桩流标操作和事件通知,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_SAL_KNET_ACC_EVENT_NOTIFY_ABNORMAL, NULL, NULL)
{
int ret = 0;
g_needFlowRule = 0;
ret = KNET_ACC_EventNotify(DP_ADDR_EVENT_CREATE, NULL);
DT_ASSERT_EQUAL(ret, 0);
struct sockaddr_in AddrIn = {0};
AddrIn.sin_family = AF_INET;
AddrIn.sin_port = htons(VALID_PORT);
AddrIn.sin_addr.s_addr = htonl(0xC0A80101);
DP_AddrEvent_t addrEvent;
addrEvent.localAddr = (DP_Sockaddr *)&AddrIn;
addrEvent.portMask = 0xFF00;
addrEvent.protocol = 0x06;
for (int i = 0; i < DP_ADDR_QUE_MAP_MAX; ++i) {
addrEvent.queMap[i] = i;
}
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetCfg, MockKnetGetCfg);
Mock->Create(KNET_IsNeedFlowRule, TEST_GetFuncRetPositive(1));
Mock->Create(KNET_EventNotify, TEST_GetFuncRetPositive(0));
ret = KNET_ACC_EventNotify(DP_ADDR_EVENT_CREATE, &addrEvent);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(KNET_GetCfg);
Mock->Delete(KNET_EventNotify);
Mock->Delete(KNET_IsNeedFlowRule);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_ACC_PRE_BIND_UN_NORMAL, NULL, NULL)
{
void *userData = 0;
struct DP_Sockaddr addr;
DP_Socklen_t addrlen = sizeof(struct DP_Sockaddr);
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
int ret = KNET_ACC_PreBind(userData, &addr, addrlen);
DT_ASSERT_EQUAL(ret, -1);
userData = 1;
ret = KNET_ACC_PreBind(userData, NULL, addrlen);
DT_ASSERT_EQUAL(ret, -1);
ret = KNET_ACC_PreBind(userData, &addr, 0);
DT_ASSERT_EQUAL(ret, -1);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_ACC_HASH_TBL_CREATE, NULL, NULL)
{
DP_HashTblCfg_t pstHashTblCfg;
DP_HashTbl_t phTableId;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
int ret = KNET_ACC_HashTblCreate(NULL, NULL);
DT_ASSERT_NOT_EQUAL(ret, 0);
Mock->Create(KNET_CreateHashTbl, TEST_GetFuncRetPositive(0));
ret = KNET_ACC_HashTblCreate(&pstHashTblCfg, &phTableId);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(KNET_CreateHashTbl);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_KNET_INIT_TCP_DEV, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(memcpy_s, TEST_GetFuncRetPositive(0));
Mock->Create(DP_CreateNetdev, TEST_GetFuncRetPositive(1));
Mock->Create(KnetConfigureStackNetdev, TEST_GetFuncRetPositive(0));
int ret = KnetInitDpNetdev();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(memcpy_s);
Mock->Delete(DP_CreateNetdev);
Mock->Delete(KnetConfigureStackNetdev);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_SEM_WAIT_NONBLOCK, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(sem_trywait, TEST_GetFuncRetPositive(0));
sem_t sem;
uint32_t ret = SemWaitNonblock(&sem);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(sem_trywait);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_SEM_POST, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(sem_trywait, TEST_GetFuncRetPositive(0));
sem_t sem;
uint32_t ret = KNET_SemWaitHook(&sem, 0);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(sem_trywait);
DeleteMock(Mock);
}
DTEST_CASE_F(SAL_FUN, TEST_HASH_TBL_OP, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_DestroyHashTbl, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_HashTblAddEntry, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_HashTblModifyEntry, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_HashTblDelEntry, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_HashTblLookupEntry, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_GetHashTblFirstEntry, TEST_GetFuncRetPositive(0));
Mock->Create(KNET_GetHashTblNextEntry, TEST_GetFuncRetPositive(0));
uintptr_t hTableId;
int ret = KNET_ACC_HashTblDestroy(hTableId);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblInsertEntry(hTableId, NULL, NULL);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblModifyEntry(hTableId, NULL, NULL);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblDelEntry(hTableId, NULL);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblLookupEntry(hTableId, NULL, NULL);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblEntryGetFirst(hTableId, NULL, NULL);
DT_ASSERT_EQUAL(ret, 0);
ret = KNET_ACC_HashTblEntryGetNext(hTableId, NULL, NULL, NULL);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(KNET_GetHashTblNextEntry);
Mock->Delete(KNET_GetHashTblFirstEntry);
Mock->Delete(KNET_HashTblLookupEntry);
Mock->Delete(KNET_HashTblDelEntry);
Mock->Delete(KNET_HashTblModifyEntry);
Mock->Delete(KNET_DestroyHashTbl);
Mock->Delete(KNET_HashTblAddEntry);
DeleteMock(Mock);
}
* @brief KNET_SemPostHook 函数,信号量发布钩子测试
* 测试步骤:
* 定义信号量入参sem,sem_post无法正常返回,打桩返回值为0,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_SEM_POST_HOOK, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(sem_post, TEST_GetFuncRetPositive(0));
sem_t sem;
uint32_t ret = KNET_SemPostHook(&sem);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(sem_post);
DeleteMock(Mock);
}
* @brief DP_SemHookReg 函数,信号量注册测试
* 测试步骤:
* 入参为空,DP_SemHookReg无法正常返回,打桩返回值为0,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_KNET_REG_SEM, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(DP_SemHookReg, TEST_GetFuncRetPositive(0));
uint32_t ret = KnetRegSem();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_SemHookReg);
DeleteMock(Mock);
}
* @brief KNET_ACC_MbufConstruct 函数,内存块构造测试
* 测试步骤:
* 1.入参mp为0,入参addr为申请地址偏移512字节,确保地址操作不会溢出,
入参offset和入参len测试数据为16
* 2.KNET_PktAlloc打桩返回为空,预期结果为NULL
* 3.KNET_PktAlloc打桩返回内存地址,预期结果非空
*/
DTEST_CASE_F(SAL_FUN, TEST_ACC_MBUF_CONSTRUCT, NULL, NULL)
{
uint32_t type = DP_MEMPOOL_TYPE_PBUF;
DP_Mempool mp = {0};
DT_ASSERT_EQUAL(MpHandleCtrlCreate(mp, type), KNET_OK);
void *retPtr = NULL;
void *addr = malloc(1024);
DT_ASSERT_NOT_EQUAL(addr, NULL);
const int originOffset = 512;
const int testOffset = 16;
const int testLen = 16;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_PktAlloc, TEST_GetFuncRetPositive(0));
retPtr = KNET_ACC_MbufConstruct(mp, addr + originOffset, testOffset, testLen);
DT_ASSERT_EQUAL(retPtr, NULL);
Mock->Delete(KNET_PktAlloc);
Mock->Create(KNET_PktAlloc, KNET_PktAllocMock);
Mock->Create(KNET_MbufAttachExtBuf, TEST_GetFuncRetPositive(0));
retPtr = KNET_ACC_MbufConstruct(mp, addr + originOffset, testOffset, testLen);
DT_ASSERT_NOT_EQUAL(retPtr, NULL);
Mock->Delete(KNET_PktAlloc);
Mock->Delete(KNET_MbufAttachExtBuf);
MpHandleCtrlDestroy(mp);
DeleteMock(Mock);
free(addr);
}
static int KNET_GetHashTblInfoMock(uint32_t tableId, KNET_HashTblInfo *info)
{
if (info != NULL) {
info->tableId = 0;
info->pfHashFunc = NULL;
info->keySize = 0;
info->currEntryNum = 1;
info->maxEntryNum = 1;
info->entrySize = 1;
}
return 0;
}
* @brief KNET_ACC_HashTblGetInfo 函数,哈希表信息获取测试
* 测试步骤:
* 1.入参hTableId为0,入参pstHashSummaryInfo为空,参数非法,预期结果为KNET_ERROR
* 2.入参hTableId为0,入参pstHashSummaryInfo非空,打桩填充结构体,预期结果为KNET_OK
*/
DTEST_CASE_F(SAL_FUN, TEST_ACC_HASHTB_GET_INFO, NULL, NULL)
{
DP_HashTbl_t hTableId = 0;
size_t ret = 0;
DP_HashTblSummaryInfo_t *pstHashSummaryInfo = malloc(sizeof(DP_HashTblSummaryInfo_t));
DT_ASSERT_NOT_EQUAL(pstHashSummaryInfo, NULL);
ret = KNET_ACC_HashTblGetInfo(0, NULL);
DT_ASSERT_EQUAL(ret, (int)KNET_ERROR);
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetHashTblInfo, KNET_GetHashTblInfoMock);
ret = KNET_ACC_HashTblGetInfo(0, pstHashSummaryInfo);
DT_ASSERT_EQUAL(ret, KNET_OK);
Mock->Delete(KNET_GetHashTblInfo);
DeleteMock(Mock);
free(pstHashSummaryInfo);
}
static union KNET_CfgValue KNET_GetCfgMock1(enum KNET_ConfKey key)
{
union KNET_CfgValue ret = {0};
if (key == CONF_COMMON_COTHREAD) {
ret.intValue = 1;
} else if (key == CONF_HW_BIFUR_ENABLE) {
ret.intValue = KERNEL_FORWARD_ENABLE;
}
return ret;
}
* @brief CheckFlowCfgValid 函数,流配置有效性检查测试
* 测试步骤:
* 1.入参dstIp,入参dstPort,入参proto 均构造,满足检查条件,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_CHECK_FLOW_CFG_VALID, NULL, NULL)
{
uint32_t dstIp = VALID_IP;
uint16_t dstPort = VALID_PORT;
int32_t proto = IPPROTO_TCP;
int ret = CheckFlowCfgValid(dstIp, dstPort, proto);
DT_ASSERT_EQUAL(ret, 0);
}
void *KNET_GetDelayRxRingMock(int cpdRingId)
{
static struct rte_ring ring = {0};
return ˚
}
* @brief KNET_ACC_DelayInputEnque 函数,延迟输入队列入队测试
* 测试步骤:
* 1.入参为空
* 2.打桩ring操作函数,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_ACC_DELAY_INPUT_ENQUE, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetDelayRxRing, KNET_GetDelayRxRingMock);
Mock->Create(rte_ring_enqueue_burst, TEST_GetFuncRetPositive(0));
int ret = KNET_ACC_DelayInputEnque(NULL, 0);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(rte_ring_enqueue_burst);
Mock->Delete(KNET_GetDelayRxRing);
DeleteMock(Mock);
}
* @brief KNET_ACC_DelayInputDeque 函数,延迟输入队列出队测试
* 测试步骤:
* 1.入参为空
* 2.打桩ring操作函数,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_ACC_DELAY_INPUT_DEQUE, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetDelayRxRing, KNET_GetDelayRxRingMock);
Mock->Create(rte_ring_dequeue_burst, TEST_GetFuncRetPositive(0));
int ret = KNET_ACC_DelayInputDeque(NULL, 0, 0);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(rte_ring_dequeue_burst);
Mock->Delete(KNET_GetDelayRxRing);
DeleteMock(Mock);
}
static union KNET_CfgValue *KNET_GetCfgMockBranch1(enum KNET_ConfKey key)
{
(void)memset_s(&g_cfg, sizeof(g_cfg), 0, sizeof(g_cfg));
if (key == CONF_HW_BIFUR_ENABLE) {
g_cfg.intValue = KERNEL_FORWARD_ENABLE;
}
return &g_cfg;
}
static union KNET_CfgValue *KNET_GetCfgMockBranch2(enum KNET_ConfKey key)
{
(void)memset_s(&g_cfg, sizeof(g_cfg), 0, sizeof(g_cfg));
errno_t ret = strcpy_s(g_cfg.strValueArr[0], sizeof(g_cfg.strValueArr[0]), "0000:06:00.0");
DT_ASSERT_EQUAL(ret, EOK);
if (key == CONF_HW_BIFUR_ENABLE) {
g_cfg.intValue = BIFUR_ENABLE;
} else if (key == CONF_INNER_KERNEL_BOND_NAME) {
g_cfg.strValue[0] = '\0';
}
return &g_cfg;
}
static union KNET_CfgValue *KNET_GetCfgMockBranch3(enum KNET_ConfKey key)
{
(void)memset_s(&g_cfg, sizeof(g_cfg), 0, sizeof(g_cfg));
errno_t ret = strcpy_s(g_cfg.strValue, sizeof(g_cfg.strValue), "0000:06:00.0");
DT_ASSERT_EQUAL(ret, EOK);
if (key == CONF_HW_BIFUR_ENABLE) {
g_cfg.intValue = BIFUR_ENABLE;
}
return &g_cfg;
}
static char *RealPathMock(const char *name, char *resolved)
{
char path[] = "/sys/bus/pci/devices";
size_t pathLen = strlen(path) + 1;
if (resolved == NULL) {
return NULL;
}
if (strncpy_s(resolved, pathLen, path, pathLen) != 0) {
return NULL;
}
return resolved;
}
* @brief KnetSetInterFace 函数,设置接口函数测试
* 测试步骤:
* 1.入参为空,BIFUR_ENABLE失效,创建TAP,预期结果为0
* 2.入参为空,网口名为空,获取Ifname,打桩路径,目录类型错误,预期结果为-1
* 3.入参为空,网口名非空,拷贝网口名,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_KNET_SET_INTERFACE, NULL, NULL)
{
int ret;
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetCfg, KNET_GetCfgMockBranch1);
Mock->Create(KNET_TAPCreate, TEST_GetFuncRetPositive(0));
ret = KnetSetInterFace();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(KNET_GetCfg);
Mock->Create(KNET_GetCfg, KNET_GetCfgMockBranch2);
Mock->Create(KNET_FetchIfIndex, TEST_GetFuncRetPositive(0));
Mock->Create(realpath, RealPathMock);
ret = KnetSetInterFace();
DT_ASSERT_EQUAL(ret, -1);
Mock->Delete(realpath);
Mock->Delete(KNET_FetchIfIndex);
Mock->Delete(KNET_GetCfg);
Mock->Create(KNET_GetCfg, KNET_GetCfgMockBranch3);
Mock->Create(KNET_FetchIfIndex, TEST_GetFuncRetPositive(0));
ret = KnetSetInterFace();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(KNET_FetchIfIndex);
Mock->Delete(KNET_TAPCreate);
Mock->Delete(KNET_GetCfg);
DeleteMock(Mock);
}
* @brief KnetConfigureStackNetdev 函数,配置协议栈网络设备测试
* 测试步骤:
* 1.入参netdev分配内存,入参ifname构造,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_KNET_CONFIG_STACK_DEV, NULL, NULL)
{
DP_Netdev_t *netdev = malloc(256);
DT_ASSERT_NOT_EQUAL(netdev, NULL);
char ifname[] = "0000:06:00.0";
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(DP_ProcIfreq, TEST_GetFuncRetPositive(0));
int ret = KnetConfigureStackNetdev(netdev, ifname);
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_ProcIfreq);
DeleteMock(Mock);
free(netdev);
}
static union KNET_CfgValue *KNET_GetCfgMockNetInfo(enum KNET_ConfKey key)
{
(void)memset_s(&g_cfg, sizeof(g_cfg), 0, sizeof(g_cfg));
if (key == CONF_INTERFACE_IP) {
g_cfg.intValue = inet_addr("192.168.0.2");
} else if (key == CONF_INTERFACE_NETMASK) {
g_cfg.intValue = 0xFFFFFF00;
} else if (key == CONF_INTERFACE_GATEWAY) {
g_cfg.intValue = VALID_IP;
}
return &g_cfg;
}
* @brief KnetSetDpRtCfg 函数,数据平面路由配置设置测试
* 测试步骤:
* 1.入参为空,打桩构造配置信息,预期结果为0
*/
DTEST_CASE_F(SAL_FUN, TEST_KNET_SET_DPRT_CFG, NULL, NULL)
{
KTestMock *Mock = CreateMock();
DT_ASSERT_NOT_EQUAL(Mock, NULL);
Mock->Create(KNET_GetCfg, KNET_GetCfgMockNetInfo);
Mock->Create(DP_RtCfg, TEST_GetFuncRetPositive(0));
int ret = KnetSetDpRtCfg();
DT_ASSERT_EQUAL(ret, 0);
Mock->Delete(DP_RtCfg);
Mock->Delete(KNET_GetCfg);
DeleteMock(Mock);
}