tests/test_node.py
2.7 KB · 87 lines · python Raw
1 """Tests for GovernanceNode and NodeRegistry."""
2
3 from __future__ import annotations
4
5 import pytest
6 from quantumshield.identity.agent import AgentIdentity
7
8 from pqc_ai_governance import (
9 GovernanceNode,
10 GovernanceProposal,
11 NodeRegistry,
12 ProposalKind,
13 UnknownNodeError,
14 VoteDecision,
15 )
16
17
18 def _fresh_proposal(proposer_did: str) -> GovernanceProposal:
19 return GovernanceProposal.create(
20 kind=ProposalKind.AUTHORIZE_MODEL,
21 subject_id="did:pqaid:model-x",
22 title="Authorize model-x",
23 proposer_did=proposer_did,
24 )
25
26
27 def test_sign_proposal_populates_signature_fields(alice: GovernanceNode) -> None:
28 proposal = _fresh_proposal(alice.did)
29 alice.sign_proposal(proposal)
30 assert proposal.signer_did == alice.did
31 assert proposal.algorithm != ""
32 assert proposal.signature != ""
33 assert proposal.public_key != ""
34
35
36 def test_verify_proposal_true_for_valid(alice: GovernanceNode) -> None:
37 proposal = _fresh_proposal(alice.did)
38 alice.sign_proposal(proposal)
39 assert GovernanceNode.verify_proposal(proposal) is True
40
41
42 def test_cast_vote_returns_signed_vote_with_valid_signature(
43 alice: GovernanceNode,
44 ) -> None:
45 proposal = _fresh_proposal(alice.did)
46 alice.sign_proposal(proposal)
47 signed = alice.cast_vote(proposal, VoteDecision.APPROVE, rationale="looks good")
48 assert signed.vote.voter_did == alice.did
49 assert signed.vote.decision == VoteDecision.APPROVE
50 assert signed.signature != ""
51 assert GovernanceNode.verify_vote(signed) is True
52
53
54 def test_verify_vote_false_for_tampered(alice: GovernanceNode) -> None:
55 proposal = _fresh_proposal(alice.did)
56 alice.sign_proposal(proposal)
57 signed = alice.cast_vote(proposal, VoteDecision.APPROVE)
58 # Tamper with the rationale so canonical bytes change
59 signed.vote.rationale = "TAMPERED"
60 assert GovernanceNode.verify_vote(signed) is False
61
62
63 def test_node_registry_crud_and_weight_sum(
64 alice: GovernanceNode, bob: GovernanceNode, dave: GovernanceNode
65 ) -> None:
66 reg = NodeRegistry()
67 reg.register(alice)
68 reg.register(bob)
69 reg.register(dave)
70 assert len(reg) == 3
71 assert reg.is_member(alice.did)
72 assert reg.total_weight() == 1 + 1 + 2
73 got = reg.get(dave.did)
74 assert got.did == dave.did
75 reg.remove(bob.did)
76 assert not reg.is_member(bob.did)
77 with pytest.raises(UnknownNodeError):
78 reg.get("did:pqaid:nobody")
79 with pytest.raises(UnknownNodeError):
80 reg.remove("did:pqaid:nobody")
81
82
83 def test_new_governance_node_via_agent_identity() -> None:
84 node = GovernanceNode(identity=AgentIdentity.create("mallory"), name="mallory")
85 assert node.did.startswith("did:pqaid:")
86 assert node.weight == 1
87