import os
import platform
import re
import subprocess
import sys

# TODO: LooseVersion is undocumented; use something else.
from distutils.version import LooseVersion

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', '.cpp', '.m']

# 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()

tools = [
    ToolSubst('%test_debuginfo', command=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 == 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')

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_builder = 'clang-cl_vs2015'
    dexter_regression_test_debugger = 'dbgeng'
    dexter_regression_test_cflags = '/Zi /Od'
    dexter_regression_test_ldflags = '/Zi'
  else:
    # Use lldb as the debugger on non-Windows platforms.
    dependencies = ['clang', 'lldb']
    dexter_regression_test_builder = 'clang'
    dexter_regression_test_debugger = 'lldb'
    dexter_regression_test_cflags = '-O0 -glldb'
    dexter_regression_test_ldflags = ''

  tools.append(ToolSubst('%dexter_regression_test_builder', dexter_regression_test_builder))
  tools.append(ToolSubst('%dexter_regression_test_debugger', dexter_regression_test_debugger))
  tools.append(ToolSubst('%dexter_regression_test_cflags', dexter_regression_test_cflags))
  tools.append(ToolSubst('%dexter_regression_test_ldflags', dexter_regression_test_cflags))

  # Typical command would take the form:
  # ./path_to_py/python.exe ./path_to_dex/dexter.py test --fail-lt 1.0 -w --builder clang --debugger lldb --cflags '-O0 -g'
  # Exclude build flags for %dexter_regression_base.
  dexter_regression_test_base = ' '.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])
  tools.append(ToolSubst('%dexter_regression_base', dexter_regression_test_base))

  # Include build flags for %dexter_regression_test.
  dexter_regression_test_build = ' '.join([
    dexter_regression_test_base,
    '--builder', dexter_regression_test_builder,
    '--cflags "',  dexter_regression_test_cflags + '"',
    '--ldflags "', dexter_regression_test_ldflags + '"'])
  tools.append(ToolSubst('%dexter_regression_test', dexter_regression_test_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')
    llvm_config.with_environment('PATHTOCLANG',
                                 add_host_triple(llvm_config.config.clang))
    llvm_config.with_environment('PATHTOCLANGPP',
                                 add_host_triple(llvm_config.use_llvm_tool('clang++')))
    llvm_config.with_environment('PATHTOCLANGCL',
                                 add_host_triple(llvm_config.use_llvm_tool('clang-cl')))
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('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('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('-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:
    if LooseVersion(gdb_version_string) < LooseVersion('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')
