]> git.proxmox.com Git - rustc.git/blob - src/llvm/utils/lit/lit/discovery.py
Imported Upstream version 1.0.0+dfsg1
[rustc.git] / src / llvm / utils / lit / lit / discovery.py
1 """
2 Test discovery functions.
3 """
4
5 import copy
6 import os
7 import sys
8
9 import lit.run
10 from lit.TestingConfig import TestingConfig
11 from lit import LitConfig, Test
12
13 def dirContainsTestSuite(path, lit_config):
14 cfgpath = os.path.join(path, lit_config.site_config_name)
15 if os.path.exists(cfgpath):
16 return cfgpath
17 cfgpath = os.path.join(path, lit_config.config_name)
18 if os.path.exists(cfgpath):
19 return cfgpath
20
21 def getTestSuite(item, litConfig, cache):
22 """getTestSuite(item, litConfig, cache) -> (suite, relative_path)
23
24 Find the test suite containing @arg item.
25
26 @retval (None, ...) - Indicates no test suite contains @arg item.
27 @retval (suite, relative_path) - The suite that @arg item is in, and its
28 relative path inside that suite.
29 """
30 def search1(path):
31 # Check for a site config or a lit config.
32 cfgpath = dirContainsTestSuite(path, litConfig)
33
34 # If we didn't find a config file, keep looking.
35 if not cfgpath:
36 parent,base = os.path.split(path)
37 if parent == path:
38 return (None, ())
39
40 ts, relative = search(parent)
41 return (ts, relative + (base,))
42
43 # We found a test suite, create a new config for it and load it.
44 if litConfig.debug:
45 litConfig.note('loading suite config %r' % cfgpath)
46
47 cfg = TestingConfig.fromdefaults(litConfig)
48 cfg.load_from_path(cfgpath, litConfig)
49 source_root = os.path.realpath(cfg.test_source_root or path)
50 exec_root = os.path.realpath(cfg.test_exec_root or path)
51 return Test.TestSuite(cfg.name, source_root, exec_root, cfg), ()
52
53 def search(path):
54 # Check for an already instantiated test suite.
55 res = cache.get(path)
56 if res is None:
57 cache[path] = res = search1(path)
58 return res
59
60 # Canonicalize the path.
61 item = os.path.realpath(item)
62
63 # Skip files and virtual components.
64 components = []
65 while not os.path.isdir(item):
66 parent,base = os.path.split(item)
67 if parent == item:
68 return (None, ())
69 components.append(base)
70 item = parent
71 components.reverse()
72
73 ts, relative = search(item)
74 return ts, tuple(relative + tuple(components))
75
76 def getLocalConfig(ts, path_in_suite, litConfig, cache):
77 def search1(path_in_suite):
78 # Get the parent config.
79 if not path_in_suite:
80 parent = ts.config
81 else:
82 parent = search(path_in_suite[:-1])
83
84 # Check if there is a local configuration file.
85 source_path = ts.getSourcePath(path_in_suite)
86 cfgpath = os.path.join(source_path, litConfig.local_config_name)
87
88 # If not, just reuse the parent config.
89 if not os.path.exists(cfgpath):
90 return parent
91
92 # Otherwise, copy the current config and load the local configuration
93 # file into it.
94 config = copy.deepcopy(parent)
95 if litConfig.debug:
96 litConfig.note('loading local config %r' % cfgpath)
97 config.load_from_path(cfgpath, litConfig)
98 return config
99
100 def search(path_in_suite):
101 key = (ts, path_in_suite)
102 res = cache.get(key)
103 if res is None:
104 cache[key] = res = search1(path_in_suite)
105 return res
106
107 return search(path_in_suite)
108
109 def getTests(path, litConfig, testSuiteCache, localConfigCache):
110 # Find the test suite for this input and its relative path.
111 ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache)
112 if ts is None:
113 litConfig.warning('unable to find test suite for %r' % path)
114 return (),()
115
116 if litConfig.debug:
117 litConfig.note('resolved input %r to %r::%r' % (path, ts.name,
118 path_in_suite))
119
120 return ts, getTestsInSuite(ts, path_in_suite, litConfig,
121 testSuiteCache, localConfigCache)
122
123 def getTestsInSuite(ts, path_in_suite, litConfig,
124 testSuiteCache, localConfigCache):
125 # Check that the source path exists (errors here are reported by the
126 # caller).
127 source_path = ts.getSourcePath(path_in_suite)
128 if not os.path.exists(source_path):
129 return
130
131 # Check if the user named a test directly.
132 if not os.path.isdir(source_path):
133 lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache)
134 yield Test.Test(ts, path_in_suite, lc)
135 return
136
137 # Otherwise we have a directory to search for tests, start by getting the
138 # local configuration.
139 lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache)
140
141 # Search for tests.
142 if lc.test_format is not None:
143 for res in lc.test_format.getTestsInDirectory(ts, path_in_suite,
144 litConfig, lc):
145 yield res
146
147 # Search subdirectories.
148 for filename in os.listdir(source_path):
149 # FIXME: This doesn't belong here?
150 if filename in ('Output', '.svn', '.git') or filename in lc.excludes:
151 continue
152
153 # Ignore non-directories.
154 file_sourcepath = os.path.join(source_path, filename)
155 if not os.path.isdir(file_sourcepath):
156 continue
157
158 # Check for nested test suites, first in the execpath in case there is a
159 # site configuration and then in the source path.
160 subpath = path_in_suite + (filename,)
161 file_execpath = ts.getExecPath(subpath)
162 if dirContainsTestSuite(file_execpath, litConfig):
163 sub_ts, subpath_in_suite = getTestSuite(file_execpath, litConfig,
164 testSuiteCache)
165 elif dirContainsTestSuite(file_sourcepath, litConfig):
166 sub_ts, subpath_in_suite = getTestSuite(file_sourcepath, litConfig,
167 testSuiteCache)
168 else:
169 sub_ts = None
170
171 # If the this directory recursively maps back to the current test suite,
172 # disregard it (this can happen if the exec root is located inside the
173 # current test suite, for example).
174 if sub_ts is ts:
175 continue
176
177 # Otherwise, load from the nested test suite, if present.
178 if sub_ts is not None:
179 subiter = getTestsInSuite(sub_ts, subpath_in_suite, litConfig,
180 testSuiteCache, localConfigCache)
181 else:
182 subiter = getTestsInSuite(ts, subpath, litConfig, testSuiteCache,
183 localConfigCache)
184
185 N = 0
186 for res in subiter:
187 N += 1
188 yield res
189 if sub_ts and not N:
190 litConfig.warning('test suite %r contained no tests' % sub_ts.name)
191
192 def find_tests_for_inputs(lit_config, inputs):
193 """
194 find_tests_for_inputs(lit_config, inputs) -> [Test]
195
196 Given a configuration object and a list of input specifiers, find all the
197 tests to execute.
198 """
199
200 # Expand '@...' form in inputs.
201 actual_inputs = []
202 for input in inputs:
203 if input.startswith('@'):
204 f = open(input[1:])
205 try:
206 for ln in f:
207 ln = ln.strip()
208 if ln:
209 actual_inputs.append(ln)
210 finally:
211 f.close()
212 else:
213 actual_inputs.append(input)
214
215 # Load the tests from the inputs.
216 tests = []
217 test_suite_cache = {}
218 local_config_cache = {}
219 for input in actual_inputs:
220 prev = len(tests)
221 tests.extend(getTests(input, lit_config,
222 test_suite_cache, local_config_cache)[1])
223 if prev == len(tests):
224 lit_config.warning('input %r contained no tests' % input)
225
226 # If there were any errors during test discovery, exit now.
227 if lit_config.numErrors:
228 sys.stderr.write('%d errors, exiting.\n' % lit_config.numErrors)
229 sys.exit(2)
230
231 return tests
232
233 def load_test_suite(inputs):
234 import platform
235 import unittest
236 from lit.LitTestCase import LitTestCase
237
238 # Create the global config object.
239 litConfig = LitConfig.LitConfig(progname = 'lit',
240 path = [],
241 quiet = False,
242 useValgrind = False,
243 valgrindLeakCheck = False,
244 valgrindArgs = [],
245 noExecute = False,
246 debug = False,
247 isWindows = (platform.system()=='Windows'),
248 params = {})
249
250 # Perform test discovery.
251 run = lit.run.Run(litConfig, find_tests_for_inputs(litConfig, inputs))
252
253 # Return a unittest test suite which just runs the tests in order.
254 return unittest.TestSuite([LitTestCase(test, run)
255 for test in run.tests])