diff --git a/tests/conftest.py b/tests/conftest.py index 88ad54e3..a628b404 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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 diff --git a/tests/elections/__init__.py b/tests/elections/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/elections/test_election.py b/tests/elections/test_election.py new file mode 100644 index 00000000..422c9251 --- /dev/null +++ b/tests/elections/test_election.py @@ -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 diff --git a/tests/upsert_validator/conftest.py b/tests/upsert_validator/conftest.py index 7a2f4f5b..58b5e6dd 100644 --- a/tests/upsert_validator/conftest.py +++ b/tests/upsert_validator/conftest.py @@ -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 diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index e4198aa4..0b8c9ff7 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -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 = [] diff --git a/tests/upsert_validator/test_validator_election.py b/tests/upsert_validator/test_validator_election.py index c1f56fff..975379b0 100644 --- a/tests/upsert_validator/test_validator_election.py +++ b/tests/upsert_validator/test_validator_election.py @@ -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', diff --git a/tests/utils.py b/tests/utils.py index 87c07a79..852be5e6 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -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])