新增 run_tests.py:三套件统一入口,只加仓库根(deploy 套件 再加 deploy/ 目录在根之前),各套件走独立子进程;verify 作 业改走运行器,coverage 作业因子进程测不到覆盖率保持原 discover 命令。tests/ 13 个文件的 sys.path 前置 import 全部 改回正常 import(含 test_host_trace 的 try/except 回落); deploy 的 deploy 目录插入与 verify-multiuser 的 spec 加载按 陷阱 2 如实保留(仅删 verify-multiuser 冗余的根插入)。 .coveragerc omit 加 */run_tests.py,使新运行器文件不计入 生产覆盖率。门槛未动(仍 75%),未补新测试。
90 lines
3.8 KiB
Python
90 lines
3.8 KiB
Python
"""dispatch_from_branch 回归测试(CI 第二阶段 F841 证据)。
|
||
|
||
背景:host.py 的 dispatch_from_branch 里 `git commit` 的返回值
|
||
曾以 `c = git(...)` 绑定却从未读取(F841)。本轨只去绑定、
|
||
不删调用——提交本身是依赖派发的前置:依赖 worktree 的改动
|
||
必须先落到依赖分支,新 worktree 才从该分支建出、带血缘。
|
||
本测试用真实 git 仓库断言这条链:
|
||
|
||
- 依赖 worktree 里未提交的改动被提交到依赖分支;
|
||
- 新 worktree 的分支 host/<name> 由依赖分支 HEAD 派生
|
||
(含该提交),且任务记录进 state。
|
||
"""
|
||
|
||
import os
|
||
import shutil
|
||
import subprocess
|
||
import tempfile
|
||
import unittest
|
||
import uuid
|
||
from pathlib import Path
|
||
import host
|
||
|
||
|
||
def _git(args, cwd, check=True):
|
||
return subprocess.run(["git"] + args, cwd=cwd, check=check,
|
||
capture_output=True, text=True)
|
||
|
||
|
||
class FakeServer:
|
||
def create_thread(self, path, model=None, sandbox=None,
|
||
approval_policy=None):
|
||
self.created = (path, model, sandbox, approval_policy)
|
||
return "th-1"
|
||
|
||
|
||
class DispatchFromBranchTest(unittest.TestCase):
|
||
def test_commit_then_worktree_from_dep_branch(self):
|
||
name = "dep-" + uuid.uuid4().hex[:8]
|
||
server = FakeServer()
|
||
state = {"tasks": {}}
|
||
with tempfile.TemporaryDirectory() as tmp:
|
||
repo = os.path.join(tmp, "repo")
|
||
os.makedirs(repo)
|
||
_git(["init", "-q", "-b", "main"], repo)
|
||
_git(["config", "user.name", "Test"], repo)
|
||
_git(["config", "user.email", "test@example.com"], repo)
|
||
Path(repo, "f.txt").write_text("base\n", encoding="utf-8")
|
||
_git(["add", "-A"], repo)
|
||
_git(["commit", "-qm", "initial"], repo)
|
||
_git(["branch", "dep-branch"], repo)
|
||
dep_wt = os.path.join(tmp, "dep-wt")
|
||
_git(["worktree", "add", "-q", dep_wt, "dep-branch"], repo)
|
||
Path(dep_wt, "f.txt").write_text("dep change\n",
|
||
encoding="utf-8")
|
||
try:
|
||
task, err = host.dispatch_from_branch(
|
||
server, state, name, "do it", repo, "dep-branch",
|
||
dep_wt, "model-x", "medium", "workspace-write", "never")
|
||
self.assertEqual(err, "")
|
||
self.assertIsNotNone(task)
|
||
self.assertEqual(task["branch"], "host/" + name)
|
||
self.assertEqual(task["thread_id"], "th-1")
|
||
# 依赖分支 HEAD 含本次提交,且新分支由它派生。
|
||
dep_head = _git(["rev-parse", "dep-branch"],
|
||
repo).stdout.strip()
|
||
new_head = _git(["rev-parse", "host/" + name],
|
||
repo).stdout.strip()
|
||
self.assertEqual(new_head, dep_head)
|
||
msg = _git(["log", "-1", "--format=%s", "dep-branch"],
|
||
repo).stdout.strip()
|
||
self.assertIn(name, msg)
|
||
self.assertEqual(
|
||
Path(task["cwd"], "f.txt").read_text(encoding="utf-8"),
|
||
"dep change\n")
|
||
self.assertIs(state["tasks"][name], task)
|
||
finally:
|
||
# 清理 HERE/work 下建出的 worktree(work/ 已
|
||
# gitignore,但不留给下一轮测试;须在临时仓
|
||
# 删除前用该仓的 git 登记移除)。
|
||
path = os.path.join(host.HERE, "work",
|
||
"host-worktrees", name)
|
||
if os.path.exists(path):
|
||
_git(["worktree", "remove", "--force", path], repo,
|
||
check=False)
|
||
shutil.rmtree(path, ignore_errors=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|