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


@requireNotWasm("no reverse execution")
class TestReverseContinueBreakpoints(ReverseTestBase):
    @skipIfRemote
    def test_reverse_continue(self):
        self.reverse_continue_internal(async_mode=False)

    @skipIfRemote
    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.ContinueInDirection(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.ContinueInDirection(lldb.eRunForward)
        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)

    @skipIfRemote
    def test_reverse_continue_breakpoint(self):
        self.reverse_continue_breakpoint_internal(async_mode=False)

    @skipIfRemote
    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.ContinueInDirection(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)

    @skipIfRemote
    @skipIf(
        oslist=["windows"],
        archs=["x86_64"],
        bugnumber="github.com/llvm/llvm-project/issues/138084",
    )
    def test_reverse_continue_skip_breakpoint(self):
        self.reverse_continue_skip_breakpoint_internal(async_mode=False)

    @skipIfRemote
    @skipIf(
        oslist=["windows"],
        archs=["x86_64"],
        bugnumber="github.com/llvm/llvm-project/issues/138084",
    )
    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 (via function call).
        # 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.ContinueInDirection(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"],
        )

    @skipIfRemote
    def test_continue_preserves_direction(self):
        self.continue_preserves_direction_internal(async_mode=False)

    @skipIfRemote
    def test_continue_preserves_direction_asyhc(self):
        self.continue_preserves_direction_internal(async_mode=True)

    def continue_preserves_direction_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.ContinueInDirection(lldb.eRunReverse)
        self.assertSuccess(status)
        self.expect_async_state_changes(
            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
        )
        # This should continue in reverse.
        status = process.Continue()
        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(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(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)
