blob: f70d595ab2e5d91a243caf1a556c0f8cf76a9f20 [file] [log] [blame]
Daniel Dunbar42ea4632010-09-15 03:57:04 +00001# -*- Python -*-
2
3# Configuration file for the 'lit' test runner.
4
5import os
6import platform
7import tempfile
8import signal
9import subprocess
10
11class LibcxxTestFormat(lit.formats.FileBasedTest):
12 """
13 Custom test format handler for use with the test format use by libc++.
14
15 Tests fall into two categories:
16 FOO.pass.cpp - Executable test which should compile, run, and exit with
17 code 0.
18 FOO.fail.cpp - Negative test case which is expected to fail compilation.
19 """
20
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000021 def __init__(self, cxx_under_test, cpp_flags, ld_flags):
Daniel Dunbarbc9a8482010-09-15 04:11:29 +000022 self.cxx_under_test = cxx_under_test
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000023 self.cpp_flags = list(cpp_flags)
24 self.ld_flags = list(ld_flags)
Daniel Dunbar42ea4632010-09-15 03:57:04 +000025
26 def execute_command(self, command):
27 p = subprocess.Popen(command, stdin=subprocess.PIPE,
28 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
29 out,err = p.communicate()
30 exitCode = p.wait()
31
32 # Detect Ctrl-C in subprocess.
33 if exitCode == -signal.SIGINT:
34 raise KeyboardInterrupt
35
36 return out, err, exitCode
37
38 def execute(self, test, lit_config):
39 name = test.path_in_suite[-1]
40 source_path = test.getSourcePath()
41
42 # Check what kind of test this is.
43 assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
44 expected_compile_fail = name.endswith('.fail.cpp')
45
46 # If this is a compile (failure) test, build it and check for failure.
47 if expected_compile_fail:
48 cmd = [self.cxx_under_test, '-c',
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000049 '-o', '/dev/null', source_path] + self.cpp_flags
Daniel Dunbar42ea4632010-09-15 03:57:04 +000050 out, err, exitCode = self.execute_command(cmd)
51 if exitCode == 1:
52 return lit.Test.PASS, ""
53 else:
54 report = """Command: %s\n""" % ' '.join(["'%s'" % a
55 for a in cmd])
56 report += """Exit Code: %d\n""" % exitCode
57 if out:
58 report += """Standard Output:\n--\n%s--""" % out
59 if err:
60 report += """Standard Error:\n--\n%s--""" % err
61 report += "\n\nExpected compilation to fail!"
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000062 return lit.Test.FAIL, report
Daniel Dunbar42ea4632010-09-15 03:57:04 +000063 else:
64 exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
65 exec_path = exec_file.name
66 exec_file.close()
67
68 try:
69 cmd = [self.cxx_under_test, '-o', exec_path,
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +000070 source_path] + self.cpp_flags + self.ld_flags
Daniel Dunbar42ea4632010-09-15 03:57:04 +000071 out, err, exitCode = self.execute_command(cmd)
72 if exitCode != 0:
Daniel Dunbar42ea4632010-09-15 03:57:04 +000073 report = """Command: %s\n""" % ' '.join(["'%s'" % a
74 for a in cmd])
75 report += """Exit Code: %d\n""" % exitCode
76 if out:
77 report += """Standard Output:\n--\n%s--""" % out
78 if err:
79 report += """Standard Error:\n--\n%s--""" % err
80 report += "\n\nCompilation failed unexpectedly!"
81 return lit.Test.FAIL, report
82
83 cmd = [exec_path]
84 out, err, exitCode = self.execute_command(cmd)
85 if exitCode != 0:
Daniel Dunbar42ea4632010-09-15 03:57:04 +000086 report = """Command: %s\n""" % ' '.join(["'%s'" % a
87 for a in cmd])
88 report += """Exit Code: %d\n""" % exitCode
89 if out:
90 report += """Standard Output:\n--\n%s--""" % out
91 if err:
92 report += """Standard Error:\n--\n%s--""" % err
93 report += "\n\nCompiled test failed unexpectedly!"
94 return lit.Test.FAIL, report
95 finally:
96 try:
97 os.remove(exec_path)
98 except:
99 pass
100 return lit.Test.PASS, ""
101
102# name: The name of this test suite.
103config.name = 'libc++'
104
105# suffixes: A list of file extensions to treat as test files.
106config.suffixes = ['.cpp']
107
108# test_source_root: The root path where tests are located.
109config.test_source_root = os.path.dirname(__file__)
110
111# FIXME: Would be nice to Use -stdlib=libc++ option with Clang's that accept it.
112cxx_under_test = lit.params.get('cxx_under_test', None)
113if cxx_under_test is None:
114 lit.fatal('must specify user parameter cxx_under_test '
115 '(e.g., --param=cxx_under_test=clang++)')
116config.test_format = LibcxxTestFormat(cxx_under_test,
Daniel Dunbar5f09d9e02010-09-15 04:31:58 +0000117 cpp_flags = ['-nostdinc++',
118 '-I/usr/include/c++/v1'],
119 ld_flags = ['-nodefaultlibs', '-lc++',
120 '-lSystem'])
Daniel Dunbar42ea4632010-09-15 03:57:04 +0000121
122config.target_triple = None