1 Commits

Author SHA1 Message Date
thead_admin
d6e05608be Linux_SDK_V1.1.2 2023-03-09 14:44:15 +08:00
17 changed files with 751 additions and 70 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
!.gitignore
*.o
out_*
buildout
build
output
install.sh
make.sh

34
CMakeLists.txt Normal file
View File

@@ -0,0 +1,34 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
cmake_minimum_required(VERSION 3.5.1)
project(prd_utils C)
set(CMAKE_C_STANDARD 99)
# Add fpic
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# Board Selection
if (${BOARD_NAME} MATCHES "light*")
set(BOARD_NAME "light")
include(cmake/board_light.cmake)
else ()
message(FATAL_ERROR, "No BOARD_NAME")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -Wall -g")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined")
include(cmake/show_cmake_param.cmake)
# Add include dirs for all sub modules
include_directories(${PROJECT_BINARY_DIR})
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(platform/${BOARD_NAME})
add_subdirectory(utils)
add_subdirectory(test)
install(FILES ${INSTALL_HEAD_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@@ -1,36 +0,0 @@
# prd-utils
#### Description
product produce utilities
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@@ -1,37 +1,20 @@
# prd-utils
# Comments
This is utilities for product produce process, including:
- utils for set/get/clean Key-Value
#### 介绍
product produce utilities
# How to get the code
- git clone git@gitlab.alibaba-inc.com:thead-linux/prd_utils.git
#### 软件架构
软件架构说明
# How to build
1. export PATH=riscv-toolchain-2.2.8/bin:$PATH
2. mkdir build
3. cd buildout
4. cmake ../ -DBOARD_NAME="light" -DCMAKE_INSTALL_BINDIR=bin -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_INCLUDEDIR=include -DCMAKE_C_COMPILER=gcc
5. make
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
# Description of each directories
- cmake/: The cmake files for build.
- include/: The header files.
- platform/: Different platform implementation code directories.
- test/: The test cases.
- utils/: The utils using in console.

6
cmake/board_light.cmake Normal file
View File

@@ -0,0 +1,6 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
SET(CMAKE_C_COMPILER riscv64-linux-gcc)
SET(CMAKE_CXX_COMPILER riscv64-linux-c++)

11
cmake/custom_macros.cmake Normal file
View File

@@ -0,0 +1,11 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
macro(BuildNormalProgram sourceName)
set(TargetName ${sourceName})
set(target_src ${sourceName}.c)
add_executable(${TargetName} ${target_src})
target_link_libraries(${TargetName} ${linkLibs})
endmacro(BuildNormalProgram)

View File

@@ -0,0 +1,19 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
message("")
message("=== Show cmake system paramerters ===")
message(STATUS "PROJECT_NAME = ${PROJECT_NAME}")
message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR = ${PROJECT_BINARY_DIR}")
message(STATUS "CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS "CMAKE_SYSTEM = ${CMAKE_SYSTEM}")
message(STATUS "CMAKE_C_COMPILER = ${CMAKE_C_COMPILER}")
message(STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}")
message(STATUS "CMAKE_SHARED_LINKER_FLAGS = ${CMAKE_SHARED_LINKER_FLAGS}")
message(STATUS "BOARD_NAME = ${BOARD_NAME}")
message(STATUS "CMAKE_INSTALL_LIBDIR = ${CMAKE_INSTALL_LIBDIR}")
message("")

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#ifndef PRD_UTILS_INTERNAL_H
#define PRD_UTILS_INTERNAL_H
#include <errno.h>
#define MKTAG_NEGA(e) (-(e))
#define LOG_COLOR_RED_YELLO_BACK "\033[1;31;43m"
#define LOG_COLOR_RED "\033[2;31;49m"
#define LOG_COLOR_YELLOW "\033[2;33;49m"
#define LOG_COLOR_GREEN "\033[2;32;49m"
#define LOG_COLOR_BLUE "\033[2;34;49m"
#define LOG_COLOR_GRAY "\033[1;30m"
#define LOG_COLOR_WHITE "\033[1;47;49m"
#define LOG_COLOR_RESET "\033[0m"
#define PRD_UTILS_LOG(fmt, args...) \
do {printf("[%s():%d] ",__FUNCTION__, __LINE__); printf(fmt,##args);} while(0)
#define PRD_UTILS_ASSERT(expr) \
do { \
if (!(expr)) { \
printf(LOG_COLOR_RED \
"\nASSERT failed at:\n"\
" >File name: %s\n" \
" >Function : %s\n" \
" >Line No. : %d\n" \
" >Condition: %s\n" \
LOG_COLOR_RESET, \
__FILE__,__FUNCTION__, __LINE__, #expr);\
exit(-1); \
} \
} while(0)
#endif /* PRD_UTILS_INTERNAL_H */

30
include/prd_utils_kv.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#ifndef PRD_UTILS_KV_H
#define PRD_UTILS_KV_H
#define PRD_UTILS_KEY_MAX_LENGTH 64
#define PRD_UTILS_VAL_MAX_LENGTH 256
#define PRD_UTILS_KV_MAX_COUNT 128
#define PRD_UTILS_KEY_NAME_ETH_ADDR "ethaddr"
#define PRD_UTILS_KEY_NAME_SN "sn"
typedef enum {
PRD_UTILS_RESULT_OK = 0,
PRD_UTILS_RESULT_KV_INPUT_INVALID = -1,
PRD_UTILS_RESULT_KV_IO_FAILED = -2,
PRD_UTILS_RESULT_KV_NOT_EXIST = -3,
} prd_utils_result_e;
// Notice:
// 1. input key CAN'T including space or other non-printable charater
// 2. input value CAN'T including any non-printable charater
int prd_utils_get_kv(char *key, char **value);
int prd_utils_set_kv(char *key, char *value);
int prd_utils_clean_kv(char *key);
#endif /* PRD_UTILS_KV_H */

View File

@@ -0,0 +1,20 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
# include
INCLUDE_DIRECTORIES(./)
SET(LIBSOURCE
prd_utils_kv_light.c
uboot_env_params.c
)
ADD_LIBRARY(prd_utils SHARED ${LIBSOURCE})
INSTALL(DIRECTORY ./include/. DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
INSTALL(TARGETS prd_utils
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <prd_utils_kv.h>
#include <prd_utils_internal.h>
#include "uboot_env_params.h"
#define CHECK_KEY_VALID(key) \
do { \
if (key == NULL || strlen(key) >= PRD_UTILS_KEY_MAX_LENGTH) \
{ \
PRD_UTILS_LOG("key is NULL or key len > %d\n", PRD_UTILS_KEY_MAX_LENGTH); \
return PRD_UTILS_RESULT_KV_INPUT_INVALID; \
} \
} while (0)
#define CHECK_VAL_VALID(val) \
do { \
if (val == NULL || strlen(val) >= PRD_UTILS_VAL_MAX_LENGTH) \
{ \
PRD_UTILS_LOG("val is NULL or val len > %d\n", PRD_UTILS_VAL_MAX_LENGTH); \
return PRD_UTILS_RESULT_KV_INPUT_INVALID; \
} \
} while (0)
int prd_utils_get_kv(char *key, char **value)
{
CHECK_KEY_VALID(key);
return light_uboot_get_env(key, value);
}
int prd_utils_set_kv(char *key, char *value)
{
CHECK_KEY_VALID(key);
CHECK_VAL_VALID(value);
return light_uboot_set_env(key, value);
}
int prd_utils_clean_kv(char *key)
{
CHECK_KEY_VALID(key);
return light_uboot_clean_env(key);
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <prd_utils_kv.h>
#include <prd_utils_internal.h>
#include "uboot_env_params.h"
static char g_result[PRD_UTILS_VAL_MAX_LENGTH] = "";
static int execmd_fetch_result_string(const char *cmd, char *result)
{
char buffer[PRD_UTILS_VAL_MAX_LENGTH];
FILE *pipe = popen(cmd, "r");
if (pipe == NULL)
{
return -1;
}
while(!feof(pipe))
{
if(fgets(buffer, PRD_UTILS_VAL_MAX_LENGTH, pipe))
{
strcat(result, buffer);
if(strlen(result) >= PRD_UTILS_VAL_MAX_LENGTH)
break;
}
}
pclose(pipe);
return 0;
}
int light_uboot_get_env(const char *key, char **value)
{
char cmd[128 + PRD_UTILS_KEY_MAX_LENGTH] ="";
memset(g_result, 0, sizeof(g_result));
snprintf(cmd, sizeof(cmd),
"fw_printenv | grep '%s=' | awk -F '=' '{print $2}' | tr -d '\n' '\r'", key);
if (execmd_fetch_result_string(cmd, g_result) == 0)
{
*value = g_result;
if (strlen(*value) == 0)
{
//PRD_UTILS_LOG("light_uboot_get_env() failed, return enmpty value\n");
return PRD_UTILS_RESULT_KV_NOT_EXIST;
}
return PRD_UTILS_RESULT_OK;
}
else
{
*value = NULL;
//PRD_UTILS_LOG("light_uboot_get_env() failed\n");
return PRD_UTILS_RESULT_KV_IO_FAILED;
}
}
int light_uboot_set_env(const char *key, char *value)
{
char cmd[128 + PRD_UTILS_KEY_MAX_LENGTH + PRD_UTILS_VAL_MAX_LENGTH] ="";
snprintf(cmd, sizeof(cmd), "fw_setenv %s '%s'", key, value);
if (system(cmd) != 0)
{
PRD_UTILS_LOG("execute cmd='%s' failed\n", cmd);
return PRD_UTILS_RESULT_KV_IO_FAILED;
}
return PRD_UTILS_RESULT_OK;
}
int light_uboot_clean_env(const char *key)
{
char cmd[128 + PRD_UTILS_KEY_MAX_LENGTH] = "";
snprintf(cmd, sizeof(cmd), "fw_setenv %s", key);
if (system(cmd) != 0)
{
PRD_UTILS_LOG("execute cmd='%s' failed\n", cmd);
return PRD_UTILS_RESULT_KV_IO_FAILED;
}
return PRD_UTILS_RESULT_OK;
}

View File

@@ -0,0 +1,12 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#ifndef UBOOT_ENV_PARAMS_H
#define UBOOT_ENV_PARAMS_H
int light_uboot_get_env(const char *key, char **value);
int light_uboot_set_env(const char *key, char *value);
int light_uboot_clean_env(const char *key);
#endif /* UBOOT_ENV_PARAMS_H */

12
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,12 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
include(${PROJECT_SOURCE_DIR}/cmake/custom_macros.cmake)
# Config all parameters for test cases below
set(linkLibs prd_utils)
# test factory param
BuildNormalProgram(test_prd_utils_kv)

254
test/test_prd_utils_kv.c Normal file
View File

@@ -0,0 +1,254 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/time.h>
#include <prd_utils_kv.h>
#include <prd_utils_internal.h>
#define KV_OP_MAX_DURATION 100 // unit: ms
static char test_key[] = "test_key";
static char test_val[] = "test value with spaces";
static char max_length_key[PRD_UTILS_KEY_MAX_LENGTH] =
"12345678901234567890123456789012345678901234567890" \
"1234567890123";
static char max_length_val[PRD_UTILS_VAL_MAX_LENGTH] =
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345";
typedef struct test_performance_records
{
// unit: us
int normal_set;
int normal_get;
int normal_clean;
int max_len_set;
int max_len_get;
int max_len_clean;
// tmp values
struct timeval tpstart;
struct timeval tpend;
} test_performance_records_t;
static test_performance_records_t perf_records;
#define GET_TIME_BEGIN() do { gettimeofday(&perf_records.tpstart, NULL); } while(0)
#define GET_TIME_RECORD(target) do { gettimeofday(&perf_records.tpend, NULL); \
target = 1000000 * (perf_records.tpend.tv_sec - perf_records.tpstart.tv_sec) \
+ perf_records.tpend.tv_usec - perf_records.tpstart.tv_usec; \
} while (0)
static int test_prd_utils_set_kv()
{
printf("Test: prd_utils_set_kv() start\n");
GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_set_kv(test_key, test_val) == PRD_UTILS_RESULT_OK);
GET_TIME_RECORD(perf_records.normal_set);
printf("Test: prd_utils_set_kv() pass\n\n");
return 0;
}
static int test_prd_utils_get_kv()
{
char *get_val;
printf("Test: prd_utils_get_kv() start\n");
GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_OK);
GET_TIME_RECORD(perf_records.normal_get);
PRD_UTILS_ASSERT(strncmp(test_val, get_val, PRD_UTILS_VAL_MAX_LENGTH) == 0);
printf("Test: prd_utils_get_kv() pass\n\n");
return 0;
}
static int test_prd_utils_clean_kv()
{
char *get_val;
printf("Test: prd_utils_clean_kv() start\n");
GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_clean_kv(test_key) == PRD_UTILS_RESULT_OK);
GET_TIME_RECORD(perf_records.normal_clean);
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_KV_NOT_EXIST);
printf("Test: prd_utils_clean_kv() pass\n\n");
return 0;
}
static int test_prd_utils_max_kv_value_length()
{
char *get_val;
printf("Test: max value length(%u) start\n", PRD_UTILS_VAL_MAX_LENGTH);
PRD_UTILS_ASSERT(strlen(max_length_val) == PRD_UTILS_VAL_MAX_LENGTH - 1);
PRD_UTILS_ASSERT(prd_utils_set_kv(test_key, max_length_val) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(strncmp(max_length_val, get_val, PRD_UTILS_VAL_MAX_LENGTH) == 0);
PRD_UTILS_ASSERT(prd_utils_clean_kv(test_key) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_KV_NOT_EXIST);
printf("Test: max value length(%u) pass\n\n", PRD_UTILS_VAL_MAX_LENGTH);
return 0;
}
static int test_prd_utils_max_kv_key_length()
{
char *get_val;
printf("Test: max key length(%u) start\n", PRD_UTILS_KEY_MAX_LENGTH);
PRD_UTILS_ASSERT(strlen(max_length_key) == PRD_UTILS_KEY_MAX_LENGTH - 1);
PRD_UTILS_ASSERT(prd_utils_set_kv(max_length_key, test_val) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(prd_utils_get_kv(max_length_key, &get_val) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(strncmp(test_val, get_val, PRD_UTILS_VAL_MAX_LENGTH) == 0);
PRD_UTILS_ASSERT(prd_utils_clean_kv(max_length_key) == PRD_UTILS_RESULT_OK);
PRD_UTILS_ASSERT(prd_utils_get_kv(max_length_key, &get_val) == PRD_UTILS_RESULT_KV_NOT_EXIST);
printf("Test: max key length(%u) pass\n\n", PRD_UTILS_KEY_MAX_LENGTH);
return 0;
}
static int test_prd_utils_max_kv_capacity()
{
char *get_val;
char test_key[PRD_UTILS_KEY_MAX_LENGTH];
char test_val[PRD_UTILS_VAL_MAX_LENGTH];
printf("Test: max kv capacity(key_len=%u, val_len=%u, count=%u) start\n",
PRD_UTILS_KEY_MAX_LENGTH, PRD_UTILS_VAL_MAX_LENGTH, PRD_UTILS_KV_MAX_COUNT);
const int test_loop_count = PRD_UTILS_KV_MAX_COUNT;
// set KVs
printf(" step1. testing set max kv(loop=%d):\n ", test_loop_count);
for (int i = 0; i < test_loop_count; i++)
{
//snprintf(test_key, PRD_UTILS_KEY_MAX_LENGTH, test_key_long_fmt, i);
snprintf(test_key, PRD_UTILS_KEY_MAX_LENGTH,
"12345678901234567890123456789012345678901234567890123456789_%03d", i);
PRD_UTILS_ASSERT(strlen(test_key) == PRD_UTILS_KEY_MAX_LENGTH - 1);
snprintf(test_val, PRD_UTILS_VAL_MAX_LENGTH,
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"1_%03d", i);
PRD_UTILS_ASSERT(strlen(test_val) == PRD_UTILS_VAL_MAX_LENGTH - 1);
if (i == 0) GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_set_kv(test_key, test_val) == PRD_UTILS_RESULT_OK);
if (i == 0) GET_TIME_RECORD(perf_records.max_len_set);
printf("."); fflush(stdout); if (i % 64 == 63) printf("\n ");
}
// get KVs and verify, clean
printf("step2. testing get max kv(loop=%d):\n ", test_loop_count);
for (int i = 0; i < test_loop_count; i++)
{
snprintf(test_key, PRD_UTILS_KEY_MAX_LENGTH,
"12345678901234567890123456789012345678901234567890123456789_%03d", i);
snprintf(test_val, PRD_UTILS_VAL_MAX_LENGTH,
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890" \
"1_%03d", i);
if (i == 0) GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_OK);
if (i == 0) GET_TIME_RECORD(perf_records.max_len_get);
PRD_UTILS_ASSERT(strncmp(test_val, get_val, PRD_UTILS_VAL_MAX_LENGTH) == 0);
printf("."); fflush(stdout); if (i % 64 == 63) printf("\n ");
}
// clean KVs
printf("step3. testing clean max kv(loop=%d):\n ", test_loop_count);
for (int i = 0; i < test_loop_count; i++)
{
snprintf(test_key, PRD_UTILS_KEY_MAX_LENGTH,
"12345678901234567890123456789012345678901234567890123456789_%03d", i);
if (i == 0) GET_TIME_BEGIN();
PRD_UTILS_ASSERT(prd_utils_clean_kv(test_key) == PRD_UTILS_RESULT_OK);
if (i == 0) GET_TIME_RECORD(perf_records.max_len_clean);
PRD_UTILS_ASSERT(prd_utils_get_kv(test_key, &get_val) == PRD_UTILS_RESULT_KV_NOT_EXIST);
printf("."); fflush(stdout); if (i % 64 == 63) printf("\n ");
}
printf("Test: max kv capacity(key_len=%u, val_len=%u, count=%u) pass\n\n",
PRD_UTILS_KEY_MAX_LENGTH, PRD_UTILS_VAL_MAX_LENGTH, PRD_UTILS_KV_MAX_COUNT);
return 0;
}
int main(int argc, char *argv[])
{
// test normal usage
PRD_UTILS_ASSERT(test_prd_utils_set_kv() == 0);
PRD_UTILS_ASSERT(test_prd_utils_get_kv() == 0);
PRD_UTILS_ASSERT(test_prd_utils_clean_kv() == 0);
// test max length
PRD_UTILS_ASSERT(test_prd_utils_max_kv_value_length() == 0);
PRD_UTILS_ASSERT(test_prd_utils_max_kv_key_length() == 0);
// test max capacity
PRD_UTILS_ASSERT(test_prd_utils_max_kv_capacity() == 0);
// print performance
printf("==== prd_utils performance test results ====================\n");
printf(" normal set_kv(key_len=%zu, val_len=%zu) cost %.3f ms\n",
strlen(test_key), strlen(test_val), (1.0 * perf_records.normal_set) / 1000);
printf(" normal get_kv(key_len=%zu, val_len=%zu) cost %.3f ms\n",
strlen(test_key), strlen(test_val), (1.0 * perf_records.normal_get) / 1000);
printf(" normal clean_kv(key_len=%zu, val_len=%zu) cost %.3f ms\n",
strlen(test_key), strlen(test_val), (1.0 * perf_records.normal_clean) / 1000);
printf(" max_len set_kv(key_len=%u, val_len=%u) cost %.3f ms\n",
PRD_UTILS_KEY_MAX_LENGTH, PRD_UTILS_VAL_MAX_LENGTH, (1.0 * perf_records.max_len_set) / 1000);
printf(" max_len get_kv(key_len=%u, val_len=%u) cost %.3f ms\n",
PRD_UTILS_KEY_MAX_LENGTH, PRD_UTILS_VAL_MAX_LENGTH, (1.0 * perf_records.max_len_get) / 1000);
printf(" max_len clean_kv(key_len=%u, val_len=%u) cost %.3f ms\n",
PRD_UTILS_KEY_MAX_LENGTH, PRD_UTILS_VAL_MAX_LENGTH, (1.0 * perf_records.max_len_clean) / 1000);
printf("============================================================\n");
PRD_UTILS_ASSERT(perf_records.normal_set/1000 < KV_OP_MAX_DURATION &&
perf_records.normal_get/1000 < KV_OP_MAX_DURATION &&
perf_records.normal_clean/1000 < KV_OP_MAX_DURATION &&
perf_records.max_len_set/1000 < KV_OP_MAX_DURATION &&
perf_records.max_len_get/1000 < KV_OP_MAX_DURATION &&
perf_records.max_len_clean/1000 < KV_OP_MAX_DURATION);
printf(LOG_COLOR_GREEN "All KV tests PASSED\n" LOG_COLOR_RESET);
return 0;
}

12
utils/CMakeLists.txt Normal file
View File

@@ -0,0 +1,12 @@
#
# Copyright (C) 2023 Alibaba Group Holding Limited
#
include(${PROJECT_SOURCE_DIR}/cmake/custom_macros.cmake)
# Config all parameters for test cases below
set(linkLibs prd_utils)
# test factory param
BuildNormalProgram(prd_utils_kv)

128
utils/prd_utils_kv.c Normal file
View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <prd_utils_kv.h>
#define PROGRAM_NAME "prd_utils_kv"
typedef struct
{
int op_code; /* 0: set, 1:get; 2: clean */
char key[PRD_UTILS_KEY_MAX_LENGTH];
char val[PRD_UTILS_VAL_MAX_LENGTH];
} cmd_params_s;
static const char *shortopts = "hs:g:c:";
static const struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"SetParam", required_argument, 0, 's'},
{"GetParam", required_argument, 0, 'g'},
{"CleanParam", required_argument, 0, 'c'},
{0, 0, 0, 0 } // Act as end of option
};
static void usage(char *program_name)
{
printf("Usage: %s [OPTION]\n", program_name);
printf(" -h, --help display this help and exit\n");
printf(" -s, --SetParam set param, for example: %s -s sn=123456abcde\n", program_name);
printf(" -g, --GetParam get param, for example: %s -g sn\n", program_name);
printf(" -c, --CleanParam clean param, for example: %s -c sn\n", program_name);
}
static int parse_params(int argc, char *argv[], cmd_params_s *params)
{
int c;
int option_index = 0;
int option_count = 0;
char *program_name = PROGRAM_NAME;
char *equal_sign;
int pos;
while ((c = getopt_long(argc, argv, shortopts, long_options, &option_index)) != -1)
{
switch (c)
{
case 'h':
usage(program_name);
exit(0);
case 's':
params->op_code = 0;
equal_sign = strchr(optarg, '=');
if (equal_sign == NULL)
{
printf("command is invalid, please flow:\n");
usage(program_name);
exit(-1);
}
pos = equal_sign - optarg;
strncpy(params->key, optarg, pos);
strncpy(params->val, optarg + pos + 1, strlen(optarg) - pos);
option_count++;
break;
case 'g':
params->op_code = 1;
sscanf(optarg, "%s", params->key);
option_count++;
break;
case 'c':
params->op_code = 2;
sscanf(optarg, "%s", params->key);
option_count++;
break;
default:
printf("Not supported opt:'%c'\n", c);
return -1;
}
}
return option_count;
}
int main(int argc, char *argv[])
{
int ret;
char *val;
cmd_params_s cmd_params;
memset(&cmd_params, 0, sizeof(cmd_params));
int option_count = parse_params(argc, argv, &cmd_params);
if (option_count == 0)
{
usage(PROGRAM_NAME);
exit(0);
}
switch (cmd_params.op_code)
{
case 0: // set
ret = prd_utils_set_kv(cmd_params.key, cmd_params.val);
printf("set '%s'='%s' %s\n", cmd_params.key, cmd_params.val, (ret == 0) ? "OK" : "failed");
break;
case 1: // get
ret = prd_utils_get_kv(cmd_params.key, &val);
if (ret != 0)
{
printf("get sys param '%s' failed\n", cmd_params.key);
return ret;
}
printf("Got sys param '%s'='%s'\n", cmd_params.key, val);
break;
case 2: // clean;
ret = prd_utils_clean_kv(cmd_params.key);
printf("clean sys param '%s' %s\n", cmd_params.key, (ret == 0) ? "OK" : "failed");
break;
}
return 0;
}