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