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