All checks were successful
AI Codebase Quality Review / ai-codebase-review (push) Successful in 39s
297 lines
9.1 KiB
Python
297 lines
9.1 KiB
Python
"""Test Suite for Dispatcher
|
|
|
|
Tests for event routing and agent execution.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "tools", "ai-review"))
|
|
|
|
from unittest.mock import MagicMock, Mock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
class TestDispatcherCreation:
|
|
"""Test dispatcher initialization."""
|
|
|
|
def test_create_dispatcher(self):
|
|
"""Test creating dispatcher."""
|
|
from dispatcher import Dispatcher
|
|
|
|
dispatcher = Dispatcher()
|
|
assert dispatcher is not None
|
|
assert dispatcher.agents == []
|
|
|
|
def test_create_dispatcher_with_config(self):
|
|
"""Test creating dispatcher with config."""
|
|
from dispatcher import Dispatcher
|
|
|
|
config = {"dispatcher": {"max_workers": 4}}
|
|
dispatcher = Dispatcher(config=config)
|
|
assert dispatcher.config == config
|
|
|
|
|
|
class TestAgentRegistration:
|
|
"""Test agent registration."""
|
|
|
|
def test_register_agent(self):
|
|
"""Test registering an agent."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class MockAgent(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "test"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="done")
|
|
|
|
dispatcher = Dispatcher()
|
|
agent = MockAgent(config={}, gitea_client=None, llm_client=None)
|
|
dispatcher.register_agent(agent)
|
|
|
|
assert len(dispatcher.agents) == 1
|
|
assert dispatcher.agents[0] == agent
|
|
|
|
def test_register_multiple_agents(self):
|
|
"""Test registering multiple agents."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class MockAgent1(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "type1"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="agent1")
|
|
|
|
class MockAgent2(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "type2"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="agent2")
|
|
|
|
dispatcher = Dispatcher()
|
|
dispatcher.register_agent(
|
|
MockAgent1(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
dispatcher.register_agent(
|
|
MockAgent2(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
|
|
assert len(dispatcher.agents) == 2
|
|
|
|
|
|
class TestEventRouting:
|
|
"""Test event routing to agents."""
|
|
|
|
def test_route_to_matching_agent(self):
|
|
"""Test that events are routed to matching agents."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class MockAgent(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "issues"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="handled")
|
|
|
|
dispatcher = Dispatcher()
|
|
agent = MockAgent(config={}, gitea_client=None, llm_client=None)
|
|
dispatcher.register_agent(agent)
|
|
|
|
result = dispatcher.dispatch(
|
|
event_type="issues",
|
|
event_data={"action": "opened"},
|
|
owner="test",
|
|
repo="repo",
|
|
)
|
|
|
|
assert len(result.agents_run) == 1
|
|
assert result.results[0].success is True
|
|
|
|
def test_no_matching_agent(self):
|
|
"""Test dispatch when no agent matches."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class MockAgent(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "issues"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="handled")
|
|
|
|
dispatcher = Dispatcher()
|
|
agent = MockAgent(config={}, gitea_client=None, llm_client=None)
|
|
dispatcher.register_agent(agent)
|
|
|
|
result = dispatcher.dispatch(
|
|
event_type="pull_request", # Different event type
|
|
event_data={"action": "opened"},
|
|
owner="test",
|
|
repo="repo",
|
|
)
|
|
|
|
assert len(result.agents_run) == 0
|
|
|
|
def test_multiple_matching_agents(self):
|
|
"""Test dispatch when multiple agents match."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class MockAgent1(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "issues"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="agent1")
|
|
|
|
class MockAgent2(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return event_type == "issues"
|
|
|
|
def execute(self, context):
|
|
return AgentResult(success=True, message="agent2")
|
|
|
|
dispatcher = Dispatcher()
|
|
dispatcher.register_agent(
|
|
MockAgent1(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
dispatcher.register_agent(
|
|
MockAgent2(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
|
|
result = dispatcher.dispatch(
|
|
event_type="issues",
|
|
event_data={"action": "opened"},
|
|
owner="test",
|
|
repo="repo",
|
|
)
|
|
|
|
assert len(result.agents_run) == 2
|
|
|
|
|
|
class TestDispatchResult:
|
|
"""Test dispatch result structure."""
|
|
|
|
def test_result_structure(self):
|
|
"""Test DispatchResult has correct structure."""
|
|
from dispatcher import DispatchResult
|
|
|
|
result = DispatchResult(
|
|
agents_run=["Agent1", "Agent2"],
|
|
results=[],
|
|
errors=[],
|
|
)
|
|
|
|
assert result.agents_run == ["Agent1", "Agent2"]
|
|
assert result.results == []
|
|
assert result.errors == []
|
|
|
|
def test_result_with_errors(self):
|
|
"""Test DispatchResult with errors."""
|
|
from dispatcher import DispatchResult
|
|
|
|
result = DispatchResult(
|
|
agents_run=["Agent1"],
|
|
results=[],
|
|
errors=["Error 1", "Error 2"],
|
|
)
|
|
|
|
assert len(result.errors) == 2
|
|
|
|
|
|
class TestAgentExecution:
|
|
"""Test agent execution through dispatcher."""
|
|
|
|
def test_agent_receives_context(self):
|
|
"""Test that agents receive proper context."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
received_context = None
|
|
|
|
class MockAgent(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return True
|
|
|
|
def execute(self, context):
|
|
nonlocal received_context
|
|
received_context = context
|
|
return AgentResult(success=True, message="done")
|
|
|
|
dispatcher = Dispatcher()
|
|
dispatcher.register_agent(
|
|
MockAgent(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
|
|
dispatcher.dispatch(
|
|
event_type="issues",
|
|
event_data={"action": "opened", "issue": {"number": 123}},
|
|
owner="testowner",
|
|
repo="testrepo",
|
|
)
|
|
|
|
assert received_context is not None
|
|
assert received_context.owner == "testowner"
|
|
assert received_context.repo == "testrepo"
|
|
assert received_context.event_type == "issues"
|
|
assert received_context.event_data["action"] == "opened"
|
|
|
|
def test_agent_failure_captured(self):
|
|
"""Test that agent failures are captured in results."""
|
|
from agents.base_agent import AgentContext, AgentResult, BaseAgent
|
|
from dispatcher import Dispatcher
|
|
|
|
class FailingAgent(BaseAgent):
|
|
def can_handle(self, event_type, event_data):
|
|
return True
|
|
|
|
def execute(self, context):
|
|
raise Exception("Test error")
|
|
|
|
dispatcher = Dispatcher()
|
|
dispatcher.register_agent(
|
|
FailingAgent(config={}, gitea_client=None, llm_client=None)
|
|
)
|
|
|
|
result = dispatcher.dispatch(
|
|
event_type="issues",
|
|
event_data={},
|
|
owner="test",
|
|
repo="repo",
|
|
)
|
|
|
|
# Agent should still be in agents_run
|
|
assert len(result.agents_run) == 1
|
|
# Result should indicate failure
|
|
assert result.results[0].success is False
|
|
|
|
|
|
class TestGetDispatcher:
|
|
"""Test get_dispatcher factory function."""
|
|
|
|
def test_get_dispatcher_returns_singleton(self):
|
|
"""Test that get_dispatcher returns configured dispatcher."""
|
|
from dispatcher import get_dispatcher
|
|
|
|
dispatcher = get_dispatcher()
|
|
assert dispatcher is not None
|
|
|
|
def test_get_dispatcher_with_config(self):
|
|
"""Test get_dispatcher with custom config."""
|
|
from dispatcher import get_dispatcher
|
|
|
|
config = {"test": "value"}
|
|
dispatcher = get_dispatcher(config=config)
|
|
assert dispatcher.config.get("test") == "value"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|