Research-Stack/4-Infrastructure/NoDupeLabs/tests/core/test_plugins.py

1005 lines
32 KiB
Python

"""Test tools module functionality."""
import pytest
from unittest.mock import patch, MagicMock
from nodupe.core.tools import (
ToolManager,
tool_manager
)
from nodupe.core.tool_system.registry import ToolRegistry
class TestToolsModule:
"""Test tools module functionality."""
def test_tool_manager_instance(self):
"""Test tool_manager instance."""
assert isinstance(tool_manager, ToolRegistry)
assert tool_manager is not None
def test_tool_manager_alias(self):
"""Test ToolManager alias."""
assert ToolManager is ToolRegistry
assert ToolManager.__name__ == "ToolRegistry"
def test_module_exports(self):
"""Test module exports."""
import nodupe.core.tools as tools_module
assert hasattr(tools_module, 'ToolManager')
assert hasattr(tools_module, 'tool_manager')
assert hasattr(tools_module, '__all__')
expected_exports = ['ToolManager', 'tool_manager']
assert tools_module.__all__ == expected_exports
class TestToolManagerFunctionality:
"""Test tool manager functionality."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_manager_initialization(self):
"""Test tool manager initialization."""
# The tool_manager should already be initialized
assert tool_manager is not None
assert isinstance(tool_manager, ToolRegistry)
# Test that it has expected attributes
assert hasattr(tool_manager, 'initialize')
assert hasattr(tool_manager, 'register')
assert hasattr(tool_manager, 'get_tool')
assert hasattr(tool_manager, 'get_tools')
assert hasattr(tool_manager, 'shutdown')
def test_tool_manager_operations(self):
"""Test tool manager operations."""
# Test basic operations
tools = tool_manager.get_tools()
assert isinstance(tools, list)
# Test tool registration
mock_tool = MagicMock()
mock_tool.name = "test_tool"
tool_manager.register(mock_tool)
retrieved = tool_manager.get_tool("test_tool")
assert retrieved is mock_tool
# Test getting all tools
all_tools = tool_manager.get_tools()
assert len(all_tools) == 1
assert all_tools[0] is mock_tool
class TestToolManagerIntegration:
"""Test tool manager integration scenarios."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_manager_with_container(self):
"""Test tool manager with dependency container."""
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
# Initialize tool manager with container
tool_manager.initialize(container)
# Verify container was set
assert tool_manager.container is container
# Test tool registration with container
mock_tool = MagicMock()
mock_tool.name = "container_tool"
tool_manager.register(mock_tool)
# Verify tool is accessible
retrieved = tool_manager.get_tool("container_tool")
assert retrieved is mock_tool
def test_tool_manager_lifecycle(self):
"""Test tool manager lifecycle operations."""
# Test initialization
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
tool_manager.initialize(container)
assert tool_manager.container is container
# Test shutdown
tool_manager.shutdown()
assert tool_manager.container is None
# Test re-initialization
tool_manager.initialize(container)
assert tool_manager.container is container
class TestToolManagerErrorHandling:
"""Test tool manager error handling."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_get_nonexistent_tool(self):
"""Test getting non-existent tool."""
result = tool_manager.get_tool("nonexistent_tool")
assert result is None
def test_register_duplicate_tool(self):
"""Test registering duplicate tool."""
mock_tool1 = MagicMock()
mock_tool1.name = "duplicate_tool"
mock_tool2 = MagicMock()
mock_tool2.name = "duplicate_tool"
# Register first tool
tool_manager.register(mock_tool1)
# Register second tool with same name (should raise ValueError)
with pytest.raises(ValueError, match="already registered"):
tool_manager.register(mock_tool2)
# Should still return the first tool
retrieved = tool_manager.get_tool("duplicate_tool")
assert retrieved is mock_tool1
def test_tool_manager_without_container(self):
"""Test tool manager operations without container."""
# Clear container
tool_manager.container = None
# Should still work for basic operations
mock_tool = MagicMock()
mock_tool.name = "no_container_tool"
tool_manager.register(mock_tool)
retrieved = tool_manager.get_tool("no_container_tool")
assert retrieved is mock_tool
class TestToolManagerEdgeCases:
"""Test tool manager edge cases."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_with_empty_name(self):
"""Test tool with empty name."""
mock_tool = MagicMock()
mock_tool.name = ""
tool_manager.register_tool(mock_tool)
retrieved = tool_manager.get_tool("")
assert retrieved is mock_tool
def test_tool_with_special_characters(self):
"""Test tool with special characters in name."""
mock_tool = MagicMock()
mock_tool.name = "tool-with_special.chars"
tool_manager.register_tool(mock_tool)
retrieved = tool_manager.get_tool("tool-with_special.chars")
assert retrieved is mock_tool
def test_multiple_tool_registrations(self):
"""Test multiple tool registrations."""
# Register multiple tools
for i in range(10):
mock_tool = MagicMock()
mock_tool.name = f"tool_{i}"
tool_manager.register_tool(mock_tool)
# Verify all tools are accessible
all_tools = tool_manager.get_all_tools()
assert len(all_tools) == 10
for i in range(10):
tool = tool_manager.get_tool(f"tool_{i}")
assert tool is not None
assert tool.name == f"tool_{i}"
class TestToolManagerCompatibility:
"""Test tool manager compatibility with tool system."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_manager_is_tool_registry(self):
"""Test that ToolManager is the same as ToolRegistry."""
assert ToolManager is ToolRegistry
assert isinstance(tool_manager, ToolRegistry)
def test_tool_manager_compatibility(self):
"""Test tool manager compatibility with tool system."""
# Test that tool_manager has the same interface as ToolRegistry
registry = ToolRegistry()
# Both should have the same methods
manager_methods = set(dir(tool_manager))
registry_methods = set(dir(registry))
# Check key methods are present
key_methods = [
'initialize',
'register_tool',
'get_tool',
'get_all_tools',
'shutdown']
for method in key_methods:
assert method in manager_methods
assert method in registry_methods
def test_tool_manager_singleton_behavior(self):
"""Test that tool_manager and ToolRegistry return the same instance (singleton)."""
# Create a new registry instance
new_registry = ToolRegistry()
# Register a tool in the new registry
mock_tool = MagicMock()
mock_tool.name = "registry_tool"
new_registry.register_tool(mock_tool)
# Should affect the global tool_manager because it's a singleton
retrieved = tool_manager.get_tool("registry_tool")
assert retrieved is mock_tool
# Both references point to the same object
assert new_registry is tool_manager
class TestToolManagerIntegrationWithCore:
"""Test tool manager integration with core system."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_manager_in_core_loader(self):
"""Test tool manager usage in core loader."""
from unittest.mock import patch
# Mock the core loader to test integration
with patch('nodupe.core.loader.ToolRegistry') as mock_registry_class:
# Create mock registry instance
mock_registry_instance = MagicMock()
mock_registry_class.return_value = mock_registry_instance
# Import and test core loader
from nodupe.core.loader import CoreLoader
loader = CoreLoader()
# Mock initialization
with patch('nodupe.core.loader.load_config') as mock_config, \
patch.object(loader, '_apply_platform_autoconfig') as mock_autoconfig, \
patch('nodupe.core.loader.create_tool_loader') as mock_loader, \
patch('nodupe.core.loader.create_tool_discovery') as mock_discovery, \
patch('nodupe.core.loader.create_lifecycle_manager') as mock_lifecycle, \
patch('nodupe.core.loader.ToolHotReload') as mock_hot_reload, \
patch('nodupe.core.loader.get_connection') as mock_db, \
patch('nodupe.core.loader.logging') as mock_logging:
mock_config.return_value = MagicMock(config={})
mock_autoconfig.return_value = {}
mock_logging.info = MagicMock()
# Initialize loader
loader.initialize()
# Verify tool registry was initialized
assert loader.tool_registry is mock_registry_instance
mock_registry_instance.initialize.assert_called_once()
def test_tool_manager_in_container(self):
"""Test tool manager integration with dependency container."""
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
# Initialize tool manager
tool_manager.initialize(container)
# Register tool manager in container
container.register_service('tool_manager', tool_manager)
# Verify it can be retrieved
retrieved = container.get_service('tool_manager')
assert retrieved is tool_manager
# Test tool operations through container
mock_tool = MagicMock()
mock_tool.name = "container_test_tool"
tool_manager.register_tool(mock_tool)
retrieved_tool = tool_manager.get_tool("container_test_tool")
assert retrieved_tool is mock_tool
class TestToolRegistryAdvanced:
"""Test advanced tool registry functionality."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_tool_registry_mass_registration(self):
"""Test mass tool registration."""
# Test registering many tools
for i in range(100):
mock_tool = MagicMock()
mock_tool.name = f"mass_tool_{i}"
tool_manager.register_tool(mock_tool)
# Verify all tools are registered
all_tools = tool_manager.get_all_tools()
assert len(all_tools) == 100
# Verify specific tools can be retrieved
for i in range(100):
tool = tool_manager.get_tool(f"mass_tool_{i}")
assert tool is not None
assert tool.name == f"mass_tool_{i}"
def test_tool_registry_performance(self):
"""Test tool registry performance."""
import time
# Test registration performance
start_time = time.time()
for i in range(1000):
mock_tool = MagicMock()
mock_tool.name = f"perf_tool_{i}"
tool_manager.register_tool(mock_tool)
registration_time = time.time() - start_time
# Test retrieval performance
start_time = time.time()
for i in range(1000):
tool = tool_manager.get_tool(f"perf_tool_{i}")
assert tool is not None
retrieval_time = time.time() - start_time
# Should be fast operations
assert registration_time < 1.0
assert retrieval_time < 0.1
def test_tool_registry_clear(self):
"""Test clearing tool registry."""
# Add some tools
for i in range(10):
mock_tool = MagicMock()
mock_tool.name = f"clear_tool_{i}"
tool_manager.register_tool(mock_tool)
# Verify tools exist
assert len(tool_manager.get_all_tools()) == 10
# Clear registry (if supported)
if hasattr(tool_manager, 'clear'):
tool_manager.clear()
assert len(tool_manager.get_all_tools()) == 0
class TestToolLoader:
"""Test tool loader functionality."""
def test_tool_loader_initialization(self):
"""Test tool loader initialization."""
from nodupe.core.tool_system.loader import ToolLoader
# Test basic initialization
loader = ToolLoader(tool_manager)
assert loader is not None
# Test that it has expected attributes
assert hasattr(loader, 'load_tool_from_file')
assert hasattr(loader, 'unload_tool')
assert hasattr(loader, 'get_all_loaded_tools')
def test_tool_loader_with_container(self):
"""Test tool loader with dependency container."""
from nodupe.core.tool_system.loader import ToolLoader
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
loader = ToolLoader(tool_manager)
# Initialize loader with container
# Note: ToolLoader doesn't have initialize method in this version,
# but let's check if it should have it or if we should just test it exists
# loader.initialize(container)
# assert loader.container is container
assert loader is not None
def test_tool_loader_load_unload(self):
"""Test tool loading and unloading."""
from nodupe.core.tool_system.loader import ToolLoader
from nodupe.core.tool_system.base import Tool
# Create a mock tool class
class TestTool(Tool):
"""Test tool class for loader tests."""
@property
def name(self):
"""Return the tool name."""
return "test_tool"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return []
def __init__(self):
"""Initialize the test tool."""
self.initialized = False
self.shutdown_called = False
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
self.initialized = True
def shutdown(self):
"""Shutdown the tool and release resources."""
self.shutdown_called = True
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {"test": True}
loader = ToolLoader()
test_tool = TestTool()
# Test loading
loaded_tool = loader.load_tool(test_tool)
assert loaded_tool is test_tool
assert test_tool.initialized is True
# Test unloading
loader.unload_tool(test_tool)
assert test_tool.shutdown_called is True
class TestToolDiscovery:
"""Test tool discovery functionality."""
def test_tool_discovery_initialization(self):
"""Test tool discovery initialization."""
from nodupe.core.tool_system.discovery import ToolDiscovery
discovery = ToolDiscovery()
assert discovery is not None
# Test that it has expected attributes
assert hasattr(discovery, 'discover_tools')
assert hasattr(discovery, 'get_discovered_tools')
def test_tool_discovery_with_container(self):
"""Test tool discovery with dependency container."""
from nodupe.core.tool_system.discovery import ToolDiscovery
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
discovery = ToolDiscovery()
# Initialize discovery with container
discovery.initialize(container)
assert discovery.container is container
class TestToolLifecycle:
"""Test tool lifecycle management."""
def test_tool_lifecycle_initialization(self):
"""Test tool lifecycle manager initialization."""
from nodupe.core.tool_system.lifecycle import ToolLifecycleManager
lifecycle = ToolLifecycleManager()
assert lifecycle is not None
# Test that it has expected attributes
assert hasattr(lifecycle, 'initialize_tools')
assert hasattr(lifecycle, 'shutdown_tools')
assert hasattr(lifecycle, 'get_tool_states')
def test_tool_lifecycle_with_container(self):
"""Test tool lifecycle with dependency container."""
from nodupe.core.tool_system.lifecycle import ToolLifecycleManager
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
lifecycle = ToolLifecycleManager()
# Initialize lifecycle with container
lifecycle.initialize(container)
assert lifecycle.container is container
class TestToolHotReload:
"""Test tool hot reload functionality."""
def test_tool_hot_reload_initialization(self):
"""Test tool hot reload initialization."""
from nodupe.core.tool_system.hot_reload import ToolHotReload
hot_reload = ToolHotReload()
assert hot_reload is not None
# Test that it has expected attributes
assert hasattr(hot_reload, 'start_watching')
assert hasattr(hot_reload, 'stop_watching')
assert hasattr(hot_reload, 'reload_tools')
def test_tool_hot_reload_with_container(self):
"""Test tool hot reload with dependency container."""
from nodupe.core.tool_system.hot_reload import ToolHotReload
from nodupe.core.container import ServiceContainer
container = ServiceContainer()
hot_reload = ToolHotReload()
# Initialize hot reload with container
hot_reload.initialize(container)
assert hot_reload.container is container
class TestToolCompatibility:
"""Test tool compatibility functionality."""
def test_tool_compatibility_initialization(self):
"""Test tool compatibility checker initialization."""
from nodupe.core.tool_system.compatibility import ToolCompatibility
compatibility = ToolCompatibility()
assert compatibility is not None
# Test that it has expected attributes
assert hasattr(compatibility, 'check_compatibility')
assert hasattr(compatibility, 'get_compatibility_report')
def test_tool_compatibility_checking(self):
"""Test tool compatibility checking."""
from nodupe.core.tool_system.compatibility import ToolCompatibility
from nodupe.core.tool_system.base import Tool
class TestTool(Tool):
"""Test tool class for compatibility tests."""
@property
def name(self):
"""Return the tool name."""
return "test_tool"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return ["core>=1.0.0"]
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
pass
def shutdown(self):
"""Shutdown the tool and release resources."""
pass
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {}
compatibility = ToolCompatibility()
test_tool = TestTool()
# Test compatibility checking
report = compatibility.check_compatibility(test_tool)
assert report is not None
assert isinstance(report, dict)
class TestToolDependencies:
"""Test tool dependency management."""
def test_tool_dependency_initialization(self):
"""Test tool dependency manager initialization."""
from nodupe.core.tool_system.dependencies import ToolDependencyManager
dependency_manager = ToolDependencyManager()
assert dependency_manager is not None
# Test that it has expected attributes
assert hasattr(dependency_manager, 'resolve_dependencies')
assert hasattr(dependency_manager, 'check_dependency_graph')
def test_tool_dependency_resolution(self):
"""Test tool dependency resolution."""
from nodupe.core.tool_system.dependencies import ToolDependencyManager
from nodupe.core.tool_system.base import Tool
class ToolA(Tool):
"""First test tool for dependency resolution."""
@property
def name(self):
"""Return the tool name."""
return "tool_a"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return []
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
pass
def shutdown(self):
"""Shutdown the tool and release resources."""
pass
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {}
class ToolB(Tool):
"""Second test tool that depends on ToolA."""
@property
def name(self):
"""Return the tool name."""
return "tool_b"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return ["tool_a"]
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
pass
def shutdown(self):
"""Shutdown the tool and release resources."""
pass
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {}
dependency_manager = ToolDependencyManager()
tool_a = ToolA()
tool_b = ToolB()
# Test dependency resolution
tools = [tool_a, tool_b]
resolved = dependency_manager.resolve_dependencies(tools)
assert resolved is not None
assert len(resolved) == 2
class TestToolSecurity:
"""Test tool security functionality."""
def test_tool_security_initialization(self):
"""Test tool security manager initialization."""
from nodupe.core.tool_system.security import ToolSecurity
security = ToolSecurity()
assert security is not None
# Test that it has expected attributes
assert hasattr(security, 'validate_tool')
assert hasattr(security, 'check_tool_permissions')
def test_tool_security_validation(self):
"""Test tool security validation."""
from nodupe.core.tool_system.security import ToolSecurity
from nodupe.core.tool_system.base import Tool
class TestTool(Tool):
"""Test tool class for security validation."""
@property
def name(self):
"""Return the tool name."""
return "test_tool"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return []
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
pass
def shutdown(self):
"""Shutdown the tool and release resources."""
pass
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {}
security = ToolSecurity()
test_tool = TestTool()
# Test security validation
is_valid = security.validate_tool(test_tool)
assert is_valid is not None
class TestToolIntegration:
"""Test complete tool system integration."""
def setup_method(self):
"""Set up test fixtures."""
tool_manager.clear()
tool_manager.container = None
def test_complete_tool_system_workflow(self):
"""Test complete tool system workflow."""
from nodupe.core.tool_system.loader import ToolLoader
from nodupe.core.tool_system.discovery import ToolDiscovery
from nodupe.core.tool_system.lifecycle import ToolLifecycleManager
from nodupe.core.tool_system.registry import ToolRegistry
from nodupe.core.tool_system.base import Tool
from nodupe.core.container import ServiceContainer
# Create a test tool
class TestTool(Tool):
"""Test tool for integration workflow tests."""
@property
def name(self):
"""Return the tool name."""
return "integration_test_tool"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return []
def __init__(self):
"""Initialize the test tool."""
self.initialized = False
self.shutdown_called = False
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
self.initialized = True
def shutdown(self):
"""Shutdown the tool and release resources."""
self.shutdown_called = True
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {"integration_test": True}
# Initialize container
container = ServiceContainer()
# Initialize tool components
registry = ToolRegistry()
loader = ToolLoader()
discovery = ToolDiscovery()
lifecycle = ToolLifecycleManager()
# Initialize components with container
registry.initialize(container)
loader.initialize(container)
discovery.initialize(container)
lifecycle.initialize(container)
# Create test tool instance
test_tool = TestTool()
# Test loading workflow
loaded_tool = loader.load_tool(test_tool)
assert loaded_tool is test_tool
assert test_tool.initialized is True
# Test registration
registry.register_tool(test_tool)
retrieved = registry.get_tool("integration_test_tool")
assert retrieved is test_tool
# Test lifecycle management
lifecycle.initialize_tools([test_tool])
assert test_tool.initialized is True
# Test shutdown
lifecycle.shutdown_tools([test_tool])
assert test_tool.shutdown_called is True
# Test unloading
loader.unload_tool(test_tool)
assert test_tool.shutdown_called is True
def test_tool_system_performance(self):
"""Test tool system performance."""
import time
from nodupe.core.tool_system.loader import ToolLoader
from nodupe.core.tool_system.registry import ToolRegistry
from nodupe.core.tool_system.base import Tool
# Create a simple test tool class
class SimpleTool(Tool):
"""Simple tool class for performance testing."""
@property
def name(self):
"""Return the tool name."""
return f"perf_tool_{self.tool_id}"
@property
def version(self):
"""Return the tool version."""
return "1.0.0"
@property
def dependencies(self):
"""Return the tool dependencies."""
return []
def __init__(self, tool_id):
"""Initialize the simple tool.
Args:
tool_id: Unique identifier for the tool instance.
"""
self.tool_id = tool_id
self.initialized = False
def initialize(self, container):
"""Initialize the tool with a service container.
Args:
container: The service container instance.
"""
self.initialized = True
def shutdown(self):
"""Shutdown the tool and release resources."""
pass
def get_capabilities(self):
"""Return the tool capabilities.
Returns:
Dictionary of capability names to values.
"""
return {}
registry = ToolRegistry()
loader = ToolLoader()
# Test mass tool loading and registration
start_time = time.time()
tools = []
for i in range(100):
tool = SimpleTool(i)
tools.append(tool)
loaded = loader.load_tool(tool)
registry.register_tool(loaded)
load_time = time.time() - start_time
# Test mass tool retrieval
start_time = time.time()
for i in range(100):
tool = registry.get_tool(f"perf_tool_{i}")
assert tool is not None
retrieval_time = time.time() - start_time
# Should be fast operations
assert load_time < 1.0
assert retrieval_time < 0.1
# Verify all tools are loaded and registered
all_tools = registry.get_all_tools()
assert len(all_tools) == 100
# Test mass tool unloading
start_time = time.time()
for tool in tools:
loader.unload_tool(tool)
unload_time = time.time() - start_time
assert unload_time < 0.5