""" Tests for Task Router Tests cover: - Intent-based routing - Routing rules - Fallback handling - Routing statistics """ import pytest import asyncio from unittest.mock import MagicMock import sys sys.path.insert(0, str(__file__).rsplit('/tests/', 1)[0]) from orchestrator.task_router import ( TaskRouter, RoutingRule, RoutingResult, RoutingStrategy, ) class TestRoutingRule: """Tests for RoutingRule dataclass""" def test_rule_creation(self): """Rule should be created correctly""" rule = RoutingRule( intent_pattern="learning_*", agent_type="tutor-agent", priority=10 ) assert rule.intent_pattern == "learning_*" assert rule.agent_type == "tutor-agent" assert rule.priority == 10 def test_rule_matches_exact(self): """Rule should match exact intent""" rule = RoutingRule( intent_pattern="grade_exam", agent_type="grader-agent" ) assert rule.matches("grade_exam", {}) is True assert rule.matches("grade_quiz", {}) is False def test_rule_matches_wildcard(self): """Rule should match wildcard patterns""" rule = RoutingRule( intent_pattern="learning_*", agent_type="tutor-agent" ) assert rule.matches("learning_math", {}) is True assert rule.matches("learning_english", {}) is True assert rule.matches("grading_math", {}) is False def test_rule_matches_conditions(self): """Rule should check conditions""" rule = RoutingRule( intent_pattern="*", agent_type="vip-agent", conditions={"is_vip": True} ) assert rule.matches("any_intent", {"is_vip": True}) is True assert rule.matches("any_intent", {"is_vip": False}) is False assert rule.matches("any_intent", {}) is False class TestRoutingResult: """Tests for RoutingResult dataclass""" def test_successful_result(self): """Should create successful routing result""" result = RoutingResult( success=True, agent_id="tutor-1", agent_type="tutor-agent", reason="Primary agent selected" ) assert result.success is True assert result.agent_id == "tutor-1" assert result.is_fallback is False def test_fallback_result(self): """Should indicate fallback routing""" result = RoutingResult( success=True, agent_id="backup-1", agent_type="backup-agent", is_fallback=True, reason="Fallback used" ) assert result.success is True assert result.is_fallback is True def test_failed_result(self): """Should create failed routing result""" result = RoutingResult( success=False, reason="No agents available" ) assert result.success is False assert result.agent_id is None class TestTaskRouter: """Tests for TaskRouter""" @pytest.fixture def router(self): """Create a task router without supervisor""" return TaskRouter(supervisor=None) def test_default_rules_exist(self, router): """Router should have default rules""" rules = router.get_rules() assert len(rules) > 0 def test_add_rule(self, router): """Should add new routing rule""" original_count = len(router.rules) router.add_rule(RoutingRule( intent_pattern="custom_*", agent_type="custom-agent", priority=100 )) assert len(router.rules) == original_count + 1 def test_rules_sorted_by_priority(self, router): """Rules should be sorted by priority (high first)""" router.add_rule(RoutingRule( intent_pattern="low_*", agent_type="low-agent", priority=1 )) router.add_rule(RoutingRule( intent_pattern="high_*", agent_type="high-agent", priority=100 )) # Highest priority should be first assert router.rules[0].priority >= router.rules[-1].priority def test_remove_rule(self, router): """Should remove routing rule""" router.add_rule(RoutingRule( intent_pattern="removable_*", agent_type="temp-agent" )) result = router.remove_rule("removable_*") assert result is True def test_find_matching_rules(self, router): """Should find rules matching intent""" matching = router.find_matching_rules("learning_math") assert len(matching) > 0 assert any(r["agent_type"] == "tutor-agent" for r in matching) def test_get_routing_stats_empty(self, router): """Should return empty stats initially""" stats = router.get_routing_stats() assert stats["total_routes"] == 0 def test_set_default_route(self, router): """Should set default agent for type""" router.set_default_route("tutor-agent", "tutor-primary") assert router._default_routes["tutor-agent"] == "tutor-primary" def test_clear_history(self, router): """Should clear routing history""" # Add some history router._routing_history.append({"test": "data"}) router.clear_history() assert len(router._routing_history) == 0 class TestRoutingStrategy: """Tests for RoutingStrategy enum""" def test_strategy_values(self): """Strategies should have expected values""" assert RoutingStrategy.DIRECT.value == "direct" assert RoutingStrategy.ROUND_ROBIN.value == "round_robin" assert RoutingStrategy.LEAST_LOADED.value == "least_loaded" assert RoutingStrategy.PRIORITY.value == "priority"