1"""
2Test lldb data formatter subsystem.
3"""
4
5
6import lldb
7from lldbsuite.test.lldbtest import *
8import lldbsuite.test.lldbutil as lldbutil
9import re
10
11
12class AdvDataFormatterTestCase(TestBase):
13    def setUp(self):
14        # Call super's setUp().
15        TestBase.setUp(self)
16        # Find the line number to break at.
17        self.line = line_number("main.cpp", "// Set break point at this line.")
18
19    def test_with_run_command(self):
20        """Test that that file and class static variables display correctly."""
21        self.build()
22        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
23
24        lldbutil.run_break_set_by_file_and_line(
25            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True
26        )
27
28        self.runCmd("run", RUN_SUCCEEDED)
29
30        # The stop reason of the thread should be breakpoint.
31        self.expect(
32            "thread list",
33            STOPPED_DUE_TO_BREAKPOINT,
34            substrs=["stopped", "stop reason = breakpoint"],
35        )
36
37        # This is the function to remove the custom formats in order to have a
38        # clean slate for the next test case.
39        def cleanup():
40            self.runCmd("type format clear", check=False)
41            self.runCmd("type summary clear", check=False)
42            self.runCmd("settings set target.max-children-count 256", check=False)
43
44        # Execute the cleanup function during test case tear down.
45        self.addTearDownHook(cleanup)
46
47        self.runCmd('type summary add --summary-string "pippo" "i_am_cool"')
48
49        self.runCmd('type summary add --summary-string "pluto" -x "i_am_cool[a-z]*"')
50
51        self.expect("frame variable cool_boy", substrs=["pippo"])
52
53        self.expect("frame variable cooler_boy", substrs=["pluto"])
54
55        self.runCmd("type summary delete i_am_cool")
56
57        self.expect("frame variable cool_boy", substrs=["pluto"])
58
59        self.runCmd("type summary clear")
60
61        self.runCmd('type summary add --summary-string "${var[]}" -x "^int\\[[0-9]\\]')
62
63        self.expect("frame variable int_array", substrs=["1,2,3,4,5"])
64        self.expect("frame variable const_int_array", substrs=["11,12,13,14,15"])
65
66        # this will fail if we don't do [] as regex correctly
67        self.runCmd('type summary add --summary-string "${var[].integer}" "i_am_cool[]')
68
69        self.expect("frame variable cool_array", substrs=["1,1,1,1,6"])
70
71        self.runCmd("type summary clear")
72
73        self.runCmd('type summary add --summary-string "${var[1-0]%x}" "int"')
74
75        self.expect("frame variable iAmInt", substrs=["01"])
76
77        self.runCmd('type summary add --summary-string "${var[0-1]%x}" "int"')
78
79        self.expect("frame variable iAmInt", substrs=["01"])
80
81        self.runCmd("type summary clear")
82
83        self.runCmd('type summary add --summary-string "${var[0-1]%x}" int')
84        self.runCmd('type summary add --summary-string "${var[0-31]%x}" float')
85
86        self.expect("frame variable *pointer", substrs=["0x", "2"])
87
88        # check fix for <rdar://problem/11338654> LLDB crashes when using a
89        # "type summary" that uses bitfields with no format
90        self.runCmd('type summary add --summary-string "${var[0-1]}" int')
91        self.expect("frame variable iAmInt", substrs=["9 1"])
92
93        self.expect("frame variable cool_array[3].floating", substrs=["0x"])
94
95        self.runCmd(
96            'type summary add --summary-string "low bits are ${*var[0-1]} tgt is ${*var}" "int *"'
97        )
98
99        self.expect("frame variable pointer", substrs=["low bits are", "tgt is 6"])
100
101        self.expect(
102            'frame variable int_array --summary-string "${*var[0-1]}"', substrs=["3"]
103        )
104
105        self.runCmd("type summary clear")
106
107        self.runCmd('type summary add --summary-string "${var[0-1]}" -x "int\[[0-9]\]"')
108
109        self.expect("frame variable int_array", substrs=["1,2"])
110
111        self.runCmd('type summary add --summary-string "${var[0-1]}" "int[]"')
112
113        self.expect("frame variable int_array", substrs=["1,2"])
114
115        # Test the patterns are matched in reverse-chronological order.
116        self.runCmd('type summary add --summary-string "${var[2-3]}" "int[]"')
117
118        self.expect("frame variable int_array", substrs=["3,4"])
119
120        self.runCmd("type summary clear")
121
122        self.runCmd('type summary add -c -x "i_am_cool\[[0-9]\]"')
123        self.runCmd("type summary add -c i_am_cool")
124
125        self.expect(
126            "frame variable cool_array",
127            substrs=[
128                "[0]",
129                "integer",
130                "floating",
131                "character",
132                "[1]",
133                "integer",
134                "floating",
135                "character",
136                "[2]",
137                "integer",
138                "floating",
139                "character",
140                "[3]",
141                "integer",
142                "floating",
143                "character",
144                "[4]",
145                "integer",
146                "floating",
147                "character",
148            ],
149        )
150
151        self.runCmd(
152            'type summary add --summary-string "int = ${*var.int_pointer}, float = ${*var.float_pointer}" IWrapPointers'
153        )
154
155        self.expect("frame variable wrapper", substrs=["int = 4", "float = 1.1"])
156
157        self.runCmd(
158            'type summary add --summary-string "low bits = ${*var.int_pointer[2]}" IWrapPointers -p'
159        )
160
161        self.expect("frame variable wrapper", substrs=["low bits = 1"])
162
163        self.expect("frame variable *wrap_pointer", substrs=["low bits = 1"])
164
165        self.runCmd("type summary clear")
166
167        self.expect(
168            'frame variable int_array --summary-string "${var[0][0-2]%hex}"',
169            substrs=["0x", "7"],
170        )
171
172        self.runCmd("type summary clear")
173
174        self.runCmd(
175            'type summary add --summary-string "${*var[].x[0-3]%hex} is a bitfield on a set of integers" -x "SimpleWithPointers\[[0-9]\]"'
176        )
177
178        self.expect(
179            'frame variable couple --summary-string "${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}"',
180            substrs=[
181                "1 are low bits of integer 9.",
182                "If I pretend it is an array I get [9,",
183            ],
184        )
185
186        # if the summary has an error, we still display the value
187        self.expect(
188            'frame variable couple --summary-string "${*var.sp.foo[0-2]"',
189            substrs=["(Couple) couple = {", "x = 0x", "y = 0x", "z = 0x", "s = 0x"],
190        )
191
192        self.runCmd(
193            'type summary add --summary-string "${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}" Couple'
194        )
195
196        self.expect(
197            "frame variable sparray", substrs=["[0x0000000f,0x0000000c,0x00000009]"]
198        )
199
200        # check that we can format a variable in a summary even if a format is
201        # defined for its datatype
202        self.runCmd("type format add -f hex int")
203        self.runCmd('type summary add --summary-string "x=${var.x%d}" Simple')
204
205        self.expect("frame variable a_simple_object", substrs=["x=3"])
206
207        self.expect("frame variable a_simple_object", matching=False, substrs=["0x0"])
208
209        # now check that the default is applied if we do not hand out a format
210        self.runCmd('type summary add --summary-string "x=${var.x}" Simple')
211
212        self.expect("frame variable a_simple_object", matching=False, substrs=["x=3"])
213
214        self.expect(
215            "frame variable a_simple_object", matching=True, substrs=["x=0x00000003"]
216        )
217
218        self.expect_var_path("constInt", value="0x0000002a")
219
220        self.expect_var_path("volatileInt", value="0x0000002b")
221
222        self.expect_var_path("constVolatileInt", value="0x0000002c")
223
224        # check that we can correctly cap the number of children shown
225        self.runCmd("settings set target.max-children-count 5")
226
227        self.expect(
228            "frame variable a_long_guy",
229            matching=True,
230            substrs=["a_1", "b_1", "c_1", "d_1", "e_1", "..."],
231        )
232
233        # check that no further stuff is printed (not ALL values are checked!)
234        self.expect(
235            "frame variable a_long_guy",
236            matching=False,
237            substrs=[
238                "f_1",
239                "g_1",
240                "h_1",
241                "i_1",
242                "j_1",
243                "q_1",
244                "a_2",
245                "f_2",
246                "t_2",
247                "w_2",
248            ],
249        )
250
251        self.runCmd("settings set target.max-children-count 1")
252        self.expect("frame variable a_long_guy", matching=True, substrs=["a_1", "..."])
253        self.expect(
254            "frame variable a_long_guy",
255            matching=False,
256            substrs=["b_1", "c_1", "d_1", "e_1"],
257        )
258        self.expect(
259            "frame variable a_long_guy",
260            matching=False,
261            substrs=[
262                "f_1",
263                "g_1",
264                "h_1",
265                "i_1",
266                "j_1",
267                "q_1",
268                "a_2",
269                "f_2",
270                "t_2",
271                "w_2",
272            ],
273        )
274
275        self.runCmd("settings set target.max-children-count 30")
276        self.expect(
277            "frame variable a_long_guy",
278            matching=True,
279            substrs=[
280                "a_1",
281                "b_1",
282                "c_1",
283                "d_1",
284                "e_1",
285                "z_1",
286                "a_2",
287                "b_2",
288                "c_2",
289                "d_2",
290                "...",
291            ],
292        )
293        self.expect(
294            "frame variable a_long_guy",
295            matching=False,
296            substrs=["e_2", "n_2", "r_2", "i_2", "k_2", "o_2"],
297        )
298
299        self.runCmd("settings set target.max-string-summary-length 5")
300        some_string = self.frame().FindVariable("some_string")
301        some_string_summary = some_string.GetSummary()
302        if re.match(r"^std::__\w+::", some_string.GetTypeName()):
303            self.assertEqual(some_string_summary, '"01234"...')
304        else:
305            # libstdc++ string formatter suffers from the same problem as some_cstring below
306            pass
307
308        some_carr = self.frame().FindVariable("some_carr")
309        some_carr_summary = some_carr.GetSummary()
310        self.assertEqual(some_carr_summary, '"01234"...')
311
312        # FIXME: c-strings should honor the target.max-string-summary-length
313        # setting. Currently a C-string will be truncated at 64 (an internal
314        # implementation detail) instead of the value specified in the setting.
315        some_cstring = self.frame().FindVariable("some_cstring")
316        some_cstring_summary = some_cstring.GetSummary()
317        self.assertEqual(len(some_cstring_summary), 66)  # 64 + 2 (for quotation marks)
318        self.assertFalse(some_cstring_summary.endswith("..."))
319
320        # override the cap
321        self.expect(
322            "frame variable a_long_guy --show-all-children",
323            matching=True,
324            substrs=[
325                "a_1",
326                "b_1",
327                "c_1",
328                "d_1",
329                "e_1",
330                "z_1",
331                "a_2",
332                "b_2",
333                "c_2",
334                "d_2",
335            ],
336        )
337        self.expect(
338            "frame variable a_long_guy --show-all-children",
339            matching=True,
340            substrs=[
341                "e_2",
342                "i_2",
343                "k_2",
344                "n_2",
345                "o_2",
346                "r_2",
347            ],
348        )
349        self.expect(
350            "frame variable a_long_guy --show-all-children",
351            matching=False,
352            substrs=["..."],
353        )
354