blob: 0c74a7d0f0810f2fca9083d32c432ad113c0b21d [file] [log] [blame]
Daniel Dunbar42ea4632010-09-15 03:57:04 +00001# -*- Python -*-
2
3# Configuration file for the 'lit' test runner.
4
5import os
Michael J. Spencerf5799be2010-12-10 19:47:54 +00006import sys
Daniel Dunbar42ea4632010-09-15 03:57:04 +00007import platform
8import tempfile
9import signal
10import subprocess
Howard Hinnant3778f272013-01-14 17:12:54 +000011import errno
12import time
Daniel Dunbar42ea4632010-09-15 03:57:04 +000013
Daniel Dunbarf51f0312013-02-05 21:03:25 +000014# FIXME: For now, this is cribbed from lit.TestRunner, to avoid introducing a
15# dependency there. What we more ideally would like to do is lift the "xfail"
16# and "requires" handling to be a core lit framework feature.
17def isExpectedFail(test, xfails):
18 # Check if any of the xfails match an available feature or the target.
19 for item in xfails:
20 # If this is the wildcard, it always fails.
21 if item == '*':
22 return True
23
24 # If this is an exact match for one of the features, it fails.
25 if item in test.config.available_features:
26 return True
27
28 # If this is a part of the target triple, it fails.
29 if item in test.suite.config.target_triple:
30 return True
31
32 return False
33
Daniel Dunbar42ea4632010-09-15 03:57:04 +000034class LibcxxTestFormat(lit.formats.FileBasedTest):
35 """
36 Custom test format handler for use with the test format use by libc++.
37
38 Tests fall into two categories:
39 FOO.pass.cpp - Executable test which should compile, run, and exit with
40 code 0.
41 FOO.fail.cpp - Negative test case which is expected to fail compilation.
42 """
43
Daniel Dunbar84958712013-02-05 18:03:49 +000044 def __init__(self, cxx_under_test, cpp_flags, ld_flags, exec_env):
Daniel Dunbarbc9a8482010-09-15 04:11:29 +000045 self.cxx_under_test = cxx_under_test
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000046 self.cpp_flags = list(cpp_flags)
47 self.ld_flags = list(ld_flags)
Daniel Dunbar84958712013-02-05 18:03:49 +000048 self.exec_env = dict(exec_env)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000049
Howard Hinnant3778f272013-01-14 17:12:54 +000050 def execute_command(self, command, in_dir=None):
51 kwargs = {
52 'stdin' :subprocess.PIPE,
53 'stdout':subprocess.PIPE,
54 'stderr':subprocess.PIPE,
55 }
56 if in_dir:
57 kwargs['cwd'] = in_dir
58 p = subprocess.Popen(command, **kwargs)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000059 out,err = p.communicate()
60 exitCode = p.wait()
61
62 # Detect Ctrl-C in subprocess.
63 if exitCode == -signal.SIGINT:
64 raise KeyboardInterrupt
65
66 return out, err, exitCode
67
68 def execute(self, test, lit_config):
Howard Hinnant3778f272013-01-14 17:12:54 +000069 while True:
70 try:
71 return self._execute(test, lit_config)
72 except OSError, oe:
73 if oe.errno != errno.ETXTBSY:
74 raise
75 time.sleep(0.1)
76
77 def _execute(self, test, lit_config):
Daniel Dunbarf51f0312013-02-05 21:03:25 +000078 # Extract test metadata from the test file.
79 xfails = []
80 requires = []
81 with open(test.getSourcePath()) as f:
82 for ln in f:
83 if 'XFAIL:' in ln:
84 items = ln[ln.index('XFAIL:') + 6:].split(',')
85 xfails.extend([s.strip() for s in items])
86 elif 'REQUIRES:' in ln:
87 items = ln[ln.index('REQUIRES:') + 9:].split(',')
88 requires.extend([s.strip() for s in items])
89 elif not ln.startswith("//") and ln.strip():
90 # Stop at the first non-empty line that is not a C++
91 # comment.
92 break
93
94 # Check that we have the required features.
95 #
96 # FIXME: For now, this is cribbed from lit.TestRunner, to avoid
97 # introducing a dependency there. What we more ideally would like to do
98 # is lift the "xfail" and "requires" handling to be a core lit framework
99 # feature.
100 missing_required_features = [f for f in requires
101 if f not in test.config.available_features]
102 if missing_required_features:
103 return (lit.Test.UNSUPPORTED,
104 "Test requires the following features: %s" % (
105 ', '.join(missing_required_features),))
106
107 # Determine if this test is an expected failure.
108 isXFail = isExpectedFail(test, xfails)
109
110 # Evaluate the test.
111 result, report = self._evaluate_test(test, lit_config)
112
113 # Convert the test result based on whether this is an expected failure.
114 if isXFail:
115 if result != lit.Test.FAIL:
116 report += "\n\nTest was expected to FAIL, but did not.\n"
117 result = lit.Test.XPASS
118 else:
119 result = lit.Test.XFAIL
120
121 return result, report
122
123 def _evaluate_test(self, test, lit_config):
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000124 name = test.path_in_suite[-1]
125 source_path = test.getSourcePath()
Howard Hinnant3778f272013-01-14 17:12:54 +0000126 source_dir = os.path.dirname(source_path)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000127
128 # Check what kind of test this is.
129 assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
130 expected_compile_fail = name.endswith('.fail.cpp')
131
132 # If this is a compile (failure) test, build it and check for failure.
133 if expected_compile_fail:
134 cmd = [self.cxx_under_test, '-c',
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000135 '-o', '/dev/null', source_path] + self.cpp_flags
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000136 out, err, exitCode = self.execute_command(cmd)
137 if exitCode == 1:
138 return lit.Test.PASS, ""
139 else:
140 report = """Command: %s\n""" % ' '.join(["'%s'" % a
141 for a in cmd])
142 report += """Exit Code: %d\n""" % exitCode
143 if out:
144 report += """Standard Output:\n--\n%s--""" % out
145 if err:
146 report += """Standard Error:\n--\n%s--""" % err
147 report += "\n\nExpected compilation to fail!"
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000148 return lit.Test.FAIL, report
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000149 else:
150 exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
151 exec_path = exec_file.name
152 exec_file.close()
153
154 try:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000155 compile_cmd = [self.cxx_under_test, '-o', exec_path,
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000156 source_path] + self.cpp_flags + self.ld_flags
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000157 cmd = compile_cmd
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000158 out, err, exitCode = self.execute_command(cmd)
159 if exitCode != 0:
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000160 report = """Command: %s\n""" % ' '.join(["'%s'" % a
161 for a in cmd])
162 report += """Exit Code: %d\n""" % exitCode
163 if out:
164 report += """Standard Output:\n--\n%s--""" % out
165 if err:
166 report += """Standard Error:\n--\n%s--""" % err
167 report += "\n\nCompilation failed unexpectedly!"
168 return lit.Test.FAIL, report
169
Daniel Dunbar84958712013-02-05 18:03:49 +0000170 cmd = []
171 if self.exec_env:
172 cmd.append('env')
173 cmd.extend('%s=%s' % (name, value)
174 for name,value in self.exec_env.items())
175 cmd.append(exec_path)
Howard Hinnantc1a45fb2012-08-02 18:36:47 +0000176 if lit_config.useValgrind:
177 cmd = lit_config.valgrindArgs + cmd
Howard Hinnant3778f272013-01-14 17:12:54 +0000178 out, err, exitCode = self.execute_command(cmd, source_dir)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000179 if exitCode != 0:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000180 report = """Compiled With: %s\n""" % ' '.join(["'%s'" % a
181 for a in compile_cmd])
182 report += """Command: %s\n""" % ' '.join(["'%s'" % a
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000183 for a in cmd])
184 report += """Exit Code: %d\n""" % exitCode
185 if out:
186 report += """Standard Output:\n--\n%s--""" % out
187 if err:
188 report += """Standard Error:\n--\n%s--""" % err
189 report += "\n\nCompiled test failed unexpectedly!"
190 return lit.Test.FAIL, report
191 finally:
192 try:
193 os.remove(exec_path)
194 except:
195 pass
196 return lit.Test.PASS, ""
197
198# name: The name of this test suite.
199config.name = 'libc++'
200
201# suffixes: A list of file extensions to treat as test files.
202config.suffixes = ['.cpp']
203
204# test_source_root: The root path where tests are located.
205config.test_source_root = os.path.dirname(__file__)
206
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000207# Gather various compiler parameters.
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000208cxx_under_test = lit.params.get('cxx_under_test', None)
209if cxx_under_test is None:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000210 cxx_under_test = getattr(config, 'cxx_under_test', None)
211 if cxx_under_test is None:
212 lit.fatal('must specify user parameter cxx_under_test '
213 '(e.g., --param=cxx_under_test=clang++)')
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000214
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000215libcxx_src_root = lit.params.get('libcxx_src_root', None)
216if libcxx_src_root is None:
217 libcxx_src_root = getattr(config, 'libcxx_src_root', None)
218 if libcxx_src_root is None:
219 libcxx_src_root = os.path.dirname(config.test_source_root)
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000220
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000221libcxx_obj_root = lit.params.get('libcxx_obj_root', None)
222if libcxx_obj_root is None:
223 libcxx_obj_root = getattr(config, 'libcxx_obj_root', None)
224 if libcxx_obj_root is None:
225 libcxx_obj_root = libcxx_src_root
226
227cxx_has_stdcxx0x_flag_str = lit.params.get('cxx_has_stdcxx0x_flag', None)
228if cxx_has_stdcxx0x_flag_str is not None:
Daniel Dunbar84958712013-02-05 18:03:49 +0000229 if cxx_has_stdcxx0x_flag_str.lower() in ('1', 'true'):
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000230 cxx_has_stdcxx0x_flag = True
Daniel Dunbar84958712013-02-05 18:03:49 +0000231 elif cxx_has_stdcxx0x_flag_str.lower() in ('', '0', 'false'):
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000232 cxx_has_stdcxx0x_flag = False
233 else:
234 lit.fatal('user parameter cxx_has_stdcxx0x_flag_str should be 0 or 1')
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000235else:
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000236 cxx_has_stdcxx0x_flag = getattr(config, 'cxx_has_stdcxx0x_flag', True)
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000237
Daniel Dunbar84958712013-02-05 18:03:49 +0000238# This test suite supports testing against either the system library or the
239# locally built one; the former mode is useful for testing ABI compatibility
240# between the current headers and a shipping dynamic library. We require the
241# user to explicitly pick one of the two modes.
242use_system_lib_str = lit.params.get('use_system_lib', None)
243if use_system_lib_str is not None:
244 if use_system_lib_str.lower() in ('1', 'true'):
245 use_system_lib = True
246 elif use_system_lib_str.lower() in ('', '0', 'false'):
247 use_system_lib = False
248 else:
249 lit.fatal('user parameter use_system_lib should be 0 or 1')
250else:
251 use_system_lib = True
252
Chandler Carruthce395a92011-01-23 01:05:20 +0000253# Configure extra compiler flags.
Howard Hinnantf1e633c2013-01-14 17:07:27 +0000254include_paths = ['-I' + libcxx_src_root + '/include', '-I' + libcxx_src_root + '/test/support']
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000255library_paths = ['-L' + libcxx_obj_root + '/lib']
Chandler Carruthce395a92011-01-23 01:05:20 +0000256compile_flags = []
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000257if cxx_has_stdcxx0x_flag:
Daniel Dunbar84958712013-02-05 18:03:49 +0000258 compile_flags += ['-std=c++0x']
Chandler Carruthce395a92011-01-23 01:05:20 +0000259
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000260# Configure extra libraries.
Daniel Dunbar84958712013-02-05 18:03:49 +0000261exec_env = {}
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000262libraries = []
263if sys.platform == 'darwin':
Daniel Dunbar84958712013-02-05 18:03:49 +0000264 libraries += ['-lSystem']
265 if not use_system_lib:
266 exec_env['DYLD_LIBRARY_PATH'] = os.path.join(libcxx_obj_root, 'lib')
267elif sys.platform == 'linux2':
268 libraries += ['-lsupc++', '-lgcc_eh', '-lc', '-lm', '-lpthread', '-lrt', '-lgcc_s']
269 libraries += ['-Wl,-R', libcxx_obj_root + '/lib']
270else:
271 lit.fatal("unrecognized system")
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000272
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000273config.test_format = LibcxxTestFormat(
274 cxx_under_test,
275 cpp_flags = ['-nostdinc++'] + compile_flags + include_paths,
Daniel Dunbar84958712013-02-05 18:03:49 +0000276 ld_flags = ['-nodefaultlibs'] + library_paths + ['-lc++'] + libraries,
277 exec_env = exec_env)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000278
Daniel Dunbarb6354a02013-02-05 22:28:03 +0000279# Get or infer the target triple.
280config.target_triple = lit.params.get('target_triple', None)
281# If no target triple was given, try to infer it from the compiler under test.
282if config.target_triple is None:
283 config.target_triple = lit.util.capture(
284 [cxx_under_test, '-dumpmachine']).strip()
285 lit.note("inferred target triple as: %r" % (config.target_triple,))
Daniel Dunbar582c97d2013-02-05 21:43:30 +0000286
287# Write an "available feature" that combines the triple when use_system_lib is
288# enabled. This is so that we can easily write XFAIL markers for tests that are
289# known to fail with versions of libc++ as were shipped with a particular
290# triple.
291if use_system_lib:
292 config.available_features.add('with_system_lib=%s' % (
293 config.target_triple,))