Files
AskaEth 3d70a3dd2c feat: M6.10–M6.19 批量收编 + M6.19 推卡验收
- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘)
- OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复
- ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640
- 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫)
- 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
2026-09-03 12:16:01 +08:00

190 lines
8.1 KiB
C
Raw Permalink 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_meow_cachegov.c — 宿主测试:SDK meow_cachegov(A:DONTNEED L0/L1 + refault 回退)。
*
* 背景(OOM_PAGECACHE_GOVERNANCE §2/§4,③混合):A 的 DONTNEED/read_pos 热路径随 SDK 库;
* 本测试用宿主桩:
* - 真实 posix_fadvise(文件数据完整性校验:drop 后文件内容不变、drop_finished 可再读);
* - meow_log 桩捕获 "[cachegov] L1 drop off=.. len=.." 断言丢弃范围([0, read_pos-keep_hot));
* - meow_cachegov_test_set_time_ms() 注入时钟驱动 refault 滚窗回退(放大 keep_hot→降L0→关A);
* - MEOW_CACHEGOV_C_FILE 指向临时文件写入 fake C 状态,断言 download_paused/prefetch_paused。
*
* 编译(patch_v2/sdk 目录下):
* gcc -Os -Wall -Wextra -I. -Iinclude -I../meow_launcherd -c meow_cachegov.c -o /tmp/cg.o
* gcc -Os -Wall -Wextra -I. -Iinclude -I../meow_launcherd test_meow_cachegov.c /tmp/cg.o -lpthread -o test_meow_cachegov
* 运行:./test_meow_cachegov (exit 0=PASS / 1=FAIL)
*/
#define _GNU_SOURCE
#include "meow_cachegov.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
/* ---- meow_log 桩:捕获最近一条 [cachegov] 行,供断言 ---- */
static char g_last_log[512];
void meow_log(int lvl, const char *fmt, ...)
{
(void)lvl;
va_list ap; va_start(ap, fmt);
vsnprintf(g_last_log, sizeof g_last_log, fmt, ap);
va_end(ap);
printf(" [cachegov.log] %s\n", g_last_log);
}
static int log_has(const char *needle) { return strstr(g_last_log, needle) != NULL; }
static int g_pass = 0, g_fail = 0;
static void check(const char *name, int cond)
{
if (cond) { g_pass++; printf("PASS %s\n", name); }
else { g_fail++; printf("FAIL %s\n", name); }
}
/* ---- read_pos 桩:由测试驱动当前读指针 ---- */
static uint64_t g_pos;
static uint64_t fake_read_pos(void *ctx) { (void)ctx; return g_pos; }
/* 建一个 size 字节的临时文件并填充确定性内容。 */
static int make_file(const char *path, size_t size)
{
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) return -1;
for (size_t off = 0; off < size; off += 4096) {
char tmp[4096];
memset(tmp, (int)(off / 4096) & 0xFF, sizeof tmp);
size_t n = (size - off) < sizeof tmp ? (size - off) : sizeof tmp;
if (write(fd, tmp, n) != (ssize_t)n) { close(fd); return -1; }
}
close(fd);
return 0;
}
/* 校验文件内容仍为确定性模式(drop 后数据完整)。 */
static int verify_file(const char *path, size_t size)
{
int fd = open(path, O_RDONLY);
if (fd < 0) return 0;
char tmp[4096];
size_t off = 0;
int ok = 1;
while (off < size) {
size_t n = (size - off) < sizeof tmp ? (size - off) : sizeof tmp;
ssize_t r = read(fd, tmp, n);
if (r != (ssize_t)n) { ok = 0; break; }
char expect[4096];
memset(expect, (int)(off / 4096) & 0xFF, n);
if (memcmp(tmp, expect, n) != 0) { ok = 0; break; }
off += (size_t)n;
}
close(fd);
return ok;
}
int main(void)
{
char path[320], cfile[360];
snprintf(path, sizeof path, "/tmp/meow_cg_%ld.bin", (long)getpid());
snprintf(cfile, sizeof cfile, "/tmp/meow_cg_%ld.state", (long)getpid());
setenv("MEOW_CACHEGOV_C_FILE", cfile, 1);
unlink(path); unlink(cfile);
const size_t size = 1024u * 1024u; /* 1MB 测试文件 */
check("make_file", make_file(path, size) == 0);
/* 1) cfg:默认 + set/get 往返 */
struct meow_cachegov_cfg c = {0};
meow_cachegov_get_cfg(&c);
check("cfg default enabled", c.enabled == 1);
check("cfg default keep_hot=256KB", c.keep_hot_bytes == 256u * 1024u);
struct meow_cachegov_cfg c2 = c;
c2.keep_hot_bytes = 128u * 1024u;
c2.drop_mode = 1;
c2.refault_backoff = 2;
check("set_cfg", meow_cachegov_set_cfg(&c2) == 0);
meow_cachegov_get_cfg(&c);
check("get_cfg roundtrip", c.keep_hot_bytes == 128u * 1024u && c.drop_mode == 1 && c.refault_backoff == 2);
/* 2) L1 drop:read_pos=512KB、keep_hot=128KB → drop [0, 384KB) off=0 len=384KB */
check("register", meow_cachegov_register(path, size, fake_read_pos, NULL) == 0);
g_pos = 512u * 1024u;
meow_cachegov_tick();
check("L1 drop off=0 len=384KB", log_has("L1 drop") && strstr(g_last_log, "off=0 len=393216"));
check("L1 range bounded by read_pos-keep_hot (no L2)",
!strstr(g_last_log, "off=393216") && strstr(g_last_log, "len=393216"));
/* 3) L1 推进:read_pos=800KB → drop [384KB, 800-128KB=672KB) off=384KB len=288KB */
g_pos = 800u * 1024u;
meow_cachegov_tick();
check("L1 drop off=384KB len=288KB", log_has("L1 drop") && strstr(g_last_log, "off=393216") && strstr(g_last_log, "len=294912"));
/* 4) refault 回退档1(放大 keep_hot 翻倍):3 次触发 2 次 → 0→1(每升降一档需间隔 ≥10s */
meow_cachegov_test_set_time_ms(0);
meow_cachegov_note_refault(); meow_cachegov_note_refault();
meow_cachegov_tick();
check("backoff -> 1 (refault*2)", meow_cachegov_backoff_level() == 1);
check("file intact after backoff1", verify_file(path, size));
/* 档1 且 keep_hot=128KB*2=256KB:read_pos=1000KB → drop 上界=744KB(已丢到 672KB) */
g_pos = 1000u * 1024u;
meow_cachegov_tick();
check("backoff1 L1 keep_hot enlarged (no L2)", meow_cachegov_backoff_level() == 1);
/* 5) 再 2 次(间隔 10s)→ 档2(L1 关,只 L0)→ download_paused=1 */
meow_cachegov_test_set_time_ms(11000);
meow_cachegov_note_refault(); meow_cachegov_note_refault();
meow_cachegov_tick();
check("backoff -> 2 (L1 off)", meow_cachegov_backoff_level() == 2);
g_pos = 900u * 1024u;
meow_cachegov_tick(); /* L1 off:应无新的 L1 drop 日志 */
check("level2 no L1 drop (only L0)", !log_has("L1 drop"));
check("download_paused @backoff>=2", meow_cachegov_download_paused() == 1);
/* 6) 再 2 次(间隔 10s)→ 档3(A 全关)→ prefetch_paused=1 + drop_finished 不再丢页 */
meow_cachegov_test_set_time_ms(22000);
meow_cachegov_note_refault(); meow_cachegov_note_refault();
meow_cachegov_tick();
check("backoff -> 3 (A off)", meow_cachegov_backoff_level() == 3);
check("prefetch_paused @backoff>=3", meow_cachegov_prefetch_paused() == 1);
meow_cachegov_test_set_time_ms(23000);
meow_cachegov_drop_finished(path);
check("drop_finished skip @A-off", log_has("drop_finished skip"));
check("file intact after A-off", verify_file(path, size));
/* 7) C 侧降载:write fake C state dl_pause=1;滚窗干净逐级降回 0 后 download_paused 仍 =1 */
{
FILE *f = fopen(cfile, "w");
check("write C state", f != NULL);
if (f) { fputs("cached_kb=35000\ndirty_kb=1000\ndl_pause=1\nprefetch_pause=0\n", f); fclose(f); }
}
meow_cachegov_test_set_time_ms(33000);
meow_cachegov_tick(); /* 3→2 */
meow_cachegov_test_set_time_ms(44000);
meow_cachegov_tick(); /* 2→1 */
meow_cachegov_test_set_time_ms(55000);
meow_cachegov_tick(); /* 1→0 */
check("backoff de-escalated to 0", meow_cachegov_backoff_level() == 0);
check("download_paused via C file", meow_cachegov_download_paused() == 1);
/* 8) L0 drop_finished(A 正常态):整文件 DONTNEED + 数据完整 + 注销条目 */
unlink(cfile);
meow_cachegov_register(path, size, fake_read_pos, NULL);
meow_cachegov_test_set_time_ms(66000);
meow_cachegov_drop_finished(path);
check("drop_finished L0 log", log_has("drop_finished L0"));
check("file intact after L0", verify_file(path, size));
check("unregister removes entry", meow_cachegov_unregister(path) != 0); /* 已注销 → 找不到 */
/* 9) disable 时 drop/tick 均 no-op:数据仍完整 */
c2.enabled = 0; meow_cachegov_set_cfg(&c2);
meow_cachegov_register(path, size, fake_read_pos, NULL);
g_pos = 512u * 1024u;
meow_cachegov_tick();
meow_cachegov_drop_finished(path);
check("file intact when disabled", verify_file(path, size));
unlink(path); unlink(cfile);
printf("----\n%d passed, %d failed\n", g_pass, g_fail);
return g_fail ? 1 : 0;
}