"""Test that lldb functions correctly after the inferior has asserted."""

import lldb
from lldbsuite.test import lldbutil
from lldbsuite.test import lldbplatformutil
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *


class AssertingInferiorTestCase(TestBase):
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    @expectedFailureAll(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr25338")
    @expectedFailureAll(bugnumber="llvm.org/pr26592", triple="^mips")
    def test_inferior_asserting(self):
        """Test that lldb reliably catches the inferior asserting (command)."""
        self.build()
        self.inferior_asserting()

    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    @expectedFailureAndroid(api_levels=list(range(16 + 1)))  # b.android.com/179836
    def test_inferior_asserting_register(self):
        """Test that lldb reliably reads registers from the inferior after asserting (command)."""
        self.build()
        self.inferior_asserting_registers()

    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    @expectedFailureAll(
        oslist=["linux"],
        archs=["arm"],
        triple=no_match(".*-android"),
        bugnumber="llvm.org/pr25338",
    )
    @expectedFailureAll(bugnumber="llvm.org/pr26592", triple="^mips")
    def test_inferior_asserting_disassemble(self):
        """Test that lldb reliably disassembles frames after asserting (command)."""
        self.build()
        self.inferior_asserting_disassemble()

    @add_test_categories(["pyapi"])
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    def test_inferior_asserting_python(self):
        """Test that lldb reliably catches the inferior asserting (Python API)."""
        self.build()
        self.inferior_asserting_python()

    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    @expectedFailureAll(
        oslist=["linux"],
        archs=["arm"],
        triple=no_match(".*-android"),
        bugnumber="llvm.org/pr25338",
    )
    @expectedFailureAll(bugnumber="llvm.org/pr26592", triple="^mips")
    def test_inferior_asserting_expr(self):
        """Test that the lldb expression interpreter can read from the inferior after asserting (command)."""
        self.build()
        self.inferior_asserting_expr()

    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows",
    )
    @expectedFailureAll(
        oslist=["linux"],
        archs=["arm"],
        triple=no_match(".*-android"),
        bugnumber="llvm.org/pr25338",
    )
    @expectedFailureAll(bugnumber="llvm.org/pr26592", triple="^mips")
    def test_inferior_asserting_step(self):
        """Test that lldb functions correctly after stepping through a call to assert()."""
        self.build()
        self.inferior_asserting_step()

    def set_breakpoint(self, line):
        lldbutil.run_break_set_by_file_and_line(
            self, "main.c", line, num_expected_locations=1, loc_exact=True
        )

    def check_stop_reason(self):
        matched = lldbplatformutil.match_android_device(
            self.getArchitecture(), valid_api_levels=list(range(1, 16 + 1))
        )
        if matched:
            # On android until API-16 the abort() call ended in a sigsegv
            # instead of in a sigabrt
            stop_reason = "signal SIGSEGV"
        else:
            stop_reason = "signal SIGABRT"

        target = self.dbg.GetTargetAtIndex(0)
        process = target.GetProcess()
        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal)

        pattern = "stop reason = (" + stop_reason + "|hit program assert)"

        # The stop reason of the thread should be an abort signal or exception.
        self.expect(
            "thread list",
            STOPPED_DUE_TO_ASSERT,
            patterns=[pattern],
            substrs=["stopped"],
        )

        return pattern

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line number of the call to assert.
        self.line = line_number("main.c", "// Assert here.")

    def inferior_asserting(self):
        """Inferior asserts upon launching; lldb should catch the event and stop."""
        exe = self.getBuildArtifact("a.out")
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        self.runCmd("run", RUN_SUCCEEDED)
        stop_reason = self.check_stop_reason()

        # And it should report a backtrace that includes the assert site.
        self.expect(
            "thread backtrace all",
            patterns=[stop_reason],
            substrs=["main", "argc", "argv"],
        )

        # And it should report the correct line number.
        self.expect(
            "thread backtrace all",
            patterns=[stop_reason],
            substrs=["main.c:%d" % self.line],
        )

    def inferior_asserting_python(self):
        """Inferior asserts upon launching; lldb should catch the event and stop."""
        exe = self.getBuildArtifact("a.out")

        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        # Now launch the process, and do not stop at entry point.
        # Both argv and envp are null.
        process = target.LaunchSimple(None, None, self.get_process_working_directory())

        if process.GetState() != lldb.eStateStopped:
            self.fail(
                "Process should be in the 'stopped' state, "
                "instead the actual state is: '%s'"
                % lldbutil.state_type_to_str(process.GetState())
            )

        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal)
        if not thread:
            self.fail("Fail to stop the thread upon assert")

        if self.TraceOn():
            lldbutil.print_stacktrace(thread)

    def inferior_asserting_registers(self):
        """Test that lldb can read registers after asserting."""
        exe = self.getBuildArtifact("a.out")
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        self.runCmd("run", RUN_SUCCEEDED)
        self.check_stop_reason()

        # change current frame to frame 0, since recognizer might have selected
        # different frame.
        self.runCmd("frame select 0", RUN_SUCCEEDED)

        # lldb should be able to read from registers from the inferior after
        # asserting.
        lldbplatformutil.check_first_register_readable(self)

    def inferior_asserting_disassemble(self):
        """Test that lldb can disassemble frames after asserting."""
        exe = self.getBuildArtifact("a.out")

        # Create a target by the debugger.
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        # Launch the process, and do not stop at the entry point.
        target.LaunchSimple(None, None, self.get_process_working_directory())
        self.check_stop_reason()

        process = target.GetProcess()
        self.assertTrue(process.IsValid(), "current process is valid")

        thread = process.GetThreadAtIndex(0)
        self.assertTrue(thread.IsValid(), "current thread is valid")

        lastframeID = thread.GetFrameAtIndex(thread.GetNumFrames() - 1).GetFrameID()

        isi386Arch = False
        if "i386" in self.getArchitecture():
            isi386Arch = True

        # lldb should be able to disassemble frames from the inferior after
        # asserting.
        for frame in thread:
            self.assertTrue(frame.IsValid(), "current frame is valid")

            self.runCmd("frame select " + str(frame.GetFrameID()), RUN_SUCCEEDED)

            # Don't expect the function name to be in the disassembly as the assert
            # function might be a no-return function where the PC is past the end
            # of the function and in the next function. We also can't back the PC up
            # because we don't know how much to back it up by on targets with opcodes
            # that have differing sizes
            pc_backup_offset = 1
            if frame.GetFrameID() == 0:
                pc_backup_offset = 0
            if isi386Arch:
                if lastframeID == frame.GetFrameID():
                    pc_backup_offset = 0
            self.expect(
                "disassemble -a %s" % (frame.GetPC() - pc_backup_offset),
                substrs=["<+0>: "],
            )

    def check_expr_in_main(self, thread):
        depth = thread.GetNumFrames()
        for i in range(depth):
            frame = thread.GetFrameAtIndex(i)
            self.assertTrue(frame.IsValid(), "current frame is valid")
            if self.TraceOn():
                print("Checking if function %s is main" % frame.GetFunctionName())

            if "main" == frame.GetFunctionName():
                frame_id = frame.GetFrameID()
                self.runCmd("frame select " + str(frame_id), RUN_SUCCEEDED)
                self.expect("expression argc", substrs=["(int)", " = 1"])
                self.expect("expression hello_world", substrs=["Hello"])
                self.expect("expression argv[0]", substrs=["a.out"])
                self.expect("expression null_ptr", substrs=["= 0x0"])
                return True
        return False

    def inferior_asserting_expr(self):
        """Test that the lldb expression interpreter can read symbols after asserting."""
        exe = self.getBuildArtifact("a.out")

        # Create a target by the debugger.
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        # Launch the process, and do not stop at the entry point.
        target.LaunchSimple(None, None, self.get_process_working_directory())
        self.check_stop_reason()

        process = target.GetProcess()
        self.assertTrue(process.IsValid(), "current process is valid")

        thread = process.GetThreadAtIndex(0)
        self.assertTrue(thread.IsValid(), "current thread is valid")

        # The lldb expression interpreter should be able to read from addresses
        # of the inferior after a call to assert().
        self.assertTrue(
            self.check_expr_in_main(thread), "cannot find 'main' in the backtrace"
        )

    def inferior_asserting_step(self):
        """Test that lldb functions correctly after stepping through a call to assert()."""
        exe = self.getBuildArtifact("a.out")

        # Create a target by the debugger.
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        # Launch the process, and do not stop at the entry point.
        self.set_breakpoint(self.line)
        target.LaunchSimple(None, None, self.get_process_working_directory())

        self.expect(
            "thread list",
            STOPPED_DUE_TO_BREAKPOINT,
            substrs=["main.c:%d" % self.line, "stop reason = breakpoint"],
        )

        self.runCmd("next")
        stop_reason = self.check_stop_reason()

        # lldb should be able to read from registers from the inferior after
        # asserting.
        if "x86_64" in self.getArchitecture():
            self.expect("register read rbp", substrs=["rbp = 0x"])
        if "i386" in self.getArchitecture():
            self.expect("register read ebp", substrs=["ebp = 0x"])

        process = target.GetProcess()
        self.assertTrue(process.IsValid(), "current process is valid")

        thread = process.GetThreadAtIndex(0)
        self.assertTrue(thread.IsValid(), "current thread is valid")

        # The lldb expression interpreter should be able to read from addresses
        # of the inferior after a call to assert().
        self.assertTrue(
            self.check_expr_in_main(thread), "cannot find 'main' in the backtrace"
        )

        # And it should report the correct line number.
        self.expect(
            "thread backtrace all",
            patterns=[stop_reason],
            substrs=["main.c:%d" % self.line],
        )
