""" Tests for llm/llm_registry.py Tests cover: - LLMRegistry class methods - Global registry functions - Thread safety - Case-insensitive registration """ import threading from unittest.mock import Mock class TestLLMRegistryInit: """Tests for LLMRegistry initialization.""" def test_init_creates_empty_registry(self): """Test that initialization creates empty registry.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() assert registry.list_registered() == [] def test_init_creates_lock(self): """Test that initialization creates threading lock.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() assert registry._lock is not None assert isinstance(registry._lock, type(threading.Lock())) class TestLLMRegistryRegister: """Tests for LLMRegistry.register method.""" def test_register_llm_instance(self): """Test registering an LLM instance.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("test-llm", mock_llm) assert registry.is_registered("test-llm") assert registry.get("test-llm") is mock_llm def test_register_llm_factory(self): """Test registering an LLM factory function.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() factory = Mock(return_value=Mock()) registry.register("test-factory", factory) assert registry.is_registered("test-factory") assert registry.get("test-factory") is factory def test_register_normalizes_name_to_lowercase(self): """Test that registration normalizes names to lowercase.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("Test-LLM", mock_llm) assert registry.is_registered("test-llm") assert registry.is_registered("TEST-LLM") assert registry.is_registered("Test-LLM") def test_register_overwrites_existing(self): """Test that registering overwrites existing LLM with same name.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm1 = Mock(name="llm1") mock_llm2 = Mock(name="llm2") registry.register("test", mock_llm1) registry.register("test", mock_llm2) assert registry.get("test") is mock_llm2 class TestLLMRegistryUnregister: """Tests for LLMRegistry.unregister method.""" def test_unregister_removes_llm(self): """Test that unregister removes the LLM.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("test", mock_llm) assert registry.is_registered("test") registry.unregister("test") assert not registry.is_registered("test") def test_unregister_nonexistent_does_nothing(self): """Test that unregistering non-existent LLM doesn't raise.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() # Should not raise registry.unregister("nonexistent") def test_unregister_is_case_insensitive(self): """Test that unregister is case-insensitive.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("Test-LLM", mock_llm) registry.unregister("TEST-LLM") assert not registry.is_registered("test-llm") class TestLLMRegistryGet: """Tests for LLMRegistry.get method.""" def test_get_returns_registered_llm(self): """Test that get returns the registered LLM.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("test", mock_llm) assert registry.get("test") is mock_llm def test_get_returns_none_for_nonexistent(self): """Test that get returns None for non-existent LLM.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() assert registry.get("nonexistent") is None def test_get_is_case_insensitive(self): """Test that get is case-insensitive.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("Test-LLM", mock_llm) assert registry.get("test-llm") is mock_llm assert registry.get("TEST-LLM") is mock_llm class TestLLMRegistryIsRegistered: """Tests for LLMRegistry.is_registered method.""" def test_is_registered_returns_true_for_registered(self): """Test that is_registered returns True for registered LLM.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("test", mock_llm) assert registry.is_registered("test") is True def test_is_registered_returns_false_for_nonexistent(self): """Test that is_registered returns False for non-existent LLM.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() assert registry.is_registered("nonexistent") is False class TestLLMRegistryListRegistered: """Tests for LLMRegistry.list_registered method.""" def test_list_registered_returns_empty_for_new_registry(self): """Test that list_registered returns empty list for new registry.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() assert registry.list_registered() == [] def test_list_registered_returns_all_names(self): """Test that list_registered returns all registered names.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() registry.register("llm1", Mock()) registry.register("llm2", Mock()) registry.register("llm3", Mock()) names = registry.list_registered() assert len(names) == 3 assert "llm1" in names assert "llm2" in names assert "llm3" in names class TestLLMRegistryClear: """Tests for LLMRegistry.clear method.""" def test_clear_removes_all_llms(self): """Test that clear removes all registered LLMs.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() registry.register("llm1", Mock()) registry.register("llm2", Mock()) registry.register("llm3", Mock()) assert len(registry.list_registered()) == 3 registry.clear() assert registry.list_registered() == [] class TestGlobalRegistryFunctions: """Tests for global registry public API functions.""" def test_register_llm_function(self): """Test global register_llm function.""" from local_deep_research.llm.llm_registry import ( register_llm, is_llm_registered, clear_llm_registry, ) try: mock_llm = Mock() register_llm("global-test", mock_llm) assert is_llm_registered("global-test") finally: clear_llm_registry() def test_unregister_llm_function(self): """Test global unregister_llm function.""" from local_deep_research.llm.llm_registry import ( register_llm, unregister_llm, is_llm_registered, clear_llm_registry, ) try: register_llm("global-test", Mock()) assert is_llm_registered("global-test") unregister_llm("global-test") assert not is_llm_registered("global-test") finally: clear_llm_registry() def test_get_llm_from_registry_function(self): """Test global get_llm_from_registry function.""" from local_deep_research.llm.llm_registry import ( register_llm, get_llm_from_registry, clear_llm_registry, ) try: mock_llm = Mock() register_llm("global-test", mock_llm) assert get_llm_from_registry("global-test") is mock_llm finally: clear_llm_registry() def test_list_registered_llms_function(self): """Test global list_registered_llms function.""" from local_deep_research.llm.llm_registry import ( register_llm, list_registered_llms, clear_llm_registry, ) try: register_llm("test1", Mock()) register_llm("test2", Mock()) names = list_registered_llms() assert "test1" in names assert "test2" in names finally: clear_llm_registry() def test_clear_llm_registry_function(self): """Test global clear_llm_registry function.""" from local_deep_research.llm.llm_registry import ( register_llm, list_registered_llms, clear_llm_registry, ) register_llm("test1", Mock()) register_llm("test2", Mock()) clear_llm_registry() assert list_registered_llms() == [] class TestThreadSafety: """Tests for thread safety of LLMRegistry.""" def test_concurrent_registration(self): """Test that concurrent registrations are thread-safe.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() errors = [] def register_llm(name): try: registry.register(name, Mock()) except Exception as e: errors.append(e) threads = [ threading.Thread(target=register_llm, args=(f"llm-{i}",)) for i in range(100) ] for t in threads: t.start() for t in threads: t.join() assert len(errors) == 0 assert len(registry.list_registered()) == 100 def test_concurrent_get(self): """Test that concurrent gets are thread-safe.""" from local_deep_research.llm.llm_registry import LLMRegistry registry = LLMRegistry() mock_llm = Mock() registry.register("test", mock_llm) results = [] def get_llm(): result = registry.get("test") results.append(result) threads = [threading.Thread(target=get_llm) for _ in range(100)] for t in threads: t.start() for t in threads: t.join() assert len(results) == 100 assert all(r is mock_llm for r in results)