fix(ncm §33): 流媒专项批六项——流式SIGSEGV防御日志/档位保真(无损级必须flac+显示档按实际)/封面4xx不重试/收藏显隐/缓存命名迁移/topbar位图图标
- §2① ncm_api.c level_attempt: 无损级(hires/lossless及以上)命中必须 type=flac,返回 mp3 视为该档不可用续降 (修「hires 档静默给 mp3 被当命中」) - §2② player_manager.c eff_level_for_resp: 显示档按响应实际格式/码率——mp3 绝不显示 Hi-Res(≤128k→标准, 否则极高), flac 采信链 eff; br 未知钳 ≤EXHIGH - §1 流式 SIGSEGV(《十面埋伏》sig=11) 审计+UBSAN 探针未复现 → 落地防御日志(dl start/done/interrupt + play done fin/exp/fail/underrun) - §3 cover.c: download_cover 回填 rc/status; 确定性 4xx(404等)不重试立即跳下一张, 仅瞬时错误退避(rc=%d status=%d 日志) - §4 playlist.c: pl_show_fav 我创建(is_collected==0)隐藏收藏钮, 我收藏保留, 搜索歌单保守显示(评论槽并入无空洞) - §5 ncm_cache.c 双点→单点迁移 + player_manager song_local_file 旧键→当前档位键(不重下) - §6 home.c: topbar 动作 ⚙↻⌕ 迁移 sb_icons 位图(meow_topappbar_set_item_icon, 修 4k 字库豆腐) - 测试: test_ncm_core 新 test_grade_flac_gate + test_cache 双点迁移断言; degrade_sim/player_flow_sim 桩 flac 化 - 验证: stream/player_flow/window/search/cache_evict/degrade sim 全 PASS + test_ncm_core host+mipsel(qemu) + mem_sim + build_ncm.sh 0 warning - 新 ncm md5 cb818786 (text 1017110/bss 1362500), 未部署留主会话; 0 真实 NCM 业务请求
This commit is contained in:
1 parent
68ce46a5d8
commit
44a790dc1d
13 files changed
+425
-24
No files matched your search
@@ -9,10 +9,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ncm.h"
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
/* §2① 档位保真离线测试用:注入 try_fn 的服务器行为模式 */
|
||||
static int g_grade_mode;
|
||||
|
||||
static int g_fail = 0;
|
||||
#define CHECK(cond, fmt, ...) do { \
|
||||
if (cond) printf(" PASS " fmt "\n", ##__VA_ARGS__); \
|
||||
@@ -147,15 +151,20 @@ static void test_cache(void) {
|
||||
CHECKRC(ncm_cache_path(&c, "103", ".flac", p2, sizeof p2), "path with dotted ext");
|
||||
CHECK(strstr(p2, "song_103.flac") != NULL && strstr(p2, "..") == NULL,
|
||||
"dotted ext normalized to single dot (%s)", p2);
|
||||
/* §19 温和兼容:历史双点名 song_<id>..mp3(旧版 ext 带前导点所致)lookup 可命中 */
|
||||
/* §19/§NEW 任务5:历史双点名 song_<id>..mp3(旧版 ext 带前导点所致)lookup 命中并
|
||||
* **迁移重命名**到单点名 song_<id>.mp3(不重下),双点存量自然消亡。 */
|
||||
{
|
||||
char legacy[NCM_CACHE_DIR_MAX + 40];
|
||||
snprintf(legacy, sizeof legacy, "%s/song_104..mp3", dir);
|
||||
FILE *lf = fopen(legacy, "wb");
|
||||
if (lf) { fputs("LEGACY", lf); fclose(lf); }
|
||||
int lrc = ncm_cache_lookup(&c, "104", "mp3", path, sizeof path);
|
||||
CHECK(lrc == NCM_OK && strstr(path, "song_104..mp3") != NULL,
|
||||
"legacy double-dot name hit (rc=%d path=%s)", lrc, path);
|
||||
CHECK(lrc == NCM_OK && strstr(path, "song_104.mp3") != NULL &&
|
||||
strstr(path, "..") == NULL,
|
||||
"legacy double-dot migrated to single-dot (rc=%d path=%s)", lrc, path);
|
||||
struct stat mst;
|
||||
CHECK(stat(legacy, &mst) != 0, "legacy double-dot file removed after migration");
|
||||
CHECK(stat(path, &mst) == 0 && mst.st_size == 6, "migrated file exists size=6");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +246,78 @@ static void test_network(void) {
|
||||
if (!net_ok) printf(" SKIP network live checks (host unreachable or TLS CA missing)\n");
|
||||
}
|
||||
|
||||
/* ---------- §2① 档位保真:SQ 及以上(lossless/hires)命中必须 flac ----------
|
||||
* 服务端对无损档请求静默返回 mp3 时,视为「该档不可用」继续降级(修「hires 档静默给 mp3
|
||||
* 被当命中」)。注入 try_fn 离线验证(0 真实请求)。 */
|
||||
static int grade_gate_try(const char *device_id, const char *cookie,
|
||||
const char *id, int level, ncm_play_url_t *out)
|
||||
{
|
||||
(void)device_id; (void)cookie; (void)id;
|
||||
memset(out, 0, sizeof *out);
|
||||
if (g_grade_mode == 0) {
|
||||
/* 全曲库只有 mp3:lossless+ 请求被静默降成 mp3(谎报 level 为请求档) */
|
||||
snprintf(out->url, sizeof out->url, "http://x/song_%d.mp3", level);
|
||||
ncm_strlcpy(out->type, "mp3", sizeof out->type);
|
||||
ncm_strlcpy(out->level, ncm_api_level_str(level), sizeof out->level);
|
||||
out->br = 320000;
|
||||
} else if (g_grade_mode == 1) {
|
||||
/* lossless 有 flac、hires 只有 mp3(降级场景) */
|
||||
if (level == NCM_LEVEL_HIRES) {
|
||||
snprintf(out->url, sizeof out->url, "http://x/song.mp3");
|
||||
ncm_strlcpy(out->type, "mp3", sizeof out->type);
|
||||
ncm_strlcpy(out->level, "hires", sizeof out->level); /* 服务端谎报 hires */
|
||||
out->br = 320000;
|
||||
} else if (level == NCM_LEVEL_LOSSLESS) {
|
||||
snprintf(out->url, sizeof out->url, "http://x/song.flac");
|
||||
ncm_strlcpy(out->type, "flac", sizeof out->type);
|
||||
ncm_strlcpy(out->level, "lossless", sizeof out->level);
|
||||
out->br = 900000;
|
||||
} else {
|
||||
snprintf(out->url, sizeof out->url, "http://x/song.mp3");
|
||||
ncm_strlcpy(out->type, "mp3", sizeof out->type);
|
||||
ncm_strlcpy(out->level, ncm_api_level_str(level), sizeof out->level);
|
||||
out->br = 320000;
|
||||
}
|
||||
} else {
|
||||
/* hires 有 flac(正常无损链) */
|
||||
snprintf(out->url, sizeof out->url, "http://x/song.flac");
|
||||
ncm_strlcpy(out->type, "flac", sizeof out->type);
|
||||
ncm_strlcpy(out->level, ncm_api_level_str(level), sizeof out->level);
|
||||
out->br = 900000;
|
||||
}
|
||||
return NCM_OK;
|
||||
}
|
||||
|
||||
static void test_grade_flac_gate(void) {
|
||||
printf("== §2① 档位保真:lossless+ 必须 flac 命中 ==\n");
|
||||
ncm_play_url_t u; int el;
|
||||
/* 只有 mp3 的曲库:请求 hires → 应降到 exhigh(<lossless 的最高 mp3 档)并拿 mp3 */
|
||||
g_grade_mode = 0;
|
||||
int rc = ncm_api_song_url_auto_av_f("dev", "", "409931770", NCM_VIP_SVIP, 0,
|
||||
NCM_LEVEL_HIRES, &u, &el, grade_gate_try);
|
||||
CHECK(rc == NCM_OK && el == NCM_LEVEL_EXHIGH && ncm_streq(u.type, "mp3"),
|
||||
"mp3-only repo: hires->exhigh (rc=%d el=%d type=%s)", rc, el, u.type);
|
||||
/* 只有 mp3 的曲库:请求 lossless → 也降到 exhigh */
|
||||
g_grade_mode = 0;
|
||||
rc = ncm_api_song_url_auto_av_f("dev", "", "409931770", NCM_VIP_SVIP, 0,
|
||||
NCM_LEVEL_LOSSLESS, &u, &el, grade_gate_try);
|
||||
CHECK(rc == NCM_OK && el == NCM_LEVEL_EXHIGH && ncm_streq(u.type, "mp3"),
|
||||
"mp3-only repo: lossless->exhigh (rc=%d el=%d)", rc, el);
|
||||
/* hires 只有 mp3、lossless 有 flac:请求 hires → 降到 lossless 并拿 flac */
|
||||
g_grade_mode = 1;
|
||||
rc = ncm_api_song_url_auto_av_f("dev", "", "409931770", NCM_VIP_SVIP, 0,
|
||||
NCM_LEVEL_HIRES, &u, &el, grade_gate_try);
|
||||
CHECK(rc == NCM_OK && el == NCM_LEVEL_LOSSLESS && ncm_streq(u.type, "flac"),
|
||||
"hires mp3 + lossless flac: hires->lossless flac (rc=%d el=%d type=%s)",
|
||||
rc, el, u.type);
|
||||
/* hires 有 flac:正常命中 hires */
|
||||
g_grade_mode = 2;
|
||||
rc = ncm_api_song_url_auto_av_f("dev", "", "409931770", NCM_VIP_SVIP, 0,
|
||||
NCM_LEVEL_HIRES, &u, &el, grade_gate_try);
|
||||
CHECK(rc == NCM_OK && el == NCM_LEVEL_HIRES && ncm_streq(u.type, "flac"),
|
||||
"hires flac: hit hires (rc=%d el=%d type=%s)", rc, el, u.type);
|
||||
}
|
||||
|
||||
/* ---------- 二期:/api/playlist/track/all 服务端分页 离线解析 ---------- */
|
||||
static void test_track_all_parse(void) {
|
||||
printf("== track_all 离线解析(二期)==\n");
|
||||
@@ -391,6 +472,7 @@ int main(int argc, char **argv) {
|
||||
test_track_all_parse();
|
||||
test_vip_parse();
|
||||
test_json_unescape();
|
||||
test_grade_flac_gate();
|
||||
|
||||
printf("\n%s\n", g_fail ? "== RESULT: FAIL ==" : "== RESULT: PASS ==");
|
||||
return g_fail ? 1 : 0;
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user