Files
MeowOS-SDK/sdk/test_meow_ui_config.c
T
MeowOS f44e3bc6d0 Add 'sdk/' from commit '2e7561d74f75de05dd7fb362f203f600afb451d7'
git-subtree-dir: sdk
git-subtree-mainline: 17a972d46f
git-subtree-split: 2e7561d74f
2026-09-01 21:08:40 +08:00

127 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* test_meow_ui_config.c — meow_config_* 宿主单测(2026-08-30)。
*
* 编译(宿主,config 为纯 libc,无需 SDK 其它对象):
* gcc -Wall -Wextra test_meow_ui_config.c meow_ui_config.c -o test_meow_ui_config -lpthread
*
* 两种模式(meow_config_dir 经 pthread_once 缓存,目录只在首次调用确定,故分两次跑):
* ./test_meow_ui_config env → 设 MEOW_DATA_DIR=<mkdtemp>,验证持久目录读写
* ./test_meow_ui_config tmp → unsetenv MEOW_DATA_DIR,验证 /tmp/meowcfg_<pid> 回退
*
* 任一断言失败 → 打印 FAIL 并以非零退出码结束。
*/
#include "meow_ui.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int g_fail = 0;
#define CHECK(cond, msg) do { \
if (cond) { printf(" PASS: %s\n", msg); } \
else { printf(" FAIL: %s\n", msg); g_fail = 1; } \
} while (0)
int main(int argc, char **argv)
{
const char *mode = (argc > 1) ? argv[1] : "env";
char *tmpdir = NULL;
if (strcmp(mode, "tmp") == 0) {
unsetenv("MEOW_DATA_DIR");
} else {
tmpdir = strdup("/tmp/meowcfgtestXXXXXX");
if (!mkdtemp(tmpdir)) { printf("FATAL: mkdtemp failed\n"); return 2; }
setenv("MEOW_DATA_DIR", tmpdir, 1);
}
printf("== meow_config test [%s] ==\n", mode);
const char *dir = meow_config_dir();
CHECK(dir != NULL, "meow_config_dir() 非 NULL");
printf(" dir = %s\n", dir ? dir : "(null)");
if (strcmp(mode, "tmp") == 0)
CHECK(dir && strstr(dir, "/tmp/meowcfg_") != NULL, "tmp 回退目录为 /tmp/meowcfg_<pid>");
else
CHECK(dir && strcmp(dir, tmpdir) == 0, "env 目录 = MEOW_DATA_DIR");
/* --- set/get 往返 --- */
CHECK(meow_config_set("k1", "hello") == MEOW_CFG_OK, "set k1=hello -> MEOW_CFG_OK");
char buf[128];
CHECK(meow_config_get("k1", buf, sizeof buf) == MEOW_CFG_OK, "get k1 -> MEOW_CFG_OK");
CHECK(strcmp(buf, "hello") == 0, "get k1 值 = hello");
/* --- 全数字 int / bool 解析 --- */
meow_config_set("num", "42");
CHECK(meow_config_int("num", -1) == 42, "int(num)=42");
meow_config_set("truth", "true");
CHECK(meow_config_bool("truth", 0) == 1, "bool(true)=1");
meow_config_set("lie", "off");
CHECK(meow_config_bool("lie", 1) == 0, "bool(off)=0");
CHECK(meow_config_int("nonnum", 7) == 7, "int 非数字 -> def");
CHECK(meow_config_bool("nonbool", 3) == 3, "bool 非法 -> def");
/* --- 未设键 --- */
CHECK(meow_config_get("absent", buf, sizeof buf) == MEOW_CFG_ERR_NOENT, "get 未设键 -> MEOW_CFG_ERR_NOENT");
CHECK(meow_config_int("absent", 9) == 9, "int 未设键 -> def");
CHECK(meow_config_bool("absent", 1) == 1, "bool 未设键 -> def");
/* --- int 便捷写(经 set)再读 --- */
char nbuf[16];
meow_config_get("num", nbuf, sizeof nbuf);
CHECK(strcmp(nbuf, "42") == 0, "int 存储为十进制 '42'");
/* --- 空值(NULL=清空为 0 字节文件,与「未设」区分)--- */
meow_config_set("empty", "");
CHECK(meow_config_get("empty", buf, sizeof buf) == MEOW_CFG_OK, "get 空值键 -> MEOW_CFG_OK");
CHECK(buf[0] == '\0', "空值键读回空串");
CHECK(meow_config_get("empty", buf, sizeof buf) != MEOW_CFG_ERR_NOENT, "空值键 ≠ 未设");
/* --- remove --- */
meow_config_remove("k1");
CHECK(meow_config_get("k1", buf, sizeof buf) == MEOW_CFG_ERR_NOENT, "remove 后 get -> NOENT");
/* --- key 清洗:'/' 等非法字符替换为 '_',杜绝路径穿越 --- */
meow_config_set("a/b", "slash");
CHECK(meow_config_get("a_b", buf, sizeof buf) == MEOW_CFG_OK && strcmp(buf, "slash") == 0,
"key 'a/b' 清洗为 'a_b'");
/* 路径穿越尝试:key 含 '/' 的非法串,不得逃出数据目录('/'→'_','.' 保留为字面量)。 */
meow_config_set("../../etc/passwd", "evil");
CHECK(meow_config_get(".._.._etc_passwd", buf, sizeof buf) == MEOW_CFG_OK &&
strcmp(buf, "evil") == 0, "key '../../etc/passwd' 清洗为 '.._.._etc_passwd'('/'→'_',无穿越)");
/* --- 参数校验 --- */
CHECK(meow_config_get(NULL, buf, sizeof buf) == MEOW_CFG_ERR_INVAL, "get(NULL) -> INVAL");
CHECK(meow_config_get("x", NULL, 10) == MEOW_CFG_ERR_INVAL, "get(out=NULL) -> INVAL");
CHECK(meow_config_get("x", buf, 0) == MEOW_CFG_ERR_INVAL, "get(outsz=0) -> INVAL");
CHECK(meow_config_set("", "v") == MEOW_CFG_ERR_INVAL, "set(空 key) -> INVAL");
/* --- 多键独立 --- */
meow_config_set("ind.a", "1");
meow_config_set("ind.b", "2");
meow_config_get("ind.a", buf, sizeof buf);
CHECK(strcmp(buf, "1") == 0, "多键独立 a");
meow_config_get("ind.b", buf, sizeof buf);
CHECK(strcmp(buf, "2") == 0, "多键独立 b");
meow_config_remove("ind.a");
meow_config_get("ind.b", buf, sizeof buf);
CHECK(strcmp(buf, "2") == 0, "删除 a 不影响 b");
/* --- 值截断(>MEOW_CFG_VAL_MAX 4096 截断;读合法)--- */
{
char big[4096 * 2];
char rbuf[4100];
memset(big, 'A', sizeof big - 1);
big[sizeof big - 1] = '\0';
meow_config_set("big", big);
meow_config_get("big", rbuf, sizeof rbuf);
CHECK(strlen(rbuf) == 4096, "值 >4096 截断为 4096");
}
if (tmpdir) free(tmpdir);
if (g_fail) { printf("\nRESULT: FAIL (%d)\n", g_fail); return 1; }
printf("\nRESULT: ALL PASS\n");
return 0;
}