mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
166 lines
4.9 KiB
Python
166 lines
4.9 KiB
Python
import pytest
|
|
|
|
from bigchaindb.backend.exceptions import BigchainDBCritical
|
|
from bigchaindb.core import Bigchain
|
|
from bigchaindb.voting import Voting, INVALID, VALID, UNDECIDED
|
|
|
|
|
|
################################################################################
|
|
# Tests for checking vote eligibility
|
|
|
|
|
|
def test_partition_eligible_votes():
|
|
class TestVoting(Voting):
|
|
@classmethod
|
|
def verify_vote_signature(cls, vote):
|
|
if vote['node_pubkey'] == 'invalid sig':
|
|
return False
|
|
if vote['node_pubkey'] == 'value error':
|
|
raise ValueError()
|
|
return True
|
|
|
|
voters = ['valid', 'invalid sig', 'value error', 'not in set']
|
|
votes = [{'node_pubkey': k} for k in voters]
|
|
|
|
el, inel = TestVoting.partition_eligible_votes(votes, voters[:-1])
|
|
assert el == [votes[0]]
|
|
assert inel == votes[1:]
|
|
|
|
|
|
################################################################################
|
|
# Test vote counting
|
|
|
|
|
|
def test_count_votes():
|
|
class TestVoting(Voting):
|
|
@classmethod
|
|
def verify_vote_schema(cls, vote):
|
|
return vote['node_pubkey'] != 'malformed'
|
|
|
|
voters = ['cheat', 'cheat', 'says invalid', 'malformed']
|
|
voters += ['kosher' + str(i) for i in range(10)]
|
|
|
|
votes = [Bigchain(v).vote('block', 'a', True) for v in voters]
|
|
votes[2]['vote']['is_block_valid'] = False
|
|
votes[-1]['vote']['previous_block'] = 'z'
|
|
|
|
assert TestVoting.count_votes(votes) == {
|
|
'counts': {
|
|
'n_valid': 10,
|
|
'n_invalid': 3,
|
|
'n_agree_prev_block': 9
|
|
},
|
|
'cheat': [votes[:2]],
|
|
'malformed': [votes[3]],
|
|
}
|
|
|
|
|
|
################################################################################
|
|
# Tests for vote decision making
|
|
|
|
|
|
DECISION_TESTS = [dict(
|
|
zip(['n_voters', 'n_valid', 'n_invalid', 'n_agree_prev_block'], t))
|
|
for t in [
|
|
(1, 1, 1, 1),
|
|
(2, 2, 1, 2),
|
|
(3, 2, 2, 2),
|
|
(4, 3, 2, 3),
|
|
(5, 3, 3, 3),
|
|
(6, 4, 3, 4),
|
|
(7, 4, 4, 4),
|
|
(8, 5, 4, 5),
|
|
]
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize('kwargs', DECISION_TESTS)
|
|
def test_decide_votes_valid(kwargs):
|
|
kwargs = kwargs.copy()
|
|
kwargs['n_invalid'] = 0
|
|
assert Voting.decide_votes(**kwargs) == VALID
|
|
kwargs['n_agree_prev_block'] -= 1
|
|
assert Voting.decide_votes(**kwargs) == INVALID
|
|
kwargs['n_valid'] -= 1
|
|
assert Voting.decide_votes(**kwargs) == UNDECIDED
|
|
|
|
|
|
@pytest.mark.parametrize('kwargs', DECISION_TESTS)
|
|
def test_decide_votes_invalid(kwargs):
|
|
kwargs = kwargs.copy()
|
|
kwargs['n_valid'] = 0
|
|
assert Voting.decide_votes(**kwargs) == INVALID
|
|
kwargs['n_invalid'] -= 1
|
|
assert Voting.decide_votes(**kwargs) == UNDECIDED
|
|
|
|
|
|
def test_decide_votes_checks_arguments():
|
|
with pytest.raises(BigchainDBCritical):
|
|
Voting.decide_votes(n_voters=1, n_valid=2, n_invalid=0,
|
|
n_agree_prev_block=0)
|
|
with pytest.raises(BigchainDBCritical):
|
|
Voting.decide_votes(n_voters=1, n_valid=0, n_invalid=2,
|
|
n_agree_prev_block=0)
|
|
with pytest.raises(BigchainDBCritical):
|
|
Voting.decide_votes(n_voters=1, n_valid=0, n_invalid=0,
|
|
n_agree_prev_block=2)
|
|
|
|
|
|
################################################################################
|
|
# Tests for vote signature
|
|
|
|
|
|
def test_verify_vote_signature_passes(b):
|
|
vote = b.vote('block', 'a', True)
|
|
assert Voting.verify_vote_signature(vote)
|
|
|
|
|
|
def test_verify_vote_signature_fails(b):
|
|
vote = b.vote('block', 'a', True)
|
|
vote['signature'] = ''
|
|
assert not Voting.verify_vote_signature(vote)
|
|
|
|
|
|
################################################################################
|
|
# Tests for vote schema
|
|
|
|
|
|
def test_verify_vote_schema(b):
|
|
vote = b.vote('b' * 64, 'a' * 64, True)
|
|
assert Voting.verify_vote_schema(vote)
|
|
vote = b.vote('b', 'a', True)
|
|
assert not Voting.verify_vote_schema(vote)
|
|
|
|
|
|
################################################################################
|
|
# block_election tests
|
|
# A more thorough test will follow as part of #1217
|
|
|
|
|
|
def test_block_election(b):
|
|
|
|
class TestVoting(Voting):
|
|
@classmethod
|
|
def verify_vote_signature(cls, vote):
|
|
return True
|
|
|
|
@classmethod
|
|
def verify_vote_schema(cls, vote):
|
|
return True
|
|
|
|
keyring = 'abc'
|
|
block = {'id': 'xyz', 'block': {'voters': 'ab'}}
|
|
votes = [{
|
|
'node_pubkey': c,
|
|
'vote': {'is_block_valid': True, 'previous_block': 'a'}
|
|
} for c in 'abc']
|
|
|
|
assert TestVoting.block_election(block, votes, keyring) == {
|
|
'status': VALID,
|
|
'block_id': 'xyz',
|
|
'counts': {'n_agree_prev_block': 2, 'n_valid': 2, 'n_invalid': 0},
|
|
'ineligible': [votes[-1]],
|
|
'cheat': [],
|
|
'malformed': [],
|
|
}
|