feat: add draft data, gap analysis report, and workspace config
This commit is contained in:
103
workspace/act/tests/test_dag.py
Normal file
103
workspace/act/tests/test_dag.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""Tests for act.dag module."""
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from act.dag import validate_dag
|
||||
from act.errors import ACTCapabilityError, ACTDAGError
|
||||
from act.ledger import ACTLedger
|
||||
from act.token import ACTRecord, Capability, TaskClaim
|
||||
|
||||
|
||||
def make_record(jti, par=None, exec_act="do.thing", exec_ts=None, cap=None):
|
||||
"""Helper to create a minimal ACTRecord."""
|
||||
return ACTRecord(
|
||||
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
|
||||
iat=1772064000, exp=1772064900,
|
||||
jti=jti,
|
||||
task=TaskClaim(purpose="t"),
|
||||
cap=cap or [Capability(action="do.thing")],
|
||||
exec_act=exec_act,
|
||||
par=par or [],
|
||||
exec_ts=exec_ts or 1772064100,
|
||||
status="completed",
|
||||
)
|
||||
|
||||
|
||||
class TestDAGValidation:
|
||||
def test_root_task(self):
|
||||
ledger = ACTLedger()
|
||||
r = make_record("root-1")
|
||||
validate_dag(r, ledger)
|
||||
|
||||
def test_child_with_parent(self):
|
||||
ledger = ACTLedger()
|
||||
parent = make_record("parent-1", exec_ts=1772064050)
|
||||
ledger.append(parent)
|
||||
child = make_record("child-1", par=["parent-1"], exec_ts=1772064100)
|
||||
validate_dag(child, ledger)
|
||||
|
||||
def test_fan_in(self):
|
||||
ledger = ACTLedger()
|
||||
p1 = make_record("p1", exec_ts=1772064050)
|
||||
p2 = make_record("p2", exec_ts=1772064060)
|
||||
ledger.append(p1)
|
||||
ledger.append(p2)
|
||||
child = make_record("child", par=["p1", "p2"], exec_ts=1772064100)
|
||||
validate_dag(child, ledger)
|
||||
|
||||
def test_duplicate_jti(self):
|
||||
ledger = ACTLedger()
|
||||
r = make_record("dup-1")
|
||||
ledger.append(r)
|
||||
r2 = make_record("dup-1")
|
||||
with pytest.raises(ACTDAGError, match="Duplicate"):
|
||||
validate_dag(r2, ledger)
|
||||
|
||||
def test_missing_parent(self):
|
||||
ledger = ACTLedger()
|
||||
r = make_record("orphan", par=["nonexistent"])
|
||||
with pytest.raises(ACTDAGError, match="not found"):
|
||||
validate_dag(r, ledger)
|
||||
|
||||
def test_self_cycle(self):
|
||||
ledger = ACTLedger()
|
||||
r = make_record("cycle", par=["cycle"])
|
||||
with pytest.raises(ACTDAGError, match="cycle"):
|
||||
validate_dag(r, ledger)
|
||||
|
||||
def test_indirect_cycle(self):
|
||||
ledger = ACTLedger()
|
||||
# a -> b -> a would be a cycle
|
||||
a = make_record("a", par=["b"], exec_ts=1772064100)
|
||||
b = make_record("b", par=["a"], exec_ts=1772064100)
|
||||
ledger.append(b)
|
||||
# When validating a, following par leads to b,
|
||||
# which has par=["a"] — cycle!
|
||||
with pytest.raises(ACTDAGError, match="cycle"):
|
||||
validate_dag(a, ledger)
|
||||
|
||||
def test_temporal_ordering_violation(self):
|
||||
ledger = ACTLedger()
|
||||
parent = make_record("parent", exec_ts=1772064200)
|
||||
ledger.append(parent)
|
||||
# Child's exec_ts is way before parent
|
||||
child = make_record("child", par=["parent"], exec_ts=1772064100)
|
||||
with pytest.raises(ACTDAGError, match="Temporal"):
|
||||
validate_dag(child, ledger)
|
||||
|
||||
def test_temporal_within_tolerance(self):
|
||||
ledger = ACTLedger()
|
||||
parent = make_record("parent", exec_ts=1772064120)
|
||||
ledger.append(parent)
|
||||
# Child exec_ts is slightly before parent but within 30s tolerance
|
||||
child = make_record("child", par=["parent"], exec_ts=1772064100)
|
||||
validate_dag(child, ledger)
|
||||
|
||||
def test_bad_exec_act(self):
|
||||
ledger = ACTLedger()
|
||||
r = make_record("bad", exec_act="not.authorized",
|
||||
cap=[Capability(action="do.thing")])
|
||||
with pytest.raises(ACTCapabilityError):
|
||||
validate_dag(r, ledger)
|
||||
Reference in New Issue
Block a user