AgentEvalTool/tests/unit/test_campaign_run_claim.py

116 lines
3.9 KiB
Python

"""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