1"""
2Test using LLDB data formatters with frozen objects coming from the expression parser.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class ExprFormattersTestCase(TestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20        # Find the line number to break for main.cpp.
21        self.line = line_number('main.cpp',
22                                '// Stop here')
23
24    @skipIfFreeBSD  # llvm.org/pr24691 skipping to avoid crashing the test runner
25    @expectedFailureNetBSD
26    @expectedFailureAll(
27        oslist=['freebsd'],
28        bugnumber='llvm.org/pr19011 Newer Clang omits C1 complete object constructor')
29    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
30    @skipIfTargetAndroid()  # skipping to avoid crashing the test runner
31    @expectedFailureAndroid('llvm.org/pr24691')  # we hit an assertion in clang
32    def test(self):
33        """Test expr + formatters for good interoperability."""
34        self.build()
35
36        # This is the function to remove the custom formats in order to have a
37        # clean slate for the next test case.
38        def cleanup():
39            self.runCmd('type summary clear', check=False)
40            self.runCmd('type synthetic clear', check=False)
41
42        # Execute the cleanup function during test case tear down.
43        self.addTearDownHook(cleanup)
44
45        """Test expr + formatters for good interoperability."""
46        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
47
48        lldbutil.run_break_set_by_file_and_line(
49            self, "main.cpp", self.line, loc_exact=True)
50
51        self.runCmd("run", RUN_SUCCEEDED)
52        self.runCmd("command script import formatters.py")
53        self.runCmd("command script import foosynth.py")
54
55        if self.TraceOn():
56            self.runCmd("frame variable foo1 --show-types")
57            self.runCmd("frame variable foo1.b --show-types")
58            self.runCmd("frame variable foo1.b.b_ref --show-types")
59
60        self.filecheck("expression --show-types -- *(new foo(47))", __file__,
61                '-check-prefix=EXPR-TYPES-NEW-FOO')
62        # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = {
63        # EXPR-TYPES-NEW-FOO-NEXT:   (int) a = 47
64        # EXPR-TYPES-NEW-FOO-NEXT:   (int *) a_ptr = 0x
65        # EXPR-TYPES-NEW-FOO-NEXT:   (bar) b = {
66        # EXPR-TYPES-NEW-FOO-NEXT:     (int) i = 94
67        # EXPR-TYPES-NEW-FOO-NEXT:     (int *) i_ptr = 0x
68        # EXPR-TYPES-NEW-FOO-NEXT:     (baz) b = {
69        # EXPR-TYPES-NEW-FOO-NEXT:       (int) h = 97
70        # EXPR-TYPES-NEW-FOO-NEXT:       (int) k = 99
71        # EXPR-TYPES-NEW-FOO-NEXT:     }
72        # EXPR-TYPES-NEW-FOO-NEXT:     (baz &) b_ref = 0x
73        # EXPR-TYPES-NEW-FOO-NEXT:   }
74        # EXPR-TYPES-NEW-FOO-NEXT: }
75
76
77        self.runCmd("type summary add -F formatters.foo_SummaryProvider3 foo")
78        self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1opts')
79        # EXPR-FOO1opts: (foo) $
80        # EXPR-FOO1opts-SAME: a = 12
81        # EXPR-FOO1opts-SAME: a_ptr = {{[0-9]+}} -> 13
82        # EXPR-FOO1opts-SAME: i = 24
83        # EXPR-FOO1opts-SAME: i_ptr = {{[0-9]+}} -> 25
84        # EXPR-FOO1opts-SAME: b_ref = {{[0-9]+}}
85        # EXPR-FOO1opts-SAME: h = 27
86        # EXPR-FOO1opts-SAME: k = 29
87        # EXPR-FOO1opts-SAME: WITH_OPTS
88
89        self.runCmd("type summary delete foo")
90
91        self.runCmd("type summary add -F formatters.foo_SummaryProvider foo")
92
93        self.expect("expression new int(12)",
94                    substrs=['(int *) $', ' = 0x'])
95
96        self.runCmd(
97            "type summary add -s \"${var%pointer} -> ${*var%decimal}\" \"int *\"")
98
99        self.expect("expression new int(12)",
100                    substrs=['(int *) $', '= 0x', ' -> 12'])
101
102        self.expect("expression foo1.a_ptr",
103                    substrs=['(int *) $', '= 0x', ' -> 13'])
104
105        self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1')
106        # EXPR-FOO1: (foo) $
107        # EXPR-FOO1-SAME: a = 12
108        # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13
109        # EXPR-FOO1-SAME: i = 24
110        # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25
111        # EXPR-FOO1-SAME: b_ref = {{[0-9]+}}
112        # EXPR-FOO1-SAME: h = 27
113        # EXPR-FOO1-SAME: k = 29
114
115        self.filecheck("expression --ptr-depth=1 -- new foo(47)", __file__,
116                '-check-prefix=EXPR-PTR-DEPTH1')
117        # EXPR-PTR-DEPTH1: (foo *) $
118        # EXPR-PTR-DEPTH1-SAME: a = 47
119        # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48
120        # EXPR-PTR-DEPTH1-SAME: i = 94
121        # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95
122
123        self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2')
124        # EXPR-FOO2: (foo) $
125        # EXPR-FOO2-SAME: a = 121
126        # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122
127        # EXPR-FOO2-SAME: i = 242
128        # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243
129        # EXPR-FOO2-SAME: h = 245
130        # EXPR-FOO2-SAME: k = 247
131
132        object_name = self.res.GetOutput()
133        object_name = object_name[7:]
134        object_name = object_name[0:object_name.find(' =')]
135
136        self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2')
137        # VAR-FOO2: (foo) foo2
138        # VAR-FOO2-SAME: a = 121
139        # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122
140        # VAR-FOO2-SAME: i = 242
141        # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243
142        # VAR-FOO2-SAME: h = 245
143        # VAR-FOO2-SAME: k = 247
144
145        # The object is the same as foo2, so use the EXPR-FOO2 checks.
146        self.filecheck("expression $" + object_name, __file__,
147                '-check-prefix=EXPR-FOO2')
148
149        self.runCmd("type summary delete foo")
150        self.runCmd(
151            "type synthetic add --python-class foosynth.FooSyntheticProvider foo")
152
153        self.expect("expression --show-types -- $" + object_name,
154                    substrs=['(foo) $', ' = {', '(int) *i_ptr = 243'])
155
156        self.runCmd("n")
157        self.runCmd("n")
158
159        self.runCmd("type synthetic delete foo")
160        self.runCmd("type summary add -F formatters.foo_SummaryProvider foo")
161
162        self.expect(
163            "expression foo2",
164            substrs=[
165                '(foo) $',
166                'a = 7777',
167                'a_ptr = ',
168                ' -> 122',
169                'i = 242',
170                'i_ptr = ',
171                ' -> 8888'])
172
173        self.expect("expression $" + object_name + '.a',
174                    substrs=['7777'])
175
176        self.expect("expression *$" + object_name + '.b.i_ptr',
177                    substrs=['8888'])
178
179        self.expect(
180            "expression $" +
181            object_name,
182            substrs=[
183                '(foo) $',
184                'a = 121',
185                'a_ptr = ',
186                ' -> 122',
187                'i = 242',
188                'i_ptr = ',
189                ' -> 8888',
190                'h = 245',
191                'k = 247'])
192
193        self.runCmd("type summary delete foo")
194        self.runCmd(
195            "type synthetic add --python-class foosynth.FooSyntheticProvider foo")
196
197        self.expect("expression --show-types -- $" + object_name,
198                    substrs=['(foo) $', ' = {', '(int) *i_ptr = 8888'])
199
200        self.runCmd("n")
201
202        self.runCmd("type synthetic delete foo")
203        self.runCmd("type summary add -F formatters.foo_SummaryProvider foo")
204
205        self.expect(
206            "expression $" +
207            object_name,
208            substrs=[
209                '(foo) $',
210                'a = 121',
211                'a_ptr = ',
212                ' -> 122',
213                'i = 242',
214                'i_ptr = ',
215                ' -> 8888',
216                'k = 247'])
217
218        process = self.dbg.GetSelectedTarget().GetProcess()
219        thread = process.GetThreadAtIndex(0)
220        frame = thread.GetSelectedFrame()
221
222        frozen = frame.EvaluateExpression("$" + object_name + ".a_ptr")
223
224        a_data = frozen.GetPointeeData()
225
226        error = lldb.SBError()
227        self.assertTrue(
228            a_data.GetUnsignedInt32(
229                error,
230                0) == 122,
231            '*a_ptr = 122')
232
233        ret = line_number("main.cpp", "Done initializing")
234        self.runCmd("thread until " + str(ret))
235
236        self.expect("frame variable numbers",
237                    substrs=['1', '2', '3', '4', '5'])
238
239        self.expect("expression numbers",
240                    substrs=['1', '2', '3', '4', '5'])
241
242        frozen = frame.EvaluateExpression("&numbers")
243
244        a_data = frozen.GetPointeeData(0, 1)
245
246        self.assertTrue(
247            a_data.GetUnsignedInt32(
248                error,
249                0) == 1,
250            'numbers[0] == 1')
251        self.assertTrue(
252            a_data.GetUnsignedInt32(
253                error,
254                4) == 2,
255            'numbers[1] == 2')
256        self.assertTrue(
257            a_data.GetUnsignedInt32(
258                error,
259                8) == 3,
260            'numbers[2] == 3')
261        self.assertTrue(
262            a_data.GetUnsignedInt32(
263                error,
264                12) == 4,
265            'numbers[3] == 4')
266        self.assertTrue(
267            a_data.GetUnsignedInt32(
268                error,
269                16) == 5,
270            'numbers[4] == 5')
271
272        frozen = frame.EvaluateExpression("numbers")
273
274        a_data = frozen.GetData()
275
276        self.assertTrue(
277            a_data.GetUnsignedInt32(
278                error,
279                0) == 1,
280            'numbers[0] == 1')
281        self.assertTrue(
282            a_data.GetUnsignedInt32(
283                error,
284                4) == 2,
285            'numbers[1] == 2')
286        self.assertTrue(
287            a_data.GetUnsignedInt32(
288                error,
289                8) == 3,
290            'numbers[2] == 3')
291        self.assertTrue(
292            a_data.GetUnsignedInt32(
293                error,
294                12) == 4,
295            'numbers[3] == 4')
296        self.assertTrue(
297            a_data.GetUnsignedInt32(
298                error,
299                16) == 5,
300            'numbers[4] == 5')
301