"""Tests for the durable, idempotent Campaign child-Run claim seam.""" from agenteval.models import Campaign, CampaignPlanEntry, CampaignStatus, RunStatus, RunTrigger from agenteval.storage.repository import ( CampaignRepository, CampaignRunClaimStatus, RunRepository, TargetRepository, ) from tests.unit.test_repository import _make_target def _running_campaign(session, *, status=CampaignStatus.RUNNING): TargetRepository(session).create(_make_target()) return CampaignRepository(session).create( Campaign( id="campaign-1", name="campaign", target_id="t-1", status=status, window_seconds=60, plan=[CampaignPlanEntry(scenario_id="scenario-1", offset_seconds=0, count=2)], ) ) def _claim(repo: RunRepository, *, occurrence_index=0): return repo.claim_campaign_run( campaign_id="campaign-1", scenario_id="scenario-1", scenario_version=3, plan_index=0, occurrence_index=occurrence_index, ) def test_claim_creates_pending_campaign_run_with_durable_identity(db_session): _running_campaign(db_session) result = _claim(RunRepository(db_session)) assert result.status is CampaignRunClaimStatus.CLAIMED assert result.accepted is True assert result.created is True assert result.run is not None assert result.run.status is RunStatus.PENDING assert result.run.triggered_by is RunTrigger.CAMPAIGN assert result.run.target_id == "t-1" assert result.run.campaign_id == "campaign-1" assert result.run.campaign_plan_index == 0 assert result.run.campaign_occurrence_index == 0 def test_repeated_claim_returns_same_run_without_duplicate(db_session): _running_campaign(db_session) repo = RunRepository(db_session) first = _claim(repo) second = _claim(repo) assert first.run is not None and second.run is not None assert second.status is CampaignRunClaimStatus.EXISTING assert second.created is False assert second.run.id == first.run.id assert len(repo.list_by_campaign("campaign-1")) == 1 def test_claim_rejects_missing_or_non_running_campaign(db_session): repo = RunRepository(db_session) missing = _claim(repo) assert missing.status is CampaignRunClaimStatus.NOT_FOUND assert missing.accepted is False _running_campaign(db_session, status=CampaignStatus.CANCELLED) cancelled = _claim(repo) assert cancelled.status is CampaignRunClaimStatus.CONFLICT assert cancelled.run is None def test_each_occurrence_has_independent_claim_identity(db_session): _running_campaign(db_session) repo = RunRepository(db_session) first = _claim(repo, occurrence_index=0) second = _claim(repo, occurrence_index=1) assert first.created is True assert second.created is True assert first.run is not None and second.run is not None assert first.run.id != second.run.id assert len(repo.list_by_campaign("campaign-1")) == 2 def test_competing_sessions_converge_on_one_claim(tmp_path): from agenteval.storage.db import EvalRunDB # noqa: F401 - register metadata from sqlmodel import Session, SQLModel, create_engine engine = create_engine( f"sqlite:///{tmp_path / 'competing-claims.db'}", connect_args={"check_same_thread": False}, ) SQLModel.metadata.create_all(engine) with Session(engine) as first_session, Session(engine) as second_session: _running_campaign(first_session) first = _claim(RunRepository(first_session)) second = _claim(RunRepository(second_session)) assert first.status is CampaignRunClaimStatus.CLAIMED assert second.status is CampaignRunClaimStatus.EXISTING assert first.run is not None and second.run is not None assert second.run.id == first.run.id assert len(RunRepository(second_session).list_by_campaign("campaign-1")) == 1