Add initial subactor debug tests
parent
9067bb2a41
commit
73a32f7d9c
|
@ -0,0 +1,25 @@
|
||||||
|
import trio
|
||||||
|
import tractor
|
||||||
|
|
||||||
|
|
||||||
|
async def breakpoint_forever():
|
||||||
|
"""Indefinitely re-enter debugger in child actor.
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
await trio.sleep(0.1)
|
||||||
|
await tractor.breakpoint()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
|
||||||
|
async with tractor.open_nursery() as n:
|
||||||
|
|
||||||
|
portal = await n.run_in_actor(
|
||||||
|
'breakpoint_forever',
|
||||||
|
breakpoint_forever,
|
||||||
|
)
|
||||||
|
await portal.result()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
tractor.run(main, debug_mode=True)
|
|
@ -0,0 +1,16 @@
|
||||||
|
import tractor
|
||||||
|
|
||||||
|
|
||||||
|
async def name_error():
|
||||||
|
getattr(doggypants)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async with tractor.open_nursery() as n:
|
||||||
|
|
||||||
|
portal = await n.run_in_actor('name_error', name_error)
|
||||||
|
await portal.result()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
tractor.run(main, debug_mode=True)
|
|
@ -24,15 +24,20 @@ def mk_cmd(ex_name: str) -> str:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
def spawn(
|
def spawn(
|
||||||
cmd: str,
|
|
||||||
testdir,
|
testdir,
|
||||||
|
arb_addr,
|
||||||
) -> pexpect.spawn:
|
) -> pexpect.spawn:
|
||||||
|
|
||||||
|
def _spawn(cmd):
|
||||||
return testdir.spawn(
|
return testdir.spawn(
|
||||||
cmd=mk_cmd(cmd),
|
cmd=mk_cmd(cmd),
|
||||||
expect_timeout=3,
|
expect_timeout=3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return _spawn
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'user_in_out',
|
'user_in_out',
|
||||||
|
@ -42,12 +47,12 @@ def spawn(
|
||||||
],
|
],
|
||||||
ids=lambda item: item[1],
|
ids=lambda item: item[1],
|
||||||
)
|
)
|
||||||
def test_root_actor_error(testdir, user_in_out):
|
def test_root_actor_error(spawn, user_in_out):
|
||||||
"""Demonstrate crash handler entering pdbpp from basic error in root actor.
|
"""Demonstrate crash handler entering pdbpp from basic error in root actor.
|
||||||
"""
|
"""
|
||||||
user_input, expect_err_str = user_in_out
|
user_input, expect_err_str = user_in_out
|
||||||
|
|
||||||
child = spawn('root_actor_error', testdir)
|
child = spawn('root_actor_error')
|
||||||
|
|
||||||
# scan for the pdbpp prompt
|
# scan for the pdbpp prompt
|
||||||
child.expect("\(Pdb\+\+\)")
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
@ -74,11 +79,11 @@ def test_root_actor_error(testdir, user_in_out):
|
||||||
],
|
],
|
||||||
ids=lambda item: f'{item[0]} -> {item[1]}',
|
ids=lambda item: f'{item[0]} -> {item[1]}',
|
||||||
)
|
)
|
||||||
def test_root_actor_bp(testdir, user_in_out):
|
def test_root_actor_bp(spawn, user_in_out):
|
||||||
"""Demonstrate breakpoint from in root actor.
|
"""Demonstrate breakpoint from in root actor.
|
||||||
"""
|
"""
|
||||||
user_input, expect_err_str = user_in_out
|
user_input, expect_err_str = user_in_out
|
||||||
child = spawn('root_actor_breakpoint', testdir)
|
child = spawn('root_actor_breakpoint')
|
||||||
|
|
||||||
# scan for the pdbpp prompt
|
# scan for the pdbpp prompt
|
||||||
child.expect("\(Pdb\+\+\)")
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
@ -98,9 +103,78 @@ def test_root_actor_bp(testdir, user_in_out):
|
||||||
assert expect_err_str in str(child.before)
|
assert expect_err_str in str(child.before)
|
||||||
|
|
||||||
|
|
||||||
def test_subactor_error(testdir):
|
def test_subactor_error(spawn):
|
||||||
...
|
child = spawn('subactor_error')
|
||||||
|
|
||||||
|
# scan for the pdbpp prompt
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
|
||||||
|
before = str(child.before.decode())
|
||||||
|
assert "Attaching to pdb in crashed actor: ('name_error'" in before
|
||||||
|
|
||||||
|
# send user command
|
||||||
|
# (in this case it's the same for 'continue' vs. 'quit')
|
||||||
|
child.sendline('continue')
|
||||||
|
child.expect('\r\n')
|
||||||
|
|
||||||
|
# the debugger should enter a second time in the nursery
|
||||||
|
# creating actor
|
||||||
|
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
|
||||||
|
before = str(child.before.decode())
|
||||||
|
|
||||||
|
# root actor gets debugger engaged
|
||||||
|
assert "Attaching to pdb in crashed actor: ('arbiter'" in before
|
||||||
|
|
||||||
|
# error is a remote error propagated from the subactor
|
||||||
|
assert "RemoteActorError: ('name_error'" in before
|
||||||
|
|
||||||
|
child.sendline('c')
|
||||||
|
child.expect('\r\n')
|
||||||
|
|
||||||
|
# process should exit
|
||||||
|
child.expect(pexpect.EOF)
|
||||||
|
|
||||||
|
|
||||||
def test_subactor_breakpoint(testdir):
|
def test_subactor_breakpoint(spawn):
|
||||||
...
|
child = spawn('subactor_breakpoint')
|
||||||
|
|
||||||
|
# scan for the pdbpp prompt
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
|
||||||
|
before = str(child.before.decode())
|
||||||
|
assert "Attaching pdb to actor: ('breakpoint_forever'" in before
|
||||||
|
|
||||||
|
# do some "next" commands to demonstrate recurrent breakpoint
|
||||||
|
# entries
|
||||||
|
for _ in range(10):
|
||||||
|
child.sendline('next')
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
|
||||||
|
# now run some "continues" to show re-entries
|
||||||
|
for _ in range(5):
|
||||||
|
child.sendline('continue')
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
before = str(child.before.decode())
|
||||||
|
assert "Attaching pdb to actor: ('breakpoint_forever'" in before
|
||||||
|
|
||||||
|
# finally quit the loop
|
||||||
|
child.sendline('q')
|
||||||
|
|
||||||
|
# child process should exit but parent will capture pdb.BdbQuit
|
||||||
|
child.expect("\(Pdb\+\+\)")
|
||||||
|
|
||||||
|
before = str(child.before.decode())
|
||||||
|
assert "RemoteActorError: ('breakpoint_forever'" in before
|
||||||
|
assert 'bdb.BdbQuit' in before
|
||||||
|
|
||||||
|
# quit the parent
|
||||||
|
child.sendline('c')
|
||||||
|
|
||||||
|
# process should exit
|
||||||
|
child.expect(pexpect.EOF)
|
||||||
|
|
||||||
|
before = str(child.before.decode())
|
||||||
|
assert "RemoteActorError: ('breakpoint_forever'" in before
|
||||||
|
assert 'bdb.BdbQuit' in before
|
||||||
|
|
Loading…
Reference in New Issue