2 Test discovery functions.
9 from lit.TestingConfig import TestingConfig
10 from lit import LitConfig, Test
12 def dirContainsTestSuite(path, lit_config):
13 cfgpath = os.path.join(path, lit_config.site_config_name)
14 if os.path.exists(cfgpath):
16 cfgpath = os.path.join(path, lit_config.config_name)
17 if os.path.exists(cfgpath):
20 def getTestSuite(item, litConfig, cache):
21 """getTestSuite(item, litConfig, cache) -> (suite, relative_path)
23 Find the test suite containing @arg item.
25 @retval (None, ...) - Indicates no test suite contains @arg item.
26 @retval (suite, relative_path) - The suite that @arg item is in, and its
27 relative path inside that suite.
30 # Check for a site config or a lit config.
31 cfgpath = dirContainsTestSuite(path, litConfig)
33 # If we didn't find a config file, keep looking.
35 parent,base = os.path.split(path)
39 ts, relative = search(parent)
40 return (ts, relative + (base,))
42 # We found a test suite, create a new config for it and load it.
44 litConfig.note('loading suite config %r' % cfgpath)
46 cfg = TestingConfig.fromdefaults(litConfig)
47 cfg.load_from_path(cfgpath, litConfig)
48 source_root = os.path.realpath(cfg.test_source_root or path)
49 exec_root = os.path.realpath(cfg.test_exec_root or path)
50 return Test.TestSuite(cfg.name, source_root, exec_root, cfg), ()
53 # Check for an already instantiated test suite.
56 cache[path] = res = search1(path)
59 # Canonicalize the path.
60 item = os.path.realpath(item)
62 # Skip files and virtual components.
64 while not os.path.isdir(item):
65 parent,base = os.path.split(item)
68 components.append(base)
72 ts, relative = search(item)
73 return ts, tuple(relative + tuple(components))
75 def getLocalConfig(ts, path_in_suite, litConfig, cache):
76 def search1(path_in_suite):
77 # Get the parent config.
81 parent = search(path_in_suite[:-1])
83 # Check if there is a local configuration file.
84 source_path = ts.getSourcePath(path_in_suite)
85 cfgpath = os.path.join(source_path, litConfig.local_config_name)
87 # If not, just reuse the parent config.
88 if not os.path.exists(cfgpath):
91 # Otherwise, copy the current config and load the local configuration
93 config = parent.clone()
95 litConfig.note('loading local config %r' % cfgpath)
96 config.load_from_path(cfgpath, litConfig)
99 def search(path_in_suite):
100 key = (ts, path_in_suite)
103 cache[key] = res = search1(path_in_suite)
106 return search(path_in_suite)
108 def getTests(path, litConfig, testSuiteCache, localConfigCache):
109 # Find the test suite for this input and its relative path.
110 ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache)
112 litConfig.warning('unable to find test suite for %r' % path)
116 litConfig.note('resolved input %r to %r::%r' % (path, ts.name,
119 return ts, getTestsInSuite(ts, path_in_suite, litConfig,
120 testSuiteCache, localConfigCache)
122 def getTestsInSuite(ts, path_in_suite, litConfig,
123 testSuiteCache, localConfigCache):
124 # Check that the source path exists (errors here are reported by the
126 source_path = ts.getSourcePath(path_in_suite)
127 if not os.path.exists(source_path):
130 # Check if the user named a test directly.
131 if not os.path.isdir(source_path):
132 lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache)
133 yield Test.Test(ts, path_in_suite, lc)
136 # Otherwise we have a directory to search for tests, start by getting the
137 # local configuration.
138 lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache)
141 if lc.test_format is not None:
142 for res in lc.test_format.getTestsInDirectory(ts, path_in_suite,
146 # Search subdirectories.
147 for filename in os.listdir(source_path):
148 # FIXME: This doesn't belong here?
149 if filename in ('Output', '.svn', '.git') or filename in lc.excludes:
152 # Ignore non-directories.
153 file_sourcepath = os.path.join(source_path, filename)
154 if not os.path.isdir(file_sourcepath):
157 # Check for nested test suites, first in the execpath in case there is a
158 # site configuration and then in the source path.
159 subpath = path_in_suite + (filename,)
160 file_execpath = ts.getExecPath(subpath)
161 if dirContainsTestSuite(file_execpath, litConfig):
162 sub_ts, subpath_in_suite = getTestSuite(file_execpath, litConfig,
164 elif dirContainsTestSuite(file_sourcepath, litConfig):
165 sub_ts, subpath_in_suite = getTestSuite(file_sourcepath, litConfig,
170 # If the this directory recursively maps back to the current test suite,
171 # disregard it (this can happen if the exec root is located inside the
172 # current test suite, for example).
176 # Otherwise, load from the nested test suite, if present.
177 if sub_ts is not None:
178 subiter = getTestsInSuite(sub_ts, subpath_in_suite, litConfig,
179 testSuiteCache, localConfigCache)
181 subiter = getTestsInSuite(ts, subpath, litConfig, testSuiteCache,
189 litConfig.warning('test suite %r contained no tests' % sub_ts.name)
191 def find_tests_for_inputs(lit_config, inputs):
193 find_tests_for_inputs(lit_config, inputs) -> [Test]
195 Given a configuration object and a list of input specifiers, find all the
199 # Expand '@...' form in inputs.
202 if os.path.exists(input) or not input.startswith('@'):
203 actual_inputs.append(input)
210 actual_inputs.append(ln)
214 # Load the tests from the inputs.
216 test_suite_cache = {}
217 local_config_cache = {}
218 for input in actual_inputs:
220 tests.extend(getTests(input, lit_config,
221 test_suite_cache, local_config_cache)[1])
222 if prev == len(tests):
223 lit_config.warning('input %r contained no tests' % input)
225 # If there were any errors during test discovery, exit now.
226 if lit_config.numErrors:
227 sys.stderr.write('%d errors, exiting.\n' % lit_config.numErrors)
232 def load_test_suite(inputs):
235 from lit.LitTestCase import LitTestCase
237 # Create the global config object.
238 litConfig = LitConfig.LitConfig(progname = 'lit',
242 valgrindLeakCheck = False,
246 isWindows = (platform.system()=='Windows'),
249 # Perform test discovery.
250 run = lit.run.Run(litConfig, find_tests_for_inputs(litConfig, inputs))
252 # Return a unittest test suite which just runs the tests in order.
253 return unittest.TestSuite([LitTestCase(test, run)
254 for test in run.tests])