Files
clang-p2996/lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
Jason Molenda c686eeb7fc [lldb] skip ReverseContinue tests on Darwin
This uses lldb-server in gdbserver mode, which requires a ProcessNative
plugin.  Darwin does not have a ProcessNative plugin; it uses
debugserver instead of lldb-server.  Skip these tests.
2024-10-10 16:08:19 -07:00

122 lines
5.3 KiB
Python

import lldb
import time
import unittest
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 TestReverseContinueBreakpoints(ReverseTestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue(self):
self.reverse_continue_internal(async_mode=False)
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue_async(self):
self.reverse_continue_internal(async_mode=True)
def reverse_continue_internal(self, async_mode):
target, process, initial_threads = self.setup_recording(async_mode)
# Reverse-continue. We'll stop at the point where we started recording.
status = process.Continue(lldb.eRunReverse)
self.assertSuccess(status)
self.expect_async_state_changes(async_mode, process, [lldb.eStateRunning, lldb.eStateStopped])
self.expect(
"thread list",
STOPPED_DUE_TO_HISTORY_BOUNDARY,
substrs=["stopped", "stop reason = history boundary"],
)
# Continue forward normally until the target exits.
status = process.Continue()
self.expect_async_state_changes(async_mode, process, [lldb.eStateRunning, lldb.eStateExited])
self.assertSuccess(status)
self.assertState(process.GetState(), lldb.eStateExited)
self.assertEqual(process.GetExitStatus(), 0)
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue_breakpoint(self):
self.reverse_continue_breakpoint_internal(async_mode=False)
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue_breakpoint_async(self):
self.reverse_continue_breakpoint_internal(async_mode=True)
def reverse_continue_breakpoint_internal(self, async_mode):
target, process, initial_threads = self.setup_recording(async_mode)
# Reverse-continue to the function "trigger_breakpoint".
trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None)
status = process.Continue(lldb.eRunReverse)
self.assertSuccess(status)
self.expect_async_state_changes(async_mode, process, [lldb.eStateRunning, lldb.eStateStopped])
threads_now = lldbutil.get_threads_stopped_at_breakpoint(process, trigger_bkpt)
self.assertEqual(threads_now, initial_threads)
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue_skip_breakpoint(self):
self.reverse_continue_skip_breakpoint_internal(async_mode=False)
@skipIfDarwin # No Darwin ProcessNative impl for lldb-server
def test_reverse_continue_skip_breakpoint_async(self):
self.reverse_continue_skip_breakpoint_internal(async_mode=True)
def reverse_continue_skip_breakpoint_internal(self, async_mode):
target, process, initial_threads = self.setup_recording(async_mode)
# Reverse-continue over a breakpoint at "trigger_breakpoint" whose
# condition is false.
# This tests that we continue in the correct direction after hitting
# the breakpoint.
trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None)
trigger_bkpt.SetCondition("false_condition")
status = process.Continue(lldb.eRunReverse)
self.expect_async_state_changes(async_mode, process, [lldb.eStateRunning, lldb.eStateStopped])
self.assertSuccess(status)
self.expect(
"thread list",
STOPPED_DUE_TO_HISTORY_BOUNDARY,
substrs=["stopped", "stop reason = history boundary"],
)
def setup_recording(self, async_mode):
"""
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("")
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)
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)
lldbutil.continue_to_breakpoint(process, stop_recording_bkpt)
target.BreakpointDelete(stop_recording_bkpt.GetID())
self.stop_recording()
self.dbg.SetAsync(async_mode)
self.expect_async_state_changes(async_mode, process, [lldb.eStateStopped])
return target, process, initial_threads
def expect_async_state_changes(self, async_mode, process, states):
if not async_mode:
return
listener = self.dbg.GetListener()
lldbutil.expect_state_changes(self, listener, process, states)