"""
A simple testing framework for lldb using python's unit testing framework.

Tests for lldb are written as python scripts which take advantage of the script
bridging provided by LLDB.framework to interact with lldb core.

A specific naming pattern is followed by the .py script to be recognized as
a module which implements a test scenario, namely, Test*.py.

To specify the directories where "Test*.py" python test scripts are located,
you need to pass in a list of directory names.  By default, the current
working directory is searched if nothing is specified on the command line.

Type:

./dotest.py -h

for available options.
"""

from __future__ import absolute_import
from __future__ import print_function

# System modules
import atexit
import datetime
import errno
import logging
import os
import platform
import re
import shutil
import signal
import subprocess
import sys
import tempfile

# Third-party modules
import six
import unittest2

# LLDB Modules
import lldbsuite
from . import configuration
from . import dotest_args
from . import lldbtest_config
from . import test_categories
from . import test_result
from ..support import seven


def is_exe(fpath):
    """Returns true if fpath is an executable."""
    if fpath == None:
        return False
    if sys.platform == 'win32':
        if not fpath.endswith(".exe"):
            fpath += ".exe"
    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)


def which(program):
    """Returns the full path to a program; None otherwise."""
    fpath, _ = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file
    return None


def usage(parser):
    parser.print_help()
    if configuration.verbose > 0:
        print("""
Examples:

This is an example of using the -f option to pinpoint to a specific test class
and test method to be run:

$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
----------------------------------------------------------------------
Collected 1 test

test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
Test 'frame variable this' when stopped on a class constructor. ... ok

----------------------------------------------------------------------
Ran 1 test in 1.396s

OK

And this is an example of using the -p option to run a single file (the filename
matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):

$ ./dotest.py -v -p ObjC
----------------------------------------------------------------------
Collected 4 tests

test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
Lookup objective-c data types and evaluate expressions. ... ok
test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
Lookup objective-c data types and evaluate expressions. ... ok

----------------------------------------------------------------------
Ran 4 tests in 16.661s

OK

Running of this script also sets up the LLDB_TEST environment variable so that
individual test cases can locate their supporting files correctly.  The script
tries to set up Python's search paths for modules by looking at the build tree
relative to this script.  See also the '-i' option in the following example.

Finally, this is an example of using the lldb.py module distributed/installed by
Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
option to add some delay between two tests.  It uses ARCH=x86_64 to specify that
as the architecture and CC=clang to specify the compiler used for the test run:

$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward

Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
----------------------------------------------------------------------
Collected 2 tests

test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok

----------------------------------------------------------------------
Ran 2 tests in 5.659s

OK

The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
notify the directory containing the session logs for test failures or errors.
In case there is any test failure/error, a similar message is appended at the
end of the stderr output for your convenience.

ENABLING LOGS FROM TESTS

Option 1:

Writing logs into different files per test case::

$ ./dotest.py --channel "lldb all"

$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets"

These log files are written to:

<session-dir>/<test-id>-host.log (logs from lldb host process)
<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server)
<session-dir>/<test-id>-<test-result>.log (console logs)

By default, logs from successful runs are deleted.  Use the --log-success flag
to create reference logs for debugging.

$ ./dotest.py --log-success

""")
    sys.exit(0)


def parseExclusion(exclusion_file):
    """Parse an exclusion file, of the following format, where
       'skip files', 'skip methods', 'xfail files', and 'xfail methods'
       are the possible list heading values:

       skip files
       <file name>
       <file name>

       xfail methods
       <method name>
    """
    excl_type = None

    with open(exclusion_file) as f:
        for line in f:
            line = line.strip()
            if not excl_type:
                excl_type = line
                continue

            if not line:
                excl_type = None
            elif excl_type == 'skip':
                if not configuration.skip_tests:
                    configuration.skip_tests = []
                configuration.skip_tests.append(line)
            elif excl_type == 'xfail':
                if not configuration.xfail_tests:
                    configuration.xfail_tests = []
                configuration.xfail_tests.append(line)


def parseOptionsAndInitTestdirs():
    """Initialize the list of directories containing our unittest scripts.

    '-h/--help as the first option prints out usage info and exit the program.
    """

    do_help = False

    platform_system = platform.system()
    platform_machine = platform.machine()

    try:
        parser = dotest_args.create_parser()
        args = parser.parse_args()
    except:
        raise

    if args.unset_env_varnames:
        for env_var in args.unset_env_varnames:
            if env_var in os.environ:
                # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
                # is automatically translated into a corresponding call to
                # unsetenv().
                del os.environ[env_var]
                # os.unsetenv(env_var)

    if args.set_env_vars:
        for env_var in args.set_env_vars:
            parts = env_var.split('=', 1)
            if len(parts) == 1:
                os.environ[parts[0]] = ""
            else:
                os.environ[parts[0]] = parts[1]

    if args.set_inferior_env_vars:
        lldbtest_config.inferior_env = ' '.join(args.set_inferior_env_vars)

    if args.h:
        do_help = True

    if args.compiler:
        configuration.compiler = os.path.abspath(args.compiler)
        if not is_exe(configuration.compiler):
            configuration.compiler = which(args.compiler)
        if not is_exe(configuration.compiler):
            logging.error(
                    '%s is not a valid compiler executable; aborting...',
                    args.compiler)
            sys.exit(-1)
    else:
        # Use a compiler appropriate appropriate for the Apple SDK if one was
        # specified
        if platform_system == 'Darwin' and args.apple_sdk:
            configuration.compiler = seven.get_command_output(
                'xcrun -sdk "%s" -find clang 2> /dev/null' %
                (args.apple_sdk))
        else:
            # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first
            candidateCompilers = ['clang-3.5', 'clang', 'gcc']
            for candidate in candidateCompilers:
                if which(candidate):
                    configuration.compiler = candidate
                    break

    if args.dsymutil:
        configuration.dsymutil = args.dsymutil
    elif platform_system == 'Darwin':
        configuration.dsymutil = seven.get_command_output(
            'xcrun -find -toolchain default dsymutil')
    if args.llvm_tools_dir:
        configuration.filecheck = shutil.which("FileCheck", path=args.llvm_tools_dir)
        configuration.yaml2obj = shutil.which("yaml2obj", path=args.llvm_tools_dir)

    if not configuration.get_filecheck_path():
        logging.warning('No valid FileCheck executable; some tests may fail...')
        logging.warning('(Double-check the --llvm-tools-dir argument to dotest.py)')

    if args.channels:
        lldbtest_config.channels = args.channels

    if args.log_success:
        lldbtest_config.log_success = args.log_success

    if args.out_of_tree_debugserver:
        lldbtest_config.out_of_tree_debugserver = args.out_of_tree_debugserver

    # Set SDKROOT if we are using an Apple SDK
    if platform_system == 'Darwin' and args.apple_sdk:
        configuration.sdkroot = seven.get_command_output(
            'xcrun --sdk "%s" --show-sdk-path 2> /dev/null' %
            (args.apple_sdk))
        if not configuration.sdkroot:
            logging.error(
                    'No SDK found with the name %s; aborting...',
                    args.apple_sdk)
            sys.exit(-1)

    if args.arch:
        configuration.arch = args.arch
    else:
        configuration.arch = platform_machine

    if args.categories_list:
        configuration.categories_list = set(
            test_categories.validate(
                args.categories_list, False))
        configuration.use_categories = True
    else:
        configuration.categories_list = []

    if args.skip_categories:
        configuration.skip_categories += test_categories.validate(
            args.skip_categories, False)

    if args.xfail_categories:
        configuration.xfail_categories += test_categories.validate(
            args.xfail_categories, False)

    if args.E:
        os.environ['CFLAGS_EXTRAS'] = args.E

    if args.dwarf_version:
        configuration.dwarf_version = args.dwarf_version
        # We cannot modify CFLAGS_EXTRAS because they're used in test cases
        # that explicitly require no debug info.
        os.environ['CFLAGS'] = '-gdwarf-{}'.format(configuration.dwarf_version)

    if args.settings:
        for setting in args.settings:
            if not len(setting) == 1 or not setting[0].count('='):
                logging.error('"%s" is not a setting in the form "key=value"',
                              setting[0])
                sys.exit(-1)
            setting_list = setting[0].split('=', 1)
            configuration.settings.append((setting_list[0], setting_list[1]))

    if args.d:
        sys.stdout.write(
            "Suspending the process %d to wait for debugger to attach...\n" %
            os.getpid())
        sys.stdout.flush()
        os.kill(os.getpid(), signal.SIGSTOP)

    if args.f:
        if any([x.startswith('-') for x in args.f]):
            usage(parser)
        configuration.filters.extend(args.f)

    if args.framework:
        configuration.lldb_framework_path = args.framework

    if args.executable:
        # lldb executable is passed explicitly
        lldbtest_config.lldbExec = os.path.realpath(args.executable)
        if not is_exe(lldbtest_config.lldbExec):
            lldbtest_config.lldbExec = which(args.executable)
        if not is_exe(lldbtest_config.lldbExec):
            logging.error(
                    '%s is not a valid executable to test; aborting...',
                    args.executable)
            sys.exit(-1)

    if args.server and args.out_of_tree_debugserver:
        logging.warning('Both --server and --out-of-tree-debugserver are set')

    if args.server and not args.out_of_tree_debugserver:
        os.environ['LLDB_DEBUGSERVER_PATH'] = args.server

    if args.excluded:
        for excl_file in args.excluded:
            parseExclusion(excl_file)

    if args.p:
        if args.p.startswith('-'):
            usage(parser)
        configuration.regexp = args.p

    if args.t:
        os.environ['LLDB_COMMAND_TRACE'] = 'YES'

    if args.v:
        configuration.verbose = 2

    # argparse makes sure we have a number
    if args.sharp:
        configuration.count = args.sharp

    if sys.platform.startswith('win32'):
        os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(
            args.disable_crash_dialog)
        os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True)

    if do_help:
        usage(parser)

    # Reproducer arguments
    if args.capture_path and args.replay_path:
        logging.error('Cannot specify both a capture and a replay path.')
        sys.exit(-1)

    if args.capture_path:
        configuration.capture_path = args.capture_path

    if args.replay_path:
        configuration.replay_path = args.replay_path
    if args.lldb_platform_name:
        configuration.lldb_platform_name = args.lldb_platform_name
    if args.lldb_platform_url:
        configuration.lldb_platform_url = args.lldb_platform_url
    if args.lldb_platform_working_dir:
        configuration.lldb_platform_working_dir = args.lldb_platform_working_dir
    if platform_system == 'Darwin'  and args.apple_sdk:
        configuration.apple_sdk = args.apple_sdk
    if args.test_build_dir:
        configuration.test_build_dir = args.test_build_dir
    if args.lldb_module_cache_dir:
        configuration.lldb_module_cache_dir = args.lldb_module_cache_dir
    else:
        configuration.lldb_module_cache_dir = os.path.join(
            configuration.test_build_dir, 'module-cache-lldb')
    if args.clang_module_cache_dir:
        configuration.clang_module_cache_dir = args.clang_module_cache_dir
    else:
        configuration.clang_module_cache_dir = os.path.join(
            configuration.test_build_dir, 'module-cache-clang')

    if args.lldb_libs_dir:
        configuration.lldb_libs_dir = args.lldb_libs_dir

    if args.enabled_plugins:
        configuration.enabled_plugins = args.enabled_plugins

    # Gather all the dirs passed on the command line.
    if len(args.args) > 0:
        configuration.testdirs = [os.path.realpath(os.path.abspath(x)) for x in args.args]

    lldbtest_config.codesign_identity = args.codesign_identity

def registerFaulthandler():
    try:
        import faulthandler
    except ImportError:
        # faulthandler is not available until python3
        return

    faulthandler.enable()
    # faulthandler.register is not available on Windows.
    if getattr(faulthandler, 'register', None):
        faulthandler.register(signal.SIGTERM, chain=True)

def setupSysPath():
    """
    Add LLDB.framework/Resources/Python to the search paths for modules.
    As a side effect, we also discover the 'lldb' executable and export it here.
    """

    # Get the directory containing the current script.
    if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
        scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
    else:
        scriptPath = os.path.dirname(os.path.abspath(__file__))
    if not scriptPath.endswith('test'):
        print("This script expects to reside in lldb's test directory.")
        sys.exit(-1)

    os.environ["LLDB_TEST"] = scriptPath

    # Set up the root build directory.
    if not configuration.test_build_dir:
        raise Exception("test_build_dir is not set")
    configuration.test_build_dir = os.path.abspath(configuration.test_build_dir)

    # Set up the LLDB_SRC environment variable, so that the tests can locate
    # the LLDB source code.
    os.environ["LLDB_SRC"] = lldbsuite.lldb_root

    pluginPath = os.path.join(scriptPath, 'plugins')
    toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode')
    toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')

    # Insert script dir, plugin dir and lldb-server dir to the sys.path.
    sys.path.insert(0, pluginPath)
    # Adding test/tools/lldb-vscode to the path makes it easy to
    # "import lldb_vscode_testcase" from the VSCode tests
    sys.path.insert(0, toolsLLDBVSCode)
    # Adding test/tools/lldb-server to the path makes it easy
    sys.path.insert(0, toolsLLDBServerPath)
    # to "import lldbgdbserverutils" from the lldb-server tests

    # This is the root of the lldb git/svn checkout
    # When this changes over to a package instead of a standalone script, this
    # will be `lldbsuite.lldb_root`
    lldbRootDirectory = lldbsuite.lldb_root

    # Some of the tests can invoke the 'lldb' command directly.
    # We'll try to locate the appropriate executable right here.

    # The lldb executable can be set from the command line
    # if it's not set, we try to find it now
    # first, we try the environment
    if not lldbtest_config.lldbExec:
        # First, you can define an environment variable LLDB_EXEC specifying the
        # full pathname of the lldb executable.
        if "LLDB_EXEC" in os.environ:
            lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]

    if not lldbtest_config.lldbExec:
        # Last, check the path
        lldbtest_config.lldbExec = which('lldb')

    if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
        print(
            "'{}' is not a path to a valid executable".format(
                lldbtest_config.lldbExec))
        lldbtest_config.lldbExec = None

    if not lldbtest_config.lldbExec:
        print("The 'lldb' executable cannot be located.  Some of the tests may not be run as a result.")
        sys.exit(-1)

    os.system('%s -v' % lldbtest_config.lldbExec)

    lldbDir = os.path.dirname(lldbtest_config.lldbExec)

    lldbVSCodeExec = os.path.join(lldbDir, "lldb-vscode")
    if is_exe(lldbVSCodeExec):
        os.environ["LLDBVSCODE_EXEC"] = lldbVSCodeExec
    else:
        if not configuration.shouldSkipBecauseOfCategories(["lldb-vscode"]):
            print(
                "The 'lldb-vscode' executable cannot be located.  The lldb-vscode tests can not be run as a result.")
            configuration.skip_categories.append("lldb-vscode")

    lldbPythonDir = None  # The directory that contains 'lldb/__init__.py'

    # If our lldb supports the -P option, use it to find the python path:
    lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], universal_newlines=True)
    if lldb_dash_p_result:
        for line in lldb_dash_p_result.splitlines():
            if os.path.isdir(line) and os.path.exists(os.path.join(line, 'lldb', '__init__.py')):
                lldbPythonDir = line
                break

    if not lldbPythonDir:
        print(
            "Unable to load lldb extension module.  Possible reasons for this include:")
        print("  1) LLDB was built with LLDB_ENABLE_PYTHON=0")
        print(
            "  2) PYTHONPATH and PYTHONHOME are not set correctly.  PYTHONHOME should refer to")
        print(
            "     the version of Python that LLDB built and linked against, and PYTHONPATH")
        print(
            "     should contain the Lib directory for the same python distro, as well as the")
        print("     location of LLDB\'s site-packages folder.")
        print(
            "  3) A different version of Python than that which was built against is exported in")
        print("     the system\'s PATH environment variable, causing conflicts.")
        print(
            "  4) The executable '%s' could not be found.  Please check " %
            lldbtest_config.lldbExec)
        print("     that it exists and is executable.")

    if lldbPythonDir:
        lldbPythonDir = os.path.normpath(lldbPythonDir)
        # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
        # If the path we've constructed looks like that, then we'll strip out
        # the Versions/A part.
        (before, frameWithVersion, after) = lldbPythonDir.rpartition(
            "LLDB.framework/Versions/A")
        if frameWithVersion != "":
            lldbPythonDir = before + "LLDB.framework" + after

        lldbPythonDir = os.path.abspath(lldbPythonDir)

        if "freebsd" in sys.platform or "linux" in sys.platform:
            os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..')

        # If tests need to find LLDB_FRAMEWORK, now they can do it
        os.environ["LLDB_FRAMEWORK"] = os.path.dirname(
            os.path.dirname(lldbPythonDir))

        # This is to locate the lldb.py module.  Insert it right after
        # sys.path[0].
        sys.path[1:1] = [lldbPythonDir]


def visit_file(dir, name):
    # Try to match the regexp pattern, if specified.
    if configuration.regexp:
        if not re.search(configuration.regexp, name):
            # We didn't match the regex, we're done.
            return

    if configuration.skip_tests:
        for file_regexp in configuration.skip_tests:
            if re.search(file_regexp, name):
                return

    # We found a match for our test.  Add it to the suite.

    # Update the sys.path first.
    if not sys.path.count(dir):
        sys.path.insert(0, dir)
    base = os.path.splitext(name)[0]

    # Thoroughly check the filterspec against the base module and admit
    # the (base, filterspec) combination only when it makes sense.

    def check(obj, parts):
        for part in parts:
            try:
                parent, obj = obj, getattr(obj, part)
            except AttributeError:
                # The filterspec has failed.
                return False
        return True

    module = __import__(base)

    def iter_filters():
        for filterspec in configuration.filters:
            parts = filterspec.split('.')
            if check(module, parts):
                yield filterspec
            elif parts[0] == base and len(parts) > 1 and check(module, parts[1:]):
                yield '.'.join(parts[1:])
            else:
                for key,value in module.__dict__.items():
                    if check(value, parts):
                        yield key + '.' + filterspec

    filtered = False
    for filterspec in iter_filters():
        filtered = True
        print("adding filter spec %s to module %s" % (filterspec, repr(module)))
        tests = unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)
        configuration.suite.addTests(tests)

    # Forgo this module if the (base, filterspec) combo is invalid
    if configuration.filters and not filtered:
        return

    if not filtered:
        # Add the entire file's worth of tests since we're not filtered.
        # Also the fail-over case when the filterspec branch
        # (base, filterspec) combo doesn't make sense.
        configuration.suite.addTests(
            unittest2.defaultTestLoader.loadTestsFromName(base))


def visit(prefix, dir, names):
    """Visitor function for os.path.walk(path, visit, arg)."""

    dir_components = set(dir.split(os.sep))
    excluded_components = set(['.svn', '.git'])
    if dir_components.intersection(excluded_components):
        return

    # Gather all the Python test file names that follow the Test*.py pattern.
    python_test_files = [
        name
        for name in names
        if name.endswith('.py') and name.startswith(prefix)]

    # Visit all the python test files.
    for name in python_test_files:
        # Ensure we error out if we have multiple tests with the same
        # base name.
        # Future improvement: find all the places where we work with base
        # names and convert to full paths.  We have directory structure
        # to disambiguate these, so we shouldn't need this constraint.
        if name in configuration.all_tests:
            raise Exception("Found multiple tests with the name %s" % name)
        configuration.all_tests.add(name)

        # Run the relevant tests in the python file.
        visit_file(dir, name)


# ======================================== #
#                                          #
# Execution of the test driver starts here #
#                                          #
# ======================================== #


def checkDsymForUUIDIsNotOn():
    cmd = ["defaults", "read", "com.apple.DebugSymbols"]
    process = subprocess.Popen(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    cmd_output = process.stdout.read()
    output_str = cmd_output.decode("utf-8")
    if "DBGFileMappedPaths = " in output_str:
        print("%s =>" % ' '.join(cmd))
        print(output_str)
        print(
            "Disable automatic lookup and caching of dSYMs before running the test suite!")
        print("Exiting...")
        sys.exit(0)


def exitTestSuite(exitCode=None):
    # lldb.py does SBDebugger.Initialize().
    # Call SBDebugger.Terminate() on exit.
    import lldb
    lldb.SBDebugger.Terminate()
    if exitCode:
        sys.exit(exitCode)


def getVersionForSDK(sdk):
    sdk = str.lower(sdk)
    full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
    basename = os.path.basename(full_path)
    basename = os.path.splitext(basename)[0]
    basename = str.lower(basename)
    ver = basename.replace(sdk, '')
    return ver


def checkCompiler():
    # Add some intervention here to sanity check that the compiler requested is sane.
    # If found not to be an executable program, we abort.
    c = configuration.compiler
    if which(c):
        return

    if not sys.platform.startswith("darwin"):
        raise Exception(c + " is not a valid compiler")

    pipe = subprocess.Popen(
        ['xcrun', '-find', c], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    cmd_output = pipe.stdout.read()
    if not cmd_output or "not found" in cmd_output:
        raise Exception(c + " is not a valid compiler")

    configuration.compiler = cmd_output.split('\n')[0]
    print("'xcrun -find %s' returning %s" % (c, configuration.compiler))

def canRunLibcxxTests():
    from lldbsuite.test import lldbplatformutil

    platform = lldbplatformutil.getPlatform()

    if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin():
        return True, "libc++ always present"

    if platform == "linux":
        with tempfile.NamedTemporaryFile() as f:
            cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.name, "-"]
            p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
            _, stderr = p.communicate("#include <algorithm>\nint main() {}")
            if not p.returncode:
                return True, "Compiling with -stdlib=libc++ works"
            return False, "Compiling with -stdlib=libc++ fails with the error: %s" % stderr

    return False, "Don't know how to build with libc++ on %s" % platform

def checkLibcxxSupport():
    result, reason = canRunLibcxxTests()
    if result:
        return # libc++ supported
    if "libc++" in configuration.categories_list:
        return # libc++ category explicitly requested, let it run.
    print("Libc++ tests will not be run because: " + reason)
    configuration.skip_categories.append("libc++")

def canRunLibstdcxxTests():
    from lldbsuite.test import lldbplatformutil

    platform = lldbplatformutil.getPlatform()
    if lldbplatformutil.target_is_android():
        platform = "android"
    if platform == "linux":
        return True, "libstdcxx always present"
    return False, "Don't know how to build with libstdcxx on %s" % platform

def checkLibstdcxxSupport():
    result, reason = canRunLibstdcxxTests()
    if result:
        return # libstdcxx supported
    if "libstdcxx" in configuration.categories_list:
        return # libstdcxx category explicitly requested, let it run.
    print("libstdcxx tests will not be run because: " + reason)
    configuration.skip_categories.append("libstdcxx")

def canRunWatchpointTests():
    from lldbsuite.test import lldbplatformutil

    platform = lldbplatformutil.getPlatform()
    if platform == "netbsd":
        if os.geteuid() == 0:
            return True, "root can always write dbregs"
        try:
            output = subprocess.check_output(["/sbin/sysctl", "-n",
              "security.models.extensions.user_set_dbregs"]).decode().strip()
            if output == "1":
                return True, "security.models.extensions.user_set_dbregs enabled"
        except subprocess.CalledProcessError:
            pass
        return False, "security.models.extensions.user_set_dbregs disabled"
    return True, "watchpoint support available"

def checkWatchpointSupport():
    result, reason = canRunWatchpointTests()
    if result:
        return # watchpoints supported
    if "watchpoint" in configuration.categories_list:
        return # watchpoint category explicitly requested, let it run.
    print("watchpoint tests will not be run because: " + reason)
    configuration.skip_categories.append("watchpoint")

def checkObjcSupport():
    from lldbsuite.test import lldbplatformutil

    if not lldbplatformutil.platformIsDarwin():
        print("objc tests will be skipped because of unsupported platform")
        configuration.skip_categories.append("objc")

def checkDebugInfoSupport():
    import lldb

    platform = lldb.selected_platform.GetTriple().split('-')[2]
    compiler = configuration.compiler
    skipped = []
    for cat in test_categories.debug_info_categories:
        if cat in configuration.categories_list:
            continue # Category explicitly requested, let it run.
        if test_categories.is_supported_on_platform(cat, platform, compiler):
            continue
        configuration.skip_categories.append(cat)
        skipped.append(cat)
    if skipped:
        print("Skipping following debug info categories:", skipped)

def checkDebugServerSupport():
    from lldbsuite.test import lldbplatformutil
    import lldb

    skip_msg = "Skipping %s tests, as they are not compatible with remote testing on this platform"
    if lldbplatformutil.platformIsDarwin():
        configuration.skip_categories.append("llgs")
        if lldb.remote_platform:
            # <rdar://problem/34539270>
            configuration.skip_categories.append("debugserver")
            print(skip_msg%"debugserver");
    else:
        configuration.skip_categories.append("debugserver")
        if lldb.remote_platform and lldbplatformutil.getPlatform() == "windows":
            configuration.skip_categories.append("llgs")
            print(skip_msg%"lldb-server");

def run_suite():
    # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
    # does not exist before proceeding to running the test suite.
    if sys.platform.startswith("darwin"):
        checkDsymForUUIDIsNotOn()

    # Start the actions by first parsing the options while setting up the test
    # directories, followed by setting up the search paths for lldb utilities;
    # then, we walk the directory trees and collect the tests into our test suite.
    #
    parseOptionsAndInitTestdirs()

    # Print a stack trace if the test hangs or is passed SIGTERM.
    registerFaulthandler()

    setupSysPath()

    import lldbconfig
    if configuration.capture_path or configuration.replay_path:
        lldbconfig.INITIALIZE = False
    import lldb

    if configuration.capture_path:
        lldb.SBReproducer.Capture(configuration.capture_path)
        lldb.SBReproducer.SetAutoGenerate(True)
    elif configuration.replay_path:
        lldb.SBReproducer.PassiveReplay(configuration.replay_path)

    if not lldbconfig.INITIALIZE:
        lldb.SBDebugger.Initialize()

    # Use host platform by default.
    lldb.selected_platform = lldb.SBPlatform.GetHostPlatform()

    # Now we can also import lldbutil
    from lldbsuite.test import lldbutil

    if configuration.lldb_platform_name:
        print("Setting up remote platform '%s'" %
              (configuration.lldb_platform_name))
        lldb.remote_platform = lldb.SBPlatform(
            configuration.lldb_platform_name)
        if not lldb.remote_platform.IsValid():
            print(
                "error: unable to create the LLDB platform named '%s'." %
                (configuration.lldb_platform_name))
            exitTestSuite(1)
        if configuration.lldb_platform_url:
            # We must connect to a remote platform if a LLDB platform URL was
            # specified
            print(
                "Connecting to remote platform '%s' at '%s'..." %
                (configuration.lldb_platform_name, configuration.lldb_platform_url))
            platform_connect_options = lldb.SBPlatformConnectOptions(
                configuration.lldb_platform_url)
            err = lldb.remote_platform.ConnectRemote(platform_connect_options)
            if err.Success():
                print("Connected.")
            else:
                print("error: failed to connect to remote platform using URL '%s': %s" % (
                    configuration.lldb_platform_url, err))
                exitTestSuite(1)
        else:
            configuration.lldb_platform_url = None

    if configuration.lldb_platform_working_dir:
        print("Setting remote platform working directory to '%s'..." %
              (configuration.lldb_platform_working_dir))
        error = lldb.remote_platform.MakeDirectory(
            configuration.lldb_platform_working_dir, 448)  # 448 = 0o700
        if error.Fail():
            raise Exception("making remote directory '%s': %s" % (
                configuration.lldb_platform_working_dir, error))

        if not lldb.remote_platform.SetWorkingDirectory(
                configuration.lldb_platform_working_dir):
            raise Exception("failed to set working directory '%s'" % configuration.lldb_platform_working_dir)
        lldb.selected_platform = lldb.remote_platform
    else:
        lldb.remote_platform = None
        configuration.lldb_platform_working_dir = None
        configuration.lldb_platform_url = None

    # Set up the working directory.
    # Note that it's not dotest's job to clean this directory.
    lldbutil.mkdir_p(configuration.test_build_dir)

    from . import lldbplatformutil
    target_platform = lldbplatformutil.getPlatform()

    checkLibcxxSupport()
    checkLibstdcxxSupport()
    checkWatchpointSupport()
    checkDebugInfoSupport()
    checkDebugServerSupport()
    checkObjcSupport()

    for testdir in configuration.testdirs:
        for (dirpath, dirnames, filenames) in os.walk(testdir):
            visit('Test', dirpath, filenames)

    #
    # Now that we have loaded all the test cases, run the whole test suite.
    #

    # Install the control-c handler.
    unittest2.signals.installHandler()

    #
    # Invoke the default TextTestRunner to run the test suite
    #
    checkCompiler()

    if configuration.verbose:
        print("compiler=%s" % configuration.compiler)

    # Iterating over all possible architecture and compiler combinations.
    configString = "arch=%s compiler=%s" % (configuration.arch,
                                            configuration.compiler)

    # Output the configuration.
    if configuration.verbose:
        sys.stderr.write("\nConfiguration: " + configString + "\n")

    # First, write out the number of collected test cases.
    if configuration.verbose:
        sys.stderr.write(configuration.separator + "\n")
        sys.stderr.write(
            "Collected %d test%s\n\n" %
            (configuration.suite.countTestCases(),
             configuration.suite.countTestCases() != 1 and "s" or ""))

    if configuration.suite.countTestCases() == 0:
        logging.error("did not discover any matching tests")
        exitTestSuite(1)

    # Invoke the test runner.
    if configuration.count == 1:
        result = unittest2.TextTestRunner(
            stream=sys.stderr,
            verbosity=configuration.verbose,
            resultclass=test_result.LLDBTestResult).run(
            configuration.suite)
    else:
        # We are invoking the same test suite more than once.  In this case,
        # mark __ignore_singleton__ flag as True so the signleton pattern is
        # not enforced.
        test_result.LLDBTestResult.__ignore_singleton__ = True
        for i in range(configuration.count):

            result = unittest2.TextTestRunner(
                stream=sys.stderr,
                verbosity=configuration.verbose,
                resultclass=test_result.LLDBTestResult).run(
                configuration.suite)

    configuration.failed = not result.wasSuccessful()

    if configuration.sdir_has_content and configuration.verbose:
        sys.stderr.write(
            "Session logs for test failures/errors/unexpected successes"
            " can be found in the test build directory\n")

    if configuration.use_categories and len(
            configuration.failures_per_category) > 0:
        sys.stderr.write("Failures per category:\n")
        for category in configuration.failures_per_category:
            sys.stderr.write(
                "%s - %d\n" %
                (category, configuration.failures_per_category[category]))

    # Exiting.
    exitTestSuite(configuration.failed)

if __name__ == "__main__":
    print(
        __file__ +
        " is for use as a module only.  It should not be run as a standalone script.")
    sys.exit(-1)
