From c74af724e43c95304fe701535057319ba9c1807a Mon Sep 17 00:00:00 2001 From: z-bowen Date: Wed, 12 Sep 2018 18:56:05 +0200 Subject: [PATCH] Problem: Need tests for `MigrationElection` Solution: - wrote a test for valid elections - refactored some fixtures to make it easier to share between `migration` and `upsert-validator` tests --- tests/commands/test_commands.py | 2 +- tests/conftest.py | 20 +++ tests/migrations/conftest.py | 11 ++ tests/migrations/test_migration_election.py | 9 ++ tests/upsert_validator/conftest.py | 32 +---- .../test_upsert_validator_vote.py | 119 +++++++++--------- 6 files changed, 107 insertions(+), 86 deletions(-) create mode 100644 tests/migrations/conftest.py create mode 100644 tests/migrations/test_migration_election.py diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 544af18a..5d897539 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -453,7 +453,7 @@ def test_election_approve_without_tendermint(caplog, b, priv_validator_path, new b, election_id = call_election(b, new_validator, node_key) - # call run_upsert_validator_approve with args that point to the election + # call run_election_approve with args that point to the election args = Namespace(action='approve', election_id=election_id, sk=priv_validator_path, diff --git a/tests/conftest.py b/tests/conftest.py index 15cfcf01..88ad54e3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -242,6 +242,26 @@ def b(): return BigchainDB() +@pytest.fixture +def b_mock(b, network_validators): + b.get_validators = mock_get_validators(network_validators) + + return b + + +def mock_get_validators(network_validators): + def validator_set(height): + validators = [] + for public_key, power in network_validators.items(): + validators.append({ + 'public_key': {'type': 'ed25519-base64', 'value': public_key}, + 'voting_power': power + }) + return validators + + return validator_set + + @pytest.fixture def create_tx(alice, user_pk): from bigchaindb.models import Transaction diff --git a/tests/migrations/conftest.py b/tests/migrations/conftest.py new file mode 100644 index 00000000..f0efdcf4 --- /dev/null +++ b/tests/migrations/conftest.py @@ -0,0 +1,11 @@ +import pytest + +from bigchaindb.migrations.migration_election import MigrationElection + + +@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]) diff --git a/tests/migrations/test_migration_election.py b/tests/migrations/test_migration_election.py new file mode 100644 index 00000000..837bebbd --- /dev/null +++ b/tests/migrations/test_migration_election.py @@ -0,0 +1,9 @@ +from bigchaindb.migrations.migration_election import MigrationElection + + +def test_valid_migration_election(b_mock, node_key): + voters = MigrationElection.recipients(b_mock) + election = MigrationElection.generate([node_key.public_key], + voters, + {}, None).sign([node_key.private_key]) + assert election.validate(b_mock) diff --git a/tests/upsert_validator/conftest.py b/tests/upsert_validator/conftest.py index 9ab2dad8..7a2f4f5b 100644 --- a/tests/upsert_validator/conftest.py +++ b/tests/upsert_validator/conftest.py @@ -12,27 +12,7 @@ from bigchaindb.upsert_validator import ValidatorElection @pytest.fixture -def b_mock(b, network_validators): - b.get_validators = mock_get_validators(network_validators) - - return b - - -def mock_get_validators(network_validators): - def validator_set(height): - validators = [] - for public_key, power in network_validators.items(): - validators.append({ - 'public_key': {'type': 'ed25519-base64', 'value': public_key}, - 'voting_power': power - }) - return validators - - return validator_set - - -@pytest.fixture -def valid_election(b_mock, node_key, new_validator): +def valid_upsert_validator_election(b_mock, node_key, new_validator): voters = ValidatorElection.recipients(b_mock) return ValidatorElection.generate([node_key.public_key], voters, @@ -40,7 +20,7 @@ def valid_election(b_mock, node_key, new_validator): @pytest.fixture -def valid_election_b(b, node_key, new_validator): +def valid_upsert_validator_election_b(b, node_key, new_validator): voters = ValidatorElection.recipients(b) return ValidatorElection.generate([node_key.public_key], voters, @@ -57,17 +37,17 @@ def fixed_seed_election(b_mock, node_key, new_validator): @pytest.fixture -def ongoing_election(b, valid_election, ed25519_node_keys): +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_election]) - block_1 = Block(app_hash='hash_1', height=1, transactions=[valid_election.id]) + 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_election + return valid_upsert_validator_election @pytest.fixture diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index 7196fa7a..e4198aa4 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -5,6 +5,7 @@ import pytest import codecs +from bigchaindb.elections.election import Election from bigchaindb.tendermint_utils import public_key_to_base64 from bigchaindb.upsert_validator import ValidatorElection from bigchaindb.common.exceptions import AmountError @@ -17,92 +18,92 @@ pytestmark = [pytest.mark.execute] @pytest.mark.bdb -def test_upsert_validator_valid_election_vote(b_mock, valid_election, ed25519_node_keys): - b_mock.store_bulk_transactions([valid_election]) +def test_upsert_validator_valid_election_vote(b_mock, valid_upsert_validator_election, ed25519_node_keys): + b_mock.store_bulk_transactions([valid_upsert_validator_election]) - input0 = valid_election.to_inputs()[0] - votes = valid_election.outputs[0].amount + input0 = valid_upsert_validator_election.to_inputs()[0] + votes = valid_upsert_validator_election.outputs[0].amount public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] - election_pub_key = ValidatorElection.to_public_key(valid_election.id) + election_pub_key = ValidatorElection.to_public_key(valid_upsert_validator_election.id) vote = Vote.generate([input0], [([election_pub_key], votes)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) assert vote.validate(b_mock) @pytest.mark.bdb -def test_upsert_validator_valid_non_election_vote(b_mock, valid_election, ed25519_node_keys): - b_mock.store_bulk_transactions([valid_election]) +def test_upsert_validator_valid_non_election_vote(b_mock, valid_upsert_validator_election, ed25519_node_keys): + b_mock.store_bulk_transactions([valid_upsert_validator_election]) - input0 = valid_election.to_inputs()[0] - votes = valid_election.outputs[0].amount + input0 = valid_upsert_validator_election.to_inputs()[0] + votes = valid_upsert_validator_election.outputs[0].amount public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] - election_pub_key = ValidatorElection.to_public_key(valid_election.id) + election_pub_key = ValidatorElection.to_public_key(valid_upsert_validator_election.id) # Ensure that threshold conditions are now allowed with pytest.raises(ValidationError): Vote.generate([input0], [([election_pub_key, key0.public_key], votes)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) @pytest.mark.bdb -def test_upsert_validator_delegate_election_vote(b_mock, valid_election, ed25519_node_keys): +def test_upsert_validator_delegate_election_vote(b_mock, valid_upsert_validator_election, ed25519_node_keys): alice = generate_key_pair() - b_mock.store_bulk_transactions([valid_election]) + b_mock.store_bulk_transactions([valid_upsert_validator_election]) - input0 = valid_election.to_inputs()[0] - votes = valid_election.outputs[0].amount + input0 = valid_upsert_validator_election.to_inputs()[0] + votes = valid_upsert_validator_election.outputs[0].amount public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] delegate_vote = Vote.generate([input0], [([alice.public_key], 3), ([key0.public_key], votes-3)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) assert delegate_vote.validate(b_mock) b_mock.store_bulk_transactions([delegate_vote]) - election_pub_key = ValidatorElection.to_public_key(valid_election.id) + election_pub_key = ValidatorElection.to_public_key(valid_upsert_validator_election.id) alice_votes = delegate_vote.to_inputs()[0] alice_casted_vote = Vote.generate([alice_votes], [([election_pub_key], 3)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([alice.private_key]) assert alice_casted_vote.validate(b_mock) key0_votes = delegate_vote.to_inputs()[1] key0_casted_vote = Vote.generate([key0_votes], [([election_pub_key], votes-3)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) assert key0_casted_vote.validate(b_mock) @pytest.mark.bdb -def test_upsert_validator_invalid_election_vote(b_mock, valid_election, ed25519_node_keys): - b_mock.store_bulk_transactions([valid_election]) +def test_upsert_validator_invalid_election_vote(b_mock, valid_upsert_validator_election, ed25519_node_keys): + b_mock.store_bulk_transactions([valid_upsert_validator_election]) - input0 = valid_election.to_inputs()[0] - votes = valid_election.outputs[0].amount + input0 = valid_upsert_validator_election.to_inputs()[0] + votes = valid_upsert_validator_election.outputs[0].amount public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] - election_pub_key = ValidatorElection.to_public_key(valid_election.id) + election_pub_key = ValidatorElection.to_public_key(valid_upsert_validator_election.id) vote = Vote.generate([input0], [([election_pub_key], votes+1)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) with pytest.raises(AmountError): @@ -110,107 +111,107 @@ def test_upsert_validator_invalid_election_vote(b_mock, valid_election, ed25519_ @pytest.mark.bdb -def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys): +def test_valid_election_votes_received(b_mock, valid_upsert_validator_election, ed25519_node_keys): alice = generate_key_pair() - b_mock.store_bulk_transactions([valid_election]) - assert valid_election.get_commited_votes(b_mock) == 0 + b_mock.store_bulk_transactions([valid_upsert_validator_election]) + assert valid_upsert_validator_election.get_commited_votes(b_mock) == 0 - input0 = valid_election.to_inputs()[0] - votes = valid_election.outputs[0].amount + input0 = valid_upsert_validator_election.to_inputs()[0] + votes = valid_upsert_validator_election.outputs[0].amount public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] # delegate some votes to alice delegate_vote = Vote.generate([input0], [([alice.public_key], 4), ([key0.public_key], votes-4)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) b_mock.store_bulk_transactions([delegate_vote]) - assert valid_election.get_commited_votes(b_mock) == 0 + assert valid_upsert_validator_election.get_commited_votes(b_mock) == 0 - election_public_key = ValidatorElection.to_public_key(valid_election.id) + election_public_key = ValidatorElection.to_public_key(valid_upsert_validator_election.id) alice_votes = delegate_vote.to_inputs()[0] key0_votes = delegate_vote.to_inputs()[1] alice_casted_vote = Vote.generate([alice_votes], [([election_public_key], 2), ([alice.public_key], 2)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([alice.private_key]) assert alice_casted_vote.validate(b_mock) b_mock.store_bulk_transactions([alice_casted_vote]) # Check if the delegated vote is count as valid vote - assert valid_election.get_commited_votes(b_mock) == 2 + assert valid_upsert_validator_election.get_commited_votes(b_mock) == 2 key0_casted_vote = Vote.generate([key0_votes], [([election_public_key], votes-4)], - election_id=valid_election.id)\ + election_id=valid_upsert_validator_election.id)\ .sign([key0.private_key]) assert key0_casted_vote.validate(b_mock) b_mock.store_bulk_transactions([key0_casted_vote]) - assert valid_election.get_commited_votes(b_mock) == votes-2 + assert valid_upsert_validator_election.get_commited_votes(b_mock) == votes - 2 @pytest.mark.bdb -def test_valid_election_conclude(b_mock, valid_election, ed25519_node_keys): +def test_valid_election_conclude(b_mock, valid_upsert_validator_election, ed25519_node_keys): # Node 0: cast vote - tx_vote0 = gen_vote(valid_election, 0, ed25519_node_keys) + tx_vote0 = gen_vote(valid_upsert_validator_election, 0, ed25519_node_keys) # check if the vote is valid even before the election doesn't exist with pytest.raises(ValidationError): assert tx_vote0.validate(b_mock) # store election - b_mock.store_bulk_transactions([valid_election]) + b_mock.store_bulk_transactions([valid_upsert_validator_election]) # cannot conclude election as not votes exist - assert not ValidatorElection.has_concluded(b_mock, valid_election.id) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id) # validate vote assert tx_vote0.validate(b_mock) - assert not ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote0]) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote0]) b_mock.store_bulk_transactions([tx_vote0]) - assert not ValidatorElection.has_concluded(b_mock, valid_election.id) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id) # Node 1: cast vote - tx_vote1 = gen_vote(valid_election, 1, ed25519_node_keys) + tx_vote1 = gen_vote(valid_upsert_validator_election, 1, ed25519_node_keys) # Node 2: cast vote - tx_vote2 = gen_vote(valid_election, 2, ed25519_node_keys) + tx_vote2 = gen_vote(valid_upsert_validator_election, 2, ed25519_node_keys) # Node 3: cast vote - tx_vote3 = gen_vote(valid_election, 3, ed25519_node_keys) + tx_vote3 = gen_vote(valid_upsert_validator_election, 3, ed25519_node_keys) assert tx_vote1.validate(b_mock) - assert not ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote1]) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote1]) # 2/3 is achieved in the same block so the election can be.has_concludedd - assert ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote1, tx_vote2]) + assert ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote1, tx_vote2]) b_mock.store_bulk_transactions([tx_vote1]) - assert not ValidatorElection.has_concluded(b_mock, valid_election.id) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id) assert tx_vote2.validate(b_mock) assert tx_vote3.validate(b_mock) # conclusion can be triggered my different votes in the same block - assert ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote2]) - assert ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote2, tx_vote3]) + assert ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote2]) + assert ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote2, tx_vote3]) b_mock.store_bulk_transactions([tx_vote2]) # Once the blockchain records >2/3 of the votes the election is assumed to be.has_concludedd # so any invocation of `.has_concluded` for that election should return False - assert not ValidatorElection.has_concluded(b_mock, valid_election.id) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id) # Vote is still valid but the election cannot be.has_concludedd as it it assmed that it has # been.has_concludedd before assert tx_vote3.validate(b_mock) - assert not ValidatorElection.has_concluded(b_mock, valid_election.id, [tx_vote3]) + assert not ValidatorElection.has_concluded(b_mock, valid_upsert_validator_election.id, [tx_vote3]) @pytest.mark.abci @@ -293,17 +294,17 @@ def test_get_validator_update(b, node_keys, node_key, ed25519_node_keys): assert not ValidatorElection.has_concluded(b, election.id, [tx_vote0, tx_vote1]) assert ValidatorElection.has_concluded(b, election.id, [tx_vote0, tx_vote1, tx_vote2]) - assert not ValidatorElection.approved_update(b, 4, [tx_vote0]) - assert not ValidatorElection.approved_update(b, 4, [tx_vote0, tx_vote1]) + assert not Election.approved_elections(b, 4, [tx_vote0]).get('VALIDATOR_ELECTION') + assert not Election.approved_elections(b, 4, [tx_vote0, tx_vote1]).get('VALIDATOR_ELECTION') - update = ValidatorElection.approved_update(b, 4, [tx_vote0, tx_vote1, tx_vote2]) + update = Election.approved_elections(b, 4, [tx_vote0, tx_vote1, tx_vote2]).get('VALIDATOR_ELECTION') assert update update_public_key = codecs.encode(update.pub_key.data, 'base64').decode().rstrip('\n') assert update_public_key == public_key64 b.store_bulk_transactions([tx_vote0, tx_vote1]) - update = ValidatorElection.approved_update(b, 4, [tx_vote2]) + update = Election.approved_elections(b, 4, [tx_vote2]).get('VALIDATOR_ELECTION') assert update update_public_key = codecs.encode(update.pub_key.data, 'base64').decode().rstrip('\n') assert update_public_key == public_key64 @@ -326,7 +327,7 @@ def test_get_validator_update(b, node_keys, node_key, ed25519_node_keys): b.store_bulk_transactions([tx_vote0, tx_vote1]) - update = ValidatorElection.approved_update(b, 9, [tx_vote2]) + update = Election.approved_elections(b, 9, [tx_vote2]).get('VALIDATOR_ELECTION') if update: update_public_key = codecs.encode(update.pub_key.data, 'base64').decode().rstrip('\n') assert update