14b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham"""
20086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim InghamTest calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.
34b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham"""
44b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
54b01c3657bc415b52284f6a0b1654642c649f5e3Jim Inghamimport unittest2
64b01c3657bc415b52284f6a0b1654642c649f5e3Jim Inghamimport lldb
74b01c3657bc415b52284f6a0b1654642c649f5e3Jim Inghamimport lldbutil
84b01c3657bc415b52284f6a0b1654642c649f5e3Jim Inghamfrom lldbtest import *
94b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
100086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Inghamclass ExprCommandWithThrowTestCase(TestBase):
114b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
124b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    mydir = os.path.join("expression_command", "call-throws")
134b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
144b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    def setUp(self):
154b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Call super's setUp().
164b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        TestBase.setUp(self)
174b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
184b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.main_source = "call-throws.m"
194b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.main_source_spec = lldb.SBFileSpec (self.main_source)
204b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
214b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
224b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
234b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    @dsym_test
244b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    def test_with_dsym(self):
250086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        """Test calling a function that throws and ObjC exception."""
264b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.buildDsym()
274b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.call_function()
284b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
29dcd2a561c052f302e9955f704bf46628d40ab2e0Daniel Malea    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin due to ObjC test case")
304b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    @dwarf_test
314b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    def test_with_dwarf(self):
320086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        """Test calling a function that throws and ObjC exception."""
334b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.buildDwarf()
344b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.call_function()
354b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
364b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    def check_after_call (self):
374b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Check that we are back where we were before:
384b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        frame = self.thread.GetFrameAtIndex(0)
394b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (self.orig_frame_pc == frame.GetPC(), "Restored the zeroth frame correctly")
404b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
414b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
424b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    def call_function(self):
430086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        """Test calling function that throws."""
444b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        exe_name = "a.out"
454b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        exe = os.path.join(os.getcwd(), exe_name)
464b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
474b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        target = self.dbg.CreateTarget(exe)
484b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue(target, VALID_TARGET)
494b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
504b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        breakpoint = target.BreakpointCreateBySourceRegex('I am about to throw.',self.main_source_spec)
514b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
524b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
534b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Launch the process, and do not stop at the entry point.
544b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        process = target.LaunchSimple(None, None, os.getcwd())
554b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
564b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue(process, PROCESS_IS_VALID)
574b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
584b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Frame #0 should be at our breakpoint.
594b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
604b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
614b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue(len(threads) == 1)
624b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.thread = threads[0]
634b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
644b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        options = lldb.SBExpressionOptions()
654b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        options.SetUnwindOnError(True)
664b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
674b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        frame = self.thread.GetFrameAtIndex(0)
684b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Store away the PC to check that the functions unwind to the right place after calls
694b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.orig_frame_pc = frame.GetPC()
704b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
714b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
724b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (value.IsValid())
734b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (value.GetError().Success() == False)
744b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
754b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.check_after_call()
764b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
774b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Okay, now try with a breakpoint in the called code in the case where
784b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # we are ignoring breakpoint hits.
794b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        handler_bkpt = target.BreakpointCreateBySourceRegex("I felt like it", self.main_source_spec)
804b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (handler_bkpt.GetNumLocations() > 0)
814b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        options.SetIgnoreBreakpoints(True)
824b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        options.SetUnwindOnError(True)
834b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
844b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
854b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
864b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == False)
874b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.check_after_call()
884b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
890086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        # Now set the ObjC language breakpoint and make sure that doesn't interfere with the call:
900086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeObjC, False, True)
910086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        self.assertTrue(exception_bkpt.GetNumLocations() > 0)
920086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham
930086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        options.SetIgnoreBreakpoints(True)
940086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        options.SetUnwindOnError(True)
950086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham
960086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
970086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham
980086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == False)
990086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham        self.check_after_call()
1000086b94b7809b9fcdc77ce5bcca1e0e64bcfef76Jim Ingham
1014b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        # Now set this unwind on error to false, and make sure that we stop where the exception was thrown
1024b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        options.SetUnwindOnError(False)
1034b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
1044b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
1054b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
1064b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == False)
1074b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham        self.check_after_call()
1084b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham
1094b01c3657bc415b52284f6a0b1654642c649f5e3Jim Inghamif __name__ == '__main__':
1104b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    import atexit
1114b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    lldb.SBDebugger.Initialize()
1124b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    atexit.register(lambda: lldb.SBDebugger.Terminate())
1134b01c3657bc415b52284f6a0b1654642c649f5e3Jim Ingham    unittest2.main()
114