mirror of https://github.com/nucypher/nucypher.git
243 lines
9.6 KiB
Python
243 lines
9.6 KiB
Python
"""
|
|
This file is part of nucypher.
|
|
|
|
nucypher is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
nucypher is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import click
|
|
import pytest
|
|
|
|
from nucypher.blockchain.eth.clients import EthereumTesterClient, PUBLIC_CHAINS
|
|
from nucypher.blockchain.eth.token import NU
|
|
from nucypher.cli.actions.confirm import (confirm_deployment, confirm_enable_restaking, confirm_enable_restaking_lock,
|
|
confirm_enable_winding_down, confirm_large_stake, confirm_staged_stake)
|
|
from nucypher.cli.literature import (ABORT_DEPLOYMENT, RESTAKING_AGREEMENT, RESTAKING_LOCK_AGREEMENT,
|
|
WINDING_DOWN_AGREEMENT, CONFIRM_STAGED_STAKE,
|
|
CONFIRM_LARGE_STAKE_VALUE, CONFIRM_LARGE_STAKE_DURATION)
|
|
|
|
from tests.constants import YES, NO
|
|
|
|
|
|
def test_confirm_deployment_cli_action(mocker, mock_stdin, test_emitter, capsys, mock_testerchain):
|
|
mock_stdin.line('foo') # anything different from `deployer_interface.client.chain_name.upper()`
|
|
with pytest.raises(click.Abort):
|
|
confirm_deployment(emitter=test_emitter, deployer_interface=mock_testerchain)
|
|
captured = capsys.readouterr()
|
|
assert ABORT_DEPLOYMENT in captured.out
|
|
assert mock_stdin.empty()
|
|
|
|
mock_stdin.line('DEPLOY') # say the magic word
|
|
result = confirm_deployment(emitter=test_emitter, deployer_interface=mock_testerchain)
|
|
assert result
|
|
captured = capsys.readouterr()
|
|
assert "Type 'DEPLOY' to continue: " in captured.out
|
|
assert mock_stdin.empty()
|
|
|
|
# Mimick a known chain name
|
|
llamanet, llamanet_chain_id = 'llamanet', 1123589012901209
|
|
mocker.patch.dict(PUBLIC_CHAINS, {'llamanet': llamanet_chain_id})
|
|
|
|
mocker.patch.object(EthereumTesterClient,
|
|
'chain_id',
|
|
return_value=llamanet_chain_id,
|
|
new_callable=mocker.PropertyMock)
|
|
|
|
mocker.patch.object(EthereumTesterClient,
|
|
'chain_name',
|
|
return_value=llamanet,
|
|
new_callable=mocker.PropertyMock)
|
|
mock_testerchain.client.is_local = False
|
|
|
|
mock_stdin.line('DEPLOY') # say the (wrong) magic word
|
|
with pytest.raises(click.Abort):
|
|
confirm_deployment(emitter=test_emitter, deployer_interface=mock_testerchain)
|
|
assert mock_stdin.empty()
|
|
captured = capsys.readouterr()
|
|
assert f"Type '{llamanet.upper()}' to continue: " in captured.out
|
|
assert ABORT_DEPLOYMENT in captured.out
|
|
|
|
mock_stdin.line(llamanet) # say the (almost correct) magic word
|
|
with pytest.raises(click.Abort):
|
|
confirm_deployment(emitter=test_emitter, deployer_interface=mock_testerchain)
|
|
assert mock_stdin.empty()
|
|
captured = capsys.readouterr()
|
|
assert f"Type '{llamanet.upper()}' to continue: " in captured.out
|
|
assert ABORT_DEPLOYMENT in captured.out
|
|
|
|
mock_stdin.line(llamanet.upper()) # say the (correct, uppercase) network name
|
|
result = confirm_deployment(emitter=test_emitter, deployer_interface=mock_testerchain)
|
|
assert result
|
|
assert mock_stdin.empty()
|
|
captured = capsys.readouterr()
|
|
assert f"Type '{llamanet.upper()}' to continue: " in captured.out
|
|
|
|
|
|
def test_confirm_enable_restaking_lock_cli_action(mock_stdin, test_emitter, capsys):
|
|
|
|
# Test data
|
|
staking_address, release_period = '0xdeadbeef', 1
|
|
|
|
# Positive Case
|
|
mock_stdin.line(YES)
|
|
result = confirm_enable_restaking_lock(emitter=test_emitter,
|
|
release_period=release_period,
|
|
staking_address=staking_address)
|
|
assert result
|
|
captured = capsys.readouterr()
|
|
assert mock_stdin.empty()
|
|
restake_agreement = RESTAKING_LOCK_AGREEMENT.format(staking_address=staking_address, release_period=release_period)
|
|
assert restake_agreement in captured.out
|
|
|
|
# Negative case
|
|
mock_stdin.line(NO)
|
|
|
|
with pytest.raises(click.Abort):
|
|
confirm_enable_restaking_lock(emitter=test_emitter,
|
|
release_period=release_period,
|
|
staking_address=staking_address)
|
|
captured = capsys.readouterr()
|
|
assert mock_stdin.empty()
|
|
restake_agreement = RESTAKING_LOCK_AGREEMENT.format(staking_address=staking_address,
|
|
release_period=release_period)
|
|
assert restake_agreement in captured.out
|
|
|
|
|
|
def test_confirm_enable_restaking_cli_action(test_emitter, mock_stdin, capsys):
|
|
|
|
# Positive Case
|
|
mock_stdin.line(YES)
|
|
staking_address = '0xdeadbeef'
|
|
result = confirm_enable_restaking(emitter=test_emitter, staking_address=staking_address)
|
|
assert result
|
|
assert mock_stdin.empty()
|
|
|
|
captured = capsys.readouterr()
|
|
restake_agreement = RESTAKING_AGREEMENT.format(staking_address=staking_address)
|
|
assert restake_agreement in captured.out
|
|
|
|
# Negative case
|
|
mock_stdin.line(NO)
|
|
|
|
with pytest.raises(click.Abort):
|
|
confirm_enable_restaking(emitter=test_emitter, staking_address=staking_address)
|
|
captured = capsys.readouterr()
|
|
assert mock_stdin.empty()
|
|
|
|
restake_agreement = RESTAKING_AGREEMENT.format(staking_address=staking_address)
|
|
assert restake_agreement in captured.out
|
|
|
|
|
|
def test_confirm_enable_winding_down_cli_action(test_emitter, mock_stdin, capsys):
|
|
|
|
# Positive Case
|
|
mock_stdin.line(YES)
|
|
staking_address = '0xdeadbeef'
|
|
result = confirm_enable_winding_down(emitter=test_emitter, staking_address=staking_address)
|
|
assert result
|
|
assert mock_stdin.empty()
|
|
|
|
captured = capsys.readouterr()
|
|
assert WINDING_DOWN_AGREEMENT in captured.out
|
|
|
|
# Negative case
|
|
mock_stdin.line(NO)
|
|
|
|
with pytest.raises(click.Abort):
|
|
confirm_enable_winding_down(emitter=test_emitter, staking_address=staking_address)
|
|
captured = capsys.readouterr()
|
|
assert mock_stdin.empty()
|
|
assert WINDING_DOWN_AGREEMENT in captured.out
|
|
|
|
|
|
def test_confirm_staged_stake_cli_action(test_emitter, mock_stdin, capsys):
|
|
|
|
staking_address, value, lock_periods = '0xdeadbeef', NU.from_tokens(1), 1
|
|
confirmation = CONFIRM_STAGED_STAKE.format(staker_address=staking_address,
|
|
lock_periods=lock_periods,
|
|
tokens=value,
|
|
nunits=value.to_nunits())
|
|
|
|
# Positive Case
|
|
mock_stdin.line(YES)
|
|
|
|
result = confirm_staged_stake(staker_address=staking_address,
|
|
value=value,
|
|
lock_periods=lock_periods)
|
|
assert result
|
|
assert mock_stdin.empty()
|
|
|
|
captured = capsys.readouterr()
|
|
assert confirmation in captured.out
|
|
|
|
# Negative case
|
|
mock_stdin.line(NO)
|
|
|
|
with pytest.raises(click.Abort):
|
|
confirm_staged_stake(staker_address=staking_address,
|
|
value=value,
|
|
lock_periods=lock_periods)
|
|
|
|
captured = capsys.readouterr()
|
|
assert confirmation in captured.out
|
|
assert mock_stdin.empty()
|
|
|
|
|
|
@pytest.mark.parametrize('value,duration,must_confirm_value,must_confirm_duration', (
|
|
(NU.from_tokens(1), 1, False, False),
|
|
(NU.from_tokens(1), 31, False, False),
|
|
(NU.from_tokens(15), 31, False, False),
|
|
(NU.from_tokens(150001), 31, True, False),
|
|
(NU.from_tokens(150000), 366, False, True),
|
|
(NU.from_tokens(150001), 366, True, True),
|
|
))
|
|
def test_confirm_large_stake_cli_action(test_emitter,
|
|
mock_stdin,
|
|
capsys,
|
|
value,
|
|
duration,
|
|
must_confirm_value,
|
|
must_confirm_duration):
|
|
|
|
asked_about_value = lambda output: CONFIRM_LARGE_STAKE_VALUE.format(value=value) in output
|
|
asked_about_duration = lambda output: CONFIRM_LARGE_STAKE_DURATION.format(lock_periods=duration) in output
|
|
|
|
# Positive Cases - either do not need to confirm anything, or say yes
|
|
if must_confirm_value:
|
|
mock_stdin.line(YES)
|
|
if must_confirm_duration:
|
|
mock_stdin.line(YES)
|
|
result = confirm_large_stake(value=value, lock_periods=duration)
|
|
assert result
|
|
captured = capsys.readouterr()
|
|
assert must_confirm_value == asked_about_value(captured.out)
|
|
assert must_confirm_duration == asked_about_duration(captured.out)
|
|
assert mock_stdin.empty()
|
|
|
|
if must_confirm_value or must_confirm_duration:
|
|
# Negative cases - must confirm something and say no
|
|
if must_confirm_value and must_confirm_duration:
|
|
# yes to the former but not to the latter
|
|
mock_stdin.line(YES)
|
|
mock_stdin.line(NO)
|
|
else:
|
|
# no to whatever one we are asked about
|
|
mock_stdin.line(NO)
|
|
|
|
with pytest.raises(click.Abort):
|
|
confirm_large_stake(value=value, lock_periods=duration)
|
|
captured = capsys.readouterr()
|
|
assert must_confirm_value == asked_about_value(captured.out)
|
|
assert must_confirm_duration == asked_about_duration(captured.out)
|
|
assert mock_stdin.empty()
|