1"""Test Python APIs for working with formatters"""
2
3from __future__ import print_function
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class SBFormattersAPITestCase(TestBase):
13
14    mydir = TestBase.compute_mydir(__file__)
15    NO_DEBUG_INFO_TESTCASE = True
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20        self.line = line_number('main.cpp', '// Set break point at this line.')
21
22    @add_test_categories(['pyapi'])
23    def test_formatters_api(self):
24        """Test Python APIs for working with formatters"""
25        self.build()
26        self.setTearDownCleanup()
27
28        """Test Python APIs for working with formatters"""
29        self.runCmd("file " + self.getBuildArtifact("a.out"),
30                    CURRENT_EXECUTABLE_SET)
31
32        lldbutil.run_break_set_by_file_and_line(
33            self, "main.cpp", self.line, num_expected_locations=1,
34            loc_exact=True)
35
36        self.runCmd("run", RUN_SUCCEEDED)
37
38        # The stop reason of the thread should be breakpoint.
39        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
40                    substrs=['stopped',
41                             'stop reason = breakpoint'])
42
43        # This is the function to remove the custom formats in order to have a
44        # clean slate for the next test case.
45        def cleanup():
46            self.runCmd('type format clear', check=False)
47            self.runCmd('type summary clear', check=False)
48            self.runCmd('type filter clear', check=False)
49            self.runCmd('type synthetic clear', check=False)
50            self.runCmd('type category delete foobar', check=False)
51            self.runCmd('type category delete JASSynth', check=False)
52            self.runCmd('type category delete newbar', check=False)
53
54        # Execute the cleanup function during test case tear down.
55        self.addTearDownHook(cleanup)
56
57        format = lldb.SBTypeFormat(lldb.eFormatHex)
58        category = self.dbg.GetDefaultCategory()
59        category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"), format)
60
61        self.expect("frame variable foo.A",
62                    substrs=['0x00000001'])
63        self.expect("frame variable foo.E", matching=False,
64                    substrs=['b8cca70a'])
65
66        category.AddTypeFormat(lldb.SBTypeNameSpecifier("long"), format)
67        self.expect("frame variable foo.A",
68                    substrs=['0x00000001'])
69        self.expect("frame variable foo.E",
70                    substrs=['b8cca70a'])
71
72        format.SetFormat(lldb.eFormatOctal)
73        category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"), format)
74        self.expect("frame variable foo.A",
75                    substrs=[' 01'])
76        self.expect("frame variable foo.E",
77                    substrs=['b8cca70a'])
78
79        category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("int"))
80        category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("long"))
81        self.expect("frame variable foo.A", matching=False,
82                    substrs=[' 01'])
83        self.expect("frame variable foo.E", matching=False,
84                    substrs=['b8cca70a'])
85
86        summary = lldb.SBTypeSummary.CreateWithSummaryString(
87            "the hello world you'll never see")
88        summary.SetSummaryString('hello world')
89        new_category = self.dbg.GetCategory("foobar")
90        self.assertFalse(
91            new_category.IsValid(),
92            "getting a non-existing category worked")
93        new_category = self.dbg.CreateCategory("foobar")
94        new_category.SetEnabled(True)
95        new_category.AddTypeSummary(
96            lldb.SBTypeNameSpecifier(
97                "^.*t$",
98                True,  # is_regexp
99            ), summary)
100
101        self.expect("frame variable foo.A",
102                    substrs=['hello world'])
103        self.expect("frame variable foo.E", matching=False,
104                    substrs=['hello world'])
105        self.expect("frame variable foo.B",
106                    substrs=['hello world'])
107        self.expect("frame variable foo.F",
108                    substrs=['hello world'])
109        new_category.SetEnabled(False)
110        self.expect("frame variable foo.A", matching=False,
111                    substrs=['hello world'])
112        self.expect("frame variable foo.E", matching=False,
113                    substrs=['hello world'])
114        self.expect("frame variable foo.B", matching=False,
115                    substrs=['hello world'])
116        self.expect("frame variable foo.F", matching=False,
117                    substrs=['hello world'])
118        self.dbg.DeleteCategory(new_category.GetName())
119        self.expect("frame variable foo.A", matching=False,
120                    substrs=['hello world'])
121        self.expect("frame variable foo.E", matching=False,
122                    substrs=['hello world'])
123        self.expect("frame variable foo.B", matching=False,
124                    substrs=['hello world'])
125        self.expect("frame variable foo.F", matching=False,
126                    substrs=['hello world'])
127
128        filter = lldb.SBTypeFilter(0)
129        filter.AppendExpressionPath("A")
130        filter.AppendExpressionPath("D")
131        self.assertTrue(
132            filter.GetNumberOfExpressionPaths() == 2,
133            "filter with two items does not have two items")
134
135        category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)
136        self.expect("frame variable foo",
137                    substrs=['A = 1', 'D = 6.28'])
138        self.expect("frame variable foo", matching=False,
139                    substrs=['B = ', 'C = ', 'E = ', 'F = '])
140
141        category.DeleteTypeFilter(
142            lldb.SBTypeNameSpecifier(
143                "JustAStruct", True))
144        self.expect("frame variable foo",
145                    substrs=['A = 1', 'D = 6.28'])
146        self.expect("frame variable foo", matching=False,
147                    substrs=['B = ', 'C = ', 'E = ', 'F = '])
148
149        category.DeleteTypeFilter(
150            lldb.SBTypeNameSpecifier(
151                "JustAStruct", False))
152        self.expect("frame variable foo",
153                    substrs=['A = 1', 'D = 6.28'])
154        self.expect("frame variable foo", matching=True,
155                    substrs=['B = ', 'C = ', 'E = ', 'F = '])
156
157        self.runCmd("command script import --allow-reload ./synth.py")
158
159        self.expect("frame variable foo", matching=False,
160                    substrs=['X = 1'])
161
162        self.dbg.GetCategory("JASSynth").SetEnabled(True)
163        self.expect("frame variable foo", matching=True,
164                    substrs=['X = 1'])
165
166        self.dbg.GetCategory("CCCSynth").SetEnabled(True)
167        self.expect(
168            "frame variable ccc",
169            matching=True,
170            substrs=[
171                'CCC object with leading value (int) a = 111',
172                'a = 111',
173                'b = 222',
174                'c = 333'])
175
176        foo_var = self.dbg.GetSelectedTarget().GetProcess(
177        ).GetSelectedThread().GetSelectedFrame().FindVariable('foo')
178        self.assertTrue(foo_var.IsValid(), 'could not find foo')
179        self.assertTrue(
180            foo_var.GetDeclaration().IsValid(),
181            'foo declaration is invalid')
182
183        self.assertTrue(
184            foo_var.GetNumChildren() == 2,
185            'synthetic value has wrong number of child items (synth)')
186        self.assertTrue(
187            foo_var.GetChildMemberWithName('X').GetValueAsUnsigned() == 1,
188            'foo_synth.X has wrong value (synth)')
189        self.assertFalse(
190            foo_var.GetChildMemberWithName('B').IsValid(),
191            'foo_synth.B is valid but should not (synth)')
192
193        self.dbg.GetCategory("JASSynth").SetEnabled(False)
194        foo_var = self.dbg.GetSelectedTarget().GetProcess(
195        ).GetSelectedThread().GetSelectedFrame().FindVariable('foo')
196        self.assertTrue(foo_var.IsValid(), 'could not find foo')
197
198        self.assertFalse(
199            foo_var.GetNumChildren() == 2,
200            'still seeing synthetic value')
201
202        filter = lldb.SBTypeFilter(0)
203        filter.AppendExpressionPath("A")
204        filter.AppendExpressionPath("D")
205        category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)
206        self.expect("frame variable foo",
207                    substrs=['A = 1', 'D = 6.28'])
208
209        foo_var = self.dbg.GetSelectedTarget().GetProcess(
210        ).GetSelectedThread().GetSelectedFrame().FindVariable('foo')
211        self.assertTrue(foo_var.IsValid(), 'could not find foo')
212
213        self.assertTrue(
214            foo_var.GetNumChildren() == 2,
215            'synthetic value has wrong number of child items (filter)')
216        self.assertTrue(
217            foo_var.GetChildMemberWithName('X').GetValueAsUnsigned() == 0,
218            'foo_synth.X has wrong value (filter)')
219        self.assertTrue(
220            foo_var.GetChildMemberWithName('A').GetValueAsUnsigned() == 1,
221            'foo_synth.A has wrong value (filter)')
222
223        self.assertTrue(filter.ReplaceExpressionPathAtIndex(
224            0, "C"), "failed to replace an expression path in filter")
225        self.expect("frame variable foo",
226                    substrs=['A = 1', 'D = 6.28'])
227        category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)
228        self.expect("frame variable foo",
229                    substrs=["C = 'e'", 'D = 6.28'])
230        category.AddTypeFilter(lldb.SBTypeNameSpecifier("FooType"), filter)
231        filter.ReplaceExpressionPathAtIndex(1, "F")
232        self.expect("frame variable foo",
233                    substrs=["C = 'e'", 'D = 6.28'])
234        category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)
235        self.expect("frame variable foo",
236                    substrs=["C = 'e'", 'F = 0'])
237        self.expect("frame variable bar",
238                    substrs=["C = 'e'", 'D = 6.28'])
239
240        foo_var = self.dbg.GetSelectedTarget().GetProcess(
241        ).GetSelectedThread().GetSelectedFrame().FindVariable('foo')
242        self.assertTrue(foo_var.IsValid(), 'could not find foo')
243        self.assertTrue(
244            foo_var.GetChildMemberWithName('C').GetValueAsUnsigned() == ord('e'),
245            'foo_synth.C has wrong value (filter)')
246
247        chosen = self.dbg.GetFilterForType(
248            lldb.SBTypeNameSpecifier("JustAStruct"))
249        self.assertTrue(
250            chosen.count == 2,
251            "wrong filter found for JustAStruct")
252        self.assertTrue(
253            chosen.GetExpressionPathAtIndex(0) == 'C',
254            "wrong item at index 0 for JustAStruct")
255        self.assertTrue(
256            chosen.GetExpressionPathAtIndex(1) == 'F',
257            "wrong item at index 1 for JustAStruct")
258
259        self.assertFalse(
260            category.DeleteTypeFilter(
261                lldb.SBTypeNameSpecifier("NoSuchType")),
262            "deleting a non-existing filter worked")
263        self.assertFalse(
264            category.DeleteTypeSummary(
265                lldb.SBTypeNameSpecifier("NoSuchType")),
266            "deleting a non-existing summary worked")
267        self.assertFalse(
268            category.DeleteTypeFormat(
269                lldb.SBTypeNameSpecifier("NoSuchType")),
270            "deleting a non-existing format worked")
271        self.assertFalse(
272            category.DeleteTypeSynthetic(
273                lldb.SBTypeNameSpecifier("NoSuchType")),
274            "deleting a non-existing synthetic worked")
275
276        self.assertFalse(
277            category.DeleteTypeFilter(
278                lldb.SBTypeNameSpecifier("")),
279            "deleting a filter for '' worked")
280        self.assertFalse(
281            category.DeleteTypeSummary(
282                lldb.SBTypeNameSpecifier("")),
283            "deleting a summary for '' worked")
284        self.assertFalse(
285            category.DeleteTypeFormat(
286                lldb.SBTypeNameSpecifier("")),
287            "deleting a format for '' worked")
288        self.assertFalse(
289            category.DeleteTypeSynthetic(
290                lldb.SBTypeNameSpecifier("")),
291            "deleting a synthetic for '' worked")
292
293        try:
294            self.assertFalse(
295                category.AddTypeSummary(
296                    lldb.SBTypeNameSpecifier("NoneSuchType"),
297                    None),
298                "adding a summary valued None worked")
299        except:
300            pass
301        else:
302            self.assertFalse(True, "adding a summary valued None worked")
303
304        try:
305            self.assertFalse(
306                category.AddTypeFilter(
307                    lldb.SBTypeNameSpecifier("NoneSuchType"),
308                    None),
309                "adding a filter valued None worked")
310        except:
311            pass
312        else:
313            self.assertFalse(True, "adding a filter valued None worked")
314
315        try:
316            self.assertFalse(
317                category.AddTypeSynthetic(
318                    lldb.SBTypeNameSpecifier("NoneSuchType"),
319                    None),
320                "adding a synthetic valued None worked")
321        except:
322            pass
323        else:
324            self.assertFalse(True, "adding a synthetic valued None worked")
325
326        try:
327            self.assertFalse(
328                category.AddTypeFormat(
329                    lldb.SBTypeNameSpecifier("NoneSuchType"),
330                    None),
331                "adding a format valued None worked")
332        except:
333            pass
334        else:
335            self.assertFalse(True, "adding a format valued None worked")
336
337        self.assertFalse(
338            category.AddTypeSummary(
339                lldb.SBTypeNameSpecifier("EmptySuchType"),
340                lldb.SBTypeSummary()),
341            "adding a summary without value worked")
342        self.assertFalse(
343            category.AddTypeFilter(
344                lldb.SBTypeNameSpecifier("EmptySuchType"),
345                lldb.SBTypeFilter()),
346            "adding a filter without value worked")
347        self.assertFalse(
348            category.AddTypeSynthetic(
349                lldb.SBTypeNameSpecifier("EmptySuchType"),
350                lldb.SBTypeSynthetic()),
351            "adding a synthetic without value worked")
352        self.assertFalse(
353            category.AddTypeFormat(
354                lldb.SBTypeNameSpecifier("EmptySuchType"),
355                lldb.SBTypeFormat()),
356            "adding a format without value worked")
357
358        self.assertFalse(
359            category.AddTypeSummary(
360                lldb.SBTypeNameSpecifier(""),
361                lldb.SBTypeSummary.CreateWithSummaryString("")),
362            "adding a summary for an invalid type worked")
363        self.assertFalse(
364            category.AddTypeFilter(
365                lldb.SBTypeNameSpecifier(""),
366                lldb.SBTypeFilter(0)),
367            "adding a filter for an invalid type worked")
368        self.assertFalse(
369            category.AddTypeSynthetic(
370                lldb.SBTypeNameSpecifier(""),
371                lldb.SBTypeSynthetic.CreateWithClassName("")),
372            "adding a synthetic for an invalid type worked")
373        self.assertFalse(
374            category.AddTypeFormat(
375                lldb.SBTypeNameSpecifier(""),
376                lldb.SBTypeFormat(
377                    lldb.eFormatHex)),
378            "adding a format for an invalid type worked")
379
380        new_category = self.dbg.CreateCategory("newbar")
381        new_category.AddTypeSummary(
382            lldb.SBTypeNameSpecifier("JustAStruct"),
383            lldb.SBTypeSummary.CreateWithScriptCode("return 'hello scripted world';"))
384        self.expect("frame variable foo", matching=False,
385                    substrs=['hello scripted world'])
386        new_category.SetEnabled(True)
387        self.expect("frame variable foo", matching=True,
388                    substrs=['hello scripted world'])
389
390        self.expect("frame variable foo_ptr", matching=True,
391                    substrs=['hello scripted world'])
392        new_category.AddTypeSummary(
393            lldb.SBTypeNameSpecifier("JustAStruct"),
394            lldb.SBTypeSummary.CreateWithScriptCode(
395                "return 'hello scripted world';",
396                lldb.eTypeOptionSkipPointers))
397        self.expect("frame variable foo", matching=True,
398                    substrs=['hello scripted world'])
399
400        frame = self.dbg.GetSelectedTarget().GetProcess(
401        ).GetSelectedThread().GetSelectedFrame()
402        foo_ptr = frame.FindVariable("foo_ptr")
403        summary = foo_ptr.GetTypeSummary()
404
405        self.assertFalse(
406            summary.IsValid(),
407            "summary found for foo* when none was planned")
408
409        self.expect("frame variable foo_ptr", matching=False,
410                    substrs=['hello scripted world'])
411
412        new_category.AddTypeSummary(
413            lldb.SBTypeNameSpecifier("JustAStruct"),
414            lldb.SBTypeSummary.CreateWithSummaryString(
415                "hello static world",
416                lldb.eTypeOptionNone))
417
418        summary = foo_ptr.GetTypeSummary()
419
420        self.assertTrue(
421            summary.IsValid(),
422            "no summary found for foo* when one was in place")
423        self.assertTrue(
424            summary.GetData() == "hello static world",
425            "wrong summary found for foo*")
426
427        self.expect("frame variable e1", substrs=["I am an empty Empty1 {}"])
428        self.expect("frame variable e2", substrs=["I am an empty Empty2"])
429        self.expect(
430            "frame variable e2",
431            substrs=["I am an empty Empty2 {}"],
432            matching=False)
433
434        self.assertTrue(
435            self.dbg.GetCategory(
436                lldb.eLanguageTypeObjC) is not None,
437            "ObjC category is None")
438
439    @add_test_categories(['pyapi'])
440    def test_force_synth_off(self):
441        """Test that one can have the public API return non-synthetic SBValues if desired"""
442        self.build(dictionary={'EXE': 'no_synth'})
443        self.setTearDownCleanup()
444
445        self.runCmd("file " + self.getBuildArtifact("no_synth"),
446                    CURRENT_EXECUTABLE_SET)
447
448        lldbutil.run_break_set_by_file_and_line(
449            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
450
451        self.runCmd("run", RUN_SUCCEEDED)
452
453        # The stop reason of the thread should be breakpoint.
454        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
455                    substrs=['stopped',
456                             'stop reason = breakpoint'])
457
458        # This is the function to remove the custom formats in order to have a
459        # clean slate for the next test case.
460        def cleanup():
461            self.runCmd('type format clear', check=False)
462            self.runCmd('type summary clear', check=False)
463            self.runCmd('type filter clear', check=False)
464            self.runCmd('type synthetic clear', check=False)
465            self.runCmd('type category delete foobar', check=False)
466            self.runCmd('type category delete JASSynth', check=False)
467            self.runCmd('type category delete newbar', check=False)
468            self.runCmd('settings set target.enable-synthetic-value true')
469
470        # Execute the cleanup function during test case tear down.
471        self.addTearDownHook(cleanup)
472
473        frame = self.dbg.GetSelectedTarget().GetProcess(
474        ).GetSelectedThread().GetSelectedFrame()
475        int_vector = frame.FindVariable("int_vector")
476        if self.TraceOn():
477            print(int_vector)
478        self.assertTrue(
479            int_vector.GetNumChildren() == 0,
480            'synthetic vector is empty')
481
482        self.runCmd('settings set target.enable-synthetic-value false')
483        frame = self.dbg.GetSelectedTarget().GetProcess(
484        ).GetSelectedThread().GetSelectedFrame()
485        int_vector = frame.FindVariable("int_vector")
486        if self.TraceOn():
487            print(int_vector)
488        self.assertFalse(
489            int_vector.GetNumChildren() == 0,
490            '"physical" vector is not empty')
491
492        self.runCmd('settings set target.enable-synthetic-value true')
493        frame = self.dbg.GetSelectedTarget().GetProcess(
494        ).GetSelectedThread().GetSelectedFrame()
495        int_vector = frame.FindVariable("int_vector")
496        if self.TraceOn():
497            print(int_vector)
498        self.assertTrue(
499            int_vector.GetNumChildren() == 0,
500            'synthetic vector is still empty')
501