Strengthen context and debugger regressions

Older review threads found that context startup mocks did not identify
the internal cancel RPC, the overrun packer seam lacked rationale and
the debugger test no longer asserted its KeyboardInterrupt transcript.

Assert exact startup/cancel RPC ordering, explain the stable error spy,
add terse test typing and restore the terminal interrupt check after
EOF.

Review: PR #481 (goodboy)
https://github.com/goodboy/tractor/pull/481#pullrequestreview-5012942328

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
wkt/to_actor_subpkg
Gud Boi 2026-08-25 15:05:55 -04:00
parent 48844aa4ac
commit 98bc642e72
2 changed files with 23 additions and 9 deletions

View File

@ -1359,6 +1359,8 @@ def test_ctxep_pauses_n_maybe_ipc_breaks(
expect_prompt=False,
)
child.expect(EOF)
before += ansi_strip(child.before.decode())
assert 'KeyboardInterrupt' in before
assert child.flag_eof
assert not child.isalive()

View File

@ -86,7 +86,7 @@ from ._helpers import (
def test_overrun_error_send_tolerates_transport_close(
monkeypatch: pytest.MonkeyPatch,
):
) -> None:
'''
Preserve a stream overrun when its error can not be shipped.
@ -108,10 +108,13 @@ def test_overrun_error_send_tolerates_transport_close(
)
packed: dict[str, object] = {}
# Spy on the generated `StreamOverrun` and return a stable wire
# `Error`; the real packer adds traceback/relay details unrelated to
# this test's secondary transport-close contract.
def pack_overrun(
local_err: BaseException,
cid: str,
**kwargs,
**kwargs: object,
) -> tractor.msg.Error:
packed['local_err'] = local_err
packed['cid'] = cid
@ -275,7 +278,7 @@ async def simple_setup_teardown(
_state = False
async def assert_state(value: bool):
async def assert_state(value: bool) -> None:
global _state
assert _state == value
@ -286,7 +289,7 @@ async def test_cancel_during_context_startup(
tmp_path: Path,
start_method: str,
debug_mode: bool,
):
) -> None:
'''
Cancel a context after sending `Start` but before its ack.
@ -303,6 +306,7 @@ async def test_cancel_during_context_startup(
started_path = tmp_path / 'startup_started'
cancelled_path = tmp_path / 'startup_cancelled'
start_sent = trio.Event()
start_funcs: list[str] = []
original_send = tractor.Channel.send
async def delay_after_start(
@ -317,7 +321,11 @@ async def test_cancel_during_context_startup(
hide_tb=hide_tb,
send_deadline=send_deadline,
)
# The patched method keeps `Channel.send()`'s broad message
# contract. It sees both the requested endpoint `Start` and the
# internal `self._cancel_task` startup RPC used for cleanup.
if isinstance(payload, tractor.msg.Start):
start_funcs.append(payload.func)
if payload.func == 'startup_cancel_target':
start_sent.set()
await trio.sleep_forever()
@ -333,7 +341,7 @@ async def test_cancel_during_context_startup(
raise AssertionError('context startup should be cancelled')
async with tractor.open_nursery() as an:
actor = tractor.current_actor()
actor: Actor = tractor.current_actor()
portal: tractor.Portal = await an.start_actor(
'startup_cancel_worker',
enable_modules=[__name__],
@ -365,6 +373,10 @@ async def test_cancel_during_context_startup(
'return_one',
) == 1
assert non_registration_contexts(actor) == contexts_before
assert start_funcs == [
'startup_cancel_target',
'_cancel_task',
]
await portal.cancel_actor()
@ -372,7 +384,7 @@ async def test_cancel_during_context_startup(
async def test_start_serialization_error_cleans_context(
start_method: str,
debug_mode: bool,
):
) -> None:
'''
Deallocate caller state when `Start` can not be serialized.
@ -385,7 +397,7 @@ async def test_start_serialization_error_cleans_context(
'''
async with tractor.open_nursery() as an:
actor = tractor.current_actor()
actor: Actor = tractor.current_actor()
portal: tractor.Portal = await an.start_actor(
'serialization_error_worker',
enable_modules=[__name__],
@ -414,7 +426,7 @@ async def test_start_serialization_error_cleans_context(
async def test_start_module_error_cleans_context(
start_method: str,
debug_mode: bool,
):
) -> None:
'''
Deallocate caller state after a remote startup rejection.
@ -427,7 +439,7 @@ async def test_start_module_error_cleans_context(
'''
async with tractor.open_nursery() as an:
actor = tractor.current_actor()
actor: Actor = tractor.current_actor()
portal: tractor.Portal = await an.start_actor(
'module_error_worker',
)