169 lines
7.4 KiB
C
169 lines
7.4 KiB
C
/*
|
||
* test_notify_post.c — 宿主交叉验证:SDK send 的 IPC 帧 → launcher 真·中央存储。
|
||
*
|
||
* 把 SDK 的 meow_notify_ipc.c(映射+传输)与 launcher 的 meow_notif.c(真·中央存储,
|
||
* meow_notif_post/dismiss)接到一起,stub 掉 meow_settings 后端;服务端复刻
|
||
* meow_launcherd.c:6427-6440 的 m_notify_t→meow_notif_t 映射 + MSG_NOTIFY_ACK 应答。
|
||
*
|
||
* 验证:SDK meow_notify_ipc_send() 产出的帧被 meow_notif_post() 真实落库并回分配 nid>0;
|
||
* 随后 meow_notify_ipc_dismiss() 经 meow_notif_dismiss() 撤下(count 归 0)。
|
||
*
|
||
* 编译(宿主 gcc):
|
||
* gcc -o test_notify_post test_notify_post.c meow_notify_ipc.c \
|
||
* ../meow_launcherd/meow_notif.c -I. -I../meow_launcherd -lpthread
|
||
*/
|
||
#include "meow_notify_ipc.h"
|
||
#include "meow_ui.h"
|
||
#include "meow_ipc.h"
|
||
#include "meow_notif.h" /* launcher 真·中央存储 */
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <errno.h>
|
||
#include <fcntl.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/un.h>
|
||
#include <pthread.h>
|
||
|
||
/* ---- stub:settings 后端(键缺省 → meow_notif.c 用默认配额) ---- */
|
||
int meow_settings_get_int(const char *key, int *out) { (void)key; (void)out; return MEOW_ERR_NOENT; }
|
||
|
||
/* ---- 复刻 launcher 的 m_notify_t → meow_notif_t 映射(meow_launcherd.c:6427-6440) ----
|
||
* 注:与 launcher 同款 snprintf(dest 较 src 小会有 format-truncation 提示),launcher 自身
|
||
* 以其编译 flags 构建无警告;此处仅为宿主测试,用 pragma 压掉以免 -Werror 干扰。 */
|
||
#if defined(__GNUC__)
|
||
#pragma GCC diagnostic push
|
||
#pragma GCC diagnostic ignored "-Wformat-truncation"
|
||
#endif
|
||
static void launcher_map(const m_notify_t *mn, meow_notif_t *n)
|
||
{
|
||
memset(n, 0, sizeof *n);
|
||
n->id = mn->replaces_id; /* 0=>新建;>0=>替换(不存在则新建) */
|
||
snprintf(n->app_id, sizeof n->app_id, "%s", mn->app_id);
|
||
snprintf(n->category, sizeof n->category, "%s", mn->category);
|
||
snprintf(n->summary, sizeof n->summary, "%s", mn->summary);
|
||
snprintf(n->body, sizeof n->body, "%s", mn->body);
|
||
snprintf(n->app_icon, sizeof n->app_icon, "%s", mn->app_icon);
|
||
snprintf(n->target_activity, sizeof n->target_activity, "%s", mn->target_activity);
|
||
n->expire_timeout = mn->expire_timeout;
|
||
n->progress = mn->progress;
|
||
n->urgency = mn->urgency; /* 0-3;旧调用=0 → LOW(静默) */
|
||
n->ongoing = mn->ongoing;
|
||
n->media = mn->media;
|
||
}
|
||
#if defined(__GNUC__)
|
||
#pragma GCC diagnostic pop
|
||
#endif
|
||
|
||
static int g_listen_fd = -1;
|
||
static int g_stop = 0;
|
||
static uint32_t g_posted_nid = 0;
|
||
static meow_notif_t g_stored; /* 回读 launcher 存储的最近一条通知(store_cb) */
|
||
static int g_store_called = 0;
|
||
|
||
static int store_cb(const meow_notif_t *n, void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (n) { g_stored = *n; g_store_called = 1; }
|
||
return 1; /* 只取第一条 */
|
||
}
|
||
|
||
static void reply_ack(int c, uint16_t type, uint32_t req_id, uint32_t status)
|
||
{
|
||
m_ack_t a; memset(&a, 0, sizeof a); a.code = MEOW_OK; a.status = status;
|
||
uint8_t rhdr[MEOW_IPC_HDR_LEN];
|
||
uint32_t mag = MEOW_IPC_MAGIC; uint16_t ver = MEOW_IPC_VERSION, t = type; uint32_t rl = sizeof a;
|
||
memcpy(rhdr+0,&mag,4); memcpy(rhdr+4,&ver,2); memcpy(rhdr+6,&t,2); memcpy(rhdr+8,&req_id,4); memcpy(rhdr+12,&rl,4);
|
||
size_t o = 0; while (o < sizeof rhdr) { ssize_t w = write(c, rhdr+o, sizeof rhdr-o); if (w<=0) break; o += (size_t)w; }
|
||
o = 0; while (o < rl) { ssize_t w = write(c, (uint8_t*)&a+o, rl-o); if (w<=0) break; o += (size_t)w; }
|
||
}
|
||
|
||
static void *server(void *arg)
|
||
{
|
||
(void)arg;
|
||
meow_notif_init();
|
||
while (!g_stop) {
|
||
int c = accept(g_listen_fd, NULL, NULL);
|
||
if (c < 0) { if (errno == EAGAIN && g_stop) break; if (errno == EBADF) break; usleep(1000); continue; }
|
||
uint8_t hdr[MEOW_IPC_HDR_LEN]; size_t o = 0;
|
||
while (o < sizeof hdr) { ssize_t r = read(c, hdr+o, sizeof hdr-o); if (r<=0) break; o += (size_t)r; }
|
||
if (o < sizeof hdr) { close(c); continue; }
|
||
uint32_t type, len, req_id; memcpy(&type, hdr+6, 2); memcpy(&req_id, hdr+8, 4); memcpy(&len, hdr+12, 4);
|
||
if (len > MEOW_IPC_MAX) { close(c); continue; }
|
||
uint8_t pay[MEOW_IPC_MAX]; o = 0;
|
||
while (o < len) { ssize_t r = read(c, pay+o, len-o); if (r<=0) break; o += (size_t)r; }
|
||
|
||
if (type == MSG_NOTIFY && len >= sizeof(m_notify_t)) {
|
||
m_notify_t mn; memcpy(&mn, pay, sizeof mn);
|
||
meow_notif_t n; launcher_map(&mn, &n);
|
||
uint32_t nid = 0;
|
||
int rc = meow_notif_post(&n, &nid);
|
||
if (rc == NOTIF_OK) g_posted_nid = nid;
|
||
reply_ack(c, MSG_NOTIFY_ACK, req_id, (rc == NOTIF_OK) ? nid : (uint32_t)rc);
|
||
fprintf(stderr, "[post-srv] post rc=%d nid=%u cat=%s\n", rc, nid, mn.category);
|
||
} else if (type == MSG_NOTIFY_DISMISS && len >= 4) {
|
||
uint32_t id; memcpy(&id, pay, 4);
|
||
int rc = meow_notif_dismiss(id);
|
||
reply_ack(c, MSG_ACK, req_id, 0);
|
||
fprintf(stderr, "[post-srv] dismiss id=%u rc=%d\n", id, rc);
|
||
}
|
||
close(c);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static int make_listen(char *path, size_t n)
|
||
{
|
||
snprintf(path, n, "/tmp/meow_notify_post_%d.sock", (int)getpid());
|
||
unlink(path);
|
||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
struct sockaddr_un a; memset(&a, 0, sizeof a); a.sun_family = AF_UNIX;
|
||
strncpy(a.sun_path, path, sizeof a.sun_path - 1);
|
||
if (bind(fd, (struct sockaddr*)&a, sizeof a) < 0 || listen(fd, 4) < 0) { close(fd); return -1; }
|
||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||
g_listen_fd = fd;
|
||
return 0;
|
||
}
|
||
|
||
static int failures = 0;
|
||
static void check(const char *name, int cond) { printf("%s %s\n", cond ? "PASS" : "FAIL", name); if (!cond) failures++; }
|
||
|
||
int main(void)
|
||
{
|
||
setenv("MEOW_LOG_APP", "intgapp", 1);
|
||
char sock[108];
|
||
if (make_listen(sock, sizeof sock) != 0) { fprintf(stderr, "cannot listen\n"); return 2; }
|
||
setenv("MEOW_IPC_SOCK", sock, 1);
|
||
pthread_t th; pthread_create(&th, NULL, server, NULL);
|
||
|
||
/* SDK send → launcher 真存储。media + ONGOING 走全部映射分支。 */
|
||
meow_notify nt; memset(&nt, 0, sizeof nt);
|
||
nt.cat = MEOW_NOTIFY_CAT_MEDIA; nt.urgency = MEOW_NOTIFY_URG_HIGH;
|
||
nt.title = "正在播放"; nt.timeout_ms = -1; nt.progress = 40;
|
||
nt.icon = "os.meow.hello/icon.png";
|
||
uint32_t nid = meow_notify_ipc_send(&nt, 0);
|
||
check("send 经 launcher 真存储回 nid>0", nid != 0);
|
||
check("send 拿到 launcher 分配的 nid(与 post 一致)", g_posted_nid == nid);
|
||
check("launcher 存储 count(media app)=1", meow_notif_count("intgapp") == 1);
|
||
|
||
/* 回读 launcher 存储,验证 urgency/icon/progress 全链路落库 */
|
||
g_store_called = 0; memset(&g_stored, 0, sizeof g_stored);
|
||
meow_notif_list(NULL, store_cb, NULL);
|
||
check("post 存储 urgency=HIGH(2)", g_store_called && g_stored.urgency == MEOW_NOTIFY_URG_HIGH);
|
||
check("post 存储 icon→app_icon", g_stored.app_icon[0] && !strcmp(g_stored.app_icon, "os.meow.hello/icon.png"));
|
||
check("post 存储 progress=40", g_stored.progress == 40);
|
||
|
||
/* SDK dismiss → launcher 撤下 */
|
||
meow_notify_ipc_dismiss(nid);
|
||
check("dismiss 后 launcher 存储 count=0", meow_notif_count("intgapp") == 0);
|
||
|
||
g_stop = 1; close(g_listen_fd);
|
||
pthread_join(th, NULL);
|
||
meow_notif_shutdown();
|
||
|
||
printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS", failures, failures == 1 ? "" : "s");
|
||
return failures ? 1 : 0;
|
||
}
|