Files
MeowOS-SDK/sdk/test_meow_cachegov.c
T
AskaEth 432875d4e6 sdk: 宿主测试头注释按实测修订 + select T1 探针修正
- test_meow_ui_select: T1 选中高亮探针移到容器卡内(x=12),
  适配 M6.37 起的 listview 默认容器模式;6/6 PASS
- 各 test_*.c 头注释补 -Iinclude、meow_ui_nav.c 及精简源列表最小补集
  (theme/widgets/notif_gesture/overlay/suppress/sdk_fixes/pinyin/ime_fix)
- test_sb_statusbar 头注释给出可链接命令(--allow-multiple-definition)
- notify_post/ui_audio_host/p1p2p3 标注需主仓组件,公开仓跳过
- docs/APP_DEV_GUIDE.md: 去掉叠字与过强表述,改为 34/38 实测口径
2026-11-04 20:26:35 +08:00

190 lines
8.1 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_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 -c meow_cachegov.c -o /tmp/cg.o
* gcc -Os -Wall -Wextra -I. -Iinclude 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;
}