tests/test_vote.py
1.8 KB · 58 lines · python Raw
1 """Tests for Vote and SignedVote."""
2
3 from __future__ import annotations
4
5 from pqc_ai_governance import SignedVote, Vote, VoteDecision
6
7
8 def test_create_populates_fields() -> None:
9 vote = Vote.create(
10 proposal_id="urn:pqc-gov-prop:x",
11 proposal_hash="deadbeef",
12 voter_did="did:pqaid:alice",
13 decision=VoteDecision.APPROVE,
14 rationale="looks good",
15 )
16 assert vote.vote_id.startswith("urn:pqc-gov-vote:")
17 assert vote.decision == VoteDecision.APPROVE
18 assert vote.rationale == "looks good"
19 assert vote.cast_at != ""
20
21
22 def test_canonical_bytes_is_deterministic() -> None:
23 vote = Vote.create(
24 proposal_id="p1",
25 proposal_hash="h1",
26 voter_did="did:pqaid:alice",
27 decision=VoteDecision.REJECT,
28 )
29 assert vote.canonical_bytes() == vote.canonical_bytes()
30
31
32 def test_signed_vote_roundtrip() -> None:
33 vote = Vote.create(
34 proposal_id="p1",
35 proposal_hash="h1",
36 voter_did="did:pqaid:alice",
37 decision=VoteDecision.ABSTAIN,
38 )
39 sv = SignedVote(vote=vote, algorithm="ML-DSA-65", signature="aa", public_key="bb")
40 restored = SignedVote.from_dict(sv.to_dict())
41 assert restored.vote.vote_id == vote.vote_id
42 assert restored.vote.decision == VoteDecision.ABSTAIN
43 assert restored.algorithm == "ML-DSA-65"
44 assert restored.signature == "aa"
45
46
47 def test_decision_preserved_through_serialization() -> None:
48 for decision in (VoteDecision.APPROVE, VoteDecision.REJECT, VoteDecision.ABSTAIN):
49 vote = Vote.create(
50 proposal_id="p",
51 proposal_hash="h",
52 voter_did="did:pqaid:alice",
53 decision=decision,
54 )
55 sv = SignedVote(vote=vote, algorithm="x", signature="", public_key="")
56 round_tripped = SignedVote.from_dict(sv.to_dict())
57 assert round_tripped.vote.decision == decision
58