# -*- Python -*-

import os
import platform
import re
import subprocess
import tempfile

import lit.formats
import lit.util

# Configuration file for the 'lit' test runner.

# name: The name of this test suite.
config.name = 'Clang'

# Tweak PATH for Win32
if platform.system() == 'Windows':
    # Seek sane tools in directories and set to $PATH.
    path = getattr(config, 'lit_tools_dir', None)
    path = lit_config.getToolsPath(path,
                                   config.environment['PATH'],
                                   ['cmp.exe', 'grep.exe', 'sed.exe'])
    if path is not None:
        path = os.path.pathsep.join((path,
                                     config.environment['PATH']))
        config.environment['PATH'] = path

# Choose between lit's internal shell pipeline runner and a real shell.  If
# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
if use_lit_shell:
    # 0 is external, "" is default, and everything else is internal.
    execute_external = (use_lit_shell == "0")
else:
    # Otherwise we default to internal on Windows and external elsewhere, as
    # bash on Windows is usually very slow.
    execute_external = (not sys.platform in ['win32'])

# testFormat: The test format to use to interpret tests.
#
# For now we require '&&' between commands, until they get globally killed and
# the test runner updated.
config.test_format = lit.formats.ShTest(execute_external)

# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s']

# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)

# test_exec_root: The root path where tests should be run.
clang_obj_root = getattr(config, 'clang_obj_root', None)
if clang_obj_root is not None:
    config.test_exec_root = os.path.join(clang_obj_root, 'test')

# Set llvm_{src,obj}_root for use by others.
config.llvm_src_root = getattr(config, 'llvm_src_root', None)
config.llvm_obj_root = getattr(config, 'llvm_obj_root', None)

# Clear some environment variables that might affect Clang.
#
# This first set of vars are read by Clang, but shouldn't affect tests
# that aren't specifically looking for these features, or are required
# simply to run the tests at all.
#
# FIXME: Should we have a tool that enforces this?

# safe_env_vars = ('TMPDIR', 'TEMP', 'TMP', 'USERPROFILE', 'PWD',
#                  'MACOSX_DEPLOYMENT_TARGET', 'IPHONEOS_DEPLOYMENT_TARGET',
#                  'IOS_SIMULATOR_DEPLOYMENT_TARGET',
#                  'VCINSTALLDIR', 'VC100COMNTOOLS', 'VC90COMNTOOLS',
#                  'VC80COMNTOOLS')
possibly_dangerous_env_vars = ['COMPILER_PATH', 'RC_DEBUG_OPTIONS',
                               'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH',
                               'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH',
                               'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH',
                               'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING',
                               'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
                               'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
                               'LIBCLANG_RESOURCE_USAGE',
                               'LIBCLANG_CODE_COMPLETION_LOGGING']
# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
if platform.system() != 'Windows':
    possibly_dangerous_env_vars.append('INCLUDE')
for name in possibly_dangerous_env_vars:
  if name in config.environment:
    del config.environment[name]

# Tweak the PATH to include the tools dir and the scripts dir.
if clang_obj_root is not None:
    llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
    if not llvm_tools_dir:
        lit_config.fatal('No LLVM tools dir set!')
    path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))
    config.environment['PATH'] = path
    llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
    if not llvm_libs_dir:
        lit_config.fatal('No LLVM libs dir set!')
    path = os.path.pathsep.join((llvm_libs_dir,
                                 config.environment.get('LD_LIBRARY_PATH','')))
    config.environment['LD_LIBRARY_PATH'] = path

# Propagate path to symbolizer for ASan/MSan.
for symbolizer in ['ASAN_SYMBOLIZER_PATH', 'MSAN_SYMBOLIZER_PATH']:
    if symbolizer in os.environ:
        config.environment[symbolizer] = os.environ[symbolizer]

###

# Check that the object root is known.
if config.test_exec_root is None:
    # Otherwise, we haven't loaded the site specific configuration (the user is
    # probably trying to run on a test file directly, and either the site
    # configuration hasn't been created by the build system, or we are in an
    # out-of-tree build situation).

    # Check for 'clang_site_config' user parameter, and use that if available.
    site_cfg = lit_config.params.get('clang_site_config', None)
    if site_cfg and os.path.exists(site_cfg):
        lit_config.load_config(config, site_cfg)
        raise SystemExit

    # Try to detect the situation where we are using an out-of-tree build by
    # looking for 'llvm-config'.
    #
    # FIXME: I debated (i.e., wrote and threw away) adding logic to
    # automagically generate the lit.site.cfg if we are in some kind of fresh
    # build situation. This means knowing how to invoke the build system though,
    # and I decided it was too much magic. We should solve this by just having
    # the .cfg files generated during the configuration step.

    llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
    if not llvm_config:
        lit_config.fatal('No site specific configuration available!')

    # Get the source and object roots.
    llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
    llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
    clang_src_root = os.path.join(llvm_src_root, "tools", "clang")
    clang_obj_root = os.path.join(llvm_obj_root, "tools", "clang")

    # Validate that we got a tree which points to here, using the standard
    # tools/clang layout.
    this_src_root = os.path.dirname(config.test_source_root)
    if os.path.realpath(clang_src_root) != os.path.realpath(this_src_root):
        lit_config.fatal('No site specific configuration available!')

    # Check that the site specific configuration exists.
    site_cfg = os.path.join(clang_obj_root, 'test', 'lit.site.cfg')
    if not os.path.exists(site_cfg):
        lit_config.fatal(
            'No site specific configuration available! You may need to '
            'run "make test" in your Clang build directory.')

    # Okay, that worked. Notify the user of the automagic, and reconfigure.
    lit_config.note('using out-of-tree build at %r' % clang_obj_root)
    lit_config.load_config(config, site_cfg)
    raise SystemExit

###

# Discover the 'clang' and 'clangcc' to use.

import os

def inferClang(PATH):
    # Determine which clang to use.
    clang = os.getenv('CLANG')

    # If the user set clang in the environment, definitely use that and don't
    # try to validate.
    if clang:
        return clang

    # Otherwise look in the path.
    clang = lit.util.which('clang', PATH)

    if not clang:
        lit_config.fatal("couldn't find 'clang' program, try setting "
                         "CLANG in your environment")

    return clang

config.clang = inferClang(config.environment['PATH']).replace('\\', '/')
if not lit_config.quiet:
    lit_config.note('using clang: %r' % config.clang)

# Note that when substituting %clang_cc1 also fill in the include directory of
# the builtin headers. Those are part of even a freestanding environment, but
# Clang relies on the driver to locate them.
def getClangBuiltinIncludeDir(clang):
    # FIXME: Rather than just getting the version, we should have clang print
    # out its resource dir here in an easy to scrape form.
    cmd = subprocess.Popen([clang, '-print-file-name=include'],
                           stdout=subprocess.PIPE)
    if not cmd.stdout:
      lit_config.fatal("Couldn't find the include dir for Clang ('%s')" % clang)
    dir = cmd.stdout.read().strip()
    if sys.platform in ['win32'] and execute_external:
        # Don't pass dosish path separator to msys bash.exe.
        dir = dir.replace('\\', '/')
    # Ensure the result is an ascii string, across Python2.5+ - Python3.
    return str(dir.decode('ascii'))

config.substitutions.append( ('%clang_cc1', '%s -cc1 -internal-isystem %s'
                              % (config.clang,
                                 getClangBuiltinIncludeDir(config.clang))) )
config.substitutions.append( ('%clang_cpp', ' ' + config.clang +
                              ' --driver-mode=cpp '))
config.substitutions.append( ('%clang_cl', ' ' + config.clang +
                              ' --driver-mode=cl '))
config.substitutions.append( ('%clangxx', ' ' + config.clang +
                              ' --driver-mode=g++ '))
config.substitutions.append( ('%clang', ' ' + config.clang + ' ') )
config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/utils/test_debuginfo.pl ') )

# FIXME: Find nicer way to prohibit this.
config.substitutions.append(
    (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") )
config.substitutions.append(
    (' clang\+\+ ', """*** Do not use 'clang++' in tests, use '%clangxx'. ***"""))
config.substitutions.append(
    (' clang-cc ',
     """*** Do not use 'clang-cc' in tests, use '%clang_cc1'. ***""") )
config.substitutions.append(
    (' clang -cc1 ',
     """*** Do not use 'clang -cc1' in tests, use '%clang_cc1'. ***""") )
config.substitutions.append(
    (' %clang-cc1 ',
     """*** invalid substitution, use '%clang_cc1'. ***""") )
config.substitutions.append(
    (' %clang-cpp ',
     """*** invalid substitution, use '%clang_cpp'. ***""") )
config.substitutions.append(
    (' %clang-cl ',
     """*** invalid substitution, use '%clang_cl'. ***""") )

###

# Set available features we allow tests to conditionalize on.
#
# As of 2011.08, crash-recovery tests still do not pass on FreeBSD.
if platform.system() not in ['FreeBSD']:
    config.available_features.add('crash-recovery')

# Shell execution
if execute_external:
    config.available_features.add('shell')

# Exclude MSYS due to transforming '/' to 'X:/mingwroot/'.
if not platform.system() in ['Windows'] or not execute_external:
    config.available_features.add('shell-preserves-root')

# ANSI escape sequences in non-dumb terminal
if platform.system() not in ['Windows']:
    config.available_features.add('ansi-escape-sequences')

# Native compilation: host arch == target arch
if config.host_arch in config.target_triple:
    config.available_features.add("native")

# Case-insensitive file system
def is_filesystem_case_insensitive():
    handle, path = tempfile.mkstemp(prefix='case-test', dir=config.test_exec_root)
    isInsensitive = os.path.exists(
        os.path.join(
            os.path.dirname(path),
            os.path.basename(path).upper()
            ))
    os.close(handle)
    os.remove(path)
    return isInsensitive

if is_filesystem_case_insensitive():
    config.available_features.add('case-insensitive-filesystem')

# Tests that require the /dev/fd filesystem.
if os.path.exists("/dev/fd/0") and sys.platform not in ['cygwin']:
    config.available_features.add('dev-fd-fs')

# [PR8833] LLP64-incompatible tests
if not re.match(r'^x86_64.*-(win32|mingw32)$', config.target_triple):
    config.available_features.add('LP64')

# [PR12920] "clang-driver" -- set if gcc driver is not used.
if not re.match(r'.*-(cygwin|mingw32)$', config.target_triple):
    config.available_features.add('clang-driver')

# Registered Targets
def get_llc_props(tool):
    set_of_targets = set()
    enable_assertions = False

    cmd = subprocess.Popen([tool, '-version'], stdout=subprocess.PIPE)

    # Parse the stdout to get the list of registered targets.
    parse_targets = False
    for line in cmd.stdout:
        line = line.decode('ascii')
        if parse_targets:
            m = re.match( r'(.*) - ', line)
            if m is not None:
                set_of_targets.add(m.group(1).strip() + '-registered-target')
            else:
                break
        elif "Registered Targets:" in line:
            parse_targets = True

        if re.search(r'with assertions', line):
            enable_assertions = True

    return {"set_of_targets":    set_of_targets,
            "enable_assertions": enable_assertions}

llc_props = get_llc_props(os.path.join(llvm_tools_dir, 'llc'))
if len(llc_props['set_of_targets']) > 0:
    config.available_features.update(llc_props['set_of_targets'])
else:
    lit_config.fatal('No Targets Registered with the LLVM Tools!')

if llc_props['enable_assertions']:
    config.available_features.add('asserts')

if lit.util.which('xmllint'):
    config.available_features.add('xmllint')

# Sanitizers.
if config.llvm_use_sanitizer == "Address":
    config.available_features.add("asan")
if (config.llvm_use_sanitizer == "Memory" or
        config.llvm_use_sanitizer == "MemoryWithOrigins"):
    config.available_features.add("msan")

# Check if we should run long running tests.
if lit_config.params.get("run_long_tests", None) == "true":
    config.available_features.add("long_tests")

# Check if we should use gmalloc.
use_gmalloc_str = lit_config.params.get('use_gmalloc', None)
if use_gmalloc_str is not None:
    if use_gmalloc_str.lower() in ('1', 'true'):
        use_gmalloc = True
    elif use_gmalloc_str.lower() in ('', '0', 'false'):
        use_gmalloc = False
    else:
        lit_config.fatal('user parameter use_gmalloc should be 0 or 1')
else:
    # Default to not using gmalloc
    use_gmalloc = False

# Allow use of an explicit path for gmalloc library.
# Will default to '/usr/lib/libgmalloc.dylib' if not set.
gmalloc_path_str = lit_config.params.get('gmalloc_path',
                                         '/usr/lib/libgmalloc.dylib')

if use_gmalloc:
     config.environment.update({'DYLD_INSERT_LIBRARIES' : gmalloc_path_str})
