53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
"""Tests for atomic Campaign cancellation and settlement ordering."""
|
|
|
|
import pytest
|
|
from agenteval.evaluation.campaign_lifecycle import CampaignCancelError, cancel_campaign
|
|
from agenteval.models import Campaign, CampaignPlanEntry, CampaignStatus
|
|
from agenteval.storage.repository import CampaignRepository
|
|
|
|
|
|
def _campaign(session, status=CampaignStatus.RUNNING):
|
|
return CampaignRepository(session).create(
|
|
Campaign(
|
|
id="campaign-1",
|
|
name="campaign",
|
|
target_id="t-1",
|
|
status=status,
|
|
window_seconds=60,
|
|
plan=[CampaignPlanEntry(scenario_id="s-1", offset_seconds=0, count=1)],
|
|
)
|
|
)
|
|
|
|
|
|
def test_cancel_is_atomic_and_stop_happens_after_durable_state(db_session):
|
|
_campaign(db_session)
|
|
observed = []
|
|
|
|
def stop(campaign_id):
|
|
observed.append(CampaignRepository(db_session).get(campaign_id).status)
|
|
|
|
cancelled = cancel_campaign(db_session, "campaign-1", stop=stop)
|
|
|
|
assert cancelled.status is CampaignStatus.CANCELLED
|
|
assert cancelled.completed_at is not None
|
|
assert observed == [CampaignStatus.CANCELLED]
|
|
|
|
|
|
def test_cancel_distinguishes_missing_and_terminal_campaign(db_session):
|
|
with pytest.raises(CampaignCancelError) as missing:
|
|
cancel_campaign(db_session, "missing")
|
|
assert missing.value.status_code == 404
|
|
|
|
_campaign(db_session, CampaignStatus.COMPLETED)
|
|
with pytest.raises(CampaignCancelError) as terminal:
|
|
cancel_campaign(db_session, "campaign-1")
|
|
assert terminal.value.status_code == 400
|
|
|
|
|
|
def test_cancel_is_idempotency_guarded_by_status(db_session):
|
|
_campaign(db_session)
|
|
cancel_campaign(db_session, "campaign-1")
|
|
with pytest.raises(CampaignCancelError) as again:
|
|
cancel_campaign(db_session, "campaign-1")
|
|
assert again.value.status_code == 400
|