fix(tests): 修复 LF 检出下 3 处失败与 3 处「假绿」空过,并补 CI 的 Linux 一档 - #15
Merged
Merged
Conversation
实测:Linux/LF 检出下 `npm test` 为 199 pass / 3 fail,而 main 的 Windows CI 全绿。
差异全部来自换行符与真实 DNS,不是业务逻辑——即「CI 绿」掩盖了 3 类真问题。
1) 契约测试的注释剥离器两处失真(test_app_update_contract)
旧实现 `line.replace(/\/\/.*$/, '')`:LF 下吃掉字符串字面量里的 `//`
(`format!("https://…/commits/{branch}")` 尾部被剪 → 端点断言恒失败);
CRLF 下 `.` 不匹配 `\r` 而 `$` 锚定其后 → 完全不生效(Windows/CI 即此情形:
注释原样留下,写一句解释性注释就误报)。统一改用按字符扫描的
tests/helpers/strip-rust-comments.mjs(跳过字符串/字符/原始串、支持嵌套块注释,LF 与 CRLF 一致)。
2) 安全用例可「真回归空过」(test_secret_injection)
粗放剥离把 `ep.contains("//")`、URL 字面量这类行从 `//` 起整段吃掉,而本文件断言全是负向。
实测注入 `let _probe = format!("http://…"); cmd.arg("--api-key");`:
旧实现 4 passed(漏判),新实现正确判红。
3) 视觉内联用例依赖真实 DNS(test_vision_inlining)
真实取数路径在 _url_to_data_uri 内部自行解析域名,而桩只替换了无生产调用点的
_url_is_safe_for_fetch(已核实零生产调用点)。后果:正例离线必红;反例则「因解析失败提前返回」
而空过——实测把 Content-Type 兜底整个关掉,离线时该用例依然全绿。改为打桩
converter._resolve_host_ips。
4) 盘根扫描用例写死 Windows 路径形态(test_turing_findsdk_chain)
`path.join('Z:\','workbuddy')` 在 POSIX 是 `Z:\/workbuddy`,写死的 `^z:/(workbuddy)/` 恒不匹配。
期望值改为与实现同源推导;变异验证:去掉盘根扫描后本用例仍会变红。
5) 隔离运行器常年红、故无人接入(harness 与用例互相矛盾)
run_isolated_tests.py 的 autouse 夹具把 usage_log 指向临时目录,而
test_record_usage_disabled_is_noop 断言该键「默认即 None」→ 该门禁恒失败。
用例改为显式 monkeypatch 置 None;隔离运行器现 423 passed / exit 0。
6) 坏路径用例在 POSIX 上往仓库根写垃圾文件(test_converter)
`r"Z:\__no_such_dir__\usage.jsonl"` 在 POSIX 是合法相对文件名 → 生成同名文件(.gitignore 未覆盖),
且用例实际走成功分支、没验证到失败兜底。改用 tmp_path 下不存在的子目录。
7) converter.py 补 `Any` 导入:12 处注解用到 Any 却只 import 了 Optional,
仅靠 `from __future__ import annotations` 未炸(mypy / get_type_hints 会失败)。
8) CI 增加 checks-linux(LF + 禁网):上述缺陷的共同成因是「只跑 Windows + 检出为 CRLF + 有真实 DNS」。
原 job 不动,Linux 档只跑 pytest / 隔离运行器 / 前端测试(不含 cargo:Linux 上 Tauri 需额外系统库)。
AGENTS.md 补「改测试前必读」四条与隔离运行器命令。
验证(LF 与 CRLF 两种检出下均实测全绿):
pytest 423 passed | 隔离运行器 423 passed / exit 0 | npm test 202 passed | check_premarked_sync ✓
未跑:cargo test(本机无 Rust 工具链)、上游真实请求。
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
一、Issue #14 上游看门(4 项评估结论:均无需吸收代码) · Sliverkiss 4ac68b77 global chat 走 /v2 绕 WAF —— converter.py 本就原生直连 /v2,无需改动 · momo0410 91b9a292 非 Windows Child::kill —— 本项目为 Windows Tauri(taskkill 进程树保护),不适用 · ardeyouxipianyi 95c3e41d UI 调整 —— 本项目为独立控制中心,无需吸收 · orangeboyChen 7ccf62f9 prepare release v1.3.8 —— 常规发版 落地:4 项 last_synced_commit/last_synced_sha 推进至最新;ardeyou 仓库更名 workbuddy2api-intl -> workbuddy2api-hub(name 同步注明);updated_at -> 2026-09-18。 实跑 tools/check-upstream.py:0 项待评估、0 项查询失败(满足工作流自动收口条件); --lint 通过(19 个源)。 二、SSRF 校验两份实现/死代码 -> 收敛为单一实现 新增 converter._resolve_public_connect_ip(host) -> (ip|None, 原因):「主机/IP 是否可连」的唯一实现。 · _url_is_safe_for_fetch 仅保留 URL 级职责(协议白名单 + 取 host),判定全部委托; · _url_to_data_uri 逐跳校验改为调用同一函数,拒绝路径 3 条 -> 1 条。 副带修复:本机/元数据主机名单(_BLOCKED_IMAGE_HOSTS、*.localhost)此前只在 那份零调用点的死代码里生效,现真实下载路径也覆盖。 防漂移用例 test_url_level_and_fetch_path_share_one_validator 锁定两条路径共用同一函数 (变异验证:把任一处改回内联判定即变红)。 连带:test_vision_inlining 不再打桩那个假接缝(_url_is_safe_for_fetch),只打桩真实接缝(DNS); 并修掉 test_ssrf_guard_blocks_dangerous_urls 中 expect_keyword 只收集不断言的真空断言。 三、responses_projection.saw_output 关闭 确认为重构残留(`Output:` 是 Codex 执行器分段标题行,本应无条件丢弃),非漏分支。 删除标志并注释保留未来分支的提示;用例补 assert "Output:" not in content 与 content.count("Key output:") == 1,锁定「丢弃标题 != 省略正文标题」。 四、测试全局配置隔离 test_snapshots_stream_resp / test_snapshots_wire / test_snapshots(_enable + 4 用例) 全部改走 monkeypatch.setitem;conftest 新增 autouse _isolate_global_config, 每例结束把 CONFIG 恢复为快照作为兜底护栏(探针验证:移除护栏即复现泄漏)。 验证:LF 与 CRLF 两种检出下 pytest 424 passed / 隔离运行器 424 passed exit 0 / npm test 202 passed / premarked 同步 ✓ / upstream --lint ✓。 未跑:cargo test(本机无 Rust 工具链);未打真实 CodeBuddy 上游。 Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个 PR 做了什么
跑仓库自带门禁时发现一件事:Windows CI 全绿,但 LF 检出下
npm test是 199 pass / 3 fail。差异全部来自换行符与真实 DNS,不是业务逻辑——也就是说 CI 的绿掩盖了 3 类真问题。本 PR 修掉这 3 处失败、3 处「假绿」空过、2 处测试基建缺陷与 1 处静态检查问题,并补了守门的一档 CI。不改任何业务逻辑:
converter.py只有 1 行改动(补Any导入),其余全是测试/CI/文档。修复清单
//(端点断言恒失败);CRLF 下完全空转(写一句解释性注释即误报)proxy.rs的ep.contains("//")等行被整段吃掉converter.py12 处用了Any却未导入关键证据(变异验证,不是「跑绿了」而已)
① 安全用例的空过——往
proxy.rs注入let _probe = format!("http://127.0.0.1:{port}/health"); cmd.arg("--api-key");:# pass 4 / # fail 0—— 漏判真回归② 视觉用例的空过——把 Content-Type 兜底整段关掉,在禁 DNS 环境下:
1 passed—— 空过1 failed—— 抓到③ 注释剥离器:代码里重新引入
releases/latest→ 新旧都抓到;注释里提到它 → 旧实现在 LF 下误报、CRLF 下漏判,新实现正确放行。④ 盘根扫描用例:把盘根扫描整段去掉 → 仍变红(
实际:[]),说明没退化成恒绿。验证
LF 与 CRLF(全仓转 CRLF 的副本,等价于 Windows 检出)两种检出下均实测全绿:
pytest -qtests/run_isolated_tests.pynpm test(LF)npm test(CRLF)check_premarked_sync.py未验证(如实声明):
cargo test没跑——沙箱无 Rust 工具链,Rust 侧本轮只读未改;未打真实上游;未在真实 Windows 上执行(用 CRLF 副本等价验证)。converter.py约 7.9k 行未逐行审阅。评审时请留意
checks-linuxjob 可以删。原cijob 我没动;Linux 档只跑 pytest / 隔离运行器 / 前端测试(不含 cargo——Linux 上 Tauri 需额外系统库)。其余修复不依赖它。tests/helpers/strip-rust-comments.mjs是新文件,两处测试共用;它按字符扫描,会跳过字符串/字符/原始串并支持嵌套块注释。docs/audit-2026-09-17.md的高危项,SSRF / 40 位 SHA / 原子落盘 / 交错工具分块 / 错误帧传播 / 降级误标 均已修复,不必再按旧报告追。未修,留给后续(详见
docs/audit-2026-09-18.md§3)_url_is_safe_for_fetch是死代码(零生产调用点),SSRF 校验存在两份且已出现差异。旧报告把它当防线、多个用例在替换它——这给的是虚假信心;真正生效的是_url_to_data_uri内部那份。建议抽公共 helper 或删掉死函数。Any能潜伏至今的原因。残留噪声里responses_projection.py:575的saw_output赋值后从未读取,像是漏了一步判断,建议确认意图而非直接删。CONFIG不还原(test_snapshots_stream_resp.py:23、test_snapshots_wire.py:29),属潜在顺序依赖。第二轮(新增提交
028e871)一、Issue #14 上游看门:4 项评估完成,均无需吸收代码
Sliverkiss/workbuddy2api4ac68b77(global chat 固定走/v2绕开/consoleWAF)converter.py本就原生直连/v2/chat/completions,天然具备该特性momo0410/workbuddy-switch-gateway91b9a292(非 Windows 改用Child::kill)ardeyouxipianyi/workbuddy2api-intl95c3e41d(UI 调整;仓库已更名workbuddy2api-hub)repo字段更名orangeboyChen/codebuddy2api7ccf62f9(prepare release v1.3.8)落地:4 项基线推进 +
repo更名同步;--lint✅;本地实跑巡检得「0 项待评估 / 0 项查询失败」——满足工作流自动收口条件,合并进 main 后 Issue #14 会被 CI 自动关闭(不手工关闭,以免与实际巡检状态脱节)。二、报告 §3 三项工程/测试问题闭环
SSRF 校验收敛为单一实现(消除死代码)
新增
converter._resolve_public_connect_ip(host) -> (ip|None, 原因)作为「主机/IP 是否可连」的唯一实现:_url_is_safe_for_fetch只保留 URL 级职责(协议白名单 + 取 host);_url_to_data_uri的逐跳校验改为调用同一函数(拒绝路径 3 条 → 1 条)。副带修复:本机/元数据主机名单(
_BLOCKED_IMAGE_HOSTS、*.localhost)此前只在那份零调用点的死代码里,真实下载路径并未执行,现已覆盖。
防漂移用例
test_url_level_and_fetch_path_share_one_validator锁定两条路径共用同一函数——变异验证:把任一处改回内联判定即变红。连带:
test_vision_inlining不再打桩那个假接缝(_url_is_safe_for_fetch,零调用点),只打桩真实接缝(DNS);并修掉
test_ssrf_guard_blocks_dangerous_urls中expect_keyword只收集不断言的真空断言。responses_projection.py:575的saw_output关闭确认为重构残留而非漏分支:
Output:是 Codex 执行器的分段标题行,本应无条件丢弃。删除标志 + 注释保留「将来若要按它分支需连同契约一起改」的提示;用例补
assert "Output:" not in content与content.count("Key output:") == 1,锁定「丢弃标题 ≠ 省略正文标题」。responses_projection.py现已 pyflakes 全清。测试全局配置隔离
test_snapshots_stream_resp.py、test_snapshots_wire.py以及同子系统的test_snapshots.py(
_enable()助手 + 4 个用例)全部改走monkeypatch.setitem;tests/conftest.py新增 autouse 夹具_isolate_global_config,每例结束把CONFIG恢复为快照——作为兜底护栏(
test_wsl_and_tool_repair.py等仍有直接赋值,现已被兜住)。已用探针用例验证:移除护栏即复现泄漏。
三、验证(LF 与 CRLF 两种检出)
pytest -qtests/run_isolated_tests.pynpm testcheck_premarked_sync.pytools/check-upstream.py --linttools/check-upstream.py(实跑)未跑:
cargo test(沙箱无 Rust 工具链,Rust 侧本轮未改动);未打真实 CodeBuddy 上游。