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