chore: migrate project into clean repository

This commit is contained in:
yuuux
2026-08-13 16:50:52 +08:00
commit d1d25a09e7
27405 changed files with 9422808 additions and 0 deletions

View File

@@ -0,0 +1 @@
build/

View File

@@ -0,0 +1,42 @@
message(STATUS "CONFIG_MAC_MANAGER: ${CONFIG_MAC_MANAGER}")
if(DEFINED CONFIG_MAC_MANAGER)
listenai_library_named(mac_manager)
listenai_library_sources(
${CMAKE_CURRENT_SOURCE_DIR}/src/mac_manager.c
${CMAKE_CURRENT_SOURCE_DIR}/src/mac_manager_ops.c
${CMAKE_CURRENT_SOURCE_DIR}/src/port/mem/sys_heap/mac_manager_mem_ops_sys_heap.c
)
listenai_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/port/mem/sys_heap
)
if (CONFIG_MAC_MANAGER_MAC_IN_LISA_KV)
listenai_library_sources(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/lisa_kv/mac_manager_content_ops_lisa_kv.c
)
listenai_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/lisa_kv
)
elseif(CONFIG_MAC_MANAGER_MAC_BY_CHIP_ID)
listenai_library_sources(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/chip_id/mac_manager_content_ops_chip_id.c
)
listenai_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/chip_id
)
elseif(CONFIG_MAC_MANAGER_MAC_GET_FROM_CHIP_ID_SAVE_TO_LISA_KV)
listenai_library_sources(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/from_chip_id_save_to_lisa_kv/mac_manager_content_ops_from_chip_id_save_to_lisa_kv.c
)
listenai_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src/port/content/from_chip_id_save_to_lisa_kv
)
else()
message(FATAL_ERROR "Only support MAC in lisa kv or chip id now")
endif() # CONFIG_MAC_MANAGER_MAC_IN_LISA_KV
endif()

View File

@@ -0,0 +1,32 @@
menu "mac manager configuration"
config MAC_MANAGER
bool "enable mac manager"
select LOG
default n
if MAC_MANAGER
choice
prompt "MAC manager selection"
default MAC_MANAGER_MAC_IN_LISA_KV
config MAC_MANAGER_MAC_IN_LISA_KV
bool "mac from lisa kv"
select LISA_KV
config MAC_MANAGER_MAC_IN_FLASH
bool "mac in flash"
config MAC_MANAGER_MAC_BY_CHIP_ID
bool "mac by chip id"
endchoice
config MAC_MANAGER_MAC_IN_FLASH_ADDR
hex "mac in flash address"
default 0xFF0000
depends on MAC_MANAGER_MAC_IN_FLASH
endif #MAC_MANAGER
endmenu

View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mac_manager.h"
#include "lisa_log.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
struct mac_manager_s {
mac_manager_content_ops_t content_ops;
mac_manager_mem_ops_t mem_ops;
mac_manager_config_t config;
bool init_done;
};
#define TAG "mac_manager"
#define UINT8_MAC_LEN 6
#define ARCS_MAC_HEADER_0 0x26
#define ARCS_MAC_HEADER_1 0x48
static bool check_mac_is_valid(const uint8_t *mac, size_t mac_len)
{
static const uint8_t zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ff_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
if (!mac || mac_len != UINT8_MAC_LEN) {
return false;
}
// 检查是否为多播地址 (第一个字节的 LSB 为 1)
// 多播地址保留用于组寻址,不能作为设备的唯一标识符
if ((mac[0] & 0x01) != 0) {
return false;
}
if (memcmp(mac, zero_mac, UINT8_MAC_LEN) == 0) {
return false;
}
if (memcmp(mac, ff_mac, UINT8_MAC_LEN) == 0) {
return false;
}
return true;
}
static int check_mac_if_exist(mac_manager_t *obj)
{
if (!obj || !obj->init_done) {
return -1;
}
uint8_t mac_addr[UINT8_MAC_LEN] = {0};
size_t mac_addr_len = UINT8_MAC_LEN;
int ret = obj->content_ops.get(mac_addr, &mac_addr_len);
if (ret != 0) {
return -2;
}
return 0;
}
static void random_mac(mac_manager_t *obj, char *out_mac)
{
uint8_t mac[UINT8_MAC_LEN];
size_t mac_len = UINT8_MAC_LEN;
if (!obj || !obj->init_done || !out_mac) {
return;
}
obj->content_ops.random(mac, &mac_len);
memcpy(out_mac, mac, mac_len);
}
int mac_manager_set(mac_manager_t *obj, const uint8_t *mac_addr, size_t mac_addr_len)
{
if (!obj || !obj->init_done || !mac_addr) {
return -1;
}
if (!check_mac_is_valid(mac_addr, mac_addr_len)) {
LISA_LOGE(TAG, "mac_manager_set: invalid mac: %02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
return -1;
}
return obj->content_ops.set(mac_addr, mac_addr_len);
}
int mac_manager_del(mac_manager_t *obj)
{
if (!obj || !obj->init_done) {
return -1;
}
return obj->content_ops.del();
}
static int gen_mac_and_set(mac_manager_t *obj, char *out_mac, size_t out_mac_len)
{
if (!obj || !obj->init_done || !out_mac || out_mac_len != UINT8_MAC_LEN) {
return -1;
}
random_mac(obj, out_mac);
return mac_manager_set(obj, (uint8_t *)out_mac, UINT8_MAC_LEN);
}
mac_manager_t *mac_manager_init(
mac_manager_mem_ops_t *mem_ops,
mac_manager_content_ops_t *ops,
mac_manager_config_t *config
)
{
int ret = 0;
if (mem_ops == NULL || ops == NULL || config == NULL) {
return NULL;
}
if (mem_ops->malloc == NULL || mem_ops->free == NULL) {
return NULL;
}
if (ops->set == NULL || ops->get == NULL || ops->del == NULL || ops->random == NULL) {
return NULL;
}
struct mac_manager_s *obj = (struct mac_manager_s *)mem_ops->malloc(sizeof(struct mac_manager_s));
if (!obj) {
return NULL;
}
memcpy(&(obj->mem_ops), mem_ops, sizeof(mac_manager_mem_ops_t));
memcpy(&(obj->content_ops), ops, sizeof(mac_manager_content_ops_t));
memcpy(&(obj->config), config, sizeof(mac_manager_config_t));
obj->init_done = true;
if (config->random_mac_if_mac_invalid) {
if (check_mac_if_exist(obj) != 0) {
char out_mac[UINT8_MAC_LEN] = {0};
ret = gen_mac_and_set(obj, out_mac, UINT8_MAC_LEN);
if (ret != 0) {
LISA_LOGE(TAG, "mac_manager_init: failed to set mac address");
}
}
}
return obj;
}
void mac_manager_deinit(mac_manager_t *obj)
{
if (!obj || !obj->init_done) {
return;
}
obj->init_done = false;
obj->mem_ops.free(obj);
}
int mac_manager_get(mac_manager_t *obj, uint8_t *mac_addr, size_t mac_addr_len)
{
if (!obj || !obj->init_done) {
return -1;
}
if (mac_addr == NULL || mac_addr_len != UINT8_MAC_LEN) {
return -1;
}
int r = obj->content_ops.get(mac_addr, &mac_addr_len);
if (r != 0)
{
return r;
}
if (!check_mac_is_valid(mac_addr, mac_addr_len)) {
if (obj->config.random_mac_if_mac_invalid) {
char out_mac[UINT8_MAC_LEN] = {0};
int ret = gen_mac_and_set(obj, out_mac, UINT8_MAC_LEN);
if (ret != 0) {
return -1;
} else {
memcpy(mac_addr, out_mac, UINT8_MAC_LEN);
return 0;
}
} else {
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
bool random_mac_if_mac_invalid;
} mac_manager_config_t;
typedef struct {
/**
* @brief Set the MAC address
* @param mac[in]: MAC address in uint8_t array
* @param mac_len[in]: MAC address length
* @retval The result execute.
*/
int (*set)(const uint8_t *mac, size_t mac_len);
/**
* @brief Get the MAC address
* @param mac[out]: output buffer
* @param mac_len[in, out]: input and output buffer length of mac
* @retval The result execute.
*/
int (*get)(uint8_t *mac, size_t *mac_len);
/**
* @brief Generate random MAC address
* @param mac[out]: generated mac address
* @param mac_len[in, out]: input and output buffer length of mac
* @retval The result execute.
*/
int (*random)(uint8_t *mac, size_t *mac_len);
/**
* @brief Delete saved MAC address
* @retval The result execute.
*/
int (*del)(void);
} mac_manager_content_ops_t;
typedef struct {
void *(*malloc)(size_t size);
void (*free)(void *ptr);
} mac_manager_mem_ops_t;
typedef struct mac_manager_s mac_manager_t;
mac_manager_t *mac_manager_init(mac_manager_mem_ops_t *mem_ops, mac_manager_content_ops_t *ops, mac_manager_config_t *config);
int mac_manager_get(mac_manager_t *obj, uint8_t *mac_addr, size_t mac_addr_len);
int mac_manager_set(mac_manager_t *obj, const uint8_t *mac_addr, size_t mac_addr_len);
int mac_manager_del(mac_manager_t *obj);
void mac_manager_deinit(mac_manager_t *obj);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mac_manager_ops.h"
#include "port/mem/sys_heap/mac_manager_mem_ops_sys_heap.h"
#ifdef CONFIG_MAC_MANAGER_MAC_IN_LISA_KV
#include "port/content/lisa_kv/mac_manager_content_ops_lisa_kv.h"
#endif
#ifdef CONFIG_MAC_MANAGER_MAC_BY_CHIP_ID
#include "port/content/chip_id/mac_manager_content_ops_chip_id.h"
#endif
static mac_manager_ops_t g_mac_manager_ops = {
.mem_ops = &mac_manager_mem_ops_sys_heap,
#ifdef CONFIG_MAC_MANAGER_MAC_IN_LISA_KV
.content_ops = &mac_manager_content_ops_lisa_kv,
#elif defined(CONFIG_MAC_MANAGER_MAC_BY_CHIP_ID)
.content_ops = &mac_manager_content_ops_chip_id,
#else
.content_ops = NULL,
#endif
};
mac_manager_ops_t* mac_manager_ops_get(void)
{
return &g_mac_manager_ops;
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "mac_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
mac_manager_mem_ops_t *mem_ops;
mac_manager_content_ops_t *content_ops;
} mac_manager_ops_t;
mac_manager_ops_t* mac_manager_ops_get(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,109 @@
#include "Driver_EFUSE.h"
#include "mac_manager.h"
#include "lisa_log.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdlib.h>
#define TAG "mac_chip_id"
#define STRING_MAC_LEN 18
#define UINT8_MAC_LEN 6
#define ARCS_MAC_HEADER_0 0x26
#define ARCS_MAC_HEADER_1 0x48
// lot id
// uuid bit0-bit7
static uint8_t get_lotid(uint64_t uuid)
{
return (uuid & 0xFF);
}
// wafer id
// (uuid >> 32), then get bit16 - bit23
static uint8_t get_wafer_id(uint64_t uuid)
{
return (uuid >> 32 >> 16) & 0xFF;
}
// wafer x
// (uuid >> 32), then get bit8 - bit15
static uint8_t get_wafer_x(uint64_t uuid)
{
return (uuid >> 32 >> 8) & 0xFF;
}
// wafer y
// (uuid >> 32), then get bit0 - bit7
static uint8_t get_wafer_y(uint64_t uuid)
{
return (uuid >> 32) & 0xFF;
}
static int set(const uint8_t *value, size_t value_len)
{
return -1;
}
static int get(uint8_t *mac, size_t *mac_len)
{
if (mac == NULL || mac_len == NULL) {
return -1;
}
if (*mac_len < UINT8_MAC_LEN) {
return -1;
}
efuse_init();
uint64_t uuid = efuse_read_uuid();
if (uuid == 0) {
LISA_LOGE(TAG, "efuse read empty uuid");
return -1;
}
mac[0] = ARCS_MAC_HEADER_0;
mac[1] = ARCS_MAC_HEADER_1;
mac[2] = get_lotid(uuid);
mac[3] = get_wafer_id(uuid);
mac[4] = get_wafer_x(uuid);
mac[5] = get_wafer_y(uuid);
*mac_len = UINT8_MAC_LEN;
return 0;
}
static int del(void)
{
return -1;
}
static int chip_id_random(uint8_t *mac, size_t *mac_len)
{
if (mac == NULL || mac_len == NULL) {
return -1;
}
if (*mac_len < UINT8_MAC_LEN) {
return -1;
}
mac[0] = ARCS_MAC_HEADER_0;
mac[1] = ARCS_MAC_HEADER_1;
srand((unsigned int)xTaskGetTickCount());
for (int i = 2; i < 6; i++) {
do {
mac[i] = (uint8_t)rand() & 0xFF;
} while (mac[i] == 0x00 || mac[i] == 0xFF);
}
return 0;
}
mac_manager_content_ops_t mac_manager_content_ops_chip_id = {
.set = set,
.get = get,
.del = del,
.random = chip_id_random
};

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "mac_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
extern mac_manager_content_ops_t mac_manager_content_ops_chip_id;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,78 @@
#include "lisa_kv.h"
#include "mac_manager.h"
#include "lisa_log.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdint.h>
#include <stdlib.h>
#define TAG "port_content_lisa_kv"
#define ARCS_MAC_HEADER_0 0x26
#define ARCS_MAC_HEADER_1 0x48
#define MAC_KEY "mac_u8_arr"
static int lisa_kv_ops_set(const uint8_t *mac, size_t mac_len)
{
return lisa_kv_set_blob(MAC_KEY, (uint8_t *)mac, mac_len);
}
static int lisa_kv_ops_get(uint8_t *mac_buf, size_t *mac_buf_len)
{
uint8_t *value = NULL;
size_t buf_len = *mac_buf_len;
if (!mac_buf || !mac_buf_len) {
return -1;
}
int ret = lisa_kv_get_blob(MAC_KEY, &value, (int *)mac_buf_len);
if (ret != 0) {
return ret;
}
if (*mac_buf_len == 0) {
return -1;
}
if (*mac_buf_len > buf_len) {
return -1;
}
memset(mac_buf, 0, *mac_buf_len);
memcpy(mac_buf, value, *mac_buf_len);
lisa_kv_free(value);
return 0;
}
static int lisa_kv_ops_del(void)
{
return lisa_kv_del(MAC_KEY);
}
static int lisa_kv_ops_random(uint8_t *mac, size_t *mac_len)
{
unsigned int curTickCount = (unsigned int)xTaskGetTickCount();
LISA_LOGI(TAG, "lisa_kv_ops_random curTickCount:%d\n", curTickCount);
srand(curTickCount);
mac[0] = ARCS_MAC_HEADER_0;
mac[1] = ARCS_MAC_HEADER_1;
for (int i = 2; i < 6; i++) {
do {
mac[i] = (uint8_t)rand() & 0xFF;
} while (mac[i] == 0x00 || mac[i] == 0xFF);
}
return 0;
}
mac_manager_content_ops_t mac_manager_content_ops_lisa_kv = {
.set = lisa_kv_ops_set,
.get = lisa_kv_ops_get,
.del = lisa_kv_ops_del,
.random = lisa_kv_ops_random
};

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "mac_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
extern mac_manager_content_ops_t mac_manager_content_ops_lisa_kv;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sysheap.h"
#include "mac_manager.h"
static void *malloc(size_t size) {
return exram_malloc(4, size);
}
static void free(void *ptr) {
exram_free(ptr);
}
mac_manager_mem_ops_t mac_manager_mem_ops_sys_heap = {
.malloc = malloc,
.free = free
};

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "mac_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
extern mac_manager_mem_ops_t mac_manager_mem_ops_sys_heap;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,17 @@
#pragma once
// 这是一个模拟的lisa_log.h文件用于测试mac_manager.c
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
#define LISA_LOGI(tag, fmt, ...) printf("[I][%s] " fmt "\n", tag, ##__VA_ARGS__)
#define LISA_LOGE(tag, fmt, ...) printf("[E][%s] " fmt "\n", tag, ##__VA_ARGS__)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mock_task.h"
#include <time.h>
DEFINE_FAKE_VALUE_FUNC(unsigned int, xTaskGetTickCount);
static unsigned int custom_xTaskGetTickCount(void)
{
return (unsigned int)time(NULL);
}
void mock_task_init(void)
{
RESET_FAKE(xTaskGetTickCount);
xTaskGetTickCount_fake.custom_fake = custom_xTaskGetTickCount;
}
void mock_task_reset(void)
{
mock_task_init();
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "task.h"
#include "fff.h"
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_FAKE_VALUE_FUNC(unsigned int, xTaskGetTickCount);
void mock_task_init(void);
void mock_task_reset(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
unsigned int xTaskGetTickCount(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void efuse_init(void);
uint64_t efuse_read_uuid(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mock_Driver_EFUSE.h"
DEFINE_FAKE_VOID_FUNC(efuse_init);
DEFINE_FAKE_VALUE_FUNC(uint64_t, efuse_read_uuid);
void mock_driver_efuse_init(void)
{
RESET_FAKE(efuse_init);
RESET_FAKE(efuse_read_uuid);
}
void mock_driver_efuse_reset(void)
{
mock_driver_efuse_init();
}

View File

@@ -0,0 +1,23 @@
#ifndef MOCK_DRIVER_EFUSE_H
#define MOCK_DRIVER_EFUSE_H
#include "Driver_EFUSE.h"
#include "fff.h"
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_FAKE_VOID_FUNC(efuse_init);
DECLARE_FAKE_VALUE_FUNC(uint64_t, efuse_read_uuid);
void mock_driver_efuse_init(void);
void mock_driver_efuse_reset(void);
#ifdef __cplusplus
}
#endif
#endif /* MOCK_DRIVER_EFUSE_H */

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void lisa_kv_free(void *value);
int lisa_kv_get_blob(const char *key, uint8_t **data, int *len);
int lisa_kv_set_blob(const char *key, uint8_t *data, int len);
int lisa_kv_del(const char *key);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,74 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mock_lisa_kv.h"
#include <stdlib.h>
#include <string.h>
DEFINE_FAKE_VOID_FUNC(lisa_kv_free, void *);
DEFINE_FAKE_VALUE_FUNC(int, lisa_kv_get_blob, const char *, uint8_t **, int *);
DEFINE_FAKE_VALUE_FUNC(int, lisa_kv_set_blob, const char *, uint8_t *, int);
DEFINE_FAKE_VALUE_FUNC(int, lisa_kv_del, const char *);
uint8_t *saved_data = NULL;
int saved_len = 0;
int mem_lisa_kv_get_blob(const char *key, uint8_t **data, int *len)
{
uint8_t *got_data = malloc(saved_len);
memcpy(got_data, saved_data, saved_len);
*data = got_data;
*len = saved_len;
return 0;
}
int mem_lisa_kv_set_blob(const char *key, uint8_t *data, int len)
{
saved_data = malloc(len);
memcpy(saved_data, data, len);
saved_len = len;
return 0;
}
void mem_lisa_kv_free(void *value)
{
if (value == NULL) {
return;
}
free(value);
}
int mem_lisa_kv_del(const char *key)
{
if (saved_data) {
free(saved_data);
}
saved_data = NULL;
saved_len = 0;
return 0;
}
void mock_lisa_kv_init(void)
{
RESET_FAKE(lisa_kv_free);
RESET_FAKE(lisa_kv_get_blob);
RESET_FAKE(lisa_kv_set_blob);
RESET_FAKE(lisa_kv_del);
lisa_kv_get_blob_fake.custom_fake = mem_lisa_kv_get_blob;
lisa_kv_set_blob_fake.custom_fake = mem_lisa_kv_set_blob;
lisa_kv_free_fake.custom_fake = mem_lisa_kv_free;
lisa_kv_del_fake.custom_fake = mem_lisa_kv_del;
}
void mock_lisa_kv_reset(void)
{
mock_lisa_kv_init();
mem_lisa_kv_del("mac");
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "lisa_kv.h"
#include "fff.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_FAKE_VOID_FUNC(lisa_kv_free, void *);
DECLARE_FAKE_VALUE_FUNC(int, lisa_kv_get_blob, const char *, uint8_t **, int *);
DECLARE_FAKE_VALUE_FUNC(int, lisa_kv_set_blob, const char *, uint8_t *, int);
DECLARE_FAKE_VALUE_FUNC(int, lisa_kv_del, const char *);
void mock_lisa_kv_init(void);
void mock_lisa_kv_reset(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mock_sysheap.h"
#include <stdlib.h>
DEFINE_FAKE_VALUE_FUNC(void *, exram_malloc, int, size_t);
DEFINE_FAKE_VOID_FUNC(exram_free, void *);
static void *mock_exram_malloc(int heap_id, size_t size)
{
return malloc(size);
}
static void mock_exram_free(void *ptr)
{
free(ptr);
}
void mock_sysheap_init(void)
{
RESET_FAKE(exram_malloc);
RESET_FAKE(exram_free);
exram_malloc_fake.custom_fake = mock_exram_malloc;
exram_free_fake.custom_fake = mock_exram_free;
}
void mock_sysheap_reset(void)
{
mock_sysheap_init();
}

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sysheap.h"
#include "fff.h"
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_FAKE_VALUE_FUNC(void *, exram_malloc, int, size_t);
DECLARE_FAKE_VOID_FUNC(exram_free, void *);
void mock_sysheap_init(void);
void mock_sysheap_reset(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *exram_malloc(int heap_id, size_t size);
void exram_free(void *ptr);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.16)
project(mac_manager_test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# 配置cmake模块路径
list(APPEND CMAKE_PREFIX_PATH "/usr/local/lib/cmake")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
find_package(unity QUIET)
# 如果找到Unity包使用包提供的变量
if(unity_FOUND)
message(STATUS "Found Unity package")
set(UNITY_LIB unity::framework)
else()
message(FATAL_ERROR "Not found Unity package")
endif()
set(PRJ_ROOT ../..)
# 创建测试可执行文件
add_executable(tests)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/utils/fff
${PRJ_ROOT}/test/utils/unity_config
)
target_sources(tests PRIVATE
${PRJ_ROOT}/src/mac_manager.c
)
target_include_directories(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PRJ_ROOT}/src
${PRJ_ROOT}/test/common/fake_lisa_log
)
target_sources(tests PRIVATE
test_mac_manager.c
mock_mem_ops.c
mock_content_ops.c
)
target_link_libraries(tests ${UNITY_LIB})
# 允许使用CTest运行测试
enable_testing()
add_test(NAME mac_manager_tests COMMAND tests)

View File

@@ -0,0 +1,150 @@
/**
* @file mock_content_ops.c
* @brief MAC管理器测试中使用的内容操作实现
*/
#include "mock_content_ops.h"
#include <string.h>
#include <stdio.h>
#define ARCS_MAC_HEADER_0 0x26
#define ARCS_MAC_HEADER_1 0x48
#define UINT8_MAC_LEN 6
int custom_mac_del(void);
DEFINE_FAKE_VALUE_FUNC(int, mock_mac_set, const uint8_t*, size_t);
DEFINE_FAKE_VALUE_FUNC(int, mock_mac_get, uint8_t* , size_t*);
DEFINE_FAKE_VALUE_FUNC(int, mock_mac_del);
DEFINE_FAKE_VALUE_FUNC(int, mock_mac_random, uint8_t*, size_t*);
void mock_content_ops_reset(void)
{
custom_mac_del();
mock_content_ops_init();
}
/**
* @brief 内存模式MAC存储结构
*/
typedef struct {
char mac_value[18];
size_t mac_len;
bool has_value;
} memory_mac_storage_t;
// 内存模式MAC存储
static memory_mac_storage_t mem_storage = {0};
/**
* @brief 设置MAC地址到内存存储中
*/
int custom_mac_set(const uint8_t* value, size_t value_len) {
if (!value) {
return -1;
}
memcpy(mem_storage.mac_value, value, value_len);
mem_storage.mac_len = value_len;
mem_storage.has_value = true;
return mock_mac_set_fake.return_val;
}
/**
* @brief 从内存存储中获取MAC地址
*/
int custom_mac_get(uint8_t* out_value, size_t* out_value_len) {
if (!out_value || !out_value_len) {
return -1;
}
if (!mem_storage.has_value) {
return -1;
}
if (*out_value_len < mem_storage.mac_len) {
return -2;
}
memcpy(out_value, mem_storage.mac_value, mem_storage.mac_len);
*out_value_len = mem_storage.mac_len;
return mock_mac_get_fake.return_val;
}
/**
* @brief 删除内存存储中的MAC地址
*/
int custom_mac_del(void) {
memset(mem_storage.mac_value, 0, sizeof(mem_storage.mac_value));
mem_storage.mac_len = 0;
mem_storage.has_value = false;
return 0;
}
int custom_mac_random(uint8_t *mac, size_t *mac_len)
{
if (mac == NULL || mac_len == NULL) {
return -1;
}
// Mock应该返回固定、可预测的值便于测试验证
// 使用固定的测试MAC地址避免随机性导致测试不确定
static const uint8_t test_mac[6] = {
ARCS_MAC_HEADER_0, // 0x26
ARCS_MAC_HEADER_1, // 0x48
0x11, // 固定值,便于测试
0x22,
0x33,
0x44
};
memcpy(mac, test_mac, UINT8_MAC_LEN);
*mac_len = UINT8_MAC_LEN;
return 0;
}
/**
* @brief 内容操作结构体
*/
static mac_manager_content_ops_t content_ops = {
.set = mock_mac_set,
.get = mock_mac_get,
.del = mock_mac_del,
.random = mock_mac_random
};
/**
* @brief 获取预先配置好的内容操作结构体
*/
mac_manager_content_ops_t* mock_content_get_ops(void) {
return &content_ops;
}
void mock_content_ops_init(void)
{
RESET_FAKE(mock_mac_set);
RESET_FAKE(mock_mac_get);
RESET_FAKE(mock_mac_del);
RESET_FAKE(mock_mac_random);
content_ops.set = mock_mac_set;
content_ops.get = mock_mac_get;
content_ops.del = mock_mac_del;
content_ops.random = mock_mac_random;
mock_mac_set_fake.custom_fake = custom_mac_set;
mock_mac_get_fake.custom_fake = custom_mac_get;
mock_mac_del_fake.custom_fake = custom_mac_del;
mock_mac_random_fake.custom_fake = custom_mac_random;
}

View File

@@ -0,0 +1,30 @@
/**
* @file mock_content_ops.h
* @brief MAC管理器测试中使用的内容操作接口
*/
#ifndef MOCK_CONTENT_OPS_H
#define MOCK_CONTENT_OPS_H
#include "mac_manager.h"
#include "fff.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
DECLARE_FAKE_VALUE_FUNC(int, mock_mac_set, const uint8_t*, size_t);
DECLARE_FAKE_VALUE_FUNC(int, mock_mac_get, uint8_t* , size_t*);
DECLARE_FAKE_VALUE_FUNC(int, mock_mac_del);
DECLARE_FAKE_VALUE_FUNC(int, mock_mac_random, uint8_t*, size_t *);
void mock_content_ops_init(void);
void mock_content_ops_reset(void);
/**
* @brief 获取预先配置好的内容操作结构体
* @return 内容操作结构体
*/
mac_manager_content_ops_t* mock_content_get_ops(void);
#endif /* MOCK_CONTENT_OPS_H */

View File

@@ -0,0 +1,57 @@
/**
* @file mock_mem_ops.c
* @brief MAC管理器测试中使用的内存操作实现
*/
#include "mock_mem_ops.h"
#include <stdlib.h>
#include <stdio.h>
DEFINE_FAKE_VALUE_FUNC(void *, mock_malloc, size_t);
DEFINE_FAKE_VOID_FUNC(mock_free, void *);
static mac_manager_mem_ops_t mem_ops = {
.malloc = mock_malloc,
.free = mock_free
};
void mock_mem_ops_reset(void)
{
mock_mem_ops_init();
}
/**
* @brief 测试用的内存分配函数
*/
static void* custom_mock_malloc(size_t size) {
return malloc(size);
}
/**
* @brief 测试用的内存释放函数
*/
static void custom_mock_free(void* ptr) {
free(ptr);
}
void mock_mem_ops_init(void)
{
RESET_FAKE(mock_malloc);
RESET_FAKE(mock_free);
mem_ops.malloc = mock_malloc;
mem_ops.free = mock_free;
mock_malloc_fake.custom_fake = custom_mock_malloc;
mock_free_fake.custom_fake = custom_mock_free;
}
mac_manager_mem_ops_t* mock_mem_ops_get(void)
{
return &mem_ops;
}

View File

@@ -0,0 +1,22 @@
/**
* @file mock_mem_ops.h
* @brief MAC管理器测试中使用的内存操作接口
*/
#ifndef MOCK_MEM_OPS_H
#define MOCK_MEM_OPS_H
#include <stdlib.h>
#include "mac_manager.h"
#include "fff.h"
DECLARE_FAKE_VALUE_FUNC(void *, mock_malloc, size_t);
DECLARE_FAKE_VOID_FUNC(mock_free, void *);
void mock_mem_ops_init(void);
void mock_mem_ops_reset(void);
mac_manager_mem_ops_t* mock_mem_ops_get(void);
#endif /* MOCK_MEM_OPS_H */

View File

@@ -0,0 +1,492 @@
#include "unity.h"
#include "mac_manager.h"
#include "mock_mem_ops.h"
#include "mock_content_ops.h"
DEFINE_FFF_GLOBALS;
// Force to use the same struct as in src
typedef struct mac_manager_s {
mac_manager_content_ops_t content_ops;
mac_manager_mem_ops_t mem_ops;
mac_manager_config_t config;
bool init_done;
} mac_manager_t;
static mac_manager_t* mgr;
static mac_manager_t *custom_mac_manager_init(mac_manager_config_t *config)
{
mgr = mac_manager_init(mock_mem_ops_get(), mock_content_get_ops(), config);
return mgr;
}
void setUp(void) {
mock_mem_ops_init();
mock_content_ops_init();
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mgr = custom_mac_manager_init(&config);
}
// 测试后清理
void tearDown(void) {
if (mgr) {
mac_manager_deinit(mgr);
mgr = NULL;
}
mock_mem_ops_reset();
mock_content_ops_reset();
}
void test_mac_manager_lisa_kv_impl(void)
{
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mock_mem_ops_reset();
mac_manager_t *mac_mgr = custom_mac_manager_init(&config);
TEST_ASSERT_EQUAL(1, mock_malloc_fake.call_count);
TEST_ASSERT_NOT_NULL(mac_mgr);
mac_manager_deinit(mac_mgr);
}
void test_mac_manager_init_with_copy_params(void)
{
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mock_mem_ops_reset();
mac_manager_mem_ops_t mem_ops = {
.free = mock_free,
.malloc = mock_malloc
};
mac_manager_content_ops_t content_ops = {
.del = mock_mac_del,
.get = mock_mac_get,
.random = mock_mac_random,
.set = mock_mac_set
};
mac_manager_t *mac_mgr = mac_manager_init(&mem_ops, &content_ops, &config);
TEST_ASSERT_NOT_NULL(mac_mgr);
TEST_ASSERT_NOT_EQUAL(&mem_ops, &(mac_mgr->mem_ops));
TEST_ASSERT_NOT_EQUAL(&content_ops, &(mac_mgr->content_ops));
TEST_ASSERT_NOT_EQUAL(&config, &(mac_mgr->config));
mac_manager_deinit(mac_mgr);
}
void test_mac_manager_random_mac_in_init(void)
{
mac_manager_config_t config = {.random_mac_if_mac_invalid = true};
mock_mac_get_fake.return_val = -2;
mac_manager_t *mac_mgr = custom_mac_manager_init(&config);
TEST_ASSERT_EQUAL(1, mock_mac_random_fake.call_count);
TEST_ASSERT_EQUAL(1, mock_mac_set_fake.call_count);
mac_manager_deinit(mac_mgr);
}
void test_mac_manager_init_with_wrong_params(void) {
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mac_manager_t *null_mgr = NULL;
mac_manager_mem_ops_t* mem_ops = mock_mem_ops_get();
mac_manager_content_ops_t* content_ops = mock_content_get_ops();
null_mgr = mac_manager_init(NULL, content_ops, &config);
TEST_ASSERT_NULL(null_mgr);
null_mgr = mac_manager_init(mem_ops, NULL, &config);
TEST_ASSERT_NULL(null_mgr);
null_mgr = mac_manager_init(mem_ops, content_ops, NULL);
TEST_ASSERT_NULL(null_mgr);
mem_ops->malloc = NULL;
null_mgr = mac_manager_init(mem_ops, content_ops, &config);
TEST_ASSERT_NULL(null_mgr);
mem_ops->malloc = mock_malloc;
mem_ops->free = NULL;
null_mgr = mac_manager_init(mem_ops, content_ops, &config);
TEST_ASSERT_NULL(null_mgr);
mem_ops->malloc = mock_malloc;
mem_ops->free = mock_free;
content_ops->random = NULL;
null_mgr = mac_manager_init(mem_ops, content_ops, &config);
TEST_ASSERT_NULL(null_mgr);
}
// 测试MAC地址获取功能
void test_mac_manager_get(void) {
uint8_t mac[6] = {0};
TEST_ASSERT_NOT_NULL(mgr);
// 当没有设置MAC时获取应该失败
int ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
// 设置有效MAC
mock_mac_set((uint8_t[]){0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, 6);
// 获取MAC地址
ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_EQUAL(0, ret);
// 验证MAC内容
uint8_t expected_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
TEST_ASSERT_EQUAL_MEMORY(expected_mac, mac, 6);
// 测试参数错误
ret = mac_manager_get(NULL, mac, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
ret = mac_manager_get(mgr, NULL, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
ret = mac_manager_get(mgr, mac, 5); // 错误的长度
TEST_ASSERT_NOT_EQUAL(0, ret);
}
void test_mac_manager_get_generate_random_mac(void) {
uint8_t mac[6] = {0};
mac_manager_config_t config = {.random_mac_if_mac_invalid = true};
mac_manager_deinit(mgr);
mgr = custom_mac_manager_init(&config);
mock_content_ops_reset();
mock_mac_set((uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 6);
mock_mac_set_fake.call_count = 0;
int ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, mock_mac_random_fake.call_count);
TEST_ASSERT_EQUAL(1, mock_mac_set_fake.call_count);
TEST_ASSERT_EQUAL(1, mock_mac_get_fake.call_count);
}
void test_mac_validation(void) {
uint8_t mac[6] = {0};
// 测试全0的MAC
mock_mac_set((uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 6);
int ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
// 测试全F的MAC
mock_mac_set((uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 6);
ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
// 测试多播MAC
mock_mac_set((uint8_t[]){0x01, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, 6);
ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL(0, ret);
// 测试有效MAC格式
mock_mac_set((uint8_t[]){0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, 6);
ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_EQUAL(0, ret);
}
// 测试 mac_manager_set() 函数 - 设置有效的MAC地址
void test_mac_manager_set_valid_mac_succeeds(void) {
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
mock_content_ops_reset();
int ret = mac_manager_set(mgr, valid_mac, 6);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Setting valid MAC should succeed");
TEST_ASSERT_EQUAL_MESSAGE(1, mock_mac_set_fake.call_count,
"content_ops.set should be called once");
}
// 测试 mac_manager_set() - 拒绝全0的MAC地址
void test_mac_manager_set_rejects_all_zeros_mac(void) {
uint8_t zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
mock_content_ops_reset();
int ret = mac_manager_set(mgr, zero_mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "Setting all-zeros MAC should fail");
TEST_ASSERT_EQUAL_MESSAGE(0, mock_mac_set_fake.call_count,
"content_ops.set should not be called for invalid MAC");
}
// 测试 mac_manager_set() - 拒绝全F的MAC地址
void test_mac_manager_set_rejects_all_ff_mac(void) {
uint8_t ff_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
mock_content_ops_reset();
int ret = mac_manager_set(mgr, ff_mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "Setting all-FF MAC should fail");
TEST_ASSERT_EQUAL_MESSAGE(0, mock_mac_set_fake.call_count,
"content_ops.set should not be called for invalid MAC");
}
// 测试 mac_manager_set() - 拒绝多播地址第一字节LSB为1
void test_mac_manager_set_rejects_multicast_address(void) {
// 测试不同的多播地址模式
uint8_t multicast_macs[][6] = {
{0x01, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, // 0x01 - LSB为1
{0x03, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, // 0x03 - LSB为1
{0x05, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, // 0x05 - LSB为1
{0xFF, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, // 0xFF - LSB为1
};
for (int i = 0; i < 4; i++) {
mock_content_ops_reset();
int ret = mac_manager_set(mgr, multicast_macs[i], 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "Setting multicast MAC should fail");
TEST_ASSERT_EQUAL_MESSAGE(0, mock_mac_set_fake.call_count,
"content_ops.set should not be called for multicast MAC");
}
}
// 测试 mac_manager_set() - NULL参数校验
void test_mac_manager_set_with_null_params(void) {
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
// 测试 NULL manager对象
int ret = mac_manager_set(NULL, valid_mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "NULL manager should fail");
// 测试 NULL MAC地址
ret = mac_manager_set(mgr, NULL, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "NULL MAC address should fail");
}
// 测试 mac_manager_set() - 错误的MAC长度
void test_mac_manager_set_with_invalid_length(void) {
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
mock_content_ops_reset();
// 测试长度不是6的情况
int ret = mac_manager_set(mgr, valid_mac, 5);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "MAC length != 6 should fail");
ret = mac_manager_set(mgr, valid_mac, 7);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "MAC length != 6 should fail");
TEST_ASSERT_EQUAL_MESSAGE(0, mock_mac_set_fake.call_count,
"content_ops.set should not be called for invalid length");
}
// 测试 mac_manager_set() - 验证边界值
void test_mac_manager_set_with_boundary_values(void) {
// 测试包含边界值但有效的MAC
uint8_t boundary_macs[][6] = {
{0x26, 0x48, 0x00, 0x01, 0xFE, 0xFD}, // 包含0x00和0xFE但有效
{0x00, 0x48, 0xAA, 0xBB, 0xCC, 0xDD}, // 第一字节为0x00偶数单播
{0x26, 0x48, 0xFF, 0xFF, 0xFF, 0xFE}, // 接近全F但有效
};
for (int i = 0; i < 3; i++) {
mock_content_ops_reset();
int ret = mac_manager_set(mgr, boundary_macs[i], 6);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Valid boundary MAC should succeed");
TEST_ASSERT_EQUAL_MESSAGE(1, mock_mac_set_fake.call_count,
"content_ops.set should be called for valid boundary MAC");
}
}
// 测试 mac_manager_del() 函数 - 正常删除操作
void test_mac_manager_del_succeeds(void) {
// 先设置一个MAC地址
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
mac_manager_set(mgr, valid_mac, 6);
mock_content_ops_reset();
// 删除MAC地址
int ret = mac_manager_del(mgr);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Deleting MAC should succeed");
TEST_ASSERT_EQUAL_MESSAGE(1, mock_mac_del_fake.call_count,
"content_ops.del should be called once");
}
// 测试 mac_manager_del() - NULL参数校验
void test_mac_manager_del_with_null_params(void) {
int ret = mac_manager_del(NULL);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret, "Deleting with NULL manager should fail");
}
// 测试 mac_manager_del() - 删除后get应该失败
void test_mac_manager_del_then_get_fails(void) {
uint8_t mac[6] = {0};
// 先设置一个MAC
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
mac_manager_set(mgr, valid_mac, 6);
// 删除MAC
int ret = mac_manager_del(mgr);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Delete should succeed");
// 尝试获取应该失败
ret = mac_manager_get(mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret,
"Getting MAC after delete should fail");
}
// 测试 mac_manager_del() - 重复删除
void test_mac_manager_del_multiple_times(void) {
// 先设置一个MAC
uint8_t valid_mac[6] = {0x26, 0x48, 0xAA, 0xBB, 0xCC, 0xDD};
mac_manager_set(mgr, valid_mac, 6);
// 第一次删除
int ret = mac_manager_del(mgr);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "First delete should succeed");
// 第二次删除没有MAC的情况
ret = mac_manager_del(mgr);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Second delete should also succeed");
}
// 测试内存泄漏 - 验证 deinit 正确释放内存
void test_memory_leak_on_deinit(void) {
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mock_mem_ops_reset();
mock_content_ops_reset();
// 初始化 manager
mac_manager_t *test_mgr = custom_mac_manager_init(&config);
TEST_ASSERT_NOT_NULL_MESSAGE(test_mgr, "Manager should be initialized");
TEST_ASSERT_EQUAL_MESSAGE(1, mock_malloc_fake.call_count,
"malloc should be called once during init");
// 清理并验证 free 被调用
mac_manager_deinit(test_mgr);
TEST_ASSERT_EQUAL_MESSAGE(1, mock_free_fake.call_count,
"free should be called once during deinit");
}
// 测试内存泄漏 - 多次初始化和清理
void test_memory_leak_multiple_init_deinit_cycles(void) {
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mock_mem_ops_reset();
mock_content_ops_reset();
// 执行多次初始化和清理循环
for (int i = 0; i < 5; i++) {
mac_manager_t *test_mgr = custom_mac_manager_init(&config);
TEST_ASSERT_NOT_NULL_MESSAGE(test_mgr, "Manager should be initialized");
mac_manager_deinit(test_mgr);
}
// 验证 malloc 和 free 调用次数匹配
TEST_ASSERT_EQUAL_MESSAGE(5, mock_malloc_fake.call_count,
"malloc should be called 5 times");
TEST_ASSERT_EQUAL_MESSAGE(5, mock_free_fake.call_count,
"free should be called 5 times to match malloc");
}
// 测试内存泄漏 - deinit NULL 指针不应该崩溃
void test_deinit_with_null_does_not_crash(void) {
// 这个测试主要验证不会崩溃
mac_manager_deinit(NULL);
// 如果到达这里,说明没有崩溃
TEST_ASSERT_TRUE_MESSAGE(true, "Deinit with NULL should not crash");
}
// 测试内存泄漏 - deinit 后不应该再能使用
void test_manager_unusable_after_deinit(void) {
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
uint8_t mac[6] = {0};
mock_mem_ops_reset();
mock_content_ops_reset();
mac_manager_t *test_mgr = custom_mac_manager_init(&config);
TEST_ASSERT_NOT_NULL(test_mgr);
// deinit 之后
mac_manager_deinit(test_mgr);
// 尝试使用应该失败(因为 init_done 被设为 false
int ret = mac_manager_get(test_mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret,
"Operations should fail after deinit");
ret = mac_manager_set(test_mgr, mac, 6);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret,
"Set operation should fail after deinit");
ret = mac_manager_del(test_mgr);
TEST_ASSERT_NOT_EQUAL_MESSAGE(0, ret,
"Del operation should fail after deinit");
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_mac_manager_lisa_kv_impl);
RUN_TEST(test_mac_manager_init_with_copy_params);
RUN_TEST(test_mac_manager_random_mac_in_init);
RUN_TEST(test_mac_manager_init_with_wrong_params);
RUN_TEST(test_mac_manager_get);
RUN_TEST(test_mac_manager_get_generate_random_mac);
RUN_TEST(test_mac_validation);
// mac_manager_set() 测试
RUN_TEST(test_mac_manager_set_valid_mac_succeeds);
RUN_TEST(test_mac_manager_set_rejects_all_zeros_mac);
RUN_TEST(test_mac_manager_set_rejects_all_ff_mac);
RUN_TEST(test_mac_manager_set_rejects_multicast_address);
RUN_TEST(test_mac_manager_set_with_null_params);
RUN_TEST(test_mac_manager_set_with_invalid_length);
RUN_TEST(test_mac_manager_set_with_boundary_values);
// mac_manager_del() 测试
RUN_TEST(test_mac_manager_del_succeeds);
RUN_TEST(test_mac_manager_del_with_null_params);
RUN_TEST(test_mac_manager_del_then_get_fails);
RUN_TEST(test_mac_manager_del_multiple_times);
// 内存泄漏测试
RUN_TEST(test_memory_leak_on_deinit);
RUN_TEST(test_memory_leak_multiple_init_deinit_cycles);
RUN_TEST(test_deinit_with_null_does_not_crash);
RUN_TEST(test_manager_unusable_after_deinit);
return UNITY_END();
}

View File

@@ -0,0 +1,7 @@
tests:
test.mac_manager:
runner: linux
builder: cmake
log_analyzer: "unity"

View File

@@ -0,0 +1,89 @@
cmake_minimum_required(VERSION 3.16)
project(mac_manager_test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
list(APPEND CMAKE_PREFIX_PATH "/usr/local/lib/cmake")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
find_package(unity QUIET)
if(unity_FOUND)
message(STATUS "Found Unity package")
set(UNITY_LIB unity::framework)
else()
message(FATAL_ERROR "Not found Unity package")
endif()
set(PRJ_ROOT ../..)
macro(listenai_library_named _name)
add_library(${_name} STATIC "")
set(LISTENAI_CURRENT_LIBRARY ${_name})
endmacro()
macro(listenai_library_sources source)
target_sources(${LISTENAI_CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
endmacro()
macro(listenai_link_libraries lib)
endmacro()
macro(listenai_include_directories source)
target_include_directories(${LISTENAI_CURRENT_LIBRARY} PUBLIC ${source} ${ARGN})
endmacro()
add_executable(tests)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/utils/fff
${PRJ_ROOT}/test/utils/unity_config
)
set(CONFIG_MAC_MANAGER 1 CACHE INTERNAL "")
set(CONFIG_MAC_MANAGER_MAC_BY_CHIP_ID 1 CACHE INTERNAL "")
add_subdirectory(${PRJ_ROOT} mac_manager)
target_sources(mac_manager PRIVATE
${PRJ_ROOT}/test/common/sysheap/mock_sysheap.c
${PRJ_ROOT}/test/common/mock_driver_efuse/mock_Driver_EFUSE.c
${PRJ_ROOT}/test/common/freertos/mock_task.c
)
target_include_directories(mac_manager PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PRJ_ROOT}/test/common/sysheap
${PRJ_ROOT}/test/common/mock_driver_efuse
${PRJ_ROOT}/test/common/fake_lisa_log
${PRJ_ROOT}/test/common/freertos
${PRJ_ROOT}/test/utils/fff
)
target_link_libraries(tests mac_manager)
target_include_directories(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_sources(tests PRIVATE
test_mac_manager.c
)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/common/sysheap
${PRJ_ROOT}/test/common/mock_driver_efuse
${PRJ_ROOT}/test/common
${PRJ_ROOT}/test/utils/fff
)
target_link_libraries(tests ${UNITY_LIB})
# 允许使用CTest运行测试
enable_testing()
add_test(NAME mac_manager_tests COMMAND tests)

View File

@@ -0,0 +1,3 @@
# README
This test used to test lisa_kv config build. Not Unit test.

View File

@@ -0,0 +1,61 @@
#include "unity.h"
#include "mac_manager.h"
#include "mac_manager_mem_ops_sys_heap.h"
#include "mac_manager_content_ops_chip_id.h"
#include "mock_sysheap.h"
#include "mock_Driver_EFUSE.h"
#include "fff.h"
DEFINE_FFF_GLOBALS;
static mac_manager_t *mgr;
static mac_manager_t *custom_mac_manager_init(mac_manager_config_t *config)
{
mgr = mac_manager_init(&mac_manager_mem_ops_sys_heap,
&mac_manager_content_ops_chip_id, config);
return mgr;
}
void setUp(void)
{
mock_sysheap_init();
mock_driver_efuse_init();
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mgr = custom_mac_manager_init(&config);
}
void tearDown(void)
{
if (mgr) {
mac_manager_deinit(mgr);
mgr = NULL;
}
mock_sysheap_reset();
mock_driver_efuse_reset();
}
void test_mac_manager_lisa_kv_impl(void)
{
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mac_manager_t *mac_mgr = mac_manager_init(&mac_manager_mem_ops_sys_heap,
&mac_manager_content_ops_chip_id, &config);
TEST_ASSERT_NOT_NULL(mac_mgr);
mac_manager_deinit(mac_mgr);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_mac_manager_lisa_kv_impl);
return UNITY_END();
}

View File

@@ -0,0 +1,8 @@
tests:
test.mac_manager_build_only_chip_id:
runner: linux
builder: cmake
build_only: true
log_analyzer: "unity"

View File

@@ -0,0 +1,89 @@
cmake_minimum_required(VERSION 3.16)
project(mac_manager_test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
list(APPEND CMAKE_PREFIX_PATH "/usr/local/lib/cmake")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
find_package(unity QUIET)
if(unity_FOUND)
message(STATUS "Found Unity package")
set(UNITY_LIB unity::framework)
else()
message(FATAL_ERROR "Not found Unity package")
endif()
set(PRJ_ROOT ../..)
macro(listenai_library_named _name)
add_library(${_name} STATIC "")
set(LISTENAI_CURRENT_LIBRARY ${_name})
endmacro()
macro(listenai_library_sources source)
target_sources(${LISTENAI_CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
endmacro()
macro(listenai_link_libraries lib)
endmacro()
macro(listenai_include_directories source)
target_include_directories(${LISTENAI_CURRENT_LIBRARY} PUBLIC ${source} ${ARGN})
endmacro()
add_executable(tests)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/utils/fff
${PRJ_ROOT}/test/utils/unity_config
)
set(CONFIG_MAC_MANAGER 1 CACHE INTERNAL "")
set(CONFIG_MAC_MANAGER_MAC_IN_LISA_KV 1 CACHE INTERNAL "")
add_subdirectory(${PRJ_ROOT} mac_manager)
target_sources(mac_manager PRIVATE
${PRJ_ROOT}/test/common/sysheap/mock_sysheap.c
${PRJ_ROOT}/test/common/mock_lisa_kv/mock_lisa_kv.c
${PRJ_ROOT}/test/common/freertos/mock_task.c
)
target_include_directories(mac_manager PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PRJ_ROOT}/test/common/sysheap
${PRJ_ROOT}/test/common/fake_lisa_log
${PRJ_ROOT}/test/common/mock_lisa_kv
${PRJ_ROOT}/test/common/freertos
${PRJ_ROOT}/test/utils/fff
)
target_link_libraries(tests mac_manager)
target_include_directories(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_sources(tests PRIVATE
test_mac_manager.c
)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/common/sysheap
${PRJ_ROOT}/test/common/mock_lisa_kv
${PRJ_ROOT}/test/common
${PRJ_ROOT}/test/utils/fff
)
target_link_libraries(tests ${UNITY_LIB})
# 允许使用CTest运行测试
enable_testing()
add_test(NAME mac_manager_tests COMMAND tests)

View File

@@ -0,0 +1,3 @@
# README
This test used to test lisa_kv config build. Not Unit test.

View File

@@ -0,0 +1,59 @@
#include "unity.h"
#include "mac_manager.h"
#include "mac_manager_mem_ops_sys_heap.h"
#include "mac_manager_content_ops_lisa_kv.h"
#include "mock_sysheap.h"
#include "mock_lisa_kv.h"
#include "fff.h"
DEFINE_FFF_GLOBALS;
static mac_manager_t *mgr;
static mac_manager_t *custom_mac_manager_init(mac_manager_config_t *config)
{
mgr = mac_manager_init(&mac_manager_mem_ops_sys_heap, &mac_manager_content_ops_lisa_kv, config);
return mgr;
}
void setUp(void)
{
mock_sysheap_init();
mock_lisa_kv_init();
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mgr = custom_mac_manager_init(&config);
}
void tearDown(void)
{
if (mgr) {
mac_manager_deinit(mgr);
mgr = NULL;
}
mock_sysheap_reset();
mock_lisa_kv_reset();
}
void test_mac_manager_lisa_kv_impl(void)
{
mac_manager_config_t config = {.random_mac_if_mac_invalid = false};
mac_manager_t *mac_mgr = mac_manager_init(&mac_manager_mem_ops_sys_heap, &mac_manager_content_ops_lisa_kv, &config);
TEST_ASSERT_NOT_NULL(mac_mgr);
mac_manager_deinit(mac_mgr);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_mac_manager_lisa_kv_impl);
return UNITY_END();
}

View File

@@ -0,0 +1,8 @@
tests:
test.mac_manager_build_only_lisa_kv:
runner: linux
builder: cmake
build_only: true
log_analyzer: "unity"

View File

@@ -0,0 +1,65 @@
cmake_minimum_required(VERSION 3.16)
project(mac_manager_test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# 配置cmake模块路径
list(APPEND CMAKE_PREFIX_PATH "/usr/local/lib/cmake")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
find_package(unity QUIET)
# 如果找到Unity包使用包提供的变量
if(unity_FOUND)
message(STATUS "Found Unity package")
set(UNITY_LIB unity::framework)
else()
message(FATAL_ERROR "Not found Unity package")
endif()
set(PRJ_ROOT ../..)
# 创建测试可执行文件
add_executable(tests)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/utils/fff
${PRJ_ROOT}/test/utils/unity_config
)
target_sources(tests PRIVATE
${PRJ_ROOT}/src/port/content/chip_id/mac_manager_content_ops_chip_id.c
)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/src/port/content/chip_id
${PRJ_ROOT}/src
)
target_sources(tests PRIVATE
test_content_chip_id.c
)
target_sources(tests PRIVATE
${PRJ_ROOT}/test/common/mock_driver_efuse/mock_Driver_EFUSE.c
${PRJ_ROOT}/test/common/freertos/mock_task.c
)
target_include_directories(tests PRIVATE
mock_driver_efuse
${PRJ_ROOT}/test/common
${PRJ_ROOT}/test/common/mock_driver_efuse
${PRJ_ROOT}/test/common/freertos
${PRJ_ROOT}/test/common/fake_lisa_log
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(tests ${UNITY_LIB})
# 允许使用CTest运行测试
enable_testing()
add_test(NAME mac_manager_tests COMMAND tests)

View File

@@ -0,0 +1,159 @@
#include "unity.h"
#include "fff.h"
#include "mac_manager_content_ops_chip_id.h"
#include "mock_Driver_EFUSE.h"
#include "mock_task.h"
DEFINE_FFF_GLOBALS;
void setUp(void) {
mock_driver_efuse_init();
mock_task_init();
}
void tearDown(void) {
mock_driver_efuse_reset();
mock_task_reset();
}
void test_content_chip_id_get(void)
{
uint8_t mac[20] = {0};
size_t mac_len = 20;
size_t expected_mac_len = 6;
uint8_t expected_mac[6] = {0x26, 0x48, 0x1A, 0xF2, 0xF4, 0xF6};
uint32_t high = 0x00F2F4F6;
uint32_t low = 0x0000001A;
efuse_read_uuid_fake.return_val = (uint64_t)high << 32 | low;
mac_manager_content_ops_chip_id.get(mac, &mac_len);
TEST_ASSERT_EQUAL_MEMORY(expected_mac, mac, mac_len);
TEST_ASSERT_EQUAL(expected_mac_len, mac_len);
}
void test_content_chip_id_random(void)
{
uint8_t mac[6] = {0};
size_t mac_len = 6;
int ret = mac_manager_content_ops_chip_id.random(mac, &mac_len);
TEST_ASSERT_EQUAL_MESSAGE(0, ret, "Random MAC generation should succeed");
TEST_ASSERT_EQUAL_MESSAGE(1, xTaskGetTickCount_fake.call_count,
"xTaskGetTickCount should be called for randomness");
TEST_ASSERT_EQUAL_MESSAGE(6, mac_len, "MAC length should be 6 bytes");
// 验证MAC头部
TEST_ASSERT_EQUAL_MESSAGE(0x26, mac[0], "First byte should be 0x26");
TEST_ASSERT_EQUAL_MESSAGE(0x48, mac[1], "Second byte should be 0x48");
// 验证2-5字节不是禁用值
for (int i = 2; i < 6; i++) {
TEST_ASSERT_NOT_EQUAL_MESSAGE(0x00, mac[i],
"MAC bytes 2-5 should not be 0x00");
TEST_ASSERT_NOT_EQUAL_MESSAGE(0xFF, mac[i],
"MAC bytes 2-5 should not be 0xFF");
}
}
void test_content_chip_id_random_with_short_mac_len(void)
{
char mac[18] = {0};
size_t mac_len = 1;
int ret = 0;
ret = mac_manager_content_ops_chip_id.random(mac, &mac_len);
TEST_ASSERT_EQUAL(-1, ret);
}
void test_content_chip_id_random_with_null_args(void)
{
int ret = 0;
size_t mac_len = 6;
char mac[6] = {0};
ret = mac_manager_content_ops_chip_id.random(NULL, NULL);
TEST_ASSERT_EQUAL(-1, ret);
ret = mac_manager_content_ops_chip_id.random(NULL, &mac_len);
TEST_ASSERT_EQUAL(-1, ret);
ret = mac_manager_content_ops_chip_id.random(mac, NULL);
TEST_ASSERT_EQUAL(-1, ret);
}
void test_content_chip_id_get_with_null_args(void)
{
int ret = 0;
size_t mac_len = 6;
char mac[6] = {0};
ret = mac_manager_content_ops_chip_id.get(NULL, NULL);
TEST_ASSERT_EQUAL(-1, ret);
ret = mac_manager_content_ops_chip_id.get(NULL, &mac_len);
TEST_ASSERT_EQUAL(-1, ret);
ret = mac_manager_content_ops_chip_id.get(mac, NULL);
TEST_ASSERT_EQUAL(-1, ret);
}
void test_content_chip_id_get_with_short_mac_len(void)
{
uint8_t mac[20] = {0};
size_t mac_len = 5;
int ret = 0;
ret = mac_manager_content_ops_chip_id.get(mac, &mac_len);
TEST_ASSERT_EQUAL(-1, ret);
}
void test_content_chip_id_set(void)
{
int ret = 0;
uint8_t mac[6] = {0};
size_t mac_len = 6;
ret = mac_manager_content_ops_chip_id.set(mac, mac_len);
// This implementation does not support set
TEST_ASSERT_EQUAL(-1, ret);
}
void test_content_chip_id_del(void)
{
int ret = 0;
ret = mac_manager_content_ops_chip_id.del();
// This implementation does not support del
TEST_ASSERT_EQUAL(-1, ret);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_content_chip_id_get);
RUN_TEST(test_content_chip_id_get_with_null_args);
RUN_TEST(test_content_chip_id_get_with_short_mac_len);
RUN_TEST(test_content_chip_id_set);
RUN_TEST(test_content_chip_id_del);
RUN_TEST(test_content_chip_id_random);
RUN_TEST(test_content_chip_id_random_with_short_mac_len);
RUN_TEST(test_content_chip_id_random_with_null_args);
return UNITY_END();
}

View File

@@ -0,0 +1,7 @@
tests:
test.port_content_chip_id:
runner: linux
builder: cmake
log_analyzer: "unity"

View File

@@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.16)
project(mac_manager_test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# 配置cmake模块路径
list(APPEND CMAKE_PREFIX_PATH "/usr/local/lib/cmake")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
find_package(unity QUIET)
# 如果找到Unity包使用包提供的变量
if(unity_FOUND)
message(STATUS "Found Unity package")
set(UNITY_LIB unity::framework)
else()
message(FATAL_ERROR "Not found Unity package")
endif()
set(PRJ_ROOT ../..)
add_executable(tests)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/utils/fff
${PRJ_ROOT}/test/utils/unity_config
)
target_sources(tests PRIVATE
${PRJ_ROOT}/src/port/content/lisa_kv/mac_manager_content_ops_lisa_kv.c
)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/src/port/content/lisa_kv
${PRJ_ROOT}/src
)
target_sources(tests PRIVATE
test_content_lisa_kv.c
)
target_sources(tests PRIVATE
${PRJ_ROOT}/test/common/mock_lisa_kv/mock_lisa_kv.c
${PRJ_ROOT}/test/common/freertos/mock_task.c
)
target_include_directories(tests PRIVATE
${PRJ_ROOT}/test/common
${PRJ_ROOT}/test/common/freertos
${PRJ_ROOT}/test/common/mock_lisa_kv
${PRJ_ROOT}/test/common/fake_lisa_log
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(tests ${UNITY_LIB})
# 允许使用CTest运行测试
enable_testing()
add_test(NAME mac_manager_tests COMMAND tests)

View File

@@ -0,0 +1,76 @@
#include "unity.h"
#include "fff.h"
#include "mac_manager_content_ops_lisa_kv.h"
#include "mock_lisa_kv.h"
#include "mock_task.h"
DEFINE_FFF_GLOBALS;
void setUp(void)
{
mock_lisa_kv_init();
mock_task_init();
}
void tearDown(void)
{
mock_lisa_kv_reset();
mock_task_reset();
}
void test_content_lisa_kv_set(void)
{
const uint8_t mac[6] = {0x26, 0x48, 0x1A, 0xF2, 0xF4, 0xF6};
size_t mac_len = 6;
int ret = 0;
ret = mac_manager_content_ops_lisa_kv.set(mac, mac_len);
TEST_ASSERT_EQUAL(1, lisa_kv_set_blob_fake.call_count);
TEST_ASSERT_EQUAL_MEMORY(mac, lisa_kv_set_blob_fake.arg1_val, lisa_kv_set_blob_fake.arg2_val);
TEST_ASSERT_EQUAL(0, ret);
}
void test_content_lisa_kv_get(void)
{
const uint8_t mac[6] = {0x26, 0x48, 0x1A, 0xF2, 0xF4, 0xF6};
uint8_t mac_get[6] = {0};
size_t mac_len = 6;
int ret = 0;
mac_manager_content_ops_lisa_kv.set(mac, mac_len);
ret = mac_manager_content_ops_lisa_kv.get(mac_get, &mac_len);
TEST_ASSERT_EQUAL(1, lisa_kv_get_blob_fake.call_count);
TEST_ASSERT_EQUAL_MEMORY(mac, mac_get, mac_len);
TEST_ASSERT_EQUAL(0, ret);
}
void test_content_lisa_kv_free_after_get(void)
{
const uint8_t mac[6] = {0x26, 0x48, 0x1A, 0xF2, 0xF4, 0xF6};
size_t mac_len = 6;
uint8_t mac_get[6] = {0};
int ret = 0;
mac_manager_content_ops_lisa_kv.set(mac, mac_len);
ret = mac_manager_content_ops_lisa_kv.get(mac_get, &mac_len);
TEST_ASSERT_EQUAL(1, lisa_kv_free_fake.call_count);
TEST_ASSERT_EQUAL(0, ret);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_content_lisa_kv_set);
RUN_TEST(test_content_lisa_kv_get);
RUN_TEST(test_content_lisa_kv_free_after_get);
return UNITY_END();
}

View File

@@ -0,0 +1,7 @@
tests:
test.port_content_lisa_kv:
runner: linux
builder: cmake
log_analyzer: "unity"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
/* Unity配置文件 */
#ifndef UNITY_CONFIG_H
#define UNITY_CONFIG_H
#include <stdio.h>
/* 自定义配置 */
#define UNITY_OUTPUT_CHAR(a) putchar(a)
#define UNITY_OUTPUT_FLUSH() fflush(stdout)
#define UNITY_OUTPUT_START() printf("\n\n")
#define UNITY_OUTPUT_COMPLETE() printf("\n")
#endif /* UNITY_CONFIG_H */