52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
"""Job/item state-machine rules: only declared transitions are legal, and terminal
|
|
states are truly terminal (no duplicate terminal transition)."""
|
|
|
|
import pytest
|
|
|
|
from photo_pipeline.services.jobs import (
|
|
ALLOWED_TRANSITIONS,
|
|
ITEM_TRANSITIONS,
|
|
TERMINAL_STATES,
|
|
ItemState,
|
|
JobState,
|
|
can_transition,
|
|
)
|
|
|
|
|
|
def test_happy_path_transitions_are_allowed():
|
|
assert can_transition(JobState.QUEUED, JobState.RUNNING)
|
|
assert can_transition(JobState.RUNNING, JobState.SUCCEEDED)
|
|
assert can_transition(JobState.RUNNING, JobState.FAILED)
|
|
assert can_transition(JobState.FAILED, JobState.RETRY_QUEUED)
|
|
assert can_transition(JobState.RETRY_QUEUED, JobState.RUNNING)
|
|
assert can_transition(JobState.RUNNING, JobState.CANCELLING)
|
|
assert can_transition(JobState.CANCELLING, JobState.CANCELLED)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"current,target",
|
|
[
|
|
(JobState.QUEUED, JobState.SUCCEEDED), # can't skip running
|
|
(JobState.SUCCEEDED, JobState.RUNNING), # terminal, no revive
|
|
(JobState.CANCELLED, JobState.RUNNING), # terminal
|
|
(JobState.RUNNING, JobState.QUEUED), # no backward
|
|
],
|
|
)
|
|
def test_invalid_transitions_are_rejected(current, target):
|
|
assert not can_transition(current, target)
|
|
|
|
|
|
def test_terminal_states_have_no_outgoing_transition():
|
|
for state in TERMINAL_STATES:
|
|
assert ALLOWED_TRANSITIONS[state] == set()
|
|
|
|
|
|
def test_duplicate_terminal_transition_is_rejected():
|
|
assert not can_transition(JobState.SUCCEEDED, JobState.SUCCEEDED)
|
|
assert not can_transition(JobState.CANCELLED, JobState.CANCELLED)
|
|
|
|
|
|
def test_item_states_are_consistent():
|
|
assert ItemState.SUCCEEDED in ITEM_TRANSITIONS[ItemState.RUNNING]
|
|
assert ITEM_TRANSITIONS[ItemState.SUCCEEDED] == set() # terminal item
|