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