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 one is for simple / no split-dwarf scenarios.

For no-split-dwarf scenarios, there are 2 variations:
1 - A stripped binary with it's corresponding unstripped binary:
2 - A stripped binary with a corresponding --only-keep-debug symbols file
"""


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

    @skipUnlessPlatform(["linux", "freebsd"])
    def test_normal_no_symbols(self):
        """
        Validate behavior with no symbols or symbol locator.
        ('baseline negative' behavior)
        """
        test_root = self.config_test(["a.out"])
        self.try_breakpoint(False)

    @skipUnlessPlatform(["linux", "freebsd"])
    def test_normal_default(self):
        """
        Validate behavior with symbols, but no symbol locator.
        ('baseline positive' behavior)
        """
        test_root = self.config_test(["a.out", "a.out.debug"])
        self.try_breakpoint(True)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux", "freebsd"])
    def test_debuginfod_symbols(self):
        """
        Test behavior with the full binary available from Debuginfod as
        'debuginfo' from the plug-in.
        """
        test_root = self.config_test(["a.out"], "a.out.unstripped")
        self.try_breakpoint(True)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux", "freebsd"])
    def test_debuginfod_executable(self):
        """
        Test behavior with the full binary available from Debuginfod as
        'executable' from the plug-in.
        """
        test_root = self.config_test(["a.out"], None, "a.out.unstripped")
        self.try_breakpoint(True)

    @skipIfCurlSupportMissing
    @skipUnlessPlatform(["linux", "freebsd"])
    def test_debuginfod_okd_symbols(self):
        """
        Test behavior with the 'only-keep-debug' symbols available from Debuginfod.
        """
        test_root = self.config_test(["a.out"], "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()
        test_dir = os.path.join(self.tmp_dir, "test")
        os.makedirs(test_dir)

        self.aout = ""
        # Copy the files used by the test:
        for f in local_files:
            shutil.copy(self.getBuildArtifact(f), test_dir)
            # The first item is the binary to be used for the test
            if self.aout == "":
                self.aout = os.path.join(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"),
                )

        # 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
