# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:

# Configuration file for the 'lit' test runner.

import errno
import locale
import os
import platform
import re
import shlex
import signal
import subprocess
import sys
import tempfile
import time

import lit.Test
import lit.formats
import lit.util

class LibcxxTestFormat(lit.formats.FileBasedTest):
    """
    Custom test format handler for use with the test format use by libc++.

    Tests fall into two categories:
      FOO.pass.cpp - Executable test which should compile, run, and exit with
                     code 0.
      FOO.fail.cpp - Negative test case which is expected to fail compilation.
    """

    def __init__(self, cxx_under_test, use_verify_for_fail,
                 cpp_flags, ld_flags, exec_env,
                 use_ccache=False):
        self.cxx_under_test = cxx_under_test
        self.use_verify_for_fail = use_verify_for_fail
        self.cpp_flags = list(cpp_flags)
        self.ld_flags = list(ld_flags)
        self.exec_env = dict(exec_env)
        self.use_ccache = use_ccache

    def execute(self, test, lit_config):
        while True:
            try:
                return self._execute(test, lit_config)
            except OSError, oe:
                if oe.errno != errno.ETXTBSY:
                    raise
                time.sleep(0.1)

    def _execute(self, test, lit_config):
        # Extract test metadata from the test file.
        requires = []
        unsupported = []
        use_verify = False
        with open(test.getSourcePath()) as f:
            for ln in f:
                if 'XFAIL:' in ln:
                    items = ln[ln.index('XFAIL:') + 6:].split(',')
                    test.xfails.extend([s.strip() for s in items])
                elif 'REQUIRES:' in ln:
                    items = ln[ln.index('REQUIRES:') + 9:].split(',')
                    requires.extend([s.strip() for s in items])
                elif 'UNSUPPORTED:' in ln:
                    items = ln[ln.index('UNSUPPORTED:') + 12:].split(',')
                    unsupported.extend([s.strip() for s in items])
                elif 'USE_VERIFY' in ln and self.use_verify_for_fail:
                    use_verify = True
                elif not ln.strip().startswith("//") and ln.strip():
                    # Stop at the first non-empty line that is not a C++
                    # comment.
                    break

        # Check that we have the required features.
        #
        # FIXME: For now, this is cribbed from lit.TestRunner, to avoid
        # introducing a dependency there. What we more ideally would like to do
        # is lift the "requires" handling to be a core lit framework feature.
        missing_required_features = [f for f in requires
                                     if f not in test.config.available_features]
        if missing_required_features:
            return (lit.Test.UNSUPPORTED,
                    "Test requires the following features: %s" % (
                      ', '.join(missing_required_features),))

        unsupported_features = [f for f in unsupported
                             if f in test.config.available_features]
        if unsupported_features:
            return (lit.Test.UNSUPPORTED,
                    "Test is unsupported with the following features: %s" % (
                       ', '.join(unsupported_features),))

        # Evaluate the test.
        return self._evaluate_test(test, use_verify, lit_config)

    def _make_report(self, cmd, out, err, rc):
        report = "Command: %s\n" % cmd
        report += "Exit Code: %d\n" % rc
        if out:
            report += "Standard Output:\n--\n%s--\n" % out
        if err:
            report += "Standard Error:\n--\n%s--\n" % err
        report += '\n'
        return cmd, report, rc

    def _compile(self, output_path, source_path, use_verify=False):
        cmd = [self.cxx_under_test, '-c', '-o', output_path, source_path]
        cmd += self.cpp_flags
        if use_verify:
            cmd += ['-Xclang', '-verify']
        if self.use_ccache:
            cmd = ['ccache'] + cmd
        out, err, rc = lit.util.executeCommand(cmd)
        return cmd, out, err, rc

    def _link(self, exec_path, object_path):
        cmd = [self.cxx_under_test, '-o', exec_path, object_path]
        cmd += self.cpp_flags + self.ld_flags
        out, err, rc = lit.util.executeCommand(cmd)
        return cmd, out, err, rc

    def _compile_and_link(self, exec_path, source_path):
        object_file = tempfile.NamedTemporaryFile(suffix=".o", delete=False)
        object_path = object_file.name
        object_file.close()
        try:
            cmd, out, err, rc = self._compile(object_path, source_path)
            if rc != 0:
                return cmd, out, err, rc
            return self._link(exec_path, object_path)
        finally:
            try:
                os.remove(object_path)
            except:
                pass

    def _build(self, exec_path, source_path, compile_only=False,
               use_verify=False):
        if compile_only:
            cmd, out, err, rc = self._compile(exec_path, source_path, use_verify)
        else:
            assert not use_verify
            cmd, out, err, rc = self._compile_and_link(exec_path, source_path)
        return self._make_report(cmd, out, err, rc)

    def _clean(self, exec_path):
        os.remove(exec_path)

    def _run(self, exec_path, lit_config, in_dir=None):
        cmd = []
        if self.exec_env:
            cmd.append('env')
            cmd.extend('%s=%s' % (name, value)
                       for name,value in self.exec_env.items())
        cmd.append(exec_path)
        if lit_config.useValgrind:
            cmd = lit_config.valgrindArgs + cmd
        out, err, rc = lit.util.executeCommand(cmd, cwd=in_dir)
        return self._make_report(cmd, out, err, rc)

    def _evaluate_test(self, test, use_verify, lit_config):
        name = test.path_in_suite[-1]
        source_path = test.getSourcePath()
        source_dir = os.path.dirname(source_path)

        # Check what kind of test this is.
        assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
        expected_compile_fail = name.endswith('.fail.cpp')

        # If this is a compile (failure) test, build it and check for failure.
        if expected_compile_fail:
            cmd, report, rc = self._build('/dev/null', source_path,
                                          compile_only=True,
                                          use_verify=use_verify)
            expected_rc = 0 if use_verify else 1
            if rc == expected_rc:
                return lit.Test.PASS, ""
            else:
                return lit.Test.FAIL, report + 'Expected compilation to fail!\n'
        else:
            exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
            exec_path = exec_file.name
            exec_file.close()

            try:
                cmd, report, rc = self._build(exec_path, source_path)
                compile_cmd = cmd
                if rc != 0:
                    report += "Compilation failed unexpectedly!"
                    return lit.Test.FAIL, report

                cmd, report, rc = self._run(exec_path, lit_config,
                                            source_dir)
                if rc != 0:
                    report = "Compiled With: %s\n%s" % (compile_cmd, report)
                    report += "Compiled test failed unexpectedly!"
                    return lit.Test.FAIL, report
            finally:
                try:
                    # Note that cleanup of exec_file happens in `_clean()`. If
                    # you override this, cleanup is your reponsibility.
                    self._clean(exec_path)
                except:
                    pass
        return lit.Test.PASS, ""


class Configuration(object):
    def __init__(self, lit_config, config):
        self.lit_config = lit_config
        self.config = config
        self.cxx = None
        self.src_root = None
        self.obj_root = None
        self.library_root = None
        self.env = {}
        self.compile_flags = []
        self.link_flags = []
        self.use_system_lib = False
        self.use_clang_verify = False
        self.use_ccache = False

        if platform.system() not in ('Darwin', 'FreeBSD', 'Linux'):
            self.lit_config.fatal("unrecognized system")

    def get_lit_conf(self, name, default=None):
        val = self.lit_config.params.get(name, None)
        if val is None:
            val = getattr(self.config, name, None)
            if val is None:
                val = default
        return val

    def get_lit_bool(self, name, default=None):
        conf = self.get_lit_conf(name)
        if conf is None:
            return default
        if conf.lower() in ('1', 'true'):
            return True
        if conf.lower() in ('', '0', 'false'):
            return False
        self.lit_config.fatal(
            "parameter '{}' should be true or false".format(name))

    def configure(self):
        self.configure_cxx()
        self.probe_cxx()
        self.configure_triple()
        self.configure_src_root()
        self.configure_obj_root()
        self.configure_library_root()
        self.configure_use_system_lib()
        self.configure_use_clang_verify()
        self.configure_ccache()
        self.configure_env()
        self.configure_std_flag()
        self.configure_compile_flags()
        self.configure_link_flags()
        self.configure_sanitizer()
        self.configure_features()
        # Print the final compile and link flags.
        self.lit_config.note('Using compile flags: %s' % self.compile_flags)
        self.lit_config.note('Using link flags: %s' % self.link_flags)
        # Print as list to prevent "set([...])" from being printed.
        self.lit_config.note('Using available_features: %s' %
                             list(self.config.available_features))

    def get_test_format(self):
        return LibcxxTestFormat(
            self.cxx,
            self.use_clang_verify,
            cpp_flags=self.compile_flags,
            ld_flags=self.link_flags,
            exec_env=self.env,
            use_ccache=self.use_ccache)

    def configure_cxx(self):
        # Gather various compiler parameters.
        self.cxx = self.get_lit_conf('cxx_under_test')

        # If no specific cxx_under_test was given, attempt to infer it as
        # clang++.
        if self.cxx is None:
            clangxx = lit.util.which('clang++',
                                     self.config.environment['PATH'])
            if clangxx:
                self.cxx = clangxx
                self.lit_config.note(
                    "inferred cxx_under_test as: %r" % self.cxx)
        if not self.cxx:
            self.lit_config.fatal('must specify user parameter cxx_under_test '
                                  '(e.g., --param=cxx_under_test=clang++)')

    def probe_cxx(self):
        # Dump all of the predefined macros
        dump_macro_cmd = [self.cxx, '-dM', '-E', '-x', 'c++', '/dev/null']
        out, err, rc = lit.util.executeCommand(dump_macro_cmd)
        if rc != 0:
            self.lit_config.warning('Failed to dump macros for compiler: %s' %
                                    self.cxx)
            return
        # Create a dict containing all the predefined macros.
        macros = {}
        lines = [l.strip() for l in out.split('\n') if l.strip()]
        for l in lines:
            assert l.startswith('#define ')
            l = l[len('#define '):]
            macro, _, value = l.partition(' ')
            macros[macro] = value
        # Add compiler information to available features.
        compiler_name = None
        major_ver = minor_ver = None
        if '__clang__' in macros.keys():
            compiler_name = 'clang'
            # Treat apple's llvm fork differently.
            if '__apple_build_version__' in macros.keys():
                compiler_name = 'apple-clang'
            major_ver = macros['__clang_major__']
            minor_ver = macros['__clang_minor__']
        elif '__GNUC__' in macros.keys():
            compiler_name = 'gcc'
            major_ver = macros['__GNUC__']
            minor_ver = macros['__GNUC_MINOR__']
        else:
            self.lit_config.warning('Failed to detect compiler for cxx: %s' %
                                    self.cxx)
        if compiler_name is not None:
            self.config.available_features.add(compiler_name)
            self.config.available_features.add('%s-%s.%s' % (
                compiler_name, major_ver, minor_ver))

    def configure_src_root(self):
        self.src_root = self.get_lit_conf(
            'libcxx_src_root', os.path.dirname(self.config.test_source_root))

    def configure_obj_root(self):
        self.obj_root = self.get_lit_conf('libcxx_obj_root', self.src_root)

    def configure_library_root(self):
        self.library_root = self.get_lit_conf('libcxx_library_root', self.obj_root)

    def configure_use_system_lib(self):
        # This test suite supports testing against either the system library or
        # the locally built one; the former mode is useful for testing ABI
        # compatibility between the current headers and a shipping dynamic
        # library.
        self.use_system_lib = self.get_lit_bool('use_system_lib')
        if self.use_system_lib is None:
            # Default to testing against the locally built libc++ library.
            self.use_system_lib = False
            self.lit_config.note(
                "inferred use_system_lib as: %r" % self.use_system_lib)

    def configure_use_clang_verify(self):
        '''If set, run clang with -verify on failing tests.'''
        self.use_clang_verify = self.get_lit_bool('use_clang_verify')
        if self.use_clang_verify is None:
            # TODO: Default this to True when using clang.
            self.use_clang_verify = False
            self.lit_config.note(
                "inferred use_clang_verify as: %r" % self.use_clang_verify)

    def configure_ccache(self):
        self.use_ccache = self.get_lit_bool('use_ccache', False)
        if self.use_ccache:
            self.lit_config.note('enabling ccache')

    def configure_features(self):
        additional_features = self.get_lit_conf('additional_features')
        if additional_features:
            for f in additional_features.split(','):
                self.config.available_features.add(f.strip())

        # Figure out which of the required locales we support
        locales = {
            'Darwin': {
                'en_US.UTF-8': 'en_US.UTF-8',
                'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
                'fr_FR.UTF-8': 'fr_FR.UTF-8',
                'fr_CA.ISO8859-1': 'cs_CZ.ISO8859-1',
                'ru_RU.UTF-8': 'ru_RU.UTF-8',
                'zh_CN.UTF-8': 'zh_CN.UTF-8',
            },
            'FreeBSD': {
                'en_US.UTF-8': 'en_US.UTF-8',
                'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
                'fr_FR.UTF-8': 'fr_FR.UTF-8',
                'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1',
                'ru_RU.UTF-8': 'ru_RU.UTF-8',
                'zh_CN.UTF-8': 'zh_CN.UTF-8',
            },
            'Linux': {
                'en_US.UTF-8': 'en_US.UTF-8',
                'cs_CZ.ISO8859-2': 'cs_CZ.ISO-8859-2',
                'fr_FR.UTF-8': 'fr_FR.UTF-8',
                'fr_CA.ISO8859-1': 'fr_CA.ISO-8859-1',
                'ru_RU.UTF-8': 'ru_RU.UTF-8',
                'zh_CN.UTF-8': 'zh_CN.UTF-8',
            },
            'Windows': {
                'en_US.UTF-8': 'English_United States.1252',
                'cs_CZ.ISO8859-2': 'Czech_Czech Republic.1250',
                'fr_FR.UTF-8': 'French_France.1252',
                'fr_CA.ISO8859-1': 'French_Canada.1252',
                'ru_RU.UTF-8': 'Russian_Russia.1251',
                'zh_CN.UTF-8': 'Chinese_China.936',
            },
        }

        default_locale = locale.setlocale(locale.LC_ALL)
        for feature, loc in locales[platform.system()].items():
            try:
                locale.setlocale(locale.LC_ALL, loc)
                self.config.available_features.add('locale.{0}'.format(feature))
            except:
                self.lit_config.warning('The locale {0} is not supported by '
                                        'your platform. Some tests will be '
                                        'unsupported.'.format(loc))
        locale.setlocale(locale.LC_ALL, default_locale)

        # Write an "available feature" that combines the triple when
        # use_system_lib is enabled. This is so that we can easily write XFAIL
        # markers for tests that are known to fail with versions of libc++ as
        # were shipped with a particular triple.
        if self.use_system_lib:
            self.config.available_features.add(
                'with_system_lib=%s' % self.config.target_triple)

        # Some linux distributions have different locale data than others.
        # Insert the distributions name and name-version into the available
        # features to allow tests to XFAIL on them.
        if sys.platform.startswith('linux'):
            name, ver, _ = platform.linux_distribution()
            name = name.lower().strip()
            ver = ver.lower().strip()
            if name:
                self.config.available_features.add(name)
            if name and ver:
                self.config.available_features.add('%s-%s' % (name, ver))

        # Simulator testing can take a really long time for some of these tests
        # so add a feature check so we can REQUIRES: long_tests in them
        self.long_tests = self.get_lit_bool('long_tests')
        if self.long_tests is None:
            # Default to running long tests.
            self.long_tests = True
            self.lit_config.note(
                "inferred long_tests as: %r" % self.long_tests)

        if self.long_tests:
            self.config.available_features.add('long_tests')

    def configure_compile_flags(self):
        # Configure extra compiler flags.
        self.compile_flags += ['-nostdinc++']
        self.compile_flags += ['-I' + self.src_root + '/include',
                               '-I' + self.src_root + '/test/support']
        if sys.platform.startswith('linux'):
            self.compile_flags += ['-D__STDC_FORMAT_MACROS',
                                   '-D__STDC_LIMIT_MACROS',
                                   '-D__STDC_CONSTANT_MACROS']
        enable_exceptions = self.get_lit_bool('enable_exceptions', True)
        if enable_exceptions:
            self.config.available_features.add('exceptions')
        else:
            self.compile_flags += ['-fno-exceptions']
        enable_rtti = self.get_lit_bool('enable_rtti', True)
        if enable_rtti:
            self.config.available_features.add('rtti')
        else:
            self.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
        enable_32bit = self.get_lit_bool('enable_32bit', False)
        if enable_32bit:
            self.compile_flags += ['-m32']
        # Configure threading features.
        enable_threads = self.get_lit_bool('enable_threads', True)
        enable_monotonic_clock = self.get_lit_bool('enable_monotonic_clock', True)
        if not enable_threads:
            self.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
            self.config.available_features.add('libcpp-has-no-threads')
            if not enable_monotonic_clock:
                self.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
                self.config.available_features.add('libcpp-has-no-monotonic-clock')
        elif not enable_monotonic_clock:
            self.lit_config.fatal('enable_monotonic_clock cannot be false when'
                                  ' enable_threads is true.')


    def configure_link_flags(self):
        self.link_flags += ['-nodefaultlibs']
        # Configure library search paths
        abi_library_path = self.get_lit_conf('abi_library_path', '')
        if not self.use_system_lib:
            self.link_flags += ['-L' + self.library_root]
            self.link_flags += ['-Wl,-rpath,' + self.library_root]
        if abi_library_path:
            self.link_flags += ['-L' + abi_library_path,
                                '-Wl,-rpath,' + abi_library_path]
        # Configure libraries
        self.link_flags += ['-lc++']
        link_flags_str = self.get_lit_conf('link_flags')
        if link_flags_str is None:
            cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
            if cxx_abi == 'libstdc++':
                self.link_flags += ['-lstdc++']
            elif cxx_abi == 'libsupc++':
                self.link_flags += ['-lsupc++']
            elif cxx_abi == 'libcxxabi':
                self.link_flags += ['-lc++abi']
            elif cxx_abi == 'libcxxrt':
                self.link_flags += ['-lcxxrt']
            elif cxx_abi == 'none':
                pass
            else:
                self.lit_config.fatal(
                    'C++ ABI setting %s unsupported for tests' % cxx_abi)

            if sys.platform == 'darwin':
                self.link_flags += ['-lSystem']
            elif sys.platform.startswith('linux'):
                self.link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread',
                                    '-lrt', '-lgcc_s']
            elif sys.platform.startswith('freebsd'):
                self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
            else:
                self.lit_config.fatal("unrecognized system: %r" % sys.platform)

        if link_flags_str:
            self.link_flags += shlex.split(link_flags_str)


    def configure_std_flag(self):
        # Try and get the std version from the command line. Fall back to
        # default given in lit.site.cfg is not present. If default is not
        # present then force c++11.
        std = self.get_lit_conf('std')
        if std is None:
            std = 'c++11'
            self.lit_config.note('using default std: \'-std=c++11\'')
        self.compile_flags += ['-std={0}'.format(std)]
        self.config.available_features.add(std)

    def configure_sanitizer(self):
        san = self.get_lit_conf('llvm_use_sanitizer', '').strip()
        if san:
            # Search for llvm-symbolizer along the compiler path first
            # and then along the PATH env variable.
            symbolizer_search_paths = os.environ.get('PATH', '')
            cxx_path = lit.util.which(self.cxx)
            if cxx_path is not None:
                symbolizer_search_paths = os.path.dirname(cxx_path) + \
                                          os.pathsep + symbolizer_search_paths
            llvm_symbolizer = lit.util.which('llvm-symbolizer',
                                             symbolizer_search_paths)
            # Setup the sanitizer compile flags
            self.compile_flags += ['-g', '-fno-omit-frame-pointer']
            if sys.platform.startswith('linux'):
                self.link_flags += ['-ldl']
            if san == 'Address':
                self.compile_flags += ['-fsanitize=address']
                if llvm_symbolizer is not None:
                    self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
                self.config.available_features.add('asan')
            elif san == 'Memory' or san == 'MemoryWithOrigins':
                self.compile_flags += ['-fsanitize=memory']
                if san == 'MemoryWithOrigins':
                    self.compile_flags += ['-fsanitize-memory-track-origins']
                if llvm_symbolizer is not None:
                    self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
                self.config.available_features.add('msan')
            elif san == 'Undefined':
                self.compile_flags += ['-fsanitize=undefined',
                                       '-fno-sanitize=vptr,function',
                                       '-fno-sanitize-recover', '-O3']
                self.config.available_features.add('ubsan')
            elif san == 'Thread':
                self.compile_flags += ['-fsanitize=thread']
                self.config.available_features.add('tsan')
            else:
                self.lit_config.fatal('unsupported value for '
                                      'libcxx_use_san: {0}'.format(san))

    def configure_triple(self):
        # Get or infer the target triple.
        self.config.target_triple = self.get_lit_conf('target_triple')
        # If no target triple was given, try to infer it from the compiler
        # under test.
        if not self.config.target_triple:
            target_triple = lit.util.capture(
                [self.cxx, '-dumpmachine']).strip()
            # Drop sub-major version components from the triple, because the
            # current XFAIL handling expects exact matches for feature checks.
            # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14
            # The 5th group handles triples greater than 3 parts
            # (ex x86_64-pc-linux-gnu).
            target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)',
                                   r'\1-\2-\3\5', target_triple)
            # linux-gnu is needed in the triple to properly identify linuxes
            # that use GLIBC. Handle redhat and opensuse triples as special
            # cases and append the missing `-gnu` portion.
            if target_triple.endswith('redhat-linux') or \
               target_triple.endswith('suse-linux'):
                target_triple += '-gnu'
            self.config.target_triple = target_triple
            self.lit_config.note(
                "inferred target_triple as: %r" % self.config.target_triple)

    def configure_env(self):
        if sys.platform == 'darwin' and not self.use_system_lib:
            self.env['DYLD_LIBRARY_PATH'] = self.library_root

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

# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.cpp']

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

# Infer the test_exec_root from the libcxx_object root.
libcxx_obj_root = getattr(config, 'libcxx_obj_root', None)
if libcxx_obj_root is not None:
    config.test_exec_root = os.path.join(libcxx_obj_root, 'test')

# Check that the test exec 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).
    site_cfg = lit_config.params.get('libcxx_site_config',
                                     os.environ.get('LIBCXX_SITE_CONFIG'))
    if not site_cfg:
        lit_config.warning('No site specific configuration file found!'
                           ' Running the tests in the default configuration.')
        # TODO: Set test_exec_root to a temporary directory where output files
        # can be placed. This is needed for ShTest.
    elif not os.path.isfile(site_cfg):
        lit_config.fatal(
            "Specified site configuration file does not exist: '%s'"  %
            site_cfg)
    else:
        lit_config.note('using site specific configuration at %s' % site_cfg)
        lit_config.load_config(config, site_cfg)
        raise SystemExit()


cfg_variant = getattr(config, 'configuration_variant', '')
if cfg_variant:
    print 'Using configuration variant: %s' % cfg_variant

# Construct an object of the type named `<VARIANT>Configuration`.
configuration = globals()['%sConfiguration' % cfg_variant](lit_config, config)
configuration.configure()
config.test_format = configuration.get_test_format()
