Author: Ebuka Ezike Date: 2026-07-22T11:32:15+01:00 New Revision: 4bb9022f545ceb2b01789bd86d29da495449351b
URL: https://github.com/llvm/llvm-project/commit/4bb9022f545ceb2b01789bd86d29da495449351b DIFF: https://github.com/llvm/llvm-project/commit/4bb9022f545ceb2b01789bd86d29da495449351b.diff LOG: [lldb-dap] Migrate breakpointAssembly and instructionBreakpoint test (#211054) Added: Modified: lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py Removed: ################################################################################ diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py index cbbea9ea9540b..9bc3d989ca4f6 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py @@ -2,162 +2,116 @@ Test lldb-dap setBreakpoints request in assembly source references. """ -from lldbsuite.test.decorators import * -from dap_server import Source -import lldbdap_testcase +from lldbsuite.test.decorators import skipIfWindows +from lldbsuite.test.tools.lldb_dap.types import LaunchArgs +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase -class TestDAP_setBreakpointsAssembly(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_setBreakpointsAssembly(DAPTestCaseBase): # When using PDB, we need to have debug information to break on assembly_func, # but this test relies on us not having debug information for that function. @skipIfWindows def test_can_break_in_source_references(self): """Tests hitting assembly source breakpoints""" program = self.getBuildArtifact("a.out") - self.build_and_launch(program) - - assmebly_func_breakpoints = self.set_function_breakpoints(["assembly_func"]) - self.continue_to_breakpoints(assmebly_func_breakpoints) - - assembly_func_frame = self.get_stackFrames()[0] - self.assertIn( - "sourceReference", - assembly_func_frame.get("source"), - "Expected assembly source frame", + session = self.build_and_create_session() + with session.configure(LaunchArgs(program)) as ctx: + [assembly_func_id] = session.resolve_function_breakpoints(["assembly_func"]) + stop_event = session.verify_stopped_on_breakpoint( + assembly_func_id, after=ctx.process_event ) - line = assembly_func_frame["line"] + top_frame = session.top_frame_from(stop_event).frame + source_reference = self.expect_not_none( + top_frame.source and top_frame.source.sourceReference, + "expected an assembly source reference", + ) - # Set an assembly breakpoint in the next line and check that it's hit - source_reference = assembly_func_frame["source"]["sourceReference"] - assembly_breakpoint_ids = self.set_source_breakpoints_assembly( - source_reference, [line + 1] + # Set an assembly breakpoint on the next line and check that it's hit. + asm_bp_response = session.set_assembly_breakpoints( + source_reference, [top_frame.line + 1] ) - self.continue_to_breakpoints(assembly_breakpoint_ids) + [asm_bp_id] = session.breakpoints_to_ids(asm_bp_response.body.breakpoints) + session.continue_to_breakpoint(asm_bp_id) - # Continue again and verify it hits in the next function call - self.continue_to_breakpoints(assmebly_func_breakpoints) - self.continue_to_breakpoints(assembly_breakpoint_ids) + # Continue again and verify it hits in the next function call. + session.continue_to_breakpoint(assembly_func_id) + session.continue_to_breakpoint(asm_bp_id) - # Clear the breakpoint and then check that the assembly breakpoint does not hit next time - self.set_source_breakpoints_assembly(source_reference, []) - self.continue_to_breakpoints(assmebly_func_breakpoints) - self.continue_to_exit() + # Clear the assembly breakpoint and verify it does not hit again. + session.set_assembly_breakpoints(source_reference, []) + session.continue_to_breakpoint(assembly_func_id) + session.continue_to_exit() def test_break_on_invalid_source_reference(self): - """Tests hitting assembly source breakpoints""" + """Tests setting breakpoints on invalid source references fails cleanly.""" program = self.getBuildArtifact("a.out") - self.build_and_launch(program) - - # Verify that setting a breakpoint on an invalid source reference fails - response = self.dap_server.request_setBreakpoints( - Source.build(source_reference=-1), [1] - ) - self.assertIsNotNone(response) - breakpoints = response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 1) - breakpoint = breakpoints[0] - self.assertFalse( - breakpoint["verified"], "Expected breakpoint to not be verified" - ) - self.assertIn("message", breakpoint, "Expected message to be present") - self.assertEqual( - breakpoint["message"], - "Invalid sourceReference.", - ) + session = self.build_and_create_session() + session.launch(LaunchArgs(program)) - # Verify that setting a breakpoint on a source reference that is not created fails - response = self.dap_server.request_setBreakpoints( - Source.build(source_reference=200), [1] - ) - self.assertIsNotNone(response) - breakpoints = response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 1) - break_point = breakpoints[0] - self.assertFalse( - break_point["verified"], "Expected breakpoint to not be verified" - ) - self.assertIn("message", break_point, "Expected message to be present") - self.assertEqual( - break_point["message"], - "Invalid sourceReference.", - ) + # Verify that setting a breakpoint on an invalid source reference or + # a source reference not created fails. + for bad_ref in (-1, 200): + response = session.set_assembly_breakpoints(bad_ref, [1]) + [bp] = response.body.breakpoints + self.assertFalse(bp.verified, "expected breakpoint to not be verified") + self.assertEqual(bp.message, "Invalid sourceReference.") @skipIfWindows def test_persistent_assembly_breakpoint(self): - """Tests that assembly breakpoints are working persistently across sessions""" + """Tests that assembly breakpoints persist across sessions.""" self.build() program = self.getBuildArtifact("a.out") - self.create_debug_adapter() - - # Run the first session and set a persistent assembly breakpoint - try: - self.dap_server.request_initialize() - self.dap_server.request_launch(program) - self.dap_server.wait_for_event(["initialized"]) - - assembly_func_breakpoints = self.set_function_breakpoints(["assembly_func"]) - self.continue_to_breakpoints(assembly_func_breakpoints) - assembly_func_frame = self.get_stackFrames()[0] - source_reference = assembly_func_frame["source"]["sourceReference"] - - # Set an assembly breakpoint in the middle of the assembly function - persistent_breakpoint_line = 4 - persistent_breakpoint_ids = self.set_source_breakpoints_assembly( - source_reference, [persistent_breakpoint_line] - ) + # Session 1: set the persistent assembly breakpoint. + session = self.create_session(disconnect_automatically=False) + with session.configure(LaunchArgs(program)) as ctx: + function_bp_ids = session.resolve_function_breakpoints(["assembly_func"]) + stop_event = session.verify_stopped_on_breakpoint( + function_bp_ids, after=ctx.process_event + ) - self.assertEqual( - len(persistent_breakpoint_ids), - 1, - "Expected one assembly breakpoint to be set", - ) + top_frame = session.top_frame_from(stop_event).frame + source = self.expect_not_none(top_frame.source) + source_reference = self.expect_not_none(source.sourceReference) - persistent_breakpoint_source = self.dap_server.resolved_breakpoints[ - persistent_breakpoint_ids[0] - ]["source"] - self.assertIn( - "adapterData", - persistent_breakpoint_source, - "Expected assembly breakpoint to have persistent information", - ) - self.assertIn( - "persistenceData", - persistent_breakpoint_source["adapterData"], - "Expected assembly breakpoint to have persistent information", - ) + persistent_breakpoint_line = 4 + response = session.set_assembly_breakpoints( + source_reference, [persistent_breakpoint_line] + ) + [persistent_bp] = response.body.breakpoints + persistent_source = self.expect_not_none( + persistent_bp.source, "expected resolved breakpoint to carry a source" + ) + adapter_data = self.expect_not_none( + persistent_source.adapterData, + "expected assembly breakpoint to carry persistence info", + ) + self.assertIn( + "persistenceData", + adapter_data, + "expected adapterData to include persistenceData", + ) - self.continue_to_breakpoints(persistent_breakpoint_ids) - finally: - self.dap_server.request_disconnect(terminateDebuggee=True) - self.dap_server.terminate() - - # Restart the session and verify the breakpoint is still there - self.create_debug_adapter() - try: - self.dap_server.request_initialize() - self.dap_server.request_launch(program) - self.dap_server.wait_for_event(["initialized"]) - - new_session_breakpoints_ids = self.set_source_breakpoints_from_source( - Source(persistent_breakpoint_source), - [persistent_breakpoint_line], - ) + session.continue_to_breakpoint(self.expect_not_none(persistent_bp.id)) + session.disconnect(terminateDebuggee=True) + session.stop() - self.assertEqual( - len(new_session_breakpoints_ids), - 1, - "Expected one breakpoint to be set in the new session", + # Session 2: replay the persisted source and verify the breakpoint hits. + adapter = self.create_stdio_debug_adapter() + session2 = self.create_session(adapter=adapter) + with session2.configure(LaunchArgs(program)) as ctx: + response = session2.set_assembly_breakpoints( + persistent_source, [persistent_breakpoint_line] ) + [new_bp_id] = session2.breakpoints_to_ids(response.body.breakpoints) - self.continue_to_breakpoints(new_session_breakpoints_ids) - current_line = self.get_stackFrames()[0]["line"] - self.assertEqual( - current_line, - persistent_breakpoint_line, - "Expected to hit the persistent assembly breakpoint at the same line", - ) - finally: - self.dap_server.request_disconnect(terminateDebuggee=True) - self.dap_server.terminate() + stop_event = session2.verify_stopped_on_breakpoint( + new_bp_id, after=ctx.process_event + ) + top_frame = session2.top_frame_from(stop_event).frame + self.assertEqual( + top_frame.line, + persistent_breakpoint_line, + "expected to hit the persistent assembly breakpoint at the same line", + ) diff --git a/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py b/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py index 8bb9ea2be5a9f..9438871bd6764 100644 --- a/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py +++ b/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py @@ -1,99 +1,79 @@ -from dap_server import Source -import shutil -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil -import lldbdap_testcase -import os -import lldb +""" +Test lldb-dap instruction breakpoints. +""" +import os -class TestDAP_InstructionBreakpointTestCase(lldbdap_testcase.DAPTestCaseBase): - NO_DEBUG_INFO_TESTCASE = True +from lldbsuite.test.decorators import skipIfWindows +from lldbsuite.test.lldbtest import line_number +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.types import LaunchArgs - def setUp(self): - lldbdap_testcase.DAPTestCaseBase.setUp(self) - self.main_basename = "main-copy.cpp" - self.main_path = os.path.realpath(self.getBuildArtifact(self.main_basename)) +class TestDAP_InstructionBreakpointTestCase(DAPTestCaseBase): + NO_DEBUG_INFO_TESTCASE = True @skipIfWindows def test_instruction_breakpoint(self): - self.build() - self.instruction_breakpoint_test() - - def instruction_breakpoint_test(self): - """Sample test to ensure SBFrame::Disassemble produces SOME output""" - # Create a target by the debugger. - target = self.createTestTarget() + """Set a source breakpoint, then use the disassembly to set an + instruction breakpoint on the next instruction and verify we hit it.""" + program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() + main_basename = "main-copy.cpp" + main_path = os.path.realpath(self.getBuildArtifact(main_basename)) main_line = line_number("main.cpp", "breakpoint 1") - program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + # Set a source breakpoint and check it was resolved against the + # renamed source file. + with session.configure(LaunchArgs(program)) as ctx: + response = session.set_source_breakpoints(main_path, [main_line]) + [source_bp] = response.body.breakpoints + self.assertTrue(source_bp.verified, "breakpoint is not verified") + self.assertEqual(source_bp.line, main_line, "incorrect breakpoint line") - # Set source breakpoint 1 - response = self.dap_server.request_setBreakpoints( - Source.build(path=self.main_path), [main_line] - ) - breakpoints = response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 1) - breakpoint = breakpoints[0] - self.assertEqual( - breakpoint["line"], main_line, "incorrect breakpoint source line" - ) - self.assertTrue(breakpoint["verified"], "breakpoint is not verified") - self.assertEqual( - self.main_basename, breakpoint["source"]["name"], "incorrect source name" - ) - self.assertEqual( - self.main_path, breakpoint["source"]["path"], "incorrect source file path" - ) - other_breakpoint_id = breakpoint["id"] + bp_source = self.expect_not_none(source_bp.source) + self.assertEqual(bp_source.name, main_basename, "incorrect source name") + self.assertEqual(bp_source.path, main_path, "incorrect source path") - # Continue and then verifiy the breakpoint - self.dap_server.request_continue() - self.verify_breakpoint_hit([other_breakpoint_id]) + source_bp_id = self.expect_not_none(source_bp.id) - # now we check the stack trace making sure that we got mapped source paths - frames = self.dap_server.request_stackTrace()["body"]["stackFrames"] - intstructionPointerReference = [] - setIntstructionBreakpoints = [] - intstructionPointerReference.append(frames[0]["instructionPointerReference"]) - self.assertEqual( - frames[0]["source"]["name"], self.main_basename, "incorrect source name" + # Run to the source breakpoint, the stack frame should also report + # the renamed source. + stop_event = session.verify_stopped_on_breakpoint( + source_bp_id, after=ctx.process_event ) + top_frame_ctx = session.top_frame_from(stop_event) + top_frame = top_frame_ctx.frame + + frame_source = self.expect_not_none(top_frame.source) + self.assertEqual(frame_source.name, main_basename, "incorrect source name") + self.assertEqual(frame_source.path, main_path, "incorrect source path") + + # Disassemble at the current PC and use the address of the following + # instruction as an instruction breakpoint target. + disasm = top_frame_ctx.disassemble() + current_inst, next_inst = disasm[0], disasm[1] + self.assertEqual( - frames[0]["source"]["path"], self.main_path, "incorrect source file path" + current_inst.address, + top_frame.instructionPointerReference, + "disassembly does not begin at the current instruction", ) + self.assertGreater(len(next_inst.address), 2) + self.assertNotEqual(next_inst.presentationHint, "invalid") - # Check disassembly view - disassembled_instructions, instruction = self.disassemble(frameIndex=0) + bp_response = session.set_instruction_breakpoints([next_inst.address]) + [inst_bp] = bp_response.body.breakpoints self.assertEqual( - instruction["address"], - intstructionPointerReference[0], - "current breakpoint reference is not in the disaasembly view", + inst_bp.instructionReference, + next_inst.address, + "instruction breakpoint was not resolved to the expected address", ) - # Get next instruction address to set instruction breakpoint - instruction_addr_list = list(disassembled_instructions.keys()) - index = instruction_addr_list.index(intstructionPointerReference[0]) - if len(instruction_addr_list) >= (index + 1): - next_inst_addr = instruction_addr_list[index + 1] - if len(next_inst_addr) > 2: - setIntstructionBreakpoints.append(next_inst_addr) - instruction_breakpoint_response = ( - self.dap_server.request_setInstructionBreakpoints( - setIntstructionBreakpoints - ) - ) - inst_breakpoints = instruction_breakpoint_response["body"][ - "breakpoints" - ] - self.assertEqual( - inst_breakpoints[0]["instructionReference"], - next_inst_addr, - "Instruction breakpoint has not been resolved or failed to relocate the instruction breakpoint", - ) - self.dap_server.request_continue() - self.verify_breakpoint_hit([inst_breakpoints[0]["id"]]) + inst_bp_id = self.expect_not_none(inst_bp.id) + session.continue_to_breakpoint(inst_bp_id) + + session.set_source_breakpoints(main_path, []) + session.set_instruction_breakpoints([]) + session.continue_to_exit(exitCode=3) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
