Allow MockRegistrySource to take any domain value while allowing the accepted values to be specified.

Update various tests that used random domain values to either use the mock, or just use TEMPORARY_DOMAIN if applicable.
pull/3262/head
derekpierre 2023-10-04 13:12:30 -04:00
parent 9708efb0ba
commit 568270d36c
4 changed files with 130 additions and 44 deletions

View File

@ -1,9 +1,11 @@
import pytest import pytest
from nucypher.config.constants import TEMPORARY_DOMAIN
def test_new_ursula_announces_herself(lonely_ursula_maker): def test_new_ursula_announces_herself(lonely_ursula_maker):
ursula_in_a_house, ursula_with_a_mouse = lonely_ursula_maker( ursula_in_a_house, ursula_with_a_mouse = lonely_ursula_maker(
quantity=2, domain="useless_domain" quantity=2, domain=TEMPORARY_DOMAIN
) )
# Neither Ursula knows about the other. # Neither Ursula knows about the other.
@ -36,7 +38,7 @@ def test_goerli_and_mumbai_as_conditions_providers(lonely_ursula_maker):
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
_ursula_who_tries_to_connect_to_an_invalid_chain = lonely_ursula_maker( _ursula_who_tries_to_connect_to_an_invalid_chain = lonely_ursula_maker(
quantity=1, quantity=1,
domain="useless_domain", domain=TEMPORARY_DOMAIN,
condition_blockchain_endpoints={ condition_blockchain_endpoints={
INVALID_CHAIN_ID: "this is a provider URI, but it doesn't matter what we pass here because the chain_id is invalid." INVALID_CHAIN_ID: "this is a provider URI, but it doesn't matter what we pass here because the chain_id is invalid."
}, },

View File

@ -2,22 +2,62 @@ from pathlib import Path
import pytest import pytest
import tests
from nucypher.acumen.perception import FleetSensor from nucypher.acumen.perception import FleetSensor
from nucypher.blockchain.eth.registry import ContractRegistry
from nucypher.characters.lawful import Ursula from nucypher.characters.lawful import Ursula
from nucypher.config.storages import LocalFileBasedNodeStorage from nucypher.config.storages import LocalFileBasedNodeStorage
from nucypher.network.nodes import TEACHER_NODES from nucypher.network.nodes import TEACHER_NODES
from tests.utils.registry import MockRegistrySource
from tests.utils.ursula import make_ursulas from tests.utils.ursula import make_ursulas
@pytest.mark.usefixtures("test_registry_source_manager") @pytest.fixture(scope="module")
def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog): def domain_1():
return "domain_uno"
@pytest.fixture(scope="module")
def domain_2():
return "domain_dos"
@pytest.fixture(scope="module")
def test_registry(module_mocker, domain_1, domain_2):
with tests.utils.registry.mock_registry_sources(
mocker=module_mocker, domain_names=[domain_1, domain_2]
):
# doesn't really matter what domain is used here
registry = ContractRegistry(MockRegistrySource(domain=domain_1))
yield registry
@pytest.fixture(scope="module")
def registry_1(domain_1, test_registry):
return ContractRegistry(MockRegistrySource(domain=domain_1))
@pytest.fixture(scope="module")
def registry_2(domain_2, test_registry):
return ContractRegistry(MockRegistrySource(domain=domain_2))
def test_learner_learns_about_domains_separately(
lonely_ursula_maker, domain_1, domain_2, registry_1, registry_2, caplog
):
hero_learner, other_first_domain_learner = lonely_ursula_maker( hero_learner, other_first_domain_learner = lonely_ursula_maker(
domain="nucypher1.test_suite", quantity=2 domain=domain_1,
registry=registry_1,
quantity=2,
) )
_nobody = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop() _nobody = lonely_ursula_maker(
domain=domain_1, registry=registry_1, quantity=1
).pop()
other_first_domain_learner.remember_node(_nobody) other_first_domain_learner.remember_node(_nobody)
second_domain_learners = lonely_ursula_maker(domain="nucypher2.test_suite", know_each_other=True, quantity=3) second_domain_learners = lonely_ursula_maker(
domain=domain_2, registry=registry_2, know_each_other=True, quantity=3
)
assert len(hero_learner.known_nodes) == 0 assert len(hero_learner.known_nodes) == 0
@ -36,8 +76,12 @@ def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog):
# All domain 1 nodes # All domain 1 nodes
assert len(hero_learner.known_nodes) == 2 assert len(hero_learner.known_nodes) == 2
new_first_domain_learner = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop() new_first_domain_learner = lonely_ursula_maker(
_new_second_domain_learner = lonely_ursula_maker(domain="nucypher2.test_suite", quantity=1).pop() domain=domain_1, registry=registry_1, quantity=1
).pop()
_new_second_domain_learner = lonely_ursula_maker(
domain=domain_2, registry=registry_2, quantity=1
).pop()
new_first_domain_learner.remember_node(hero_learner) new_first_domain_learner.remember_node(hero_learner)
@ -52,7 +96,9 @@ def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog):
assert _nobody in new_first_domain_learner.known_nodes assert _nobody in new_first_domain_learner.known_nodes
def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir): def test_learner_restores_metadata_from_storage(
lonely_ursula_maker, tmpdir, domain_1, domain_2
):
# Create a local file-based node storage # Create a local file-based node storage
root = tmpdir.mkdir("known_nodes") root = tmpdir.mkdir("known_nodes")
metadata = root.mkdir("metadata") metadata = root.mkdir("metadata")
@ -62,20 +108,24 @@ def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir):
storage_root=Path(root)) storage_root=Path(root))
# Use the ursula maker with this storage so it's populated with nodes from one domain # Use the ursula maker with this storage so it's populated with nodes from one domain
_some_ursulas = lonely_ursula_maker(domain="fistro", _some_ursulas = lonely_ursula_maker(
node_storage=old_storage, domain=domain_1,
know_each_other=True, node_storage=old_storage,
quantity=3, know_each_other=True,
save_metadata=True) quantity=3,
save_metadata=True,
)
# Create a pair of new learners in a different domain, using the previous storage, and learn from it # Create a pair of new learners in a different domain, using the previous storage, and learn from it
new_learners = lonely_ursula_maker(domain="duodenal", new_learners = lonely_ursula_maker(
node_storage=old_storage, domain=domain_2,
quantity=2, node_storage=old_storage,
know_each_other=True, quantity=2,
save_metadata=False) know_each_other=True,
save_metadata=False,
)
learner, buddy = new_learners learner, buddy = new_learners
buddy._Learner__known_nodes = FleetSensor(domain="fistro") buddy._Learner__known_nodes = FleetSensor(domain=domain_1)
# The learner shouldn't learn about any node from the first domain, since it's different. # The learner shouldn't learn about any node from the first domain, since it's different.
learner.learn_from_teacher_node() learner.learn_from_teacher_node()
@ -88,11 +138,19 @@ def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir):
def test_learner_ignores_stored_nodes_from_other_domains( def test_learner_ignores_stored_nodes_from_other_domains(
lonely_ursula_maker, tmpdir, testerchain, ursula_test_config lonely_ursula_maker,
domain_1,
domain_2,
registry_1,
registry_2,
tmpdir,
testerchain,
ursula_test_config,
): ):
learner, other_staker = make_ursulas( learner, other_staker = make_ursulas(
ursula_test_config, ursula_test_config,
domain="call-it-mainnet", domain=domain_1,
registry=registry_1,
quantity=2, quantity=2,
know_each_other=True, know_each_other=True,
staking_provider_addresses=testerchain.stake_providers_accounts[:2], staking_provider_addresses=testerchain.stake_providers_accounts[:2],
@ -101,7 +159,8 @@ def test_learner_ignores_stored_nodes_from_other_domains(
pest, *other_ursulas_from_the_wrong_side_of_the_tracks = make_ursulas( pest, *other_ursulas_from_the_wrong_side_of_the_tracks = make_ursulas(
ursula_test_config, ursula_test_config,
domain="i-dunno-testt-maybe", domain=domain_2,
registry=registry_2,
quantity=5, quantity=5,
know_each_other=True, know_each_other=True,
staking_provider_addresses=testerchain.stake_providers_accounts[2:], staking_provider_addresses=testerchain.stake_providers_accounts[2:],
@ -129,13 +188,16 @@ def test_learner_ignores_stored_nodes_from_other_domains(
assert pest not in other_staker.known_nodes # But not anymore. assert pest not in other_staker.known_nodes # But not anymore.
def test_learner_with_empty_storage_uses_fallback_nodes(lonely_ursula_maker, mocker): def test_learner_with_empty_storage_uses_fallback_nodes(
domain = "learner-domain" lonely_ursula_maker, domain_1, mocker
mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True) ):
mocker.patch.dict(TEACHER_NODES, {domain_1: ("teacher-uri",)}, clear=True)
# Create a learner and a teacher # Create a learner and a teacher
learner, teacher = lonely_ursula_maker(domain=domain, quantity=2, save_metadata=False) learner, teacher = lonely_ursula_maker(
mocker.patch.object(Ursula, 'from_teacher_uri', return_value=teacher) domain=domain_1, quantity=2, save_metadata=False
)
mocker.patch.object(Ursula, "from_teacher_uri", return_value=teacher)
# Since there are no nodes in local node storage, the learner should only learn about the teacher # Since there are no nodes in local node storage, the learner should only learn about the teacher
learner.learn_from_teacher_node() learner.learn_from_teacher_node()
@ -143,10 +205,16 @@ def test_learner_with_empty_storage_uses_fallback_nodes(lonely_ursula_maker, moc
def test_learner_uses_both_nodes_from_storage_and_fallback_nodes( def test_learner_uses_both_nodes_from_storage_and_fallback_nodes(
lonely_ursula_maker, tmpdir, mocker, test_registry, ursula_test_config, testerchain lonely_ursula_maker,
domain_1,
registry_1,
tmpdir,
mocker,
test_registry,
ursula_test_config,
testerchain,
): ):
domain = "learner-domain" mocker.patch.dict(TEACHER_NODES, {domain_1: ("teacher-uri",)}, clear=True)
mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True)
# Create a local file-based node storage # Create a local file-based node storage
root = tmpdir.mkdir("known_nodes") root = tmpdir.mkdir("known_nodes")
@ -159,7 +227,8 @@ def test_learner_uses_both_nodes_from_storage_and_fallback_nodes(
# Create some nodes and persist them to local storage # Create some nodes and persist them to local storage
other_nodes = make_ursulas( other_nodes = make_ursulas(
ursula_test_config, ursula_test_config,
domain=domain, domain=domain_1,
registry=registry_1,
node_storage=node_storage, node_storage=node_storage,
know_each_other=True, know_each_other=True,
quantity=3, quantity=3,
@ -170,7 +239,8 @@ def test_learner_uses_both_nodes_from_storage_and_fallback_nodes(
# Create a teacher and a learner using existing node storage # Create a teacher and a learner using existing node storage
learner, teacher = lonely_ursula_maker( learner, teacher = lonely_ursula_maker(
domain=domain, domain=domain_1,
registry=registry_1,
node_storage=node_storage, node_storage=node_storage,
quantity=2, quantity=2,
know_each_other=True, know_each_other=True,

View File

@ -3,15 +3,18 @@ from functools import partial
import pytest_twisted as pt import pytest_twisted as pt
from twisted.internet.threads import deferToThread from twisted.internet.threads import deferToThread
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.network.middleware import RestMiddleware from nucypher.network.middleware import RestMiddleware
from tests.constants import MOCK_ETH_PROVIDER_URI from tests.constants import MOCK_ETH_PROVIDER_URI
def test_proper_seed_node_instantiation(lonely_ursula_maker): def test_proper_seed_node_instantiation(lonely_ursula_maker):
_lonely_ursula_maker = partial(lonely_ursula_maker, quantity=1) _lonely_ursula_maker = partial(lonely_ursula_maker, quantity=1)
firstula = _lonely_ursula_maker(domain="this-is-meaningful-now").pop() firstula = _lonely_ursula_maker(domain=TEMPORARY_DOMAIN).pop()
firstula_as_seed_node = firstula.seed_node_metadata() firstula_as_seed_node = firstula.seed_node_metadata()
any_other_ursula = _lonely_ursula_maker(seed_nodes=[firstula_as_seed_node], domain="this-is-meaningful-now").pop() any_other_ursula = _lonely_ursula_maker(
seed_nodes=[firstula_as_seed_node], domain=TEMPORARY_DOMAIN
).pop()
assert not any_other_ursula.known_nodes assert not any_other_ursula.known_nodes
any_other_ursula.start_learning_loop(now=True) any_other_ursula.start_learning_loop(now=True)

View File

@ -20,13 +20,22 @@ from nucypher.config.constants import TEMPORARY_DOMAIN
@contextmanager @contextmanager
def mock_registry_sources(mocker): def mock_registry_sources(mocker, domain_names: List[str] = None):
test_domain = TACoDomain( if not domain_names:
TEMPORARY_DOMAIN, EthChain.TESTERCHAIN, PolygonChain.TESTERCHAIN domain_names = [TEMPORARY_DOMAIN]
)
mocker.patch.object(domains, "SUPPORTED_DOMAINS", [test_domain]) supported_domains = []
mocker.patch.object(domains, "SUPPORTED_DOMAIN_NAMES", [TEMPORARY_DOMAIN]) supported_domain_names = []
for domain_name in domain_names:
test_domain = TACoDomain(
domain_name, EthChain.TESTERCHAIN, PolygonChain.TESTERCHAIN
)
supported_domains.append(test_domain)
supported_domain_names.append(domain_name)
mocker.patch.object(domains, "SUPPORTED_DOMAINS", supported_domains)
mocker.patch.object(domains, "SUPPORTED_DOMAIN_NAMES", supported_domain_names)
mocker.patch.object(MockRegistrySource, "ALLOWED_DOMAINS", domain_names)
mocker.patch.object(RegistrySourceManager, "_FALLBACK_CHAIN", (MockRegistrySource,)) mocker.patch.object(RegistrySourceManager, "_FALLBACK_CHAIN", (MockRegistrySource,))
@ -34,15 +43,17 @@ def mock_registry_sources(mocker):
class MockRegistrySource(RegistrySource): class MockRegistrySource(RegistrySource):
ALLOWED_DOMAINS = [TEMPORARY_DOMAIN]
name = "Mock Registry Source" name = "Mock Registry Source"
is_primary = False is_primary = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.domain != TEMPORARY_DOMAIN: if self.domain not in self.ALLOWED_DOMAINS:
raise ValueError( raise ValueError(
f"Somehow, MockRegistrySource is trying to get a registry for '{self.domain}'. " f"Somehow, MockRegistrySource is trying to get a registry for '{self.domain}'. "
f"Only '{TEMPORARY_DOMAIN}' is supported.'" f"Only '{','.join(self.ALLOWED_DOMAINS)}' are supported.'"
) )
@property @property