- Rename `par` to `pred` (predecessor) in types, serialization, tests - Remove `pol`, `pol_decision` from core payload; move to `ect_ext` - Remove `sub` from payload (not part of ECT spec) - Update `typ` from `wimse-exec+jwt` to `exec+jwt` (accept both) - Rename MaxParLength to MaxPredLength everywhere - Update testdata, demos, READMEs with migration table - All Go tests pass, all 56 Python tests pass (90% coverage)
112 lines
2.6 KiB
Python
112 lines
2.6 KiB
Python
"""Tests for DAG validation."""
|
|
|
|
import time
|
|
|
|
import pytest
|
|
|
|
from ect import Payload, MemoryLedger, validate_dag, default_dag_config
|
|
|
|
|
|
def test_validate_dag_root():
|
|
store = MemoryLedger()
|
|
payload = Payload(
|
|
iss="",
|
|
aud=[],
|
|
iat=0,
|
|
exp=0,
|
|
jti="jti-001",
|
|
exec_act="",
|
|
pred=[],
|
|
wid="wf-1",
|
|
)
|
|
validate_dag(payload, store, default_dag_config())
|
|
|
|
|
|
def test_validate_dag_duplicate_jti():
|
|
store = MemoryLedger()
|
|
p = Payload(
|
|
iss="x",
|
|
aud=["y"],
|
|
iat=0,
|
|
exp=0,
|
|
jti="jti-001",
|
|
exec_act="a",
|
|
pred=[],
|
|
wid="wf-1",
|
|
)
|
|
store.append("dummy-jws", p)
|
|
payload = Payload(
|
|
iss="",
|
|
aud=[],
|
|
iat=0,
|
|
exp=0,
|
|
jti="jti-001",
|
|
exec_act="",
|
|
pred=[],
|
|
wid="wf-1",
|
|
)
|
|
with pytest.raises(ValueError, match="task ID.*already exists"):
|
|
validate_dag(payload, store, default_dag_config())
|
|
|
|
|
|
def test_validate_dag_pred_exists():
|
|
store = MemoryLedger()
|
|
now = int(time.time())
|
|
p = Payload(
|
|
iss="x",
|
|
aud=["y"],
|
|
iat=now - 60,
|
|
exp=now + 600,
|
|
jti="jti-001",
|
|
exec_act="a",
|
|
pred=[],
|
|
wid="wf-1",
|
|
)
|
|
store.append("jws1", p)
|
|
payload = Payload(
|
|
iss="",
|
|
aud=[],
|
|
iat=now,
|
|
exp=now + 600,
|
|
jti="jti-002",
|
|
exec_act="b",
|
|
pred=["jti-001"],
|
|
wid="wf-1",
|
|
)
|
|
validate_dag(payload, store, default_dag_config())
|
|
|
|
|
|
def test_validate_dag_pred_not_found():
|
|
store = MemoryLedger()
|
|
now = int(time.time())
|
|
payload = Payload(
|
|
iss="",
|
|
aud=[],
|
|
iat=now,
|
|
exp=now + 600,
|
|
jti="jti-002",
|
|
exec_act="",
|
|
pred=["jti-missing"],
|
|
)
|
|
with pytest.raises(ValueError, match="predecessor task not found"):
|
|
validate_dag(payload, store, default_dag_config())
|
|
|
|
|
|
def test_validate_dag_pred_policy_rejected_requires_compensation():
|
|
store = MemoryLedger()
|
|
now = int(time.time())
|
|
p = Payload(
|
|
iss="x", aud=["y"], iat=now - 60, exp=now + 600,
|
|
jti="jti-rej", exec_act="a", pred=[], wid="wf-1",
|
|
ext={"pol": "p", "pol_decision": "rejected"},
|
|
)
|
|
store.append("jws1", p)
|
|
payload = Payload(
|
|
iss="", aud=[], iat=now, exp=now + 600,
|
|
jti="jti-child", exec_act="b", pred=["jti-rej"], wid="wf-1",
|
|
)
|
|
with pytest.raises(ValueError, match="compensation"):
|
|
validate_dag(payload, store, default_dag_config())
|
|
payload.ext = {"compensation_required": True}
|
|
validate_dag(payload, store, default_dag_config())
|