blob: 89d84932a5e57e209dd8a527165107865774c6f2 [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
14class LibcxxTestFormat(lit.formats.FileBasedTest):
15 """
16 Custom test format handler for use with the test format use by libc++.
17
18 Tests fall into two categories:
19 FOO.pass.cpp - Executable test which should compile, run, and exit with
20 code 0.
21 FOO.fail.cpp - Negative test case which is expected to fail compilation.
22 """
23
Daniel Dunbar84958712013-02-05 18:03:49 +000024 def __init__(self, cxx_under_test, cpp_flags, ld_flags, exec_env):
Daniel Dunbarbc9a8482010-09-15 04:11:29 +000025 self.cxx_under_test = cxx_under_test
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000026 self.cpp_flags = list(cpp_flags)
27 self.ld_flags = list(ld_flags)
Daniel Dunbar84958712013-02-05 18:03:49 +000028 self.exec_env = dict(exec_env)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000029
Howard Hinnant3778f272013-01-14 17:12:54 +000030 def execute_command(self, command, in_dir=None):
31 kwargs = {
32 'stdin' :subprocess.PIPE,
33 'stdout':subprocess.PIPE,
34 'stderr':subprocess.PIPE,
35 }
36 if in_dir:
37 kwargs['cwd'] = in_dir
38 p = subprocess.Popen(command, **kwargs)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000039 out,err = p.communicate()
40 exitCode = p.wait()
41
42 # Detect Ctrl-C in subprocess.
43 if exitCode == -signal.SIGINT:
44 raise KeyboardInterrupt
45
46 return out, err, exitCode
47
48 def execute(self, test, lit_config):
Howard Hinnant3778f272013-01-14 17:12:54 +000049 while True:
50 try:
51 return self._execute(test, lit_config)
52 except OSError, oe:
53 if oe.errno != errno.ETXTBSY:
54 raise
55 time.sleep(0.1)
56
57 def _execute(self, test, lit_config):
Daniel Dunbar42ea4632010-09-15 03:57:04 +000058 name = test.path_in_suite[-1]
59 source_path = test.getSourcePath()
Howard Hinnant3778f272013-01-14 17:12:54 +000060 source_dir = os.path.dirname(source_path)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000061
62 # Check what kind of test this is.
63 assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
64 expected_compile_fail = name.endswith('.fail.cpp')
65
66 # If this is a compile (failure) test, build it and check for failure.
67 if expected_compile_fail:
68 cmd = [self.cxx_under_test, '-c',
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000069 '-o', '/dev/null', source_path] + self.cpp_flags
Daniel Dunbar42ea4632010-09-15 03:57:04 +000070 out, err, exitCode = self.execute_command(cmd)
71 if exitCode == 1:
72 return lit.Test.PASS, ""
73 else:
74 report = """Command: %s\n""" % ' '.join(["'%s'" % a
75 for a in cmd])
76 report += """Exit Code: %d\n""" % exitCode
77 if out:
78 report += """Standard Output:\n--\n%s--""" % out
79 if err:
80 report += """Standard Error:\n--\n%s--""" % err
81 report += "\n\nExpected compilation to fail!"
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000082 return lit.Test.FAIL, report
Daniel Dunbar42ea4632010-09-15 03:57:04 +000083 else:
84 exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
85 exec_path = exec_file.name
86 exec_file.close()
87
88 try:
Michael J. Spencerf5799be2010-12-10 19:47:54 +000089 compile_cmd = [self.cxx_under_test, '-o', exec_path,
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000090 source_path] + self.cpp_flags + self.ld_flags
Michael J. Spencerf5799be2010-12-10 19:47:54 +000091 cmd = compile_cmd
Daniel Dunbar42ea4632010-09-15 03:57:04 +000092 out, err, exitCode = self.execute_command(cmd)
93 if exitCode != 0:
Daniel Dunbar42ea4632010-09-15 03:57:04 +000094 report = """Command: %s\n""" % ' '.join(["'%s'" % a
95 for a in cmd])
96 report += """Exit Code: %d\n""" % exitCode
97 if out:
98 report += """Standard Output:\n--\n%s--""" % out
99 if err:
100 report += """Standard Error:\n--\n%s--""" % err
101 report += "\n\nCompilation failed unexpectedly!"
102 return lit.Test.FAIL, report
103
Daniel Dunbar84958712013-02-05 18:03:49 +0000104 cmd = []
105 if self.exec_env:
106 cmd.append('env')
107 cmd.extend('%s=%s' % (name, value)
108 for name,value in self.exec_env.items())
109 cmd.append(exec_path)
Howard Hinnantc1a45fb2012-08-02 18:36:47 +0000110 if lit_config.useValgrind:
111 cmd = lit_config.valgrindArgs + cmd
Howard Hinnant3778f272013-01-14 17:12:54 +0000112 out, err, exitCode = self.execute_command(cmd, source_dir)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000113 if exitCode != 0:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000114 report = """Compiled With: %s\n""" % ' '.join(["'%s'" % a
115 for a in compile_cmd])
116 report += """Command: %s\n""" % ' '.join(["'%s'" % a
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000117 for a in cmd])
118 report += """Exit Code: %d\n""" % exitCode
119 if out:
120 report += """Standard Output:\n--\n%s--""" % out
121 if err:
122 report += """Standard Error:\n--\n%s--""" % err
123 report += "\n\nCompiled test failed unexpectedly!"
124 return lit.Test.FAIL, report
125 finally:
126 try:
127 os.remove(exec_path)
128 except:
129 pass
130 return lit.Test.PASS, ""
131
132# name: The name of this test suite.
133config.name = 'libc++'
134
135# suffixes: A list of file extensions to treat as test files.
136config.suffixes = ['.cpp']
137
138# test_source_root: The root path where tests are located.
139config.test_source_root = os.path.dirname(__file__)
140
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000141# Gather various compiler parameters.
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000142cxx_under_test = lit.params.get('cxx_under_test', None)
143if cxx_under_test is None:
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000144 cxx_under_test = getattr(config, 'cxx_under_test', None)
145 if cxx_under_test is None:
146 lit.fatal('must specify user parameter cxx_under_test '
147 '(e.g., --param=cxx_under_test=clang++)')
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000148
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000149libcxx_src_root = lit.params.get('libcxx_src_root', None)
150if libcxx_src_root is None:
151 libcxx_src_root = getattr(config, 'libcxx_src_root', None)
152 if libcxx_src_root is None:
153 libcxx_src_root = os.path.dirname(config.test_source_root)
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000154
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000155libcxx_obj_root = lit.params.get('libcxx_obj_root', None)
156if libcxx_obj_root is None:
157 libcxx_obj_root = getattr(config, 'libcxx_obj_root', None)
158 if libcxx_obj_root is None:
159 libcxx_obj_root = libcxx_src_root
160
161cxx_has_stdcxx0x_flag_str = lit.params.get('cxx_has_stdcxx0x_flag', None)
162if cxx_has_stdcxx0x_flag_str is not None:
Daniel Dunbar84958712013-02-05 18:03:49 +0000163 if cxx_has_stdcxx0x_flag_str.lower() in ('1', 'true'):
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000164 cxx_has_stdcxx0x_flag = True
Daniel Dunbar84958712013-02-05 18:03:49 +0000165 elif cxx_has_stdcxx0x_flag_str.lower() in ('', '0', 'false'):
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000166 cxx_has_stdcxx0x_flag = False
167 else:
168 lit.fatal('user parameter cxx_has_stdcxx0x_flag_str should be 0 or 1')
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000169else:
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000170 cxx_has_stdcxx0x_flag = getattr(config, 'cxx_has_stdcxx0x_flag', True)
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000171
Daniel Dunbar84958712013-02-05 18:03:49 +0000172# This test suite supports testing against either the system library or the
173# locally built one; the former mode is useful for testing ABI compatibility
174# between the current headers and a shipping dynamic library. We require the
175# user to explicitly pick one of the two modes.
176use_system_lib_str = lit.params.get('use_system_lib', None)
177if use_system_lib_str is not None:
178 if use_system_lib_str.lower() in ('1', 'true'):
179 use_system_lib = True
180 elif use_system_lib_str.lower() in ('', '0', 'false'):
181 use_system_lib = False
182 else:
183 lit.fatal('user parameter use_system_lib should be 0 or 1')
184else:
185 use_system_lib = True
186
Chandler Carruthce395a92011-01-23 01:05:20 +0000187# Configure extra compiler flags.
Howard Hinnantf1e633c2013-01-14 17:07:27 +0000188include_paths = ['-I' + libcxx_src_root + '/include', '-I' + libcxx_src_root + '/test/support']
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000189library_paths = ['-L' + libcxx_obj_root + '/lib']
Chandler Carruthce395a92011-01-23 01:05:20 +0000190compile_flags = []
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000191if cxx_has_stdcxx0x_flag:
Daniel Dunbar84958712013-02-05 18:03:49 +0000192 compile_flags += ['-std=c++0x']
Chandler Carruthce395a92011-01-23 01:05:20 +0000193
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000194# Configure extra libraries.
Daniel Dunbar84958712013-02-05 18:03:49 +0000195exec_env = {}
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000196libraries = []
197if sys.platform == 'darwin':
Daniel Dunbar84958712013-02-05 18:03:49 +0000198 libraries += ['-lSystem']
199 if not use_system_lib:
200 exec_env['DYLD_LIBRARY_PATH'] = os.path.join(libcxx_obj_root, 'lib')
201elif sys.platform == 'linux2':
202 libraries += ['-lsupc++', '-lgcc_eh', '-lc', '-lm', '-lpthread', '-lrt', '-lgcc_s']
203 libraries += ['-Wl,-R', libcxx_obj_root + '/lib']
204else:
205 lit.fatal("unrecognized system")
Michael J. Spencerf5799be2010-12-10 19:47:54 +0000206
Daniel Dunbar7c4b8532012-11-27 23:56:28 +0000207config.test_format = LibcxxTestFormat(
208 cxx_under_test,
209 cpp_flags = ['-nostdinc++'] + compile_flags + include_paths,
Daniel Dunbar84958712013-02-05 18:03:49 +0000210 ld_flags = ['-nodefaultlibs'] + library_paths + ['-lc++'] + libraries,
211 exec_env = exec_env)
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000212
213config.target_triple = None