Add initial subactor debug tests

debug_tests
Tyler Goodlet 2020-10-04 09:54:36 -04:00
parent 9067bb2a41
commit 73a32f7d9c
3 changed files with 128 additions and 13 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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