xref: /llvm-project/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py (revision fa6377119c0624773cb698935692d46843e9f6ec)
1"""
2Test lldb-dap dataBreakpointInfo and setDataBreakpoints requests
3"""
4
5from lldbsuite.test.decorators import *
6from lldbsuite.test.lldbtest import *
7import lldbdap_testcase
8
9
10class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
11    def setUp(self):
12        lldbdap_testcase.DAPTestCaseBase.setUp(self)
13        self.accessTypes = ["read", "write", "readWrite"]
14
15    @skipIfWindows
16    def test_duplicate_start_addresses(self):
17        """Test setDataBreakpoints with multiple watchpoints starting at the same addresses."""
18        program = self.getBuildArtifact("a.out")
19        self.build_and_launch(program)
20        source = "main.cpp"
21        first_loop_break_line = line_number(source, "// first loop breakpoint")
22        self.set_source_breakpoints(source, [first_loop_break_line])
23        self.continue_to_next_stop()
24        self.dap_server.get_stackFrame()
25        # Test setting write watchpoint using expressions: &x, arr+2
26        response_x = self.dap_server.request_dataBreakpointInfo(0, "&x")
27        response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "arr+2")
28        # Test response from dataBreakpointInfo request.
29        self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4")
30        self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes)
31        self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4")
32        self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes)
33        # The first one should be overwritten by the third one as they start at
34        # the same address. This is indicated by returning {verified: False} for
35        # the first one.
36        dataBreakpoints = [
37            {"dataId": response_x["body"]["dataId"], "accessType": "read"},
38            {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
39            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
40        ]
41        set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
42        self.assertEqual(
43            set_response["body"]["breakpoints"],
44            [{"verified": False}, {"verified": True}, {"verified": True}],
45        )
46
47        self.continue_to_next_stop()
48        x_val = self.dap_server.get_local_variable_value("x")
49        i_val = self.dap_server.get_local_variable_value("i")
50        self.assertEqual(x_val, "2")
51        self.assertEqual(i_val, "1")
52
53        self.continue_to_next_stop()
54        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
55        i_val = self.dap_server.get_local_variable_value("i")
56        self.assertEqual(arr_2["value"], "42")
57        self.assertEqual(i_val, "2")
58
59    @skipIfWindows
60    def test_expression(self):
61        """Tests setting data breakpoints on expression."""
62        program = self.getBuildArtifact("a.out")
63        self.build_and_launch(program)
64        source = "main.cpp"
65        first_loop_break_line = line_number(source, "// first loop breakpoint")
66        self.set_source_breakpoints(source, [first_loop_break_line])
67        self.continue_to_next_stop()
68        self.dap_server.get_stackFrame()
69        # Test setting write watchpoint using expressions: &x, arr+2
70        response_x = self.dap_server.request_dataBreakpointInfo(0, "&x")
71        response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "arr+2")
72        # Test response from dataBreakpointInfo request.
73        self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4")
74        self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes)
75        self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4")
76        self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes)
77        dataBreakpoints = [
78            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
79            {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
80        ]
81        set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
82        self.assertEqual(
83            set_response["body"]["breakpoints"],
84            [{"verified": True}, {"verified": True}],
85        )
86
87        self.continue_to_next_stop()
88        x_val = self.dap_server.get_local_variable_value("x")
89        i_val = self.dap_server.get_local_variable_value("i")
90        self.assertEqual(x_val, "2")
91        self.assertEqual(i_val, "1")
92
93        self.continue_to_next_stop()
94        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
95        i_val = self.dap_server.get_local_variable_value("i")
96        self.assertEqual(arr_2["value"], "42")
97        self.assertEqual(i_val, "2")
98
99    @skipIfWindows
100    def test_functionality(self):
101        """Tests setting data breakpoints on variable."""
102        program = self.getBuildArtifact("a.out")
103        self.build_and_launch(program)
104        source = "main.cpp"
105        first_loop_break_line = line_number(source, "// first loop breakpoint")
106        self.set_source_breakpoints(source, [first_loop_break_line])
107        self.continue_to_next_stop()
108        self.dap_server.get_local_variables()
109        # Test write watchpoints on x, arr[2]
110        response_x = self.dap_server.request_dataBreakpointInfo(1, "x")
111        arr = self.dap_server.get_local_variable("arr")
112        response_arr_2 = self.dap_server.request_dataBreakpointInfo(
113            arr["variablesReference"], "[2]"
114        )
115
116        # Test response from dataBreakpointInfo request.
117        self.assertEqual(response_x["body"]["dataId"].split("/")[1], "4")
118        self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes)
119        self.assertEqual(response_arr_2["body"]["dataId"].split("/")[1], "4")
120        self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes)
121        dataBreakpoints = [
122            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
123            {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
124        ]
125        set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
126        self.assertEqual(
127            set_response["body"]["breakpoints"],
128            [{"verified": True}, {"verified": True}],
129        )
130
131        self.continue_to_next_stop()
132        x_val = self.dap_server.get_local_variable_value("x")
133        i_val = self.dap_server.get_local_variable_value("i")
134        self.assertEqual(x_val, "2")
135        self.assertEqual(i_val, "1")
136
137        self.continue_to_next_stop()
138        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
139        i_val = self.dap_server.get_local_variable_value("i")
140        self.assertEqual(arr_2["value"], "42")
141        self.assertEqual(i_val, "2")
142        self.dap_server.request_setDataBreakpoint([])
143
144        # Test hit condition
145        second_loop_break_line = line_number(source, "// second loop breakpoint")
146        breakpoint_ids = self.set_source_breakpoints(source, [second_loop_break_line])
147        self.continue_to_breakpoints(breakpoint_ids)
148        dataBreakpoints = [
149            {
150                "dataId": response_x["body"]["dataId"],
151                "accessType": "write",
152                "hitCondition": "2",
153            }
154        ]
155        set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
156        self.assertEqual(set_response["body"]["breakpoints"], [{"verified": True}])
157        self.continue_to_next_stop()
158        x_val = self.dap_server.get_local_variable_value("x")
159        self.assertEqual(x_val, "3")
160
161        # Test condition
162        dataBreakpoints = [
163            {
164                "dataId": response_x["body"]["dataId"],
165                "accessType": "write",
166                "condition": "x==10",
167            }
168        ]
169        set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
170        self.assertEqual(set_response["body"]["breakpoints"], [{"verified": True}])
171        self.continue_to_next_stop()
172        x_val = self.dap_server.get_local_variable_value("x")
173        self.assertEqual(x_val, "10")
174