1import os 2import sys 3 4 5class TestingConfig(object): 6 """" 7 TestingConfig - Information on the tests inside a suite. 8 """ 9 10 @staticmethod 11 def fromdefaults(litConfig): 12 """ 13 fromdefaults(litConfig) -> TestingConfig 14 15 Create a TestingConfig object with default values. 16 """ 17 # Set the environment based on the command line arguments. 18 environment = { 19 'PATH' : os.pathsep.join(litConfig.path + 20 [os.environ.get('PATH','')]), 21 'LLVM_DISABLE_CRASH_REPORT' : '1', 22 } 23 24 pass_vars = [ 25 'LIBRARY_PATH', 26 'LD_LIBRARY_PATH', 27 'SYSTEMROOT', 28 'TERM', 29 'CLANG', 30 'LLDB', 31 'LD_PRELOAD', 32 'LLVM_SYMBOLIZER_PATH', 33 'ASAN_SYMBOLIZER_PATH', 34 'HWASAN_SYMBOLIZER_PATH', 35 'LSAN_SYMBOLIZER_PATH', 36 'MSAN_SYMBOLIZER_PATH', 37 'TSAN_SYMBOLIZER_PATH', 38 'UBSAN_SYMBOLIZER_PATH', 39 'ASAN_OPTIONS', 40 'LSAN_OPTIONS', 41 'HWASAN_OPTIONS', 42 'MSAN_OPTIONS', 43 'TSAN_OPTIONS', 44 'UBSAN_OPTIONS', 45 'ADB', 46 'ANDROID_SERIAL', 47 'SSH_AUTH_SOCK', 48 'SANITIZER_IGNORE_CVE_2016_2143', 49 'TMPDIR', 50 'TMP', 51 'TEMP', 52 'TEMPDIR', 53 'AVRLIT_BOARD', 54 'AVRLIT_PORT', 55 'FILECHECK_OPTS', 56 'VCINSTALLDIR', 57 'VCToolsinstallDir', 58 'VSINSTALLDIR', 59 'WindowsSdkDir', 60 'WindowsSDKLibVersion', 61 'SOURCE_DATE_EPOCH', 62 'GTEST_FILTER', 63 'DFLTCC', 64 ] 65 66 if sys.platform.startswith('aix'): 67 pass_vars += ['LIBPATH'] 68 elif sys.platform == 'win32': 69 pass_vars += [ 70 'COMSPEC', 71 'INCLUDE', 72 'LIB', 73 'PATHEXT', 74 'USERPROFILE', 75 ] 76 environment['PYTHONBUFFERED'] = '1' 77 78 for var in pass_vars: 79 val = os.environ.get(var, '') 80 # Check for empty string as some variables such as LD_PRELOAD cannot be empty 81 # ('') for OS's such as OpenBSD. 82 if val: 83 environment[var] = val 84 85 # Set the default available features based on the LitConfig. 86 available_features = [] 87 if litConfig.useValgrind: 88 available_features.append('valgrind') 89 if litConfig.valgrindLeakCheck: 90 available_features.append('vg_leak') 91 92 return TestingConfig(None, 93 name = '<unnamed>', 94 suffixes = set(), 95 test_format = None, 96 environment = environment, 97 substitutions = [], 98 unsupported = False, 99 test_exec_root = None, 100 test_source_root = None, 101 excludes = [], 102 available_features = available_features, 103 pipefail = True, 104 standalone_tests = False) 105 106 def load_from_path(self, path, litConfig): 107 """ 108 load_from_path(path, litConfig) 109 110 Load the configuration module at the provided path into the given config 111 object. 112 """ 113 114 # Load the config script data. 115 data = None 116 f = open(path) 117 try: 118 data = f.read() 119 except: 120 litConfig.fatal('unable to load config file: %r' % (path,)) 121 f.close() 122 123 # Execute the config script to initialize the object. 124 cfg_globals = dict(globals()) 125 cfg_globals['config'] = self 126 cfg_globals['lit_config'] = litConfig 127 cfg_globals['__file__'] = path 128 try: 129 exec(compile(data, path, 'exec'), cfg_globals, None) 130 if litConfig.debug: 131 litConfig.note('... loaded config %r' % path) 132 except SystemExit: 133 e = sys.exc_info()[1] 134 # We allow normal system exit inside a config file to just 135 # return control without error. 136 if e.args: 137 raise 138 except: 139 import traceback 140 litConfig.fatal( 141 'unable to parse config file %r, traceback: %s' % ( 142 path, traceback.format_exc())) 143 self.finish(litConfig) 144 145 def __init__(self, parent, name, suffixes, test_format, 146 environment, substitutions, unsupported, 147 test_exec_root, test_source_root, excludes, 148 available_features, pipefail, limit_to_features = [], 149 is_early = False, parallelism_group = None, 150 standalone_tests = False): 151 self.parent = parent 152 self.name = str(name) 153 self.suffixes = set(suffixes) 154 self.test_format = test_format 155 self.environment = dict(environment) 156 self.substitutions = list(substitutions) 157 self.unsupported = unsupported 158 self.test_exec_root = test_exec_root 159 self.test_source_root = test_source_root 160 self.excludes = set(excludes) 161 self.available_features = set(available_features) 162 self.pipefail = pipefail 163 self.standalone_tests = standalone_tests 164 # This list is used by TestRunner.py to restrict running only tests that 165 # require one of the features in this list if this list is non-empty. 166 # Configurations can set this list to restrict the set of tests to run. 167 self.limit_to_features = set(limit_to_features) 168 self.parallelism_group = parallelism_group 169 self._recursiveExpansionLimit = None 170 171 @property 172 def recursiveExpansionLimit(self): 173 return self._recursiveExpansionLimit 174 175 @recursiveExpansionLimit.setter 176 def recursiveExpansionLimit(self, value): 177 if value is not None and not isinstance(value, int): 178 raise ValueError('recursiveExpansionLimit must be either None or an integer (got <{}>)'.format(value)) 179 if isinstance(value, int) and value < 0: 180 raise ValueError('recursiveExpansionLimit must be a non-negative integer (got <{}>)'.format(value)) 181 self._recursiveExpansionLimit = value 182 183 def finish(self, litConfig): 184 """finish() - Finish this config object, after loading is complete.""" 185 186 self.name = str(self.name) 187 self.suffixes = set(self.suffixes) 188 self.environment = dict(self.environment) 189 self.substitutions = list(self.substitutions) 190 if self.test_exec_root is not None: 191 # FIXME: This should really only be suite in test suite config 192 # files. Should we distinguish them? 193 self.test_exec_root = str(self.test_exec_root) 194 if self.test_source_root is not None: 195 # FIXME: This should really only be suite in test suite config 196 # files. Should we distinguish them? 197 self.test_source_root = str(self.test_source_root) 198 self.excludes = set(self.excludes) 199 200 @property 201 def root(self): 202 """root attribute - The root configuration for the test suite.""" 203 if self.parent is None: 204 return self 205 else: 206 return self.parent.root 207 208class SubstituteCaptures: 209 """ 210 Helper class to indicate that the substitutions contains backreferences. 211 212 This can be used as the following in lit.cfg to mark subsitutions as having 213 back-references:: 214 215 config.substutions.append(('\b[^ ]*.cpp', SubstituteCaptures('\0.txt'))) 216 217 """ 218 def __init__(self, substitution): 219 self.substitution = substitution 220 221 def replace(self, pattern, replacement): 222 return self.substitution 223 224 def __str__(self): 225 return self.substitution 226 227 def __len__(self): 228 return len(self.substitution) 229 230 def __getitem__(self, item): 231 return self.substitution.__getitem__(item) 232 233