| """ | |
| Test that SBFrame::GetVariables() calls work correctly. | |
| """ | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbplatform | |
| from lldbsuite.test import lldbutil | |
| def get_names_from_value_list(value_list): | |
| names = list() | |
| for value in value_list: | |
| names.append(value.GetName()) | |
| return names | |
| class TestGetVariables(TestBase): | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| self.source = "main.c" | |
| def verify_variable_names(self, description, value_list, names): | |
| copy_names = list(names) | |
| actual_names = get_names_from_value_list(value_list) | |
| for name in actual_names: | |
| if name in copy_names: | |
| copy_names.remove(name) | |
| else: | |
| self.assertTrue(False, "didn't find '%s' in %s" % (name, copy_names)) | |
| self.assertEqual( | |
| len(copy_names), | |
| 0, | |
| "%s: we didn't find variables: %s in value list (%s)" | |
| % (description, copy_names, actual_names), | |
| ) | |
| @expectedFailureAll(debug_info=["pdb"], bugnumber="llvm.org/pr149498") | |
| def test(self): | |
| self.build() | |
| # Set debugger into synchronous mode | |
| self.dbg.SetAsync(False) | |
| # Create a target by the debugger. | |
| exe = self.getBuildArtifact("a.out") | |
| target = self.dbg.CreateTarget(exe) | |
| self.assertTrue(target, VALID_TARGET) | |
| line1 = line_number(self.source, "// breakpoint 1") | |
| line2 = line_number(self.source, "// breakpoint 2") | |
| line3 = line_number(self.source, "// breakpoint 3") | |
| breakpoint1 = target.BreakpointCreateByLocation(self.source, line1) | |
| breakpoint2 = target.BreakpointCreateByLocation(self.source, line2) | |
| breakpoint3 = target.BreakpointCreateByLocation(self.source, line3) | |
| self.assertGreaterEqual(breakpoint1.GetNumLocations(), 1, PROCESS_IS_VALID) | |
| self.assertGreaterEqual(breakpoint2.GetNumLocations(), 1, PROCESS_IS_VALID) | |
| self.assertGreaterEqual(breakpoint3.GetNumLocations(), 1, PROCESS_IS_VALID) | |
| # Register our shared libraries for remote targets so they get | |
| # automatically uploaded | |
| arguments = None | |
| environment = None | |
| # Now launch the process, and do not stop at entry point. | |
| process = target.LaunchSimple( | |
| arguments, environment, self.get_process_working_directory() | |
| ) | |
| self.assertTrue(process, PROCESS_IS_VALID) | |
| threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint1) | |
| self.assertEqual( | |
| len(threads), 1, "There should be a thread stopped at breakpoint 1" | |
| ) | |
| thread = threads[0] | |
| self.assertTrue(thread.IsValid(), "Thread must be valid") | |
| frame = thread.GetFrameAtIndex(0) | |
| self.assertTrue(frame.IsValid(), "Frame must be valid") | |
| arg_names = ["argc", "argv"] | |
| local_names = ["i", "j", "k"] | |
| static_names = ["static_var", "g_global_var", "g_static_var"] | |
| breakpoint1_locals = ["i"] | |
| breakpoint1_statics = ["static_var"] | |
| num_args = len(arg_names) | |
| num_locals = len(local_names) | |
| num_statics = len(static_names) | |
| args_yes = True | |
| args_no = False | |
| locals_yes = True | |
| locals_no = False | |
| statics_yes = True | |
| statics_no = False | |
| in_scopy_only = True | |
| ignore_scope = False | |
| # Verify if we ask for only arguments that we got what we expect | |
| vars = frame.GetVariables(args_yes, locals_no, statics_no, ignore_scope) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| num_args, | |
| "There should be %i arguments, but we are reporting %i" | |
| % (num_args, vars.GetSize()), | |
| ) | |
| self.verify_variable_names("check names of arguments", vars, arg_names) | |
| self.assertEqual( | |
| len(arg_names), | |
| num_args, | |
| "make sure verify_variable_names() didn't mutate list", | |
| ) | |
| # Verify if we ask for only locals that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_yes, statics_no, ignore_scope) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| num_locals, | |
| "There should be %i local variables, but we are reporting %i" | |
| % (num_locals, vars.GetSize()), | |
| ) | |
| self.verify_variable_names("check names of locals", vars, local_names) | |
| # Verify if we ask for only statics that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_no, statics_yes, ignore_scope) | |
| print("statics: ", str(vars)) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| num_statics, | |
| "There should be %i static variables, but we are reporting %i" | |
| % (num_statics, vars.GetSize()), | |
| ) | |
| self.verify_variable_names("check names of statics", vars, static_names) | |
| # Verify if we ask for arguments and locals that we got what we expect | |
| vars = frame.GetVariables(args_yes, locals_yes, statics_no, ignore_scope) | |
| desc = "arguments + locals" | |
| names = arg_names + local_names | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Verify if we ask for arguments and statics that we got what we expect | |
| vars = frame.GetVariables(args_yes, locals_no, statics_yes, ignore_scope) | |
| desc = "arguments + statics" | |
| names = arg_names + static_names | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Verify if we ask for locals and statics that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_yes, statics_yes, ignore_scope) | |
| desc = "locals + statics" | |
| names = local_names + static_names | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Verify if we ask for arguments, locals and statics that we got what | |
| # we expect | |
| vars = frame.GetVariables(args_yes, locals_yes, statics_yes, ignore_scope) | |
| desc = "arguments + locals + statics" | |
| names = arg_names + local_names + static_names | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Verify if we ask for in scope locals that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) | |
| desc = "in scope locals at breakpoint 1" | |
| names = ["i"] | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Continue to breakpoint 2 | |
| process.Continue() | |
| threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint2) | |
| self.assertEqual( | |
| len(threads), 1, "There should be a thread stopped at breakpoint 2" | |
| ) | |
| thread = threads[0] | |
| self.assertTrue(thread.IsValid(), "Thread must be valid") | |
| frame = thread.GetFrameAtIndex(0) | |
| self.assertTrue(frame.IsValid(), "Frame must be valid") | |
| # Verify if we ask for in scope locals that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) | |
| desc = "in scope locals at breakpoint 2" | |
| names = ["i", "j"] | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) | |
| # Continue to breakpoint 3 | |
| process.Continue() | |
| threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint3) | |
| self.assertEqual( | |
| len(threads), 1, "There should be a thread stopped at breakpoint 3" | |
| ) | |
| thread = threads[0] | |
| self.assertTrue(thread.IsValid(), "Thread must be valid") | |
| frame = thread.GetFrameAtIndex(0) | |
| self.assertTrue(frame.IsValid(), "Frame must be valid") | |
| # Verify if we ask for in scope locals that we got what we expect | |
| vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) | |
| desc = "in scope locals at breakpoint 3" | |
| names = ["i", "j", "k"] | |
| count = len(names) | |
| self.assertEqual( | |
| vars.GetSize(), | |
| count, | |
| "There should be %i %s (%s) but we are reporting %i (%s)" | |
| % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars)), | |
| ) | |
| self.verify_variable_names("check names of %s" % (desc), vars, names) |