1"""
2Test lldb data formatter subsystem.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class CppDataFormatterTestCase(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 at.
21        self.line = line_number('main.cpp', '// Set break point at this line.')
22
23    @skipIf(debug_info="gmodules",
24            bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
25    def test_with_run_command(self):
26        """Test that that file and class static variables display correctly."""
27        self.build()
28        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
29
30        lldbutil.run_break_set_by_file_and_line(
31            self, "main.cpp", self.line, num_expected_locations=1, 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        self.expect("frame variable",
41                    substrs=['(Speed) SPILookHex = 5.55'  # Speed by default is 5.55.
42                             ])
43
44        # This is the function to remove the custom formats in order to have a
45        # clean slate for the next test case.
46        def cleanup():
47            self.runCmd('type format clear', check=False)
48            self.runCmd('type summary clear', check=False)
49
50        # Execute the cleanup function during test case tear down.
51        self.addTearDownHook(cleanup)
52
53        self.runCmd("type format add -C yes -f x Speed BitField")
54        self.runCmd("type format add -C no -f c RealNumber")
55        self.runCmd("type format add -C no -f x Type2")
56        self.runCmd("type format add -C yes -f c Type1")
57
58        # The type format list should show our custom formats.
59        self.expect(
60            "type format list",
61            substrs=['Speed', 'BitField', 'RealNumber', 'Type2', 'Type1'])
62
63        self.expect("frame variable",
64                    patterns=['\(Speed\) SPILookHex = 0x[0-9a-f]+'  # Speed should look hex-ish now.
65                              ])
66
67        # gcc4.2 on Mac OS X skips typedef chains in the DWARF output
68        if self.getCompiler() in ['clang', 'llvm-gcc']:
69            self.expect("frame variable",
70                        patterns=['\(SignalMask\) SMILookHex = 0x[0-9a-f]+'  # SignalMask should look hex-ish now.
71                                  ])
72            self.expect("frame variable", matching=False,
73                        patterns=['\(Type4\) T4ILookChar = 0x[0-9a-f]+'  # Type4 should NOT look hex-ish now.
74                                  ])
75
76        # Now let's delete the 'Speed' custom format.
77        self.runCmd("type format delete Speed")
78
79        # The type format list should not show 'Speed' at this point.
80        self.expect("type format list", matching=False,
81                    substrs=['Speed'])
82
83        # Delete type format for 'Speed', we should expect an error message.
84        self.expect("type format delete Speed", error=True,
85                    substrs=['no custom formatter for Speed'])
86
87        self.runCmd(
88            "type summary add --summary-string \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v")
89
90        self.expect("frame variable strarr",
91                    substrs=['arr = "Hello world!"'])
92
93        self.runCmd("type summary clear")
94
95        self.runCmd(
96            "type summary add --summary-string \"ptr = ${var%s}\" \"char *\" -v")
97
98        self.expect("frame variable strptr",
99                    substrs=['ptr = "Hello world!"'])
100
101        self.runCmd(
102            "type summary add --summary-string \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v")
103
104        self.expect("frame variable strarr",
105                    substrs=['arr = "Hello world!'])
106
107        # check that rdar://problem/10011145 (Standard summary format for
108        # char[] doesn't work as the result of "expr".) is solved
109        self.expect("p strarr",
110                    substrs=['arr = "Hello world!'])
111
112        self.expect("frame variable strptr",
113                    substrs=['ptr = "Hello world!"'])
114
115        self.expect("p strptr",
116                    substrs=['ptr = "Hello world!"'])
117
118        self.expect(
119            "p (char*)\"1234567890123456789012345678901234567890123456789012345678901234ABC\"",
120            substrs=[
121                '(char *) $',
122                ' = ptr = ',
123                ' "1234567890123456789012345678901234567890123456789012345678901234ABC"'])
124
125        self.runCmd("type summary add -c Point")
126
127        self.expect("frame variable iAmSomewhere",
128                    substrs=['x = 4',
129                             'y = 6'])
130
131        self.expect("type summary list",
132                    substrs=['Point',
133                             'one-line'])
134
135        self.runCmd("type summary add --summary-string \"y=${var.y%x}\" Point")
136
137        self.expect("frame variable iAmSomewhere",
138                    substrs=['y=0x'])
139
140        self.runCmd(
141            "type summary add --summary-string \"y=${var.y},x=${var.x}\" Point")
142
143        self.expect("frame variable iAmSomewhere",
144                    substrs=['y=6',
145                             'x=4'])
146
147        self.runCmd("type summary add --summary-string \"hello\" Point -e")
148
149        self.expect("type summary list",
150                    substrs=['Point',
151                             'show children'])
152
153        self.expect("frame variable iAmSomewhere",
154                    substrs=['hello',
155                             'x = 4',
156                             '}'])
157
158        self.runCmd(
159            "type summary add --summary-string \"Sign: ${var[31]%B} Exponent: ${var[23-30]%x} Mantissa: ${var[0-22]%u}\" ShowMyGuts")
160
161        self.expect("frame variable cool_pointer->floating",
162                    substrs=['Sign: true',
163                             'Exponent: 0x',
164                             '80'])
165
166        self.runCmd("type summary add --summary-string \"a test\" i_am_cool")
167
168        self.expect("frame variable cool_pointer",
169                    substrs=['a test'])
170
171        self.runCmd(
172            "type summary add --summary-string \"a test\" i_am_cool --skip-pointers")
173
174        self.expect("frame variable cool_pointer",
175                    substrs=['a test'],
176                    matching=False)
177
178        self.runCmd(
179            "type summary add --summary-string \"${var[1-3]}\" \"int [5]\"")
180
181        self.expect("frame variable int_array",
182                    substrs=['2',
183                             '3',
184                             '4'])
185
186        self.runCmd("type summary clear")
187
188        self.runCmd(
189            "type summary add --summary-string \"${var[0-2].integer}\" \"i_am_cool *\"")
190        self.runCmd(
191            "type summary add --summary-string \"${var[2-4].integer}\" \"i_am_cool [5]\"")
192
193        self.expect("frame variable cool_array",
194                    substrs=['1,1,6'])
195
196        self.expect("frame variable cool_pointer",
197                    substrs=['3,0,0'])
198
199        # test special symbols for formatting variables into summaries
200        self.runCmd(
201            "type summary add --summary-string \"cool object @ ${var%L}\" i_am_cool")
202        self.runCmd("type summary delete \"i_am_cool [5]\"")
203
204        # this test might fail if the compiler tries to store
205        # these values into registers.. hopefully this is not
206        # going to be the case
207        self.expect("frame variable cool_array",
208                    substrs=['[0] = cool object @ 0x',
209                             '[1] = cool object @ 0x',
210                             '[2] = cool object @ 0x',
211                             '[3] = cool object @ 0x',
212                             '[4] = cool object @ 0x'])
213
214        # test getting similar output by exploiting ${var} = 'type @ location'
215        # for aggregates
216        self.runCmd("type summary add --summary-string \"${var}\" i_am_cool")
217
218        # this test might fail if the compiler tries to store
219        # these values into registers.. hopefully this is not
220        # going to be the case
221        self.expect("frame variable cool_array",
222                    substrs=['[0] = i_am_cool @ 0x',
223                             '[1] = i_am_cool @ 0x',
224                             '[2] = i_am_cool @ 0x',
225                             '[3] = i_am_cool @ 0x',
226                             '[4] = i_am_cool @ 0x'])
227
228        # test getting same output by exploiting %T and %L together for
229        # aggregates
230        self.runCmd(
231            "type summary add --summary-string \"${var%T} @ ${var%L}\" i_am_cool")
232
233        # this test might fail if the compiler tries to store
234        # these values into registers.. hopefully this is not
235        # going to be the case
236        self.expect("frame variable cool_array",
237                    substrs=['[0] = i_am_cool @ 0x',
238                             '[1] = i_am_cool @ 0x',
239                             '[2] = i_am_cool @ 0x',
240                             '[3] = i_am_cool @ 0x',
241                             '[4] = i_am_cool @ 0x'])
242
243        self.runCmd("type summary add --summary-string \"goofy\" i_am_cool")
244        self.runCmd(
245            "type summary add --summary-string \"${var.second_cool%S}\" i_am_cooler")
246
247        self.expect("frame variable the_coolest_guy",
248                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
249
250        # check that unwanted type specifiers are removed
251        self.runCmd("type summary delete i_am_cool")
252        self.runCmd(
253            "type summary add --summary-string \"goofy\" \"class i_am_cool\"")
254        self.expect("frame variable the_coolest_guy",
255                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
256
257        self.runCmd("type summary delete i_am_cool")
258        self.runCmd(
259            "type summary add --summary-string \"goofy\" \"enum i_am_cool\"")
260        self.expect("frame variable the_coolest_guy",
261                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
262
263        self.runCmd("type summary delete i_am_cool")
264        self.runCmd(
265            "type summary add --summary-string \"goofy\" \"struct i_am_cool\"")
266        self.expect("frame variable the_coolest_guy",
267                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
268
269        # many spaces, but we still do the right thing
270        self.runCmd("type summary delete i_am_cool")
271        self.runCmd(
272            "type summary add --summary-string \"goofy\" \"union     i_am_cool\"")
273        self.expect("frame variable the_coolest_guy",
274                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
275
276        # but that not *every* specifier is removed
277        self.runCmd("type summary delete i_am_cool")
278        self.runCmd(
279            "type summary add --summary-string \"goofy\" \"wrong i_am_cool\"")
280        self.expect("frame variable the_coolest_guy", matching=False,
281                    substrs=['(i_am_cooler) the_coolest_guy = goofy'])
282
283        # check that formats are not sticking since that is the behavior we
284        # want
285        self.expect("frame variable iAmInt --format hex",
286                    substrs=['(int) iAmInt = 0x00000001'])
287        self.expect(
288            "frame variable iAmInt",
289            matching=False,
290            substrs=['(int) iAmInt = 0x00000001'])
291        self.expect("frame variable iAmInt", substrs=['(int) iAmInt = 1'])
292