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