199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprecht 699451b44SJordan Rupprechtimport lldb 799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 999451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1099451b44SJordan Rupprecht 1199451b44SJordan Rupprecht 1299451b44SJordan Rupprechtclass ExprCommandWithThrowTestCase(TestBase): 1399451b44SJordan Rupprecht def setUp(self): 1499451b44SJordan Rupprecht # Call super's setUp(). 1599451b44SJordan Rupprecht TestBase.setUp(self) 1699451b44SJordan Rupprecht 1799451b44SJordan Rupprecht self.main_source = "call-throws.m" 1899451b44SJordan Rupprecht self.main_source_spec = lldb.SBFileSpec(self.main_source) 1999451b44SJordan Rupprecht 20a852cf66SMichał Górny @add_test_categories(["objc"]) 2199451b44SJordan Rupprecht def test(self): 2299451b44SJordan Rupprecht """Test calling a function that throws and ObjC exception.""" 2399451b44SJordan Rupprecht self.build() 2499451b44SJordan Rupprecht self.call_function() 2599451b44SJordan Rupprecht 2699451b44SJordan Rupprecht def check_after_call(self): 2799451b44SJordan Rupprecht # Check that we are back where we were before: 2899451b44SJordan Rupprecht frame = self.thread.GetFrameAtIndex(0) 290ed758b2SDave Lee self.assertEqual( 302238dcc3SJonas Devlieghere self.orig_frame_pc, frame.GetPC(), "Restored the zeroth frame correctly" 312238dcc3SJonas Devlieghere ) 3299451b44SJordan Rupprecht 3399451b44SJordan Rupprecht def call_function(self): 3499451b44SJordan Rupprecht """Test calling function that throws.""" 352238dcc3SJonas Devlieghere (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( 362238dcc3SJonas Devlieghere self, "I am about to throw.", self.main_source_spec 372238dcc3SJonas Devlieghere ) 3899451b44SJordan Rupprecht 3999451b44SJordan Rupprecht options = lldb.SBExpressionOptions() 4099451b44SJordan Rupprecht options.SetUnwindOnError(True) 4199451b44SJordan Rupprecht 4299451b44SJordan Rupprecht frame = self.thread.GetFrameAtIndex(0) 4399451b44SJordan Rupprecht # Store away the PC to check that the functions unwind to the right 4499451b44SJordan Rupprecht # place after calls 4599451b44SJordan Rupprecht self.orig_frame_pc = frame.GetPC() 4699451b44SJordan Rupprecht 4799451b44SJordan Rupprecht value = frame.EvaluateExpression("[my_class callMeIThrow]", options) 4899451b44SJordan Rupprecht self.assertTrue(value.IsValid()) 491eeeab82SJordan Rupprecht self.assertFalse(value.GetError().Success()) 5099451b44SJordan Rupprecht 5199451b44SJordan Rupprecht self.check_after_call() 5299451b44SJordan Rupprecht 5399451b44SJordan Rupprecht # Okay, now try with a breakpoint in the called code in the case where 5499451b44SJordan Rupprecht # we are ignoring breakpoint hits. 5599451b44SJordan Rupprecht handler_bkpt = target.BreakpointCreateBySourceRegex( 562238dcc3SJonas Devlieghere "I felt like it", self.main_source_spec 572238dcc3SJonas Devlieghere ) 589c246882SJordan Rupprecht self.assertGreater(handler_bkpt.GetNumLocations(), 0) 5999451b44SJordan Rupprecht options.SetIgnoreBreakpoints(True) 6099451b44SJordan Rupprecht options.SetUnwindOnError(True) 6199451b44SJordan Rupprecht 6299451b44SJordan Rupprecht value = frame.EvaluateExpression("[my_class callMeIThrow]", options) 6399451b44SJordan Rupprecht 64*fd35a923SEisuke Kawashima self.assertTrue(value.IsValid() and not value.GetError().Success()) 6599451b44SJordan Rupprecht self.check_after_call() 6699451b44SJordan Rupprecht 6799451b44SJordan Rupprecht # Now set the ObjC language breakpoint and make sure that doesn't 6899451b44SJordan Rupprecht # interfere with the call: 6999451b44SJordan Rupprecht exception_bkpt = target.BreakpointCreateForException( 702238dcc3SJonas Devlieghere lldb.eLanguageTypeObjC, False, True 712238dcc3SJonas Devlieghere ) 729c246882SJordan Rupprecht self.assertGreater(exception_bkpt.GetNumLocations(), 0) 7399451b44SJordan Rupprecht 7499451b44SJordan Rupprecht options.SetIgnoreBreakpoints(True) 7599451b44SJordan Rupprecht options.SetUnwindOnError(True) 7699451b44SJordan Rupprecht 7799451b44SJordan Rupprecht value = frame.EvaluateExpression("[my_class callMeIThrow]", options) 7899451b44SJordan Rupprecht 79*fd35a923SEisuke Kawashima self.assertTrue(value.IsValid() and not value.GetError().Success()) 8099451b44SJordan Rupprecht self.check_after_call() 8199451b44SJordan Rupprecht 8299451b44SJordan Rupprecht # Now turn off exception trapping, and call a function that catches the exceptions, 8399451b44SJordan Rupprecht # and make sure the function actually completes, and we get the right 8499451b44SJordan Rupprecht # value: 8599451b44SJordan Rupprecht options.SetTrapExceptions(False) 8699451b44SJordan Rupprecht value = frame.EvaluateExpression("[my_class iCatchMyself]", options) 8799451b44SJordan Rupprecht self.assertTrue(value.IsValid()) 8835674976SPavel Labath self.assertSuccess(value.GetError()) 8980fcecb1SJonas Devlieghere self.assertEqual(value.GetValueAsUnsigned(), 57) 9099451b44SJordan Rupprecht self.check_after_call() 9199451b44SJordan Rupprecht options.SetTrapExceptions(True) 9299451b44SJordan Rupprecht 9399451b44SJordan Rupprecht # Now set this unwind on error to false, and make sure that we stop 9499451b44SJordan Rupprecht # where the exception was thrown 9599451b44SJordan Rupprecht options.SetUnwindOnError(False) 9699451b44SJordan Rupprecht value = frame.EvaluateExpression("[my_class callMeIThrow]", options) 9799451b44SJordan Rupprecht 98*fd35a923SEisuke Kawashima self.assertTrue(value.IsValid() and not value.GetError().Success()) 9999451b44SJordan Rupprecht self.check_after_call() 100