"""Tests for cloud abstraction layer. Run with: pytest suno_utils/tests/test_cloud_abstraction.py """ import pytest from unittest.mock import Mock, patch import os from suno_utils.cloud.backend import InferenceBackend, get_backend, set_backend_provider from suno_utils.cloud.factory import CloudProvider, CloudBackendFactory from suno_utils.cloud.chirp_backend import ChirpInferenceBackend class TestQueueBackend: """Test queue backend abstraction.""" def test_modal_queue_adapter(self): """Test Modal queue adapter initialization.""" backend = InferenceBackend(CloudProvider.MODAL) queue = backend.get_queue("test-queue") assert queue is not None assert hasattr(queue, "put") assert hasattr(queue, "get") assert hasattr(queue, "iterate") assert hasattr(queue, "iterate_async") def test_queue_caching(self): """Test that queues are cached.""" backend = InferenceBackend(CloudProvider.MODAL) queue1 = backend.get_queue("test-queue") queue2 = backend.get_queue("test-queue") assert queue1 is queue2 # Same instance class TestVolumeBackend: """Test volume backend abstraction.""" def test_modal_volume_adapter(self): """Test Modal volume adapter initialization.""" backend = InferenceBackend(CloudProvider.MODAL) volume = backend.get_volume("test-volume", "/test/path") assert volume is not None assert hasattr(volume, "get_mount_path") assert hasattr(volume, "exists") assert hasattr(volume, "list_files") assert volume.get_mount_path() == "/test/path" class TestKVStoreBackend: """Test key-value store backend abstraction.""" def test_modal_kv_adapter(self): """Test Modal KV adapter initialization.""" backend = InferenceBackend(CloudProvider.MODAL) kv = backend.get_kv_store("test-kv") assert kv is not None assert hasattr(kv, "get") assert hasattr(kv, "put") assert hasattr(kv, "delete") assert hasattr(kv, "contains") class TestSecretsBackend: """Test secrets backend abstraction.""" def test_modal_secrets_adapter(self): """Test Modal secrets adapter initialization.""" backend = InferenceBackend(CloudProvider.MODAL) secrets = backend.get_secrets() assert secrets is not None assert hasattr(secrets, "get_secret") class TestBackendFactory: """Test backend factory.""" def test_factory_creates_modal_backend(self): """Test factory creates Modal backend by default.""" factory = CloudBackendFactory(CloudProvider.MODAL) queue = factory.create_queue("test-queue") assert queue is not None def test_global_backend(self): """Test global backend singleton.""" backend = get_backend() assert backend is not None assert isinstance(backend, InferenceBackend) class TestChirpBackend: """Test Chirp-specific backend helper.""" def test_chirp_backend_initialization(self): """Test Chirp backend initializes all components.""" chirp = ChirpInferenceBackend("dev") # Check queues assert chirp.mp3_chunk_queue is not None assert chirp.webm_chunk_queue is not None assert chirp.stream_key_queue is not None assert chirp.token_queue is not None assert chirp.events_queue is not None # Check volume assert chirp.volume_adapter is not None assert chirp.volume_mount_path == "/volume" # Check secrets assert chirp.secrets_backend is not None def test_chirp_backend_queue_names(self): """Test Chirp backend uses correct queue names.""" chirp = ChirpInferenceBackend("dev") assert chirp.chunk_queue_name == "chunk-queue-dev" assert chirp.webm_chunk_queue_name == "chunk-queue-webm-dev" assert chirp.stream_key_queue_name == "stream-key-queue-dev" assert chirp.token_queue_name == "token-queue-dev" def test_chirp_backend_get_volume_dict(self): """Test Chirp backend volume dict for Modal decorator.""" chirp = ChirpInferenceBackend("dev") volume_dict = chirp.get_volume_dict() # Should return dict with mount path as key assert isinstance(volume_dict, dict) def test_chirp_backend_get_secrets_list(self): """Test Chirp backend secrets list for Modal decorator.""" chirp = ChirpInferenceBackend("dev") secrets_list = chirp.get_secrets_list() # Should return list assert isinstance(secrets_list, list) class TestProviderSwitching: """Test switching between providers.""" def test_switch_provider_via_set_backend(self): """Test switching provider programmatically.""" set_backend_provider(CloudProvider.MODAL) backend = get_backend() assert backend.provider == CloudProvider.MODAL @patch.dict(os.environ, {"CLOUD_PROVIDER": "modal"}) def test_configure_from_env(self): """Test configuring provider from environment.""" from suno_utils.cloud.backend import configure_backend_from_env configure_backend_from_env() backend = get_backend() assert backend.provider == CloudProvider.MODAL class TestBackwardCompatibility: """Test backward compatibility with existing Modal code.""" def test_queue_interface_matches_modal(self): """Test that queue interface matches Modal.Queue API.""" backend = InferenceBackend(CloudProvider.MODAL) queue = backend.get_queue("test-queue") # Check all Modal Queue methods are available assert hasattr(queue, "put") assert hasattr(queue, "get") assert hasattr(queue, "iterate") # Check signature matches Modal import inspect put_sig = inspect.signature(queue.put) assert "partition" in put_sig.parameters assert "partition_ttl" in put_sig.parameters assert "block" in put_sig.parameters assert "timeout" in put_sig.parameters class TestMocking: """Test that backends can be easily mocked.""" def test_mock_queue_backend(self): """Test mocking queue backend for testing.""" backend = InferenceBackend(CloudProvider.MODAL) # Create mock queue mock_queue = Mock() mock_queue.put.return_value = None mock_queue.get.return_value = "test_data" # Inject mock backend._queues["test-queue"] = mock_queue # Use it queue = backend.get_queue("test-queue") queue.put("data", partition="key") result = queue.get(partition="key") # Verify assert queue is mock_queue assert result == "test_data" mock_queue.put.assert_called_once() if __name__ == "__main__": pytest.main([__file__, "-v"])