| """ | |
| Test the "process continue --reverse" and "--forward" options. | |
| """ | |
| import lldb | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.gdbclientutils import * | |
| from lldbsuite.test.lldbreverse import ReverseTestBase | |
| from lldbsuite.test import lldbutil | |
| class TestReverseContinue(ReverseTestBase): | |
| @skipIfRemote | |
| def test_reverse_continue(self): | |
| target, _, _ = self.setup_recording() | |
| # Set breakpoint and reverse-continue | |
| trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) | |
| self.assertTrue(trigger_bkpt.GetNumLocations() > 0) | |
| self.expect( | |
| "process continue --reverse", | |
| substrs=["stop reason = breakpoint {0}.1".format(trigger_bkpt.GetID())], | |
| ) | |
| # `process continue` should preserve current base direction. | |
| self.expect( | |
| "process continue", | |
| STOPPED_DUE_TO_HISTORY_BOUNDARY, | |
| substrs=["stopped", "stop reason = history boundary"], | |
| ) | |
| self.expect( | |
| "process continue --forward", | |
| substrs=["stop reason = breakpoint {0}.1".format(trigger_bkpt.GetID())], | |
| ) | |
| def setup_recording(self): | |
| """ | |
| Record execution of code between "start_recording" and "stop_recording" breakpoints. | |
| Returns with the target stopped at "stop_recording", with recording disabled, | |
| ready to reverse-execute. | |
| """ | |
| self.build() | |
| target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) | |
| process = self.connect(target) | |
| # Record execution from the start of the function "start_recording" | |
| # to the start of the function "stop_recording". We want to keep the | |
| # interval that we record as small as possible to minimize the run-time | |
| # of our single-stepping recorder. | |
| start_recording_bkpt = target.BreakpointCreateByName("start_recording", None) | |
| self.assertTrue(start_recording_bkpt.GetNumLocations() > 0) | |
| initial_threads = lldbutil.continue_to_breakpoint(process, start_recording_bkpt) | |
| self.assertEqual(len(initial_threads), 1) | |
| target.BreakpointDelete(start_recording_bkpt.GetID()) | |
| self.start_recording() | |
| stop_recording_bkpt = target.BreakpointCreateByName("stop_recording", None) | |
| self.assertTrue(stop_recording_bkpt.GetNumLocations() > 0) | |
| lldbutil.continue_to_breakpoint(process, stop_recording_bkpt) | |
| target.BreakpointDelete(stop_recording_bkpt.GetID()) | |
| self.stop_recording() | |
| self.dbg.SetAsync(False) | |
| return target, process, initial_threads |