|
| 1 | +""" |
| 2 | +Test that the built in ObjC exception throw recognizer works |
| 3 | +""" |
| 4 | + |
| 5 | +import lldb |
| 6 | +from lldbsuite.test.decorators import * |
| 7 | +import lldbsuite.test.lldbutil as lldbutil |
| 8 | +from lldbsuite.test.lldbtest import * |
| 9 | + |
| 10 | +class TestObjCRecognizer(TestBase): |
| 11 | + |
| 12 | + NO_DEBUG_INFO_TESTCASE = True |
| 13 | + |
| 14 | + @skipUnlessDarwin |
| 15 | + def test_exception_recognizer_sub_class(self): |
| 16 | + """There can be many tests in a test case - describe this test here.""" |
| 17 | + self.build() |
| 18 | + self.main_source_file = lldb.SBFileSpec("main.m") |
| 19 | + self.objc_recognizer_test(True) |
| 20 | + |
| 21 | + @skipUnlessDarwin |
| 22 | + def test_exception_recognizer_plain(self): |
| 23 | + """There can be many tests in a test case - describe this test here.""" |
| 24 | + self.build() |
| 25 | + self.main_source_file = lldb.SBFileSpec("main.m") |
| 26 | + self.objc_recognizer_test(False) |
| 27 | + |
| 28 | + def objc_recognizer_test(self, sub_class): |
| 29 | + """Make sure we stop at the exception and get all the fields out of the recognizer. |
| 30 | + If sub_class is True, we make a subclass of NSException and throw that.""" |
| 31 | + if sub_class: |
| 32 | + bkpt_string = "Set a breakpoint here for MyException" |
| 33 | + else: |
| 34 | + bkpt_string = "Set a breakpoint here for plain exception" |
| 35 | + |
| 36 | + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, |
| 37 | + bkpt_string, self.main_source_file) |
| 38 | + |
| 39 | + # Now turn on the ObjC Exception breakpoint and continue to hit it: |
| 40 | + exception_bkpt = target.BreakpointCreateForException(lldb.eLanguageTypeObjC, False, True) |
| 41 | + self.assertTrue(exception_bkpt.GetNumLocations() > 0, "Got some exception locations") |
| 42 | + |
| 43 | + threads = lldbutil.continue_to_breakpoint(process, exception_bkpt) |
| 44 | + self.assertEqual(len(threads), 1, "One thread hit exception breakpoint") |
| 45 | + frame = threads[0].frame[0] |
| 46 | + |
| 47 | + # This test relies on the dereference argument to ValueCheck, which isn't on |
| 48 | + # this branch, so I'm skipping that portion of the test. |
| 49 | + return |
| 50 | + |
| 51 | + var_opts = lldb.SBVariablesOptions() |
| 52 | + var_opts.SetIncludeRecognizedArguments(True) |
| 53 | + var_opts.SetUseDynamic(True) |
| 54 | + vars = frame.GetVariables(var_opts) |
| 55 | + self.assertEqual(len(vars), 1, "Got the synthetic argument") |
| 56 | + self.assertTrue(vars[0].IsValid(), "Got a valid Exception variable") |
| 57 | + |
| 58 | + # This will be a pointer |
| 59 | + |
| 60 | + ns_exception_children = [ValueCheck(type="NSObject"), |
| 61 | + ValueCheck(name="name", summary='"NSException"'), |
| 62 | + ValueCheck(name="reason", summary='"Simple Reason"'), |
| 63 | + ValueCheck(name="userInfo"), |
| 64 | + ValueCheck(name="reserved")] |
| 65 | + ns_exception = ValueCheck(type="NSException", children=ns_exception_children) |
| 66 | + if not sub_class: |
| 67 | + simple_check = ValueCheck(name="exception", dereference=ns_exception) |
| 68 | + simple_check.check_value(self, vars[0], "Simple exception is right") |
| 69 | + else: |
| 70 | + my_exception_children = [ns_exception, ValueCheck(name="extra_info", type="int", value="100")] |
| 71 | + my_exception = ValueCheck(type="MyException", children=my_exception_children) |
| 72 | + sub_check = ValueCheck(name="exception", type="MyException *", dereference=my_exception) |
| 73 | + sub_check.check_value(self, vars[0], "Subclass exception is right") |
0 commit comments