You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

48 lines
1.5 KiB

from pathlib import Path
import pytest
from gcode.safety import REJECT_SHELL, REJECT_WRITE, SafetyGate, unified_diff
from gcode.tools.fs import make_fs_tools
from gcode.tools.shell import make_shell_tools
def test_unified_diff_contains_change() -> None:
diff = unified_diff("a.py", "print(1)\n", "print(2)\n")
assert "-print(1)" in diff
assert "+print(2)" in diff
@pytest.mark.asyncio
async def test_unique_replace_and_reject(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.chdir(tmp_path)
path = tmp_path / "a.py"
path.write_text("foo\nfoo\n", encoding="utf-8")
async def deny(kind: str, detail: str) -> bool:
return False
tools = {t.name: t for t in make_fs_tools(SafetyGate(deny), tmp_path)}
out = await tools["replace_in_file"].ainvoke(
{"path": "a.py", "old_text": "foo", "new_text": "bar"}
)
assert "出现了 2 次" in out
assert path.read_text(encoding="utf-8") == "foo\nfoo\n"
path.write_text("only-once\n", encoding="utf-8")
out = await tools["replace_in_file"].ainvoke(
{"path": "a.py", "old_text": "only-once", "new_text": "twice"}
)
assert REJECT_WRITE in out
assert path.read_text(encoding="utf-8") == "only-once\n"
@pytest.mark.asyncio
async def test_shell_denied_does_not_run() -> None:
async def deny(kind: str, detail: str) -> bool:
return False
tools = {t.name: t for t in make_shell_tools(SafetyGate(deny))}
out = await tools["execute_command"].ainvoke({"command": "echo should-not-run"})
assert REJECT_SHELL in out