import os
import platform
import re
import subprocess
import sys

import lit.formats
import lit.util

from lit.llvm import llvm_config
from lit.llvm.subst import ToolSubst

# Configuration file for the 'lit' test runner.

# name: The name of this test suite.
config.name = "cross-project-tests"

# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)

# suffixes: A list of file extensions to treat as test files.
config.suffixes = [".c", ".cl", ".cpp", ".m", ".test"]

# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
# directories.
config.excludes = ["Inputs"]

# test_source_root: The root path where tests are located.
config.test_source_root = config.cross_project_tests_src_root

# test_exec_root: The root path where tests should be run.
config.test_exec_root = config.cross_project_tests_obj_root

llvm_config.use_default_substitutions()

lldb_python_path = os.path.join(
    config.llvm_libs_dir,
    f"python{sys.version_info.major}.{sys.version_info.minor}",
    "site-packages",
)
python_exec_path = sys.executable
tools = [
    ToolSubst(
        "%test_debuginfo",
        command="PYTHON_EXEC_PATH="
        + python_exec_path
        + " LLDB_PYTHON_PATH="
        + lldb_python_path
        + " "
        + os.path.join(
            config.cross_project_tests_src_root,
            "debuginfo-tests",
            "llgdb-tests",
            "test_debuginfo.pl",
        ),
    ),
    ToolSubst("%llvm_src_root", config.llvm_src_root),
    ToolSubst("%llvm_tools_dir", config.llvm_tools_dir),
]


def get_required_attr(config, attr_name):
    attr_value = getattr(config, attr_name, None)
    if attr_value is None:
        lit_config.fatal(
            "No attribute %r in test configuration! You may need to run "
            "tests from your build directory or add this attribute "
            "to lit.site.cfg " % attr_name
        )
    return attr_value


# If this is an MSVC environment, the tests at the root of the tree are
# unsupported. The local win_cdb test suite, however, is supported.
is_msvc = get_required_attr(config, "is_msvc")
if is_msvc:
    config.available_features.add("msvc")
    # FIXME: We should add some llvm lit utility code to find the Windows SDK
    # and set up the environment appopriately.
    win_sdk = "C:/Program Files (x86)/Windows Kits/10/"
    arch = "x64"
    llvm_config.with_system_environment(["LIB", "LIBPATH", "INCLUDE"])
    # Clear _NT_SYMBOL_PATH to prevent cdb from attempting to load symbols from
    # the network.
    llvm_config.with_environment("_NT_SYMBOL_PATH", "")
    tools.append(
        ToolSubst("%cdb", '"%s"' % os.path.join(win_sdk, "Debuggers", arch, "cdb.exe"))
    )

# clang_src_dir and lld_src_dir are not used by these tests, but are required by
# use_clang() and use_lld() respectively, so set them to "", if needed.
if not hasattr(config, "clang_src_dir"):
    config.clang_src_dir = ""
llvm_config.use_clang(required=("clang" in config.llvm_enabled_projects))

if not hasattr(config, "lld_src_dir"):
    config.lld_src_dir = ""
llvm_config.use_lld(required=("lld" in config.llvm_enabled_projects))

if "compiler-rt" in config.llvm_enabled_projects:
    config.available_features.add("compiler-rt")

# Check which debuggers are available:
lldb_path = llvm_config.use_llvm_tool("lldb", search_env="LLDB")

if lldb_path is not None:
    config.available_features.add("lldb")

if llvm_config.use_llvm_tool("llvm-ar"):
    config.available_features.add("llvm-ar")

def configure_dexter_substitutions():
    """Configure substitutions for host platform and return list of dependencies"""
    # Produce dexter path, lldb path, and combine into the %dexter substitution
    # for running a test.
    dexter_path = os.path.join(
        config.cross_project_tests_src_root, "debuginfo-tests", "dexter", "dexter.py"
    )
    dexter_test_cmd = '"{}" "{}" test'.format(sys.executable, dexter_path)
    if lldb_path is not None:
        dexter_test_cmd += ' --lldb-executable "{}"'.format(lldb_path)
    tools.append(ToolSubst("%dexter", dexter_test_cmd))

    # For testing other bits of dexter that aren't under the "test" subcommand,
    # have a %dexter_base substitution.
    dexter_base_cmd = '"{}" "{}"'.format(sys.executable, dexter_path)
    tools.append(ToolSubst("%dexter_base", dexter_base_cmd))

    # Set up commands for DexTer regression tests.
    # Builder, debugger, optimisation level and several other flags differ
    # depending on whether we're running a unix like or windows os.
    if platform.system() == "Windows":
        # The Windows builder script uses lld.
        dependencies = ["clang", "lld-link"]
        dexter_regression_test_c_builder = "clang-cl"
        dexter_regression_test_cxx_builder = "clang-cl"
        dexter_regression_test_debugger = "dbgeng"
        dexter_regression_test_c_flags = "/Zi /Od"
        dexter_regression_test_cxx_flags = "/Zi /Od"
        dexter_regression_test_additional_flags = ""
    else:
        # Use lldb as the debugger on non-Windows platforms.
        dependencies = ["clang", "lldb"]
        dexter_regression_test_c_builder = "clang"
        dexter_regression_test_cxx_builder = "clang++"
        dexter_regression_test_debugger = "lldb"
        dexter_regression_test_c_flags = "-O0 -glldb -std=gnu11"
        dexter_regression_test_cxx_flags = "-O0 -glldb -std=gnu++11"
        dexter_regression_test_additional_flags = '--lldb-executable "{}"'.format(
            lldb_path
        )

    tools.append(
        ToolSubst("%dexter_regression_test_c_builder", dexter_regression_test_c_builder)
    )
    tools.append(
        ToolSubst(
            "%dexter_regression_test_cxx_builder", dexter_regression_test_cxx_builder
        )
    )
    tools.append(
        ToolSubst("%dexter_regression_test_debugger", dexter_regression_test_debugger)
    )
    # We don't need to distinguish cflags and ldflags because for Dexter
    # regression tests we use clang to drive the linker, and so all flags will be
    # passed in a single command.
    tools.append(
        ToolSubst("%dexter_regression_test_c_flags", dexter_regression_test_c_flags)
    )
    tools.append(
        ToolSubst("%dexter_regression_test_cxx_flags", dexter_regression_test_cxx_flags)
    )

    # Typical command would take the form:
    # ./path_to_py/python.exe ./path_to_dex/dexter.py test --fail-lt 1.0 -w --binary %t --debugger lldb --cflags '-O0 -g'
    dexter_regression_test_run = " ".join(
        # "python", "dexter.py", test, fail_mode, builder, debugger, cflags, ldflags
        [
            '"{}"'.format(sys.executable),
            '"{}"'.format(dexter_path),
            "test",
            "--fail-lt 1.0 -w",
            "--debugger",
            dexter_regression_test_debugger,
            dexter_regression_test_additional_flags,
        ]
    )
    tools.append(ToolSubst("%dexter_regression_test_run", dexter_regression_test_run))

    # Include build flags for %dexter_regression_test.
    dexter_regression_test_c_build = " ".join(
        [
            dexter_regression_test_c_builder,
            dexter_regression_test_c_flags,
        ]
    )
    dexter_regression_test_cxx_build = " ".join(
        [
            dexter_regression_test_cxx_builder,
            dexter_regression_test_cxx_flags,
        ]
    )
    tools.append(
        ToolSubst("%dexter_regression_test_c_build", dexter_regression_test_c_build)
    )
    tools.append(
        ToolSubst("%dexter_regression_test_cxx_build", dexter_regression_test_cxx_build)
    )
    return dependencies


def add_host_triple(clang):
    return "{} --target={}".format(clang, config.host_triple)


# The set of arches we can build.
targets = set(config.targets_to_build)
# Add aliases to the target set.
if "AArch64" in targets:
    targets.add("arm64")
if "ARM" in config.targets_to_build:
    targets.add("thumbv7")


def can_target_host():
    # Check if the targets set contains anything that looks like our host arch.
    # The arch name in the triple and targets set may be spelled differently
    # (e.g. x86 vs X86).
    return any(config.host_triple.lower().startswith(x.lower()) for x in targets)


# Dexter tests run on the host machine. If the host arch is supported add
# 'dexter' as an available feature and force the dexter tests to use the host
# triple.
if can_target_host():
    if config.host_triple != config.target_triple:
        print("Forcing dexter tests to use host triple {}.".format(config.host_triple))
    dependencies = configure_dexter_substitutions()
    if all(d in config.available_features for d in dependencies):
        config.available_features.add("dexter")
else:
    print(
        "Host triple {} not supported. Skipping dexter tests in the "
        "debuginfo-tests project.".format(config.host_triple)
    )

tool_dirs = [config.llvm_tools_dir]

llvm_config.add_tool_substitutions(tools, tool_dirs)

lit.util.usePlatformSdkOnDarwin(config, lit_config)

if platform.system() == "Darwin":
    xcode_lldb_vers = subprocess.check_output(["xcrun", "lldb", "--version"]).decode(
        "utf-8"
    )
    match = re.search(r"lldb-(\d+)", xcode_lldb_vers)
    if match:
        apple_lldb_vers = int(match.group(1))
        if apple_lldb_vers < 1000:
            config.available_features.add("apple-lldb-pre-1000")


def get_gdb_version_string():
    """Return gdb's version string, or None if gdb cannot be found or the
    --version output is formatted unexpectedly.
    """
    # See if we can get a gdb version, e.g.
    #   $ gdb --version
    #   GNU gdb (GDB) 10.2
    #   ...More stuff...
    try:
        gdb_vers_lines = (
            subprocess.check_output(["gdb", "--version"]).decode().splitlines()
        )
    except:
        return None  # We coudln't find gdb or something went wrong running it.
    if len(gdb_vers_lines) < 1:
        print("Unkown GDB version format (too few lines)", file=sys.stderr)
        return None
    match = re.search(r"GNU gdb \(.*?\) ((\d|\.)+)", gdb_vers_lines[0].strip())
    if match is None:
        print(f"Unkown GDB version format: {gdb_vers_lines[0]}", file=sys.stderr)
        return None
    return match.group(1)


def get_clang_default_dwarf_version_string(triple):
    """Return the default dwarf version string for clang on this (host) platform
    or None if we can't work it out.
    """
    # Get the flags passed by the driver and look for -dwarf-version.
    cmd = f'{llvm_config.use_llvm_tool("clang")} -g -xc  -c - -v -### --target={triple}'
    stderr = subprocess.run(cmd.split(), stderr=subprocess.PIPE).stderr.decode()
    match = re.search(r"-dwarf-version=(\d+)", stderr)
    if match is None:
        print("Cannot determine default dwarf version", file=sys.stderr)
        return None
    return match.group(1)


# Some cross-project-tests use gdb, but not all versions of gdb are compatible
# with clang's dwarf. Add feature `gdb-clang-incompatibility` to signal that
# there's an incompatibility between clang's default dwarf version for this
# platform and the installed gdb version.
dwarf_version_string = get_clang_default_dwarf_version_string(config.host_triple)
gdb_version_string = get_gdb_version_string()
if dwarf_version_string and gdb_version_string:
    if int(dwarf_version_string) >= 5:
        try:
            from packaging import version
        except:
            lit_config.fatal("Running gdb tests requires the packaging package")
        if version.parse(gdb_version_string) < version.parse("10.1"):
            # Example for llgdb-tests, which use lldb on darwin but gdb elsewhere:
            # XFAIL: !system-darwin && gdb-clang-incompatibility
            config.available_features.add("gdb-clang-incompatibility")
            print(
                "XFAIL some tests: use gdb version >= 10.1 to restore test coverage",
                file=sys.stderr,
            )

llvm_config.feature_config([("--build-mode", {"Debug|RelWithDebInfo": "debug-info"})])

# Allow 'REQUIRES: XXX-registered-target' in tests.
for arch in config.targets_to_build:
    config.available_features.add(arch.lower() + "-registered-target")
