forked from goodboy/tractor
Ensure kbi will cancel context block
Follow up to previous commit: extend our simple context test set to include cancellation via kbi in the parent as well as timeout logic and testing of the parent opening a stream even though the target actor does not. Thanks again to https://github.com/adder46/wrath for discovering this bug.fix_kbi_in_ctx_block
parent
c1727ce05e
commit
8d79d83ac2
|
@ -51,26 +51,35 @@ async def assert_state(value: bool):
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'error_parent',
|
'error_parent',
|
||||||
[False, True],
|
[False, ValueError, KeyboardInterrupt],
|
||||||
)
|
)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'callee_blocks_forever',
|
'callee_blocks_forever',
|
||||||
[False, True],
|
[False, True],
|
||||||
|
ids=lambda item: f'callee_blocks_forever={item}'
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'pointlessly_open_stream',
|
||||||
|
[False, True],
|
||||||
|
ids=lambda item: f'open_stream={item}'
|
||||||
)
|
)
|
||||||
def test_simple_context(
|
def test_simple_context(
|
||||||
error_parent,
|
error_parent,
|
||||||
callee_blocks_forever,
|
callee_blocks_forever,
|
||||||
|
pointlessly_open_stream,
|
||||||
):
|
):
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
|
|
||||||
async with tractor.open_nursery() as n:
|
with trio.fail_after(1.5):
|
||||||
|
async with tractor.open_nursery() as nursery:
|
||||||
|
|
||||||
portal = await n.start_actor(
|
portal = await nursery.start_actor(
|
||||||
'simple_context',
|
'simple_context',
|
||||||
enable_modules=[__name__],
|
enable_modules=[__name__],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
async with portal.open_context(
|
async with portal.open_context(
|
||||||
simple_setup_teardown,
|
simple_setup_teardown,
|
||||||
data=10,
|
data=10,
|
||||||
|
@ -81,15 +90,33 @@ def test_simple_context(
|
||||||
|
|
||||||
if callee_blocks_forever:
|
if callee_blocks_forever:
|
||||||
await portal.run(assert_state, value=True)
|
await portal.run(assert_state, value=True)
|
||||||
await ctx.cancel()
|
|
||||||
else:
|
else:
|
||||||
assert await ctx.result() == 'yo'
|
assert await ctx.result() == 'yo'
|
||||||
|
|
||||||
# after cancellation
|
if not error_parent:
|
||||||
await portal.run(assert_state, value=False)
|
await ctx.cancel()
|
||||||
|
|
||||||
|
if pointlessly_open_stream:
|
||||||
|
async with ctx.open_stream():
|
||||||
if error_parent:
|
if error_parent:
|
||||||
raise ValueError
|
raise error_parent
|
||||||
|
|
||||||
|
if callee_blocks_forever:
|
||||||
|
await ctx.cancel()
|
||||||
|
else:
|
||||||
|
# in this case the stream will send a
|
||||||
|
# 'stop' msg to the far end which needs
|
||||||
|
# to be ignored
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if error_parent:
|
||||||
|
raise error_parent
|
||||||
|
|
||||||
|
finally:
|
||||||
|
|
||||||
|
# after cancellation
|
||||||
|
if not error_parent:
|
||||||
|
await portal.run(assert_state, value=False)
|
||||||
|
|
||||||
# shut down daemon
|
# shut down daemon
|
||||||
await portal.cancel_actor()
|
await portal.cancel_actor()
|
||||||
|
@ -97,7 +124,7 @@ def test_simple_context(
|
||||||
if error_parent:
|
if error_parent:
|
||||||
try:
|
try:
|
||||||
trio.run(main)
|
trio.run(main)
|
||||||
except ValueError:
|
except error_parent:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
trio.run(main)
|
trio.run(main)
|
||||||
|
|
Loading…
Reference in New Issue