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