
This uses [teyit](https://pypi.org/project/teyit/) to modernize asserts, as recommended by the [unittest release notes](https://docs.python.org/3.12/whatsnew/3.12.html#id3). For example, `assertTrue(a == b)` is replaced with `assertEqual(a, b)`. This produces better error messages, e.g. `error: unexpectedly found 1 and 2 to be different` instead of `error: False`.
254 lines
9.7 KiB
Python
254 lines
9.7 KiB
Python
"""
|
|
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),
|
|
)
|
|
|
|
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)
|