1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
# -*- Python -*-
# Configuration file for the 'lit' test runner.
import os
import platform
import shlex
import shutil
import lit.formats
# name: The name of this test suite.
config.name = 'lldb-api'
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.py']
# test_source_root: The root path where tests are located.
# test_exec_root: The root path where tests should be run.
config.test_source_root = os.path.dirname(__file__)
config.test_exec_root = config.test_source_root
def mkdir_p(path):
import errno
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if not os.path.isdir(path):
raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
def find_sanitizer_runtime(name):
import subprocess
resource_dir = subprocess.check_output(
[config.cmake_cxx_compiler,
'-print-resource-dir']).decode('utf-8').strip()
return os.path.join(resource_dir, 'lib', 'darwin', name)
def find_shlibpath_var():
if platform.system() in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']:
yield 'LD_LIBRARY_PATH'
elif platform.system() == 'Darwin':
yield 'DYLD_LIBRARY_PATH'
elif platform.system() == 'Windows':
yield 'PATH'
# On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim python
# binary as the ASan interceptors get loaded too late. Also, when SIP is
# enabled, we can't inject libraries into system binaries at all, so we need a
# copy of the "real" python to work with.
def find_python_interpreter():
# Avoid doing any work if we already copied the binary.
copied_python = os.path.join(config.lldb_build_directory, 'copied-python')
if os.path.isfile(copied_python):
return copied_python
# Find the "real" python binary.
import shutil, subprocess
real_python = subprocess.check_output([
config.python_executable,
os.path.join(os.path.dirname(os.path.realpath(__file__)),
'get_darwin_real_python.py')
]).decode('utf-8').strip()
shutil.copy(real_python, copied_python)
# Now make sure the copied Python works. The Python in Xcode has a relative
# RPATH and cannot be copied.
try:
# We don't care about the output, just make sure it runs.
subprocess.check_output([copied_python, '-V'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
# The copied Python didn't work. Assume we're dealing with the Python
# interpreter in Xcode. Given that this is not a system binary SIP
# won't prevent us form injecting the interceptors so we get away with
# not copying the executable.
os.remove(copied_python)
return real_python
# The copied Python works.
return copied_python
if 'Address' in config.llvm_use_sanitizer:
config.environment['ASAN_OPTIONS'] = 'detect_stack_use_after_return=1'
if 'Darwin' in config.host_os and 'x86' in config.host_triple:
config.environment['DYLD_INSERT_LIBRARIES'] = find_sanitizer_runtime(
'libclang_rt.asan_osx_dynamic.dylib')
if 'Thread' in config.llvm_use_sanitizer:
if 'Darwin' in config.host_os and 'x86' in config.host_triple:
config.environment['DYLD_INSERT_LIBRARIES'] = find_sanitizer_runtime(
'libclang_rt.tsan_osx_dynamic.dylib')
if 'DYLD_INSERT_LIBRARIES' in config.environment and platform.system() == 'Darwin':
config.python_executable = find_python_interpreter()
# Shared library build of LLVM may require LD_LIBRARY_PATH or equivalent.
if config.shared_libs:
for shlibpath_var in find_shlibpath_var():
# In stand-alone build llvm_shlib_dir specifies LLDB's lib directory while
# llvm_libs_dir specifies LLVM's lib directory.
shlibpath = os.path.pathsep.join(
(config.llvm_shlib_dir, config.llvm_libs_dir,
config.environment.get(shlibpath_var, '')))
config.environment[shlibpath_var] = shlibpath
else:
lit_config.warning("unable to inject shared library path on '{}'".format(
platform.system()))
# Propagate LLDB_CAPTURE_REPRODUCER
if 'LLDB_CAPTURE_REPRODUCER' in os.environ:
config.environment['LLDB_CAPTURE_REPRODUCER'] = os.environ[
'LLDB_CAPTURE_REPRODUCER']
# Support running the test suite under the lldb-repro wrapper. This makes it
# possible to capture a test suite run and then rerun all the test from the
# just captured reproducer.
lldb_repro_mode = lit_config.params.get('lldb-run-with-repro', None)
if lldb_repro_mode:
lit_config.note("Running API tests in {} mode.".format(lldb_repro_mode))
mkdir_p(config.lldb_reproducer_directory)
if lldb_repro_mode == 'capture':
config.available_features.add('lldb-repro-capture')
elif lldb_repro_mode == 'replay':
config.available_features.add('lldb-repro-replay')
# Clean the module caches in the test build directory. This is necessary in an
# incremental build whenever clang changes underneath, so doing it once per
# lit.py invocation is close enough.
for cachedir in [config.clang_module_cache, config.lldb_module_cache]:
if os.path.isdir(cachedir):
print("Deleting module cache at %s." % cachedir)
shutil.rmtree(cachedir)
# Set a default per-test timeout of 10 minutes. Setting a timeout per test
# requires that killProcessAndChildren() is supported on the platform and
# lit complains if the value is set but it is not supported.
supported, errormsg = lit_config.maxIndividualTestTimeIsSupported
if supported:
lit_config.maxIndividualTestTime = 600
else:
lit_config.warning("Could not set a default per-test timeout. " + errormsg)
# Build dotest command.
dotest_cmd = [config.dotest_path]
dotest_cmd += ['--arch', config.test_arch]
dotest_cmd.extend(config.dotest_args_str.split(';'))
# Library path may be needed to locate just-built clang.
if config.llvm_libs_dir:
dotest_cmd += ['--env', 'LLVM_LIBS_DIR=' + config.llvm_libs_dir]
# Forward ASan-specific environment variables to tests, as a test may load an
# ASan-ified dylib.
for env_var in ('ASAN_OPTIONS', 'DYLD_INSERT_LIBRARIES'):
if env_var in config.environment:
dotest_cmd += ['--inferior-env', env_var + '=' + config.environment[env_var]]
if config.lldb_build_directory:
dotest_cmd += ['--build-dir', config.lldb_build_directory]
if config.lldb_module_cache:
dotest_cmd += ['--lldb-module-cache-dir', config.lldb_module_cache]
if config.clang_module_cache:
dotest_cmd += ['--clang-module-cache-dir', config.clang_module_cache]
if config.lldb_executable:
dotest_cmd += ['--executable', config.lldb_executable]
if config.test_compiler:
dotest_cmd += ['--compiler', config.test_compiler]
if config.dsymutil:
dotest_cmd += ['--dsymutil', config.dsymutil]
if config.filecheck:
dotest_cmd += ['--filecheck', config.filecheck]
if config.yaml2obj:
dotest_cmd += ['--yaml2obj', config.yaml2obj]
if config.lldb_libs_dir:
dotest_cmd += ['--lldb-libs-dir', config.lldb_libs_dir]
if 'lldb-repro-capture' in config.available_features or \
'lldb-repro-replay' in config.available_features:
dotest_cmd += ['--skip-category=lldb-vscode', '--skip-category=std-module']
if config.enabled_plugins:
for plugin in config.enabled_plugins:
dotest_cmd += ['--enable-plugin', plugin]
# We don't want to force users passing arguments to lit to use `;` as a
# separator. We use Python's simple lexical analyzer to turn the args into a
# list. Pass there arguments last so they can override anything that was
# already configured.
if config.dotest_lit_args_str:
dotest_cmd.extend(shlex.split(config.dotest_lit_args_str))
# Load LLDB test format.
sys.path.append(os.path.join(config.lldb_src_root, "test", "API"))
import lldbtest
# testFormat: The test format to use to interpret tests.
config.test_format = lldbtest.LLDBTest(dotest_cmd)
|