blob: 023ac4a118930274ce1a498d3410d47a08fb1ac3 [file] [log] [blame]
Daniel Dunbar62b94392013-02-12 19:28:51 +00001# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
Daniel Dunbar42ea4632010-09-15 03:57:04 +00002
3# Configuration file for the 'lit' test runner.
4
Daniel Dunbarb6b3e502013-08-30 19:52:12 +00005import errno
Dan Alberta85b27f2014-08-04 18:44:48 +00006import locale
Daniel Dunbar42ea4632010-09-15 03:57:04 +00007import os
8import platform
Daniel Dunbarb6b3e502013-08-30 19:52:12 +00009import re
10import shlex
Daniel Dunbar42ea4632010-09-15 03:57:04 +000011import signal
12import subprocess
Daniel Dunbarb6b3e502013-08-30 19:52:12 +000013import sys
14import tempfile
Howard Hinnant3778f272013-01-14 17:12:54 +000015import time
Daniel Dunbar42ea4632010-09-15 03:57:04 +000016
Daniel Dunbar4a381292013-08-09 14:44:11 +000017import lit.Test
18import lit.formats
19import lit.util
20
Daniel Dunbar42ea4632010-09-15 03:57:04 +000021class LibcxxTestFormat(lit.formats.FileBasedTest):
22 """
23 Custom test format handler for use with the test format use by libc++.
24
25 Tests fall into two categories:
26 FOO.pass.cpp - Executable test which should compile, run, and exit with
27 code 0.
28 FOO.fail.cpp - Negative test case which is expected to fail compilation.
29 """
30
Justin Bogner33a2a2e2014-09-03 04:32:08 +000031 def __init__(self, cxx_under_test, use_verify_for_fail,
32 cpp_flags, ld_flags, exec_env):
Daniel Dunbarbc9a8482010-09-15 04:11:29 +000033 self.cxx_under_test = cxx_under_test
Justin Bogner33a2a2e2014-09-03 04:32:08 +000034 self.use_verify_for_fail = use_verify_for_fail
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000035 self.cpp_flags = list(cpp_flags)
36 self.ld_flags = list(ld_flags)
Daniel Dunbar84958712013-02-05 18:03:49 +000037 self.exec_env = dict(exec_env)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000038
Howard Hinnant3778f272013-01-14 17:12:54 +000039 def execute_command(self, command, in_dir=None):
40 kwargs = {
41 'stdin' :subprocess.PIPE,
42 'stdout':subprocess.PIPE,
43 'stderr':subprocess.PIPE,
44 }
45 if in_dir:
46 kwargs['cwd'] = in_dir
47 p = subprocess.Popen(command, **kwargs)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000048 out,err = p.communicate()
49 exitCode = p.wait()
50
51 # Detect Ctrl-C in subprocess.
52 if exitCode == -signal.SIGINT:
53 raise KeyboardInterrupt
54
55 return out, err, exitCode
56
57 def execute(self, test, lit_config):
Howard Hinnant3778f272013-01-14 17:12:54 +000058 while True:
59 try:
60 return self._execute(test, lit_config)
61 except OSError, oe:
62 if oe.errno != errno.ETXTBSY:
63 raise
64 time.sleep(0.1)
65
66 def _execute(self, test, lit_config):
Daniel Dunbarf51f0312013-02-05 21:03:25 +000067 # Extract test metadata from the test file.
Daniel Dunbarf51f0312013-02-05 21:03:25 +000068 requires = []
Eric Fiselier339bdc32014-08-18 06:43:06 +000069 unsupported = []
Daniel Dunbarf51f0312013-02-05 21:03:25 +000070 with open(test.getSourcePath()) as f:
71 for ln in f:
72 if 'XFAIL:' in ln:
73 items = ln[ln.index('XFAIL:') + 6:].split(',')
Daniel Dunbar019c5902013-08-21 23:06:32 +000074 test.xfails.extend([s.strip() for s in items])
Daniel Dunbarf51f0312013-02-05 21:03:25 +000075 elif 'REQUIRES:' in ln:
76 items = ln[ln.index('REQUIRES:') + 9:].split(',')
77 requires.extend([s.strip() for s in items])
Eric Fiselier339bdc32014-08-18 06:43:06 +000078 elif 'UNSUPPORTED:' in ln:
79 items = ln[ln.index('UNSUPPORTED:') + 12:].split(',')
80 unsupported.extend([s.strip() for s in items])
Eric Fiselier993dfb12014-07-31 22:56:52 +000081 elif not ln.strip().startswith("//") and ln.strip():
Daniel Dunbarf51f0312013-02-05 21:03:25 +000082 # Stop at the first non-empty line that is not a C++
83 # comment.
84 break
85
86 # Check that we have the required features.
87 #
88 # FIXME: For now, this is cribbed from lit.TestRunner, to avoid
89 # introducing a dependency there. What we more ideally would like to do
Daniel Dunbar019c5902013-08-21 23:06:32 +000090 # is lift the "requires" handling to be a core lit framework feature.
Daniel Dunbarf51f0312013-02-05 21:03:25 +000091 missing_required_features = [f for f in requires
92 if f not in test.config.available_features]
93 if missing_required_features:
94 return (lit.Test.UNSUPPORTED,
95 "Test requires the following features: %s" % (
96 ', '.join(missing_required_features),))
97
Eric Fiselier339bdc32014-08-18 06:43:06 +000098 unsupported_features = [f for f in unsupported
99 if f in test.config.available_features]
100 if unsupported_features:
101 return (lit.Test.UNSUPPORTED,
102 "Test is unsupported with the following features: %s" % (
103 ', '.join(unsupported_features),))
104
Daniel Dunbarf51f0312013-02-05 21:03:25 +0000105 # Evaluate the test.
Daniel Dunbar019c5902013-08-21 23:06:32 +0000106 return self._evaluate_test(test, lit_config)
Daniel Dunbarf51f0312013-02-05 21:03:25 +0000107
108 def _evaluate_test(self, test, lit_config):
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000109 name = test.path_in_suite[-1]
110 source_path = test.getSourcePath()
Howard Hinnant3778f272013-01-14 17:12:54 +0000111 source_dir = os.path.dirname(source_path)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000112
113 # Check what kind of test this is.
114 assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
115 expected_compile_fail = name.endswith('.fail.cpp')
116
117 # If this is a compile (failure) test, build it and check for failure.
118 if expected_compile_fail:
119 cmd = [self.cxx_under_test, '-c',
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000120 '-o', '/dev/null', source_path] + self.cpp_flags
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000121 expected_rc = 1
122 if self.use_verify_for_fail:
123 cmd += ['-Xclang', '-verify']
124 expected_rc = 0
125 out, err, rc = self.execute_command(cmd)
126 if rc == expected_rc:
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000127 return lit.Test.PASS, ""
128 else:
129 report = """Command: %s\n""" % ' '.join(["'%s'" % a
130 for a in cmd])
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000131 report += """Exit Code: %d\n""" % rc
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000132 if out:
133 report += """Standard Output:\n--\n%s--""" % out
134 if err:
135 report += """Standard Error:\n--\n%s--""" % err
136 report += "\n\nExpected compilation to fail!"
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000137 return lit.Test.FAIL, report
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000138 else:
139 exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
140 exec_path = exec_file.name
141 exec_file.close()
142
143 try:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000144 compile_cmd = [self.cxx_under_test, '-o', exec_path,
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000145 source_path] + self.cpp_flags + self.ld_flags
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000146 cmd = compile_cmd
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000147 out, err, exitCode = self.execute_command(cmd)
148 if exitCode != 0:
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000149 report = """Command: %s\n""" % ' '.join(["'%s'" % a
150 for a in cmd])
151 report += """Exit Code: %d\n""" % exitCode
152 if out:
153 report += """Standard Output:\n--\n%s--""" % out
154 if err:
155 report += """Standard Error:\n--\n%s--""" % err
156 report += "\n\nCompilation failed unexpectedly!"
157 return lit.Test.FAIL, report
158
Daniel Dunbar84958712013-02-05 18:03:49 +0000159 cmd = []
160 if self.exec_env:
161 cmd.append('env')
162 cmd.extend('%s=%s' % (name, value)
163 for name,value in self.exec_env.items())
164 cmd.append(exec_path)
Howard Hinnantc1a45fb2012-08-02 18:36:47 +0000165 if lit_config.useValgrind:
166 cmd = lit_config.valgrindArgs + cmd
Howard Hinnant3778f272013-01-14 17:12:54 +0000167 out, err, exitCode = self.execute_command(cmd, source_dir)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000168 if exitCode != 0:
Daniel Dunbar62b94392013-02-12 19:28:51 +0000169 report = """Compiled With: %s\n""" % \
170 ' '.join(["'%s'" % a for a in compile_cmd])
171 report += """Command: %s\n""" % \
172 ' '.join(["'%s'" % a for a in cmd])
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000173 report += """Exit Code: %d\n""" % exitCode
174 if out:
175 report += """Standard Output:\n--\n%s--""" % out
176 if err:
177 report += """Standard Error:\n--\n%s--""" % err
178 report += "\n\nCompiled test failed unexpectedly!"
179 return lit.Test.FAIL, report
180 finally:
181 try:
182 os.remove(exec_path)
183 except:
184 pass
185 return lit.Test.PASS, ""
186
Dan Albertae2526b2014-08-21 17:30:44 +0000187
188class Configuration(object):
189 def __init__(self, lit_config, config):
190 self.lit_config = lit_config
191 self.config = config
192 self.cxx = None
193 self.src_root = None
194 self.obj_root = None
195 self.env = {}
196 self.compile_flags = []
197 self.link_flags = []
198 self.use_system_lib = False
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000199 self.use_clang_verify = False
Dan Albertae2526b2014-08-21 17:30:44 +0000200
201 if platform.system() not in ('Darwin', 'FreeBSD', 'Linux'):
202 self.lit_config.fatal("unrecognized system")
203
204 def get_lit_conf(self, name, default=None):
205 val = self.lit_config.params.get(name, None)
206 if val is None:
207 val = getattr(self.config, name, None)
208 if val is None:
209 val = default
210 return val
211
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000212 def get_lit_bool(self, name):
213 conf = self.get_lit_conf(name)
214 if conf is None:
215 return None
216 if conf.lower() in ('1', 'true'):
217 return True
218 if conf.lower() in ('', '0', 'false'):
219 return False
220 self.lit_config.fatal(
221 "parameter '{}' should be true or false".format(name))
222
Dan Albertae2526b2014-08-21 17:30:44 +0000223 def configure(self):
224 self.configure_cxx()
225 self.configure_triple()
226 self.configure_src_root()
227 self.configure_obj_root()
228 self.configure_use_system_lib()
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000229 self.configure_use_clang_verify()
Dan Albertae2526b2014-08-21 17:30:44 +0000230 self.configure_env()
231 self.configure_std_flag()
232 self.configure_compile_flags()
233 self.configure_link_flags()
234 self.configure_sanitizer()
235 self.configure_features()
236
237 def get_test_format(self):
238 return LibcxxTestFormat(
239 self.cxx,
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000240 self.use_clang_verify,
Dan Albertae2526b2014-08-21 17:30:44 +0000241 cpp_flags=['-nostdinc++'] + self.compile_flags,
242 ld_flags=['-nodefaultlibs'] + self.link_flags,
243 exec_env=self.env)
244
245 def configure_cxx(self):
246 # Gather various compiler parameters.
247 self.cxx = self.get_lit_conf('cxx_under_test')
248
249 # If no specific cxx_under_test was given, attempt to infer it as
250 # clang++.
251 if self.cxx is None:
252 clangxx = lit.util.which('clang++',
253 self.config.environment['PATH'])
254 if clangxx:
255 self.cxx = clangxx
256 self.lit_config.note(
257 "inferred cxx_under_test as: %r" % self.cxx)
258 if not self.cxx:
259 self.lit_config.fatal('must specify user parameter cxx_under_test '
260 '(e.g., --param=cxx_under_test=clang++)')
261
262 def configure_src_root(self):
263 self.src_root = self.get_lit_conf(
264 'libcxx_src_root', os.path.dirname(self.config.test_source_root))
265
266 def configure_obj_root(self):
267 self.obj_root = self.get_lit_conf('libcxx_obj_root', self.src_root)
268
269 def configure_use_system_lib(self):
270 # This test suite supports testing against either the system library or
271 # the locally built one; the former mode is useful for testing ABI
272 # compatibility between the current headers and a shipping dynamic
273 # library.
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000274 self.use_system_lib = self.get_lit_bool('use_system_lib')
275 if self.use_system_lib is None:
Dan Albertae2526b2014-08-21 17:30:44 +0000276 # Default to testing against the locally built libc++ library.
277 self.use_system_lib = False
278 self.lit_config.note(
279 "inferred use_system_lib as: %r" % self.use_system_lib)
280
Justin Bogner33a2a2e2014-09-03 04:32:08 +0000281 def configure_use_clang_verify(self):
282 '''If set, run clang with -verify on failing tests.'''
283 self.use_clang_verify = self.get_lit_bool('use_clang_verify')
284 if self.use_clang_verify is None:
285 # TODO: Default this to True when using clang.
286 self.use_clang_verify = False
287 self.lit_config.note(
288 "inferred use_clang_verify as: %r" % self.use_clang_verify)
289
Dan Albertae2526b2014-08-21 17:30:44 +0000290 def configure_features(self):
291 # Figure out which of the required locales we support
292 locales = {
293 'Darwin': {
294 'en_US.UTF-8': 'en_US.UTF-8',
295 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
296 'fr_FR.UTF-8': 'fr_FR.UTF-8',
297 'fr_CA.ISO8859-1': 'cs_CZ.ISO8859-1',
298 'ru_RU.UTF-8': 'ru_RU.UTF-8',
299 'zh_CN.UTF-8': 'zh_CN.UTF-8',
300 },
301 'FreeBSD': {
302 'en_US.UTF-8': 'en_US.UTF-8',
303 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
304 'fr_FR.UTF-8': 'fr_FR.UTF-8',
305 'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1',
306 'ru_RU.UTF-8': 'ru_RU.UTF-8',
307 'zh_CN.UTF-8': 'zh_CN.UTF-8',
308 },
309 'Linux': {
310 'en_US.UTF-8': 'en_US.UTF-8',
311 'cs_CZ.ISO8859-2': 'cs_CZ.ISO-8859-2',
312 'fr_FR.UTF-8': 'fr_FR.UTF-8',
313 'fr_CA.ISO8859-1': 'fr_CA.ISO-8859-1',
314 'ru_RU.UTF-8': 'ru_RU.UTF-8',
315 'zh_CN.UTF-8': 'zh_CN.UTF-8',
316 },
317 'Windows': {
318 'en_US.UTF-8': 'English_United States.1252',
319 'cs_CZ.ISO8859-2': 'Czech_Czech Republic.1250',
320 'fr_FR.UTF-8': 'French_France.1252',
321 'fr_CA.ISO8859-1': 'French_Canada.1252',
322 'ru_RU.UTF-8': 'Russian_Russia.1251',
323 'zh_CN.UTF-8': 'Chinese_China.936',
324 },
325 }
326
327 default_locale = locale.setlocale(locale.LC_ALL)
328 for feature, loc in locales[platform.system()].items():
329 try:
330 locale.setlocale(locale.LC_ALL, loc)
Eric Fiselier561dfb52014-08-23 04:02:21 +0000331 self.config.available_features.add('locale.{0}'.format(feature))
Dan Albertae2526b2014-08-21 17:30:44 +0000332 except:
Eric Fiselier561dfb52014-08-23 04:02:21 +0000333 self.lit_config.warning('The locale {0} is not supported by '
Dan Albertae2526b2014-08-21 17:30:44 +0000334 'your platform. Some tests will be '
335 'unsupported.'.format(loc))
336 locale.setlocale(locale.LC_ALL, default_locale)
337
338 # Write an "available feature" that combines the triple when
339 # use_system_lib is enabled. This is so that we can easily write XFAIL
340 # markers for tests that are known to fail with versions of libc++ as
341 # were shipped with a particular triple.
342 if self.use_system_lib:
343 # Drop sub-major version components from the triple, because the
344 # current XFAIL handling expects exact matches for feature checks.
345 sanitized_triple = re.sub(
346 r"([^-]+)-([^-]+)-([^-.]+).*", r"\1-\2-\3",
347 self.config.target_triple)
348 self.config.available_features.add(
349 'with_system_lib=%s' % sanitized_triple)
350
351 def configure_compile_flags(self):
352 # Configure extra compiler flags.
353 self.compile_flags += ['-I' + self.src_root + '/include',
354 '-I' + self.src_root + '/test/support']
355
356 def configure_link_flags(self):
357 self.link_flags += ['-L' + self.obj_root + '/lib', '-lc++']
358 link_flags_str = self.get_lit_conf('link_flags')
359 if link_flags_str is None:
360 cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
361 if cxx_abi == 'libstdc++':
362 self.link_flags += ['-lstdc++']
363 elif cxx_abi == 'libsupc++':
364 self.link_flags += ['-lsupc++']
365 elif cxx_abi == 'libcxxabi':
366 self.link_flags += ['-lc++abi']
367 elif cxx_abi == 'libcxxrt':
368 self.link_flags += ['-lcxxrt']
369 elif cxx_abi == 'none':
370 pass
371 else:
372 self.lit_config.fatal(
373 'C++ ABI setting %s unsupported for tests' % cxx_abi)
374
375 if sys.platform == 'darwin':
376 self.link_flags += ['-lSystem']
377 elif sys.platform == 'linux2':
378 self.link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread',
379 '-lrt', '-lgcc_s']
380 elif sys.platform.startswith('freebsd'):
381 self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
382 else:
383 self.lit_config.fatal("unrecognized system")
384
385 self.lit_config.note(
386 "inferred link_flags as: %r" % self.link_flags)
387 if link_flags_str:
388 self.link_flags += shlex.split(link_flags_str)
389
390 if sys.platform == 'linux2':
391 if not self.use_system_lib:
392 self.link_flags += ['-Wl,-R', self.obj_root + '/lib']
393 self.compile_flags += ['-D__STDC_FORMAT_MACROS',
394 '-D__STDC_LIMIT_MACROS',
395 '-D__STDC_CONSTANT_MACROS']
396 elif sys.platform.startswith('freebsd'):
397 if not self.use_system_lib:
398 self.link_flags += ['-Wl,-R', self.obj_root + '/lib']
399
400 def configure_std_flag(self):
401 # Try and get the std version from the command line. Fall back to
402 # default given in lit.site.cfg is not present. If default is not
403 # present then force c++11.
404 std = self.get_lit_conf('std')
405 if std is None:
406 std = 'c++11'
407 self.lit_config.note('using default std: \'-std=c++11\'')
Eric Fiselier561dfb52014-08-23 04:02:21 +0000408 self.compile_flags += ['-std={0}'.format(std)]
Dan Albertae2526b2014-08-21 17:30:44 +0000409 self.config.available_features.add(std)
410
411 def configure_sanitizer(self):
412 san = self.get_lit_conf('llvm_use_sanitizer', '').strip()
413 if san:
414 self.compile_flags += ['-fno-omit-frame-pointer']
415 if san == 'Address':
416 self.compile_flags += ['-fsanitize=address']
417 self.config.available_features.add('asan')
418 elif san == 'Memory' or san == 'MemoryWithOrigins':
419 self.compile_flags += ['-fsanitize=memory']
420 if san == 'MemoryWithOrigins':
421 self.compile_flags += ['-fsanitize-memory-track-origins']
422 self.config.available_features.add('msan')
423 else:
424 self.lit_config.fatal('unsupported value for '
Eric Fiselier561dfb52014-08-23 04:02:21 +0000425 'libcxx_use_san: {0}'.format(san))
Dan Albertae2526b2014-08-21 17:30:44 +0000426
427 def configure_triple(self):
428 # Get or infer the target triple.
429 self.config.target_triple = self.get_lit_conf('target_triple')
430 # If no target triple was given, try to infer it from the compiler
431 # under test.
432 if not self.config.target_triple:
433 self.config.target_triple = lit.util.capture(
434 [self.cxx, '-dumpmachine']).strip()
435 self.lit_config.note(
436 "inferred target_triple as: %r" % self.config.target_triple)
437
438 def configure_env(self):
439 # Configure extra linker parameters.
440 if sys.platform == 'darwin':
441 if not self.use_system_lib:
442 self.env['DYLD_LIBRARY_PATH'] = os.path.join(self.obj_root,
443 'lib')
444
445
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000446# name: The name of this test suite.
447config.name = 'libc++'
448
449# suffixes: A list of file extensions to treat as test files.
450config.suffixes = ['.cpp']
451
452# test_source_root: The root path where tests are located.
453config.test_source_root = os.path.dirname(__file__)
454
Dan Albertae2526b2014-08-21 17:30:44 +0000455configuration = Configuration(lit_config, config)
456configuration.configure()
457config.test_format = configuration.get_test_format()