"""
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.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)

    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')
    intelpt = os.path.join(scriptPath, 'tools', 'intelpt')

    # 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
    # to "import lldbgdbserverutils" from the lldb-server tests
    sys.path.insert(0, toolsLLDBServerPath)
    # Adding test/tools/intelpt to the path makes it easy
    # to "import intelpt_testcase" from the lldb-server tests
    sys.path.insert(0, intelpt)

    # 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 <cassert>\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.
    if configuration.verbose:
        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.
    if configuration.verbose:
        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"
    elif platform == "freebsd" and configuration.arch == "aarch64":
        import lldb
        if lldb.SBPlatform.GetHostPlatform().GetOSMajorVersion() < 13:
            return False, "Watchpoint support on arm64 requires FreeBSD 13.0"
    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.
    if configuration.verbose:
        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():
        if configuration.verbose:
            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
    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)

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")
            if configuration.verbose:
                print(skip_msg%"debugserver");
    else:
        configuration.skip_categories.append("debugserver")
        if lldb.remote_platform and lldbplatformutil.getPlatform() == "windows":
            configuration.skip_categories.append("llgs")
            if configuration.verbose:
                print(skip_msg%"lldb-server");


def checkForkVForkSupport():
    from lldbsuite.test import lldbplatformutil

    platform = lldbplatformutil.getPlatform()
    if platform not in ["freebsd", "linux", "netbsd"]:
        configuration.skip_categories.append("fork")


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 lldb
    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.")
                lldb.selected_platform = lldb.remote_platform
            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)

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

    print("Skipping the following test categories: {}".format(configuration.skip_categories))

    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)
