Problem: Need tests to verify that the unified conclusion for ValidatorElection and MigrationElection works when both election types conclude in the same block

Solution: Wrote some integration tests
This commit is contained in:
z-bowen 2018-09-13 22:46:49 +02:00
parent 9942867e47
commit cc0ce0e5e4
7 changed files with 210 additions and 71 deletions

View File

@ -20,15 +20,17 @@ from logging.config import dictConfig
import pytest
from pymongo import MongoClient
from bigchaindb import ValidatorElection
from bigchaindb.common import crypto
from bigchaindb.log import setup_logging
from bigchaindb.migrations.migration_election import MigrationElection
from bigchaindb.tendermint_utils import key_from_base64
from bigchaindb.backend import schema
from bigchaindb.backend import schema, query
from bigchaindb.common.crypto import (key_pair_from_ed25519_key,
public_key_from_ed25519_key)
from bigchaindb.common.exceptions import DatabaseDoesNotExist
from bigchaindb.lib import Block
from tests.utils import gen_vote
TEST_DB_NAME = 'bigchain_test'
@ -694,3 +696,117 @@ def new_validator():
'type': 'ed25519-base16'},
'power': power,
'node_id': node_id}
@pytest.fixture
def valid_upsert_validator_election(b_mock, node_key, new_validator):
voters = ValidatorElection.recipients(b_mock)
return ValidatorElection.generate([node_key.public_key],
voters,
new_validator, None).sign([node_key.private_key])
@pytest.fixture
def valid_upsert_validator_election_2(b_mock, node_key, new_validator):
voters = ValidatorElection.recipients(b_mock)
return ValidatorElection.generate([node_key.public_key],
voters,
new_validator, None).sign([node_key.private_key])
@pytest.fixture
def valid_migration_election(b_mock, node_key):
voters = MigrationElection.recipients(b_mock)
return MigrationElection.generate([node_key.public_key],
voters,
{}, None).sign([node_key.private_key])
@pytest.fixture
def valid_migration_election_2(b_mock, node_key):
voters = MigrationElection.recipients(b_mock)
return MigrationElection.generate([node_key.public_key],
voters,
{}, None).sign([node_key.private_key])
@pytest.fixture
def ongoing_validator_election(b, valid_upsert_validator_election, ed25519_node_keys):
validators = b.get_validators(height=1)
genesis_validators = {'validators': validators,
'height': 0,
'election_id': None}
query.store_validator_set(b.connection, genesis_validators)
b.store_bulk_transactions([valid_upsert_validator_election])
block_1 = Block(app_hash='hash_1', height=1, transactions=[valid_upsert_validator_election.id])
b.store_block(block_1._asdict())
return valid_upsert_validator_election
@pytest.fixture
def ongoing_validator_election_2(b, valid_upsert_validator_election_2, ed25519_node_keys):
validators = b.get_validators(height=1)
genesis_validators = {'validators': validators,
'height': 0,
'election_id': None}
query.store_validator_set(b.connection, genesis_validators)
b.store_bulk_transactions([valid_upsert_validator_election_2])
block_1 = Block(app_hash='hash_2', height=1, transactions=[valid_upsert_validator_election_2.id])
b.store_block(block_1._asdict())
return valid_upsert_validator_election_2
@pytest.fixture
def ongoing_migration_election(b, valid_migration_election, ed25519_node_keys):
b.store_bulk_transactions([valid_migration_election])
block_1 = Block(app_hash='hash_1', height=1, transactions=[valid_migration_election.id])
b.store_block(block_1._asdict())
return valid_migration_election
@pytest.fixture
def ongoing_migration_election_2(b, valid_migration_election_2, ed25519_node_keys):
b.store_bulk_transactions([valid_migration_election_2])
block_1 = Block(app_hash='hash_2', height=1, transactions=[valid_migration_election_2.id])
b.store_block(block_1._asdict())
return valid_migration_election_2
@pytest.fixture
def validator_election_votes(b_mock, ongoing_validator_election, ed25519_node_keys):
voters = ValidatorElection.recipients(b_mock)
votes = generate_votes(ongoing_validator_election, voters, ed25519_node_keys)
return votes
@pytest.fixture
def validator_election_votes_2(b_mock, ongoing_validator_election_2, ed25519_node_keys):
voters = ValidatorElection.recipients(b_mock)
votes = generate_votes(ongoing_validator_election_2, voters, ed25519_node_keys)
return votes
@pytest.fixture
def migration_election_votes(b_mock, ongoing_migration_election, ed25519_node_keys):
voters = MigrationElection.recipients(b_mock)
votes = generate_votes(ongoing_migration_election, voters, ed25519_node_keys)
return votes
@pytest.fixture
def migration_election_votes_2(b_mock, ongoing_migration_election_2, ed25519_node_keys):
voters = MigrationElection.recipients(b_mock)
votes = generate_votes(ongoing_migration_election_2, voters, ed25519_node_keys)
return votes
def generate_votes(election, voters, keys):
votes = []
for voter in range(len(voters)):
v = gen_vote(election, voter, keys)
votes.append(v)
return votes

View File

View File

@ -0,0 +1,60 @@
from unittest.mock import MagicMock
import pytest
from bigchaindb.elections.election import Election
@pytest.mark.bdb
def test_approved_elections_one_migration_one_upsert(b,
ongoing_validator_election, validator_election_votes,
ongoing_migration_election, migration_election_votes):
txns = validator_election_votes + \
migration_election_votes
mock_chain_migration, mock_store_validator = run_approved_elections(b, txns)
mock_chain_migration.assert_called_once()
mock_store_validator.assert_called_once()
@pytest.mark.bdb
def test_approved_elections_two_migrations_two_upsert(b,
ongoing_validator_election, validator_election_votes,
ongoing_validator_election_2, validator_election_votes_2,
ongoing_migration_election, migration_election_votes,
ongoing_migration_election_2, migration_election_votes_2):
txns = validator_election_votes + \
validator_election_votes_2 + \
migration_election_votes + \
migration_election_votes_2
mock_chain_migration, mock_store_validator = run_approved_elections(b, txns)
mock_chain_migration.assert_called_once()
mock_store_validator.assert_called_once()
@pytest.mark.bdb
def test_approved_elections_two_migrations_one_upsert(b,
ongoing_validator_election, validator_election_votes,
ongoing_migration_election, migration_election_votes,
ongoing_migration_election_2, migration_election_votes_2):
txns = validator_election_votes + \
migration_election_votes + \
migration_election_votes_2
mock_chain_migration, mock_store_validator = run_approved_elections(b, txns)
mock_chain_migration.assert_called_once()
mock_store_validator.assert_called_once()
def test_approved_elections_no_elections(b):
txns = []
mock_chain_migration, mock_store_validator = run_approved_elections(b, txns)
mock_chain_migration.assert_not_called()
mock_store_validator.assert_not_called()
def run_approved_elections(bigchain, txns):
mock_chain_migration = MagicMock()
mock_store_validator = MagicMock()
bigchain.migrate_abci_chain = mock_chain_migration
bigchain.store_validator_set = mock_store_validator
Election.approved_elections(bigchain, 1, txns)
return mock_chain_migration, mock_store_validator

View File

@ -5,20 +5,10 @@ from unittest.mock import patch
import pytest
from bigchaindb import Vote
from bigchaindb.backend.localmongodb import query
from bigchaindb.lib import Block
from bigchaindb.upsert_validator import ValidatorElection
@pytest.fixture
def valid_upsert_validator_election(b_mock, node_key, new_validator):
voters = ValidatorElection.recipients(b_mock)
return ValidatorElection.generate([node_key.public_key],
voters,
new_validator, None).sign([node_key.private_key])
@pytest.fixture
def valid_upsert_validator_election_b(b, node_key, new_validator):
voters = ValidatorElection.recipients(b)
@ -37,30 +27,16 @@ def fixed_seed_election(b_mock, node_key, new_validator):
@pytest.fixture
def ongoing_election(b, valid_upsert_validator_election, ed25519_node_keys):
validators = b.get_validators(height=1)
genesis_validators = {'validators': validators,
'height': 0,
'election_id': None}
query.store_validator_set(b.connection, genesis_validators)
b.store_bulk_transactions([valid_upsert_validator_election])
block_1 = Block(app_hash='hash_1', height=1, transactions=[valid_upsert_validator_election.id])
b.store_block(block_1._asdict())
return valid_upsert_validator_election
@pytest.fixture
def concluded_election(b, ongoing_election, ed25519_node_keys):
def concluded_election(b, ongoing_validator_election, ed25519_node_keys):
election_result = {'height': 2,
'election_id': ongoing_election.id}
'election_id': ongoing_validator_election.id}
query.store_election_results(b.connection, election_result)
return ongoing_election
return ongoing_validator_election
@pytest.fixture
def inconclusive_election(b, ongoing_election, new_validator):
def inconclusive_election(b, ongoing_validator_election, new_validator):
validators = b.get_validators(height=1)
validators[0]['voting_power'] = 15
validator_update = {'validators': validators,
@ -68,20 +44,4 @@ def inconclusive_election(b, ongoing_election, new_validator):
'election_id': 'some_other_election'}
query.store_validator_set(b.connection, validator_update)
return ongoing_election
def vote(election, voter, keys, b):
election_input = election.to_inputs()[voter]
votes = election.outputs[voter].amount
public_key = election_input.owners_before[0]
key = keys[public_key]
election_pub_key = ValidatorElection.to_public_key(election.id)
v = Vote.generate([election_input],
[([election_pub_key], votes)],
election_id=election.id)\
.sign([key.private_key])
b.store_bulk_transactions([v])
return v
return ongoing_validator_election

View File

@ -12,7 +12,7 @@ from bigchaindb.common.exceptions import AmountError
from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.exceptions import ValidationError
from bigchaindb.elections.vote import Vote
from tests.utils import generate_block
from tests.utils import generate_block, gen_vote
pytestmark = [pytest.mark.execute]
@ -341,22 +341,6 @@ def test_get_validator_update(b, node_keys, node_key, ed25519_node_keys):
# ============================================================================
# Helper functions
# ============================================================================
def to_inputs(election, i, ed25519_node_keys):
input0 = election.to_inputs()[i]
votes = election.outputs[i].amount
public_key0 = input0.owners_before[0]
key0 = ed25519_node_keys[public_key0]
return (input0, votes, key0)
def gen_vote(election, i, ed25519_node_keys):
(input_i, votes_i, key_i) = to_inputs(election, i, ed25519_node_keys)
election_pub_key = ValidatorElection.to_public_key(election.id)
return Vote.generate([input_i],
[([election_pub_key], votes_i)],
election_id=election.id)\
.sign([key_i.private_key])
def reset_validator_set(b, node_keys, height):
validators = []

View File

@ -111,9 +111,9 @@ def test_upsert_validator_invalid_election(b_mock, new_validator, node_key, fixe
tx_election.validate(b_mock)
def test_get_status_ongoing(b, ongoing_election, new_validator):
def test_get_status_ongoing(b, ongoing_validator_election, new_validator):
status = ValidatorElection.ONGOING
resp = ongoing_election.get_status(b)
resp = ongoing_validator_election.get_status(b)
assert resp == status
@ -158,13 +158,13 @@ def test_get_status_inconclusive(b, inconclusive_election, new_validator):
assert resp == status
def test_upsert_validator_show(caplog, ongoing_election, b):
def test_upsert_validator_show(caplog, ongoing_validator_election, b):
from bigchaindb.commands.bigchaindb import run_election_show
election_id = ongoing_election.id
public_key = public_key_to_base64(ongoing_election.asset['data']['public_key']['value'])
power = ongoing_election.asset['data']['power']
node_id = ongoing_election.asset['data']['node_id']
election_id = ongoing_validator_election.id
public_key = public_key_to_base64(ongoing_validator_election.asset['data']['public_key']['value'])
power = ongoing_validator_election.asset['data']['power']
node_id = ongoing_validator_election.asset['data']['node_id']
status = ValidatorElection.ONGOING
show_args = Namespace(action='show',

View File

@ -4,8 +4,10 @@
from functools import singledispatch
from bigchaindb import Vote
from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection
from bigchaindb.backend.schema import TABLES
from bigchaindb.elections.election import Election
@singledispatch
@ -33,3 +35,20 @@ def generate_block(bigchain):
code, message = bigchain.write_transaction(tx, 'broadcast_tx_commit')
assert code == 202
time.sleep(2)
def to_inputs(election, i, ed25519_node_keys):
input0 = election.to_inputs()[i]
votes = election.outputs[i].amount
public_key0 = input0.owners_before[0]
key0 = ed25519_node_keys[public_key0]
return (input0, votes, key0)
def gen_vote(election, i, ed25519_node_keys):
(input_i, votes_i, key_i) = to_inputs(election, i, ed25519_node_keys)
election_pub_key = Election.to_public_key(election.id)
return Vote.generate([input_i],
[([election_pub_key], votes_i)],
election_id=election.id)\
.sign([key_i.private_key])