Port final tests

This commit is contained in:
vrde 2016-08-02 16:04:08 +02:00
parent 074cae4484
commit 79980c08a6
No known key found for this signature in database
GPG Key ID: 6581C7C39B3D397D
3 changed files with 16 additions and 138 deletions

View File

@ -38,10 +38,14 @@ class Vote:
block (dict): the block to process block (dict): the block to process
Returns: Returns:
An iterator that yields a transaction, block id, and the total ``None`` if the block has been already voted, an iterator that
number of transactions contained in the block. yields a transaction, block id, and the total number of
transactions contained in the block otherwise.
""" """
if self.bigchain.has_previous_vote(block):
return
num_tx = len(block['block']['transactions']) num_tx = len(block['block']['transactions'])
for tx in block['block']['transactions']: for tx in block['block']['transactions']:
yield tx, block['id'], num_tx yield tx, block['id'], num_tx

View File

@ -1,11 +1,8 @@
import pytest
import time import time
import rethinkdb as r import rethinkdb as r
import multiprocessing as mp import multiprocessing as mp
from bigchaindb import util from bigchaindb.voter import Election
from bigchaindb.voter import Election, BlockStream
from bigchaindb import crypto, Bigchain from bigchaindb import crypto, Bigchain
@ -23,132 +20,6 @@ def dummy_block():
return block return block
class TestBigchainVoter(object):
def test_vote_creation_valid(self, b):
# create valid block
block = dummy_block()
# retrieve vote
vote = b.vote(block['id'], 'abc', True)
# assert vote is correct
assert vote['vote']['voting_for_block'] == block['id']
assert vote['vote']['previous_block'] == 'abc'
assert vote['vote']['is_block_valid'] is True
assert vote['vote']['invalid_reason'] is None
assert vote['node_pubkey'] == b.me
assert crypto.VerifyingKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_vote_creation_invalid(self, b):
# create valid block
block = dummy_block()
# retrieve vote
vote = b.vote(block['id'], 'abc', False)
# assert vote is correct
assert vote['vote']['voting_for_block'] == block['id']
assert vote['vote']['previous_block'] == 'abc'
assert vote['vote']['is_block_valid'] is False
assert vote['vote']['invalid_reason'] is None
assert vote['node_pubkey'] == b.me
assert crypto.VerifyingKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_voter_considers_unvoted_blocks_when_single_node(self, b):
# simulate a voter going donw in a single node environment
b.create_genesis_block()
# insert blocks in the database while the voter process is not listening
# (these blocks won't appear in the changefeed)
block_1 = dummy_block()
b.write_block(block_1, durability='hard')
block_2 = dummy_block()
b.write_block(block_2, durability='hard')
# voter is back online, we simulate that by creating a queue and a Voter instance
q_new_block = mp.Queue()
voter = Voter(q_new_block)
# vote
voter.start()
time.sleep(1)
# create a new block that will appear in the changefeed
block_3 = dummy_block()
b.write_block(block_3, durability='hard')
time.sleep(1)
voter.kill()
# retrive blocks from bigchain
blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn))
# FIXME: remove genesis block, we don't vote on it (might change in the future)
blocks.pop(0)
# retrieve vote
votes = r.table('votes').run(b.conn)
votes = list(votes)
assert all(vote['node_pubkey'] == b.me for vote in votes)
def test_voter_chains_blocks_with_the_previous_ones(self, b):
b.create_genesis_block()
# sleep so that `block_*` as a higher timestamp then `genesis`
time.sleep(1)
block_1 = dummy_block()
b.write_block(block_1, durability='hard')
time.sleep(1)
block_2 = dummy_block()
b.write_block(block_2, durability='hard')
q_new_block = mp.Queue()
voter = Voter(q_new_block)
voter.start()
time.sleep(1)
voter.kill()
# retrive blocks from bigchain
blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn))
# retrieve votes
votes = list(r.table('votes').run(b.conn))
assert votes[0]['vote']['voting_for_block'] in (blocks[1]['id'], blocks[2]['id'])
assert votes[1]['vote']['voting_for_block'] in (blocks[1]['id'], blocks[2]['id'])
def test_voter_checks_for_previous_vote(self, b):
b.create_genesis_block()
block_1 = dummy_block()
b.write_block(block_1, durability='hard')
q_new_block = mp.Queue()
voter = Voter(q_new_block)
voter.start()
time.sleep(1)
retrieved_block = r.table('bigchain').get(block_1['id']).run(b.conn)
# queue block for voting AGAIN
q_new_block.put(retrieved_block)
time.sleep(1)
voter.kill()
re_retrieved_block = r.table('bigchain').get(block_1['id']).run(b.conn)
# block should be unchanged
assert retrieved_block == re_retrieved_block
@pytest.mark.skipif(reason='Updating the block_number must be atomic')
def test_updating_block_number_must_be_atomic(self):
pass
class TestBlockElection(object): class TestBlockElection(object):
def test_quorum(self, b): def test_quorum(self, b):

View File

@ -357,6 +357,8 @@ def test_voter_checks_for_previous_vote(monkeypatch, b):
block_1 = dummy_block(b) block_1 = dummy_block(b)
inpipe.put(block_1) inpipe.put(block_1)
assert r.table('votes').count().run(b.conn) == 0
vote_pipeline = vote.create_pipeline() vote_pipeline = vote.create_pipeline()
vote_pipeline.setup(indata=inpipe, outdata=outpipe) vote_pipeline.setup(indata=inpipe, outdata=outpipe)
vote_pipeline.start() vote_pipeline.start()
@ -364,17 +366,18 @@ def test_voter_checks_for_previous_vote(monkeypatch, b):
# wait for the result # wait for the result
outpipe.get() outpipe.get()
retrieved_block = r.table('bigchain').get(block_1['id']).run(b.conn)
# queue block for voting AGAIN # queue block for voting AGAIN
inpipe.put(retrieved_block) inpipe.put(block_1)
re_retrieved_block = r.table('bigchain').get(block_1['id']).run(b.conn) # queue another block
inpipe.put(dummy_block(b))
# wait for the result of the new block
outpipe.get()
vote_pipeline.terminate() vote_pipeline.terminate()
# block should be unchanged assert r.table('votes').count().run(b.conn) == 2
assert retrieved_block == re_retrieved_block
@patch.object(Pipeline, 'start') @patch.object(Pipeline, 'start')