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