blob: 8d54e2687710dc38241a2246b421febe3d8ff51b [file] [log] [blame]
Jim Ingham0ac57092013-02-14 03:05:42 +00001"""
Jim Ingham641a67c2013-05-16 21:52:36 +00002Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.
Jim Ingham0ac57092013-02-14 03:05:42 +00003"""
4
5import unittest2
6import lldb
7import lldbutil
8from lldbtest import *
9
Jim Ingham641a67c2013-05-16 21:52:36 +000010class ExprCommandWithThrowTestCase(TestBase):
Jim Ingham0ac57092013-02-14 03:05:42 +000011
Greg Clayton4570d3e2013-12-10 23:19:29 +000012 mydir = TestBase.compute_mydir(__file__)
Jim Ingham0ac57092013-02-14 03:05:42 +000013
14 def setUp(self):
15 # Call super's setUp().
16 TestBase.setUp(self)
17
18 self.main_source = "call-throws.m"
19 self.main_source_spec = lldb.SBFileSpec (self.main_source)
20
21
Robert Flack13c7ad92015-03-30 14:12:17 +000022 @skipUnlessDarwin
Jim Ingham0ac57092013-02-14 03:05:42 +000023 @dsym_test
24 def test_with_dsym(self):
Jim Ingham641a67c2013-05-16 21:52:36 +000025 """Test calling a function that throws and ObjC exception."""
Jim Ingham0ac57092013-02-14 03:05:42 +000026 self.buildDsym()
27 self.call_function()
28
Robert Flack13c7ad92015-03-30 14:12:17 +000029 @skipUnlessDarwin
Jim Ingham0ac57092013-02-14 03:05:42 +000030 @dwarf_test
31 def test_with_dwarf(self):
Jim Ingham641a67c2013-05-16 21:52:36 +000032 """Test calling a function that throws and ObjC exception."""
Jim Ingham0ac57092013-02-14 03:05:42 +000033 self.buildDwarf()
34 self.call_function()
35
36 def check_after_call (self):
37 # Check that we are back where we were before:
38 frame = self.thread.GetFrameAtIndex(0)
39 self.assertTrue (self.orig_frame_pc == frame.GetPC(), "Restored the zeroth frame correctly")
40
41
42 def call_function(self):
Jim Ingham641a67c2013-05-16 21:52:36 +000043 """Test calling function that throws."""
Jim Ingham0ac57092013-02-14 03:05:42 +000044 exe_name = "a.out"
45 exe = os.path.join(os.getcwd(), exe_name)
46
47 target = self.dbg.CreateTarget(exe)
48 self.assertTrue(target, VALID_TARGET)
49
50 breakpoint = target.BreakpointCreateBySourceRegex('I am about to throw.',self.main_source_spec)
51 self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
52
53 # Launch the process, and do not stop at the entry point.
Greg Claytonc6947512013-12-13 19:18:59 +000054 process = target.LaunchSimple (None, None, self.get_process_working_directory())
Jim Ingham0ac57092013-02-14 03:05:42 +000055
56 self.assertTrue(process, PROCESS_IS_VALID)
57
58 # Frame #0 should be at our breakpoint.
59 threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
60
61 self.assertTrue(len(threads) == 1)
62 self.thread = threads[0]
63
64 options = lldb.SBExpressionOptions()
65 options.SetUnwindOnError(True)
66
67 frame = self.thread.GetFrameAtIndex(0)
68 # Store away the PC to check that the functions unwind to the right place after calls
69 self.orig_frame_pc = frame.GetPC()
70
71 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
72 self.assertTrue (value.IsValid())
73 self.assertTrue (value.GetError().Success() == False)
74
75 self.check_after_call()
76
77 # Okay, now try with a breakpoint in the called code in the case where
78 # we are ignoring breakpoint hits.
79 handler_bkpt = target.BreakpointCreateBySourceRegex("I felt like it", self.main_source_spec)
80 self.assertTrue (handler_bkpt.GetNumLocations() > 0)
81 options.SetIgnoreBreakpoints(True)
82 options.SetUnwindOnError(True)
83
84 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
85
86 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
87 self.check_after_call()
88
Jim Ingham641a67c2013-05-16 21:52:36 +000089 # Now set the ObjC language breakpoint and make sure that doesn't interfere with the call:
90 exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeObjC, False, True)
91 self.assertTrue(exception_bkpt.GetNumLocations() > 0)
92
93 options.SetIgnoreBreakpoints(True)
94 options.SetUnwindOnError(True)
95
96 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
97
98 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
99 self.check_after_call()
100
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000101
102 # Now turn off exception trapping, and call a function that catches the exceptions,
103 # and make sure the function actually completes, and we get the right value:
104 options.SetTrapExceptions(False)
105 value = frame.EvaluateExpression ("[my_class iCatchMyself]", options)
106 self.assertTrue (value.IsValid())
107 self.assertTrue (value.GetError().Success() == True)
108 self.assertTrue (value.GetValueAsUnsigned() == 57)
109 self.check_after_call()
110 options.SetTrapExceptions(True)
111
Jim Ingham0ac57092013-02-14 03:05:42 +0000112 # Now set this unwind on error to false, and make sure that we stop where the exception was thrown
113 options.SetUnwindOnError(False)
114 value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
115
116
117 self.assertTrue (value.IsValid() and value.GetError().Success() == False)
118 self.check_after_call()
119
120if __name__ == '__main__':
121 import atexit
122 lldb.SBDebugger.Initialize()
123 atexit.register(lambda: lldb.SBDebugger.Terminate())
124 unittest2.main()