2 Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.
5 from __future__ import print_function
10 from lldbsuite.test.decorators import *
11 from lldbsuite.test.lldbtest import *
12 from lldbsuite.test import lldbutil
14 class ExprCommandWithThrowTestCase(TestBase):
16 mydir = TestBase.compute_mydir(__file__)
19 # Call super's setUp().
22 self.main_source = "call-throws.m"
23 self.main_source_spec = lldb.SBFileSpec (self.main_source)
27 """Test calling a function that throws and ObjC exception."""
31 def check_after_call (self):
32 # Check that we are back where we were before:
33 frame = self.thread.GetFrameAtIndex(0)
34 self.assertTrue (self.orig_frame_pc == frame.GetPC(), "Restored the zeroth frame correctly")
37 def call_function(self):
38 """Test calling function that throws."""
40 exe = os.path.join(os.getcwd(), exe_name)
42 target = self.dbg.CreateTarget(exe)
43 self.assertTrue(target, VALID_TARGET)
45 breakpoint = target.BreakpointCreateBySourceRegex('I am about to throw.',self.main_source_spec)
46 self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
48 # Launch the process, and do not stop at the entry point.
49 process = target.LaunchSimple (None, None, self.get_process_working_directory())
51 self.assertTrue(process, PROCESS_IS_VALID)
53 # Frame #0 should be at our breakpoint.
54 threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
56 self.assertTrue(len(threads) == 1)
57 self.thread = threads[0]
59 options = lldb.SBExpressionOptions()
60 options.SetUnwindOnError(True)
62 frame = self.thread.GetFrameAtIndex(0)
63 # Store away the PC to check that the functions unwind to the right place after calls
64 self.orig_frame_pc = frame.GetPC()
66 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
67 self.assertTrue (value.IsValid())
68 self.assertTrue (value.GetError().Success() == False)
70 self.check_after_call()
72 # Okay, now try with a breakpoint in the called code in the case where
73 # we are ignoring breakpoint hits.
74 handler_bkpt = target.BreakpointCreateBySourceRegex("I felt like it", self.main_source_spec)
75 self.assertTrue (handler_bkpt.GetNumLocations() > 0)
76 options.SetIgnoreBreakpoints(True)
77 options.SetUnwindOnError(True)
79 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
81 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
82 self.check_after_call()
84 # Now set the ObjC language breakpoint and make sure that doesn't interfere with the call:
85 exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeObjC, False, True)
86 self.assertTrue(exception_bkpt.GetNumLocations() > 0)
88 options.SetIgnoreBreakpoints(True)
89 options.SetUnwindOnError(True)
91 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
93 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
94 self.check_after_call()
97 # Now turn off exception trapping, and call a function that catches the exceptions,
98 # and make sure the function actually completes, and we get the right value:
99 options.SetTrapExceptions(False)
100 value = frame.EvaluateExpression ("[my_class iCatchMyself]", options)
101 self.assertTrue (value.IsValid())
102 self.assertTrue (value.GetError().Success() == True)
103 self.assertTrue (value.GetValueAsUnsigned() == 57)
104 self.check_after_call()
105 options.SetTrapExceptions(True)
107 # Now set this unwind on error to false, and make sure that we stop where the exception was thrown
108 options.SetUnwindOnError(False)
109 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
112 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
113 self.check_after_call()