UDS: implicitly create `Address.bindspace: Path`
Since it's merely a local-file-sys subdirectory and there should be no reason file creation conflicts with other bind spaces. Also add 2 test suites to match, - `tests/ipc/test_each_tpt::test_uds_bindspace_created_implicitly` to verify the dir creation when DNE. - `..test_uds_double_listen_raises_connerr` to ensure a double bind raises a `ConnectionError` from the src `OSError`.to_asyncio_eoc_signal
parent
c2acc4f55c
commit
d079675dd4
|
@ -0,0 +1,113 @@
|
|||
'''
|
||||
Unit-ish tests for specific IPC transport protocol backends.
|
||||
|
||||
'''
|
||||
from __future__ import annotations
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import trio
|
||||
import tractor
|
||||
from tractor import (
|
||||
Actor,
|
||||
_state,
|
||||
_addr,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bindspace_dir_str() -> str:
|
||||
|
||||
bs_dir_str: str = '/run/user/1000/doggy'
|
||||
bs_dir = Path(bs_dir_str)
|
||||
assert not bs_dir.is_dir()
|
||||
|
||||
yield bs_dir_str
|
||||
|
||||
# delete it on suite teardown.
|
||||
# ?TODO? should we support this internally
|
||||
# or is leaking it ok?
|
||||
if bs_dir.is_dir():
|
||||
bs_dir.rmdir()
|
||||
|
||||
|
||||
def test_uds_bindspace_created_implicitly(
|
||||
debug_mode: bool,
|
||||
bindspace_dir_str: str,
|
||||
):
|
||||
registry_addr: tuple = (
|
||||
f'{bindspace_dir_str}',
|
||||
'registry@doggy.sock',
|
||||
)
|
||||
bs_dir_str: str = registry_addr[0]
|
||||
|
||||
# XXX, ensure bindspace-dir DNE beforehand!
|
||||
assert not Path(bs_dir_str).is_dir()
|
||||
|
||||
async def main():
|
||||
async with tractor.open_nursery(
|
||||
enable_transports=['uds'],
|
||||
registry_addrs=[registry_addr],
|
||||
debug_mode=debug_mode,
|
||||
) as _an:
|
||||
|
||||
# XXX MUST be created implicitly by
|
||||
# `.ipc._uds.start_listener()`!
|
||||
assert Path(bs_dir_str).is_dir()
|
||||
|
||||
root: Actor = tractor.current_actor()
|
||||
assert root.is_registrar
|
||||
|
||||
assert registry_addr in root.reg_addrs
|
||||
assert (
|
||||
registry_addr
|
||||
in
|
||||
_state._runtime_vars['_registry_addrs']
|
||||
)
|
||||
assert (
|
||||
_addr.wrap_address(registry_addr)
|
||||
in
|
||||
root.registry_addrs
|
||||
)
|
||||
|
||||
trio.run(main)
|
||||
|
||||
|
||||
def test_uds_double_listen_raises_connerr(
|
||||
debug_mode: bool,
|
||||
bindspace_dir_str: str,
|
||||
):
|
||||
registry_addr: tuple = (
|
||||
f'{bindspace_dir_str}',
|
||||
'registry@doggy.sock',
|
||||
)
|
||||
|
||||
async def main():
|
||||
async with tractor.open_nursery(
|
||||
enable_transports=['uds'],
|
||||
registry_addrs=[registry_addr],
|
||||
debug_mode=debug_mode,
|
||||
) as _an:
|
||||
|
||||
# runtime up
|
||||
root: Actor = tractor.current_actor()
|
||||
|
||||
from tractor.ipc._uds import (
|
||||
start_listener,
|
||||
UDSAddress,
|
||||
)
|
||||
ya_bound_addr: UDSAddress = root.registry_addrs[0]
|
||||
try:
|
||||
await start_listener(
|
||||
addr=ya_bound_addr,
|
||||
)
|
||||
except ConnectionError as connerr:
|
||||
assert type(src_exc := connerr.__context__) is OSError
|
||||
assert 'Address already in use' in src_exc.args
|
||||
# complete, exit test.
|
||||
|
||||
else:
|
||||
pytest.fail('It dint raise a connerr !?')
|
||||
|
||||
|
||||
trio.run(main)
|
|
@ -103,8 +103,6 @@ class UDSAddress(
|
|||
self.filedir
|
||||
or
|
||||
self.def_bindspace
|
||||
# or
|
||||
# get_rt_dir()
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -230,7 +228,14 @@ async def start_listener(
|
|||
addr: UDSAddress,
|
||||
**kwargs,
|
||||
) -> SocketListener:
|
||||
# sock = addr._sock = socket.socket(
|
||||
'''
|
||||
Start listening for inbound connections via
|
||||
a `trio.SocketListener` (task) which `socket.bind()`s on `addr`.
|
||||
|
||||
Note, if the `UDSAddress.bindspace: Path` directory dne it is
|
||||
implicitly created.
|
||||
|
||||
'''
|
||||
sock = socket.socket(
|
||||
socket.AF_UNIX,
|
||||
socket.SOCK_STREAM
|
||||
|
@ -241,7 +246,17 @@ async def start_listener(
|
|||
f'|_{addr}\n'
|
||||
)
|
||||
|
||||
# ?TODO? should we use the `actor.lifetime_stack`
|
||||
# to rm on shutdown?
|
||||
bindpath: Path = addr.sockpath
|
||||
if not (bs := addr.bindspace).is_dir():
|
||||
log.info(
|
||||
'Creating bindspace dir in file-sys\n'
|
||||
f'>{{\n'
|
||||
f'|_{bs!r}\n'
|
||||
)
|
||||
bs.mkdir()
|
||||
|
||||
with _reraise_as_connerr(
|
||||
src_excs=(
|
||||
FileNotFoundError,
|
||||
|
|
Loading…
Reference in New Issue