From 304372419ae12e54a1eb78dfc129059b160af7e8 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Sat, 16 Sep 2017 15:31:34 +0000 Subject: [PATCH] [lit] Add a single process mode. This is helpful for debugging test failures since it removes the multiprocessing pool from the picture. This will obviously slow down the test suite by a few orders of magnitude, so it should only be used for debugging specific failures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313460 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/lit/lit/LitConfig.py | 3 +- utils/lit/lit/main.py | 8 ++-- utils/lit/lit/run.py | 92 +++++++++++++++++++++----------------- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py index 3351ebed54b..fbb04dc4e6f 100644 --- a/utils/lit/lit/LitConfig.py +++ b/utils/lit/lit/LitConfig.py @@ -21,7 +21,7 @@ class LitConfig(object): def __init__(self, progname, path, quiet, useValgrind, valgrindLeakCheck, valgrindArgs, - noExecute, debug, isWindows, + noExecute, debug, isWindows, singleProcess, params, config_prefix = None, maxIndividualTestTime = 0, maxFailures = None, @@ -37,6 +37,7 @@ class LitConfig(object): self.valgrindUserArgs = list(valgrindArgs) self.noExecute = noExecute self.debug = debug + self.singleProcess = singleProcess self.isWindows = bool(isWindows) self.params = dict(params) self.bashPath = None diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py index f0162464ce3..95a5500a504 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -289,9 +289,10 @@ def main_with_tmp(builtinParameters): debug_group.add_argument("--show-tests", dest="showTests", help="Show all discovered tests", action="store_true", default=False) - debug_group.add_argument("--use-processes", dest="executionStrategy", - help="Run tests in parallel with processes (not threads)", - action="store_const", const="PROCESSES") + debug_group.add_argument("--single-process", dest="singleProcess", + help="Don't run tests in parallel. Intended for debugging " + "single test failures", + action="store_true", default=False) opts = parser.parse_args() args = opts.test_paths @@ -341,6 +342,7 @@ def main_with_tmp(builtinParameters): valgrindLeakCheck = opts.valgrindLeakCheck, valgrindArgs = opts.valgrindArgs, noExecute = opts.noExecute, + singleProcess = opts.singleProcess, debug = opts.debug, isWindows = isWindows, params = userParams, diff --git a/utils/lit/lit/run.py b/utils/lit/lit/run.py index 3e39bdb9220..a4a21234fa3 100644 --- a/utils/lit/lit/run.py +++ b/utils/lit/lit/run.py @@ -55,45 +55,7 @@ class Run(object): return _execute_test_impl(test, self.lit_config, self.parallelism_semaphores) - def execute_tests(self, display, jobs, max_time=None): - """ - execute_tests(display, jobs, [max_time]) - - Execute each of the tests in the run, using up to jobs number of - parallel tasks, and inform the display of each individual result. The - provided tests should be a subset of the tests available in this run - object. - - If max_time is non-None, it should be a time in seconds after which to - stop executing tests. - - The display object will have its update method called with each test as - it is completed. The calls are guaranteed to be locked with respect to - one another, but are *not* guaranteed to be called on the same thread as - this method was invoked on. - - Upon completion, each test in the run will have its result - computed. Tests which were not actually executed (for any reason) will - be given an UNRESOLVED result. - """ - # Don't do anything if we aren't going to run any tests. - if not self.tests or jobs == 0: - return - - # Install a console-control signal handler on Windows. - if win32api is not None: - def console_ctrl_handler(type): - print('\nCtrl-C detected, terminating.') - pool.terminate() - pool.join() - abort_now() - return True - win32api.SetConsoleCtrlHandler(console_ctrl_handler, True) - - # Save the display object on the runner so that we can update it from - # our task completion callback. - self.display = display - + def execute_tests_in_pool(self, jobs, max_time): # We need to issue many wait calls, so compute the final deadline and # subtract time.time() from that as we go along. deadline = None @@ -110,8 +72,6 @@ class Run(object): self.parallelism_semaphores)) try: - self.failure_count = 0 - self.hit_max_failures = False async_results = [pool.apply_async(worker_run_one_test, args=(test_index, test), callback=self.consume_test_result) @@ -141,6 +101,56 @@ class Run(object): finally: pool.join() + def execute_tests(self, display, jobs, max_time=None): + """ + execute_tests(display, jobs, [max_time]) + + Execute each of the tests in the run, using up to jobs number of + parallel tasks, and inform the display of each individual result. The + provided tests should be a subset of the tests available in this run + object. + + If max_time is non-None, it should be a time in seconds after which to + stop executing tests. + + The display object will have its update method called with each test as + it is completed. The calls are guaranteed to be locked with respect to + one another, but are *not* guaranteed to be called on the same thread as + this method was invoked on. + + Upon completion, each test in the run will have its result + computed. Tests which were not actually executed (for any reason) will + be given an UNRESOLVED result. + """ + # Don't do anything if we aren't going to run any tests. + if not self.tests or jobs == 0: + return + + # Install a console-control signal handler on Windows. + if win32api is not None: + def console_ctrl_handler(type): + print('\nCtrl-C detected, terminating.') + pool.terminate() + pool.join() + abort_now() + return True + win32api.SetConsoleCtrlHandler(console_ctrl_handler, True) + + # Save the display object on the runner so that we can update it from + # our task completion callback. + self.display = display + + self.failure_count = 0 + self.hit_max_failures = False + if self.lit_config.singleProcess: + global child_lit_config + child_lit_config = self.lit_config + for test_index, test in enumerate(self.tests): + result = worker_run_one_test(test_index, test) + self.consume_test_result(result) + else: + self.execute_tests_in_pool(jobs, max_time) + # Mark any tests that weren't run as UNRESOLVED. for test in self.tests: if test.result is None: -- 2.40.0