1"""
2Test that SBFrame::GetVariables() calls work correctly.
3"""
4
5from __future__ import print_function
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbplatform
12from lldbsuite.test import lldbutil
13
14
15def get_names_from_value_list(value_list):
16    names = list()
17    for value in value_list:
18        names.append(value.GetName())
19    return names
20
21
22class TestGetVariables(TestBase):
23
24    mydir = TestBase.compute_mydir(__file__)
25
26    def setUp(self):
27        # Call super's setUp().
28        TestBase.setUp(self)
29        self.source = 'main.c'
30
31    def verify_variable_names(self, description, value_list, names):
32        copy_names = list(names)
33        actual_names = get_names_from_value_list(value_list)
34        for name in actual_names:
35            if name in copy_names:
36                copy_names.remove(name)
37            else:
38                self.assertTrue(
39                    False, "didn't find '%s' in %s" %
40                    (name, copy_names))
41        self.assertEqual(
42            len(copy_names), 0, "%s: we didn't find variables: %s in value list (%s)" %
43            (description, copy_names, actual_names))
44
45    def test(self):
46        self.build()
47
48        # Set debugger into synchronous mode
49        self.dbg.SetAsync(False)
50
51        # Create a target by the debugger.
52        exe = self.getBuildArtifact("a.out")
53        target = self.dbg.CreateTarget(exe)
54        self.assertTrue(target, VALID_TARGET)
55
56        line1 = line_number(self.source, '// breakpoint 1')
57        line2 = line_number(self.source, '// breakpoint 2')
58        line3 = line_number(self.source, '// breakpoint 3')
59
60        breakpoint1 = target.BreakpointCreateByLocation(self.source, line1)
61        breakpoint2 = target.BreakpointCreateByLocation(self.source, line2)
62        breakpoint3 = target.BreakpointCreateByLocation(self.source, line3)
63
64        self.assertTrue(breakpoint1.GetNumLocations() >= 1, PROCESS_IS_VALID)
65        self.assertTrue(breakpoint2.GetNumLocations() >= 1, PROCESS_IS_VALID)
66        self.assertTrue(breakpoint3.GetNumLocations() >= 1, PROCESS_IS_VALID)
67
68        # Register our shared libraries for remote targets so they get
69        # automatically uploaded
70        arguments = None
71        environment = None
72
73        # Now launch the process, and do not stop at entry point.
74        process = target.LaunchSimple(
75            arguments, environment, self.get_process_working_directory())
76        self.assertTrue(process, PROCESS_IS_VALID)
77
78        threads = lldbutil.get_threads_stopped_at_breakpoint(
79            process, breakpoint1)
80        self.assertEqual(
81            len(threads),
82            1,
83            "There should be a thread stopped at breakpoint 1")
84
85        thread = threads[0]
86        self.assertTrue(thread.IsValid(), "Thread must be valid")
87        frame = thread.GetFrameAtIndex(0)
88        self.assertTrue(frame.IsValid(), "Frame must be valid")
89
90        arg_names = ['argc', 'argv']
91        local_names = ['i', 'j', 'k']
92        static_names = ['static_var', 'g_global_var', 'g_static_var']
93        breakpoint1_locals = ['i']
94        breakpoint1_statics = ['static_var']
95        num_args = len(arg_names)
96        num_locals = len(local_names)
97        num_statics = len(static_names)
98        args_yes = True
99        args_no = False
100        locals_yes = True
101        locals_no = False
102        statics_yes = True
103        statics_no = False
104        in_scopy_only = True
105        ignore_scope = False
106
107        # Verify if we ask for only arguments that we got what we expect
108        vars = frame.GetVariables(
109            args_yes, locals_no, statics_no, ignore_scope)
110        self.assertEqual(
111            vars.GetSize(),
112            num_args,
113            "There should be %i arguments, but we are reporting %i" %
114            (num_args,
115             vars.GetSize()))
116        self.verify_variable_names("check names of arguments", vars, arg_names)
117        self.assertEqual(
118            len(arg_names),
119            num_args,
120            "make sure verify_variable_names() didn't mutate list")
121
122        # Verify if we ask for only locals that we got what we expect
123        vars = frame.GetVariables(
124            args_no, locals_yes, statics_no, ignore_scope)
125        self.assertEqual(
126            vars.GetSize(),
127            num_locals,
128            "There should be %i local variables, but we are reporting %i" %
129            (num_locals,
130             vars.GetSize()))
131        self.verify_variable_names("check names of locals", vars, local_names)
132
133        # Verify if we ask for only statics that we got what we expect
134        vars = frame.GetVariables(
135            args_no, locals_no, statics_yes, ignore_scope)
136        print('statics: ', str(vars))
137        self.assertEqual(
138            vars.GetSize(),
139            num_statics,
140            "There should be %i static variables, but we are reporting %i" %
141            (num_statics,
142             vars.GetSize()))
143        self.verify_variable_names(
144            "check names of statics", vars, static_names)
145
146        # Verify if we ask for arguments and locals that we got what we expect
147        vars = frame.GetVariables(
148            args_yes, locals_yes, statics_no, ignore_scope)
149        desc = 'arguments + locals'
150        names = arg_names + local_names
151        count = len(names)
152        self.assertEqual(
153            vars.GetSize(),
154            count,
155            "There should be %i %s (%s) but we are reporting %i (%s)" %
156            (count,
157             desc,
158             names,
159             vars.GetSize(),
160             get_names_from_value_list(vars)))
161        self.verify_variable_names("check names of %s" % (desc), vars, names)
162
163        # Verify if we ask for arguments and statics that we got what we expect
164        vars = frame.GetVariables(
165            args_yes, locals_no, statics_yes, ignore_scope)
166        desc = 'arguments + statics'
167        names = arg_names + static_names
168        count = len(names)
169        self.assertEqual(
170            vars.GetSize(),
171            count,
172            "There should be %i %s (%s) but we are reporting %i (%s)" %
173            (count,
174             desc,
175             names,
176             vars.GetSize(),
177             get_names_from_value_list(vars)))
178        self.verify_variable_names("check names of %s" % (desc), vars, names)
179
180        # Verify if we ask for locals and statics that we got what we expect
181        vars = frame.GetVariables(
182            args_no, locals_yes, statics_yes, ignore_scope)
183        desc = 'locals + statics'
184        names = local_names + static_names
185        count = len(names)
186        self.assertEqual(
187            vars.GetSize(),
188            count,
189            "There should be %i %s (%s) but we are reporting %i (%s)" %
190            (count,
191             desc,
192             names,
193             vars.GetSize(),
194             get_names_from_value_list(vars)))
195        self.verify_variable_names("check names of %s" % (desc), vars, names)
196
197        # Verify if we ask for arguments, locals and statics that we got what
198        # we expect
199        vars = frame.GetVariables(
200            args_yes, locals_yes, statics_yes, ignore_scope)
201        desc = 'arguments + locals + statics'
202        names = arg_names + local_names + static_names
203        count = len(names)
204        self.assertEqual(
205            vars.GetSize(),
206            count,
207            "There should be %i %s (%s) but we are reporting %i (%s)" %
208            (count,
209             desc,
210             names,
211             vars.GetSize(),
212             get_names_from_value_list(vars)))
213        self.verify_variable_names("check names of %s" % (desc), vars, names)
214
215        # Verify if we ask for in scope locals that we got what we expect
216        vars = frame.GetVariables(
217            args_no, locals_yes, statics_no, in_scopy_only)
218        desc = 'in scope locals at breakpoint 1'
219        names = ['i']
220        count = len(names)
221        self.assertEqual(
222            vars.GetSize(),
223            count,
224            "There should be %i %s (%s) but we are reporting %i (%s)" %
225            (count,
226             desc,
227             names,
228             vars.GetSize(),
229             get_names_from_value_list(vars)))
230        self.verify_variable_names("check names of %s" % (desc), vars, names)
231
232        # Continue to breakpoint 2
233        process.Continue()
234
235        threads = lldbutil.get_threads_stopped_at_breakpoint(
236            process, breakpoint2)
237        self.assertEqual(
238            len(threads),
239            1,
240            "There should be a thread stopped at breakpoint 2")
241
242        thread = threads[0]
243        self.assertTrue(thread.IsValid(), "Thread must be valid")
244        frame = thread.GetFrameAtIndex(0)
245        self.assertTrue(frame.IsValid(), "Frame must be valid")
246
247        # Verify if we ask for in scope locals that we got what we expect
248        vars = frame.GetVariables(
249            args_no, locals_yes, statics_no, in_scopy_only)
250        desc = 'in scope locals at breakpoint 2'
251        names = ['i', 'j']
252        count = len(names)
253        self.assertEqual(
254            vars.GetSize(),
255            count,
256            "There should be %i %s (%s) but we are reporting %i (%s)" %
257            (count,
258             desc,
259             names,
260             vars.GetSize(),
261             get_names_from_value_list(vars)))
262        self.verify_variable_names("check names of %s" % (desc), vars, names)
263
264        # Continue to breakpoint 3
265        process.Continue()
266
267        threads = lldbutil.get_threads_stopped_at_breakpoint(
268            process, breakpoint3)
269        self.assertEqual(
270            len(threads),
271            1,
272            "There should be a thread stopped at breakpoint 3")
273
274        thread = threads[0]
275        self.assertTrue(thread.IsValid(), "Thread must be valid")
276        frame = thread.GetFrameAtIndex(0)
277        self.assertTrue(frame.IsValid(), "Frame must be valid")
278
279        # Verify if we ask for in scope locals that we got what we expect
280        vars = frame.GetVariables(
281            args_no, locals_yes, statics_no, in_scopy_only)
282        desc = 'in scope locals at breakpoint 3'
283        names = ['i', 'j', 'k']
284        count = len(names)
285        self.assertEqual(
286            vars.GetSize(),
287            count,
288            "There should be %i %s (%s) but we are reporting %i (%s)" %
289            (count,
290             desc,
291             names,
292             vars.GetSize(),
293             get_names_from_value_list(vars)))
294        self.verify_variable_names("check names of %s" % (desc), vars, names)
295