Skip to content

Commit a512679

Browse files
authored
TEST: cover cancelled readback cleanup boundary (#2639)
Signed-off-by: fei <204683769+feiiiiii5@users.noreply.github.com>
1 parent a37dccd commit a512679

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

‎tests/unit/backend/test_scenario_run_service.py‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,48 @@ async def run_until_cancelled() -> None:
16741674
assert progress.run.status is ScenarioRunState.CANCELLED
16751675
assert [result.attack_result_id for result in progress.results] == [delta.attack_result_id]
16761676

1677+
async def test_cancelled_readback_reports_terminal_state_and_cleans_up_active_task(
1678+
self, mock_all_registries
1679+
) -> None:
1680+
"""Cancelled runs read back terminal DB state and drop the active-task entry exactly once."""
1681+
mock_memory = mock_all_registries["memory"]
1682+
started = asyncio.Event()
1683+
1684+
async def run_until_cancelled() -> None:
1685+
started.set()
1686+
await asyncio.Event().wait()
1687+
1688+
mock_all_registries["scenario_instance"].run_async.side_effect = run_until_cancelled
1689+
service = ScenarioRunService()
1690+
response = await service.start_run_async(request=_make_request())
1691+
await asyncio.wait_for(started.wait(), timeout=5)
1692+
rid = response.scenario_result_id
1693+
# Narrowly scoped internal invariant: the live run stays tracked until readback.
1694+
assert rid in service._active_tasks
1695+
1696+
running_result = mock_all_registries["db_result"]
1697+
cancelled_result = _make_db_scenario_result(
1698+
result_id=rid,
1699+
run_state=ScenarioRunState.CANCELLED,
1700+
)
1701+
cancelled_result.metadata = {}
1702+
mock_memory.get_scenario_results.side_effect = [
1703+
[running_result],
1704+
[cancelled_result],
1705+
[cancelled_result],
1706+
[cancelled_result],
1707+
]
1708+
1709+
await service.cancel_run_async(scenario_result_id=rid)
1710+
fetched = service.get_run(scenario_result_id=rid)
1711+
assert fetched is not None
1712+
assert fetched.status is ScenarioRunState.CANCELLED
1713+
assert rid not in service._active_tasks
1714+
1715+
fetched_again = service.get_run(scenario_result_id=rid)
1716+
assert fetched_again is not None
1717+
assert fetched_again.status is ScenarioRunState.CANCELLED
1718+
16771719
async def test_cancel_completed_run_raises_value_error(self, mock_memory) -> None:
16781720
"""Test that cancelling a completed run raises ValueError."""
16791721
db_result = _make_db_scenario_result(result_id="sr-done", run_state=ScenarioRunState.COMPLETED)

0 commit comments

Comments
 (0)