"""
Test that the built in ObjC exception throw recognizer works
"""
import lldb
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *
class TestObjCRecognizer(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipUnlessDarwin
def test_exception_recognizer_sub_class(self):
"""There can be many tests in a test case - describe this test here."""
self.build()
self.main_source_file = lldb.SBFileSpec("main.m")
self.objc_recognizer_test(True)
@skipUnlessDarwin
def test_exception_recognizer_plain(self):
"""There can be many tests in a test case - describe this test here."""
self.build()
self.main_source_file = lldb.SBFileSpec("main.m")
self.objc_recognizer_test(False)
def objc_recognizer_test(self, sub_class):
"""Make sure we stop at the exception and get all the fields out of the recognizer.
If sub_class is True, we make a subclass of NSException and throw that."""
if sub_class:
bkpt_string = "Set a breakpoint here for MyException"
else:
bkpt_string = "Set a breakpoint here for plain exception"
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, bkpt_string, self.main_source_file
)
# Now turn on the ObjC Exception breakpoint and continue to hit it:
exception_bkpt = target.BreakpointCreateForException(
lldb.eLanguageTypeObjC, False, True
)
self.assertGreater(
exception_bkpt.GetNumLocations(), 0, "Got some exception locations"
)
threads = lldbutil.continue_to_breakpoint(process, exception_bkpt)
self.assertEqual(len(threads), 1, "One thread hit exception breakpoint")
frame = threads[0].frame[0]
var_opts = lldb.SBVariablesOptions()
var_opts.SetIncludeRecognizedArguments(True)
var_opts.SetUseDynamic(True)
vars = frame.GetVariables(var_opts)
self.assertEqual(len(vars), 1, "Got the synthetic argument")
self.assertTrue(vars[0].IsValid(), "Got a valid Exception variable")
# This will be a pointer
ns_exception_children = [
ValueCheck(type="NSObject"),
ValueCheck(name="name", summary='"NSException"'),
ValueCheck(name="reason", summary='"Simple Reason"'),
ValueCheck(name="userInfo"),
ValueCheck(name="reserved"),
]
ns_exception = ValueCheck(type="NSException", children=ns_exception_children)
if not sub_class:
simple_check = ValueCheck(name="exception", dereference=ns_exception)
simple_check.check_value(self, vars[0], "Simple exception is right")
else:
my_exception_children = [
ns_exception,
ValueCheck(name="extra_info", type="int", value="100"),
]
my_exception = ValueCheck(
type="MyException", children=my_exception_children
)
sub_check = ValueCheck(
name="exception", type="MyException *", dereference=my_exception
)
sub_check.check_value(self, vars[0], "Subclass exception is right")