541 lines
20 KiB
Python
541 lines
20 KiB
Python
|
"""
|
||
|
Test breakpoint serialization.
|
||
|
"""
|
||
|
|
||
|
import os
|
||
|
import json
|
||
|
import lldb
|
||
|
from lldbsuite.test.decorators import *
|
||
|
from lldbsuite.test.lldbtest import *
|
||
|
from lldbsuite.test import lldbutil
|
||
|
|
||
|
|
||
|
class BreakpointSerialization(TestBase):
|
||
|
NO_DEBUG_INFO_TESTCASE = True
|
||
|
|
||
|
@add_test_categories(["pyapi"])
|
||
|
def test_resolvers(self):
|
||
|
"""Use Python APIs to test that we serialize resolvers."""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_resolvers()
|
||
|
|
||
|
def test_filters(self):
|
||
|
"""Use Python APIs to test that we serialize search filters correctly."""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_filters()
|
||
|
|
||
|
def test_options(self):
|
||
|
"""Use Python APIs to test that we serialize breakpoint options correctly."""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_options()
|
||
|
|
||
|
def test_appending(self):
|
||
|
"""Use Python APIs to test that we serialize breakpoint options correctly."""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_appending()
|
||
|
|
||
|
def test_name_filters(self):
|
||
|
"""Use python APIs to test that reading in by name works correctly."""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_names()
|
||
|
|
||
|
def test_scripted_extra_args(self):
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
self.do_check_extra_args()
|
||
|
|
||
|
def test_resolver_serialization(self):
|
||
|
"""Test that breakpoint resolvers contain the expected information"""
|
||
|
self.build()
|
||
|
self.setup_targets_and_cleanup()
|
||
|
|
||
|
exe_path = self.getBuildArtifact("a.out")
|
||
|
exe_module = self.orig_target.module["a.out"]
|
||
|
self.assertTrue(
|
||
|
exe_module.IsValid(), "Failed to find the executable module in target"
|
||
|
)
|
||
|
sym_ctx_list = exe_module.FindFunctions("main")
|
||
|
self.assertTrue(sym_ctx_list.GetSize() == 1, "Unable to find function 'main'")
|
||
|
sym_ctx = sym_ctx_list.GetContextAtIndex(0)
|
||
|
self.assertTrue(
|
||
|
sym_ctx.IsValid(), "SBSymbolContext representing function 'main' is invalid"
|
||
|
)
|
||
|
main_func = sym_ctx.GetFunction()
|
||
|
self.assertTrue(
|
||
|
main_func.IsValid(), "SBFunction representing 'main' is invalid"
|
||
|
)
|
||
|
main_addr = main_func.GetStartAddress()
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateBySBAddress(main_addr)
|
||
|
self.assertTrue(
|
||
|
bkpt.IsValid(), "Could not place breakpoint on 'main' by address"
|
||
|
)
|
||
|
stream = lldb.SBStream()
|
||
|
sd = bkpt.SerializeToStructuredData()
|
||
|
sd.GetAsJSON(stream)
|
||
|
serialized_data = json.loads(stream.GetData())
|
||
|
|
||
|
self.assertIn(
|
||
|
exe_path,
|
||
|
serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["ModuleName"],
|
||
|
)
|
||
|
|
||
|
def test_structured_data_serialization(self):
|
||
|
target = self.dbg.GetDummyTarget()
|
||
|
self.assertTrue(target.IsValid(), VALID_TARGET)
|
||
|
|
||
|
interpreter = self.dbg.GetCommandInterpreter()
|
||
|
result = lldb.SBCommandReturnObject()
|
||
|
interpreter.HandleCommand("br set -f foo -l 42", result)
|
||
|
result = lldb.SBCommandReturnObject()
|
||
|
interpreter.HandleCommand("br set -c 'argc == 1' -n main", result)
|
||
|
|
||
|
bkp1 = target.GetBreakpointAtIndex(0)
|
||
|
self.assertTrue(bkp1.IsValid(), VALID_BREAKPOINT)
|
||
|
stream = lldb.SBStream()
|
||
|
sd = bkp1.SerializeToStructuredData()
|
||
|
sd.GetAsJSON(stream)
|
||
|
serialized_data = json.loads(stream.GetData())
|
||
|
self.assertEqual(
|
||
|
serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["FileName"], "foo"
|
||
|
)
|
||
|
self.assertEqual(
|
||
|
serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["LineNumber"], 42
|
||
|
)
|
||
|
|
||
|
bkp2 = target.GetBreakpointAtIndex(1)
|
||
|
self.assertTrue(bkp2.IsValid(), VALID_BREAKPOINT)
|
||
|
stream = lldb.SBStream()
|
||
|
sd = bkp2.SerializeToStructuredData()
|
||
|
sd.GetAsJSON(stream)
|
||
|
serialized_data = json.loads(stream.GetData())
|
||
|
self.assertIn(
|
||
|
"main",
|
||
|
serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["SymbolNames"],
|
||
|
)
|
||
|
self.assertEqual(
|
||
|
serialized_data["Breakpoint"]["BKPTOptions"]["ConditionText"], "argc == 1"
|
||
|
)
|
||
|
|
||
|
invalid_bkp = lldb.SBBreakpoint()
|
||
|
self.assertFalse(invalid_bkp.IsValid(), "Breakpoint should not be valid.")
|
||
|
stream = lldb.SBStream()
|
||
|
sd = invalid_bkp.SerializeToStructuredData()
|
||
|
sd.GetAsJSON(stream)
|
||
|
self.assertFalse(
|
||
|
stream.GetData(), "Invalid breakpoint should have an empty structured data"
|
||
|
)
|
||
|
|
||
|
def setup_targets_and_cleanup(self):
|
||
|
def cleanup():
|
||
|
self.RemoveTempFile(self.bkpts_file_path)
|
||
|
|
||
|
if self.orig_target.IsValid():
|
||
|
self.dbg.DeleteTarget(self.orig_target)
|
||
|
self.dbg.DeleteTarget(self.copy_target)
|
||
|
|
||
|
self.addTearDownHook(cleanup)
|
||
|
self.RemoveTempFile(self.bkpts_file_path)
|
||
|
|
||
|
exe = self.getBuildArtifact("a.out")
|
||
|
|
||
|
# Create the targets we are making breakpoints in and copying them to:
|
||
|
self.orig_target = self.dbg.CreateTarget(exe)
|
||
|
self.assertTrue(self.orig_target, VALID_TARGET)
|
||
|
|
||
|
self.copy_target = self.dbg.CreateTarget(exe)
|
||
|
self.assertTrue(self.copy_target, VALID_TARGET)
|
||
|
|
||
|
def setUp(self):
|
||
|
# Call super's setUp().
|
||
|
TestBase.setUp(self)
|
||
|
|
||
|
self.bkpts_file_path = self.getBuildArtifact("breakpoints.json")
|
||
|
self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)
|
||
|
|
||
|
def check_equivalence(self, source_bps, do_write=True):
|
||
|
error = lldb.SBError()
|
||
|
|
||
|
if do_write:
|
||
|
error = self.orig_target.BreakpointsWriteToFile(
|
||
|
self.bkpts_file_spec, source_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed writing breakpoints to file")
|
||
|
|
||
|
copy_bps = lldb.SBBreakpointList(self.copy_target)
|
||
|
error = self.copy_target.BreakpointsCreateFromFile(
|
||
|
self.bkpts_file_spec, copy_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed reading breakpoints from file")
|
||
|
|
||
|
num_source_bps = source_bps.GetSize()
|
||
|
num_copy_bps = copy_bps.GetSize()
|
||
|
self.assertEqual(
|
||
|
num_source_bps,
|
||
|
num_copy_bps,
|
||
|
"Didn't get same number of input and output breakpoints - orig: %d copy: %d"
|
||
|
% (num_source_bps, num_copy_bps),
|
||
|
)
|
||
|
|
||
|
for i in range(0, num_source_bps):
|
||
|
source_bp = source_bps.GetBreakpointAtIndex(i)
|
||
|
source_desc = lldb.SBStream()
|
||
|
source_bp.GetDescription(source_desc, False)
|
||
|
source_text = source_desc.GetData()
|
||
|
|
||
|
# I am assuming here that the breakpoints will get written out in breakpoint ID order, and
|
||
|
# read back in ditto. That is true right now, and I can't see any reason to do it differently
|
||
|
# but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to
|
||
|
# see which one is which.
|
||
|
copy_id = source_bp.GetID()
|
||
|
copy_bp = copy_bps.FindBreakpointByID(copy_id)
|
||
|
self.assertTrue(
|
||
|
copy_bp.IsValid(), "Could not find copy breakpoint %d." % (copy_id)
|
||
|
)
|
||
|
|
||
|
copy_desc = lldb.SBStream()
|
||
|
copy_bp.GetDescription(copy_desc, False)
|
||
|
copy_text = copy_desc.GetData()
|
||
|
|
||
|
# These two should be identical.
|
||
|
self.trace("Source text for %d is %s." % (i, source_text))
|
||
|
self.assertEqual(
|
||
|
source_text,
|
||
|
copy_text,
|
||
|
"Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"
|
||
|
% (source_text, copy_text),
|
||
|
)
|
||
|
|
||
|
def do_check_resolvers(self):
|
||
|
"""Use Python APIs to check serialization of breakpoint resolvers"""
|
||
|
|
||
|
empty_module_list = lldb.SBFileSpecList()
|
||
|
empty_cu_list = lldb.SBFileSpecList()
|
||
|
blubby_file_spec = lldb.SBFileSpec(
|
||
|
os.path.join(self.getSourceDir(), "blubby.c")
|
||
|
)
|
||
|
|
||
|
# It isn't actually important for these purposes that these breakpoint
|
||
|
# actually have locations.
|
||
|
source_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))
|
||
|
# Make sure we do one breakpoint right:
|
||
|
self.check_equivalence(source_bps)
|
||
|
source_bps.Clear()
|
||
|
|
||
|
source_bps.Append(
|
||
|
self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
)
|
||
|
source_bps.Append(
|
||
|
self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
)
|
||
|
source_bps.Append(
|
||
|
self.orig_target.BreakpointCreateBySourceRegex(
|
||
|
"dont really care", blubby_file_spec
|
||
|
)
|
||
|
)
|
||
|
|
||
|
# And some number greater than one:
|
||
|
self.check_equivalence(source_bps)
|
||
|
|
||
|
def do_check_filters(self):
|
||
|
"""Use Python APIs to check serialization of breakpoint filters."""
|
||
|
module_list = lldb.SBFileSpecList()
|
||
|
module_list.Append(lldb.SBFileSpec("SomeBinary"))
|
||
|
module_list.Append(lldb.SBFileSpec("SomeOtherBinary"))
|
||
|
|
||
|
cu_list = lldb.SBFileSpecList()
|
||
|
cu_list.Append(lldb.SBFileSpec("SomeCU.c"))
|
||
|
cu_list.Append(lldb.SBFileSpec("AnotherCU.c"))
|
||
|
cu_list.Append(lldb.SBFileSpec("ThirdCU.c"))
|
||
|
|
||
|
blubby_file_spec = lldb.SBFileSpec(
|
||
|
os.path.join(self.getSourceDir(), "blubby.c")
|
||
|
)
|
||
|
|
||
|
# It isn't actually important for these purposes that these breakpoint
|
||
|
# actually have locations.
|
||
|
source_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
bkpt = self.orig_target.BreakpointCreateByLocation(
|
||
|
blubby_file_spec, 666, 0, module_list
|
||
|
)
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
# Make sure we do one right:
|
||
|
self.check_equivalence(source_bps)
|
||
|
source_bps.Clear()
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list
|
||
|
)
|
||
|
source_bps.Append(bkpt)
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeFull, module_list, cu_list
|
||
|
)
|
||
|
source_bps.Append(bkpt)
|
||
|
bkpt = self.orig_target.BreakpointCreateBySourceRegex(
|
||
|
"dont really care", blubby_file_spec
|
||
|
)
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
# And some number greater than one:
|
||
|
self.check_equivalence(source_bps)
|
||
|
|
||
|
def do_check_options(self):
|
||
|
"""Use Python APIs to check serialization of breakpoint options."""
|
||
|
|
||
|
empty_module_list = lldb.SBFileSpecList()
|
||
|
empty_cu_list = lldb.SBFileSpecList()
|
||
|
blubby_file_spec = lldb.SBFileSpec(
|
||
|
os.path.join(self.getSourceDir(), "blubby.c")
|
||
|
)
|
||
|
|
||
|
# It isn't actually important for these purposes that these breakpoint
|
||
|
# actually have locations.
|
||
|
source_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByLocation(
|
||
|
lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()
|
||
|
)
|
||
|
bkpt.SetEnabled(False)
|
||
|
bkpt.SetOneShot(True)
|
||
|
bkpt.SetThreadID(10)
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
# Make sure we get one right:
|
||
|
self.check_equivalence(source_bps)
|
||
|
source_bps.Clear()
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
bkpt.SetIgnoreCount(10)
|
||
|
bkpt.SetThreadName("grubby")
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
bkpt.SetCondition("gonna remove this")
|
||
|
bkpt.SetCondition("")
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
bkpt.SetCondition("something != something_else")
|
||
|
bkpt.SetQueueName("grubby")
|
||
|
bkpt.AddName("FirstName")
|
||
|
bkpt.AddName("SecondName")
|
||
|
bkpt.SetScriptCallbackBody(
|
||
|
'\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n'
|
||
|
)
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateBySourceRegex(
|
||
|
"dont really care", blubby_file_spec
|
||
|
)
|
||
|
cmd_list = lldb.SBStringList()
|
||
|
cmd_list.AppendString("frame var")
|
||
|
cmd_list.AppendString("thread backtrace")
|
||
|
|
||
|
bkpt.SetCommandLineCommands(cmd_list)
|
||
|
source_bps.Append(bkpt)
|
||
|
|
||
|
self.check_equivalence(source_bps)
|
||
|
|
||
|
def do_check_appending(self):
|
||
|
"""Use Python APIs to check appending to already serialized options."""
|
||
|
|
||
|
empty_module_list = lldb.SBFileSpecList()
|
||
|
empty_cu_list = lldb.SBFileSpecList()
|
||
|
blubby_file_spec = lldb.SBFileSpec(
|
||
|
os.path.join(self.getSourceDir(), "blubby.c")
|
||
|
)
|
||
|
|
||
|
# It isn't actually important for these purposes that these breakpoint
|
||
|
# actually have locations.
|
||
|
|
||
|
all_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
source_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByLocation(
|
||
|
lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()
|
||
|
)
|
||
|
bkpt.SetEnabled(False)
|
||
|
bkpt.SetOneShot(True)
|
||
|
bkpt.SetThreadID(10)
|
||
|
source_bps.Append(bkpt)
|
||
|
all_bps.Append(bkpt)
|
||
|
|
||
|
error = lldb.SBError()
|
||
|
error = self.orig_target.BreakpointsWriteToFile(
|
||
|
self.bkpts_file_spec, source_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed writing breakpoints to file")
|
||
|
|
||
|
source_bps.Clear()
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
bkpt.SetIgnoreCount(10)
|
||
|
bkpt.SetThreadName("grubby")
|
||
|
source_bps.Append(bkpt)
|
||
|
all_bps.Append(bkpt)
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateByName(
|
||
|
"blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list
|
||
|
)
|
||
|
bkpt.SetCondition("something != something_else")
|
||
|
bkpt.SetQueueName("grubby")
|
||
|
bkpt.AddName("FirstName")
|
||
|
bkpt.AddName("SecondName")
|
||
|
|
||
|
source_bps.Append(bkpt)
|
||
|
all_bps.Append(bkpt)
|
||
|
|
||
|
error = self.orig_target.BreakpointsWriteToFile(
|
||
|
self.bkpts_file_spec, source_bps, True
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed appending breakpoints to file")
|
||
|
|
||
|
self.check_equivalence(all_bps)
|
||
|
|
||
|
def do_check_names(self):
|
||
|
bkpt = self.orig_target.BreakpointCreateByLocation(
|
||
|
lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()
|
||
|
)
|
||
|
good_bkpt_name = "GoodBreakpoint"
|
||
|
write_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
bkpt.AddName(good_bkpt_name)
|
||
|
write_bps.Append(bkpt)
|
||
|
|
||
|
error = lldb.SBError()
|
||
|
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
|
||
|
self.assertSuccess(error, "Failed writing breakpoints to file")
|
||
|
|
||
|
copy_bps = lldb.SBBreakpointList(self.copy_target)
|
||
|
names_list = lldb.SBStringList()
|
||
|
names_list.AppendString("NoSuchName")
|
||
|
|
||
|
error = self.copy_target.BreakpointsCreateFromFile(
|
||
|
self.bkpts_file_spec, names_list, copy_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed reading breakpoints from file")
|
||
|
self.assertEqual(
|
||
|
copy_bps.GetSize(), 0, "Found breakpoints with a nonexistent name."
|
||
|
)
|
||
|
|
||
|
names_list.AppendString(good_bkpt_name)
|
||
|
error = self.copy_target.BreakpointsCreateFromFile(
|
||
|
self.bkpts_file_spec, names_list, copy_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed reading breakpoints from file")
|
||
|
self.assertEqual(copy_bps.GetSize(), 1, "Found the matching breakpoint.")
|
||
|
|
||
|
def do_check_extra_args(self):
|
||
|
import side_effect
|
||
|
|
||
|
interp = self.dbg.GetCommandInterpreter()
|
||
|
error = lldb.SBError()
|
||
|
|
||
|
script_name = os.path.join(self.getSourceDir(), "resolver.py")
|
||
|
|
||
|
command = "command script import " + script_name
|
||
|
result = lldb.SBCommandReturnObject()
|
||
|
interp.HandleCommand(command, result)
|
||
|
self.assertTrue(
|
||
|
result.Succeeded(), "com scr imp failed: %s" % (result.GetError())
|
||
|
)
|
||
|
|
||
|
# First make sure a scripted breakpoint with no args works:
|
||
|
bkpt = self.orig_target.BreakpointCreateFromScript(
|
||
|
"resolver.Resolver",
|
||
|
lldb.SBStructuredData(),
|
||
|
lldb.SBFileSpecList(),
|
||
|
lldb.SBFileSpecList(),
|
||
|
)
|
||
|
self.assertTrue(bkpt.IsValid(), "Bkpt is valid")
|
||
|
write_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
|
||
|
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
|
||
|
self.assertSuccess(error, "Failed writing breakpoints")
|
||
|
|
||
|
side_effect.g_extra_args = None
|
||
|
copy_bps = lldb.SBBreakpointList(self.copy_target)
|
||
|
error = self.copy_target.BreakpointsCreateFromFile(
|
||
|
self.bkpts_file_spec, copy_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed reading breakpoints")
|
||
|
|
||
|
self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")
|
||
|
no_keys = lldb.SBStringList()
|
||
|
side_effect.g_extra_args.GetKeys(no_keys)
|
||
|
self.assertEqual(no_keys.GetSize(), 0, "Should have no keys")
|
||
|
|
||
|
self.orig_target.DeleteAllBreakpoints()
|
||
|
self.copy_target.DeleteAllBreakpoints()
|
||
|
|
||
|
# Now try one with extra args:
|
||
|
|
||
|
extra_args = lldb.SBStructuredData()
|
||
|
stream = lldb.SBStream()
|
||
|
stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}')
|
||
|
extra_args.SetFromJSON(stream)
|
||
|
self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.")
|
||
|
|
||
|
bkpt = self.orig_target.BreakpointCreateFromScript(
|
||
|
"resolver.Resolver",
|
||
|
extra_args,
|
||
|
lldb.SBFileSpecList(),
|
||
|
lldb.SBFileSpecList(),
|
||
|
)
|
||
|
self.assertTrue(bkpt.IsValid(), "Bkpt is valid")
|
||
|
write_bps = lldb.SBBreakpointList(self.orig_target)
|
||
|
|
||
|
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
|
||
|
self.assertSuccess(error, "Failed writing breakpoints")
|
||
|
|
||
|
orig_extra_args = side_effect.g_extra_args
|
||
|
self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid")
|
||
|
|
||
|
orig_keys = lldb.SBStringList()
|
||
|
orig_extra_args.GetKeys(orig_keys)
|
||
|
self.assertEqual(2, orig_keys.GetSize(), "Should have two keys")
|
||
|
|
||
|
side_effect.g_extra_args = None
|
||
|
|
||
|
copy_bps = lldb.SBBreakpointList(self.copy_target)
|
||
|
error = self.copy_target.BreakpointsCreateFromFile(
|
||
|
self.bkpts_file_spec, copy_bps
|
||
|
)
|
||
|
self.assertSuccess(error, "Failed reading breakpoints")
|
||
|
|
||
|
self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")
|
||
|
|
||
|
copy_extra_args = side_effect.g_extra_args
|
||
|
copy_keys = lldb.SBStringList()
|
||
|
copy_extra_args.GetKeys(copy_keys)
|
||
|
self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys")
|
||
|
|
||
|
for idx in range(0, orig_keys.GetSize()):
|
||
|
key = orig_keys.GetStringAtIndex(idx)
|
||
|
copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100)
|
||
|
|
||
|
if key == "first_arg":
|
||
|
self.assertEqual(copy_value, "first_value")
|
||
|
elif key == "second_arg":
|
||
|
self.assertEqual(copy_value, "second_value")
|
||
|
else:
|
||
|
self.Fail("Unknown key: %s" % (key))
|