183 lines · python
1"""2Test lldb-dap setBreakpoints request3"""4 5import dap_server6import lldbdap_testcase7from lldbsuite.test import lldbutil8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10 11 12def get_subprocess(root_process, process_name):13 queue = [root_process]14 while queue:15 process = queue.pop()16 if process.name() == process_name:17 return process18 queue.extend(process.children())19 20 self.assertTrue(False, "No subprocess with name %s found" % process_name)21 22 23class TestDAP_console(lldbdap_testcase.DAPTestCaseBase):24 def check_lldb_command(25 self, lldb_command, contains_string, assert_msg, command_escape_prefix="`"26 ):27 response = self.dap_server.request_evaluate(28 f"{command_escape_prefix}{lldb_command}", context="repl"29 )30 output = response["body"]["result"]31 self.assertIn(32 contains_string,33 output,34 (35 """Verify %s by checking the command output:\n"""36 """'''\n%s'''\nfor the string: "%s" """37 % (assert_msg, output, contains_string)38 ),39 )40 41 def test_scopes_variables_setVariable_evaluate(self):42 """43 Tests that the "scopes" request causes the currently selected44 thread and frame to be updated. There are no DAP packets that tell45 lldb-dap which thread and frame are selected other than the46 "scopes" request. lldb-dap will now select the thread and frame47 for the latest "scopes" request that it receives.48 49 The LLDB command interpreter needs to have the right thread and50 frame selected so that commands executed in the debug console act51 on the right scope. This applies both to the expressions that are52 evaluated and the lldb commands that start with the backtick53 character.54 """55 program = self.getBuildArtifact("a.out")56 self.build_and_launch(program)57 source = "main.cpp"58 breakpoint1_line = line_number(source, "// breakpoint 1")59 lines = [breakpoint1_line]60 # Set breakpoint in the thread function so we can step the threads61 breakpoint_ids = self.set_source_breakpoints(source, lines)62 self.assertEqual(63 len(breakpoint_ids), len(lines), "expect correct number of breakpoints"64 )65 self.continue_to_breakpoints(breakpoint_ids)66 # Cause a "scopes" to be sent for frame zero which should update the67 # selected thread and frame to frame 0.68 self.dap_server.get_local_variables(frameIndex=0)69 70 # Verify frame #0 is selected in the command interpreter by running71 # the "frame select" command with no frame index which will print the72 # currently selected frame.73 self.check_lldb_command("frame select", "frame #0", "frame 0 is selected")74 75 # Cause a "scopes" to be sent for frame one which should update the76 # selected thread and frame to frame 1.77 self.dap_server.get_local_variables(frameIndex=1)78 79 # Verify frame #1 is selected in the command interpreter by running80 # the "frame select" command with no frame index which will print the81 # currently selected frame.82 self.check_lldb_command("frame select", "frame #1", "frame 1 is selected")83 84 def test_custom_escape_prefix(self):85 program = self.getBuildArtifact("a.out")86 self.build_and_launch(program, commandEscapePrefix="::")87 source = "main.cpp"88 breakpoint1_line = line_number(source, "// breakpoint 1")89 breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line])90 self.continue_to_breakpoints(breakpoint_ids)91 92 self.check_lldb_command(93 "help",94 "For more information on any command",95 "Help can be invoked",96 command_escape_prefix="::",97 )98 99 def test_empty_escape_prefix(self):100 program = self.getBuildArtifact("a.out")101 self.build_and_launch(program, commandEscapePrefix="")102 source = "main.cpp"103 breakpoint1_line = line_number(source, "// breakpoint 1")104 breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line])105 self.continue_to_breakpoints(breakpoint_ids)106 107 self.check_lldb_command(108 "help",109 "For more information on any command",110 "Help can be invoked",111 command_escape_prefix="",112 )113 114 @skipIfWindows115 def test_exit_status_message_sigterm(self):116 source = "main.cpp"117 program = self.getBuildArtifact("a.out")118 self.build_and_launch(program, commandEscapePrefix="")119 breakpoint1_line = line_number(source, "// breakpoint 1")120 breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line])121 self.continue_to_breakpoints(breakpoint_ids)122 123 # Kill lldb-server process.124 process_name = (125 "debugserver" if platform.system() in ["Darwin"] else "lldb-server"126 )127 128 try:129 import psutil130 except ImportError:131 print(132 "psutil not installed, please install using 'pip install psutil'. "133 "Skipping test_exit_status_message_sigterm test.",134 file=sys.stderr,135 )136 return137 process = get_subprocess(psutil.Process(os.getpid()), process_name)138 process.terminate()139 process.wait()140 141 # Get the console output142 console_output = self.collect_console(pattern="exited with status")143 144 # Verify the exit status message is printed.145 self.assertRegex(146 console_output,147 ".*exited with status = -1 .* died with signal SIGTERM.*",148 "Exit status does not contain message 'exited with status'",149 )150 151 def test_exit_status_message_ok(self):152 program = self.getBuildArtifact("a.out")153 self.build_and_launch(program, commandEscapePrefix="")154 self.continue_to_exit()155 156 # Get the console output157 console_output = self.collect_console(pattern="exited with status")158 159 # Verify the exit status message is printed.160 self.assertIn(161 "exited with status = 0 (0x00000000)",162 console_output,163 "Exit status does not contain message 'exited with status'",164 )165 166 def test_diagnositcs(self):167 program = self.getBuildArtifact("a.out")168 self.build_and_launch(program)169 170 core = self.getBuildArtifact("minidump.core")171 self.yaml2obj("minidump.yaml", core)172 self.dap_server.request_evaluate(173 f"target create --core {core}", context="repl"174 )175 176 diagnostics = self.collect_important(pattern="minidump file")177 178 self.assertIn(179 "warning: unable to retrieve process ID from minidump file",180 diagnostics,181 "diagnostic found in important output",182 )183