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