144 lines
5.2 KiB
Python
144 lines
5.2 KiB
Python
"""Tests for CRDT labor attestations."""
|
|
|
|
from src.crdt.labor_crdt import (
|
|
AttestationEntry,
|
|
AttestationLog,
|
|
CRDTLaborSystem,
|
|
claim_tokens,
|
|
merge_labor,
|
|
pending_tokens,
|
|
submit_attestation,
|
|
)
|
|
|
|
RATES = {"code": 10.0, "governance": 5.0, "community": 3.0}
|
|
|
|
|
|
def _entry(eid: str, ctype: str = "code", units: float = 1.0,
|
|
ts: float = 0.0, attester: str = "oracle") -> AttestationEntry:
|
|
return AttestationEntry(eid, ctype, units, ts, attester)
|
|
|
|
|
|
class TestAttestation:
|
|
def test_submit_creates_log(self):
|
|
system = CRDTLaborSystem()
|
|
entry = _entry("e1", units=5.0)
|
|
system = submit_attestation(system, "alice", entry)
|
|
assert "alice" in system.logs
|
|
assert "e1" in system.logs["alice"].entries
|
|
|
|
def test_duplicate_entry_is_noop(self):
|
|
system = CRDTLaborSystem()
|
|
entry = _entry("e1", units=5.0)
|
|
s1 = submit_attestation(system, "alice", entry)
|
|
s2 = submit_attestation(s1, "alice", entry)
|
|
assert len(s2.logs["alice"].entries) == 1
|
|
|
|
def test_multiple_entries(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0, ts=0))
|
|
system = submit_attestation(system, "alice", _entry("e2", units=3.0, ts=1))
|
|
assert len(system.logs["alice"].entries) == 2
|
|
|
|
def test_pure_functional(self):
|
|
system = CRDTLaborSystem()
|
|
entry = _entry("e1")
|
|
updated = submit_attestation(system, "alice", entry)
|
|
assert "alice" not in system.logs
|
|
assert "alice" in updated.logs
|
|
|
|
|
|
class TestClaiming:
|
|
def test_claim_mints_tokens(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0))
|
|
system, tokens = claim_tokens(system, "alice", 1, RATES)
|
|
assert tokens == 50.0 # 5 units * 10 tokens/unit
|
|
assert system.logs["alice"].claimed_up_to == 1
|
|
assert system.logs["alice"].total_minted == 50.0
|
|
|
|
def test_claim_respects_monotone(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0, ts=0))
|
|
system = submit_attestation(system, "alice", _entry("e2", units=3.0, ts=1))
|
|
system, t1 = claim_tokens(system, "alice", 1, RATES)
|
|
# Claiming again at same index = no-op
|
|
system, t2 = claim_tokens(system, "alice", 1, RATES)
|
|
assert t2 == 0.0
|
|
|
|
def test_claim_partial(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0, ts=0))
|
|
system = submit_attestation(system, "alice", _entry("e2", units=3.0, ts=1))
|
|
system, t1 = claim_tokens(system, "alice", 1, RATES)
|
|
assert t1 == 50.0
|
|
system, t2 = claim_tokens(system, "alice", 2, RATES)
|
|
assert t2 == 30.0
|
|
|
|
def test_claim_nonexistent_contributor(self):
|
|
system = CRDTLaborSystem()
|
|
system, tokens = claim_tokens(system, "nobody", 1, RATES)
|
|
assert tokens == 0.0
|
|
|
|
|
|
class TestPending:
|
|
def test_pending_before_claim(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0))
|
|
assert pending_tokens(system, "alice", RATES) == 50.0
|
|
|
|
def test_pending_after_claim(self):
|
|
system = CRDTLaborSystem()
|
|
system = submit_attestation(system, "alice", _entry("e1", units=5.0, ts=0))
|
|
system = submit_attestation(system, "alice", _entry("e2", units=3.0, ts=1))
|
|
system, _ = claim_tokens(system, "alice", 1, RATES)
|
|
assert pending_tokens(system, "alice", RATES) == 30.0
|
|
|
|
|
|
class TestLaborMerge:
|
|
def test_merge_commutativity(self):
|
|
a = CRDTLaborSystem()
|
|
a = submit_attestation(a, "alice", _entry("e1", units=5.0))
|
|
b = CRDTLaborSystem()
|
|
b = submit_attestation(b, "alice", _entry("e2", units=3.0))
|
|
|
|
ab = merge_labor(a, b)
|
|
ba = merge_labor(b, a)
|
|
assert set(ab.logs["alice"].entries) == set(ba.logs["alice"].entries)
|
|
|
|
def test_merge_idempotency(self):
|
|
a = CRDTLaborSystem()
|
|
a = submit_attestation(a, "alice", _entry("e1", units=5.0))
|
|
aa = merge_labor(a, a)
|
|
assert len(aa.logs["alice"].entries) == 1
|
|
|
|
def test_merge_unions_entries(self):
|
|
a = CRDTLaborSystem()
|
|
a = submit_attestation(a, "alice", _entry("e1", units=5.0))
|
|
b = CRDTLaborSystem()
|
|
b = submit_attestation(b, "alice", _entry("e2", units=3.0))
|
|
|
|
merged = merge_labor(a, b)
|
|
assert len(merged.logs["alice"].entries) == 2
|
|
|
|
def test_merge_max_claimed(self):
|
|
a = CRDTLaborSystem()
|
|
a = submit_attestation(a, "alice", _entry("e1", units=5.0))
|
|
a, _ = claim_tokens(a, "alice", 1, RATES)
|
|
|
|
b = CRDTLaborSystem()
|
|
b = submit_attestation(b, "alice", _entry("e1", units=5.0))
|
|
|
|
merged = merge_labor(a, b)
|
|
assert merged.logs["alice"].claimed_up_to == 1
|
|
|
|
def test_merge_max_total_minted(self):
|
|
a = CRDTLaborSystem()
|
|
a = submit_attestation(a, "alice", _entry("e1", units=5.0))
|
|
a, _ = claim_tokens(a, "alice", 1, RATES)
|
|
|
|
b = CRDTLaborSystem()
|
|
b = submit_attestation(b, "alice", _entry("e1", units=5.0))
|
|
|
|
merged = merge_labor(a, b)
|
|
assert merged.logs["alice"].total_minted == 50.0
|