nucypher/tests/cli/test_felix.py

140 lines
4.9 KiB
Python
Raw Normal View History

2019-03-05 20:08:42 +00:00
import os
import pytest_twisted
from twisted.internet import threads
2019-03-21 22:51:51 +00:00
from twisted.internet.task import Clock
2019-03-05 20:08:42 +00:00
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
from nucypher.blockchain.eth.registry import BaseContractRegistry, LocalContractRegistry
2019-03-21 22:51:51 +00:00
from nucypher.blockchain.eth.token import NU
from nucypher.characters.chaotic import Felix
2019-03-05 20:08:42 +00:00
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import FelixConfiguration
from nucypher.utilities.sandbox.constants import (
TEMPORARY_DOMAIN,
TEST_PROVIDER_URI,
INSECURE_DEVELOPMENT_PASSWORD,
MOCK_CUSTOM_INSTALLATION_PATH_2
)
@pytest_twisted.inlineCallbacks
def test_run_felix(click_runner,
testerchain,
test_registry,
agency,
deploy_user_input,
mock_primary_registry_filepath):
2019-03-21 22:51:51 +00:00
clock = Clock()
Felix._CLOCK = clock
Felix.DISTRIBUTION_INTERVAL = 5 # seconds
Felix.DISBURSEMENT_INTERVAL = 0.01 # hours
2019-03-21 22:51:51 +00:00
Felix.STAGING_DELAY = 2 # seconds
2019-03-05 20:08:42 +00:00
# Main thread (Flask)
os.environ['NUCYPHER_FELIX_DB_SECRET'] = INSECURE_DEVELOPMENT_PASSWORD
# Mock live contract registry reads
LocalContractRegistry.read = lambda *a, **kw: test_registry.read()
# Test subproc (Click)
envvars = {'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD,
'NUCYPHER_FELIX_DB_SECRET': INSECURE_DEVELOPMENT_PASSWORD,
'FLASK_DEBUG': '1'}
# Felix creates a system configuration
init_args = ('felix', 'init',
'--debug',
'--registry-filepath', mock_primary_registry_filepath,
'--checksum-address', testerchain.client.accounts[0],
'--config-root', MOCK_CUSTOM_INSTALLATION_PATH_2,
'--network', TEMPORARY_DOMAIN,
'--provider', TEST_PROVIDER_URI)
2019-03-05 20:08:42 +00:00
result = click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False, env=envvars)
2019-03-05 20:08:42 +00:00
assert result.exit_code == 0
configuration_file_location = os.path.join(MOCK_CUSTOM_INSTALLATION_PATH_2, FelixConfiguration.generate_filename())
2019-03-05 20:08:42 +00:00
# Felix Creates a Database
db_args = ('felix', 'createdb',
'--debug',
'--config-file', configuration_file_location,
'--provider', TEST_PROVIDER_URI)
result = click_runner.invoke(nucypher_cli, db_args, catch_exceptions=False, env=envvars)
assert result.exit_code == 0
# Felix Runs Web Services
2019-03-05 20:08:42 +00:00
def run_felix():
args = ('felix', 'run',
'--debug',
2019-03-05 20:08:42 +00:00
'--config-file', configuration_file_location,
'--provider', TEST_PROVIDER_URI,
'--dry-run')
2019-03-05 20:08:42 +00:00
run_result = click_runner.invoke(nucypher_cli, args, catch_exceptions=False, env=envvars)
assert run_result.exit_code == 0
return run_result
2019-03-05 20:08:42 +00:00
# A (mocked) client requests Felix's services
def request_felix_landing_page(_result):
2019-03-05 20:08:42 +00:00
# Init an equal Felix to the already running one.
felix_config = FelixConfiguration.from_configuration_file(filepath=configuration_file_location,
registry_filepath=mock_primary_registry_filepath)
felix_config.attach_keyring()
2019-03-05 20:08:42 +00:00
felix_config.keyring.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
felix = felix_config.produce()
# Make a flask app
web_app = felix.make_web_app()
test_client = web_app.test_client()
# Load the landing page
2019-03-05 20:08:42 +00:00
response = test_client.get('/')
assert response.status_code == 200
# Register a new recipient
response = test_client.post('/register', data={'address': testerchain.client.accounts[-1]})
assert response.status_code == 200
2019-03-05 20:08:42 +00:00
return
2019-03-21 22:51:51 +00:00
def time_travel(_result):
clock.advance(amount=60)
# Record starting ether balance
recipient = testerchain.client.accounts[-1]
staker = Staker(checksum_address=recipient,
registry=test_registry,
is_me=True)
original_eth_balance = staker.eth_balance
# Run the callbacks
2019-03-05 20:08:42 +00:00
d = threads.deferToThread(run_felix)
d.addCallback(request_felix_landing_page)
2019-03-21 22:51:51 +00:00
d.addCallback(time_travel)
2019-03-05 20:08:42 +00:00
yield d
2019-03-21 22:51:51 +00:00
def confirm_airdrop(_results):
recipient = testerchain.client.accounts[-1]
staker = Staker(checksum_address=recipient,
registry=test_registry,
is_me=True)
2019-03-21 22:51:51 +00:00
2019-08-21 10:59:52 +00:00
assert staker.token_balance == NU(45000, 'NU')
2019-03-21 22:51:51 +00:00
# TODO: Airdrop Testnet Ethers?
2019-09-03 18:45:52 +00:00
new_eth_balance = original_eth_balance + testerchain.w3.fromWei(Felix.ETHER_AIRDROP_AMOUNT, 'ether')
assert staker.eth_balance == new_eth_balance
2019-03-21 22:51:51 +00:00
staged_airdrops = Felix._AIRDROP_QUEUE
next_airdrop = staged_airdrops[0]
next_airdrop.addCallback(confirm_airdrop)
yield next_airdrop