test(ncm): M9 分类/登录门宿主单测(83 断言)+ 传输层归一 4 例 + REPORT §41
- bench/session_gate_sim.c(新):真实 core + ncm_http_request 桩,覆盖 A 错误分类矩阵(-4/-5/-6/-17/裸 mbedtls vs -13/其它)、B HTTP 状态矩阵 (401/403 vs 5xx/429 vs 3xx/4xx)、C 登录门 + 启动决策(无网→离线、无会话→扫码)、 D 真实 ncm_api 状态/业务码映射(含 -460→SVC、301/302→AUTH)、 E 真实 ncm_login_status_check/refresh 映射、F 会话密钥稳定性(换 MAC 仍可解、 旧 MAC 密文可解且自动迁移)。83 PASS / 0 FAIL,0 真实请求。 - bench/http_truncate_sim.c:追加 4 例传输层归一(握手 fatal alert→NET、握手超时→TIMEOUT、 读 fatal alert→NET、CA 失败→TLS),原 8 例截断守卫零回归(12 PASS)。 - build_ncm_sims.sh:window/search/plpage/apicache/cookie_refresh 链入 ncm_session.o (appstate/api/login 新依赖),新增 session_gate_sim 构建与运行。 - test_ncm_core.c:采用 M8 分支的 $TMPDIR 适配(Termux /tmp 不可写;合并时以 M8 为准)。 - 相关 sim 头注释同步链接命令(ncm_apicache.o/ncm_session.o)。 - REPORT §41:判定点调用链与行号、根因证据、实现、验证矩阵与诚实出入 (mipsel/真机未跑;app.c 宿主不可编译的既有原因;403/-460 取舍)。 验证:test_ncm_core_host 139 PASS/0 FAIL;session_gate_sim 83 PASS; http_truncate_sim 12 PASS;window/search/apicache/cookie_refresh sim 通过; 核心 12 TU + 应用 13 TU(-Wall -Wextra)0 warning。
This commit is contained in:
1 parent
e0bd503261
commit
2ca386973b
8 files changed
+606
-12
No files matched your search
@@ -15,6 +15,12 @@
|
||||
* chunked 完整(0 分块末端) → BS_DONE → NCM_OK
|
||||
* chunked 中途关闭 → 截断 → 非 NCM_OK(NCM_ERR_IO)
|
||||
*
|
||||
* M9 追加(传输层错误归一):mbedtls 裸负码不得原样穿透给上层——
|
||||
* 握手失败(fatal alert) → NCM_ERR_NET
|
||||
* 握手超时 → NCM_ERR_TIMEOUT
|
||||
* 读阶段 fatal alert(对端 reset/拒绝) → NCM_ERR_NET
|
||||
* CA 加载/校验失败(verify_ca=1) → NCM_ERR_TLS
|
||||
*
|
||||
* 编译(在 ncm_app 下):
|
||||
* gcc -O2 -Wall -Wextra -DJSMN_HEADER -I. -Icore -Ivendor/mbedtls/include \
|
||||
* -c bench/http_truncate_sim.c -o /tmp/t.o
|
||||
@@ -48,6 +54,8 @@ static const tr_chunk_t *g_script;
|
||||
static int g_script_n;
|
||||
static int g_script_i;
|
||||
static int g_close_rc; /* 脚本耗尽后的 ssl_read 返回值 */
|
||||
static int g_handshake_rc; /* M9:0=正常;否则握手直接失败(模拟网络/TLS 异常) */
|
||||
static int g_ca_fail; /* M9:1=CA 加载失败(verify_ca=1 时应判 NCM_ERR_TLS) */
|
||||
|
||||
static void tr_script(const tr_chunk_t *chunks, int n, int close_rc) {
|
||||
g_script = chunks; g_script_n = n; g_script_i = 0; g_close_rc = close_rc;
|
||||
@@ -110,13 +118,13 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, void *p_bio,
|
||||
mbedtls_ssl_recv_timeout_t *f_recv_timeout) {
|
||||
(void)ssl; (void)p_bio; (void)f_send; (void)f_recv; (void)f_recv_timeout;
|
||||
}
|
||||
int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) { (void)ssl; return 0; }
|
||||
int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) { (void)ssl; return g_handshake_rc; }
|
||||
void mbedtls_ssl_free(mbedtls_ssl_context *ssl) { (void)ssl; }
|
||||
void mbedtls_ssl_config_free(mbedtls_ssl_config *conf) { (void)conf; }
|
||||
|
||||
void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) { (void)crt; }
|
||||
int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *crt, const char *path) {
|
||||
(void)crt; (void)path; return 0; /* CA 加载成功(validate=0 时不走此径,桩兜底) */
|
||||
(void)crt; (void)path; return g_ca_fail ? -1 : 0; /* CA 加载成功/失败(M9 用例可控) */
|
||||
}
|
||||
void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) { (void)crt; }
|
||||
|
||||
@@ -136,12 +144,13 @@ static int on_body(void *ctx, const unsigned char *data, size_t len) {
|
||||
/* 运行一个用例:装填脚本 → 发起 GET 下载 → 记录 rc / body_len / content_length */
|
||||
typedef struct { int rc; size_t body_len; size_t content_length; } case_result_t;
|
||||
|
||||
static case_result_t run_case(const tr_chunk_t *script, int script_n, int close_rc) {
|
||||
static case_result_t run_case_ex(const tr_chunk_t *script, int script_n, int close_rc,
|
||||
int verify_ca) {
|
||||
ncm_http_req_t req;
|
||||
memset(&req, 0, sizeof req);
|
||||
req.url = "https://ex.test/song.mp3";
|
||||
req.method = "GET";
|
||||
req.verify_ca = 0; /* 跳过 CA 校验,聚焦 body 终态判定 */
|
||||
req.verify_ca = verify_ca; /* 0=跳过 CA 校验,聚焦 body 终态判定 */
|
||||
req.timeout_ms = 3000;
|
||||
|
||||
sink_cb_t sink; memset(&sink, 0, sizeof sink);
|
||||
@@ -157,6 +166,10 @@ static case_result_t run_case(const tr_chunk_t *script, int script_n, int close_
|
||||
return r;
|
||||
}
|
||||
|
||||
static case_result_t run_case(const tr_chunk_t *script, int script_n, int close_rc) {
|
||||
return run_case_ex(script, script_n, close_rc, 0);
|
||||
}
|
||||
|
||||
static int g_fail = 0;
|
||||
static void check(const char *name, int ok, const char *detail) {
|
||||
if (!ok) g_fail++;
|
||||
@@ -286,6 +299,40 @@ int main(void) {
|
||||
(r.rc != NCM_OK) && (r.rc == NCM_ERR_IO), dbg);
|
||||
}
|
||||
|
||||
/* ---- 场景 9(M9):握手 fatal alert(对端 reset/拒绝)→ 归一为 NCM_ERR_NET ---- */
|
||||
{
|
||||
g_handshake_rc = MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE;
|
||||
case_result_t r = run_case(NULL, 0, 0);
|
||||
g_handshake_rc = 0;
|
||||
snprintf(dbg, sizeof dbg, "rc=%d", r.rc);
|
||||
check("handshake_fatal_alert -> NCM_ERR_NET", r.rc == NCM_ERR_NET, dbg);
|
||||
}
|
||||
|
||||
/* ---- 场景 10(M9):握手超时 → NCM_ERR_TIMEOUT ---- */
|
||||
{
|
||||
g_handshake_rc = MBEDTLS_ERR_SSL_TIMEOUT;
|
||||
case_result_t r = run_case(NULL, 0, 0);
|
||||
g_handshake_rc = 0;
|
||||
snprintf(dbg, sizeof dbg, "rc=%d", r.rc);
|
||||
check("handshake_timeout -> NCM_ERR_TIMEOUT", r.rc == NCM_ERR_TIMEOUT, dbg);
|
||||
}
|
||||
|
||||
/* ---- 场景 11(M9):读阶段 fatal alert(连接被 reset)→ NCM_ERR_NET ---- */
|
||||
{
|
||||
case_result_t r = run_case(NULL, 0, MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);
|
||||
snprintf(dbg, sizeof dbg, "rc=%d", r.rc);
|
||||
check("read_fatal_alert -> NCM_ERR_NET", r.rc == NCM_ERR_NET, dbg);
|
||||
}
|
||||
|
||||
/* ---- 场景 12(M9):CA 不可用(verify_ca=1)→ NCM_ERR_TLS(不静默放行) ---- */
|
||||
{
|
||||
g_ca_fail = 1;
|
||||
case_result_t r = run_case_ex(NULL, 0, 0, 1);
|
||||
g_ca_fail = 0;
|
||||
snprintf(dbg, sizeof dbg, "rc=%d", r.rc);
|
||||
check("ca_load_fail -> NCM_ERR_TLS", r.rc == NCM_ERR_TLS, dbg);
|
||||
}
|
||||
|
||||
printf("\n== HTTP TRUNCATE SIM: %s ==\n", g_fail ? "FAIL" : "ALL PASS");
|
||||
return g_fail ? 1 : 0;
|
||||
}
|
||||
Reference in new issue
Block a user