"""VMPackerExtension unit tests.""" from __future__ import annotations from pathlib import Path from unittest.mock import patch import pytest from sandboxer.extensions.vm_packer import VMPackerExtension from sandboxer.models import Profile def _profile() -> Profile: return Profile.model_validate( { "id": "profile.vm-haskell-build", "version": "1.0.0", "extension": "ext.vm-packer", } ) def test_provision_attach_via_alias(tmp_path: Path) -> None: repo = tmp_path / "proj" repo.mkdir() ext = VMPackerExtension() with ( patch("sandboxer.extensions.vm_packer.SSHConfig.run", return_value=(0, "")), patch("sandboxer.extensions.vm_packer.SSHConfig.rsync") as rsync, ): handle = ext.provision( _profile(), {"vm": "haskell-build", "repo": str(repo)}, "localhost", ) assert handle["vm_target"] == "haskell-build" assert handle["remote_dir"].startswith("/build/sbx-") rsync.assert_called_once() def test_provision_requires_vm_input() -> None: ext = VMPackerExtension() with pytest.raises(ValueError, match="inputs.vm"): ext.provision(_profile(), {}, "localhost") def test_wait_ready_success() -> None: ext = VMPackerExtension() handle = { "vm_host": "haskell-build", "remote_dir": "/build/sbx-abc12345", "host": "localhost", "ssh_user": "build", "ssh_port": "", } with patch("sandboxer.extensions.vm_packer.SSHConfig.run", return_value=(0, "ready\n")): reach = ext.wait_ready(handle) assert reach["remote_dir"] == "/build/sbx-abc12345" assert "haskell-build" in (reach["ssh"] or "") def test_teardown_preserves_vm() -> None: ext = VMPackerExtension() handle = { "vm_host": "localhost", "remote_dir": "/build/sbx-deadbeef", "ssh_user": "build", "ssh_port": "12222", } with patch("sandboxer.extensions.vm_packer.SSHConfig.run", return_value=(0, "")): report = ext.teardown(handle) assert report["vm_preserved"] == "true" assert report["workspace_removed"] == "True"