/* test_wd_fw.c — 宿主单测:meow_watchdog 的「SDK 框架 App 判定」逻辑(M2.86, issue 226)。 * * 编译:#include meow_watchdog.c(去 main 拿 wd_app_is_framework/wd_json_str/wd_framework_from_pid)。 * gcc -Wall -Wextra -Os -DWd_NO_MAIN -Wno-unused-function -Wno-unused-parameter \ * test_wd_fw.c -o test_wd_fw * (meow_watchdog.c 含仅 main 使用的静态函数,宿主去 main 后须 -Wno-unused-function 静音; * mips 目标构建不定义 WD_NO_MAIN,不受影响。) * 运行:./test_wd_fw;全 PASS -> exit 0。 */ #define WD_NO_MAIN #include "meow_watchdog.c" #include #include #include #include #include static int g_pass = 0, g_fail = 0; static void check(const char *name, int got, int want) { if (got == want) { g_pass++; printf("PASS %s\n", name); } else { g_fail++; printf("FAIL %s: got %d want %d\n", name, got, want); } } /* ---- M2.87:SIGUSR1 手势让位(handle_touch 左缘滑动分支)---- * 判定(meow_watchdog.c):`!g_fw_app && immersive` 才发 SIGUSR1(只给裸沉浸 App); * SDK 框架 App(g_fw_app=1)不发(返回由 SDK on_swipe 处理),防 SIGUSR1 杀死 App。 */ static volatile int g_sigusr1_hits = 0; static void on_sigusr1(int s) { (void)s; g_sigusr1_hits++; } /* 经 handle_touch 模拟一次「左缘起点+向右滑」完整手势(press→release),返回 SIGUSR1 命中数。 */ static int sim_swipe_sigusr1(int fw, int immersive) { g_fw_app = fw; g_sigusr1_hits = 0; last_x = 5; last_y = 300; /* 左缘原点(xSWIPE_DX=50) */ handle_touch(immersive, getpid(), now - 3000, 0); /* release */ return g_sigusr1_hits; } /* 在 / 建目录并写 app.json;写失败返回 -1。 */ static int fixture(const char *base, const char *name, const char *appjson) { char dir[512], path[560]; snprintf(dir, sizeof dir, "%s/%s", base, name); if (mkdir(dir, 0755) != 0 && access(dir, F_OK) != 0) return -1; snprintf(path, sizeof path, "%s/app.json", dir); FILE *f = fopen(path, "w"); if (!f) return -1; fputs(appjson, f); fclose(f); return 0; } static int expect_fw(const char *base, const char *name, const char *appjson, int want) { char dir[512]; snprintf(dir, sizeof dir, "%s/%s", base, name); if (fixture(base, name, appjson) != 0) { g_fail++; printf("FAIL %s: cannot write fixture\n", name); return 0; } char label[256]; snprintf(label, sizeof label, "is_fw(%s)", name); check(label, wd_app_is_framework(dir), want); return 1; } int main(void) { signal(SIGUSR1, on_sigusr1); /* 捕获 handle_touch 可能发出的 SIGUSR1(测命中) */ char dir[] = "/tmp/wdfwXXXXXX"; if (!mkdtemp(dir)) { perror("mkdtemp"); return 2; } /* 框架 App:各值形态 */ expect_fw(dir, "v_num", "{\"name\":\"x\",\"framework\":1,\"exec\":\"/a/b\"}", 1); /* JSON 数值 1 */ expect_fw(dir, "v_true", "{\"name\":\"x\",\"framework\":true}", 1); /* true */ expect_fw(dir, "v_yes", "framework=yes", 1); /* 扁平 yes */ expect_fw(dir, "v_str", "{\"framework\":\"true\"}", 1); /* 字符串 "true" */ expect_fw(dir, "v_space","{\"name\":\"x\", \"framework\" : 1 }", 1); /* 空格容错 */ /* 非框架 App */ expect_fw(dir, "v_zero", "{\"name\":\"x\",\"framework\":0}", 0); /* 数值 0 */ expect_fw(dir, "v_false","{\"framework\":false}", 0); /* false */ expect_fw(dir, "v_none", "{\"name\":\"x\",\"exec\":\"/a/b\"}", 0); /* 无 framework 键 */ expect_fw(dir, "v_sub", "{\"x_framework\":1}", 0); /* 键前缀歧义:不误判 */ /* 多行 JSON(framework 单独一行,值独立) */ expect_fw(dir, "multiline", "{\n \"name\": \"x\",\n \"framework\": 1,\n \"exec\": \"/a/b\"\n}\n", 1); /* wd_json_str 直接断言(防 "myframework" / 前缀干扰) */ { char out[16] = ""; check("json_str exact", wd_json_str("{\"framework\":1}", "framework", out, sizeof out) > 0 && !strcmp(out, "1"), 1); check("json_str prefix-reject", wd_json_str("{\"x_framework\":1}", "framework", out, sizeof out), 0); check("json_str no-hit", wd_json_str("{\"name\":\"x\"}", "framework", out, sizeof out), 0); } /* wd_framework_from_pid:自进程 /proc/self/exe 目录无 app.json -> 0,不崩 */ check("from_pid(no app.json)", wd_framework_from_pid(getpid()), 0); /* ---- M2.87 SIGUSR1 让位判定(仅裸沉浸 App 发 SIGUSR1)---- */ check("sigusr1 fw-app (framework=1) -> 0", sim_swipe_sigusr1(1, 1), 0); /* SDK 框架 App:不发 */ check("sigusr1 bare-immersive -> 1", sim_swipe_sigusr1(0, 1), 1); /* 裸沉浸:发(命中) */ check("sigusr1 bare-nonimmersive -> 0", sim_swipe_sigusr1(0, 0), 0); /* 裸非沉浸:不发 */ /* 清理 */ { char path[560]; const char *names[] = { "v_num","v_true","v_yes","v_str","v_space","v_zero", "v_false","v_none","v_sub","multiline" }; for (unsigned i = 0; i < sizeof names / sizeof names[0]; i++) { snprintf(path, sizeof path, "%s/%s/app.json", dir, names[i]); unlink(path); snprintf(path, sizeof path, "%s/%s", dir, names[i]); rmdir(path); } rmdir(dir); } printf("\n%d pass, %d fail\n", g_pass, g_fail); return g_fail ? 1 : 0; }