"""
Test support for the DebugInfoD network symbol acquisition protocol.
"""
import os
import shutil
import tempfile

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


"""
Test support for the DebugInfoD network symbol acquisition protocol.
This file is for split-dwarf (dwp) scenarios.

1 - A split binary target with it's corresponding DWP file
2 - A stripped, split binary target with an unstripped binary and a DWP file
3 - A stripped, split binary target with an --only-keep-debug symbols file and a DWP file
"""


# It looks like Linux-AArch64 doesn't support build-id's on the LLDB builtbots
class DebugInfodDWPTests(TestBase):
    # No need to try every flavor of debug inf.
    NO_DEBUG_INFO_TESTCASE = True

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_normal_stripped(self):
        """
        Validate behavior with a stripped binary, no symbols or symbol locator.
        """
        self.config_test(["a.out"])
        self.try_breakpoint(False)

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_normal_stripped_split_with_dwp(self):
        """
        Validate behavior with symbols, but no symbol locator.
        """
        self.config_test(["a.out", "a.out.debug", "a.out.dwp"])
        self.try_breakpoint(True)

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_normal_stripped_only_dwp(self):
        """
        Validate behavior *with* dwp symbols only, but missing other symbols,
        but no symbol locator. This shouldn't work: without the other symbols
        DWO's appear mostly useless.
        """
        self.config_test(["a.out", "a.out.dwp"])
        self.try_breakpoint(False)

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_debuginfod_dwp_from_service(self):
        """
        Test behavior with the unstripped binary, and DWP from the service.
        """
        self.config_test(["a.out.debug"], "a.out.dwp")
        self.try_breakpoint(True)

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_debuginfod_both_symfiles_from_service(self):
        """
        Test behavior with a stripped binary, with the unstripped binary and
        dwp symbols from Debuginfod.
        """
        self.config_test(["a.out"], "a.out.dwp", "a.out.unstripped")
        self.try_breakpoint(True)

    @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))
    def test_debuginfod_both_okd_symfiles_from_service(self):
        """
        Test behavior with both the only-keep-debug symbols and the dwp symbols
        from Debuginfod.
        """
        self.config_test(["a.out"], "a.out.dwp", "a.out.debug")
        self.try_breakpoint(True)

    def try_breakpoint(self, should_have_loc):
        """
        This function creates a target from self.aout, sets a function-name
        breakpoint, and checks to see if we have a file/line location,
        as a way to validate that the symbols have been loaded.
        should_have_loc specifies if we're testing that symbols have or
        haven't been loaded.
        """
        target = self.dbg.CreateTarget(self.aout)
        self.assertTrue(target and target.IsValid(), "Target is valid")

        bp = target.BreakpointCreateByName("func")
        self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid")
        self.assertEqual(bp.GetNumLocations(), 1)

        loc = bp.GetLocationAtIndex(0)
        self.assertTrue(loc and loc.IsValid(), "Location is valid")
        addr = loc.GetAddress()
        self.assertTrue(addr and addr.IsValid(), "Loc address is valid")
        line_entry = addr.GetLineEntry()
        self.assertEqual(
            should_have_loc,
            line_entry != None and line_entry.IsValid(),
            "Loc line entry is valid",
        )
        if should_have_loc:
            self.assertEqual(line_entry.GetLine(), 4)
            self.assertEqual(
                line_entry.GetFileSpec().GetFilename(),
                self.main_source_file.GetFilename(),
            )
        self.dbg.DeleteTarget(target)
        shutil.rmtree(self.tmp_dir)

    def config_test(self, local_files, debuginfo=None, executable=None):
        """
        Set up a test with local_files[] copied to a different location
        so that we control which files are, or are not, found in the file system.
        Also, create a stand-alone file-system 'hosted' debuginfod server with the
        provided debuginfo and executable files (if they exist)

        Make the filesystem look like:

        /tmp/<tmpdir>/test/[local_files]

        /tmp/<tmpdir>/cache (for lldb to use as a temp cache)

        /tmp/<tmpdir>/buildid/<uuid>/executable -> <executable>
        /tmp/<tmpdir>/buildid/<uuid>/debuginfo -> <debuginfo>
        Returns the /tmp/<tmpdir> path
        """

        self.build()

        uuid = self.getUUID("a.out")
        if not uuid:
            self.fail("Could not get UUID for a.out")
            return
        self.main_source_file = lldb.SBFileSpec("main.c")
        self.tmp_dir = tempfile.mkdtemp()
        self.test_dir = os.path.join(self.tmp_dir, "test")
        os.makedirs(self.test_dir)

        self.aout = ""
        # Copy the files used by the test:
        for f in local_files:
            shutil.copy(self.getBuildArtifact(f), self.test_dir)
            if self.aout == "":
                self.aout = os.path.join(self.test_dir, f)

        use_debuginfod = debuginfo != None or executable != None

        # Populated the 'file://... mocked' Debuginfod server:
        if use_debuginfod:
            os.makedirs(os.path.join(self.tmp_dir, "cache"))
            uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid)
            os.makedirs(uuid_dir)
            if debuginfo:
                shutil.copy(
                    self.getBuildArtifact(debuginfo),
                    os.path.join(uuid_dir, "debuginfo"),
                )
            if executable:
                shutil.copy(
                    self.getBuildArtifact(executable),
                    os.path.join(uuid_dir, "executable"),
                )
        os.remove(self.getBuildArtifact("main.dwo"))
        # Configure LLDB for the test:
        self.runCmd(
            "settings set symbols.enable-external-lookup %s"
            % str(use_debuginfod).lower()
        )
        self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls")
        if use_debuginfod:
            self.runCmd(
                "settings set plugin.symbol-locator.debuginfod.cache-path %s/cache"
                % self.tmp_dir
            )
            self.runCmd(
                "settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s"
                % self.tmp_dir
            )

    def getUUID(self, filename):
        try:
            target = self.dbg.CreateTarget(self.getBuildArtifact(filename))
            module = target.GetModuleAtIndex(0)
            uuid = module.GetUUIDString().replace("-", "").lower()
            self.dbg.DeleteTarget(target)
            return uuid if len(uuid) == 40 else None
        except:
            return None
