Skip to content

test 模式统一外部命令 mock(fkst.test.mock_command/command_calls)#9

Merged
loning merged 1 commit into
devfrom
feat/test-mock-command
Jun 5, 2026
Merged

test 模式统一外部命令 mock(fkst.test.mock_command/command_calls)#9
loning merged 1 commit into
devfrom
feat/test-mock-command

Conversation

@loning

@loning loning commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

动机

引擎对外部 CLI 的调用——exec_sync(/bin/sh)、spawn_codex_sync(codex)、git_* 原语(git)——此前在包测试里只能靠每包自写 fake 二进制 on PATH(per-tool、per-package、模拟 CLI)。统一在 test 模式劫持这些外部进程调用,让包零样板、确定性地测"调用外部 CLI 的逻辑"。

改了什么

  • 新增 external_command.rs:MockCommandState(FIFO mock 队列 + call 记录)+ 渲染命令行(exec_sync=shell 串;codex=codex exec … -;git=git -C <root> …)。
  • 三执行点(sdk_basic/sdk_git/sdk_codex)在真进程前检查注入的 mock runner:test 命中返回 {stdout,stderr,exit_code}(exec 直接返回 / git 照常解析 mocked stdout / codex 短路返回);未命中 → fail-closed(unmocked external command: <rendered>,绝不 Command::new)。
  • codex 仅加 test-mode 短路分支,未重构 streaming/permit/stall/log 真路径。setup_worktree 的 git 调用经同一 runner(test 未 mock fail-closed),不合成 worktree 副作用。
  • fkst.test.mock_command(pattern, result)(前缀/子串匹配渲染命令行、FIFO 一次性、多注册按序)+ fkst.test.command_calls()(记录含 codex prompt/stdin,供断言)。
  • 注入:register_test_sdk 建共享 Arc;run_department dept_lua 共享同一 Arc;每 test 前 reset。生产 register_framework_sdkNone、行为不变;supervise/run/self-test/conformance 无 mock。
  • primitive 自测(sdk_basic/sdk_codex/sdk_git)保留真工具/fake-PATH 不迁 mock。

为什么这样

codex/git/gh 本质都是引擎在边界 spawn 外部进程。统一 mock 在那个边界劫持,比 per-tool fake 二进制 / per-package 函数注入 seam 更一致、可复用、fail-closed。ghexec_sync 跑 → 匹配 shell 串;git 读原语照常解析 mocked stdout。下游 fkst-packages 将据此把 github-proxy 的 fake gh、autochrono 的 spawner seam 迁到 mock_command,并取回 run_department 端到端覆盖。

测试

test_runner_cli14 个 mock 场景(exec / codex sync+async / git 读原语 mocked-stdout 解析 / fail-closed 各类 / per-test 隔离 / FIFO 序列消费 / command_calls stdin / setup_worktree fail-closed);本地 bin 116、self_test_cli 6、sdk_git serial 26、supervise_smoke 5 全绿;sdk_codex 22(生产真路径不受影响)。

sdk_git 并行有 pre-existing 本机 env-race(serial 全过、CI 绿),与本改无关。

🤖 Generated with Claude Code

引擎对外部 CLI 的调用(exec_sync 的 /bin/sh、spawn_codex_sync 的 codex、
git_* 原语的 git)此前在测试里只能靠每包自写 fake 二进制 on PATH,per-tool、
per-package、模拟 CLA。本改在 test 模式提供统一劫持:按渲染命令行匹配、返回
预设结果、未 mock fail-closed。生产路径完全不变。

- 新增 crates/fkst-framework/src/external_command.rs:MockCommandState(Arc,
  FIFO mock 队列 + call 记录)+ 渲染命令行(exec_sync=shell cmd 串;codex=
  codex exec ... -;git=git -C <root> ...)。
- 三执行点(sdk_basic exec_sync、sdk_git、sdk_codex)在真进程前检查注入的
  mock runner:test 命中返回 {stdout,stderr,exit_code}(exec 直接返回 / git
  照常解析 mocked stdout / codex 短路返回);未命中 → Lua error
  "unmocked external command: <rendered>",绝不 Command::new。codex 仅加
  test-mode 短路分支,未重构 streaming/permit/stall/log 真路径。
  setup_worktree 的 git 调用经同一 runner(test 未 mock fail-closed),不合成
  worktree 副作用。
- fkst.test.mock_command(pattern, {stdout,stderr?,exit_code?}):前缀/子串匹配
  渲染命令行,FIFO 一次性消费,多注册按序。fkst.test.command_calls() 返回
  已记录调用(含 codex prompt/stdin)供断言。
- 注入:register_test_sdk 建共享 Arc;run_department dept_lua 共享同一 Arc;
  每 test function 前 reset。生产 register_framework_sdk 传 None、行为不变;
  supervise/run/self-test/conformance 无 mock。
- primitive 自测(sdk_basic/sdk_codex/sdk_git)保留真工具/fake-PATH,不迁 mock
  (仅 +2 行 #[path] mod external_command)。
- 文档:SPEC/CLAUDE/README/architecture/examples 同步 test-mode mock 说明。

测试:test_runner_cli 含 14 个 mock 场景(exec/codex sync+async/git 读原语经
mocked stdout 解析/fail-closed 各类/per-test 隔离/FIFO 序列消费/command_calls
stdin/setup_worktree fail-closed);bin 116、self_test 6、sdk_git serial 26、
supervise_smoke 5 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@loning loning merged commit ea58bc2 into dev Jun 5, 2026
4 checks passed
@loning loning deleted the feat/test-mock-command branch June 5, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant