"""
Test python scripted process in lldb
"""

import os, shutil

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

import addressable_bits_scripted_process
import dummy_scripted_process


@requireThreadSupport
class ScriptedProcesTestCase(TestBase):
    NO_DEBUG_INFO_TESTCASE = True

    @skipUnlessDarwin
    def test_python_plugin_package(self):
        """Test that the lldb python module has a `plugins.scripted_process`
        package."""
        self.expect(
            "script import lldb.plugins",
            substrs=["ModuleNotFoundError"],
            matching=False,
        )

        self.expect("script dir(lldb.plugins)", substrs=["scripted_process"])

        self.expect(
            "script import lldb.plugins.scripted_process",
            substrs=["ModuleNotFoundError"],
            matching=False,
        )

        self.expect(
            "script dir(lldb.plugins.scripted_process)", substrs=["ScriptedProcess"]
        )

        self.expect(
            "script from lldb.plugins.scripted_process import ScriptedProcess",
            substrs=["ImportError"],
            matching=False,
        )

        self.expect("script dir(ScriptedProcess)", substrs=["launch"])

    def move_blueprint_to_dsym(self, blueprint_name):
        blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
        dsym_bundle = self.getBuildArtifact("a.out.dSYM")
        blueprint_destination_path = os.path.join(
            dsym_bundle, "Contents", "Resources", "Python"
        )
        if not os.path.exists(blueprint_destination_path):
            os.mkdir(blueprint_destination_path)

        blueprint_destination_path = os.path.join(
            blueprint_destination_path, "a_out.py"
        )
        shutil.copy(blueprint_origin_path, blueprint_destination_path)

    # No dylib on Windows.
    @skipIfWindows
    def test_missing_methods_scripted_register_context(self):
        """Test that we only instanciate scripted processes if they implement
        all the required abstract methods."""
        self.build()

        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"

        def cleanup():
            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]

        self.addTearDownHook(cleanup)

        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)
        log_file = self.getBuildArtifact("script.log")
        self.runCmd("log enable lldb script -f " + log_file)
        self.assertTrue(os.path.isfile(log_file))
        script_path = os.path.join(
            self.getSourceDir(), "missing_methods_scripted_process.py"
        )
        self.runCmd("command script import " + script_path)

        launch_info = lldb.SBLaunchInfo(None)
        launch_info.SetProcessPluginName("ScriptedProcess")
        launch_info.SetScriptedProcessClassName(
            "missing_methods_scripted_process.MissingMethodsScriptedProcess"
        )
        error = lldb.SBError()

        process = target.Launch(launch_info, error)

        self.assertFailure(error)

        with open(log_file, "r") as f:
            log = f.read()

        self.assertIn(
            "abstract method MissingMethodsScriptedProcess.read_memory_at_address not implemented",
            log,
        )
        self.assertIn(
            "abstract method MissingMethodsScriptedProcess.is_alive not implemented",
            log,
        )
        self.assertIn(
            "abstract method MissingMethodsScriptedProcess.get_scripted_thread_plugin not implemented",
            log,
        )

    @requireDarwin
    def test_invalid_scripted_register_context(self):
        """Test that we can launch an lldb scripted process with an invalid
        Scripted Thread, with invalid register context."""
        self.build()

        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"

        def cleanup():
            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]

        self.addTearDownHook(cleanup)

        self.runCmd("settings set target.load-script-from-symbol-file true")
        self.move_blueprint_to_dsym("invalid_scripted_process.py")
        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)
        log_file = self.getBuildArtifact("thread.log")
        self.runCmd("log enable lldb thread -f " + log_file)
        self.assertTrue(os.path.isfile(log_file))

        launch_info = lldb.SBLaunchInfo(None)
        launch_info.SetProcessPluginName("ScriptedProcess")
        launch_info.SetScriptedProcessClassName("a_out.InvalidScriptedProcess")
        error = lldb.SBError()

        process = target.Launch(launch_info, error)

        self.assertSuccess(error)
        self.assertTrue(process, PROCESS_IS_VALID)
        self.assertEqual(process.GetProcessID(), 666)
        self.assertEqual(process.GetNumThreads(), 0)

        impl = process.GetScriptedImplementation()
        self.assertTrue(impl)
        impl = process.GetScriptedImplementation()
        self.assertTrue(impl)
        impl = process.GetScriptedImplementation()
        self.assertTrue(impl)
        impl = process.GetScriptedImplementation()
        self.assertTrue(impl)

        addr = 0x500000000
        buff = process.ReadMemory(addr, 4, error)
        self.assertEqual(buff, None)
        self.assertTrue(error.Fail())
        self.assertEqual(
            error.GetCString(),
            "Failed to read memory from scripted process at 0x500000000: "
            "This is an invalid scripted process!",
        )

        with open(log_file, "r") as f:
            log = f.read()

        self.assertIn("Failed to get scripted thread registers data.", log)

    @skipUnlessDarwin
    def test_scripted_extension_instances(self):
        """Test that the threads and frames a scripted process creates in Python
        are listed under their own classes, not under the process's."""
        self.build()
        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)

        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"

        def cleanup():
            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]

        self.addTearDownHook(cleanup)

        script_path = os.path.join(self.getSourceDir(), "dummy_scripted_process.py")
        self.runCmd("command script import " + script_path)

        args = lldb.SBStructuredData()
        self.assertSuccess(args.SetFromJSON('{"answer": 42}'))
        launch_info = lldb.SBLaunchInfo(None)
        launch_info.SetProcessPluginName("ScriptedProcess")
        launch_info.SetScriptedProcessClassName(
            "dummy_scripted_process.DummyScriptedProcess"
        )
        launch_info.SetScriptedProcessDictionary(args)

        error = lldb.SBError()
        process = target.Launch(launch_info, error)
        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
        # Fetching the frames is what wraps the Python frame objects.
        self.assertGreater(process.GetThreadAtIndex(0).GetNumFrames(), 0)

        result = lldb.SBCommandReturnObject()
        self.dbg.GetCommandInterpreter().HandleCommand(
            "scripting extension list --instances --json", result
        )
        self.assertTrue(result.Succeeded(), result.GetError())
        data = lldb.SBStructuredData()
        self.assertSuccess(data.SetFromJSON(result.GetOutput()))
        groups = {}
        for i in range(data.GetSize()):
            group = data.GetItemAtIndex(i)
            groups[group.GetValueForKey("class_name").GetStringValue(256)] = group

        def args_of(class_name):
            instance = groups[class_name].GetValueForKey("instances").GetItemAtIndex(0)
            return instance.GetValueForKey("args")

        process_class = "dummy_scripted_process.DummyScriptedProcess"
        thread_class = "dummy_scripted_process.DummyScriptedThread"
        frame_class = "dummy_scripted_process.DummyScriptedFrame"
        self.assertIn(process_class, groups)
        self.assertIn(thread_class, groups)
        self.assertIn(frame_class, groups)
        self.assertEqual(groups[process_class].GetValueForKey("instances").GetSize(), 1)
        for class_name in (thread_class, frame_class):
            self.assertEqual(
                os.path.realpath(
                    groups[class_name]
                    .GetValueForKey("source_path")
                    .GetStringValue(4096)
                ),
                os.path.realpath(script_path),
            )

        # Only the process was created from the launch arguments.
        self.assertEqual(
            args_of(process_class).GetValueForKey("answer").GetIntegerValue(), 42
        )
        self.assertFalse(args_of(thread_class).IsValid())

    @skipUnlessDarwin
    def test_scripted_process_and_scripted_thread(self):
        """Test that we can launch an lldb scripted process using the SBAPI,
        check its process ID, read string from memory, check scripted thread
        id, name stop reason and register context.
        """
        self.build()
        target_0 = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target_0, VALID_TARGET)

        os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] = "1"

        def cleanup():
            del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]

        self.addTearDownHook(cleanup)

        scripted_process_example_relpath = "dummy_scripted_process.py"
        self.runCmd(
            "command script import "
            + os.path.join(self.getSourceDir(), scripted_process_example_relpath)
        )

        self.runCmd(
            "target stop-hook add -k first -v 1 -k second -v 2 -P dummy_scripted_process.DummyStopHook"
        )

        launch_info = lldb.SBLaunchInfo(None)
        launch_info.SetProcessPluginName("ScriptedProcess")
        launch_info.SetScriptedProcessClassName(
            "dummy_scripted_process.DummyScriptedProcess"
        )

        error = lldb.SBError()
        process_0 = target_0.Launch(launch_info, error)
        self.assertTrue(process_0 and process_0.IsValid(), PROCESS_IS_VALID)
        self.assertEqual(process_0.GetProcessID(), 42)
        self.assertEqual(process_0.GetNumThreads(), 1)

        py_impl = process_0.GetScriptedImplementation()
        self.assertTrue(py_impl)
        self.assertIsInstance(py_impl, dummy_scripted_process.DummyScriptedProcess)
        self.assertFalse(hasattr(py_impl, "my_super_secret_member"))
        py_impl.my_super_secret_member = 42
        self.assertTrue(hasattr(py_impl, "my_super_secret_member"))
        self.assertEqual(py_impl.my_super_secret_method(), 42)

        self.assertTrue(hasattr(py_impl, "handled_stop"))
        self.assertTrue(py_impl.handled_stop)

        # Try reading from target #0 process ...
        addr = 0x500000000
        message = "Hello, target 0"
        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)
        self.assertSuccess(error)
        self.assertEqual(buff, message)

        target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target_1, VALID_TARGET)

        # We still need to specify a PID when attaching even for scripted processes
        attach_info = lldb.SBAttachInfo(42)
        attach_info.SetProcessPluginName("ScriptedProcess")
        attach_info.SetScriptedProcessClassName(
            "dummy_scripted_process.DummyScriptedProcess"
        )

        error = lldb.SBError()
        process_1 = target_1.Attach(attach_info, error)
        self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID)
        self.assertEqual(process_1.GetProcessID(), 42)
        self.assertEqual(process_1.GetNumThreads(), 1)

        # ... then try reading from target #1 process ...
        message = "Hello, target 1"
        buff = process_1.ReadCStringFromMemory(addr, len(message) + 1, error)
        self.assertSuccess(error)
        self.assertEqual(buff, message)

        # ... now, reading again from target #0 process to make sure the call
        # gets dispatched to the right target.
        message = "Hello, target 0"
        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)
        self.assertSuccess(error)
        self.assertEqual(buff, message)

        # Let's write some memory.
        message = "Hello, world!"
        bytes_written = process_0.WriteMemoryAsCString(addr, message, error)
        self.assertSuccess(error)
        self.assertEqual(bytes_written, len(message) + 1)

        # ... and check if that memory was saved properly.
        buff = process_0.ReadCStringFromMemory(addr, len(message) + 1, error)
        self.assertSuccess(error)
        self.assertEqual(buff, message)

        thread = process_0.GetSelectedThread()
        self.assertTrue(thread, "Invalid thread.")
        self.assertEqual(thread.GetThreadID(), 0x19)
        self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1")
        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonTrace)

        self.assertGreater(thread.GetNumFrames(), 0)

        frame = thread.GetFrameAtIndex(0)
        GPRs = None
        register_set = frame.registers  # Returns an SBValueList.
        for regs in register_set:
            if "general purpose" in regs.name.lower():
                GPRs = regs
                break

        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
        self.assertGreater(GPRs.GetNumChildren(), 0)
        for idx, reg in enumerate(GPRs, start=1):
            if idx > 21:
                break
            self.assertEqual(idx, int(reg.value, 16))

        self.assertTrue(frame.IsSynthetic(), "Frame is not synthetic")
        pc = frame.GetPCAddress().GetLoadAddress(target_0)
        self.assertEqual(pc, 0x0100001B00)

        # Regression test: ScriptedFrame.__init__ used GetThreadByIndexID(tid)
        # instead of GetThreadByID(tid). If the thread ID doesn't match any
        # thread index, the lookup returns an invalid SBThread. Downstream,
        # resolving the execution context from an SBFrame backed by this
        # invalid thread yields a null Process, and calling
        # ProcessModID::IsRunningExpression() on it crashes.
        tid = thread.GetThreadID()
        self.assertTrue(
            process_0.GetThreadByID(tid).IsValid(),
            "GetThreadByID(tid) should find the thread",
        )
        self.assertFalse(
            process_0.GetThreadByIndexID(tid).IsValid(),
            "GetThreadByIndexID(tid) should NOT find the thread "
            "(index ID != thread ID)",
        )

        # Construct a new ScriptedFrame with the SBThread (which carries the
        # real thread ID) and verify its thread member is valid. This exercises
        # the SBThread branch in ScriptedFrame.__init__ where thread.id is
        # used with GetThreadByID.
        post_launch_frame = dummy_scripted_process.DummyScriptedFrame(
            thread, lldb.SBStructuredData(), 42, "test_frame"
        )
        self.assertTrue(
            post_launch_frame.thread.IsValid(),
            "ScriptedFrame.thread should be valid after thread " "registration",
        )
        self.assertEqual(post_launch_frame.thread.GetThreadID(), tid)

    # No dylib on Windows.
    @skipIfWindows
    @skipIf(archs=no_match(["arm64", "arm64e", "aarch64"]))
    def test_scripted_process_addressable_bits(self):
        """Test that the addressable bits a scripted process reports are in
        effect for the very first stop, without resuming the process."""
        self.build()

        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)

        self.runCmd(
            "command script import "
            + os.path.join(self.getSourceDir(), "addressable_bits_scripted_process.py")
        )

        launch_info = lldb.SBLaunchInfo(None)
        launch_info.SetProcessPluginName("ScriptedProcess")
        launch_info.SetScriptedProcessClassName(
            "addressable_bits_scripted_process.AddressableBitsScriptedProcess"
        )

        error = lldb.SBError()
        process = target.Launch(launch_info, error)
        self.assertSuccess(error)
        self.assertTrue(process, PROCESS_IS_VALID)

        # The script only reports "lowmem", so the high memory masks have to
        # fall back to it.
        for mask_type in [lldb.eAddressMaskTypeCode, lldb.eAddressMaskTypeData]:
            for mask_range in [lldb.eAddressMaskRangeLow, lldb.eAddressMaskRangeHigh]:
                self.assertEqual(
                    process.GetAddressMask(mask_type, mask_range),
                    0xFFFFFFFC00000000,
                    f"mask type {mask_type}, range {mask_range}",
                )
        self.assertEqual(
            process.FixAddress(addressable_bits_scripted_process.TAGGED_PC),
            addressable_bits_scripted_process.FIXED_PC,
        )

        # The mask has to have been installed before the threads and their
        # stack frames were built for this stop: nothing resumes the process
        # here, so a frame that resolved its pc with the default mask would
        # never be recomputed.
        #
        # Thread 0 has its frame zero built by the unwinder from the register
        # context, thread 1 reports its frames from the script.
        for idx in range(2):
            frame = process.GetThreadAtIndex(idx).GetFrameAtIndex(0)
            self.assertEqual(
                frame.GetPC(),
                addressable_bits_scripted_process.FIXED_PC,
                f"thread {idx} frame zero pc",
            )
