"""
Test stepping out from a function in a multi-threaded program.
"""


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


class ThreadStepOutTestCase(TestBase):
    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"])
    @expectedFailureNetBSD
    def test_step_single_thread(self):
        """Test thread step out on one thread via command interpreter."""
        self.build()
        self.step_out_test(self.step_out_single_thread_with_cmd)

    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"])
    @expectedFailureAll(
        oslist=["watchos"], archs=["armv7k"], bugnumber="rdar://problem/34674488"
    )  # stop reason is trace when it should be step-out
    @expectedFailureNetBSD
    def test_step_all_threads(self):
        """Test thread step out on all threads via command interpreter."""
        self.build()
        self.step_out_test(self.step_out_all_threads_with_cmd)

    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681")
    @expectedFailureNetBSD
    def test_python(self):
        """Test thread step out on one thread via Python API (dwarf)."""
        self.build()
        self.step_out_test(self.step_out_with_python)

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line number for our breakpoint.
        self.bkpt_string = "// Set breakpoint here"
        self.breakpoint = line_number("main.cpp", self.bkpt_string)
        self.step_in_line = line_number("main.cpp", "// But we might still be here")
        self.step_out_dest = line_number(
            "main.cpp", "// Expect to stop here after step-out."
        )

    def check_stepping_thread(self):
        zeroth_frame = self.step_out_thread.frames[0]
        line_entry = zeroth_frame.line_entry
        self.assertTrue(line_entry.IsValid(), "Stopped at a valid line entry")
        self.assertEqual("main.cpp", line_entry.file.basename, "Still in main.cpp")
        # We can't really tell whether we stay on our line
        # or get to the next line, it depends on whether there are any
        # instructions between the call and the return.
        line = line_entry.line
        self.assertTrue(
            line == self.step_out_dest or line == self.step_in_line,
            "Stepped to the wrong line: {0}".format(line),
        )

    def step_out_single_thread_with_cmd(self):
        other_threads = {}
        for thread in self.process.threads:
            if thread.GetIndexID() == self.step_out_thread.GetIndexID():
                continue
            other_threads[thread.GetIndexID()] = thread.frames[0].line_entry

        # There should be other threads...
        self.assertNotEqual(len(other_threads), 0)
        self.step_out_with_cmd("this-thread")
        # The other threads should not have made progress:
        for thread in self.process.threads:
            index_id = thread.GetIndexID()
            line_entry = other_threads.get(index_id)
            if line_entry:
                self.assertEqual(
                    thread.frames[0].line_entry.file.basename,
                    line_entry.file.basename,
                    "Thread {0} moved by file".format(index_id),
                )
                self.assertEqual(
                    thread.frames[0].line_entry.line,
                    line_entry.line,
                    "Thread {0} moved by line".format(index_id),
                )

    def step_out_all_threads_with_cmd(self):
        self.step_out_with_cmd("all-threads")

    def step_out_with_cmd(self, run_mode):
        self.runCmd("thread select %d" % self.step_out_thread.GetIndexID())
        self.runCmd("thread step-out -m %s" % run_mode)
        self.expect(
            "process status",
            "Expected stop reason to be step-out",
            substrs=["stop reason = step out"],
        )

        selected_thread = self.process.GetSelectedThread()
        self.assertEqual(
            selected_thread.GetIndexID(),
            self.step_out_thread.GetIndexID(),
            "Step out changed selected thread.",
        )
        self.check_stepping_thread()

    def step_out_with_python(self):
        self.step_out_thread.StepOut()

        reason = self.step_out_thread.GetStopReason()
        self.assertEqual(
            lldb.eStopReasonPlanComplete,
            reason,
            "Expected thread stop reason 'plancomplete', but got '%s'"
            % lldbutil.stop_reason_to_str(reason),
        )
        self.check_stepping_thread()

    def step_out_test(self, step_out_func):
        """Test single thread step out of a function."""
        (
            self.inferior_target,
            self.process,
            thread,
            bkpt,
        ) = lldbutil.run_to_source_breakpoint(
            self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False
        )

        # We hit the breakpoint on at least one thread.  If we hit it on both threads
        # simultaneously, we can try the step out.  Otherwise, suspend the thread
        # that hit the breakpoint, and continue till the second thread hits
        # the breakpoint:

        (breakpoint_threads, other_threads) = ([], [])
        lldbutil.sort_stopped_threads(
            self.process,
            breakpoint_threads=breakpoint_threads,
            other_threads=other_threads,
        )
        if len(breakpoint_threads) == 1:
            success = thread.Suspend()
            self.assertTrue(success, "Couldn't suspend a thread")
            breakpoint_threads = lldbutil.continue_to_breakpoint(self.process, bkpt)
            self.assertEqual(len(breakpoint_threads), 2, "Second thread stopped")
            success = thread.Resume()
            self.assertTrue(success, "Couldn't resume a thread")

        self.step_out_thread = breakpoint_threads[0]

        # Step out of thread stopped at breakpoint
        step_out_func()
