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. 20# test_exec_root: The root path where tests should be run. 21config.test_source_root = os.path.dirname(__file__) 22config.test_exec_root = config.test_source_root 23 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 88if 'Address' in config.llvm_use_sanitizer: 89 config.environment['ASAN_OPTIONS'] = 'detect_stack_use_after_return=1' 90 if 'Darwin' in config.host_os and 'x86' in config.host_triple: 91 config.environment['DYLD_INSERT_LIBRARIES'] = find_sanitizer_runtime( 92 'libclang_rt.asan_osx_dynamic.dylib') 93 94if 'Thread' in config.llvm_use_sanitizer: 95 if 'Darwin' in config.host_os and 'x86' in config.host_triple: 96 config.environment['DYLD_INSERT_LIBRARIES'] = find_sanitizer_runtime( 97 'libclang_rt.tsan_osx_dynamic.dylib') 98 99if 'DYLD_INSERT_LIBRARIES' in config.environment and platform.system() == 'Darwin': 100 config.python_executable = find_python_interpreter() 101 102# Shared library build of LLVM may require LD_LIBRARY_PATH or equivalent. 103if config.shared_libs: 104 for shlibpath_var in find_shlibpath_var(): 105 # In stand-alone build llvm_shlib_dir specifies LLDB's lib directory while 106 # llvm_libs_dir specifies LLVM's lib directory. 107 shlibpath = os.path.pathsep.join( 108 (config.llvm_shlib_dir, config.llvm_libs_dir, 109 config.environment.get(shlibpath_var, ''))) 110 config.environment[shlibpath_var] = shlibpath 111 else: 112 lit_config.warning("unable to inject shared library path on '{}'".format( 113 platform.system())) 114 115# Propagate LLDB_CAPTURE_REPRODUCER 116if 'LLDB_CAPTURE_REPRODUCER' in os.environ: 117 config.environment['LLDB_CAPTURE_REPRODUCER'] = os.environ[ 118 'LLDB_CAPTURE_REPRODUCER'] 119 120# Support running the test suite under the lldb-repro wrapper. This makes it 121# possible to capture a test suite run and then rerun all the test from the 122# just captured reproducer. 123lldb_repro_mode = lit_config.params.get('lldb-run-with-repro', None) 124if lldb_repro_mode: 125 lit_config.note("Running API tests in {} mode.".format(lldb_repro_mode)) 126 mkdir_p(config.lldb_reproducer_directory) 127 if lldb_repro_mode == 'capture': 128 config.available_features.add('lldb-repro-capture') 129 elif lldb_repro_mode == 'replay': 130 config.available_features.add('lldb-repro-replay') 131 132# Clean the module caches in the test build directory. This is necessary in an 133# incremental build whenever clang changes underneath, so doing it once per 134# lit.py invocation is close enough. 135for cachedir in [config.clang_module_cache, config.lldb_module_cache]: 136 if os.path.isdir(cachedir): 137 print("Deleting module cache at %s." % cachedir) 138 shutil.rmtree(cachedir) 139 140# Set a default per-test timeout of 10 minutes. Setting a timeout per test 141# requires that killProcessAndChildren() is supported on the platform and 142# lit complains if the value is set but it is not supported. 143supported, errormsg = lit_config.maxIndividualTestTimeIsSupported 144if supported: 145 lit_config.maxIndividualTestTime = 600 146else: 147 lit_config.warning("Could not set a default per-test timeout. " + errormsg) 148 149# Build dotest command. 150dotest_cmd = [config.dotest_path] 151dotest_cmd += ['--arch', config.test_arch] 152dotest_cmd.extend(config.dotest_args_str.split(';')) 153 154# Library path may be needed to locate just-built clang. 155if config.llvm_libs_dir: 156 dotest_cmd += ['--env', 'LLVM_LIBS_DIR=' + config.llvm_libs_dir] 157 158# Forward ASan-specific environment variables to tests, as a test may load an 159# ASan-ified dylib. 160for env_var in ('ASAN_OPTIONS', 'DYLD_INSERT_LIBRARIES'): 161 if env_var in config.environment: 162 dotest_cmd += ['--inferior-env', env_var + '=' + config.environment[env_var]] 163 164if config.lldb_build_directory: 165 dotest_cmd += ['--build-dir', config.lldb_build_directory] 166 167if config.lldb_module_cache: 168 dotest_cmd += ['--lldb-module-cache-dir', config.lldb_module_cache] 169 170if config.clang_module_cache: 171 dotest_cmd += ['--clang-module-cache-dir', config.clang_module_cache] 172 173if config.lldb_executable: 174 dotest_cmd += ['--executable', config.lldb_executable] 175 176if config.test_compiler: 177 dotest_cmd += ['--compiler', config.test_compiler] 178 179if config.dsymutil: 180 dotest_cmd += ['--dsymutil', config.dsymutil] 181 182if config.filecheck: 183 dotest_cmd += ['--filecheck', config.filecheck] 184 185if config.yaml2obj: 186 dotest_cmd += ['--yaml2obj', config.yaml2obj] 187 188if config.lldb_libs_dir: 189 dotest_cmd += ['--lldb-libs-dir', config.lldb_libs_dir] 190 191if 'lldb-repro-capture' in config.available_features or \ 192 'lldb-repro-replay' in config.available_features: 193 dotest_cmd += ['--skip-category=lldb-vscode', '--skip-category=std-module'] 194 195if config.enabled_plugins: 196 for plugin in config.enabled_plugins: 197 dotest_cmd += ['--enable-plugin', plugin] 198 199# We don't want to force users passing arguments to lit to use `;` as a 200# separator. We use Python's simple lexical analyzer to turn the args into a 201# list. Pass there arguments last so they can override anything that was 202# already configured. 203if config.dotest_lit_args_str: 204 dotest_cmd.extend(shlex.split(config.dotest_lit_args_str)) 205 206 207# Load LLDB test format. 208sys.path.append(os.path.join(config.lldb_src_root, "test", "API")) 209import lldbtest 210 211# testFormat: The test format to use to interpret tests. 212config.test_format = lldbtest.LLDBTest(dotest_cmd) 213