Add `open_crash_handler()` / `repl_fixture` suite
Nicely nailing 2 birds by leveraging the new `repl_fixture` support to actually avoid use of a `pexpect`-style test B) Functionality audit summary, - ensures `open_crash_handler() as bxerr:` adheres to, - `raise_on_exit` semantics including only raising from a list of exc-types, - `repl_fixture` setup/teardown invocation and that `yield False` blocks REPL interaction, - delivering a `BoxedMaybeException` with the correct state set post crash. - all the above outside the actor-runtime existing. Also luckily enough, this seems to have found a bug for which a fix is coming right up!main^2
parent
760b9890c4
commit
9ff448faa3
|
@ -14,6 +14,9 @@ TODO:
|
|||
|
||||
'''
|
||||
from __future__ import annotations
|
||||
from contextlib import (
|
||||
contextmanager as cm,
|
||||
)
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
@ -28,6 +31,8 @@ from .conftest import (
|
|||
PROMPT,
|
||||
_pause_msg,
|
||||
)
|
||||
|
||||
import pytest
|
||||
from pexpect.exceptions import (
|
||||
# TIMEOUT,
|
||||
EOF,
|
||||
|
@ -183,3 +188,117 @@ def test_breakpoint_hook_restored(
|
|||
)
|
||||
child.sendline('c')
|
||||
child.expect(EOF)
|
||||
|
||||
|
||||
|
||||
_to_raise = Exception('Triggering a crash')
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'to_raise',
|
||||
[
|
||||
None,
|
||||
_to_raise,
|
||||
RuntimeError('Never crash handle this!'),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
'raise_on_exit',
|
||||
[
|
||||
True,
|
||||
[type(_to_raise)],
|
||||
False,
|
||||
]
|
||||
)
|
||||
def test_crash_handler_cms(
|
||||
debug_mode: bool,
|
||||
to_raise: Exception,
|
||||
raise_on_exit: bool|list[Exception],
|
||||
):
|
||||
'''
|
||||
Verify the `.devx.open_crash_handler()` API(s) by also
|
||||
(conveniently enough) tesing its `repl_fixture: ContextManager`
|
||||
param support which for this suite allows use to avoid use of
|
||||
a `pexpect`-style-test since we use the fixture to avoid actually
|
||||
entering `PdbpREPL.iteract()` :smirk:
|
||||
|
||||
'''
|
||||
import tractor
|
||||
# import trio
|
||||
|
||||
# state flags
|
||||
repl_acquired: bool = False
|
||||
repl_released: bool = False
|
||||
|
||||
@cm
|
||||
def block_repl_ux(
|
||||
repl: tractor.devx.debug.PdbREPL,
|
||||
maybe_bxerr: (
|
||||
tractor.devx._debug.BoxedMaybeException
|
||||
|None
|
||||
) = None,
|
||||
enter_repl: bool = True,
|
||||
|
||||
) -> bool:
|
||||
'''
|
||||
Set pre/post-REPL state vars and bypass actual conole
|
||||
interaction.
|
||||
|
||||
'''
|
||||
nonlocal repl_acquired, repl_released
|
||||
|
||||
# task: trio.Task = trio.lowlevel.current_task()
|
||||
# print(f'pre-REPL active_task={task.name}')
|
||||
|
||||
print('pre-REPL')
|
||||
repl_acquired = True
|
||||
yield False # never actually .interact()
|
||||
print('post-REPL')
|
||||
repl_released = True
|
||||
|
||||
try:
|
||||
# TODO, with runtime's `debug_mode` setting
|
||||
# -[ ] need to open runtime tho obvi..
|
||||
#
|
||||
# with tractor.devx.maybe_open_crash_handler(
|
||||
# pdb=True,
|
||||
|
||||
with tractor.devx.open_crash_handler(
|
||||
raise_on_exit=raise_on_exit,
|
||||
repl_fixture=block_repl_ux
|
||||
) as bxerr:
|
||||
if to_raise is not None:
|
||||
raise to_raise
|
||||
|
||||
except Exception as _exc:
|
||||
exc = _exc
|
||||
if (
|
||||
raise_on_exit is True
|
||||
or
|
||||
type(to_raise) in raise_on_exit
|
||||
):
|
||||
assert (
|
||||
exc
|
||||
is
|
||||
to_raise
|
||||
is
|
||||
bxerr.value
|
||||
)
|
||||
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
assert (
|
||||
to_raise is None
|
||||
or
|
||||
not raise_on_exit
|
||||
or
|
||||
type(to_raise) not in raise_on_exit
|
||||
)
|
||||
assert bxerr.value is to_raise
|
||||
|
||||
assert bxerr.raise_on_exit == raise_on_exit
|
||||
|
||||
if to_raise is not None:
|
||||
assert repl_acquired
|
||||
assert repl_released
|
||||
|
|
Loading…
Reference in New Issue