77db8f745d7ea33a4a7409fba8a48c636a2351ea
[openbsd] /
1 """
2 Test lldb breakpoint command add/list/delete.
3 """
4
5
6
7 import lldb
8 from lldbsuite.test.decorators import *
9 from lldbsuite.test.lldbtest import *
10 from lldbsuite.test import lldbutil
11 import side_effect
12
13
14 class BreakpointCommandTestCase(TestBase):
15
16     NO_DEBUG_INFO_TESTCASE = True
17     mydir = TestBase.compute_mydir(__file__)
18
19     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
20     def not_test_breakpoint_command_sequence(self):
21         """Test a sequence of breakpoint command add, list, and delete."""
22         self.build()
23         self.breakpoint_command_sequence()
24
25     @skipIf(oslist=["windows"], bugnumber="llvm.org/pr44431")
26     def test_script_parameters(self):
27         """Test a sequence of breakpoint command add, list, and delete."""
28         self.build()
29         self.breakpoint_command_script_parameters()
30
31     def test_commands_on_creation(self):
32         self.build()
33         self.breakpoint_commands_on_creation()
34
35     def setUp(self):
36         # Call super's setUp().
37         TestBase.setUp(self)
38         # Find the line number to break inside main().
39         self.line = line_number('main.c', '// Set break point at this line.')
40         # disable "There is a running process, kill it and restart?" prompt
41         self.runCmd("settings set auto-confirm true")
42         self.addTearDownHook(
43             lambda: self.runCmd("settings clear auto-confirm"))
44
45     def test_delete_all_breakpoints(self):
46         """Test that deleting all breakpoints works."""
47         self.build()
48         exe = self.getBuildArtifact("a.out")
49         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
50
51         lldbutil.run_break_set_by_symbol(self, "main")
52         lldbutil.run_break_set_by_file_and_line(
53             self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
54
55         self.runCmd("run", RUN_SUCCEEDED)
56
57         self.runCmd("breakpoint delete")
58         self.runCmd("process continue")
59         self.expect("process status", PROCESS_STOPPED,
60                     patterns=['Process .* exited with status = 0'])
61
62
63     def breakpoint_command_sequence(self):
64         """Test a sequence of breakpoint command add, list, and delete."""
65         exe = self.getBuildArtifact("a.out")
66         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
67
68         # Add three breakpoints on the same line.  The first time we don't specify the file,
69         # since the default file is the one containing main:
70         lldbutil.run_break_set_by_file_and_line(
71             self, None, self.line, num_expected_locations=1, loc_exact=True)
72         lldbutil.run_break_set_by_file_and_line(
73             self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
74         lldbutil.run_break_set_by_file_and_line(
75             self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
76         # Breakpoint 4 - set at the same location as breakpoint 1 to test
77         # setting breakpoint commands on two breakpoints at a time
78         lldbutil.run_break_set_by_file_and_line(
79             self, None, self.line, num_expected_locations=1, loc_exact=True)
80         # Make sure relative path source breakpoints work as expected. We test
81         # with partial paths with and without "./" prefixes.
82         lldbutil.run_break_set_by_file_and_line(
83             self, "./main.c", self.line,
84             num_expected_locations=1, loc_exact=True)
85         lldbutil.run_break_set_by_file_and_line(
86             self, "breakpoint_command/main.c", self.line,
87             num_expected_locations=1, loc_exact=True)
88         lldbutil.run_break_set_by_file_and_line(
89             self, "./breakpoint_command/main.c", self.line,
90             num_expected_locations=1, loc_exact=True)
91         lldbutil.run_break_set_by_file_and_line(
92             self, "breakpoint/breakpoint_command/main.c", self.line,
93             num_expected_locations=1, loc_exact=True)
94         lldbutil.run_break_set_by_file_and_line(
95             self, "./breakpoint/breakpoint_command/main.c", self.line,
96             num_expected_locations=1, loc_exact=True)
97         # Test relative breakpoints with incorrect paths and make sure we get
98         # no breakpoint locations
99         lldbutil.run_break_set_by_file_and_line(
100             self, "invalid/main.c", self.line,
101             num_expected_locations=0, loc_exact=True)
102         lldbutil.run_break_set_by_file_and_line(
103             self, "./invalid/main.c", self.line,
104             num_expected_locations=0, loc_exact=True)
105         # Now add callbacks for the breakpoints just created.
106         self.runCmd(
107             "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4")
108         self.runCmd(
109             "breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2")
110
111         import side_effect
112         self.runCmd("command script import --allow-reload ./bktptcmd.py")
113
114         self.runCmd(
115             "breakpoint command add --python-function bktptcmd.function 3")
116
117         # Check that the breakpoint commands are correctly set.
118
119         # The breakpoint list now only contains breakpoint 1.
120         self.expect(
121             "breakpoint list", "Breakpoints 1 & 2 created", substrs=[
122                 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" %
123                 self.line], patterns=[
124                 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" %
125                 self.line])
126
127         self.expect(
128             "breakpoint list -f",
129             "Breakpoints 1 & 2 created",
130             substrs=[
131                 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" %
132                 self.line],
133             patterns=[
134                 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" %
135                 self.line,
136                 "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
137                 self.line,
138                 "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
139                 self.line])
140
141         self.expect("breakpoint command list 1", "Breakpoint 1 command ok",
142                     substrs=["Breakpoint commands:",
143                              "frame variable --show-types --scope"])
144         self.expect("breakpoint command list 2", "Breakpoint 2 command ok",
145                     substrs=["Breakpoint commands (Python):",
146                              "import side_effect",
147                              "side_effect.one_liner"])
148         self.expect("breakpoint command list 3", "Breakpoint 3 command ok",
149                     substrs=["Breakpoint commands (Python):",
150                              "bktptcmd.function(frame, bp_loc, internal_dict)"])
151
152         self.expect("breakpoint command list 4", "Breakpoint 4 command ok",
153                     substrs=["Breakpoint commands:",
154                              "frame variable --show-types --scope"])
155
156         self.runCmd("breakpoint delete 4")
157
158         # Next lets try some other breakpoint kinds.  First break with a regular expression
159         # and then specify only one file.  The first time we should get two locations,
160         # the second time only one:
161
162         lldbutil.run_break_set_by_regexp(
163             self, r"._MyFunction", num_expected_locations=2)
164
165         lldbutil.run_break_set_by_regexp(
166             self,
167             r"._MyFunction",
168             extra_options="-f a.c",
169             num_expected_locations=1)
170
171         lldbutil.run_break_set_by_regexp(
172             self,
173             r"._MyFunction",
174             extra_options="-f a.c -f b.c",
175             num_expected_locations=2)
176
177         # Now try a source regex breakpoint:
178         lldbutil.run_break_set_by_source_regexp(
179             self,
180             r"is about to return [12]0",
181             extra_options="-f a.c -f b.c",
182             num_expected_locations=2)
183
184         lldbutil.run_break_set_by_source_regexp(
185             self,
186             r"is about to return [12]0",
187             extra_options="-f a.c",
188             num_expected_locations=1)
189
190         # Reset our canary variables and run the program.
191         side_effect.one_liner = None
192         side_effect.bktptcmd = None
193         self.runCmd("run", RUN_SUCCEEDED)
194
195         # Check the value of canary variables.
196         self.assertEquals("one liner was here", side_effect.one_liner)
197         self.assertEquals("function was here", side_effect.bktptcmd)
198
199         # Finish the program.
200         self.runCmd("process continue")
201
202         # Remove the breakpoint command associated with breakpoint 1.
203         self.runCmd("breakpoint command delete 1")
204
205         # Remove breakpoint 2.
206         self.runCmd("breakpoint delete 2")
207
208         self.expect(
209             "breakpoint command list 1",
210             startstr="Breakpoint 1 does not have an associated command.")
211         self.expect(
212             "breakpoint command list 2",
213             error=True,
214             startstr="error: '2' is not a currently valid breakpoint ID.")
215
216         # The breakpoint list now only contains breakpoint 1.
217         self.expect(
218             "breakpoint list -f",
219             "Breakpoint 1 exists",
220             patterns=[
221                 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" %
222                 self.line,
223                 "hit count = 1"])
224
225         # Not breakpoint 2.
226         self.expect(
227             "breakpoint list -f",
228             "No more breakpoint 2",
229             matching=False,
230             substrs=[
231                 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" %
232                 self.line])
233
234         # Run the program again, with breakpoint 1 remaining.
235         self.runCmd("run", RUN_SUCCEEDED)
236
237         # We should be stopped again due to breakpoint 1.
238
239         # The stop reason of the thread should be breakpoint.
240         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
241                     substrs=['stopped',
242                              'stop reason = breakpoint'])
243
244         # The breakpoint should have a hit count of 2.
245         self.expect("breakpoint list -f", BREAKPOINT_HIT_TWICE,
246                     substrs=['resolved, hit count = 2'])
247
248     def breakpoint_command_script_parameters(self):
249         """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function."""
250         exe = self.getBuildArtifact("a.out")
251         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
252
253         # Add a breakpoint.
254         lldbutil.run_break_set_by_file_and_line(
255             self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
256
257         # Now add callbacks for the breakpoints just created.
258         self.runCmd("breakpoint command add -s python -o 'import side_effect; side_effect.frame = str(frame); side_effect.bp_loc = str(bp_loc)' 1")
259
260         # Reset canary variables and run.
261         side_effect.frame = None
262         side_effect.bp_loc = None
263         self.runCmd("run", RUN_SUCCEEDED)
264
265         self.expect(side_effect.frame, exe=False, startstr="frame #0:")
266         self.expect(side_effect.bp_loc, exe=False,
267                 patterns=["1.* where = .*main .* resolved, hit count = 1"])
268
269     def breakpoint_commands_on_creation(self):
270         """Test that setting breakpoint commands when creating the breakpoint works"""
271         exe = self.getBuildArtifact("a.out")
272         target = self.dbg.CreateTarget(exe)
273         self.assertTrue(target.IsValid(), "Created an invalid target.")
274
275         # Add a breakpoint.
276         lldbutil.run_break_set_by_file_and_line(
277             self, "main.c", self.line, num_expected_locations=1, loc_exact=True,
278             extra_options='-C bt -C "thread list" -C continue')
279
280         bkpt = target.FindBreakpointByID(1)
281         self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
282         com_list = lldb.SBStringList()
283         bkpt.GetCommandLineCommands(com_list)
284         self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands")
285         self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt")
286         self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list")
287         self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue")