# -*- Python -*-

import os
import platform
import re
import subprocess
import tempfile


# 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.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.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.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.params.get('clang_site_config', None)
    if site_cfg and os.path.exists(site_cfg):
        lit.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.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.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.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.note('using out-of-tree build at %r' % clang_obj_root)
    lit.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.fatal("couldn't find 'clang' program, try setting "
                  "CLANG in your environment")

    return clang

config.clang = inferClang(config.environment['PATH']).replace('\\', '/')
if not lit.quiet:
    lit.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.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('\\', '/')
    return dir

config.substitutions.append( ('%clang_cc1', '%s -cc1 -internal-isystem %s'
                              % (config.clang,
                                 getClangBuiltinIncludeDir(config.clang))) )

config.substitutions.append( ('%clangxx', ' ' + config.clang +
                              ' -ccc-cxx '))
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'. ***""") )

###

# 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 lit.getBashPath() == '':
    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')

# 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:
        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.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.params.get("run_long_tests", None) == "true":
    config.available_features.add("long_tests")

# Check if we should use gmalloc.
use_gmalloc_str = lit.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.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.params.get('gmalloc_path', '/usr/lib/libgmalloc.dylib')

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