Files
MeowOS-For-R3P2/patch_v2/sdk/test_notify_ipc.c
T

282 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* test_notify_ipc.c — 宿主测试:任务 #5 SDK↔IPC 桥(meow_notify_ipc.{h,c})。
*
* 用本地 AF_UNIX stub socket(回环)验证:
* T1 枚举↔字符串映射:CAT_PROGRESS→"progress"、CAT_MEDIA→"media" + media=1;
* T2 timeout 映射:-1(ONGOING)→expire=0xFFFFFFFF + ongoing=1;0(NEVER)→expire=0;
* >0→该毫秒 + ongoing=0;
* T3 回读 MSG_NOTIFY_ACK 拿 launcher 分配的 nid;replaces_id 原样透传;progress 钳位;
* T4 无 socket 降级:connect 失败 → meow_notify_ipc_send 返回 0,不崩;
* T5 dismiss:meow_notify_ipc_dismiss(nid) 发出 MSG_NOTIFY_DISMISS 帧(负载=nid)。
*
* 编译(宿主 gcc,不依赖 meow_ui.a 其余 TU):
* gcc -o test_notify_ipc test_notify_ipc.c meow_notify_ipc.c \
* -I. -I../meow_launcherd -lpthread
* 运行:./test_notify_ipc (全部 PASS 退出码 0,任一 FAIL 退出码 1)
*/
#include "meow_notify_ipc.h"
#include "meow_ui.h"
#include "meow_ipc.h" /* 帧头 / m_notify_t / m_ack_t / MSG_*(同源校验) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pthread.h>
/* ---- 捕获:stub 服务端解析到的帧内容(mutex 保护;客户端返回后读取) ---- */
typedef struct {
uint32_t type; /* 收到的帧类型 */
m_notify_t n; /* MSG_NOTIFY 负载 */
uint32_t dismiss_id; /* MSG_NOTIFY_DISMISS 负载 */
uint32_t req_id;
uint32_t nid_to_return; /* ACK 中回填的 status */
int got; /* 已收到一帧 */
} cap_t;
static cap_t g_cap;
static pthread_mutex_t g_cap_mu = PTHREAD_MUTEX_INITIALIZER;
static void cap_store(uint32_t type, uint32_t req_id, const uint8_t *pay, uint32_t len,
uint32_t nid_to_return)
{
pthread_mutex_lock(&g_cap_mu);
memset(&g_cap, 0, sizeof g_cap);
g_cap.type = type;
g_cap.req_id = req_id;
g_cap.nid_to_return = nid_to_return;
if (type == MSG_NOTIFY && len >= sizeof(m_notify_t)) memcpy(&g_cap.n, pay, sizeof(m_notify_t));
if (type == MSG_NOTIFY_DISMISS && len >= 4) memcpy(&g_cap.dismiss_id, pay, 4);
g_cap.got = 1;
pthread_mutex_unlock(&g_cap_mu);
}
/* ---- stub 服务端线程:accept 一个连接 → 读一帧 → 校验由主线程做,这里只收 + 回 ACK ---- */
static int g_listen_fd = -1;
static void *server_thread(void *arg)
{
(void)arg;
int c = accept(g_listen_fd, NULL, NULL);
if (c < 0) return NULL;
/* 读 16B 头 */
uint8_t hdr[MEOW_IPC_HDR_LEN];
uint32_t off = 0;
while (off < sizeof hdr) {
ssize_t r = read(c, hdr + off, sizeof hdr - off);
if (r <= 0) { close(c); return NULL; }
off += (size_t)r;
}
uint32_t magic, len;
uint16_t ver, type;
memcpy(&magic, hdr, 4);
memcpy(&ver, hdr + 4, 2);
memcpy(&type, hdr + 6, 2);
memcpy(&len, hdr + 12, 4);
uint32_t req_id; memcpy(&req_id, hdr + 8, 4);
if (magic != MEOW_IPC_MAGIC || ver != MEOW_IPC_VERSION) { close(c); return NULL; }
if (len > MEOW_IPC_MAX) { close(c); return NULL; }
uint8_t pay[MEOW_IPC_MAX];
off = 0;
while (off < len) {
ssize_t r = read(c, pay + off, len - off);
if (r <= 0) { close(c); return NULL; }
off += (size_t)r;
}
cap_store(type, req_id, pay, len, (uint32_t)strtoul(getenv("TEST_NID"), NULL, 0));
/* MSG_NOTIFY → 回 m_ack_t(code=OK, status=nid_to_return);
* MSG_NOTIFY_DISMISS → 回 m_ack_t(code=OK, status=0,同 launcher 行为)。 */
if (type == MSG_NOTIFY || type == MSG_NOTIFY_DISMISS) {
m_ack_t a;
memset(&a, 0, sizeof a);
a.code = MEOW_OK;
a.status = (type == MSG_NOTIFY) ? (uint32_t)strtoul(getenv("TEST_NID"), NULL, 0) : 0;
uint8_t rhdr[MEOW_IPC_HDR_LEN];
uint32_t rmagic = MEOW_IPC_MAGIC;
uint16_t rver = MEOW_IPC_VERSION, rtype = (uint16_t)(type == MSG_NOTIFY ? MSG_NOTIFY_ACK : MSG_ACK);
uint32_t rlen = sizeof a;
memcpy(rhdr + 0, &rmagic, 4);
memcpy(rhdr + 4, &rver, 2);
memcpy(rhdr + 6, &rtype, 2);
memcpy(rhdr + 8, &req_id, 4);
memcpy(rhdr + 12, &rlen, 4);
off = 0;
while (off < sizeof rhdr) { ssize_t w = write(c, rhdr + off, sizeof rhdr - off); if (w <= 0) break; off += (size_t)w; }
off = 0;
while (off < rlen) { ssize_t w = write(c, (uint8_t*)&a + off, rlen - off); if (w <= 0) break; off += (size_t)w; }
}
close(c);
return NULL;
}
static int failures = 0;
static void check(const char *name, int cond)
{
printf("%s %s\n", cond ? "PASS" : "FAIL", name);
if (!cond) failures++;
}
/* 建 listening socket,返回 fd;路径写入 sock_path。 */
static int arb_listen(char *sock_path, size_t slen)
{
static int count = 0;
snprintf(sock_path, slen, "/tmp/meow_notify_ipc_%d_%d.sock", (int)getpid(), count++);
unlink(sock_path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) { perror("socket"); return -1; }
struct sockaddr_un a;
memset(&a, 0, sizeof a);
a.sun_family = AF_UNIX;
strncpy(a.sun_path, sock_path, sizeof a.sun_path - 1);
if (bind(fd, (struct sockaddr *)&a, sizeof a) < 0) { perror("bind"); close(fd); return -1; }
if (listen(fd, 1) < 0) { perror("listen"); close(fd); return -1; }
return fd;
}
int main(void)
{
setenv("MEOW_LOG_APP", "testapp", 1); /* 固定 app_id,供 stub 校验 */
/* ---------- T1/T2/T3:映射 + ACK 回 nid ---------- */
{
char sock[108];
g_listen_fd = arb_listen(sock, sizeof sock);
if (g_listen_fd < 0) { fprintf(stderr, "cannot create listener\n"); return 2; }
setenv("MEOW_IPC_SOCK", sock, 1);
setenv("TEST_NID", "0x1234", 1);
pthread_t th;
pthread_create(&th, NULL, server_thread, NULL);
meow_notify nt;
memset(&nt, 0, sizeof nt);
nt.cat = MEOW_NOTIFY_CAT_PROGRESS;
nt.urgency = MEOW_NOTIFY_URG_NORMAL;
nt.title = "下载中";
nt.body = "70%";
nt.timeout_ms = 5000; /* >0 → expire=5000, ongoing=0 */
nt.progress = 150; /* 钳位 → 100 */
uint32_t nid = meow_notify_ipc_send(&nt, 0);
pthread_join(th, NULL);
close(g_listen_fd);
check("T3 send 返回 launcher nid(0x1234)", nid == 0x1234);
pthread_mutex_lock(&g_cap_mu);
int got = g_cap.got;
const m_notify_t *cn = &g_cap.n;
pthread_mutex_unlock(&g_cap_mu);
check("T3 stub 收到 MSG_NOTIFY 帧", got && g_cap.type == MSG_NOTIFY);
check("T1 CAT_PROGRESS→category=progress", !strcmp(cn->category, "progress"));
check("T2 timeout>0→expire_timeout=5000", cn->expire_timeout == 5000);
check("T2 timeout>0→ongoing=0", cn->ongoing == 0);
check("T1 media=0(非媒体)", cn->media == 0);
check("T1 progress 钳位 150→100", cn->progress == 100);
check("T2 replaces_id 透传=0", cn->replaces_id == 0);
check("T1 app_id=testapp", !strcmp(cn->app_id, "testapp"));
check("T1 summary=下载中", !strcmp(cn->summary, "下载中"));
}
/* ---------- T1/T2:媒体类型 + ONGOING(-1) ---------- */
{
char sock[108];
g_listen_fd = arb_listen(sock, sizeof sock);
setenv("MEOW_IPC_SOCK", sock, 1);
setenv("TEST_NID", "0x9999", 1);
pthread_t th;
pthread_create(&th, NULL, server_thread, NULL);
meow_notify nt;
memset(&nt, 0, sizeof nt);
nt.cat = MEOW_NOTIFY_CAT_MEDIA;
nt.urgency = MEOW_NOTIFY_URG_CRITICAL;
nt.title = "Now Playing";
nt.timeout_ms = MEOW_NOTIFY_TIMEOUT_ONGOING; /* -1 */
uint32_t nid = meow_notify_ipc_send(&nt, 0);
pthread_join(th, NULL);
close(g_listen_fd);
check("T3 send(media/ongoing) 返回 nid(0x9999)", nid == 0x9999);
check("T1 CAT_MEDIA→category=media", !strcmp(g_cap.n.category, "media"));
check("T1 CAT_MEDIA→media=1", g_cap.n.media == 1);
check("T2 ONGOING(-1)→expire=0xFFFFFFFF", g_cap.n.expire_timeout == 0xFFFFFFFFu);
check("T2 ONGOING(-1)→ongoing=1", g_cap.n.ongoing == 1);
}
/* ---------- T2:NEVER(0) 超时 ---------- */
{
char sock[108];
g_listen_fd = arb_listen(sock, sizeof sock);
setenv("MEOW_IPC_SOCK", sock, 1);
setenv("TEST_NID", "0x1", 1);
pthread_t th;
pthread_create(&th, NULL, server_thread, NULL);
meow_notify nt;
memset(&nt, 0, sizeof nt);
nt.cat = MEOW_NOTIFY_CAT_GENERAL;
nt.title = "x";
nt.timeout_ms = MEOW_NOTIFY_TIMEOUT_NEVER; /* 0 */
(void)meow_notify_ipc_send(&nt, 0);
pthread_join(th, NULL);
close(g_listen_fd);
check("T2 NEVER(0)→expire=0 & ongoing=0",
g_cap.n.expire_timeout == 0 && g_cap.n.ongoing == 0);
check("T1 CAT_GENERAL→category=general", !strcmp(g_cap.n.category, "general"));
}
/* ---------- T3:replaces_id 透传 ---------- */
{
char sock[108];
g_listen_fd = arb_listen(sock, sizeof sock);
setenv("MEOW_IPC_SOCK", sock, 1);
setenv("TEST_NID", "0xBEEF", 1);
pthread_t th;
pthread_create(&th, NULL, server_thread, NULL);
meow_notify nt;
memset(&nt, 0, sizeof nt);
nt.cat = MEOW_NOTIFY_CAT_MESSAGE;
nt.title = "repl";
nt.timeout_ms = 0;
(void)meow_notify_ipc_send(&nt, 0x42u);
pthread_join(th, NULL);
close(g_listen_fd);
check("T3 replaces_id 透传=0x42", g_cap.n.replaces_id == 0x42u);
}
/* ---------- T4:无 socket 降级不崩 ---------- */
{
/* 指向不存在路径 */
char dead[108];
snprintf(dead, sizeof dead, "/tmp/meow_notify_ipc_dead_%d.sock", (int)getpid());
unlink(dead);
setenv("MEOW_IPC_SOCK", dead, 1);
meow_notify nt;
memset(&nt, 0, sizeof nt);
nt.cat = MEOW_NOTIFY_CAT_EMAIL;
nt.title = "no-socket";
nt.timeout_ms = 0;
uint32_t nid = meow_notify_ipc_send(&nt, 0);
check("T4 无 socket→返回 0(降级不崩)", nid == 0);
meow_notify_ipc_dismiss(0x1234); /* 无 socket 静默,不崩 */
check("T4 dismiss 无 socket 静默不崩", 1);
}
/* ---------- T5:dismiss 发 MSG_NOTIFY_DISMISS ---------- */
{
char sock[108];
g_listen_fd = arb_listen(sock, sizeof sock);
setenv("MEOW_IPC_SOCK", sock, 1);
pthread_t th;
pthread_create(&th, NULL, server_thread, NULL);
meow_notify_ipc_dismiss(0xABCDu);
pthread_join(th, NULL);
close(g_listen_fd);
check("T5 stub 收到 MSG_NOTIFY_DISMISS 帧", g_cap.got && g_cap.type == MSG_NOTIFY_DISMISS);
check("T5 dismiss 负载=nid=0xABCD", g_cap.dismiss_id == 0xABCDu);
}
printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS",
failures, failures == 1 ? "" : "s");
return failures ? 1 : 0;
}