146 lines · python
1"""2Test lldb-dap attach commands3"""4 5from lldbsuite.test.decorators import *6from lldbsuite.test.lldbtest import *7from lldbsuite.test import lldbutil8import lldbdap_testcase9import time10 11 12class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase):13 @skipIfNetBSD # Hangs on NetBSD as well14 def test_commands(self):15 """16 Tests the "initCommands", "preRunCommands", "stopCommands",17 "exitCommands", "terminateCommands" and "attachCommands"18 that can be passed during attach.19 20 "initCommands" are a list of LLDB commands that get executed21 before the target is created.22 "preRunCommands" are a list of LLDB commands that get executed23 after the target has been created and before the launch.24 "stopCommands" are a list of LLDB commands that get executed each25 time the program stops.26 "exitCommands" are a list of LLDB commands that get executed when27 the process exits28 "attachCommands" are a list of LLDB commands that get executed and29 must have a valid process in the selected target in LLDB after30 they are done executing. This allows custom commands to create any31 kind of debug session.32 "terminateCommands" are a list of LLDB commands that get executed when33 the debugger session terminates.34 """35 program = self.build_and_create_debug_adapter_for_attach()36 37 # Here we just create a target and launch the process as a way to test38 # if we are able to use attach commands to create any kind of a target39 # and use it for debugging40 attachCommands = [41 'target create -d "%s"' % (program),42 "process launch --stop-at-entry",43 ]44 initCommands = ["target list", "platform list"]45 preRunCommands = ["image list a.out", "image dump sections a.out"]46 postRunCommands = ["help trace", "help process trace"]47 stopCommands = ["frame variable", "thread backtrace"]48 exitCommands = ["expr 2+3", "expr 3+4"]49 terminateCommands = ["expr 4+2"]50 self.attach(51 program=program,52 attachCommands=attachCommands,53 initCommands=initCommands,54 preRunCommands=preRunCommands,55 stopCommands=stopCommands,56 exitCommands=exitCommands,57 terminateCommands=terminateCommands,58 postRunCommands=postRunCommands,59 )60 # Get output from the console. This should contain both the61 # "initCommands" and the "preRunCommands".62 output = self.get_console()63 # Verify all "initCommands" were found in console output64 self.verify_commands("initCommands", output, initCommands)65 # Verify all "preRunCommands" were found in console output66 self.verify_commands("preRunCommands", output, preRunCommands)67 # Verify all "postRunCommands" were found in console output68 self.verify_commands("postRunCommands", output, postRunCommands)69 70 functions = ["main"]71 breakpoint_ids = self.set_function_breakpoints(functions)72 self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")73 self.continue_to_breakpoints(breakpoint_ids)74 output = self.collect_console(pattern=stopCommands[-1])75 self.verify_commands("stopCommands", output, stopCommands)76 77 # Continue after launch and hit the "pause()" call and stop the target.78 # Get output from the console. This should contain both the79 # "stopCommands" that were run after we stop.80 self.do_continue()81 time.sleep(0.5)82 self.dap_server.request_pause()83 self.dap_server.wait_for_stopped()84 output = self.collect_console(pattern=stopCommands[-1])85 self.verify_commands("stopCommands", output, stopCommands)86 87 # Continue until the program exits88 self.continue_to_exit()89 # Get output from the console. This should contain both the90 # "exitCommands" that were run after the second breakpoint was hit91 # and the "terminateCommands" due to the debugging session ending92 output = self.collect_console(93 pattern=terminateCommands[0],94 )95 self.verify_commands("exitCommands", output, exitCommands)96 self.verify_commands("terminateCommands", output, terminateCommands)97 98 def test_attach_command_process_failures(self):99 """100 Tests that a 'attachCommands' is expected to leave the debugger's101 selected target with a valid process.102 """103 program = self.build_and_create_debug_adapter_for_attach()104 attachCommands = ['script print("oops, forgot to attach to a process...")']105 resp = self.attach(106 program=program,107 attachCommands=attachCommands,108 expectFailure=True,109 )110 self.assertFalse(resp["success"])111 self.assertIn(112 "attachCommands failed to attach to a process",113 resp["body"]["error"]["format"],114 )115 116 @skipIfNetBSD # Hangs on NetBSD as well117 def test_terminate_commands(self):118 """119 Tests that the "terminateCommands", that can be passed during120 attach, are run when the debugger is disconnected.121 """122 program = self.build_and_create_debug_adapter_for_attach()123 124 # Here we just create a target and launch the process as a way to test125 # if we are able to use attach commands to create any kind of a target126 # and use it for debugging127 attachCommands = [128 'target create -d "%s"' % (program),129 "process launch --stop-at-entry",130 ]131 terminateCommands = ["expr 4+2"]132 self.attach(133 program=program,134 attachCommands=attachCommands,135 terminateCommands=terminateCommands,136 disconnectAutomatically=False,137 )138 self.get_console()139 # Once it's disconnected the console should contain the140 # "terminateCommands"141 self.dap_server.request_disconnect(terminateDebuggee=True)142 output = self.collect_console(143 pattern=terminateCommands[0],144 )145 self.verify_commands("terminateCommands", output, terminateCommands)146