"""
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
"""


class DebugInfodDWPTests(TestBase):
    # No need to try every flavor of debug inf.
    NO_DEBUG_INFO_TESTCASE = True

    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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)

    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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)

    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
    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:
            spec = lldb.SBModuleSpec()
            spec.SetFileSpec(lldb.SBFileSpec(self.getBuildArtifact(filename)))
            module = lldb.SBModule(spec)
            uuid = module.GetUUIDString().replace("-", "").lower()
            # Don't want lldb's fake 32 bit CRC's for this one
            return uuid if len(uuid) > 8 else None
        except:
            return None
