forked from goodboy/tractor
81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
"""
|
|
RPC related
|
|
"""
|
|
import pytest
|
|
import tractor
|
|
import trio
|
|
|
|
|
|
async def sleep_back_actor(
|
|
actor_name,
|
|
func_name,
|
|
func_defined,
|
|
exposed_mods,
|
|
):
|
|
async with tractor.find_actor(actor_name) as portal:
|
|
try:
|
|
await portal.run(__name__, func_name)
|
|
except tractor.RemoteActorError as err:
|
|
if not func_defined:
|
|
expect = AttributeError
|
|
if not exposed_mods:
|
|
expect = tractor.ModuleNotExposed
|
|
|
|
assert err.type is expect
|
|
raise
|
|
|
|
|
|
async def short_sleep():
|
|
await trio.sleep(0)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'to_call', [
|
|
([], 'short_sleep'),
|
|
([__name__], 'short_sleep'),
|
|
([__name__], 'fake_func'),
|
|
],
|
|
ids=['no_mods', 'this_mod', 'this_mod_bad_func'],
|
|
)
|
|
def test_rpc_errors(arb_addr, to_call):
|
|
"""Test errors when making various RPC requests to an actor
|
|
that either doesn't have the requested module exposed or doesn't define
|
|
the named function.
|
|
"""
|
|
exposed_mods, funcname = to_call
|
|
func_defined = globals().get(funcname, False)
|
|
|
|
async def main():
|
|
actor = tractor.current_actor()
|
|
assert actor.is_arbiter
|
|
|
|
# spawn a subactor which calls us back
|
|
async with tractor.open_nursery() as n:
|
|
await n.run_in_actor(
|
|
'subactor',
|
|
sleep_back_actor,
|
|
actor_name=actor.name,
|
|
# function from this module the subactor will invoke
|
|
# when it RPCs back to this actor
|
|
func_name=funcname,
|
|
exposed_mods=exposed_mods,
|
|
func_defined=True if func_defined else False,
|
|
)
|
|
|
|
def run():
|
|
tractor.run(
|
|
main,
|
|
arbiter_addr=arb_addr,
|
|
rpc_module_paths=exposed_mods,
|
|
)
|
|
|
|
# handle both parameterized cases
|
|
if exposed_mods and func_defined:
|
|
run()
|
|
else:
|
|
# underlying errors are propogated upwards (yet)
|
|
with pytest.raises(tractor.RemoteActorError) as err:
|
|
run()
|
|
|
|
assert err.value.type is tractor.RemoteActorError
|