llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Ebuka Ezike (da-viper) <details> <summary>Changes</summary> Drop the raw line number when matching the expected location. --- Patch is 30.94 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213269.diff 3 Files Affected: - (modified) lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py (+195-214) - (modified) lldb/test/API/tools/lldb-dap/locations/TestDAP_locations.py (+53-67) - (modified) lldb/test/API/tools/lldb-dap/locations/main.cpp (+8-8) ``````````diff diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py index b26618df7800c..225a947674351 100644 --- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py @@ -2,251 +2,232 @@ Test lldb-dap dataBreakpointInfo and setDataBreakpoints requests """ -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -import lldbdap_testcase +from lldbsuite.test.decorators import skipIfWasm, skipIfWindows +from lldbsuite.test.lldbtest import line_number +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.types import DataBreakpoint, LaunchArgs -@skipIfWasm # data breakpoints map to watchpoints -class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase): - def setUp(self): - lldbdap_testcase.DAPTestCaseBase.setUp(self) - self.accessTypes = ["read", "write", "readWrite"] +@skipIfWasm # data breakpoints map to watchpoints. +class TestDAP_setDataBreakpoints(DAPTestCaseBase): + ACCESS_TYPES = ["read", "write", "readWrite"] @skipIfWindows def test_duplicate_start_addresses(self): """Test setDataBreakpoints with multiple watchpoints starting at the same addresses.""" program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + session = self.build_and_create_session() source = "main.cpp" first_loop_break_line = line_number(source, "// first loop breakpoint") - self.set_source_breakpoints(source, [first_loop_break_line]) - self.continue_to_next_stop() - self.dap_server.get_stackFrame() - # Test setting write watchpoint using expressions: &x, arr+2 - response_x = self.dap_server.request_dataBreakpointInfo(0, "&x") - response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "arr+2") - # Test response from dataBreakpointInfo request. - self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes) - self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes) - # The first one should be overwritten by the third one as they start at - # the same address. This is indicated by returning {verified: False} for - # the first one. - dataBreakpoints = [ - {"dataId": response_x["body"]["dataId"], "accessType": "read"}, - {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"}, - {"dataId": response_x["body"]["dataId"], "accessType": "write"}, + with session.configure(LaunchArgs(program)) as ctx: + session.resolve_source_breakpoints(source, [first_loop_break_line]) + stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event) + + # Verify write watchpoints on expressions `&x` and `arr+2`. + top_frame_id = session.top_frame_from(stop_event).frame.id + response_x = session.data_breakpoint_info("&x", 0, top_frame_id) + response_arr_2 = session.data_breakpoint_info("arr+2", 0, top_frame_id) + + x_data_id = self.expect_not_none(response_x.body.dataId) + arr_2_data_id = self.expect_not_none(response_arr_2.body.dataId) + self.assertEqual(x_data_id.split("/")[1], "4") + self.assertEqual(response_x.body.accessTypes, self.ACCESS_TYPES) + self.assertEqual(arr_2_data_id.split("/")[1], "4") + self.assertEqual(response_arr_2.body.accessTypes, self.ACCESS_TYPES) + + # The first breakpoint should be overwritten by the third breakpoint because + # they share the same starting address. The debug adapter indicates this by + # returning a breakpoint that is not verified for the first breakpoint. + data_breakpoints = [ + DataBreakpoint(dataId=x_data_id, accessType="read"), + DataBreakpoint(dataId=arr_2_data_id, accessType="write"), + DataBreakpoint(dataId=x_data_id, accessType="write"), ] - set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) - breakpoints = set_response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 3) - self.assertFalse(breakpoints[0]["verified"]) - self.assertTrue(breakpoints[1]["verified"]) - self.assertTrue(breakpoints[2]["verified"]) - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[2]["id"]]) - x_val = self.dap_server.get_local_variable_value("x") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(x_val, "2") - self.assertEqual(i_val, "1") - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[1]["id"]]) - arr_2 = self.dap_server.get_local_variable_child("arr", "[2]") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(arr_2["value"], "42") - self.assertEqual(i_val, "2") + set_response = session.set_data_breakpoints(data_breakpoints) + [bp_x_read, bp_arr_2, bp_x_write] = set_response.body.breakpoints + self.assertFalse(bp_x_read.verified) + self.assertTrue(bp_arr_2.verified) + self.assertTrue(bp_x_write.verified) + + # Hit the write watchpoint on `x` at i == 1. + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_x_write.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["x"].value, "2") + self.assertEqual(top_frame.locals["i"].value, "1") + + # Hit the write watchpoint on `arr[2]` at i == 2. + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_arr_2.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["arr"]["[2]"].value, "42") + self.assertEqual(top_frame.locals["i"].value, "2") + + session.set_data_breakpoints([]) + session.continue_to_exit() @skipIfWindows def test_expression(self): """Tests setting data breakpoints on expression.""" - program = self.getBuildArtifact("a.out") - self.build_and_launch(program) source = "main.cpp" + program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() first_loop_break_line = line_number(source, "// first loop breakpoint") - self.set_source_breakpoints(source, [first_loop_break_line]) - self.continue_to_next_stop() - self.dap_server.get_stackFrame() - # Test setting write watchpoint using expressions: &x, arr+2 - response_x = self.dap_server.request_dataBreakpointInfo(0, "&x") - response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "arr+2") - # Test response from dataBreakpointInfo request. - self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes) - self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes) - dataBreakpoints = [ - {"dataId": response_x["body"]["dataId"], "accessType": "write"}, - {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"}, + with session.configure(LaunchArgs(program)) as ctx: + session.resolve_source_breakpoints(source, [first_loop_break_line]) + stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event) + + # Verify write watchpoints on expressions `&x` and `arr+2`. + top_frame_id = session.top_frame_from(stop_event).frame.id + response_x = session.data_breakpoint_info("&x", 0, top_frame_id) + response_arr_2 = session.data_breakpoint_info("arr+2", 0, top_frame_id) + + x_data_id = self.expect_not_none(response_x.body.dataId) + arr_2_data_id = self.expect_not_none(response_arr_2.body.dataId) + self.assertEqual(x_data_id.split("/")[1], "4") + self.assertEqual(response_x.body.accessTypes, self.ACCESS_TYPES) + self.assertEqual(arr_2_data_id.split("/")[1], "4") + self.assertEqual(response_arr_2.body.accessTypes, self.ACCESS_TYPES) + + data_breakpoints = [ + DataBreakpoint(dataId=x_data_id, accessType="write"), + DataBreakpoint(dataId=arr_2_data_id, accessType="write"), ] - set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) - breakpoints = set_response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 2) - self.assertTrue(breakpoints[0]["verified"]) - self.assertTrue(breakpoints[1]["verified"]) - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[0]["id"]]) - x_val = self.dap_server.get_local_variable_value("x") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(x_val, "2") - self.assertEqual(i_val, "1") - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[1]["id"]]) - arr_2 = self.dap_server.get_local_variable_child("arr", "[2]") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(arr_2["value"], "42") - self.assertEqual(i_val, "2") + set_response = session.set_data_breakpoints(data_breakpoints) + [bp_x, bp_arr_2] = set_response.body.breakpoints + self.assertTrue(bp_x.verified) + self.assertTrue(bp_arr_2.verified) + + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_x.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["x"].value, "2") + self.assertEqual(top_frame.locals["i"].value, "1") + + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_arr_2.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["arr"]["[2]"].value, "42") + self.assertEqual(top_frame.locals["i"].value, "2") + + session.set_data_breakpoints([]) + session.continue_to_exit() @skipIfWindows def test_functionality(self): """Tests setting data breakpoints on variable.""" - program = self.getBuildArtifact("a.out") - self.build_and_launch(program) source = "main.cpp" + program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() first_loop_break_line = line_number(source, "// first loop breakpoint") - first_bp_ids = self.set_source_breakpoints(source, [first_loop_break_line]) - self.assertEqual(len(first_bp_ids), 1) - self.continue_to_next_stop() - self.dap_server.get_local_variables() - locals_ref = self.get_locals_scope_reference() - self.assertIsNotNone(locals_ref, "Failed to get locals scope reference") - # Test write watchpoints on x, arr[2] - response_x = self.dap_server.request_dataBreakpointInfo(locals_ref, "x") - arr = self.dap_server.get_local_variable("arr") - response_arr_2 = self.dap_server.request_dataBreakpointInfo( - arr["variablesReference"], "[2]" - ) - - # Test response from dataBreakpointInfo request. - self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes) - self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4") - self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes) - dataBreakpoints = [ - {"dataId": response_x["body"]["dataId"], "accessType": "write"}, - {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"}, + with session.configure(LaunchArgs(program)) as ctx: + session.resolve_source_breakpoints(source, [first_loop_break_line]) + stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event) + + top_frame_ctx = session.top_frame_from(stop_event) + frame_id = top_frame_ctx.frame.id + locals_ref = top_frame_ctx.locals.variablesReference + + # Verify write watchpoints on x and arr[2]. + response_x = session.data_breakpoint_info("x", locals_ref, frame_id) + arr = top_frame_ctx.locals["arr"] + arr_var_ref = self.expect_not_none(arr.variablesReference) + response_arr_2 = session.data_breakpoint_info("[2]", arr_var_ref, frame_id) + + x_data_id = self.expect_not_none(response_x.body.dataId) + arr_2_data_id = self.expect_not_none(response_arr_2.body.dataId) + self.assertEqual(x_data_id.split("/")[1], "4") + self.assertEqual(response_x.body.accessTypes, self.ACCESS_TYPES) + self.assertEqual(arr_2_data_id.split("/")[1], "4") + self.assertEqual(response_arr_2.body.accessTypes, self.ACCESS_TYPES) + + data_breakpoints = [ + DataBreakpoint(dataId=x_data_id, accessType="write"), + DataBreakpoint(dataId=arr_2_data_id, accessType="write"), ] - set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) - breakpoints = set_response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 2) - self.assertTrue(breakpoints[0]["verified"]) - self.assertTrue(breakpoints[1]["verified"]) - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[0]["id"]]) - x_val = self.dap_server.get_local_variable_value("x") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(x_val, "2") - self.assertEqual(i_val, "1") - - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[1]["id"]]) - arr_2 = self.dap_server.get_local_variable_child("arr", "[2]") - i_val = self.dap_server.get_local_variable_value("i") - self.assertEqual(arr_2["value"], "42") - self.assertEqual(i_val, "2") - self.dap_server.request_setDataBreakpoint([]) - - # Verify breakpoints are unique. - all_breakpoints = set( - [first_bp_ids[0], breakpoints[0]["id"], breakpoints[1]["id"]] - ) - self.assertEqual( - len(all_breakpoints), 3, f"found breakpoints {all_breakpoints}" - ) + set_response = session.set_data_breakpoints(data_breakpoints) + [bp_x, bp_arr_2] = set_response.body.breakpoints + self.assertTrue(bp_x.verified) + self.assertTrue(bp_arr_2.verified) + + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_x.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["x"].value, "2") + self.assertEqual(top_frame.locals["i"].value, "1") - # Test hit condition + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_arr_2.id)) + top_frame = session.top_frame_from(stop_event) + self.assertEqual(top_frame.locals["arr"]["[2]"].value, "42") + self.assertEqual(top_frame.locals["i"].value, "2") + + session.set_data_breakpoints([]) + + # Verify hit condition: skip past the second-loop breakpoint until `x` + # has been written twice, then verify we stop with x == 3. second_loop_break_line = line_number(source, "// second loop breakpoint") - breakpoint_ids = self.set_source_breakpoints(source, [second_loop_break_line]) - self.continue_to_breakpoints(breakpoint_ids) - dataBreakpoints = [ - { - "dataId": response_x["body"]["dataId"], - "accessType": "write", - "hitCondition": "2", - } - ] - set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) - breakpoints = set_response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 1) - self.assertTrue(breakpoints[0]["verified"]) - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[0]["id"]]) - x_val = self.dap_server.get_local_variable_value("x") - self.assertEqual(x_val, "3") - - # Test condition - dataBreakpoints = [ - { - "dataId": response_x["body"]["dataId"], - "accessType": "write", - "condition": "x==10", - } - ] - set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) - breakpoints = set_response["body"]["breakpoints"] - self.assertEqual(len(breakpoints), 1) - self.assertTrue(breakpoints[0]["verified"]) - self.dap_server.request_continue() - self.verify_breakpoint_hit([breakpoints[0]["id"]]) - x_val = self.dap_server.get_local_variable_value("x") - self.assertEqual(x_val, "10") + breakpoint_ids = session.resolve_source_breakpoints( + source, [second_loop_break_line] + ) + session.continue_to_any_breakpoint(breakpoint_ids) + set_response = session.set_data_breakpoints( + [DataBreakpoint(dataId=x_data_id, accessType="write", hitCondition="2")] + ) + [bp_hit] = set_response.body.breakpoints + self.assertTrue(bp_hit.verified) + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_hit.id)) + self.assertEqual(session.top_frame_from(stop_event).locals["x"].value, "3") + + # Test condition: only stop when the write makes x == 10. + set_response = session.set_data_breakpoints( + [DataBreakpoint(dataId=x_data_id, accessType="write", condition="x==10")] + ) + [bp_cond] = set_response.body.breakpoints + self.assertTrue(bp_cond.verified) + stop_event = session.continue_to_breakpoint(self.expect_not_none(bp_cond.id)) + self.assertEqual(session.top_frame_from(stop_event).locals["x"].value, "10") @skipIfWindows def test_bytes(self): """Tests setting data breakpoints on memory range.""" + source = self.getSourcePath("main.cpp") program = self.getBuildArtifact("a.out") - self.build_and_launch(program) - source = "main.cpp" + session = self.build_and_create_session() first_loop_break_line = line_number(source, "// first loop breakpoint") - self.set_source_breakpoints(source, [first_loop_break_line]) - self.continue_to_next_stop() - # Test write watchpoints on x, arr[2] - x = self.dap_server.get_local_variable("x") - response_x = self.dap_server.request_dataBreakpointInfo( - 0, x["memoryReference"], 4 - ) - arr_2 = self.dap_server.get_local_variable_child("arr", "[2]") - response_arr_2 = self.dap_server.request_dataBreakpointInfo( - 0, arr_2["memoryReference"], 4 + with session.configure(LaunchArgs(program)) as ctx: + session.resolve_source_breakpoints(source, [first_loop_break_line]) + stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event) + + # Set write watchpoints on x and arr[2] using their memory references. + top_frame = session.top_frame_from(stop_event) + x_memory_reference = self.expect_not_none(top_frame.locals["x"].memoryReference) + arr_2_mem_ref = self.expect_not_none( + top_frame.locals["arr"]["[2]"].memoryReference ) - - # Test response from dataBreakpointInfo request. - self.assertEqual( - response_x["body"]["dataId"].split("/"), [x["memoryReference"][2:], "4"] - ) - self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes) - self.assertEqual( - response_arr_2["body"]["dataId"].split("/"), - [arr_2["memoryReference"][2:], "4"], + response_x = session.data_breakpoint_info_as_address(x_memory_reference, 4) + response_arr_2 = session.data_breakpoint_info_as_address(arr_2_mem_ref, 4) + + x_data_id = self.expect_not_none(response_x.body.dataId) + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/213269 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
