1"""
2Test lldb data formatter subsystem.
3"""
4
5
6
7import lldb
8from lldbsuite.test.lldbtest import *
9import lldbsuite.test.lldbutil as lldbutil
10
11
12class ScriptDataFormatterTestCase(TestBase):
13
14    def test_with_run_command(self):
15        """Test data formatter commands."""
16        self.build()
17        self.data_formatter_commands()
18
19    def setUp(self):
20        # Call super's setUp().
21        TestBase.setUp(self)
22        # Find the line number to break at.
23        self.line = line_number('main.cpp', '// Set break point at this line.')
24
25    def data_formatter_commands(self):
26        """Test that that file and class static variables display correctly."""
27        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
28
29        lldbutil.run_break_set_by_file_and_line(
30            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
31
32        self.runCmd("run", RUN_SUCCEEDED)
33
34        # The stop reason of the thread should be breakpoint.
35        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
36                    substrs=['stopped',
37                             'stop reason = breakpoint'])
38
39        # This is the function to remove the custom formats in order to have a
40        # clean slate for the next test case.
41        def cleanup():
42            self.runCmd('type format clear', check=False)
43            self.runCmd('type summary clear', check=False)
44
45        # Execute the cleanup function during test case tear down.
46        self.addTearDownHook(cleanup)
47
48        # Set the script here to ease the formatting
49        script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');'
50
51        self.runCmd(
52            "type summary add i_am_cool --python-script \"%s\"" %
53            script)
54        self.expect('type summary list i_am_cool', substrs=[script])
55
56        self.expect("frame variable one",
57                    substrs=['Hello from Python',
58                             '1 time!'])
59
60        self.expect("frame variable two",
61                    substrs=['Hello from Python',
62                             '4 times!'])
63
64        self.runCmd("n")  # skip ahead to make values change
65
66        self.expect("frame variable three",
67                    substrs=['Hello from Python, 10 times!',
68                             'Hello from Python, 4 times!'])
69
70        self.runCmd("n")  # skip ahead to make values change
71
72        self.expect("frame variable two",
73                    substrs=['Hello from Python',
74                             '1 time!'])
75
76        script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'int says \' + a_val; return str;'
77
78        # Check that changes in the script are immediately reflected
79        self.runCmd(
80            "type summary add i_am_cool --python-script \"%s\"" %
81            script)
82
83        self.expect("frame variable two",
84                    substrs=['int says 1'])
85
86        self.expect("frame variable twoptr",
87                    substrs=['int says 1'])
88
89        # Change the summary
90        self.runCmd(
91            "type summary add --summary-string \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool")
92
93        self.expect("frame variable two",
94                    substrs=['int says 1',
95                             'and float says 2.71'])
96        # Try it for pointers
97        self.expect("frame variable twoptr",
98                    substrs=['int says 1',
99                             'and float says 2.71'])
100
101        # Force a failure for pointers
102        self.runCmd(
103            "type summary add i_am_cool -p --python-script \"%s\"" %
104            script)
105
106        self.expect("frame variable twoptr", matching=False,
107                    substrs=['and float says 2.71'])
108
109        script = 'return \'Python summary\''
110
111        self.runCmd(
112            "type summary add --name test_summary --python-script \"%s\"" %
113            script)
114
115        # attach the Python named summary to someone
116        self.expect("frame variable one --summary test_summary",
117                    substrs=['Python summary'])
118
119        # should not bind to the type
120        self.expect("frame variable two", matching=False,
121                    substrs=['Python summary'])
122
123        # and should not stick to the variable
124        self.expect("frame variable one", matching=False,
125                    substrs=['Python summary'])
126
127        self.runCmd(
128            "type summary add i_am_cool --summary-string \"Text summary\"")
129
130        # should be temporary only
131        self.expect("frame variable one", matching=False,
132                    substrs=['Python summary'])
133
134        # use the type summary
135        self.expect("frame variable two",
136                    substrs=['Text summary'])
137
138        self.runCmd("n")  # skip ahead to make values change
139
140        # both should use the type summary now
141        self.expect("frame variable one",
142                    substrs=['Text summary'])
143
144        self.expect("frame variable two",
145                    substrs=['Text summary'])
146
147        # disable type summary for pointers, and make a Python regex summary
148        self.runCmd(
149            "type summary add i_am_cool -p --summary-string \"Text summary\"")
150        self.runCmd("type summary add -x cool --python-script \"%s\"" % script)
151
152        # variables should stick to the type summary
153        self.expect("frame variable one",
154                    substrs=['Text summary'])
155
156        self.expect("frame variable two",
157                    substrs=['Text summary'])
158
159        # array and pointer should match the Python one
160        self.expect("frame variable twoptr",
161                    substrs=['Python summary'])
162
163        self.expect("frame variable array",
164                    substrs=['Python summary'])
165
166        # return pointers to the type summary
167        self.runCmd(
168            "type summary add i_am_cool --summary-string \"Text summary\"")
169
170        self.expect("frame variable one",
171                    substrs=['Text summary'])
172
173        self.expect("frame variable two",
174                    substrs=['Text summary'])
175
176        self.expect("frame variable twoptr",
177                    substrs=['Text summary'])
178
179        self.expect("frame variable array",
180                    substrs=['Python summary'])
181