"""
Test SBTarget APIs.
"""

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


class TargetAPITestCase(TestBase):
    SHARED_BUILD_TESTCASE = False

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line number to of function 'c'.
        self.line1 = line_number(
            "main.c", "// Find the line number for breakpoint 1 here."
        )
        self.line2 = line_number(
            "main.c", "// Find the line number for breakpoint 2 here."
        )
        self.line_main = line_number("main.c", "// Set a break at entry to main.")

    # rdar://problem/9700873
    # Find global variable value fails for dwarf if inferior not started
    # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)
    #
    # It does not segfaults now.  But for dwarf, the variable value is None if
    # the inferior process does not exist yet.  The radar has been updated.
    def test_find_global_variables(self):
        """Exercise SBTarget.FindGlobalVariables() API."""
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        self.find_global_variables("b.out")

    def test_find_compile_units(self):
        """Exercise SBTarget.FindCompileUnits() API."""
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        self.find_compile_units(self.getBuildArtifact("b.out"))

    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
    def test_find_functions(self):
        """Exercise SBTarget.FindFunctions() API."""
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        self.find_functions("b.out")

    def test_get_description(self):
        """Exercise SBTarget.GetDescription() API."""
        self.build()
        self.get_description()

    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
    def test_resolve_symbol_context_with_address(self):
        """Exercise SBTarget.ResolveSymbolContextForAddress() API."""
        self.build()
        self.resolve_symbol_context_with_address()

    def test_get_platform(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")
        platform = target.platform
        self.assertTrue(platform, VALID_PLATFORM)

    def test_resolve_file_address(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        # find the file address in the .data section of the main
        # module
        data_section = self.find_data_section(target)
        data_section_addr = data_section.file_addr

        # resolve the above address, and compare the address produced
        # by the resolution against the original address/section
        res_file_addr = target.ResolveFileAddress(data_section_addr)
        self.assertTrue(res_file_addr.IsValid())

        self.assertEqual(data_section_addr, res_file_addr.file_addr)

        data_section2 = res_file_addr.section
        self.assertIsNotNone(data_section2)
        self.assertEqual(data_section.name, data_section2.name)

    def test_get_arch_name(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        arch_name = target.arch_name
        self.assertTrue(len(arch_name) > 0, "Got an arch name")

        # Test consistency with triple.
        triple = target.triple
        self.assertTrue(len(triple) > 0, "Got a triple")
        self.assertEqual(
            triple.split("-")[0],
            arch_name,
            "Arch name is equal to the first item of the triple",
        )

    @skipIfWasm  # there is no ABI plugin for Wasm to name
    def test_get_ABIName(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        abi_pre_launch = target.GetABIName()
        self.assertNotEqual(len(abi_pre_launch), 0, "Got an ABI string")

        breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main)
        self.assertTrue(breakpoint, VALID_BREAKPOINT)

        # Put debugger into synchronous mode so when we target.LaunchSimple returns
        # it will guaranteed to be at the breakpoint
        self.dbg.SetAsync(False)

        # Launch the process, and do not stop at the entry point.
        process = target.LaunchSimple(None, None, self.get_process_working_directory())
        abi_after_launch = target.GetABIName()
        self.assertEqual(
            abi_pre_launch, abi_after_launch, "ABI's match before and during run"
        )

    @skipIfWasm  # zero is a valid address in a Wasm linear memory, so a read of it succeeds
    def test_read_memory(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main)
        self.assertTrue(breakpoint, VALID_BREAKPOINT)

        # Put debugger into synchronous mode so when we target.LaunchSimple returns
        # it will guaranteed to be at the breakpoint
        self.dbg.SetAsync(False)

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

        # find the file address in the .data section of the main
        # module
        data_section = self.find_data_section(target)
        sb_addr = lldb.SBAddress(data_section, 0)
        error = lldb.SBError()
        content = target.ReadMemory(sb_addr, 1, error)
        self.assertSuccess(error, "Make sure memory read succeeded")
        self.assertEqual(len(content), 1)

        # Make sure reading from 0x0 fails
        sb_addr = lldb.SBAddress(0, target)
        self.assertIsNone(target.ReadMemory(sb_addr, 1, error))
        self.assertTrue(error.Fail())

    @skipIfWindows  # stdio manipulation unsupported on Windows
    @skipIfRemote  # stdio manipulation unsupported on remote iOS devices<rdar://problem/54581135>
    @skipIf(oslist=["linux"], archs=["arm$", "aarch64"])
    @no_debug_info_test
    def test_launch_simple(self):
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        # Set the debugger to synchronous mode so we only continue after the
        # process has exited.
        self.dbg.SetAsync(False)

        process = target.LaunchSimple(
            ["foo", "bar"], ["baz"], self.get_process_working_directory()
        )
        process.Continue()
        self.assertState(process.GetState(), lldb.eStateExited)
        output = process.GetSTDOUT(9999)
        self.assertIn("arg: foo", output)
        self.assertIn("arg: bar", output)
        self.assertIn("env: baz", output)

        self.runCmd("setting set target.run-args foo")
        self.runCmd("setting set target.env-vars bar=baz")
        process = target.LaunchSimple(None, None, self.get_process_working_directory())
        process.Continue()
        self.assertState(process.GetState(), lldb.eStateExited)
        output = process.GetSTDOUT(9999)
        self.assertIn("arg: foo", output)
        self.assertIn("env: bar=baz", output)

        # Clear all the run args set above.
        self.runCmd("setting clear target.run-args")
        process = target.LaunchSimple(None, None, self.get_process_working_directory())
        process.Continue()
        self.assertEqual(process.GetState(), lldb.eStateExited)
        output = process.GetSTDOUT(9999)
        self.assertNotIn("arg: foo", output)

        self.runCmd("settings set target.disable-stdio true")
        process = target.LaunchSimple(None, None, self.get_process_working_directory())
        process.Continue()
        self.assertState(process.GetState(), lldb.eStateExited)
        output = process.GetSTDOUT(9999)
        self.assertEqual(output, "")

    def create_simple_target(self, fn):
        exe = self.getBuildArtifact(fn)
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)
        return target

    def find_data_section(self, target):
        mod = target.GetModuleAtIndex(0)
        data_section = None
        for s in mod.sections:
            sect_type = s.GetSectionType()
            if sect_type == lldb.eSectionTypeData:
                data_section = s
                break
            elif sect_type == lldb.eSectionTypeContainer:
                for i in range(s.GetNumSubSections()):
                    ss = s.GetSubSectionAtIndex(i)
                    sect_type = ss.GetSectionType()
                    if sect_type == lldb.eSectionTypeData:
                        data_section = ss
                        break

        self.assertIsNotNone(data_section)
        return data_section

    def find_global_variables(self, exe_name):
        """Exercise SBTarget.FindGlobalVariables() API."""
        # rdar://problem/9700873
        # Find global variable value fails for dwarf if inferior not started
        # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)
        # Remove the lines to create a breakpoint and to start the inferior
        # which are workarounds for the dwarf case.
        target, _, _, _ = lldbutil.run_to_line_breakpoint(
            self, lldb.SBFileSpec("main.c"), self.line1, exe_name=exe_name
        )

        value_list = target.FindGlobalVariables("my_global_var_of_char_type", 3)
        self.assertEqual(value_list.GetSize(), 1)
        my_global_var = value_list.GetValueAtIndex(0)
        self.DebugSBValue(my_global_var)
        self.assertTrue(my_global_var)
        self.expect(
            my_global_var.GetName(), exe=False, startstr="my_global_var_of_char_type"
        )
        self.expect(my_global_var.GetTypeName(), exe=False, startstr="char")
        self.expect(my_global_var.GetValue(), exe=False, startstr="'X'")

        # While we are at it, let's also exercise the similar
        # SBModule.FindGlobalVariables() API.
        for m in target.module_iter():
            if (
                os.path.normpath(m.GetFileSpec().GetDirectory()) == self.getBuildDir()
                and m.GetFileSpec().GetFilename() == exe_name
            ):
                value_list = m.FindGlobalVariables(
                    target, "my_global_var_of_char_type", 3
                )
                self.assertEqual(value_list.GetSize(), 1)
                self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "'X'")
                break

    def find_compile_units(self, exe):
        """Exercise SBTarget.FindCompileUnits() API."""
        source_name = "main.c"

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

        list = target.FindCompileUnits(lldb.SBFileSpec(source_name, False))
        # Executable has been built just from one source file 'main.c',
        # so we may check only the first element of list.
        self.assertEqual(
            list[0].GetCompileUnit().GetFileSpec().GetFilename(), source_name
        )

    def find_functions(self, exe_name):
        """Exercise SBTarget.FindFunctions() API."""
        exe = self.getBuildArtifact(exe_name)

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

        # Try it with a null name:
        list = target.FindFunctions(None, lldb.eFunctionNameTypeAuto)
        self.assertEqual(list.GetSize(), 0)

        list = target.FindFunctions("c", lldb.eFunctionNameTypeAuto)
        self.assertEqual(list.GetSize(), 1)

        for sc in list:
            self.assertEqual(sc.GetModule().GetFileSpec().GetFilename(), exe_name)
            self.assertEqual(sc.GetSymbol().GetName(), "c")

    def get_description(self):
        """Exercise SBTarget.GetDescription() API."""
        exe = self.getBuildArtifact("a.out")

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

        from lldbsuite.test.lldbutil import get_description

        # get_description() allows no option to mean
        # lldb.eDescriptionLevelBrief.
        desc = get_description(target)
        # desc = get_description(target, option=lldb.eDescriptionLevelBrief)
        if not desc:
            self.fail("SBTarget.GetDescription() failed")
        self.expect(desc, exe=False, substrs=["a.out"])
        self.expect(
            desc, exe=False, matching=False, substrs=["Target", "Module", "Breakpoint"]
        )

        desc = get_description(target, option=lldb.eDescriptionLevelFull)
        if not desc:
            self.fail("SBTarget.GetDescription() failed")
        self.expect(
            desc, exe=False, substrs=["Target", "Module", "a.out", "Breakpoint"]
        )

    @skipIfRemote
    @no_debug_info_test
    def test_launch_new_process_and_redirect_stdout(self):
        """Exercise SBTarget.Launch() API with redirected stdout."""
        self.build()
        exe = self.getBuildArtifact("a.out")

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

        # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done.
        # We should still see the entire stdout redirected once the process is
        # finished.
        line = line_number("main.c", "// a(3) -> c(3)")
        breakpoint = target.BreakpointCreateByLocation("main.c", line)

        # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file.
        # The inferior should run to completion after "process.Continue()"
        # call.
        local_path = self.getBuildArtifact("stdout.txt")
        if os.path.exists(local_path):
            os.remove(local_path)

        if lldb.remote_platform:
            stdout_path = lldbutil.append_to_process_working_directory(
                self, "lldb-stdout-redirect.txt"
            )
        else:
            stdout_path = local_path
        error = lldb.SBError()
        process = target.Launch(
            self.dbg.GetListener(),
            None,
            None,
            None,
            stdout_path,
            None,
            None,
            0,
            False,
            error,
        )
        process.Continue()
        # self.runCmd("process status")
        if lldb.remote_platform:
            # copy output file to host
            lldb.remote_platform.Get(
                lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path)
            )

        # The 'stdout.txt' file should now exist.
        self.assertTrue(
            os.path.isfile(local_path),
            "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.",
        )

        # Read the output file produced by running the program.
        with open(local_path, "r") as f:
            output = f.read()

        self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"])

    def resolve_symbol_context_with_address(self):
        """Exercise SBTarget.ResolveSymbolContextForAddress() API."""
        exe = self.getBuildArtifact("a.out")

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

        # Now create the two breakpoints inside function 'a'.
        breakpoint1 = target.BreakpointCreateByLocation("main.c", self.line1)
        breakpoint2 = target.BreakpointCreateByLocation("main.c", self.line2)
        self.trace("breakpoint1:", breakpoint1)
        self.trace("breakpoint2:", breakpoint2)
        self.assertTrue(
            breakpoint1 and breakpoint1.GetNumLocations() == 1, VALID_BREAKPOINT
        )
        self.assertTrue(
            breakpoint2 and breakpoint2.GetNumLocations() == 1, VALID_BREAKPOINT
        )

        # Now launch the process, and do not stop at entry point.
        process = target.LaunchSimple(None, None, self.get_process_working_directory())
        self.assertTrue(process, PROCESS_IS_VALID)

        # Frame #0 should be on self.line1.
        self.assertState(process.GetState(), lldb.eStateStopped)
        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
        self.assertTrue(
            thread.IsValid(),
            "There should be a thread stopped due to breakpoint condition",
        )
        # self.runCmd("process status")
        frame0 = thread.GetFrameAtIndex(0)
        lineEntry = frame0.GetLineEntry()
        self.assertEqual(lineEntry.GetLine(), self.line1)

        address1 = lineEntry.GetStartAddress()

        # Continue the inferior, the breakpoint 2 should be hit.
        process.Continue()
        self.assertState(process.GetState(), lldb.eStateStopped)
        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
        self.assertTrue(
            thread.IsValid(),
            "There should be a thread stopped due to breakpoint condition",
        )
        # self.runCmd("process status")
        frame0 = thread.GetFrameAtIndex(0)
        lineEntry = frame0.GetLineEntry()
        self.assertEqual(lineEntry.GetLine(), self.line2)

        address2 = lineEntry.GetStartAddress()

        self.trace("address1:", address1)
        self.trace("address2:", address2)

        # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses
        # from our line entry.
        context1 = target.ResolveSymbolContextForAddress(
            address1, lldb.eSymbolContextEverything
        )
        context2 = target.ResolveSymbolContextForAddress(
            address2, lldb.eSymbolContextEverything
        )

        self.assertTrue(context1 and context2)
        self.trace("context1:", context1)
        self.trace("context2:", context2)

        # Verify that the context point to the same function 'a'.
        symbol1 = context1.GetSymbol()
        symbol2 = context2.GetSymbol()
        self.assertTrue(symbol1 and symbol2)
        self.trace("symbol1:", symbol1)
        self.trace("symbol2:", symbol2)

        from lldbsuite.test.lldbutil import get_description

        desc1 = get_description(symbol1)
        desc2 = get_description(symbol2)
        self.assertTrue(
            desc1 and desc2 and desc1 == desc2,
            "The two addresses should resolve to the same symbol",
        )

    @skipIfRemote
    @skipIfWasm  # the default architecture is the host's, which no Wasm module matches
    def test_default_arch(self):
        """Test the other two target create methods using LLDB_ARCH_DEFAULT."""
        self.build()
        exe = self.getBuildArtifact("a.out")
        target = self.dbg.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)
        self.assertTrue(target.IsValid(), "Default arch made a valid target.")
        # This should also work with the target's triple:
        target2 = self.dbg.CreateTargetWithFileAndArch(exe, target.GetTriple())
        self.assertTrue(target2.IsValid(), "Round trip with triple works")
        # And this triple should work for the FileAndTriple API:
        target3 = self.dbg.CreateTargetWithFileAndTargetTriple(exe, target.GetTriple())
        self.assertTrue(target3.IsValid())

    @skipIfWindows
    def test_is_loaded(self):
        """Exercise SBTarget.IsLoaded(SBModule&) API."""
        d = {"EXE": "b.out"}
        self.build(dictionary=d)
        self.setTearDownCleanup(dictionary=d)
        target = self.create_simple_target("b.out")

        self.assertFalse(target.IsLoaded(lldb.SBModule()))

        num_modules = target.GetNumModules()
        for i in range(num_modules):
            module = target.GetModuleAtIndex(i)
            self.assertFalse(
                target.IsLoaded(module),
                "Target that isn't " "running shouldn't have any module loaded.",
            )

        process = target.LaunchSimple(None, None, self.get_process_working_directory())

        for i in range(num_modules):
            module = target.GetModuleAtIndex(i)
            self.assertTrue(
                target.IsLoaded(module),
                "Running the target should " "have loaded its modules.",
            )

    @no_debug_info_test
    def test_setting_selected_target_with_invalid_target(self):
        """Make sure we don't crash when trying to select invalid target."""
        target = lldb.SBTarget()
        self.dbg.SetSelectedTarget(target)

    @no_debug_info_test
    def test_get_api_mutex(self):
        """Make sure we can lock and unlock the API mutex from Python."""
        target = self.dbg.GetDummyTarget()

        mutex = target.GetAPIMutex()
        self.assertTrue(mutex.IsValid())
        mutex.lock()
        # The API call below doesn't actually matter, it's just there to
        # confirm we don't block on the API lock.
        target.BreakpointCreateByName("foo", "bar")
        mutex.unlock()

    @no_debug_info_test
    def test_get_api_mutex_with_statement(self):
        """Make sure we can lock and unlock the API mutex using a with-statement from Python."""
        target = self.dbg.GetDummyTarget()

        with target.GetAPIMutex() as mutex:
            self.assertTrue(mutex.IsValid())
            # The API call below doesn't actually matter, it's just there to
            # confirm we don't block on the API lock.
            target.BreakpointCreateByName("foo", "bar")
