Files
2026-07-13 13:12:33 +08:00

67 lines
2.0 KiB
Python

"""Unit tests for ``StageOutcome`` invariants.
Exercises ``StageOutcome.success(...)``, ``StageOutcome.terminate_with(...)``,
and each invalid construction the ``__post_init__`` rejects.
"""
from __future__ import annotations
from dataclasses import dataclass
import pytest
from opensquilla.engine.turn_runner.outcome import StageOutcome
from opensquilla.engine.types import ErrorEvent
@dataclass(frozen=True)
class _DummyOutput:
value: int
def test_success_constructs_with_output() -> None:
out = _DummyOutput(value=7)
oc = StageOutcome.success(out)
assert oc.terminate is False
assert oc.output is out
assert oc.early_yield is None
def test_terminate_with_constructs_with_event() -> None:
ev = ErrorEvent(message="No provider available", code="no_provider")
oc = StageOutcome.terminate_with(ev)
assert oc.terminate is True
assert oc.early_yield is ev
assert oc.output is None
def test_terminate_true_requires_early_yield() -> None:
with pytest.raises(ValueError, match="requires early_yield"):
StageOutcome(output=None, early_yield=None, terminate=True)
def test_terminate_true_forbids_output() -> None:
out = _DummyOutput(value=1)
ev = ErrorEvent(message="x", code="y")
with pytest.raises(ValueError, match="must have output=None"):
StageOutcome(output=out, early_yield=ev, terminate=True)
def test_terminate_false_forbids_early_yield() -> None:
ev = ErrorEvent(message="x", code="y")
out = _DummyOutput(value=1)
with pytest.raises(ValueError, match="must have early_yield=None"):
StageOutcome(output=out, early_yield=ev, terminate=False)
def test_terminate_false_requires_output() -> None:
with pytest.raises(ValueError, match="requires output"):
StageOutcome(output=None, early_yield=None, terminate=False)
def test_outcome_is_frozen() -> None:
out = _DummyOutput(value=2)
oc = StageOutcome.success(out)
with pytest.raises(Exception): # FrozenInstanceError, but message varies
oc.output = _DummyOutput(value=3) # type: ignore[misc]