blob: fc4b8ff074e37175ad95e229774ae478ba3ab755 [file] [log] [blame]
Johnny Chene8d9dc62011-10-31 19:04:07 +00001#!/usr/bin/env python
2
3"""
4Run the test suite using a separate process for each test file.
Vince Harronede59652015-01-08 02:11:26 +00005
6Each test will run with a time limit of 5 minutes by default.
7
8Override the default time limit of 5 minutes by setting
9the environment variable LLDB_TEST_TIMEOUT.
10
11E.g., export LLDB_TEST_TIMEOUT=10m
12
13Override the time limit for individual tests by setting
14the environment variable LLDB_[TEST NAME]_TIMEOUT.
15
16E.g., export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=2m
17
18Set to "0" to run without time limit.
19
20E.g., export LLDB_TEST_TIMEOUT=0
21or export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=0
Johnny Chene8d9dc62011-10-31 19:04:07 +000022"""
23
Greg Clayton2256d0d2014-03-24 23:01:57 +000024import multiprocessing
Todd Fiala3f0a3602014-07-08 06:42:37 +000025import os
26import platform
Vince Harron17f429f2014-12-13 00:08:19 +000027import shlex
28import subprocess
Todd Fiala3f0a3602014-07-08 06:42:37 +000029import sys
Steve Puccibefe2b12014-03-07 00:01:11 +000030
Johnny Chene8d9dc62011-10-31 19:04:07 +000031from optparse import OptionParser
32
Vince Harron17f429f2014-12-13 00:08:19 +000033def get_timeout_command():
Vince Harronede59652015-01-08 02:11:26 +000034 """Search for a suitable timeout command."""
Vince Harron17f429f2014-12-13 00:08:19 +000035 if sys.platform.startswith("win32"):
36 return None
37 try:
38 subprocess.call("timeout")
39 return "timeout"
40 except OSError:
41 pass
42 try:
43 subprocess.call("gtimeout")
44 return "gtimeout"
45 except OSError:
46 pass
47 return None
48
49timeout_command = get_timeout_command()
50
51default_timeout = os.getenv("LLDB_TEST_TIMEOUT") or "5m"
52
53# Status codes for running command with timeout.
54eTimedOut, ePassed, eFailed = 124, 0, 1
55
56def call_with_timeout(command, timeout):
Vince Harronede59652015-01-08 02:11:26 +000057 """Run command with a timeout if possible."""
58 if timeout_command and timeout != "0":
Vince Harron17f429f2014-12-13 00:08:19 +000059 return subprocess.call([timeout_command, timeout] + command,
60 stdin=subprocess.PIPE)
61 return (ePassed if subprocess.call(command, stdin=subprocess.PIPE) == 0
62 else eFailed)
Johnny Chene8d9dc62011-10-31 19:04:07 +000063
Steve Puccibefe2b12014-03-07 00:01:11 +000064def process_dir(root, files, test_root, dotest_options):
65 """Examine a directory for tests, and invoke any found within it."""
Vince Harron17f429f2014-12-13 00:08:19 +000066 timed_out = []
Daniel Maleacbaef262013-02-15 21:31:37 +000067 failed = []
68 passed = []
Steve Puccibefe2b12014-03-07 00:01:11 +000069 for name in files:
70 path = os.path.join(root, name)
71
72 # We're only interested in the test file with the "Test*.py" naming pattern.
73 if not name.startswith("Test") or not name.endswith(".py"):
74 continue
75
76 # Neither a symbolically linked file.
77 if os.path.islink(path):
78 continue
79
Zachary Turnerf6896b02015-01-05 19:37:03 +000080 script_file = os.path.join(test_root, "dotest.py")
81 is_posix = (os.name == "posix")
82 split_args = shlex.split(dotest_options, posix=is_posix) if dotest_options else []
83 command = ([sys.executable, script_file] +
84 split_args +
Vince Harron17f429f2014-12-13 00:08:19 +000085 ["-p", name, root])
86
87 timeout_name = os.path.basename(os.path.splitext(name)[0]).upper()
88
89 timeout = os.getenv("LLDB_%s_TIMEOUT" % timeout_name) or default_timeout
90
91 exit_status = call_with_timeout(command, timeout)
92
93 if ePassed == exit_status:
Steve Puccibefe2b12014-03-07 00:01:11 +000094 passed.append(name)
Vince Harron17f429f2014-12-13 00:08:19 +000095 else:
96 if eTimedOut == exit_status:
97 timed_out.append(name)
98 failed.append(name)
99 return (timed_out, failed, passed)
Steve Puccibefe2b12014-03-07 00:01:11 +0000100
101in_q = None
102out_q = None
103
Todd Fiala3f0a3602014-07-08 06:42:37 +0000104def process_dir_worker(arg_tuple):
Steve Puccibefe2b12014-03-07 00:01:11 +0000105 """Worker thread main loop when in multithreaded mode.
106 Takes one directory specification at a time and works on it."""
Todd Fiala3f0a3602014-07-08 06:42:37 +0000107 (root, files, test_root, dotest_options) = arg_tuple
108 return process_dir(root, files, test_root, dotest_options)
Steve Puccibefe2b12014-03-07 00:01:11 +0000109
110def walk_and_invoke(test_root, dotest_options, num_threads):
111 """Look for matched files and invoke test driver on each one.
112 In single-threaded mode, each test driver is invoked directly.
113 In multi-threaded mode, submit each test driver to a worker
114 queue, and then wait for all to complete."""
Todd Fiala3f0a3602014-07-08 06:42:37 +0000115
116 # Collect the test files that we'll run.
117 test_work_items = []
118 for root, dirs, files in os.walk(test_root, topdown=False):
119 test_work_items.append((root, files, test_root, dotest_options))
120
121 # Run the items, either in a pool (for multicore speedup) or
122 # calling each individually.
123 if num_threads > 1:
124 pool = multiprocessing.Pool(num_threads)
125 test_results = pool.map(process_dir_worker, test_work_items)
126 else:
127 test_results = []
128 for work_item in test_work_items:
129 test_results.append(process_dir_worker(work_item))
130
Vince Harron17f429f2014-12-13 00:08:19 +0000131 timed_out = []
Steve Puccibefe2b12014-03-07 00:01:11 +0000132 failed = []
133 passed = []
Todd Fiala3f0a3602014-07-08 06:42:37 +0000134
135 for test_result in test_results:
Vince Harron17f429f2014-12-13 00:08:19 +0000136 (dir_timed_out, dir_failed, dir_passed) = test_result
137 timed_out += dir_timed_out
Todd Fiala3f0a3602014-07-08 06:42:37 +0000138 failed += dir_failed
139 passed += dir_passed
140
Vince Harron17f429f2014-12-13 00:08:19 +0000141 return (timed_out, failed, passed)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000142
143def main():
Johnny Chene8d9dc62011-10-31 19:04:07 +0000144 test_root = sys.path[0]
145
146 parser = OptionParser(usage="""\
147Run lldb test suite using a separate process for each test file.
Vince Harronede59652015-01-08 02:11:26 +0000148
149 Each test will run with a time limit of 5 minutes by default.
150
151 Override the default time limit of 5 minutes by setting
152 the environment variable LLDB_TEST_TIMEOUT.
153
154 E.g., export LLDB_TEST_TIMEOUT=10m
155
156 Override the time limit for individual tests by setting
157 the environment variable LLDB_[TEST NAME]_TIMEOUT.
158
159 E.g., export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=2m
160
161 Set to "0" to run without time limit.
162
163 E.g., export LLDB_TEST_TIMEOUT=0
164 or export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=0
Johnny Chene8d9dc62011-10-31 19:04:07 +0000165""")
166 parser.add_option('-o', '--options',
167 type='string', action='store',
168 dest='dotest_options',
169 help="""The options passed to 'dotest.py' if specified.""")
170
Greg Clayton2256d0d2014-03-24 23:01:57 +0000171 parser.add_option('-t', '--threads',
172 type='int',
173 dest='num_threads',
Ed Mastecec2a5b2014-11-21 02:41:25 +0000174 help="""The number of threads to use when running tests separately.""")
Greg Clayton2256d0d2014-03-24 23:01:57 +0000175
Johnny Chene8d9dc62011-10-31 19:04:07 +0000176 opts, args = parser.parse_args()
177 dotest_options = opts.dotest_options
Ed Mastecec2a5b2014-11-21 02:41:25 +0000178
179 if opts.num_threads:
180 num_threads = opts.num_threads
181 else:
Greg Clayton2256d0d2014-03-24 23:01:57 +0000182 num_threads_str = os.environ.get("LLDB_TEST_THREADS")
183 if num_threads_str:
184 num_threads = int(num_threads_str)
Greg Clayton2256d0d2014-03-24 23:01:57 +0000185 else:
Ed Mastecec2a5b2014-11-21 02:41:25 +0000186 num_threads = multiprocessing.cpu_count()
187 if num_threads < 1:
188 num_threads = 1
Johnny Chene8d9dc62011-10-31 19:04:07 +0000189
Daniel Maleab42556f2013-04-19 18:32:53 +0000190 system_info = " ".join(platform.uname())
Vince Harron17f429f2014-12-13 00:08:19 +0000191 (timed_out, failed, passed) = walk_and_invoke(test_root, dotest_options,
192 num_threads)
193 timed_out = set(timed_out)
Daniel Maleacbaef262013-02-15 21:31:37 +0000194 num_tests = len(failed) + len(passed)
Daniel Maleab42556f2013-04-19 18:32:53 +0000195
Daniel Maleacbaef262013-02-15 21:31:37 +0000196 print "Ran %d tests." % num_tests
197 if len(failed) > 0:
Shawn Best13491c42014-10-22 19:29:00 +0000198 failed.sort()
Daniel Maleacbaef262013-02-15 21:31:37 +0000199 print "Failing Tests (%d)" % len(failed)
200 for f in failed:
Vince Harron17f429f2014-12-13 00:08:19 +0000201 print "%s: LLDB (suite) :: %s (%s)" % (
202 "TIMEOUT" if f in timed_out else "FAIL", f, system_info
203 )
Daniel Maleacbaef262013-02-15 21:31:37 +0000204 sys.exit(1)
205 sys.exit(0)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000206
207if __name__ == '__main__':
208 main()