"""Tests for OpenCode Zen model registry functionality.""" import json import os import tempfile from unittest.mock import patch from providers.registries.zen import ZenModelRegistry from providers.shared import ProviderType class TestZenModelRegistry: """Test cases for Zen model registry.""" def test_registry_initialization(self): """Test registry initializes with default config.""" registry = ZenModelRegistry() # Should load models from default location assert len(registry.list_models()) > 0 assert len(registry.list_aliases()) > 0 # Should include our configured models assert "claude-sonnet-4-5" in registry.list_models() assert "gpt-5.1-codex" in registry.list_models() def test_custom_config_path(self): """Test registry with custom config path.""" # Create temporary config config_data = { "models": [ { "model_name": "test/zen-model-1", "aliases": ["zen-test1", "zt1"], "context_window": 4096, "max_output_tokens": 2048, "intelligence_score": 15, } ] } with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump(config_data, f) temp_path = f.name try: registry = ZenModelRegistry(config_path=temp_path) assert len(registry.list_models()) == 1 assert "test/zen-model-1" in registry.list_models() assert "zen-test1" in registry.list_aliases() assert "zt1" in registry.list_aliases() finally: os.unlink(temp_path) def test_get_capabilities(self): """Test capability retrieval.""" registry = ZenModelRegistry() # Test getting capabilities for a known model caps = registry.get_capabilities("claude-sonnet-4-5") assert caps is not None assert caps.provider == ProviderType.ZEN assert caps.model_name == "claude-sonnet-4-5" assert caps.friendly_name == "OpenCode Zen (claude-sonnet-4-5)" assert caps.context_window == 200000 assert caps.intelligence_score == 17 # Test getting capabilities for unknown model caps = registry.get_capabilities("unknown-model") assert caps is None def test_resolve_model(self): """Test model resolution with aliases.""" registry = ZenModelRegistry() # Test resolving a direct model name config = registry.resolve("claude-sonnet-4-5") assert config is not None assert config.model_name == "claude-sonnet-4-5" # Test resolving an alias config = registry.resolve("zen-sonnet") assert config is not None assert config.model_name == "claude-sonnet-4-5" # Test resolving unknown model config = registry.resolve("unknown-model") assert config is None def test_list_aliases(self): """Test alias listing.""" registry = ZenModelRegistry() aliases = registry.list_aliases() assert isinstance(aliases, list) assert len(aliases) > 0 # Should include our configured aliases assert "zen-sonnet" in aliases assert "zen-codex" in aliases assert "zen-gemini" in aliases def test_environment_config_path(self): """Test registry respects environment variable for config path.""" config_data = { "models": [ { "model_name": "env/test-model", "aliases": ["env-test"], "context_window": 8192, "max_output_tokens": 4096, "intelligence_score": 10, } ] } with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump(config_data, f) temp_path = f.name try: with patch.dict(os.environ, {"ZEN_MODELS_CONFIG_PATH": temp_path}): registry = ZenModelRegistry() assert "env/test-model" in registry.list_models() assert "env-test" in registry.list_aliases() finally: os.unlink(temp_path) def test_malformed_config(self): """Test registry handles malformed config gracefully.""" malformed_config = { "models": [ { "model_name": "test/bad-model", # Missing required fields } ] } with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump(malformed_config, f) temp_path = f.name try: registry = ZenModelRegistry(config_path=temp_path) # Should still initialize but model may not load properly # This tests error handling in config loading registry.list_models() # Test that this doesn't crash # May or may not include the malformed model depending on validation finally: os.unlink(temp_path) def test_empty_config(self): """Test registry with empty config.""" empty_config = {"models": []} with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump(empty_config, f) temp_path = f.name try: registry = ZenModelRegistry(config_path=temp_path) assert len(registry.list_models()) == 0 assert len(registry.list_aliases()) == 0 finally: os.unlink(temp_path)