From b14699d40ba18af58dff9236b55d101bfb9de86a Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Wed, 13 Oct 2021 23:34:25 -0400 Subject: [PATCH] Adjust debugger tests to expect depth > 1 crashes With the new fixes to the trio spawner we can expect that both root *and* depth > 1 nursery owning actors will now not clobber any children that are in debug (either via breakpoint or through crashing). The tests changed now include more checks which ensure the 2nd level parent-ish actors also bubble up through into `pdb` and don't kill any of their (crashed) children before they're done themselves debugging. --- .../debugging/multi_subactor_root_errors.py | 6 +++ tests/test_debugger.py | 52 ++++++++++++++++--- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/examples/debugging/multi_subactor_root_errors.py b/examples/debugging/multi_subactor_root_errors.py index 6c69618..640f222 100644 --- a/examples/debugging/multi_subactor_root_errors.py +++ b/examples/debugging/multi_subactor_root_errors.py @@ -1,3 +1,8 @@ +''' +Test that a nested nursery will avoid clobbering +the debugger latched by a broken child. + +''' import trio import tractor @@ -35,6 +40,7 @@ async def main(): """ async with tractor.open_nursery( debug_mode=True, + # loglevel='cancel', ) as n: # spawn both actors diff --git a/tests/test_debugger.py b/tests/test_debugger.py index 87bce1b..bd1cba6 100644 --- a/tests/test_debugger.py +++ b/tests/test_debugger.py @@ -236,7 +236,8 @@ def test_subactor_breakpoint(spawn): def test_multi_subactors(spawn): - """Multiple subactors, both erroring and breakpointing as well as + """ + Multiple subactors, both erroring and breakpointing as well as a nested subactor erroring. """ child = spawn(r'multi_subactors') @@ -259,6 +260,7 @@ def test_multi_subactors(spawn): # first name_error failure child.expect(r"\(Pdb\+\+\)") before = str(child.before.decode()) + assert "Attaching to pdb in crashed actor: ('name_error'" in before assert "NameError" in before # continue again @@ -267,6 +269,7 @@ def test_multi_subactors(spawn): # 2nd name_error failure child.expect(r"\(Pdb\+\+\)") before = str(child.before.decode()) + assert "Attaching to pdb in crashed actor: ('name_error_1'" in before assert "NameError" in before # breakpoint loop should re-engage @@ -275,6 +278,19 @@ def test_multi_subactors(spawn): before = str(child.before.decode()) assert "Attaching pdb to actor: ('breakpoint_forever'" in before + # wait for spawn error to show up + while 'breakpoint_forever' in before: + child.sendline('c') + child.expect(r"\(Pdb\+\+\)") + before = str(child.before.decode()) + + # 2nd depth nursery should trigger + # child.sendline('c') + # child.expect(r"\(Pdb\+\+\)") + # before = str(child.before.decode()) + assert "Attaching to pdb in crashed actor: ('spawn_error'" in before + assert "RemoteActorError: ('name_error_1'" in before + # now run some "continues" to show re-entries for _ in range(5): child.sendline('c') @@ -284,16 +300,24 @@ def test_multi_subactors(spawn): child.sendline('q') child.expect(r"\(Pdb\+\+\)") before = str(child.before.decode()) + # debugger attaches to root assert "Attaching to pdb in crashed actor: ('root'" in before + # expect a multierror with exceptions for each sub-actor assert "RemoteActorError: ('breakpoint_forever'" in before + assert "RemoteActorError: ('name_error'" in before + assert "RemoteActorError: ('spawn_error'" in before + assert "RemoteActorError: ('name_error_1'" in before assert 'bdb.BdbQuit' in before # process should exit child.sendline('c') child.expect(pexpect.EOF) - + # repeat of previous multierror for final output before = str(child.before.decode()) assert "RemoteActorError: ('breakpoint_forever'" in before + assert "RemoteActorError: ('name_error'" in before + assert "RemoteActorError: ('spawn_error'" in before + assert "RemoteActorError: ('name_error_1'" in before assert 'bdb.BdbQuit' in before @@ -387,16 +411,29 @@ def test_multi_subactors_root_errors(spawn): before = str(child.before.decode()) assert "NameError: name 'doggypants' is not defined" in before - # continue again + # continue again to catch 2nd name error from + # actor 'name_error_1' (which is 2nd depth). child.sendline('c') child.expect(r"\(Pdb\+\+\)") - - # should now get attached in root with assert error before = str(child.before.decode()) + assert "Attaching to pdb in crashed actor: ('name_error_1'" in before + assert "NameError" in before - # should have come just after priot prompt + child.sendline('c') + child.expect(r"\(Pdb\+\+\)") + before = str(child.before.decode()) + assert "Attaching to pdb in crashed actor: ('spawn_error'" in before + # boxed error from previous step + assert "RemoteActorError: ('name_error_1'" in before + assert "NameError" in before + + child.sendline('c') + child.expect(r"\(Pdb\+\+\)") + before = str(child.before.decode()) assert "Attaching to pdb in crashed actor: ('root'" in before - assert "AssertionError" in before + # boxed error from first level failure + assert "RemoteActorError: ('name_error'" in before + assert "NameError" in before # warnings assert we probably don't need # assert "Cancelling nursery in ('spawn_error'," in before @@ -406,6 +443,7 @@ def test_multi_subactors_root_errors(spawn): child.expect(pexpect.EOF) before = str(child.before.decode()) + # error from root actor and root task that created top level nursery assert "AssertionError" in before