made ABCI non-singleton again (to improve mock testabiliy)

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2023-02-27 16:43:58 +01:00
parent c6b22a8e8c
commit 743cadd877
No known key found for this signature in database
8 changed files with 44 additions and 60 deletions

View File

@ -17,7 +17,7 @@ MODE_COMMIT = BROADCAST_TX_COMMIT
MODE_LIST = (BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC, MODE_COMMIT)
class ABCI_RPC(metaclass=Singleton):
class ABCI_RPC:
def __init__(self):
autoconfigure()
self.tendermint_host = Config().get()["tendermint"]["host"]

View File

@ -124,7 +124,7 @@ def run_election_new(args, planet):
globals()[f"run_election_new_{election_type}"](args, planet)
def create_new_election(sk, planet, election_class, data):
def create_new_election(sk, planet, election_class, data, abci_rpc):
try:
key = load_node_key(sk)
voters = planet.get_recipients_list()
@ -137,8 +137,8 @@ def create_new_election(sk, planet, election_class, data):
logger.error(fd_404)
return False
resp = ABCI_RPC().write_transaction(
MODE_LIST, ABCI_RPC().tendermint_rpc_endpoint, MODE_COMMIT, election, BROADCAST_TX_COMMIT
resp = abci_rpc.write_transaction(
MODE_LIST, abci_rpc.tendermint_rpc_endpoint, MODE_COMMIT, election, BROADCAST_TX_COMMIT
)
if resp == (202, ""):
logger.info("[SUCCESS] Submitted proposal with id: {}".format(election.id))
@ -148,7 +148,7 @@ def create_new_election(sk, planet, election_class, data):
return False
def run_election_new_upsert_validator(args, planet):
def run_election_new_upsert_validator(args, planet, abci_rpc):
"""Initiates an election to add/update/remove a validator to an existing Planetmint network
:param args: dict
@ -172,10 +172,10 @@ def run_election_new_upsert_validator(args, planet):
}
]
return create_new_election(args.sk, planet, ValidatorElection, new_validator)
return create_new_election(args.sk, planet, ValidatorElection, new_validator, abci_rpc)
def run_election_new_chain_migration(args, planet):
def run_election_new_chain_migration(args, planet, abci_rpc):
"""Initiates an election to halt block production
:param args: dict
@ -186,10 +186,10 @@ def run_election_new_chain_migration(args, planet):
:return: election_id or `False` in case of failure
"""
return create_new_election(args.sk, planet, ChainMigrationElection, [{"data": {}}])
return create_new_election(args.sk, planet, ChainMigrationElection, [{"data": {}}], abci_rpc)
def run_election_approve(args, validator: Validator):
def run_election_approve(args, validator: Validator, abci_rpc):
"""Approve an election
:param args: dict
@ -216,8 +216,8 @@ def run_election_approve(args, validator: Validator):
approval = Vote.generate(inputs, [([election_pub_key], voting_power)], [tx.id]).sign([key.private_key])
validator.validate_transaction(approval)
resp = ABCI_RPC().write_transaction(
MODE_LIST, ABCI_RPC().tendermint_rpc_endpoint, MODE_COMMIT, approval, BROADCAST_TX_COMMIT
resp = abci_rpc.write_transaction(
MODE_LIST, abci_rpc.tendermint_rpc_endpoint, MODE_COMMIT, approval, BROADCAST_TX_COMMIT
)
if resp == (202, ""):

View File

@ -19,6 +19,7 @@ from planetmint.config import Config
from planetmint.commands.planetmint import run_election_show
from planetmint.commands.planetmint import run_election_new_chain_migration
from planetmint.commands.planetmint import run_election_approve
from planetmint.commands.planetmint import run_election_new_upsert_validator
from planetmint.backend.connection import Connection
@ -311,9 +312,7 @@ class MockResponse:
@pytest.mark.abci
def test_election_new_upsert_validator_with_tendermint(b, priv_validator_path, user_sk, validators):
from planetmint.commands.planetmint import run_election_new_upsert_validator
def test_election_new_upsert_validator_with_tendermint(b, priv_validator_path, user_sk, validators, test_abci_rpc):
new_args = Namespace(
action="new",
election_type="upsert-validator",
@ -324,23 +323,19 @@ def test_election_new_upsert_validator_with_tendermint(b, priv_validator_path, u
config={},
)
election_id = run_election_new_upsert_validator(new_args, b)
election_id = run_election_new_upsert_validator(new_args, b, test_abci_rpc)
assert b.models.get_transaction(election_id)
@pytest.mark.bdb
def test_election_new_upsert_validator_without_tendermint(caplog, b, priv_validator_path, user_sk):
from planetmint.commands.planetmint import run_election_new_upsert_validator
# from planetmint.abci.rpc import write_transaction
def test_election_new_upsert_validator_without_tendermint(caplog, b, priv_validator_path, user_sk, test_abci_rpc):
def mock_write(modelist, endpoint, mode_commit, transaction, mode):
b.models.store_bulk_transactions([transaction])
return (202, "")
b.models.get_validators = mock_get_validators
ABCI_RPC().write_transaction = mock_write
test_abci_rpc.write_transaction = mock_write
args = Namespace(
action="new",
@ -353,41 +348,39 @@ def test_election_new_upsert_validator_without_tendermint(caplog, b, priv_valida
)
with caplog.at_level(logging.INFO):
election_id = run_election_new_upsert_validator(args, b)
assert caplog.records[1].msg == "[SUCCESS] Submitted proposal with id: " + election_id
election_id = run_election_new_upsert_validator(args, b, test_abci_rpc)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id
assert b.models.get_transaction(election_id)
@pytest.mark.abci
def test_election_new_chain_migration_with_tendermint(b, priv_validator_path, user_sk, validators):
def test_election_new_chain_migration_with_tendermint(b, priv_validator_path, user_sk, validators, test_abci_rpc):
new_args = Namespace(action="new", election_type="migration", sk=priv_validator_path, config={})
election_id = run_election_new_chain_migration(new_args, b)
election_id = run_election_new_chain_migration(new_args, b, test_abci_rpc)
assert b.models.get_transaction(election_id)
@pytest.mark.bdb
def test_election_new_chain_migration_without_tendermint(caplog, b, priv_validator_path, user_sk):
def test_election_new_chain_migration_without_tendermint(caplog, b, priv_validator_path, user_sk, test_abci_rpc):
def mock_write(modelist, endpoint, mode_commit, transaction, mode):
b.models.store_bulk_transactions([transaction])
return (202, "")
b.models.get_validators = mock_get_validators
ABCI_RPC().write_transaction = mock_write
test_abci_rpc.write_transaction = mock_write
args = Namespace(action="new", election_type="migration", sk=priv_validator_path, config={})
with caplog.at_level(logging.INFO):
election_id = run_election_new_chain_migration(args, b)
election_id = run_election_new_chain_migration(args, b, test_abci_rpc)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id
assert b.models.get_transaction(election_id)
@pytest.mark.bdb
def test_election_new_upsert_validator_invalid_election(caplog, b, priv_validator_path, user_sk):
from planetmint.commands.planetmint import run_election_new_upsert_validator
def test_election_new_upsert_validator_invalid_election(caplog, b, priv_validator_path, user_sk, test_abci_rpc):
args = Namespace(
action="new",
election_type="upsert-validator",
@ -399,20 +392,19 @@ def test_election_new_upsert_validator_invalid_election(caplog, b, priv_validato
)
with caplog.at_level(logging.ERROR):
assert not run_election_new_upsert_validator(args, b)
assert not run_election_new_upsert_validator(args, b, test_abci_rpc)
assert caplog.records[0].msg.__class__ == FileNotFoundError
@pytest.mark.bdb
def test_election_new_upsert_validator_invalid_power(caplog, b, priv_validator_path, user_sk):
from planetmint.commands.planetmint import run_election_new_upsert_validator
def test_election_new_upsert_validator_invalid_power(caplog, b, priv_validator_path, user_sk, test_abci_rpc):
from transactions.common.exceptions import InvalidPowerChange
def mock_write(modelist, endpoint, mode_commit, transaction, mode):
b.models.store_bulk_transactions([transaction])
return (400, "")
ABCI_RPC().write_transaction = mock_write
test_abci_rpc.write_transaction = mock_write
b.models.get_validators = mock_get_validators
args = Namespace(
action="new",
@ -425,14 +417,12 @@ def test_election_new_upsert_validator_invalid_power(caplog, b, priv_validator_p
)
with caplog.at_level(logging.ERROR):
assert not run_election_new_upsert_validator(args, b)
assert not run_election_new_upsert_validator(args, b, test_abci_rpc)
assert caplog.records[0].msg.__class__ == InvalidPowerChange
@pytest.mark.abci
def test_election_approve_with_tendermint(b, priv_validator_path, user_sk, validators):
from planetmint.commands.planetmint import run_election_new_upsert_validator
def test_election_approve_with_tendermint(b, priv_validator_path, user_sk, validators, test_abci_rpc):
public_key = "CJxdItf4lz2PwEf4SmYNAu/c/VpmX39JEgC5YpH7fxg="
new_args = Namespace(
action="new",
@ -444,65 +434,63 @@ def test_election_approve_with_tendermint(b, priv_validator_path, user_sk, valid
config={},
)
election_id = run_election_new_upsert_validator(new_args, b)
election_id = run_election_new_upsert_validator(new_args, b, test_abci_rpc)
assert election_id
args = Namespace(action="approve", election_id=election_id, sk=priv_validator_path, config={})
approve = run_election_approve(args, b)
approve = run_election_approve(args, b, test_abci_rpc)
assert b.models.get_transaction(approve)
@pytest.mark.bdb
def test_election_approve_without_tendermint(caplog, b, priv_validator_path, new_validator, node_key):
def test_election_approve_without_tendermint(caplog, b, priv_validator_path, new_validator, node_key, test_abci_rpc):
from planetmint.commands.planetmint import run_election_approve
from argparse import Namespace
b, election_id = call_election(b, new_validator, node_key)
b, election_id = call_election(b, new_validator, node_key, test_abci_rpc)
# call run_election_approve with args that point to the election
args = Namespace(action="approve", election_id=election_id, sk=priv_validator_path, config={})
# assert returned id is in the db
with caplog.at_level(logging.INFO):
approval_id = run_election_approve(args, b)
approval_id = run_election_approve(args, b, test_abci_rpc)
assert caplog.records[0].msg == "[SUCCESS] Your vote has been submitted"
assert b.models.get_transaction(approval_id)
@pytest.mark.bdb
def test_election_approve_failure(caplog, b, priv_validator_path, new_validator, node_key):
from planetmint.commands.planetmint import run_election_approve
def test_election_approve_failure(caplog, b, priv_validator_path, new_validator, node_key, test_abci_rpc):
from argparse import Namespace
b, election_id = call_election(b, new_validator, node_key)
b, election_id = call_election(b, new_validator, node_key, test_abci_rpc)
def mock_write(modelist, endpoint, mode_commit, transaction, mode):
b.models.store_bulk_transactions([transaction])
return (400, "")
ABCI_RPC().write_transaction = mock_write
test_abci_rpc.write_transaction = mock_write
# call run_upsert_validator_approve with args that point to the election
args = Namespace(action="approve", election_id=election_id, sk=priv_validator_path, config={})
with caplog.at_level(logging.ERROR):
assert not run_election_approve(args, b)
assert not run_election_approve(args, b, test_abci_rpc)
assert caplog.records[0].msg == "Failed to commit vote"
@pytest.mark.bdb
def test_election_approve_called_with_bad_key(caplog, b, bad_validator_path, new_validator, node_key):
from planetmint.commands.planetmint import run_election_approve
def test_election_approve_called_with_bad_key(caplog, b, bad_validator_path, new_validator, node_key, test_abci_rpc):
from argparse import Namespace
b, election_id = call_election(b, new_validator, node_key)
b, election_id = call_election(b, new_validator, node_key, test_abci_rpc)
# call run_upsert_validator_approve with args that point to the election, but a bad signing key
args = Namespace(action="approve", election_id=election_id, sk=bad_validator_path, config={})
with caplog.at_level(logging.ERROR):
assert not run_election_approve(args, b)
assert not run_election_approve(args, b, test_abci_rpc)
assert (
caplog.records[0].msg == "The key you provided does not match any of "
"the eligible voters in this election."
@ -599,14 +587,14 @@ def mock_get_validators(height):
]
def call_election(b, new_validator, node_key):
def call_election(b, new_validator, node_key, abci_rpc):
def mock_write(modelist, endpoint, mode_commit, transaction, mode):
b.models.store_bulk_transactions([transaction])
return (202, "")
# patch the validator set. We now have one validator with power 10
b.models.get_validators = mock_get_validators
ABCI_RPC().write_transaction = mock_write
abci_rpc.write_transaction = mock_write
# our voters is a list of length 1, populated from our mocked validator
voters = b.get_recipients_list()

View File

@ -21,7 +21,6 @@ from collections import namedtuple
from logging import getLogger
from logging.config import dictConfig
from planetmint.abci.rpc import ABCI_RPC
from planetmint.backend.connection import Connection
from planetmint.backend.tarantool.connection import TarantoolDBConnection
from transactions.common import crypto

View File

@ -14,7 +14,6 @@ from abci.server import ProtocolHandler
from abci.utils import read_messages
from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT, BROADCAST_TX_SYNC
from planetmint.abci.rpc import ABCI_RPC
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
from planetmint.version import __tm_supported_versions__
from io import BytesIO

View File

@ -21,7 +21,6 @@ from planetmint.abci.block import Block
from ipld import marshal, multihash
from uuid import uuid4
from planetmint.abci.rpc import ABCI_RPC
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
from tests.utils import delete_unspent_outputs, get_utxoset_merkle_root, store_unspent_outputs, update_utxoset

View File

@ -6,7 +6,7 @@
import pytest
import codecs
from planetmint.abci.rpc import ABCI_RPC, MODE_LIST, MODE_COMMIT
from planetmint.abci.rpc import MODE_LIST, MODE_COMMIT
from planetmint.abci.tendermint_utils import public_key_to_base64
from transactions.types.elections.validator_election import ValidatorElection

View File

@ -12,7 +12,6 @@ import random
from functools import singledispatch
from planetmint import backend
from planetmint.abci.rpc import ABCI_RPC
from planetmint.backend.localmongodb.connection import LocalMongoDBConnection
from planetmint.backend.tarantool.connection import TarantoolDBConnection
from planetmint.backend.schema import TABLES