Cleanup and parameterize fixtures for FT coverage; Introduces test configuration factory functions for pyetst fixtures.

pull/1989/head
Kieran Prasch 2020-05-17 10:23:49 -07:00
parent 4a5aed06a1
commit 44de13d149
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
15 changed files with 240 additions and 263 deletions

View File

@ -21,7 +21,7 @@ import json
import click
from json.decoder import JSONDecodeError
from typing import Type
from typing import Optional, Type
from nucypher.characters.control.emitters import StdoutEmitter
from nucypher.cli.actions.confirm import confirm_destroy_configuration
@ -44,23 +44,31 @@ def forget(emitter: StdoutEmitter, configuration: CharacterConfiguration) -> Non
emitter.message(SUCCESSFUL_FORGET_NODES, color='red')
def update_configuration(emitter: StdoutEmitter,
config_class: Type[CharacterConfiguration],
filepath: str,
updates: dict) -> None:
def get_or_update_configuration(emitter: StdoutEmitter,
filepath: str,
config_class: Type[CharacterConfiguration],
updates: Optional[dict] = None) -> None:
"""
Utility for writing updates to an existing configuration file then displaying the result.
If the config file is invalid, trey very hard to display the problem.
If the config file is invalid, trey very hard to display the problem. If there are no updates,
the config file will be displayed without changes.
"""
try:
config = config_class.from_configuration_file(filepath=filepath)
except FileNotFoundError:
return handle_invalid_configuration_file(emitter=emitter,
config_class=config_class,
filepath=filepath)
except config_class.ConfigurationError:
return handle_invalid_configuration_file(emitter=emitter,
config_class=config_class,
filepath=filepath)
pretty_fields = ', '.join(updates)
emitter.message(SUCCESSFUL_UPDATE_CONFIGURATION_VALUES.format(fields=pretty_fields), color='yellow')
config.update(**updates)
emitter.echo(f"{config_class.NAME.capitalize()} Configuration {filepath} \n {'='*55}")
if updates:
pretty_fields = ', '.join(updates)
emitter.message(SUCCESSFUL_UPDATE_CONFIGURATION_VALUES.format(fields=pretty_fields), color='yellow')
config.update(**updates)
emitter.echo(config.serialize())

View File

@ -25,9 +25,9 @@ from nucypher.characters.control.interfaces import AliceInterface
from nucypher.cli.actions.auth import get_client_password, get_nucypher_password
from nucypher.cli.actions.config import (
destroy_configuration,
handle_missing_configuration_file, update_configuration
handle_missing_configuration_file, get_or_update_configuration
)
from nucypher.cli.actions.select import select_client_account
from nucypher.cli.actions.select import select_client_account, select_config_file
from nucypher.cli.commands.deploy import option_gas_strategy
from nucypher.cli.config import group_general_config
from nucypher.cli.options import (
@ -328,14 +328,15 @@ def init(general_config, full_config_options, config_root):
def config(general_config, config_file, full_config_options):
"""View and optionally update existing Alice's configuration."""
emitter = setup_emitter(general_config)
configuration_file_location = config_file or AliceConfiguration.default_filepath()
emitter.echo(f"Alice Configuration {configuration_file_location} \n {'='*55}")
if not config_file:
config_file = select_config_file(emitter=emitter,
checksum_address=full_config_options.pay_with,
config_class=AliceConfiguration)
updates = full_config_options.get_updates()
if updates:
update_configuration(emitter=emitter,
config_class=AliceConfiguration,
filepath=configuration_file_location,
updates=updates)
get_or_update_configuration(emitter=emitter,
config_class=AliceConfiguration,
filepath=config_file,
updates=updates)
@alice.command()

View File

@ -5,10 +5,10 @@ from nucypher.characters.control.interfaces import BobInterface
from nucypher.cli.actions.auth import get_nucypher_password
from nucypher.cli.actions.config import (
destroy_configuration,
update_configuration,
get_or_update_configuration,
handle_missing_configuration_file
)
from nucypher.cli.actions.select import select_client_account
from nucypher.cli.actions.select import select_client_account, select_config_file
from nucypher.cli.commands.deploy import option_gas_strategy
from nucypher.cli.config import group_general_config
from nucypher.cli.options import (
@ -224,15 +224,15 @@ def run(general_config, character_options, config_file, controller_port, dry_run
def config(general_config, config_options, config_file):
"""View and optionally update existing Bob's configuration."""
emitter = setup_emitter(general_config)
bob_config = config_options.create_config(emitter, config_file)
filepath = config_file or bob_config.config_file_location
emitter.echo(f"Bob Configuration {filepath} \n {'='*55}")
if not config_file:
config_file = select_config_file(emitter=emitter,
checksum_address=config_options.checksum_address,
config_class=BobConfiguration)
updates = config_options.get_updates()
if updates:
update_configuration(emitter=emitter,
config_class=BobConfiguration,
filepath=filepath,
updates=updates)
get_or_update_configuration(emitter=emitter,
config_class=BobConfiguration,
filepath=config_file,
updates=updates)
@bob.command()

View File

@ -28,7 +28,7 @@ from nucypher.blockchain.eth.signers import ClefSigner
from nucypher.blockchain.eth.token import NU, StakeList
from nucypher.blockchain.eth.utils import datetime_at_period
from nucypher.cli.actions.auth import get_client_password
from nucypher.cli.actions.config import update_configuration, handle_missing_configuration_file
from nucypher.cli.actions.config import get_or_update_configuration, handle_missing_configuration_file
from nucypher.cli.actions.confirm import (
confirm_enable_restaking,
confirm_enable_restaking_lock,
@ -304,13 +304,11 @@ def config(general_config, config_file, config_options):
"""View and optionally update existing StakeHolder's configuration."""
emitter = setup_emitter(general_config)
configuration_file_location = config_file or StakeHolderConfiguration.default_filepath()
emitter.echo(f"StakeHolder Configuration {configuration_file_location} \n {'='*55}")
updates = config_options.get_updates()
if updates:
update_configuration(emitter=emitter,
config_class=StakeHolderConfiguration,
filepath=configuration_file_location,
updates=updates)
get_or_update_configuration(emitter=emitter,
config_class=StakeHolderConfiguration,
filepath=configuration_file_location,
updates=updates)
@stake.command('list')

View File

@ -27,7 +27,7 @@ from nucypher.blockchain.eth.utils import datetime_at_period
from nucypher.cli.actions.auth import get_client_password, get_nucypher_password
from nucypher.cli.actions.config import (
destroy_configuration,
handle_missing_configuration_file
handle_missing_configuration_file, get_or_update_configuration
)
from nucypher.cli.actions.select import select_client_account, select_config_file, select_network
from nucypher.cli.commands.deploy import option_gas_strategy
@ -401,10 +401,11 @@ def config(general_config, config_options, config_file):
checksum_address=config_options.worker_address,
config_class=UrsulaConfiguration)
emitter.echo(f"Ursula Configuration {config_file} \n {'='*55}")
updates = config_options.get_updates()
get_or_update_configuration(emitter=emitter,
config_class=UrsulaConfiguration,
filepath=config_file,
config_options=config_options)
updates=updates)
@ursula.command(name='commit-next')

View File

@ -2,12 +2,13 @@ import click
import pytest
from pathlib import Path
from nucypher.cli.actions import config as config_actions
from nucypher.cli.actions.config import (
destroy_configuration,
forget,
handle_invalid_configuration_file,
handle_missing_configuration_file,
update_configuration
get_or_update_configuration
)
from nucypher.cli.literature import MISSING_CONFIGURATION_FILE, SUCCESSFUL_DESTRUCTION
from nucypher.config.characters import UrsulaConfiguration
@ -30,54 +31,81 @@ def test_forget(alice_blockchain_test_config,
mock_click_confirm):
mock_click_confirm.return_value = YES
forget(emitter=test_emitter, configuration=alice_blockchain_test_config)
# TODO: Finish me
def test_update_configuration(alice_blockchain_test_config,
CONFIGS = [
'alice_blockchain_test_config',
'bob_blockchain_test_config',
'ursula_decentralized_test_config',
]
@pytest.fixture(scope='function', params=CONFIGS)
def config(request, mocker):
# Setup
config = request.getfixturevalue(request.param)
config_class = config.__class__
config_file = config.filepath
# Test Data
raw_payload = config.serialize()
JSON_payload = config.deserialize(payload=raw_payload)
# Isolate from filesystem
mocker.patch('__main__.open', return_value=raw_payload)
# Mock configuration disk I/O
mocker.patch.object(config_class, '_read_configuration_file', return_value=JSON_payload)
mocker.patch.object(config_class, '_write_configuration_file', return_value=config_file)
# Spy on the code path
mocker.spy(config_class, 'update')
mocker.spy(config_actions, 'handle_invalid_configuration_file')
mocker.spy(config_actions, 'handle_missing_configuration_file')
return config
def test_update_configuration(config,
test_emitter,
stdout_trap,
mocker,
test_registry_source_manager):
# Setup
config_class = alice_blockchain_test_config.__class__
config_file = alice_blockchain_test_config.filepath
# Test Data
raw_payload = alice_blockchain_test_config.serialize()
JSON_payload = alice_blockchain_test_config.deserialize(payload=raw_payload)
# Isolate from filesystem and Spy on the methods we're testing here
mocker.patch('__main__.open', return_value=raw_payload)
mocker.patch.object(config_class, '_read_configuration_file', return_value=JSON_payload)
ghostwriter = mocker.patch.object(config_class, '_write_configuration_file', return_value=config_file)
spy_update = mocker.spy(config_class, 'update')
config_class = config.__class__
config_file = config.filepath
# Test
updates = dict(federated_only=True)
assert not alice_blockchain_test_config.federated_only
update_configuration(emitter=test_emitter,
config_class=config_class,
filepath=config_file,
updates=updates)
assert not config.federated_only
get_or_update_configuration(emitter=test_emitter,
config_class=config_class,
filepath=config_file,
updates=updates)
# The stand-in configuration is untouched...
assert not alice_blockchain_test_config.federated_only
assert not config.federated_only
# ... but updates were passed aloing to the config file system writing handlers
ghostwriter.assert_called_once_with(filepath=alice_blockchain_test_config.filepath, override=True)
assert spy_update.call_args.kwargs == updates
# ... but updates were passed along to the config file system writing handlers
config._write_configuration_file.assert_called_once_with(filepath=config.filepath, override=True)
assert config.update.call_args.kwargs == updates
# Ensure only the affirmative path was followed
config_actions.handle_invalid_configuration_file.assert_not_called()
config_actions.handle_missing_configuration_file.assert_not_called()
def test_destroy_configuration(alice_blockchain_test_config,
def test_destroy_configuration(config,
test_emitter,
stdout_trap,
mocker,
mock_click_confirm):
# Setup
config = alice_blockchain_test_config
config_class = alice_blockchain_test_config.__class__
config_file = Path(alice_blockchain_test_config.filepath)
config_class = config.__class__
config_file = config.filepath
# Isolate from filesystem and Spy on the methods we're testing here
spy_keyring_attached = mocker.spy(CharacterConfiguration, 'attach_keyring')
@ -86,7 +114,7 @@ def test_destroy_configuration(alice_blockchain_test_config,
# Test
mock_click_confirm.return_value = YES
destroy_configuration(emitter=test_emitter, character_config=alice_blockchain_test_config)
destroy_configuration(emitter=test_emitter, character_config=config)
output = stdout_trap.getvalue()
assert SUCCESSFUL_DESTRUCTION in output
@ -99,11 +127,11 @@ def test_destroy_configuration(alice_blockchain_test_config,
mock_os_remove.assert_called_with(filepath=config.db_filepath)
def test_handle_missing_configuration_file(alice_blockchain_test_config):
def test_handle_missing_configuration_file(config):
# Setup
config_class = alice_blockchain_test_config.__class__
config_file = Path(alice_blockchain_test_config.filepath)
config_class = config.__class__
config_file = Path(config.filepath)
# Test Data
init_command = f"{config_class.NAME} init"
@ -119,17 +147,16 @@ def test_handle_missing_configuration_file(alice_blockchain_test_config):
character_config_class=config_class)
@pytest.mark.parametrize('bad_config_payload', BAD_CONFIG_PAYLOADS)
def test_handle_invalid_configuration_file(mocker,
alice_blockchain_test_config,
config,
test_emitter,
stdout_trap,
bad_config_payload):
# Setup
config_class = alice_blockchain_test_config.__class__
config_file = Path(alice_blockchain_test_config.filepath)
config_class = config.__class__
config_file = Path(config.filepath)
# Assume the file exists but is full of garbage
mocker.patch.object(CharacterConfiguration,

View File

@ -31,6 +31,7 @@ from nucypher.blockchain.eth.signers import KeystoreSigner
from nucypher.characters.control.emitters import StdoutEmitter
from nucypher.config.characters import AliceConfiguration, UrsulaConfiguration
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.config.characters import UrsulaConfiguration
from tests.constants import (
KEYFILE_NAME_TEMPLATE,
MOCK_KEYSTORE_PATH,
@ -40,7 +41,12 @@ from tests.constants import (
from tests.fixtures import _make_testerchain, make_token_economics
from tests.mock.agents import FAKE_RECEIPT, MockContractAgency, MockNucypherToken, MockStakingAgent, MockWorkLockAgent
from tests.mock.interfaces import MockBlockchain, make_mock_registry_source_manager
from tests.utils.middleware import MockRestMiddleware
from tests.utils.config import (
make_alice_test_configuration,
make_bob_test_configuration,
make_ursula_test_configuration
)
from tests.utils.ursula import MOCK_URSULA_STARTING_PORT
@pytest.fixture(scope='module')
@ -216,16 +222,31 @@ def patch_keystore(mock_accounts, monkeypatch, mocker):
@pytest.fixture(scope="module")
def alice_blockchain_test_config(mock_account, test_registry):
# TODO: Combine with larger scoped fixture via factory function
config = AliceConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
provider_uri=MOCK_PROVIDER_URI,
checksum_address=mock_account.address,
network_middleware=MockRestMiddleware(),
abort_on_learning_error=True,
save_metadata=False,
reload_metadata=False,
registry=test_registry)
def alice_blockchain_test_config(mock_testerchain, test_registry):
config = make_alice_test_configuration(federated=False,
provider_uri=MOCK_PROVIDER_URI,
test_registry=test_registry,
checksum_address=mock_testerchain.alice_account)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def bob_blockchain_test_config(mock_testerchain, test_registry):
config = make_bob_test_configuration(federated=False,
provider_uri=MOCK_PROVIDER_URI,
test_registry=test_registry,
checksum_address=mock_testerchain.bob_account)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def ursula_decentralized_test_config(mock_testerchain, test_registry):
config = make_ursula_test_configuration(federated=False,
provider_uri=MOCK_PROVIDER_URI,
test_registry=test_registry,
rest_port=MOCK_URSULA_STARTING_PORT,
checksum_address=mock_testerchain.ursula_account(index=0))
yield config
config.cleanup()

View File

@ -6,7 +6,8 @@ from nucypher.cli.literature import SUCCESSFUL_DESTRUCTION
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import AliceConfiguration
from nucypher.config.constants import NUCYPHER_ENVVAR_KEYRING_PASSWORD, TEMPORARY_DOMAIN
from tests.constants import (INSECURE_DEVELOPMENT_PASSWORD, MOCK_CUSTOM_INSTALLATION_PATH, MOCK_IP_ADDRESS)
from tests.constants import (FAKE_PASSWORD_CONFIRMED, INSECURE_DEVELOPMENT_PASSWORD, MOCK_CUSTOM_INSTALLATION_PATH,
MOCK_IP_ADDRESS)
@mock.patch('nucypher.config.characters.AliceConfiguration.default_filepath', return_value='/non/existent/file')
@ -15,7 +16,7 @@ def test_missing_configuration_file(default_filepath_mock, click_runner):
result = click_runner.invoke(nucypher_cli, cmd_args, catch_exceptions=False)
assert result.exit_code != 0
assert default_filepath_mock.called
assert "run: 'nucypher alice init'" in result.output
assert "nucypher alice init" in result.output
def test_initialize_alice_defaults(click_runner, mocker, custom_filepath, monkeypatch):
@ -30,9 +31,7 @@ def test_initialize_alice_defaults(click_runner, mocker, custom_filepath, monkey
'--network', TEMPORARY_DOMAIN,
'--config-root', custom_filepath,
'--federated-only')
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED, catch_exceptions=False)
assert result.exit_code == 0
# REST Host
@ -58,9 +57,7 @@ def test_alice_control_starts_with_mocked_keyring(click_runner, mocker, monkeypa
good_enough_config = AliceConfiguration(dev_mode=True, federated_only=True, keyring=MockKeyring)
mocker.patch.object(AliceConfiguration, "from_configuration_file", return_value=good_enough_config)
init_args = ('alice', 'run', '-x', '--network', TEMPORARY_DOMAIN)
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED)
assert result.exit_code == 0, result.exception
@ -73,8 +70,7 @@ def test_initialize_alice_with_custom_configuration_root(custom_filepath, click_
'--federated-only',
'--config-root', custom_filepath)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD, ip=MOCK_IP_ADDRESS)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED, catch_exceptions=False)
assert result.exit_code == 0
# CLI Output
@ -96,37 +92,24 @@ def test_initialize_alice_with_custom_configuration_root(custom_filepath, click_
def test_alice_control_starts_with_preexisting_configuration(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, AliceConfiguration.generate_filename())
run_args = ('alice', 'run',
'--dry-run',
'--config-file', custom_config_filepath)
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, run_args, input=user_input)
run_args = ('alice', 'run', '--dry-run', '--config-file', custom_config_filepath)
result = click_runner.invoke(nucypher_cli, run_args, input=FAKE_PASSWORD_CONFIRMED)
assert result.exit_code == 0
def test_alice_cannot_init_with_dev_flag(click_runner):
init_args = ('alice', 'init',
'--network', TEMPORARY_DOMAIN,
'--federated-only',
'--dev')
init_args = ('alice', 'init', '--network', TEMPORARY_DOMAIN, '--federated-only', '--dev')
result = click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False)
assert result.exit_code == 2
assert 'Cannot create a persistent development character' in result.output, \
'Missing or invalid error message was produced.'
'Missing or invalid error message was produced.'
def test_alice_derive_policy_pubkey(click_runner):
label = 'random_label'
derive_key_args = ('alice', 'derive-policy-pubkey',
'--label', label,
'--dev')
derive_key_args = ('alice', 'derive-policy-pubkey', '--label', label, '--dev')
result = click_runner.invoke(nucypher_cli, derive_key_args, catch_exceptions=False)
assert result.exit_code == 0
assert "policy_encrypting_key" in result.output
assert "label" in result.output
@ -134,24 +117,16 @@ def test_alice_derive_policy_pubkey(click_runner):
def test_alice_public_keys(click_runner):
derive_key_args = ('alice', 'public-keys',
'--dev')
derive_key_args = ('alice', 'public-keys', '--dev')
result = click_runner.invoke(nucypher_cli, derive_key_args, catch_exceptions=False)
assert result.exit_code == 0
assert "alice_verifying_key" in result.output
def test_alice_view_preexisting_configuration(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, AliceConfiguration.generate_filename())
view_args = ('alice', 'config',
'--config-file', custom_config_filepath)
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, view_args, input=user_input)
view_args = ('alice', 'config', '--config-file', custom_config_filepath)
result = click_runner.invoke(nucypher_cli, view_args, input=FAKE_PASSWORD_CONFIRMED)
assert result.exit_code == 0
assert "checksum_address" in result.output
assert "domains" in result.output
@ -162,10 +137,7 @@ def test_alice_view_preexisting_configuration(click_runner, custom_filepath):
def test_alice_destroy(click_runner, custom_filepath):
"""Should be the last test since it deletes the configuration file"""
custom_config_filepath = custom_filepath / AliceConfiguration.generate_filename()
destroy_args = ('alice', 'destroy',
'--config-file', custom_config_filepath,
'--force')
destroy_args = ('alice', 'destroy', '--config-file', custom_config_filepath, '--force')
result = click_runner.invoke(nucypher_cli, destroy_args, catch_exceptions=False)
assert result.exit_code == 0
assert SUCCESSFUL_DESTRUCTION in result.output

View File

@ -3,19 +3,24 @@ from base64 import b64encode
from unittest import mock
import os
import pytest
from twisted.logger import Logger
from nucypher.characters.control.emitters import JSONRPCStdoutEmitter
from nucypher.characters.lawful import Ursula
from nucypher.cli import utils
from nucypher.cli.literature import SUCCESSFUL_DESTRUCTION
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import BobConfiguration
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.powers import SigningPower
from nucypher.utilities.logging import GlobalLoggerSettings
from tests.constants import INSECURE_DEVELOPMENT_PASSWORD, MOCK_CUSTOM_INSTALLATION_PATH, MOCK_IP_ADDRESS
from nucypher.config.constants import TEMPORARY_DOMAIN
from tests.constants import (
FAKE_PASSWORD_CONFIRMED,
INSECURE_DEVELOPMENT_PASSWORD,
MOCK_CUSTOM_INSTALLATION_PATH,
MOCK_IP_ADDRESS
)
log = Logger()
@ -26,15 +31,12 @@ def test_missing_configuration_file(default_filepath_mock, click_runner):
result = click_runner.invoke(nucypher_cli, cmd_args, catch_exceptions=False)
assert result.exit_code != 0
assert default_filepath_mock.called
assert "run: 'nucypher bob init'" in result.output
assert "nucypher bob init" in result.output
def test_bob_public_keys(click_runner):
derive_key_args = ('bob', 'public-keys',
'--dev')
derive_key_args = ('bob', 'public-keys', '--dev')
result = click_runner.invoke(nucypher_cli, derive_key_args, catch_exceptions=False)
assert result.exit_code == 0
assert "bob_encrypting_key" in result.output
assert "bob_verifying_key" in result.output
@ -46,9 +48,7 @@ def test_initialize_bob_with_custom_configuration_root(custom_filepath, click_ru
'--network', TEMPORARY_DOMAIN,
'--federated-only',
'--config-root', custom_filepath)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD, ip=MOCK_IP_ADDRESS)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED, catch_exceptions=False)
assert result.exit_code == 0, result.exception
# CLI Output
@ -71,13 +71,8 @@ def test_initialize_bob_with_custom_configuration_root(custom_filepath, click_ru
def test_bob_control_starts_with_preexisting_configuration(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, BobConfiguration.generate_filename())
init_args = ('bob', 'run',
'--dry-run',
'--config-file', custom_config_filepath)
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input)
init_args = ('bob', 'run', '--dry-run', '--config-file', custom_config_filepath)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED)
assert result.exit_code == 0, result.exception
assert "Bob Verifying Key" in result.output
assert "Bob Encrypting Key" in result.output
@ -85,13 +80,8 @@ def test_bob_control_starts_with_preexisting_configuration(click_runner, custom_
def test_bob_view_with_preexisting_configuration(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, BobConfiguration.generate_filename())
view_args = ('bob', 'config',
'--config-file', custom_config_filepath)
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, view_args, input=user_input)
view_args = ('bob', 'config', '--config-file', custom_config_filepath)
result = click_runner.invoke(nucypher_cli, view_args, input=FAKE_PASSWORD_CONFIRMED)
assert result.exit_code == 0, result.exception
assert "checksum_address" in result.output
assert "domains" in result.output
@ -101,29 +91,12 @@ def test_bob_view_with_preexisting_configuration(click_runner, custom_filepath):
def test_bob_public_keys(click_runner):
derive_key_args = ('bob', 'public-keys', '--dev')
result = click_runner.invoke(nucypher_cli, derive_key_args, catch_exceptions=False)
assert result.exit_code == 0
assert "bob_encrypting_key" in result.output
assert "bob_verifying_key" in result.output
# Should be the last test since it deletes the configuration file
def test_bob_destroy(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, BobConfiguration.generate_filename())
destroy_args = ('bob', 'destroy',
'--config-file', custom_config_filepath,
'--force')
result = click_runner.invoke(nucypher_cli, destroy_args, catch_exceptions=False)
assert result.exit_code == 0, result.exception
assert SUCCESSFUL_DESTRUCTION in result.output
assert not os.path.exists(custom_config_filepath), "Bob config file was deleted"
# FIXME
@pytest.mark.skip(reason="Needs proper mocking of bob")
def test_bob_retrieves_twice_via_cli(click_runner,
capsule_side_channel,
enacted_federated_policy,
@ -180,7 +153,7 @@ def test_bob_retrieves_twice_via_cli(click_runner,
this_fuckin_guy.controller.emitter = JSONRPCStdoutEmitter()
return this_fuckin_guy
mocker.patch('nucypher.cli.actions.utils.make_cli_character', return_value=substitute_bob)
mocker.patch.object(utils, 'make_cli_character', return_value=substitute_bob)
# Once...
with GlobalLoggerSettings.pause_all_logging_while():
@ -203,3 +176,13 @@ def test_bob_retrieves_twice_via_cli(click_runner,
retrieve_response = json.loads(retrieve_response.output)
for cleartext in retrieve_response['result']['cleartexts']:
assert cleartext.encode() == capsule_side_channel.plaintexts[1]
# NOTE: Should be the last test in this module since it deletes the configuration file
def test_bob_destroy(click_runner, custom_filepath):
custom_config_filepath = os.path.join(custom_filepath, BobConfiguration.generate_filename())
destroy_args = ('bob', 'destroy', '--config-file', custom_config_filepath, '--force')
result = click_runner.invoke(nucypher_cli, destroy_args, catch_exceptions=False)
assert result.exit_code == 0, result.exception
assert SUCCESSFUL_DESTRUCTION in result.output
assert not os.path.exists(custom_config_filepath), "Bob config file was deleted"

View File

@ -8,7 +8,8 @@ from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import AliceConfiguration, BobConfiguration, UrsulaConfiguration
from nucypher.config.constants import NUCYPHER_ENVVAR_KEYRING_PASSWORD, NUCYPHER_ENVVAR_WORKER_IP_ADDRESS, \
TEMPORARY_DOMAIN
from tests.constants import (INSECURE_DEVELOPMENT_PASSWORD, MOCK_CUSTOM_INSTALLATION_PATH, MOCK_IP_ADDRESS,
from tests.constants import (FAKE_PASSWORD_CONFIRMED, INSECURE_DEVELOPMENT_PASSWORD, MOCK_CUSTOM_INSTALLATION_PATH,
MOCK_IP_ADDRESS,
TEST_PROVIDER_URI)
CONFIG_CLASSES = (AliceConfiguration, BobConfiguration, UrsulaConfiguration)
@ -28,8 +29,11 @@ def test_initialize_via_cli(config_class, custom_filepath, click_runner, monkeyp
'--federated-only',
'--config-root', custom_filepath)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False, env=ENV)
result = click_runner.invoke(nucypher_cli,
init_args,
input=FAKE_PASSWORD_CONFIRMED,
catch_exceptions=False,
env=ENV)
assert result.exit_code == 0
# CLI Output

View File

@ -26,9 +26,9 @@ from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import UrsulaConfiguration
from nucypher.config.constants import APP_DIR, DEFAULT_CONFIG_ROOT, NUCYPHER_ENVVAR_KEYRING_PASSWORD, TEMPORARY_DOMAIN
from tests.constants import (
INSECURE_DEVELOPMENT_PASSWORD,
FAKE_PASSWORD_CONFIRMED, INSECURE_DEVELOPMENT_PASSWORD,
MOCK_CUSTOM_INSTALLATION_PATH,
MOCK_IP_ADDRESS)
MOCK_IP_ADDRESS, YES)
from tests.utils.ursula import MOCK_URSULA_STARTING_PORT
@ -39,11 +39,9 @@ def test_initialize_ursula_defaults(click_runner, mocker):
mocker.patch.object(UrsulaConfiguration, 'to_configuration_file', autospec=True)
# Use default ursula init args
init_args = ('ursula', 'init',
'--network', TEMPORARY_DOMAIN,
'--federated-only')
init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN, '--federated-only')
user_input = 'Y\n{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD, ip=MOCK_IP_ADDRESS)
user_input = YES + FAKE_PASSWORD_CONFIRMED
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False)
assert result.exit_code == 0
@ -64,9 +62,7 @@ def test_initialize_custom_configuration_root(custom_filepath, click_runner):
'--config-root', custom_filepath,
'--rest-host', MOCK_IP_ADDRESS,
'--rest-port', MOCK_URSULA_STARTING_PORT)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False)
result = click_runner.invoke(nucypher_cli, init_args, input=FAKE_PASSWORD_CONFIRMED, catch_exceptions=False)
assert result.exit_code == 0
# CLI Output

View File

@ -33,7 +33,8 @@ from nucypher.blockchain.eth.token import NU, Stake, StakeList
from nucypher.characters.lawful import Enrico, Ursula
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import UrsulaConfiguration
from tests.constants import (INSECURE_DEVELOPMENT_PASSWORD, MOCK_INDIVIDUAL_ALLOCATION_FILEPATH, MOCK_IP_ADDRESS,
from tests.constants import (FAKE_PASSWORD_CONFIRMED, INSECURE_DEVELOPMENT_PASSWORD,
MOCK_INDIVIDUAL_ALLOCATION_FILEPATH, MOCK_IP_ADDRESS,
ONE_YEAR_IN_SECONDS,
TEST_PROVIDER_URI)
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, MOCK_URSULA_STARTING_PORT, select_test_port
@ -426,10 +427,9 @@ def test_ursula_init(click_runner,
'--rest-host', MOCK_IP_ADDRESS,
'--rest-port', MOCK_URSULA_STARTING_PORT)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli,
init_args,
input=user_input,
input=FAKE_PASSWORD_CONFIRMED,
catch_exceptions=False)
assert result.exit_code == 0

View File

@ -30,7 +30,8 @@ from nucypher.characters.lawful import Enrico, Ursula
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import StakeHolderConfiguration, UrsulaConfiguration
from nucypher.config.constants import TEMPORARY_DOMAIN
from tests.constants import FEE_RATE_RANGE, INSECURE_DEVELOPMENT_PASSWORD, MOCK_IP_ADDRESS, TEST_PROVIDER_URI
from tests.constants import FAKE_PASSWORD_CONFIRMED, FEE_RATE_RANGE, INSECURE_DEVELOPMENT_PASSWORD, MOCK_IP_ADDRESS, \
TEST_PROVIDER_URI
from tests.utils.middleware import MockRestMiddleware
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, MOCK_URSULA_STARTING_PORT, select_test_port
@ -237,10 +238,9 @@ def test_ursula_init(click_runner,
'--rest-host', MOCK_IP_ADDRESS,
'--rest-port', MOCK_URSULA_STARTING_PORT)
user_input = '{password}\n{password}'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
result = click_runner.invoke(nucypher_cli,
init_args,
input=user_input,
input=FAKE_PASSWORD_CONFIRMED,
catch_exceptions=False)
assert result.exit_code == 0

View File

@ -143,6 +143,7 @@ YES = 'Y\n'
NO = 'N\n'
FAKE_PASSWORD_CONFIRMED = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
CLI_TEST_ENV = {NUCYPHER_ENVVAR_KEYRING_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD}

View File

@ -95,6 +95,8 @@ from tests.performance_mocks import (
mock_verify_node
)
from tests.utils.blockchain import TesterBlockchain, token_airdrop
from tests.utils.config import make_alice_test_configuration, make_bob_test_configuration, \
make_ursula_test_configuration
from tests.utils.middleware import MockRestMiddleware, MockRestMiddlewareForLargeFleetTests
from tests.utils.policy import generate_random_label
from tests.utils.ursula import MOCK_URSULA_STARTING_PORT, make_decentralized_ursulas, make_federated_ursulas
@ -139,101 +141,64 @@ def certificates_tempdir():
#
# Configuration
# Federated Configuration
#
@pytest.fixture(scope="module")
def ursula_federated_test_config():
ursula_config = UrsulaConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
rest_port=MOCK_URSULA_STARTING_PORT,
start_learning_now=False,
abort_on_learning_error=True,
federated_only=True,
network_middleware=MockRestMiddleware(),
save_metadata=False,
reload_metadata=False,
availability_check=False)
yield ursula_config
ursula_config.cleanup()
@pytest.fixture(scope="module")
def ursula_decentralized_test_config(test_registry):
ursula_config = UrsulaConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
provider_uri=TEST_PROVIDER_URI,
rest_port=MOCK_URSULA_STARTING_PORT,
start_learning_now=False,
abort_on_learning_error=True,
federated_only=False,
network_middleware=MockRestMiddleware(),
save_metadata=False,
reload_metadata=False,
registry=test_registry,
availability_check=False)
yield ursula_config
ursula_config.cleanup()
@pytest.fixture(scope="module")
def alice_federated_test_config(federated_ursulas):
config = AliceConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
network_middleware=MockRestMiddleware(),
known_nodes=federated_ursulas,
federated_only=True,
abort_on_learning_error=True,
save_metadata=False,
reload_metadata=False,)
def ursula_federated_test_config(test_registry):
config = make_ursula_test_configuration(federated=True, rest_port=MOCK_URSULA_STARTING_PORT)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def alice_blockchain_test_config(blockchain_ursulas, testerchain, test_registry):
config = AliceConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
provider_uri=TEST_PROVIDER_URI,
checksum_address=testerchain.alice_account,
network_middleware=MockRestMiddleware(),
known_nodes=blockchain_ursulas,
abort_on_learning_error=True,
save_metadata=False,
reload_metadata=False,
registry=test_registry)
def alice_federated_test_config(federated_ursulas):
config = make_alice_test_configuration(federated=True, known_nodes=federated_ursulas)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def bob_federated_test_config():
config = BobConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
network_middleware=MockRestMiddleware(),
start_learning_now=False,
abort_on_learning_error=True,
federated_only=True,
save_metadata=False,
reload_metadata=False,)
config = make_bob_test_configuration(federated=True)
yield config
config.cleanup()
#
# Decentralized Configuration
#
@pytest.fixture(scope="module")
def ursula_decentralized_test_config(test_registry):
config = make_ursula_test_configuration(federated=False,
provider_uri=TEST_PROVIDER_URI,
test_registry=test_registry,
rest_port=MOCK_URSULA_STARTING_PORT)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def alice_blockchain_test_config(blockchain_ursulas, testerchain, test_registry):
config = make_alice_test_configuration(federated=False,
provider_uri=TEST_PROVIDER_URI,
known_nodes=blockchain_ursulas,
test_registry=test_registry)
yield config
config.cleanup()
@pytest.fixture(scope="module")
def bob_blockchain_test_config(blockchain_ursulas, testerchain, test_registry):
config = BobConfiguration(dev_mode=True,
domains={TEMPORARY_DOMAIN},
provider_uri=TEST_PROVIDER_URI,
checksum_address=testerchain.bob_account,
network_middleware=MockRestMiddleware(),
known_nodes=blockchain_ursulas,
start_learning_now=False,
abort_on_learning_error=True,
federated_only=False,
save_metadata=False,
reload_metadata=False,
registry=test_registry)
config = make_bob_test_configuration(federated=False,
provider_uri=TEST_PROVIDER_URI,
test_registry=test_registry,
checksum_address=testerchain.bob_account,
known_nodes=blockchain_ursulas)
yield config
config.cleanup()