blob: c7e2b8c7d08a3b283d3adf8f442586d3cb1be6ae [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.
5"""
6
Greg Clayton2256d0d2014-03-24 23:01:57 +00007import multiprocessing
Todd Fiala3f0a3602014-07-08 06:42:37 +00008import os
9import platform
Vince Harron17f429f2014-12-13 00:08:19 +000010import shlex
11import subprocess
Todd Fiala3f0a3602014-07-08 06:42:37 +000012import sys
Steve Puccibefe2b12014-03-07 00:01:11 +000013
Johnny Chene8d9dc62011-10-31 19:04:07 +000014from optparse import OptionParser
15
Vince Harron17f429f2014-12-13 00:08:19 +000016def get_timeout_command():
17 if sys.platform.startswith("win32"):
18 return None
19 try:
20 subprocess.call("timeout")
21 return "timeout"
22 except OSError:
23 pass
24 try:
25 subprocess.call("gtimeout")
26 return "gtimeout"
27 except OSError:
28 pass
29 return None
30
31timeout_command = get_timeout_command()
32
33default_timeout = os.getenv("LLDB_TEST_TIMEOUT") or "5m"
34
35# Status codes for running command with timeout.
36eTimedOut, ePassed, eFailed = 124, 0, 1
37
38def call_with_timeout(command, timeout):
39 """Each test will timeout after 5 minutes by default.
40 Override the default timeout of 5 minutes with LLDB_TEST_TIMEOUT.
41 E.g., LLDB_TEST_TIMEOUT=10m
42 Override the timeout for individual tests with LLDB_[TEST NAME]_TIMEOUT.
43 E.g., LLDB_TESTCONCURRENTEVENTS_TIMEOUT=2m
44 Set to "0" to run without timeout."""
45 if timeout_command:
46 return subprocess.call([timeout_command, timeout] + command,
47 stdin=subprocess.PIPE)
48 return (ePassed if subprocess.call(command, stdin=subprocess.PIPE) == 0
49 else eFailed)
Johnny Chene8d9dc62011-10-31 19:04:07 +000050
Steve Puccibefe2b12014-03-07 00:01:11 +000051def process_dir(root, files, test_root, dotest_options):
52 """Examine a directory for tests, and invoke any found within it."""
Vince Harron17f429f2014-12-13 00:08:19 +000053 timed_out = []
Daniel Maleacbaef262013-02-15 21:31:37 +000054 failed = []
55 passed = []
Steve Puccibefe2b12014-03-07 00:01:11 +000056 for name in files:
57 path = os.path.join(root, name)
58
59 # We're only interested in the test file with the "Test*.py" naming pattern.
60 if not name.startswith("Test") or not name.endswith(".py"):
61 continue
62
63 # Neither a symbolically linked file.
64 if os.path.islink(path):
65 continue
66
Zachary Turnerf6896b02015-01-05 19:37:03 +000067 script_file = os.path.join(test_root, "dotest.py")
68 is_posix = (os.name == "posix")
69 split_args = shlex.split(dotest_options, posix=is_posix) if dotest_options else []
70 command = ([sys.executable, script_file] +
71 split_args +
Vince Harron17f429f2014-12-13 00:08:19 +000072 ["-p", name, root])
73
74 timeout_name = os.path.basename(os.path.splitext(name)[0]).upper()
75
76 timeout = os.getenv("LLDB_%s_TIMEOUT" % timeout_name) or default_timeout
77
78 exit_status = call_with_timeout(command, timeout)
79
80 if ePassed == exit_status:
Steve Puccibefe2b12014-03-07 00:01:11 +000081 passed.append(name)
Vince Harron17f429f2014-12-13 00:08:19 +000082 else:
83 if eTimedOut == exit_status:
84 timed_out.append(name)
85 failed.append(name)
86 return (timed_out, failed, passed)
Steve Puccibefe2b12014-03-07 00:01:11 +000087
88in_q = None
89out_q = None
90
Todd Fiala3f0a3602014-07-08 06:42:37 +000091def process_dir_worker(arg_tuple):
Steve Puccibefe2b12014-03-07 00:01:11 +000092 """Worker thread main loop when in multithreaded mode.
93 Takes one directory specification at a time and works on it."""
Todd Fiala3f0a3602014-07-08 06:42:37 +000094 (root, files, test_root, dotest_options) = arg_tuple
95 return process_dir(root, files, test_root, dotest_options)
Steve Puccibefe2b12014-03-07 00:01:11 +000096
97def walk_and_invoke(test_root, dotest_options, num_threads):
98 """Look for matched files and invoke test driver on each one.
99 In single-threaded mode, each test driver is invoked directly.
100 In multi-threaded mode, submit each test driver to a worker
101 queue, and then wait for all to complete."""
Todd Fiala3f0a3602014-07-08 06:42:37 +0000102
103 # Collect the test files that we'll run.
104 test_work_items = []
105 for root, dirs, files in os.walk(test_root, topdown=False):
106 test_work_items.append((root, files, test_root, dotest_options))
107
108 # Run the items, either in a pool (for multicore speedup) or
109 # calling each individually.
110 if num_threads > 1:
111 pool = multiprocessing.Pool(num_threads)
112 test_results = pool.map(process_dir_worker, test_work_items)
113 else:
114 test_results = []
115 for work_item in test_work_items:
116 test_results.append(process_dir_worker(work_item))
117
Vince Harron17f429f2014-12-13 00:08:19 +0000118 timed_out = []
Steve Puccibefe2b12014-03-07 00:01:11 +0000119 failed = []
120 passed = []
Todd Fiala3f0a3602014-07-08 06:42:37 +0000121
122 for test_result in test_results:
Vince Harron17f429f2014-12-13 00:08:19 +0000123 (dir_timed_out, dir_failed, dir_passed) = test_result
124 timed_out += dir_timed_out
Todd Fiala3f0a3602014-07-08 06:42:37 +0000125 failed += dir_failed
126 passed += dir_passed
127
Vince Harron17f429f2014-12-13 00:08:19 +0000128 return (timed_out, failed, passed)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000129
130def main():
Johnny Chene8d9dc62011-10-31 19:04:07 +0000131 test_root = sys.path[0]
132
133 parser = OptionParser(usage="""\
134Run lldb test suite using a separate process for each test file.
135""")
136 parser.add_option('-o', '--options',
137 type='string', action='store',
138 dest='dotest_options',
139 help="""The options passed to 'dotest.py' if specified.""")
140
Greg Clayton2256d0d2014-03-24 23:01:57 +0000141 parser.add_option('-t', '--threads',
142 type='int',
143 dest='num_threads',
Ed Mastecec2a5b2014-11-21 02:41:25 +0000144 help="""The number of threads to use when running tests separately.""")
Greg Clayton2256d0d2014-03-24 23:01:57 +0000145
Johnny Chene8d9dc62011-10-31 19:04:07 +0000146 opts, args = parser.parse_args()
147 dotest_options = opts.dotest_options
Ed Mastecec2a5b2014-11-21 02:41:25 +0000148
149 if opts.num_threads:
150 num_threads = opts.num_threads
151 else:
Greg Clayton2256d0d2014-03-24 23:01:57 +0000152 num_threads_str = os.environ.get("LLDB_TEST_THREADS")
153 if num_threads_str:
154 num_threads = int(num_threads_str)
Greg Clayton2256d0d2014-03-24 23:01:57 +0000155 else:
Ed Mastecec2a5b2014-11-21 02:41:25 +0000156 num_threads = multiprocessing.cpu_count()
157 if num_threads < 1:
158 num_threads = 1
Johnny Chene8d9dc62011-10-31 19:04:07 +0000159
Daniel Maleab42556f2013-04-19 18:32:53 +0000160 system_info = " ".join(platform.uname())
Vince Harron17f429f2014-12-13 00:08:19 +0000161 (timed_out, failed, passed) = walk_and_invoke(test_root, dotest_options,
162 num_threads)
163 timed_out = set(timed_out)
Daniel Maleacbaef262013-02-15 21:31:37 +0000164 num_tests = len(failed) + len(passed)
Daniel Maleab42556f2013-04-19 18:32:53 +0000165
Daniel Maleacbaef262013-02-15 21:31:37 +0000166 print "Ran %d tests." % num_tests
167 if len(failed) > 0:
Shawn Best13491c42014-10-22 19:29:00 +0000168 failed.sort()
Daniel Maleacbaef262013-02-15 21:31:37 +0000169 print "Failing Tests (%d)" % len(failed)
170 for f in failed:
Vince Harron17f429f2014-12-13 00:08:19 +0000171 print "%s: LLDB (suite) :: %s (%s)" % (
172 "TIMEOUT" if f in timed_out else "FAIL", f, system_info
173 )
Daniel Maleacbaef262013-02-15 21:31:37 +0000174 sys.exit(1)
175 sys.exit(0)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000176
177if __name__ == '__main__':
178 main()