100 lines · python
1"""2Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.3"""4 5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class ExprCommandWithThrowTestCase(TestBase):13 def setUp(self):14 # Call super's setUp().15 TestBase.setUp(self)16 17 self.main_source = "call-throws.m"18 self.main_source_spec = lldb.SBFileSpec(self.main_source)19 20 @add_test_categories(["objc"])21 def test(self):22 """Test calling a function that throws and ObjC exception."""23 self.build()24 self.call_function()25 26 def check_after_call(self):27 # Check that we are back where we were before:28 frame = self.thread.GetFrameAtIndex(0)29 self.assertEqual(30 self.orig_frame_pc, frame.GetPC(), "Restored the zeroth frame correctly"31 )32 33 def call_function(self):34 """Test calling function that throws."""35 (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(36 self, "I am about to throw.", self.main_source_spec37 )38 39 options = lldb.SBExpressionOptions()40 options.SetUnwindOnError(True)41 42 frame = self.thread.GetFrameAtIndex(0)43 # Store away the PC to check that the functions unwind to the right44 # place after calls45 self.orig_frame_pc = frame.GetPC()46 47 value = frame.EvaluateExpression("[my_class callMeIThrow]", options)48 self.assertTrue(value.IsValid())49 self.assertFalse(value.GetError().Success())50 51 self.check_after_call()52 53 # Okay, now try with a breakpoint in the called code in the case where54 # we are ignoring breakpoint hits.55 handler_bkpt = target.BreakpointCreateBySourceRegex(56 "I felt like it", self.main_source_spec57 )58 self.assertGreater(handler_bkpt.GetNumLocations(), 0)59 options.SetIgnoreBreakpoints(True)60 options.SetUnwindOnError(True)61 62 value = frame.EvaluateExpression("[my_class callMeIThrow]", options)63 64 self.assertTrue(value.IsValid() and not value.GetError().Success())65 self.check_after_call()66 67 # Now set the ObjC language breakpoint and make sure that doesn't68 # interfere with the call:69 exception_bkpt = target.BreakpointCreateForException(70 lldb.eLanguageTypeObjC, False, True71 )72 self.assertGreater(exception_bkpt.GetNumLocations(), 0)73 74 options.SetIgnoreBreakpoints(True)75 options.SetUnwindOnError(True)76 77 value = frame.EvaluateExpression("[my_class callMeIThrow]", options)78 79 self.assertTrue(value.IsValid() and not value.GetError().Success())80 self.check_after_call()81 82 # Now turn off exception trapping, and call a function that catches the exceptions,83 # and make sure the function actually completes, and we get the right84 # value:85 options.SetTrapExceptions(False)86 value = frame.EvaluateExpression("[my_class iCatchMyself]", options)87 self.assertTrue(value.IsValid())88 self.assertSuccess(value.GetError())89 self.assertEqual(value.GetValueAsUnsigned(), 57)90 self.check_after_call()91 options.SetTrapExceptions(True)92 93 # Now set this unwind on error to false, and make sure that we stop94 # where the exception was thrown95 options.SetUnwindOnError(False)96 value = frame.EvaluateExpression("[my_class callMeIThrow]", options)97 98 self.assertTrue(value.IsValid() and not value.GetError().Success())99 self.check_after_call()100