"""Modal cloud adapter tests.""" from __future__ import annotations from unittest.mock import MagicMock, patch import pytest from sandboxer.extensions.modal import ModalExtension from sandboxer.models import Profile def _profile() -> Profile: return Profile.model_validate( { "id": "profile.modal-gpu", "version": "1.0.0", "extension": "ext.modal", } ) def test_provision_and_teardown_with_mock_client(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("MODAL_TOKEN_ID", "modal-token") ext = ModalExtension( { "api_base": "https://api.modal.com", "api_key_env": "MODAL_TOKEN_ID", "provider": "modal", } ) mock_client = MagicMock() create_resp = MagicMock() create_resp.status_code = 200 create_resp.json.return_value = { "sandbox_id": "modal-prov-1", "url": "https://modal.run/sandbox/modal-prov-1", "status": "ready", } ready_resp = MagicMock() ready_resp.status_code = 200 ready_resp.json.return_value = {"status": "ready"} delete_resp = MagicMock() delete_resp.status_code = 200 mock_client.post.return_value = create_resp mock_client.get.return_value = ready_resp mock_client.delete.return_value = delete_resp mock_client.__enter__.return_value = mock_client mock_client.__exit__.return_value = None with patch.object(ext, "_client_factory", return_value=mock_client): handle = ext.provision(_profile(), {}, "modal") assert handle["provider_sandbox_id"] == "modal-prov-1" ext.wait_ready(handle) report = ext.teardown(handle) assert report["provider_removed"] == "true" def test_provision_without_credentials_raises() -> None: ext = ModalExtension({"api_key_env": "MODAL_TOKEN_ID"}) with pytest.raises(RuntimeError, match="API key"): ext.provision(_profile(), {}, "modal")