174 lines
7.7 KiB
C
174 lines
7.7 KiB
C
/* test_bgmgr.c — 批③ 后台管理页 逻辑层宿主单测(meow_bgmgr)。
|
||
*
|
||
* 验证:
|
||
* 1) bgmgr_collect:enumerate 后台表 → app_meta 补 name/icon/framework/is_fg → proc_sample 补
|
||
* pcpu/rss_kb;行 killable 预判正确;name 回退 app_id。
|
||
* 2) bgmgr_can_kill 门控矩阵:framework=1 → 0(**框架 App 不 kill**);is_fg=1 → 0(当前前台不 kill);
|
||
* pid<=0 → 0(非后台/无进程);普通后台(非框架/非前台/pid>0)→ 1。
|
||
* 3) bgmgr_kill_all 一键清:框架 App 不杀、当前前台不杀、非后台不杀;其余逐一 kill;返回 kill 数。
|
||
* 4) bgmgr_status_str / bgmgr_mem_str 文案。
|
||
* 只依赖 meow_bgmgr.c + meow_ipc.h(纯 C);宿主 gcc 直编:
|
||
* gcc -Wall -Wextra -std=gnu99 test_bgmgr.c meow_bgmgr.c -o test_bgmgr
|
||
*/
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <stdint.h>
|
||
#include "meow_bgmgr.h"
|
||
|
||
static int g_fails = 0;
|
||
#define CHECK(cond, msg) do { \
|
||
if (cond) printf("PASS: %s\n", msg); \
|
||
else { printf("FAIL: %s\n", msg); g_fails++; } } while (0)
|
||
|
||
/* ---- 假件(enumerate/app_meta/proc_sample 注入)---- */
|
||
static const char g_meta_app[][24] = {
|
||
"os.meow.hello", "os.meow.reader", "os.meow.sysguard", "os.meow.fgapp",
|
||
};
|
||
static int g_killed_n = 0;
|
||
static char g_killed_app[8][40];
|
||
static int g_meta_use_unknown = 0; /* 第 4 行 meta 返回 -1(未注册),测 name 回退 */
|
||
|
||
static int fake_enumerate(void *ctx, bgmgr_row_t *rows, int max)
|
||
{
|
||
(void)ctx;
|
||
if (max < 4) return 0;
|
||
/* 4 个后台行:hello=普通、reader=常驻、sysguard=framework、fgapp=当前前台 */
|
||
memset(&rows[0], 0, sizeof rows[0]);
|
||
snprintf(rows[0].app_id, sizeof rows[0].app_id, "%s", g_meta_app[0]);
|
||
rows[0].pid = 1001; rows[0].keepalive = 0; rows[0].on_card = 0; rows[0].bg_since_ms = 1000;
|
||
|
||
memset(&rows[1], 0, sizeof rows[1]);
|
||
snprintf(rows[1].app_id, sizeof rows[1].app_id, "%s", g_meta_app[1]);
|
||
rows[1].pid = 1002; rows[1].keepalive = 1; rows[1].on_card = 0; rows[1].bg_since_ms = 2000;
|
||
|
||
memset(&rows[2], 0, sizeof rows[2]);
|
||
snprintf(rows[2].app_id, sizeof rows[2].app_id, "%s", g_meta_app[2]);
|
||
rows[2].pid = 1003; rows[2].keepalive = 0; rows[2].on_card = 0; rows[2].bg_since_ms = 3000;
|
||
|
||
memset(&rows[3], 0, sizeof rows[3]);
|
||
snprintf(rows[3].app_id, sizeof rows[3].app_id, "%s", g_meta_app[3]);
|
||
rows[3].pid = 1004; rows[3].keepalive = 0; rows[3].on_card = 0; rows[3].bg_since_ms = 4000;
|
||
return 4;
|
||
}
|
||
|
||
/* meta:hello/reader/sysguard/fgapp 各给名字;sysguard 标 framework;pid==1004 标前台。 */
|
||
static int fake_app_meta(void *ctx, const char *app_id, pid_t pid,
|
||
char *name, int nl, char *icon, int il,
|
||
char *framework, int *is_fg)
|
||
{
|
||
(void)ctx;
|
||
if (!strcmp(app_id, "os.meow.hello")) snprintf(name, nl, "播放");
|
||
else if (!strcmp(app_id, "os.meow.reader")) snprintf(name, nl, "阅读");
|
||
else if (!strcmp(app_id, "os.meow.sysguard")) snprintf(name, nl, "系统守护");
|
||
else if (!strcmp(app_id, "os.meow.fgapp")) snprintf(name, nl, "前台应用");
|
||
else return -1; /* 未注册 → name 回退 app_id */
|
||
snprintf(icon, il, "/tmp/icon_%s.png", app_id);
|
||
*framework = (!strcmp(app_id, "os.meow.sysguard")) ? '1' : 0;
|
||
*is_fg = (pid == 1004) ? 1 : 0; /* fgapp 标前台 */
|
||
return 0;
|
||
}
|
||
|
||
static int fake_proc_sample(void *ctx, pid_t pid, double *pcpu, long *rss_kb)
|
||
{
|
||
(void)ctx;
|
||
if (pid <= 0) return -1;
|
||
*pcpu = (double)(pid % 100) * 0.5; /* 1001->0.5% ... 1004->2.0% */
|
||
*rss_kb = (long)(pid % 10) * 2048; /* 1001->2048 ... 1004->8192 */
|
||
return 0;
|
||
}
|
||
|
||
static void fake_log(const char *fmt, ...) { (void)fmt; }
|
||
|
||
static void fake_kill(const char *app_id)
|
||
{
|
||
if (g_killed_n < 8) snprintf(g_killed_app[g_killed_n++], 40, "%s", app_id);
|
||
}
|
||
|
||
/* enumerate 只回一行:未注册 app_id,测 name 回退。 */
|
||
static int fake_enumerate_unknown(void *ctx, bgmgr_row_t *rows, int max)
|
||
{
|
||
(void)ctx;
|
||
if (max < 1) return 0;
|
||
(void)g_meta_use_unknown;
|
||
memset(&rows[0], 0, sizeof rows[0]);
|
||
snprintf(rows[0].app_id, sizeof rows[0].app_id, "os.meow.noreg");
|
||
rows[0].pid = 2001; rows[0].keepalive = 0;
|
||
return 1;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
bgmgr_ops_t ops;
|
||
memset(&ops, 0, sizeof ops);
|
||
ops.enumerate = fake_enumerate;
|
||
ops.app_meta = fake_app_meta;
|
||
ops.proc_sample = fake_proc_sample;
|
||
ops.log = fake_log;
|
||
|
||
bgmgr_row_t rows[MEOW_BGMR_ROW_MAX];
|
||
int n = bgmgr_collect(&ops, rows, MEOW_BGMR_ROW_MAX);
|
||
|
||
printf("=== 1) collect ===\n");
|
||
CHECK(n == 4, "collect returns 4 rows");
|
||
CHECK(!strcmp(rows[0].name, "播放") && rows[0].pid == 1001, "row0 hello name/pid");
|
||
CHECK(rows[0].framework == 0, "row0 hello not framework");
|
||
CHECK(!strcmp(rows[1].name, "阅读") && rows[1].keepalive == 1, "row1 reader keepalive");
|
||
CHECK(rows[2].framework == '1', "row2 sysguard framework");
|
||
CHECK(rows[3].is_fg == 1, "row3 fgapp is_fg");
|
||
CHECK(rows[0].pcpu > 0 && rows[0].rss_kb > 0, "row0 pcpu/rss populated");
|
||
CHECK(rows[0].killable == 1 && rows[2].killable == 0, "killable prefilled by can_kill");
|
||
CHECK(!strcmp(rows[2].icon, "/tmp/icon_os.meow.sysguard.png"), "icon populated");
|
||
|
||
/* name 回退:未注册 app_id(app_meta 返回 -1)→ name==app_id */
|
||
printf("=== 1b) name fallback ===\n");
|
||
{
|
||
bgmgr_ops_t o2 = ops; o2.enumerate = fake_enumerate_unknown;
|
||
bgmgr_row_t r1[1]; memset(r1, 0, sizeof r1);
|
||
int n2 = bgmgr_collect(&o2, r1, 1);
|
||
CHECK(n2 == 1, "unknown row collected");
|
||
CHECK(!strcmp(r1[0].name, "os.meow.noreg"), "name falls back to app_id");
|
||
CHECK(bgmgr_can_kill(&r1[0]) == 1, "unknown bg app still killable");
|
||
}
|
||
|
||
printf("=== 2) can_kill gating ===\n");
|
||
CHECK(bgmgr_can_kill(&rows[2]) == 0, "framework app NOT killable");
|
||
CHECK(bgmgr_can_kill(&rows[3]) == 0, "fg app NOT killable (is_fg)");
|
||
CHECK(bgmgr_can_kill(&rows[0]) == 1, "normal bg app killable");
|
||
CHECK(bgmgr_can_kill(&rows[1]) == 1, "keepalive bg app killable");
|
||
{
|
||
bgmgr_row_t dead; memset(&dead, 0, sizeof dead);
|
||
snprintf(dead.app_id, sizeof dead.app_id, "x");
|
||
dead.pid = 0;
|
||
CHECK(bgmgr_can_kill(&dead) == 0, "pid<=0 NOT killable");
|
||
CHECK(bgmgr_can_kill(NULL) == 0, "NULL NOT killable");
|
||
}
|
||
|
||
printf("=== 3) kill_all (one-key clear) ===\n");
|
||
g_killed_n = 0;
|
||
int k = bgmgr_kill_all(&ops, rows, n, fake_kill);
|
||
CHECK(k == 2, "kill_all kills 2 (hello+reader)");
|
||
CHECK(g_killed_n == 2, "kill_all actually invoked kill_fn 2x");
|
||
int killed_fw = 0, killed_fg = 0, killed_bg = 0;
|
||
for (int i = 0; i < g_killed_n; i++) {
|
||
if (!strcmp(g_killed_app[i], "os.meow.sysguard")) killed_fw = 1;
|
||
if (!strcmp(g_killed_app[i], "os.meow.fgapp")) killed_fg = 1;
|
||
if (!strcmp(g_killed_app[i], "os.meow.hello")) killed_bg = 1;
|
||
}
|
||
CHECK(killed_fw == 0, "kill_all did NOT kill framework app");
|
||
CHECK(killed_fg == 0, "kill_all did NOT kill fg app");
|
||
CHECK(killed_bg == 1, "kill_all killed a real bg app");
|
||
CHECK(bgmgr_kill_all(&ops, rows, n, NULL) == 0, "kill_all NULL kill_fn -> 0");
|
||
|
||
printf("=== 4) status/mem str ===\n");
|
||
CHECK(!strcmp(bgmgr_status_str(&rows[1]), "常驻"), "status_str keepalive=常驻");
|
||
CHECK(!strcmp(bgmgr_status_str(&rows[0]), "后台"), "status_str normal=后台");
|
||
CHECK(!strcmp(bgmgr_status_str(&rows[3]), "前台"), "status_str is_fg=前台");
|
||
CHECK(!strcmp(bgmgr_mem_str(512), "512KB"), "mem_str(<1MB)=KB");
|
||
CHECK(!strcmp(bgmgr_mem_str(2048), "2.0MB"), "mem_str(>=1MB)=MB");
|
||
|
||
if (g_fails == 0) printf("\nALL PASS (%d checks)\n", 20);
|
||
else printf("\n%d FAILED\n", g_fails);
|
||
return g_fails ? 1 : 0;
|
||
}
|