mirror of
https://github.com/razzant/ouroboros.git
synced 2026-08-04 08:09:48 +00:00
117 lines
4.6 KiB
Python
117 lines
4.6 KiB
Python
"""Tests for ouroboros/tools/git_rollback.py — rollback_to_target tool."""
|
|
|
|
import subprocess
|
|
import types
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
from ouroboros.tools.registry import ToolContext
|
|
|
|
|
|
@pytest.fixture
|
|
def ctx(tmp_path):
|
|
"""Minimal ToolContext pointing at a temporary git repo."""
|
|
repo = tmp_path / "repo"
|
|
repo.mkdir()
|
|
subprocess.run(["git", "init"], cwd=repo, capture_output=True)
|
|
subprocess.run(["git", "config", "user.email", "t@t"], cwd=repo, capture_output=True)
|
|
subprocess.run(["git", "config", "user.name", "T"], cwd=repo, capture_output=True)
|
|
(repo / "f.txt").write_text("init")
|
|
subprocess.run(["git", "add", "."], cwd=repo, capture_output=True)
|
|
subprocess.run(["git", "commit", "-m", "init"], cwd=repo, capture_output=True)
|
|
return ToolContext(repo_dir=str(repo), drive_root=str(tmp_path / "data"))
|
|
|
|
|
|
def test_rollback_empty_target(ctx):
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
result = _rollback_to_target(ctx, target="", confirm=True)
|
|
assert "ROLLBACK_ERROR" in result
|
|
assert "required" in result
|
|
|
|
|
|
def test_rollback_preview_valid_sha(ctx):
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
sha = subprocess.run(
|
|
["git", "rev-parse", "HEAD"],
|
|
cwd=ctx.repo_dir, capture_output=True, text=True,
|
|
).stdout.strip()
|
|
result = _rollback_to_target(ctx, target=sha, confirm=False)
|
|
assert "Will reset" in result
|
|
assert sha[:8] in result
|
|
assert "confirm=true" in result
|
|
|
|
|
|
def test_rollback_preview_invalid_target(ctx):
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
result = _rollback_to_target(ctx, target="nonexistent_tag_xyz", confirm=False)
|
|
assert "ROLLBACK_ERROR" in result
|
|
assert "Cannot resolve" in result
|
|
|
|
|
|
def test_rollback_confirm_calls_git_ops(ctx):
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
with mock.patch(
|
|
"ouroboros.tools.git_rollback.rollback_to_version",
|
|
create=True,
|
|
) as mock_rb:
|
|
# Simulate successful rollback via git_ops import inside function
|
|
mock_rb.return_value = (True, "Rolled back to abc123 (abc12345)")
|
|
# We need to patch the import inside the function
|
|
fake_git_ops = types.ModuleType("supervisor.git_ops")
|
|
fake_git_ops.rollback_to_version = mock_rb
|
|
with mock.patch.dict("sys.modules", {"supervisor.git_ops": fake_git_ops}):
|
|
result = _rollback_to_target(ctx, target="HEAD", confirm=True)
|
|
assert "abc12345" in result or "Rolled back" in result
|
|
|
|
|
|
def test_rollback_confirm_failure(ctx):
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
fake_git_ops = types.ModuleType("supervisor.git_ops")
|
|
fake_git_ops.rollback_to_version = mock.Mock(
|
|
return_value=(False, "Cannot resolve badref")
|
|
)
|
|
with mock.patch.dict("sys.modules", {"supervisor.git_ops": fake_git_ops}):
|
|
result = _rollback_to_target(ctx, target="badref", confirm=True)
|
|
assert "ROLLBACK_ERROR" in result
|
|
|
|
|
|
def test_get_tools_exports():
|
|
from ouroboros.tools.git_rollback import get_tools
|
|
tools = get_tools()
|
|
assert len(tools) == 1
|
|
assert tools[0].name == "vcs_rollback"
|
|
schema = tools[0].schema
|
|
assert "target" in schema["parameters"]["properties"]
|
|
assert "confirm" in schema["parameters"]["properties"]
|
|
|
|
|
|
def test_rollback_in_core_tool_names():
|
|
from ouroboros.tool_capabilities import CORE_TOOL_NAMES
|
|
assert "vcs_rollback" in CORE_TOOL_NAMES
|
|
|
|
|
|
def test_rollback_in_initial_tool_schemas():
|
|
"""rollback_to_target must be visible in the runtime initial_tool_schemas path."""
|
|
import pathlib, tempfile
|
|
from ouroboros.tools.registry import ToolRegistry
|
|
from ouroboros.tool_policy import initial_tool_schemas
|
|
with tempfile.TemporaryDirectory() as d:
|
|
reg = ToolRegistry(repo_dir=pathlib.Path(d), drive_root=pathlib.Path(d))
|
|
schemas = initial_tool_schemas(reg)
|
|
names = {s["function"]["name"] for s in schemas}
|
|
assert "vcs_rollback" in names
|
|
|
|
|
|
def test_rollback_requests_restart_on_success(ctx):
|
|
"""After successful rollback, ctx.pending_restart_reason is set."""
|
|
from ouroboros.tools.git_rollback import _rollback_to_target
|
|
import types
|
|
fake_git_ops = types.ModuleType("supervisor.git_ops")
|
|
fake_git_ops.rollback_to_version = mock.Mock(
|
|
return_value=(True, "Rolled back to abc123")
|
|
)
|
|
with mock.patch.dict("sys.modules", {"supervisor.git_ops": fake_git_ops}):
|
|
result = _rollback_to_target(ctx, target="HEAD", confirm=True)
|
|
assert "restart has been requested" in result
|
|
assert ctx.pending_restart_reason == "rollback_to_target completed"
|