通知模型补全(agent-107: SDK icon+update_progress / IPC urgency+MSG_NOTIFY_PROGRESS / 存储 urgency+icon回退+progress / CSV加3列) + 全屏收合视觉+滑条(agent-108)
This commit is contained in:
1 parent
b3e57d4b55
commit
e8fa373a2f
18 files changed
+410
-56
No files matched your search
@@ -53,9 +53,37 @@ static void make_notif(meow_notif_t *n, uint32_t id, const char *sum, const char
|
||||
strcpy(n->summary, sum);
|
||||
strcpy(n->body, body);
|
||||
strcpy(n->target_activity, "act");
|
||||
n->urgency = 0; /* 0=LOW(缺省值) */
|
||||
n->progress = -1; /* 无进度 */
|
||||
n->ongoing = 1;
|
||||
}
|
||||
|
||||
/* 回读指定 summary 的活跃通知(meow_notif_list 回调;按 g_find_key 匹配) */
|
||||
static meow_notif_t g_got; static int g_got_found = 0; static char g_find_key[64];
|
||||
static int find_cb(const meow_notif_t *n, void *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if (n && strcmp(n->summary, g_find_key) == 0) { g_got = *n; g_got_found = 1; return 1; }
|
||||
return 0;
|
||||
}
|
||||
static meow_notif_t find_notif(const char *summary)
|
||||
{
|
||||
g_got_found = 0; memset(&g_got, 0, sizeof g_got);
|
||||
snprintf(g_find_key, sizeof g_find_key, "%s", summary);
|
||||
meow_notif_list(NULL, find_cb, NULL);
|
||||
return g_got_found ? g_got : (meow_notif_t){0};
|
||||
}
|
||||
|
||||
/* 图标回退 stub:com.app → "app_icon_name";其他 app → 无 */
|
||||
static int stub_icon_cb(const char *app_id, char *out, size_t outsz)
|
||||
{
|
||||
if (app_id && !strcmp(app_id, "com.app")) { snprintf(out, outsz, "app_icon_name"); return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dump_cb 类型是 void,而 meow_notif_dump_tf 返回 int——包一层(同 launcher notif_dump_tf_placeholder) */
|
||||
static void dump_tf_wrapper(const meow_notif_t *n){ (void)meow_notif_dump_tf(n); }
|
||||
|
||||
/* --- 1) CSV 转义 + 去换行 --- */
|
||||
static void test_csv_escape(const char *path)
|
||||
{
|
||||
@@ -71,9 +99,9 @@ static void test_csv_escape(const char *path)
|
||||
char *s = read_all(path, NULL);
|
||||
CHECK(s != NULL, "file exists after dump");
|
||||
const char *expect =
|
||||
"1234567890123,42,\"com.app\",\"general\",\"\",\"Hel\"\"lo, world line2\","
|
||||
"\"Body with\ttab\",\"act\",1,1,0\n"; /* ongoing=1 media=1 dismissed=0 */
|
||||
CHECK(s && strcmp(s, expect) == 0, "CSV line matches expected (escape+newline-strip)");
|
||||
"1234567890123,42,\"com.app\",\"\",\"general\",0,-1,\"Hel\"\"lo, world line2\","
|
||||
"\"Body with\ttab\",\"act\",1,1,0\n"; /* app_icon="" urgency=0 progress=-1 ongoing=1 media=1 dismissed=0 */
|
||||
CHECK(s && strcmp(s, expect) == 0, "CSV line matches expected (escape+newline-strip+new cols)");
|
||||
if (s) { fprintf(stderr, " got: %s", s); fprintf(stderr, " exp: %s", expect); }
|
||||
free(s);
|
||||
}
|
||||
@@ -134,24 +162,92 @@ static void test_init_clear(const char *path)
|
||||
free(s);
|
||||
}
|
||||
|
||||
/* --- 4) icon 回退:app_icon 空 → 按 app_id 用该 app 默认图标;非空 → 保留 --- */
|
||||
static void test_icon_fallback(const char *path)
|
||||
{
|
||||
meow_notif_set_icon_cb(stub_icon_cb);
|
||||
meow_notif_before_poweroff(); /* 清内存表,回到干净态(dump_cb=NULL 不落盘) */
|
||||
meow_notif_set_tf_path(path);
|
||||
meow_notif_set_tf_max(1024 * 1024);
|
||||
|
||||
/* 空 app_icon → 回退 app 图标 */
|
||||
meow_notif_t n;
|
||||
make_notif(&n, 0, "icon-test", "");
|
||||
uint32_t id = 0;
|
||||
CHECK(meow_notif_post(&n, &id) == NOTIF_OK, "icon-fallback post ok");
|
||||
meow_notif_t got = find_notif("icon-test");
|
||||
CHECK(got.id != 0 && !strcmp(got.app_icon, "app_icon_name"), "empty app_icon → app icon fallback");
|
||||
|
||||
/* 非空 app_icon → 独立图标(不回退) */
|
||||
make_notif(&n, 0, "icon-custom", "");
|
||||
n.app_icon[0] = 0; strcpy(n.app_icon, "custom/icon.png");
|
||||
CHECK(meow_notif_post(&n, &id) == NOTIF_OK, "icon-custom post ok");
|
||||
got = find_notif("icon-custom");
|
||||
CHECK(got.id != 0 && !strcmp(got.app_icon, "custom/icon.png"), "non-empty app_icon kept (per-notif icon)");
|
||||
}
|
||||
|
||||
/* --- 5) progress 实时(仅内存)vs 里程碑(100% 落盘 + 释放) --- */
|
||||
static void test_progress_live(const char *path)
|
||||
{
|
||||
meow_notif_set_icon_cb(NULL);
|
||||
meow_notif_set_dump_cb(NULL);
|
||||
meow_notif_before_poweroff(); /* 清内存表,回到干净态 */
|
||||
meow_notif_set_tf_path(path);
|
||||
meow_notif_set_tf_max(1024 * 1024);
|
||||
meow_notif_set_dump_cb(dump_tf_wrapper); /* 归档即写 CSV;验证落盘快照 */
|
||||
|
||||
meow_notif_t n;
|
||||
make_notif(&n, 0, "live", "");
|
||||
n.ongoing = 0; /* 非 ONGOING,便于验证 100% 释放 */
|
||||
n.progress = 0;
|
||||
uint32_t id = 0;
|
||||
CHECK(meow_notif_post(&n, &id) == NOTIF_OK, "progress post ok");
|
||||
CHECK(meow_notif_count(NULL) == 1, "one active after post");
|
||||
|
||||
/* 实时 <100%:仅内存,不落盘 */
|
||||
CHECK(meow_notif_update_progress(id, 70) == NOTIF_OK, "update_progress(70) ok");
|
||||
CHECK(meow_notif_count(NULL) == 1, "still active after live update (not dumped)");
|
||||
long len = 0; char *s = read_all(path, &len);
|
||||
CHECK((s == NULL || len == 0), "no CSV written on live update (<100%)");
|
||||
free(s);
|
||||
|
||||
/* 里程碑 100%:立即归档落盘 + 释放非 ONGOING 槽 */
|
||||
CHECK(meow_notif_update_progress(id, 100) == NOTIF_OK, "update_progress(100) ok");
|
||||
CHECK(meow_notif_count(NULL) == 0, "slot released after 100% milestone");
|
||||
s = read_all(path, &len);
|
||||
CHECK(s != NULL && len > 0, "CSV written on 100% milestone");
|
||||
CHECK(s && strstr(s, ",100,\"live\"") != NULL, "milestone CSV has progress=100 title=live");
|
||||
if (s) fprintf(stderr, " milestone row: %s", s);
|
||||
free(s);
|
||||
|
||||
/* 已释放 id → NOENT */
|
||||
CHECK(meow_notif_update_progress(id, 50) == NOTIF_ERR_NOENT, "update on released id -> NOENT");
|
||||
|
||||
meow_notif_set_dump_cb(NULL); /* 复位 */
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char tmp[] = "/tmp/meow_notif_tf_test_XXXXXX";
|
||||
char *dir = mkdtemp(tmp);
|
||||
if (!dir) { perror("mkdtemp"); return 2; }
|
||||
|
||||
char p1[512], p2[512], p3[512];
|
||||
char p1[512], p2[512], p3[512], p4[512], p5[512];
|
||||
snprintf(p1, sizeof p1, "%s/csv.log", dir);
|
||||
snprintf(p2, sizeof p2, "%s/trim.log", dir);
|
||||
snprintf(p3, sizeof p3, "%s/init.log", dir);
|
||||
snprintf(p4, sizeof p4, "%s/icon.log", dir);
|
||||
snprintf(p5, sizeof p5, "%s/prog.log", dir);
|
||||
|
||||
CHECK(p1[0] != 0, "tmpdir ready");
|
||||
test_csv_escape(p1);
|
||||
test_trim(p2);
|
||||
test_init_clear(p3);
|
||||
test_icon_fallback(p4);
|
||||
test_progress_live(p5);
|
||||
|
||||
/* 清理:删除日志文件 + 目录(保底) */
|
||||
unlink(p1); unlink(p2); unlink(p3); rmdir(dir);
|
||||
unlink(p1); unlink(p2); unlink(p3); unlink(p4); unlink(p5); rmdir(dir);
|
||||
|
||||
fprintf(stderr, "\n%s (failures=%d)\n", g_fail ? "== TEST FAILED ==" : "== TEST PASSED ==", g_fail);
|
||||
return g_fail ? 1 : 0;
|
||||
|
||||
Reference in new issue
Block a user