Files
aiturk-hermes-ide/tests/tools/test_terminal_self_repo_guard.py

137 lines
4.9 KiB
Python

"""terminal_tool wiring tests for the self-repo git mutation guard."""
import json
from contextlib import ExitStack
from unittest.mock import MagicMock, patch
import pytest
import tools.self_repo_guard as self_repo_guard
def _make_env_config(**overrides):
config = {
"env_type": "local",
"timeout": 180,
"cwd": "/tmp",
"host_cwd": None,
"modal_mode": "auto",
"docker_image": "",
"singularity_image": "",
"modal_image": "",
"daytona_image": "",
}
config.update(overrides)
return config
@pytest.fixture
def repo(tmp_path):
root = tmp_path / "hermes-agent"
(root / ".git").mkdir(parents=True)
return root.resolve()
def _run(command, config, monkeypatch, repo_root, session_cwds=None,
guard_on=True, **kwargs):
from tools.terminal_tool import terminal_tool
monkeypatch.setattr(self_repo_guard, "get_running_source_root", lambda: repo_root)
monkeypatch.setattr(self_repo_guard, "guard_active", lambda: guard_on)
mock_env = MagicMock()
mock_env.execute.return_value = {"output": "ok", "returncode": 0}
mock_env.cwd = config["cwd"]
with ExitStack() as stack:
stack.enter_context(
patch("tools.terminal_tool._get_env_config", return_value=config)
)
stack.enter_context(patch("tools.terminal_tool._start_cleanup_thread"))
stack.enter_context(
patch("tools.terminal_tool._active_environments", {"default": mock_env})
)
stack.enter_context(patch("tools.terminal_tool._last_activity", {"default": 0}))
stack.enter_context(
patch("tools.terminal_tool._session_cwd", session_cwds or {})
)
stack.enter_context(
patch(
"tools.terminal_tool._check_all_guards", return_value={"approved": True}
)
)
result = json.loads(terminal_tool(command=command, **kwargs))
return result, mock_env
class TestSelfRepoGuardWiring:
def test_blocks_checkout_in_source_repo(self, repo, monkeypatch):
config = _make_env_config(cwd=str(repo))
result, env = _run("git checkout pr-51020", config, monkeypatch, repo)
assert result["status"] == "blocked"
assert "mix module versions" in result["error"]
assert str(repo) in result["error"]
env.execute.assert_not_called()
def test_force_cannot_bypass(self, repo, monkeypatch):
config = _make_env_config(cwd=str(repo))
result, env = _run(
"git reset --hard origin/main", config, monkeypatch, repo, force=True
)
assert result["status"] == "blocked"
env.execute.assert_not_called()
def test_workdir_targeting_repo_is_blocked(self, repo, monkeypatch, tmp_path):
config = _make_env_config(cwd=str(tmp_path))
result, env = _run("git pull", config, monkeypatch, repo, workdir=str(repo))
assert result["status"] == "blocked"
env.execute.assert_not_called()
def test_session_cwd_targeting_repo_is_blocked(self, repo, monkeypatch, tmp_path):
config = _make_env_config(cwd=str(tmp_path))
result, env = _run(
"git checkout main",
config,
monkeypatch,
repo,
session_cwds={"session-1": str(repo)},
task_id="session-1",
)
assert result["status"] == "blocked"
env.execute.assert_not_called()
def test_readonly_git_passes_through(self, repo, monkeypatch):
config = _make_env_config(cwd=str(repo))
result, env = _run("git status", config, monkeypatch, repo)
assert result.get("status") != "blocked"
env.execute.assert_called_once()
def test_mutation_outside_repo_passes_through(self, repo, monkeypatch, tmp_path):
other = tmp_path / "other"
other.mkdir()
config = _make_env_config(cwd=str(other))
result, env = _run("git checkout main", config, monkeypatch, repo)
assert result.get("status") != "blocked"
env.execute.assert_called_once()
def test_packaged_install_passes_through(self, repo, monkeypatch):
config = _make_env_config(cwd=str(repo))
result, env = _run("git checkout main", config, monkeypatch, None)
assert result.get("status") != "blocked"
env.execute.assert_called_once()
def test_guard_inactive_passes_through(self, repo, monkeypatch):
"""POSIX (guard_active() False): mutations in the source repo run."""
config = _make_env_config(cwd=str(repo))
result, env = _run(
"git reset --hard origin/main", config, monkeypatch, repo,
guard_on=False,
)
assert result.get("status") != "blocked"
env.execute.assert_called_once()
def test_guard_active_matches_platform(self):
"""guard_active() is True exactly on Windows."""
import os
assert self_repo_guard.guard_active() == (os.name == "nt")