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