162 lines
6.8 KiB
C
162 lines
6.8 KiB
C
/* test_bg_keep.c — 批①`background_keepalive` 声明层宿主单测。
|
||
*
|
||
* 验证 meow_parse_app_json 对 app.json 后台三位(background / background_audio /
|
||
* background_keepalive)的解析与 meow_acct_sync 透传,重点覆盖**前缀不串扰**:
|
||
* - "background_keepalive":true → a->background_keepalive=='1';且 background/background_audio
|
||
* 在该行不被误命中(分别是 0/0);
|
||
* - background:true → a->background=='1'(独立键匹配不受影响);
|
||
* - background_audio:true → a->background_audio=='1';
|
||
* - 一行三键并存:三者各归其位;
|
||
* - meow_acct_sync 透传 background_keepalive 到注册表。
|
||
* 实现手法同 test_fg_act.c:真实 include app_launcher.c,-ffunction-sections -Wl,--gc-sections
|
||
* 只保留 parseInt/acct_sync/upsert/find 触及函数;json_str/meow_parse_depends/logmsg 由本文件提供
|
||
* 忠实桩(json_str 复刻 util.c 语义,含键前缀独立 ident_ch + 整体 UTF-8 截断)。
|
||
*
|
||
* 运行(patch_v2/meow_launcherd 下):
|
||
* gcc -D_GNU_SOURCE -Wall -Wextra -ffunction-sections -Wl,--gc-sections \
|
||
* -I. -o test_bg_keep test_bg_keep.c && ./test_bg_keep
|
||
* 全 PASS -> exit 0。
|
||
*/
|
||
#ifndef _GNU_SOURCE
|
||
#define _GNU_SOURCE
|
||
#endif
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdarg.h>
|
||
#include <stdlib.h>
|
||
|
||
/* ---- logmsg:app_launcher.c 依赖,minimal 桩 ---- */
|
||
void logmsg(const char *fmt, ...)
|
||
{
|
||
(void)fmt;
|
||
}
|
||
|
||
/* ---- json_str:复刻 util.c 语义(键前缀独立 + 值提取 + UTF-8 截断)---- */
|
||
static int ident_ch(char c)
|
||
{
|
||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||
(c >= '0' && c <= '9') || c == '_' || c == '.';
|
||
}
|
||
static void utf8_trim(char *s)
|
||
{
|
||
size_t n = strlen(s), i = 0, last_good = 0;
|
||
while (i < n) {
|
||
unsigned char c = (unsigned char)s[i];
|
||
int len = (c < 0x80) ? 1 : (c >= 0xF0) ? 4 : (c >= 0xE0) ? 3 : (c >= 0xC0) ? 2 : 1;
|
||
if (i + (size_t)len > n) break;
|
||
i += (size_t)len;
|
||
last_good = i;
|
||
}
|
||
s[last_good] = '\0';
|
||
}
|
||
int json_str(const char *buf, const char *key, char *out, int olen)
|
||
{
|
||
out[0] = 0;
|
||
if (!buf || !key || olen <= 0) return 0;
|
||
const char *p = strstr(buf, key);
|
||
if (!p) return 0;
|
||
if (p > buf && ident_ch((unsigned char)p[-1])) return 0; /* 键前缀需独立 */
|
||
p += strlen(key);
|
||
if (*p == '"') p++; /* JSON 键自身右引号 */
|
||
while (*p && (*p == ':' || *p == '=')) p++;
|
||
while (*p == ' ' || *p == '\t') p++;
|
||
if (*p == '"') p++; /* 值左引号 */
|
||
int i = 0;
|
||
while (*p && *p != '"' && *p != ',' && *p != '\n' && *p != '\r' && i < olen - 1)
|
||
out[i++] = *p++;
|
||
out[i] = 0;
|
||
while (i > 0 && (out[i - 1] == ' ' || out[i - 1] == '\t')) out[--i] = 0;
|
||
utf8_trim(out);
|
||
return (int)strlen(out);
|
||
}
|
||
|
||
#include "app_launcher.c" /* 真实实现:meow_parse_app_json / meow_acct_sync / meow_acct_upsert */
|
||
|
||
/* meow_parse_depends:本测试 app.json 无 depends 行,桩返回 0(struct meow_dep 此时已可见)。 */
|
||
int meow_parse_depends(const char *val, struct meow_dep *deps, int max)
|
||
{
|
||
(void)val; (void)deps; (void)max;
|
||
return 0;
|
||
}
|
||
|
||
static int g_fail = 0;
|
||
#define CHECK(cond, msg) do { \
|
||
if (!(cond)) { fprintf(stderr, "FAIL: %s (%s:%d)\n", msg, __FILE__, __LINE__); g_fail++; } \
|
||
else fprintf(stderr, "ok: %s\n", msg); \
|
||
} while (0)
|
||
|
||
/* 用一段 app.json 内容解析出 struct app。返回 0=成功。 */
|
||
static int parse_json(const char *content, struct app *a)
|
||
{
|
||
FILE *f = tmpfile();
|
||
if (!f) return -1;
|
||
fputs(content, f);
|
||
rewind(f);
|
||
memset(a, 0, sizeof *a);
|
||
meow_parse_app_json(f, a);
|
||
fclose(f);
|
||
return 0;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
/* ---- 1) 单独 background_keepalive:true ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n\"background_keepalive\":true\n}", &a);
|
||
CHECK(a.background_keepalive == '1', "background_keepalive:true -> '1'");
|
||
CHECK(a.background == 0, "keepalive 行不误命中 background (==0)");
|
||
CHECK(a.background_audio == 0, "keepalive 行不误命中 background_audio (==0)");
|
||
}
|
||
/* ---- 2) 单独 background:true ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n\"background\":true\n}", &a);
|
||
CHECK(a.background == '1', "background:true -> '1'(独立键匹配不受影响)");
|
||
CHECK(a.background_keepalive == 0, "background 行不串 to keepalive (==0)");
|
||
CHECK(a.background_audio == 0, "background 行不串 to background_audio (==0)");
|
||
}
|
||
/* ---- 3) 单独 background_audio:true ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n\"background_audio\":true\n}", &a);
|
||
CHECK(a.background_audio == '1', "background_audio:true -> '1'");
|
||
CHECK(a.background == 0, "background_audio 行不误命中 background (==0)");
|
||
CHECK(a.background_keepalive == 0, "background_audio 行不串 to keepalive (==0)");
|
||
}
|
||
/* ---- 4) 三键并存:各归其位(逐行格式,值后跟 , 或换行,同真实 app.json) ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n\"background\":true,\n"
|
||
"\"background_audio\":true,\n\"background_keepalive\":true\n}", &a);
|
||
CHECK(a.background == '1', "三键并存 background=='1'");
|
||
CHECK(a.background_audio == '1', "三键并存 background_audio=='1'");
|
||
CHECK(a.background_keepalive == '1', "三键并存 background_keepalive=='1'");
|
||
}
|
||
/* ---- 5) 假值 / 前导噪声不应置位 ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n\"background_keepalive\":false,\n"
|
||
"\"background_audio\":0\n}", &a);
|
||
CHECK(a.background_keepalive == 0, "background_keepalive:false -> 0");
|
||
CHECK(a.background_audio == 0, "background_audio:0 -> 0");
|
||
CHECK(a.background == 0, "无 background 键 -> 0");
|
||
}
|
||
/* ---- 6) meow_acct_sync 透传 ---- */
|
||
{
|
||
struct app a;
|
||
parse_json("{\n\"name\":\"X\",\n\"exec\":\"/usr/bin/x\",\n"
|
||
"\"background_keepalive\":true,\n\"background_audio\":true\n}", &a);
|
||
meow_acct_sync("dev.test.keep", &a); /* 以 app_id 建/更注册表项 */
|
||
struct meow_acct *ac = meow_acct_find("dev.test.keep");
|
||
CHECK(ac != NULL, "meow_acct_sync 建注册表项");
|
||
CHECK(ac && ac->background_keepalive == '1', "透传 background_keepalive=='1'");
|
||
CHECK(ac && ac->background_audio == '1', "透传 background_audio=='1'");
|
||
CHECK(ac && ac->background == 0, "透传 background==0");
|
||
}
|
||
|
||
if (g_fail) { fprintf(stderr, "\n== %d assertion(s) FAILED ==\n", g_fail); return 1; }
|
||
fprintf(stderr, "\n== test_bg_keep ALL PASS ==\n");
|
||
return 0;
|
||
}
|