"""Unit tests for the intelligent-eval scheduling domain (domain.py). 从 test_intelligent_eval_task_queue.py 迁移:原先隔着 task_queue 的过渡 wrapper 测试,ADR-0008 残留 wrapper 删除后直接锁定 domain 模块—— 时段解析、欠账、优先级、注意原因的唯一实现。 """ from datetime import timedelta from agenteval.intelligent_eval import domain from agenteval.intelligent_eval.models import IntelligentEvalStatus from agenteval.storage.db import IntelligentEvalDB, IntelligentEvalSessionDB, utc_now from sqlmodel import Session def test_is_slot_due(): """Test time slot due detection.""" # Slot "8-10h" should be due after 8 hours slot = {"time_slot": "8-10h", "sessions": 2} assert domain.is_slot_due(slot, timedelta(hours=7)) is False assert domain.is_slot_due(slot, timedelta(hours=8)) is True assert domain.is_slot_due(slot, timedelta(hours=9)) is True # Invalid slot format assert domain.is_slot_due({"time_slot": "invalid"}, timedelta(hours=1)) is False assert domain.is_slot_due({}, timedelta(hours=1)) is False def test_is_slot_due_minute_format(): """Minute-level slots (1h window: "0-20min") must be parsed and due on time.""" # 0-20min: due at 0min, not before assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=-1)) is False assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=0)) is True assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=5)) is True # 20-40min: not due before 20min, due at 20min assert domain.is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=19)) is False assert domain.is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=20)) is True # parse both formats consistently (hours) assert domain.parse_time_slot("8-10h") == (8.0, 10.0) assert domain.parse_time_slot("0-20min") == (0.0, 1.0 / 3) assert domain.parse_time_slot("20-40min") == (1.0 / 3, 2.0 / 3) assert domain.parse_time_slot("bad") is None def test_calculate_session_deficit(db_session: Session): """Test session deficit calculation.""" # Create eval with plan eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=9), ) eval_db.set_plan({ "time_distribution": [ {"time_slot": "0-2h", "sessions": 1}, {"time_slot": "8-10h", "sessions": 2}, ], "estimated_sessions": 3, }) db_session.add(eval_db) db_session.commit() # No sessions yet, should have 3 (1 from 0-2h, 2 from 8-10h) deficit = domain.calculate_session_deficit(eval_db, db_session) assert deficit == 3 # Add 1 session session_db = IntelligentEvalSessionDB( eval_id=eval_db.id, target_id="target1", status="completed", ) db_session.add(session_db) db_session.commit() # Should have 3, has 1, deficit = 2 deficit = domain.calculate_session_deficit(eval_db, db_session) assert deficit == 2 def test_calculate_priority(db_session: Session): """Test task priority calculation.""" # Eval with due slot and deficit eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=9), ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 2, }) db_session.add(eval_db) db_session.commit() priority = domain.calculate_priority(eval_db, db_session) # Base 100 - 50 (slot due) - 20 (deficit 2 * 10) - 20 (wait 9h / 10min = 54, capped at 20) assert priority == 10 def test_get_attention_reason(db_session: Session): """Test attention reason detection.""" # Eval with due slot eval_db = IntelligentEvalDB( name="test", target_id="target1", status=IntelligentEvalStatus.EXECUTING.value, started_at=utc_now() - timedelta(hours=9), ) eval_db.set_plan({ "time_distribution": [{"time_slot": "8-10h", "sessions": 2}], "estimated_sessions": 2, }) db_session.add(eval_db) db_session.commit() reason = domain.get_attention_reason(eval_db, db_session) assert reason == "slot_due" # Add all sessions as completed 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() reason = domain.get_attention_reason(eval_db, db_session) assert reason == "all_sessions_completed"