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 print("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 and 'x86' in config.host_triple: 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 and 'x86' in config.host_triple: 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. 162if is_configured('llvm_libs_dir'): 163 dotest_cmd += ['--env', 'LLVM_LIBS_DIR=' + config.llvm_libs_dir] 164 165# Forward ASan-specific environment variables to tests, as a test may load an 166# ASan-ified dylib. 167for env_var in ('ASAN_OPTIONS', 'DYLD_INSERT_LIBRARIES'): 168 if env_var in config.environment: 169 dotest_cmd += ['--inferior-env', env_var + '=' + config.environment[env_var]] 170 171if is_configured('test_arch'): 172 dotest_cmd += ['--arch', config.test_arch] 173 174if is_configured('lldb_build_directory'): 175 dotest_cmd += ['--build-dir', config.lldb_build_directory] 176 177if is_configured('lldb_module_cache'): 178 delete_module_cache(config.lldb_module_cache) 179 dotest_cmd += ['--lldb-module-cache-dir', config.lldb_module_cache] 180 181if is_configured('clang_module_cache'): 182 delete_module_cache(config.clang_module_cache) 183 dotest_cmd += ['--clang-module-cache-dir', config.clang_module_cache] 184 185if is_configured('lldb_executable'): 186 dotest_cmd += ['--executable', config.lldb_executable] 187 188if is_configured('test_compiler'): 189 dotest_cmd += ['--compiler', config.test_compiler] 190 191if is_configured('dsymutil'): 192 dotest_cmd += ['--dsymutil', config.dsymutil] 193 194if is_configured('llvm_tools_dir'): 195 dotest_cmd += ['--llvm-tools-dir', config.llvm_tools_dir] 196 197if is_configured('server'): 198 dotest_cmd += ['--server', config.server] 199 200if is_configured('lldb_libs_dir'): 201 dotest_cmd += ['--lldb-libs-dir', config.lldb_libs_dir] 202 203if is_configured('lldb_framework_dir'): 204 dotest_cmd += ['--framework', config.lldb_framework_dir] 205 206if 'lldb-repro-capture' in config.available_features or \ 207 'lldb-repro-replay' in config.available_features: 208 dotest_cmd += ['--skip-category=lldb-vscode', '--skip-category=std-module'] 209 210if 'lldb-simulator-ios' in config.available_features: 211 dotest_cmd += ['--apple-sdk', 'iphonesimulator', 212 '--platform-name', 'ios-simulator'] 213elif 'lldb-simulator-watchos' in config.available_features: 214 dotest_cmd += ['--apple-sdk', 'watchsimulator', 215 '--platform-name', 'watchos-simulator'] 216elif 'lldb-simulator-tvos' in config.available_features: 217 dotest_cmd += ['--apple-sdk', 'appletvsimulator', 218 '--platform-name', 'tvos-simulator'] 219 220if is_configured('enabled_plugins'): 221 for plugin in config.enabled_plugins: 222 dotest_cmd += ['--enable-plugin', plugin] 223 224if is_configured('dotest_lit_args_str'): 225 # We don't want to force users passing arguments to lit to use `;` as a 226 # separator. We use Python's simple lexical analyzer to turn the args into a 227 # list. Pass there arguments last so they can override anything that was 228 # already configured. 229 dotest_cmd.extend(shlex.split(config.dotest_lit_args_str)) 230 231# Load LLDB test format. 232sys.path.append(os.path.join(config.lldb_src_root, "test", "API")) 233import lldbtest 234 235# testFormat: The test format to use to interpret tests. 236config.test_format = lldbtest.LLDBTest(dotest_cmd) 237 238# Propagate FREEBSD_LEGACY_PLUGIN 239if 'FREEBSD_LEGACY_PLUGIN' in os.environ: 240 config.environment['FREEBSD_LEGACY_PLUGIN'] = os.environ[ 241 'FREEBSD_LEGACY_PLUGIN'] 242 243# Propagate XDG_CACHE_HOME 244if 'XDG_CACHE_HOME' in os.environ: 245 config.environment['XDG_CACHE_HOME'] = os.environ['XDG_CACHE_HOME'] 246