Files
clang-p2996/lldb/test/API/macosx/objc_exception_recognizer/TestObjCRecognizer.py
Jim Ingham f79c037b63 Fix the check in StopInfoBreakpoint for "are we currently running an expression"
We were checking "WasTheLastResumeForUserExpression" but that returns true even
if that expression was completed, provided we haven't run again.  This uses a
better check.

This is actually fairly hard to trigger.  It happens the first time you hit an
objc_exception_throw breakpoint and invoke that frame recognizer for that.  But
I couldn't trigger it using a Python based frame recognizer.  So I wrote a test
for the objc_exception_throw_breakpoint recognizer which should have been there
anyway...  It fails (the target auto-continues) w/o this patch and succeeds with
it.

Differential Revision: https://reviews.llvm.org/D147587
2023-04-05 17:14:25 -07:00

70 lines
3.2 KiB
Python

"""
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.assertTrue(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")