"""Unit tests for worker decision logic.""" from datetime import timedelta import pytest from sqlmodel import Session from agenteval.intelligent_eval.decision import DecisionType, is_eval_completed, make_decision from agenteval.intelligent_eval.models import IntelligentEvalStatus from agenteval.storage.db import IntelligentEvalDB, IntelligentEvalSessionDB, utc_now def test_decision_wait_not_executing(db_session: Session): """Test decision is WAIT when eval is not executing.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.COMPLETED.value, ) db_session.add(eval_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.WAIT assert "不在执行中" in decision.reason def test_decision_wait_no_plan(db_session: Session): """Test decision is WAIT when eval has no plan.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now(), ) db_session.add(eval_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.WAIT assert "缺少计划" in decision.reason def test_decision_start_analysis_all_completed(db_session: Session): """Test decision is START_ANALYSIS when all sessions completed.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=10), ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 2, }) db_session.add(eval_db) db_session.commit() # Add 2 completed sessions for _ in range(2): session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", ) db_session.add(session_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.START_ANALYSIS assert "所有 2 个会话已完成" in decision.reason def test_decision_execute_session_slot_deficit(db_session: Session): """Test decision is EXECUTE_SESSION when current slot has deficit.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=8, minutes=30), # 8.5 hours ago ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 2, }) db_session.add(eval_db) db_session.commit() # Add 1 session created within the 8-10h slot (deficit = 1) # Slot starts at started_at + 8h = 0.5h ago session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="running", created_at=utc_now() - timedelta(minutes=20), # 20 minutes ago, within slot ) db_session.add(session_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.EXECUTE_SESSION assert "欠账 1 个会话" in decision.reason assert decision.context["current_slot"] == "8-10h" assert decision.context["deficit"] == 1 def test_decision_execute_session_high_severity(db_session: Session): """Test decision is EXECUTE_SESSION when high severity issue found.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=8, minutes=30), ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 3, # Not all completed yet }) db_session.add(eval_db) db_session.commit() # Add 2 completed sessions within the slot (no deficit) for _ in range(2): session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", created_at=utc_now() - timedelta(minutes=20), # Within slot ) # One with high severity session_db.set_verdict({"severity": "high", "issues": ["critical bug"]}) db_session.add(session_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.EXECUTE_SESSION assert "高严重度问题" in decision.reason def test_decision_wait_no_deficit(db_session: Session): """Test decision is WAIT when no deficit in current slot.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=8, minutes=30), ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 3, # Not all completed yet }) db_session.add(eval_db) db_session.commit() # Add 2 sessions within the slot (no deficit) for _ in range(2): session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="running", created_at=utc_now() - timedelta(minutes=20), # Within slot ) db_session.add(session_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.WAIT assert "无欠账" in decision.reason def test_decision_wait_outside_slots(db_session: Session): """Test decision is WAIT when current time is outside all slots.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=5), # 5 hours ago, outside 8-10h ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 2, }) db_session.add(eval_db) db_session.commit() decision = make_decision(eval_db, db_session) assert decision.decision_type == DecisionType.WAIT assert "不在任何时段内" in decision.reason def test_is_eval_completed_not_executing(db_session: Session): """Test is_eval_completed returns False when eval is not executing.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.COMPLETED.value, ) db_session.add(eval_db) db_session.commit() assert is_eval_completed(eval_db, db_session) is False def test_is_eval_completed_no_plan(db_session: Session): """Test is_eval_completed returns False when eval has no plan.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, ) db_session.add(eval_db) db_session.commit() assert is_eval_completed(eval_db, db_session) is False def test_is_eval_completed_sessions_not_finished(db_session: Session): """Test is_eval_completed returns False when not all sessions completed.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, ) eval_db.set_plan({"estimated_sessions": 2}) db_session.add(eval_db) db_session.commit() # Add only 1 completed session session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", ) db_session.add(session_db) db_session.commit() assert is_eval_completed(eval_db, db_session) is False def test_is_eval_completed_no_report(db_session: Session): """Test is_eval_completed returns False when report not submitted.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, ) eval_db.set_plan({"estimated_sessions": 2}) db_session.add(eval_db) db_session.commit() # Add 2 completed sessions for _ in range(2): session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", ) db_session.add(session_db) db_session.commit() assert is_eval_completed(eval_db, db_session) is False def test_is_eval_completed_true(db_session: Session): """Test is_eval_completed returns True when all conditions met.""" eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, ) eval_db.set_plan({"estimated_sessions": 2}) eval_db.set_report({"summary": "test report"}) db_session.add(eval_db) db_session.commit() # Add 2 completed sessions for _ in range(2): session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", ) db_session.add(session_db) db_session.commit() assert is_eval_completed(eval_db, db_session) is True