blob: 60e18a7a0a58cbb9d870e30bba18a60a6cf3d467 [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
Siva Chandra2d7832e2015-05-08 23:08:53 +00006Each test will run with a time limit of 10 minutes by default.
Vince Harronede59652015-01-08 02:11:26 +00007
Siva Chandra2d7832e2015-05-08 23:08:53 +00008Override the default time limit of 10 minutes by setting
Vince Harronede59652015-01-08 02:11:26 +00009the 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 Harron06381732015-05-12 23:10:36 +000027import re
Vince Harron17f429f2014-12-13 00:08:19 +000028import shlex
29import subprocess
Todd Fiala3f0a3602014-07-08 06:42:37 +000030import sys
Steve Puccibefe2b12014-03-07 00:01:11 +000031
Johnny Chene8d9dc62011-10-31 19:04:07 +000032from optparse import OptionParser
33
Vince Harron17f429f2014-12-13 00:08:19 +000034def get_timeout_command():
Vince Harronede59652015-01-08 02:11:26 +000035 """Search for a suitable timeout command."""
Vince Harron17f429f2014-12-13 00:08:19 +000036 if sys.platform.startswith("win32"):
37 return None
38 try:
39 subprocess.call("timeout")
40 return "timeout"
41 except OSError:
42 pass
43 try:
44 subprocess.call("gtimeout")
45 return "gtimeout"
46 except OSError:
47 pass
48 return None
49
50timeout_command = get_timeout_command()
51
Siva Chandra2d7832e2015-05-08 23:08:53 +000052default_timeout = os.getenv("LLDB_TEST_TIMEOUT") or "10m"
Vince Harron17f429f2014-12-13 00:08:19 +000053
54# Status codes for running command with timeout.
55eTimedOut, ePassed, eFailed = 124, 0, 1
56
57def call_with_timeout(command, timeout):
Vince Harronede59652015-01-08 02:11:26 +000058 """Run command with a timeout if possible."""
Zachary Turnerdc494d52015-02-07 00:14:55 +000059 if os.name != "nt":
60 if timeout_command and timeout != "0":
61 return subprocess.call([timeout_command, timeout] + command,
62 stdin=subprocess.PIPE, close_fds=True)
63 return (ePassed if subprocess.call(command, stdin=subprocess.PIPE, close_fds=True) == 0
64 else eFailed)
65 else:
66 if timeout_command and timeout != "0":
67 return subprocess.call([timeout_command, timeout] + command,
68 stdin=subprocess.PIPE)
69 return (ePassed if subprocess.call(command, stdin=subprocess.PIPE) == 0
70 else eFailed)
Johnny Chene8d9dc62011-10-31 19:04:07 +000071
Steve Puccibefe2b12014-03-07 00:01:11 +000072def process_dir(root, files, test_root, dotest_options):
73 """Examine a directory for tests, and invoke any found within it."""
Vince Harron17f429f2014-12-13 00:08:19 +000074 timed_out = []
Daniel Maleacbaef262013-02-15 21:31:37 +000075 failed = []
76 passed = []
Steve Puccibefe2b12014-03-07 00:01:11 +000077 for name in files:
78 path = os.path.join(root, name)
79
80 # We're only interested in the test file with the "Test*.py" naming pattern.
81 if not name.startswith("Test") or not name.endswith(".py"):
82 continue
83
84 # Neither a symbolically linked file.
85 if os.path.islink(path):
86 continue
87
Zachary Turnerf6896b02015-01-05 19:37:03 +000088 script_file = os.path.join(test_root, "dotest.py")
89 is_posix = (os.name == "posix")
90 split_args = shlex.split(dotest_options, posix=is_posix) if dotest_options else []
91 command = ([sys.executable, script_file] +
92 split_args +
Vince Harron17f429f2014-12-13 00:08:19 +000093 ["-p", name, root])
94
95 timeout_name = os.path.basename(os.path.splitext(name)[0]).upper()
96
97 timeout = os.getenv("LLDB_%s_TIMEOUT" % timeout_name) or default_timeout
98
99 exit_status = call_with_timeout(command, timeout)
100
101 if ePassed == exit_status:
Steve Puccibefe2b12014-03-07 00:01:11 +0000102 passed.append(name)
Vince Harron17f429f2014-12-13 00:08:19 +0000103 else:
104 if eTimedOut == exit_status:
105 timed_out.append(name)
106 failed.append(name)
107 return (timed_out, failed, passed)
Steve Puccibefe2b12014-03-07 00:01:11 +0000108
109in_q = None
110out_q = None
111
Todd Fiala3f0a3602014-07-08 06:42:37 +0000112def process_dir_worker(arg_tuple):
Steve Puccibefe2b12014-03-07 00:01:11 +0000113 """Worker thread main loop when in multithreaded mode.
114 Takes one directory specification at a time and works on it."""
Todd Fiala3f0a3602014-07-08 06:42:37 +0000115 (root, files, test_root, dotest_options) = arg_tuple
116 return process_dir(root, files, test_root, dotest_options)
Steve Puccibefe2b12014-03-07 00:01:11 +0000117
Vince Harrone06a7a82015-05-12 23:12:19 +0000118def walk_and_invoke(test_directory, test_subdir, dotest_options, num_threads):
Steve Puccibefe2b12014-03-07 00:01:11 +0000119 """Look for matched files and invoke test driver on each one.
120 In single-threaded mode, each test driver is invoked directly.
121 In multi-threaded mode, submit each test driver to a worker
Vince Harrone06a7a82015-05-12 23:12:19 +0000122 queue, and then wait for all to complete.
123
124 test_directory - lldb/test/ directory
125 test_subdir - lldb/test/ or a subfolder with the tests we're interested in running
126 """
Todd Fiala3f0a3602014-07-08 06:42:37 +0000127
128 # Collect the test files that we'll run.
129 test_work_items = []
Vince Harrone06a7a82015-05-12 23:12:19 +0000130 for root, dirs, files in os.walk(test_subdir, topdown=False):
131 test_work_items.append((root, files, test_directory, dotest_options))
Todd Fiala3f0a3602014-07-08 06:42:37 +0000132
133 # Run the items, either in a pool (for multicore speedup) or
134 # calling each individually.
135 if num_threads > 1:
136 pool = multiprocessing.Pool(num_threads)
137 test_results = pool.map(process_dir_worker, test_work_items)
138 else:
139 test_results = []
140 for work_item in test_work_items:
141 test_results.append(process_dir_worker(work_item))
142
Vince Harron17f429f2014-12-13 00:08:19 +0000143 timed_out = []
Steve Puccibefe2b12014-03-07 00:01:11 +0000144 failed = []
145 passed = []
Todd Fiala3f0a3602014-07-08 06:42:37 +0000146
147 for test_result in test_results:
Vince Harron17f429f2014-12-13 00:08:19 +0000148 (dir_timed_out, dir_failed, dir_passed) = test_result
149 timed_out += dir_timed_out
Todd Fiala3f0a3602014-07-08 06:42:37 +0000150 failed += dir_failed
151 passed += dir_passed
152
Vince Harron17f429f2014-12-13 00:08:19 +0000153 return (timed_out, failed, passed)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000154
Vince Harron06381732015-05-12 23:10:36 +0000155def getExpectedTimeouts(dotest_options):
156 # returns a set of test filenames that might timeout
157 # are we running against a remote target?
158 m = re.search('\sremote-(\w+)', dotest_options)
159 if m:
160 target = m.group(1)
161 remote = True
162 else:
163 target = sys.platform
164 remote = False
165
166 expected_timeout = set()
167
168 if target.startswith("linux"):
169 expected_timeout |= {
170 "TestAttachResume.py",
171 "TestConnectRemote.py",
172 "TestCreateAfterAttach.py",
173 "TestExitDuringStep.py",
174 "TestThreadStepOut.py",
175 }
176 elif target.startswith("android"):
177 expected_timeout |= {
178 "TestExitDuringStep.py",
179 "TestHelloWorld.py",
180 }
181 return expected_timeout
182
Johnny Chene8d9dc62011-10-31 19:04:07 +0000183def main():
Vince Harrond5fa1022015-05-10 15:24:12 +0000184 # We can't use sys.path[0] to determine the script directory
185 # because it doesn't work under a debugger
Vince Harrone06a7a82015-05-12 23:12:19 +0000186 test_directory = os.path.dirname(os.path.realpath(__file__))
Johnny Chene8d9dc62011-10-31 19:04:07 +0000187 parser = OptionParser(usage="""\
188Run lldb test suite using a separate process for each test file.
Vince Harronede59652015-01-08 02:11:26 +0000189
Siva Chandra2d7832e2015-05-08 23:08:53 +0000190 Each test will run with a time limit of 10 minutes by default.
Vince Harronede59652015-01-08 02:11:26 +0000191
Siva Chandra2d7832e2015-05-08 23:08:53 +0000192 Override the default time limit of 10 minutes by setting
Vince Harronede59652015-01-08 02:11:26 +0000193 the environment variable LLDB_TEST_TIMEOUT.
194
195 E.g., export LLDB_TEST_TIMEOUT=10m
196
197 Override the time limit for individual tests by setting
198 the environment variable LLDB_[TEST NAME]_TIMEOUT.
199
200 E.g., export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=2m
201
202 Set to "0" to run without time limit.
203
204 E.g., export LLDB_TEST_TIMEOUT=0
205 or export LLDB_TESTCONCURRENTEVENTS_TIMEOUT=0
Johnny Chene8d9dc62011-10-31 19:04:07 +0000206""")
207 parser.add_option('-o', '--options',
208 type='string', action='store',
209 dest='dotest_options',
210 help="""The options passed to 'dotest.py' if specified.""")
211
Greg Clayton2256d0d2014-03-24 23:01:57 +0000212 parser.add_option('-t', '--threads',
213 type='int',
214 dest='num_threads',
Ed Mastecec2a5b2014-11-21 02:41:25 +0000215 help="""The number of threads to use when running tests separately.""")
Greg Clayton2256d0d2014-03-24 23:01:57 +0000216
Johnny Chene8d9dc62011-10-31 19:04:07 +0000217 opts, args = parser.parse_args()
218 dotest_options = opts.dotest_options
Ed Mastecec2a5b2014-11-21 02:41:25 +0000219
Vince Harrone06a7a82015-05-12 23:12:19 +0000220 # The root directory was specified on the command line
221 if len(args) == 0:
222 test_subdir = test_directory
223 else:
224 test_subdir = os.path.join(test_directory, args[0])
225
Ed Mastecec2a5b2014-11-21 02:41:25 +0000226 if opts.num_threads:
227 num_threads = opts.num_threads
228 else:
Greg Clayton2256d0d2014-03-24 23:01:57 +0000229 num_threads_str = os.environ.get("LLDB_TEST_THREADS")
230 if num_threads_str:
231 num_threads = int(num_threads_str)
Greg Clayton2256d0d2014-03-24 23:01:57 +0000232 else:
Ed Mastecec2a5b2014-11-21 02:41:25 +0000233 num_threads = multiprocessing.cpu_count()
234 if num_threads < 1:
235 num_threads = 1
Johnny Chene8d9dc62011-10-31 19:04:07 +0000236
Daniel Maleab42556f2013-04-19 18:32:53 +0000237 system_info = " ".join(platform.uname())
Vince Harrone06a7a82015-05-12 23:12:19 +0000238 (timed_out, failed, passed) = walk_and_invoke(test_directory, test_subdir, dotest_options,
Vince Harron17f429f2014-12-13 00:08:19 +0000239 num_threads)
240 timed_out = set(timed_out)
Daniel Maleacbaef262013-02-15 21:31:37 +0000241 num_tests = len(failed) + len(passed)
Daniel Maleab42556f2013-04-19 18:32:53 +0000242
Vince Harron06381732015-05-12 23:10:36 +0000243 # remove expected timeouts from failures
244 expected_timeout = getExpectedTimeouts(dotest_options)
245 for xtime in expected_timeout:
246 if xtime in timed_out:
247 timed_out.remove(xtime)
248 failed.remove(xtime)
249
Daniel Maleacbaef262013-02-15 21:31:37 +0000250 print "Ran %d tests." % num_tests
251 if len(failed) > 0:
Shawn Best13491c42014-10-22 19:29:00 +0000252 failed.sort()
Daniel Maleacbaef262013-02-15 21:31:37 +0000253 print "Failing Tests (%d)" % len(failed)
254 for f in failed:
Vince Harron17f429f2014-12-13 00:08:19 +0000255 print "%s: LLDB (suite) :: %s (%s)" % (
256 "TIMEOUT" if f in timed_out else "FAIL", f, system_info
257 )
Daniel Maleacbaef262013-02-15 21:31:37 +0000258 sys.exit(1)
259 sys.exit(0)
Johnny Chene8d9dc62011-10-31 19:04:07 +0000260
261if __name__ == '__main__':
262 main()