109467b48Spatrickimport os
209467b48Spatrickimport sys
309467b48Spatrick
409467b48Spatrick
5097a140dSpatrickclass TestingConfig(object):
609467b48Spatrick    """"
709467b48Spatrick    TestingConfig - Information on the tests inside a suite.
809467b48Spatrick    """
909467b48Spatrick
1009467b48Spatrick    @staticmethod
1109467b48Spatrick    def fromdefaults(litConfig):
1209467b48Spatrick        """
1309467b48Spatrick        fromdefaults(litConfig) -> TestingConfig
1409467b48Spatrick
1509467b48Spatrick        Create a TestingConfig object with default values.
1609467b48Spatrick        """
1709467b48Spatrick        # Set the environment based on the command line arguments.
1809467b48Spatrick        environment = {
1909467b48Spatrick            'PATH' : os.pathsep.join(litConfig.path +
2009467b48Spatrick                                     [os.environ.get('PATH','')]),
2109467b48Spatrick            'LLVM_DISABLE_CRASH_REPORT' : '1',
2209467b48Spatrick            }
2309467b48Spatrick
24*d415bd75Srobert        pass_vars = [
25*d415bd75Srobert            'LIBRARY_PATH',
26*d415bd75Srobert            'LD_LIBRARY_PATH',
27*d415bd75Srobert            'SYSTEMROOT',
28*d415bd75Srobert            'TERM',
29*d415bd75Srobert            'CLANG',
30*d415bd75Srobert            'LLDB',
31*d415bd75Srobert            'LD_PRELOAD',
32*d415bd75Srobert            'LLVM_SYMBOLIZER_PATH',
33*d415bd75Srobert            'ASAN_SYMBOLIZER_PATH',
34*d415bd75Srobert            'HWASAN_SYMBOLIZER_PATH',
35*d415bd75Srobert            'LSAN_SYMBOLIZER_PATH',
36*d415bd75Srobert            'MSAN_SYMBOLIZER_PATH',
37*d415bd75Srobert            'TSAN_SYMBOLIZER_PATH',
38*d415bd75Srobert            'UBSAN_SYMBOLIZER_PATH',
39*d415bd75Srobert            'ASAN_OPTIONS',
40*d415bd75Srobert            'LSAN_OPTIONS',
41*d415bd75Srobert            'HWASAN_OPTIONS',
42*d415bd75Srobert            'MSAN_OPTIONS',
43*d415bd75Srobert            'TSAN_OPTIONS',
44*d415bd75Srobert            'UBSAN_OPTIONS',
45*d415bd75Srobert            'ADB',
46*d415bd75Srobert            'ANDROID_SERIAL',
47*d415bd75Srobert            'SSH_AUTH_SOCK',
48*d415bd75Srobert            'SANITIZER_IGNORE_CVE_2016_2143',
49*d415bd75Srobert            'TMPDIR',
50*d415bd75Srobert            'TMP',
51*d415bd75Srobert            'TEMP',
52*d415bd75Srobert            'TEMPDIR',
53*d415bd75Srobert            'AVRLIT_BOARD',
54*d415bd75Srobert            'AVRLIT_PORT',
55*d415bd75Srobert            'FILECHECK_OPTS',
56*d415bd75Srobert            'VCINSTALLDIR',
57*d415bd75Srobert            'VCToolsinstallDir',
58*d415bd75Srobert            'VSINSTALLDIR',
59*d415bd75Srobert            'WindowsSdkDir',
60*d415bd75Srobert            'WindowsSDKLibVersion',
61*d415bd75Srobert            'SOURCE_DATE_EPOCH',
62*d415bd75Srobert            'GTEST_FILTER',
63*d415bd75Srobert            'DFLTCC',
64*d415bd75Srobert        ]
6509467b48Spatrick
66*d415bd75Srobert        if sys.platform.startswith('aix'):
67*d415bd75Srobert            pass_vars += ['LIBPATH']
68*d415bd75Srobert        elif sys.platform == 'win32':
69*d415bd75Srobert            pass_vars += [
70*d415bd75Srobert                'COMSPEC',
71*d415bd75Srobert                'INCLUDE',
72*d415bd75Srobert                'LIB',
73*d415bd75Srobert                'PATHEXT',
74*d415bd75Srobert                'USERPROFILE',
75*d415bd75Srobert            ]
7609467b48Spatrick            environment['PYTHONBUFFERED'] = '1'
7709467b48Spatrick
7809467b48Spatrick        for var in pass_vars:
7909467b48Spatrick            val = os.environ.get(var, '')
8009467b48Spatrick            # Check for empty string as some variables such as LD_PRELOAD cannot be empty
8109467b48Spatrick            # ('') for OS's such as OpenBSD.
8209467b48Spatrick            if val:
8309467b48Spatrick                environment[var] = val
8409467b48Spatrick
8509467b48Spatrick        # Set the default available features based on the LitConfig.
8609467b48Spatrick        available_features = []
8709467b48Spatrick        if litConfig.useValgrind:
8809467b48Spatrick            available_features.append('valgrind')
8909467b48Spatrick            if litConfig.valgrindLeakCheck:
9009467b48Spatrick                available_features.append('vg_leak')
9109467b48Spatrick
9209467b48Spatrick        return TestingConfig(None,
9309467b48Spatrick                             name = '<unnamed>',
9409467b48Spatrick                             suffixes = set(),
9509467b48Spatrick                             test_format = None,
9609467b48Spatrick                             environment = environment,
9709467b48Spatrick                             substitutions = [],
9809467b48Spatrick                             unsupported = False,
9909467b48Spatrick                             test_exec_root = None,
10009467b48Spatrick                             test_source_root = None,
10109467b48Spatrick                             excludes = [],
10209467b48Spatrick                             available_features = available_features,
10373471bf0Spatrick                             pipefail = True,
10473471bf0Spatrick                             standalone_tests = False)
10509467b48Spatrick
10609467b48Spatrick    def load_from_path(self, path, litConfig):
10709467b48Spatrick        """
10809467b48Spatrick        load_from_path(path, litConfig)
10909467b48Spatrick
11009467b48Spatrick        Load the configuration module at the provided path into the given config
11109467b48Spatrick        object.
11209467b48Spatrick        """
11309467b48Spatrick
11409467b48Spatrick        # Load the config script data.
11509467b48Spatrick        data = None
11609467b48Spatrick        f = open(path)
11709467b48Spatrick        try:
11809467b48Spatrick            data = f.read()
11909467b48Spatrick        except:
12009467b48Spatrick            litConfig.fatal('unable to load config file: %r' % (path,))
12109467b48Spatrick        f.close()
12209467b48Spatrick
12309467b48Spatrick        # Execute the config script to initialize the object.
12409467b48Spatrick        cfg_globals = dict(globals())
12509467b48Spatrick        cfg_globals['config'] = self
12609467b48Spatrick        cfg_globals['lit_config'] = litConfig
12709467b48Spatrick        cfg_globals['__file__'] = path
12809467b48Spatrick        try:
12909467b48Spatrick            exec(compile(data, path, 'exec'), cfg_globals, None)
13009467b48Spatrick            if litConfig.debug:
13109467b48Spatrick                litConfig.note('... loaded config %r' % path)
13209467b48Spatrick        except SystemExit:
13309467b48Spatrick            e = sys.exc_info()[1]
13409467b48Spatrick            # We allow normal system exit inside a config file to just
13509467b48Spatrick            # return control without error.
13609467b48Spatrick            if e.args:
13709467b48Spatrick                raise
13809467b48Spatrick        except:
13909467b48Spatrick            import traceback
14009467b48Spatrick            litConfig.fatal(
14109467b48Spatrick                'unable to parse config file %r, traceback: %s' % (
14209467b48Spatrick                    path, traceback.format_exc()))
14309467b48Spatrick        self.finish(litConfig)
14409467b48Spatrick
14509467b48Spatrick    def __init__(self, parent, name, suffixes, test_format,
14609467b48Spatrick                 environment, substitutions, unsupported,
14709467b48Spatrick                 test_exec_root, test_source_root, excludes,
14809467b48Spatrick                 available_features, pipefail, limit_to_features = [],
14973471bf0Spatrick                 is_early = False, parallelism_group = None,
15073471bf0Spatrick                 standalone_tests = False):
15109467b48Spatrick        self.parent = parent
15209467b48Spatrick        self.name = str(name)
15309467b48Spatrick        self.suffixes = set(suffixes)
15409467b48Spatrick        self.test_format = test_format
15509467b48Spatrick        self.environment = dict(environment)
15609467b48Spatrick        self.substitutions = list(substitutions)
15709467b48Spatrick        self.unsupported = unsupported
15809467b48Spatrick        self.test_exec_root = test_exec_root
15909467b48Spatrick        self.test_source_root = test_source_root
16009467b48Spatrick        self.excludes = set(excludes)
16109467b48Spatrick        self.available_features = set(available_features)
16209467b48Spatrick        self.pipefail = pipefail
16373471bf0Spatrick        self.standalone_tests = standalone_tests
16409467b48Spatrick        # This list is used by TestRunner.py to restrict running only tests that
16509467b48Spatrick        # require one of the features in this list if this list is non-empty.
16609467b48Spatrick        # Configurations can set this list to restrict the set of tests to run.
16709467b48Spatrick        self.limit_to_features = set(limit_to_features)
16809467b48Spatrick        self.parallelism_group = parallelism_group
169097a140dSpatrick        self._recursiveExpansionLimit = None
170097a140dSpatrick
171097a140dSpatrick    @property
172097a140dSpatrick    def recursiveExpansionLimit(self):
173097a140dSpatrick        return self._recursiveExpansionLimit
174097a140dSpatrick
175097a140dSpatrick    @recursiveExpansionLimit.setter
176097a140dSpatrick    def recursiveExpansionLimit(self, value):
177097a140dSpatrick        if value is not None and not isinstance(value, int):
178097a140dSpatrick            raise ValueError('recursiveExpansionLimit must be either None or an integer (got <{}>)'.format(value))
179097a140dSpatrick        if isinstance(value, int) and value < 0:
180097a140dSpatrick            raise ValueError('recursiveExpansionLimit must be a non-negative integer (got <{}>)'.format(value))
181097a140dSpatrick        self._recursiveExpansionLimit = value
18209467b48Spatrick
18309467b48Spatrick    def finish(self, litConfig):
18409467b48Spatrick        """finish() - Finish this config object, after loading is complete."""
18509467b48Spatrick
18609467b48Spatrick        self.name = str(self.name)
18709467b48Spatrick        self.suffixes = set(self.suffixes)
18809467b48Spatrick        self.environment = dict(self.environment)
18909467b48Spatrick        self.substitutions = list(self.substitutions)
19009467b48Spatrick        if self.test_exec_root is not None:
19109467b48Spatrick            # FIXME: This should really only be suite in test suite config
19209467b48Spatrick            # files. Should we distinguish them?
19309467b48Spatrick            self.test_exec_root = str(self.test_exec_root)
19409467b48Spatrick        if self.test_source_root is not None:
19509467b48Spatrick            # FIXME: This should really only be suite in test suite config
19609467b48Spatrick            # files. Should we distinguish them?
19709467b48Spatrick            self.test_source_root = str(self.test_source_root)
19809467b48Spatrick        self.excludes = set(self.excludes)
19909467b48Spatrick
20009467b48Spatrick    @property
20109467b48Spatrick    def root(self):
20209467b48Spatrick        """root attribute - The root configuration for the test suite."""
20309467b48Spatrick        if self.parent is None:
20409467b48Spatrick            return self
20509467b48Spatrick        else:
20609467b48Spatrick            return self.parent.root
20709467b48Spatrick
20809467b48Spatrickclass SubstituteCaptures:
20909467b48Spatrick    """
21009467b48Spatrick    Helper class to indicate that the substitutions contains backreferences.
21109467b48Spatrick
21209467b48Spatrick    This can be used as the following in lit.cfg to mark subsitutions as having
21309467b48Spatrick    back-references::
21409467b48Spatrick
21509467b48Spatrick        config.substutions.append(('\b[^ ]*.cpp', SubstituteCaptures('\0.txt')))
21609467b48Spatrick
21709467b48Spatrick    """
21809467b48Spatrick    def __init__(self, substitution):
21909467b48Spatrick        self.substitution = substitution
22009467b48Spatrick
22109467b48Spatrick    def replace(self, pattern, replacement):
22209467b48Spatrick        return self.substitution
22309467b48Spatrick
22409467b48Spatrick    def __str__(self):
22509467b48Spatrick        return self.substitution
22609467b48Spatrick
22709467b48Spatrick    def __len__(self):
22809467b48Spatrick        return len(self.substitution)
22909467b48Spatrick
23009467b48Spatrick    def __getitem__(self, item):
23109467b48Spatrick        return self.substitution.__getitem__(item)
23209467b48Spatrick
233