/* * test_meow_ui_vol.c — 宿主单元测试:SDK 状态栏音量换算纯函数 + settings.conf 读取。 * * 直接编译 meow_ui_vol.c(纯函数,无 meow_ui 依赖),用临时 settings 文件验证: * V1 解析:launcher 落盘 "key = value"(带空格)形式能正确读到值(根因回归—— * 旧代码朴素前缀匹配 "audio.volume=" 永远读不到 → 卡默认 60); * V2 解析:无空格 "key=value" / 多空格 / 头注释行 / 键缺失回退默认 / 精确匹配 * (audio.volume 不误配 audio.volume_max); * V3 clamp:volume_max 上限、硬上限 100、负值兜底 0、上限异常(<0)兜底 0; * V4 管道(镜像 meow_ui_sys.c settings_vol):读 + clamp 到 volume_max; * V5 展示串:与 meow_ui_sys.c statusbar_right_str 同款 "VOL %d%%",断言显示值即 * 当前夹后音量(含 step 语义:a.volume_step 只决定步进,展示原样不/舍入)。 * * 编译(宿主 gcc,mipsel 无关): * gcc -o test_meow_ui_vol test_meow_ui_vol.c meow_ui_vol.c -I. */ #include "meow_ui_vol.h" #include #include #include #include static int failures = 0; static void check(const char *name, int cond) { printf("%s %s\n", cond ? "PASS" : "FAIL", name); if (!cond) failures++; } /* 写一份临时 settings 文件(lines 为已含 '\n' 的行内容;NULL 结束) */ static const char *tmp_path; static void write_settings(const char **lines) { FILE *f = fopen(tmp_path, "w"); if (!f) { perror("fopen"); exit(2); } for (int i = 0; lines[i]; i++) fputs(lines[i], f); fclose(f); } /* 镜像 meow_ui_sys.c 的 settings_vol():读 audio.volume + volume_max,再 clamp。 */ static int settings_vol_of(const char *path) { int vol = meow_ui_vol_read(path, "audio.volume", MEOW_UI_VOL_DEFAULT); int vol_max = meow_ui_vol_read(path, "audio.volume_max", MEOW_UI_VOL_MAX_DEF); return meow_ui_vol_clamp(vol, vol_max); } /* 状态栏右侧 VOL 串组装(与 meow_ui_sys.c statusbar_right_str 同款)。 */ static void vol_display(int vol, int vol_max, char *out, size_t n) { snprintf(out, n, "VOL %d%%", meow_ui_vol_clamp(vol, vol_max)); } int main(void) { char base[64]; snprintf(base, sizeof base, "/tmp/meow_vol_%d.conf", (int)getpid()); tmp_path = base; /* ---- V1 解析:launcher 落盘格式 "key = value"(带空格)——根因回归 ---- */ { const char *L[] = { "# meow-settings 1\n", "audio.volume = 82\n", NULL }; write_settings(L); check("V1 launcher 空格格式 audio.volume=82 -> 82", meow_ui_vol_read(tmp_path, "audio.volume", -1) == 82); } /* ---- V2 解析:无空格 / 多空格 / 注释 / 缺键 / 精确匹配 ---- */ { const char *L[] = { "audio.volume=40\n", NULL }; write_settings(L); check("V2 无空格 audio.volume=40 -> 40", meow_ui_vol_read(tmp_path, "audio.volume", -1) == 40); const char *L2[] = { " audio.volume = 7 \n", NULL }; write_settings(L2); check("V2 多空格 audio.volume = 7 -> 7", meow_ui_vol_read(tmp_path, "audio.volume", -1) == 7); const char *L3[] = { "display.brightness = 100\n", NULL }; write_settings(L3); check("V2 键缺失 -> 默认 -1", meow_ui_vol_read(tmp_path, "audio.volume", -1) == -1); const char *L4[] = { "audio.volume_max = 90\n", NULL }; write_settings(L4); check("V2 audio.volume 不误配 audio.volume_max -> 默认", meow_ui_vol_read(tmp_path, "audio.volume", -1) == -1); check("V2 单独读 audio.volume_max=90 -> 90", meow_ui_vol_read(tmp_path, "audio.volume_max", -1) == 90); } /* ---- V3 clamp 纯函数 ---- */ check("V3 clamp(60,100)=60", meow_ui_vol_clamp(60, 100) == 60); check("V3 clamp(80,60)=60 (尊重 volume_max)", meow_ui_vol_clamp(80, 60) == 60); check("V3 clamp(80,100)=80", meow_ui_vol_clamp(80, 100) == 80); check("V3 clamp(150,100)=100 (硬上限)", meow_ui_vol_clamp(150, 100) == 100); check("V3 clamp(150,80)=80", meow_ui_vol_clamp(150, 80) == 80); check("V3 clamp(-5,100)=0 (负值兜底)", meow_ui_vol_clamp(-5, 100) == 0); check("V3 clamp(60,0)=0 (上限 0)", meow_ui_vol_clamp(60, 0) == 0); check("V3 clamp(60,-10)=0 (上限异常兜底)", meow_ui_vol_clamp(60, -10) == 0); check("V3 clamp(120,255)=100 (硬上限优先于大上限)", meow_ui_vol_clamp(120, 255) == 100); /* ---- V4 管道:读 + clamp 到 volume_max(镜像 settings_vol)---- */ { const char *L[] = { "audio.volume = 82\n", "audio.volume_max = 100\n", NULL }; write_settings(L); check("V4 vol=82 max=100 -> 82", settings_vol_of(tmp_path) == 82); const char *L2[] = { "audio.volume = 82\n", "audio.volume_max = 60\n", NULL }; write_settings(L2); check("V4 vol=82 max=60 -> 60 (clamp)", settings_vol_of(tmp_path) == 60); const char *L3[] = { "audio.volume = 150\n", "audio.volume_max = 100\n", NULL }; write_settings(L3); check("V4 vol=150 max=100 -> 100 (硬上限)", settings_vol_of(tmp_path) == 100); const char *L4[] = { "audio.volume = -3\n", "audio.volume_max = 100\n", NULL }; write_settings(L4); check("V4 vol=-3 -> 0", settings_vol_of(tmp_path) == 0); const char *L5[] = { "display.brightness = 100\n", NULL }; /* 无音量键 */ write_settings(L5); check("V4 无 audio.volume -> 默认 60", settings_vol_of(tmp_path) == MEOW_UI_VOL_DEFAULT); } /* ---- V5 展示串:VOL %d%(step 只决定步进,展示原样不/舍入)---- */ { char s[16]; vol_display(60, 100, s, sizeof s); check("V5 vol=60 -> \"VOL 60%\"", !strcmp(s, "VOL 60%")); vol_display(80, 60, s, sizeof s); check("V5 vol=80 max=60 -> \"VOL 60%\" (显示夹后值)", !strcmp(s, "VOL 60%")); vol_display(-5, 100, s, sizeof s); check("V5 vol=-5 -> \"VOL 0%\"", !strcmp(s, "VOL 0%")); vol_display(37, 100, s, sizeof s); check("V5 vol=37 -> \"VOL 37%\" (step 值原样展示)", !strcmp(s, "VOL 37%")); } unlink(tmp_path); printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS", failures, failures == 1 ? "" : "s"); return failures ? 1 : 0; }