4c6f32b08964fde58c98932629e0bd474b434226
[openbsd] /
1 """
2 Test breakpoint serialization.
3 """
4
5 import os
6 import lldb
7 from lldbsuite.test.decorators import *
8 from lldbsuite.test.lldbtest import *
9 from lldbsuite.test import lldbutil
10
11
12 class BreakpointSerialization(TestBase):
13
14     mydir = TestBase.compute_mydir(__file__)
15     NO_DEBUG_INFO_TESTCASE = True
16
17     @add_test_categories(['pyapi'])
18     def test_resolvers(self):
19         """Use Python APIs to test that we serialize resolvers."""
20         self.build()
21         self.setup_targets_and_cleanup()
22         self.do_check_resolvers()
23
24     def test_filters(self):
25         """Use Python APIs to test that we serialize search filters correctly."""
26         self.build()
27         self.setup_targets_and_cleanup()
28         self.do_check_filters()
29
30     def test_options(self):
31         """Use Python APIs to test that we serialize breakpoint options correctly."""
32         self.build()
33         self.setup_targets_and_cleanup()
34         self.do_check_options()
35
36     def test_appending(self):
37         """Use Python APIs to test that we serialize breakpoint options correctly."""
38         self.build()
39         self.setup_targets_and_cleanup()
40         self.do_check_appending()
41
42     def test_name_filters(self):
43         """Use python APIs to test that reading in by name works correctly."""
44         self.build()
45         self.setup_targets_and_cleanup()
46         self.do_check_names()
47         
48     def test_scripted_extra_args(self):
49         self.build()
50         self.setup_targets_and_cleanup()
51         self.do_check_extra_args()
52         
53     def setup_targets_and_cleanup(self):
54         def cleanup ():
55             self.RemoveTempFile(self.bkpts_file_path)
56
57             if self.orig_target.IsValid():
58                 self.dbg.DeleteTarget(self.orig_target)
59                 self.dbg.DeleteTarget(self.copy_target)
60
61         self.addTearDownHook(cleanup)
62         self.RemoveTempFile(self.bkpts_file_path)
63
64         exe = self.getBuildArtifact("a.out")
65
66         # Create the targets we are making breakpoints in and copying them to:
67         self.orig_target = self.dbg.CreateTarget(exe)
68         self.assertTrue(self.orig_target, VALID_TARGET)
69
70         self.copy_target = self.dbg.CreateTarget(exe)
71         self.assertTrue(self.copy_target, VALID_TARGET)
72
73     def setUp(self):
74         # Call super's setUp().
75         TestBase.setUp(self)
76
77         self.bkpts_file_path = self.getBuildArtifact("breakpoints.json")
78         self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)
79
80     def check_equivalence(self, source_bps, do_write = True):
81
82         error = lldb.SBError()
83
84         if (do_write):
85             error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
86             self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
87
88         copy_bps = lldb.SBBreakpointList(self.copy_target)
89         error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps)
90         self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
91
92         num_source_bps = source_bps.GetSize()
93         num_copy_bps = copy_bps.GetSize()
94         self.assertTrue(num_source_bps == num_copy_bps, "Didn't get same number of input and output breakpoints - orig: %d copy: %d"%(num_source_bps, num_copy_bps))
95
96         for i in range(0, num_source_bps):
97             source_bp = source_bps.GetBreakpointAtIndex(i)
98             source_desc = lldb.SBStream()
99             source_bp.GetDescription(source_desc, False)
100             source_text = source_desc.GetData()
101
102             # I am assuming here that the breakpoints will get written out in breakpoint ID order, and
103             # read back in ditto.  That is true right now, and I can't see any reason to do it differently
104             # but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to
105             # see which one is which.
106             copy_id = source_bp.GetID()
107             copy_bp = copy_bps.FindBreakpointByID(copy_id)
108             self.assertTrue(copy_bp.IsValid(), "Could not find copy breakpoint %d."%(copy_id))
109
110             copy_desc = lldb.SBStream()
111             copy_bp.GetDescription(copy_desc, False)
112             copy_text = copy_desc.GetData()
113
114             # These two should be identical.
115             # print ("Source text for %d is %s."%(i, source_text))
116             self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text))
117
118     def do_check_resolvers(self):
119         """Use Python APIs to check serialization of breakpoint resolvers"""
120
121         empty_module_list = lldb.SBFileSpecList()
122         empty_cu_list = lldb.SBFileSpecList()
123         blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c"))
124
125         # It isn't actually important for these purposes that these breakpoint
126         # actually have locations.
127         source_bps = lldb.SBBreakpointList(self.orig_target)
128         source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))
129         # Make sure we do one breakpoint right:
130         self.check_equivalence(source_bps)
131         source_bps.Clear()
132
133         source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list))
134         source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list))
135         source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec))
136
137         # And some number greater than one:
138         self.check_equivalence(source_bps)
139
140     def do_check_filters(self):
141         """Use Python APIs to check serialization of breakpoint filters."""
142         module_list = lldb.SBFileSpecList()
143         module_list.Append(lldb.SBFileSpec("SomeBinary"))
144         module_list.Append(lldb.SBFileSpec("SomeOtherBinary"))
145
146         cu_list = lldb.SBFileSpecList()
147         cu_list.Append(lldb.SBFileSpec("SomeCU.c"))
148         cu_list.Append(lldb.SBFileSpec("AnotherCU.c"))
149         cu_list.Append(lldb.SBFileSpec("ThirdCU.c"))
150
151         blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c"))
152
153         # It isn't actually important for these purposes that these breakpoint
154         # actually have locations.
155         source_bps = lldb.SBBreakpointList(self.orig_target)
156         bkpt = self.orig_target.BreakpointCreateByLocation(blubby_file_spec, 666, 0, module_list)
157         source_bps.Append(bkpt)
158
159         # Make sure we do one right:
160         self.check_equivalence(source_bps)
161         source_bps.Clear()
162
163         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list)
164         source_bps.Append(bkpt)
165         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, module_list, cu_list)
166         source_bps.Append(bkpt)
167         bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)
168         source_bps.Append(bkpt)
169
170         # And some number greater than one:
171         self.check_equivalence(source_bps)
172
173     def do_check_options(self):
174         """Use Python APIs to check serialization of breakpoint options."""
175
176         empty_module_list = lldb.SBFileSpecList()
177         empty_cu_list = lldb.SBFileSpecList()
178         blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c"))
179
180         # It isn't actually important for these purposes that these breakpoint
181         # actually have locations.
182         source_bps = lldb.SBBreakpointList(self.orig_target)
183
184         bkpt = self.orig_target.BreakpointCreateByLocation(
185             lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
186         bkpt.SetEnabled(False)
187         bkpt.SetOneShot(True)
188         bkpt.SetThreadID(10)
189         source_bps.Append(bkpt)
190
191         # Make sure we get one right:
192         self.check_equivalence(source_bps)
193         source_bps.Clear()
194
195         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
196         bkpt.SetIgnoreCount(10)
197         bkpt.SetThreadName("grubby")
198         source_bps.Append(bkpt)
199
200         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
201         bkpt.SetCondition("gonna remove this")
202         bkpt.SetCondition("")
203         source_bps.Append(bkpt)
204
205         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)
206         bkpt.SetCondition("something != something_else")
207         bkpt.SetQueueName("grubby")
208         bkpt.AddName("FirstName")
209         bkpt.AddName("SecondName")
210         bkpt.SetScriptCallbackBody('\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n')
211         source_bps.Append(bkpt)
212
213         bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)
214         cmd_list = lldb.SBStringList()
215         cmd_list.AppendString("frame var")
216         cmd_list.AppendString("thread backtrace")
217
218         bkpt.SetCommandLineCommands(cmd_list)
219         source_bps.Append(bkpt)
220
221         self.check_equivalence(source_bps)
222
223     def do_check_appending(self):
224         """Use Python APIs to check appending to already serialized options."""
225
226         empty_module_list = lldb.SBFileSpecList()
227         empty_cu_list = lldb.SBFileSpecList()
228         blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c"))
229
230         # It isn't actually important for these purposes that these breakpoint
231         # actually have locations.
232
233         all_bps = lldb.SBBreakpointList(self.orig_target)
234         source_bps = lldb.SBBreakpointList(self.orig_target)
235
236         bkpt = self.orig_target.BreakpointCreateByLocation(
237             lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
238         bkpt.SetEnabled(False)
239         bkpt.SetOneShot(True)
240         bkpt.SetThreadID(10)
241         source_bps.Append(bkpt)
242         all_bps.Append(bkpt)
243
244         error = lldb.SBError()
245         error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
246         self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
247
248         source_bps.Clear()
249
250         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
251         bkpt.SetIgnoreCount(10)
252         bkpt.SetThreadName("grubby")
253         source_bps.Append(bkpt)
254         all_bps.Append(bkpt)
255
256         bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)
257         bkpt.SetCondition("something != something_else")
258         bkpt.SetQueueName("grubby")
259         bkpt.AddName("FirstName")
260         bkpt.AddName("SecondName")
261
262         source_bps.Append(bkpt)
263         all_bps.Append(bkpt)
264
265         error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps, True)
266         self.assertTrue(error.Success(), "Failed appending breakpoints to file: %s."%(error.GetCString()))
267
268         self.check_equivalence(all_bps)
269
270     def do_check_names(self):
271         bkpt = self.orig_target.BreakpointCreateByLocation(
272             lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
273         good_bkpt_name = "GoodBreakpoint"
274         write_bps = lldb.SBBreakpointList(self.orig_target)
275         bkpt.AddName(good_bkpt_name)
276         write_bps.Append(bkpt)
277
278         error = lldb.SBError()
279         error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
280         self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
281
282         copy_bps = lldb.SBBreakpointList(self.copy_target)
283         names_list = lldb.SBStringList()
284         names_list.AppendString("NoSuchName")
285
286         error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps)
287         self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
288         self.assertTrue(copy_bps.GetSize() == 0, "Found breakpoints with a nonexistent name.")
289
290         names_list.AppendString(good_bkpt_name)
291         error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps)
292         self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
293         self.assertTrue(copy_bps.GetSize() == 1, "Found the matching breakpoint.")
294
295     def do_check_extra_args(self):
296
297         import side_effect
298         interp = self.dbg.GetCommandInterpreter()
299         error = lldb.SBError()
300
301         script_name = os.path.join(self.getSourceDir(), "resolver.py")
302
303         command = "command script import " + script_name
304         result = lldb.SBCommandReturnObject()
305         interp.HandleCommand(command, result)
306         self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError()))
307
308         # First make sure a scripted breakpoint with no args works:
309         bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", lldb.SBStructuredData(),
310                                                            lldb.SBFileSpecList(), lldb.SBFileSpecList())
311         self.assertTrue(bkpt.IsValid(), "Bkpt is valid")
312         write_bps = lldb.SBBreakpointList(self.orig_target)
313
314         error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
315         self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString()))
316
317         side_effect.g_extra_args = None
318         copy_bps = lldb.SBBreakpointList(self.copy_target)
319         error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps)
320         self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString()))
321
322         self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")
323         no_keys = lldb.SBStringList()
324         side_effect.g_extra_args.GetKeys(no_keys)
325         self.assertEqual(no_keys.GetSize(), 0, "Should have no keys")
326
327         self.orig_target.DeleteAllBreakpoints()
328         self.copy_target.DeleteAllBreakpoints()
329
330         # Now try one with extra args:
331         
332         extra_args = lldb.SBStructuredData()
333         stream = lldb.SBStream()
334         stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}')
335         extra_args.SetFromJSON(stream)
336         self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.")
337         
338         bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver",
339                                                            extra_args, lldb.SBFileSpecList(), lldb.SBFileSpecList())
340         self.assertTrue(bkpt.IsValid(), "Bkpt is valid")
341         write_bps = lldb.SBBreakpointList(self.orig_target)
342
343         error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
344         self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString()))
345
346         orig_extra_args = side_effect.g_extra_args
347         self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid")
348
349         orig_keys = lldb.SBStringList()
350         orig_extra_args.GetKeys(orig_keys)
351         self.assertEqual(2, orig_keys.GetSize(), "Should have two keys")
352
353         side_effect.g_extra_args = None
354
355         copy_bps = lldb.SBBreakpointList(self.copy_target)
356         error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps)
357         self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString()))
358
359         self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")
360
361         copy_extra_args = side_effect.g_extra_args
362         copy_keys = lldb.SBStringList()
363         copy_extra_args.GetKeys(copy_keys)
364         self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys")
365
366         for idx in range(0, orig_keys.GetSize()):
367             key = orig_keys.GetStringAtIndex(idx)
368             copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100)
369
370             if key == "first_arg":
371                 self.assertEqual(copy_value, "first_value")
372             elif key == "second_arg":
373                 self.assertEqual(copy_value, "second_value")
374             else:
375                 self.Fail("Unknown key: %s"%(key))