[lit] Improve lit.Run class
* Push timing of overall test time into run module * Make lit.Run a proper class * Add a few TODO comments llvm-svn: 375065
This commit is contained in:
		
							parent
							
								
									f80f15e38a
								
							
						
					
					
						commit
						f35cebe71d
					
				| 
						 | 
					@ -9,7 +9,6 @@ See lit.pod for more information.
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import platform
 | 
					import platform
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import lit.cl_arguments
 | 
					import lit.cl_arguments
 | 
				
			||||||
import lit.discovery
 | 
					import lit.discovery
 | 
				
			||||||
| 
						 | 
					@ -209,8 +208,6 @@ def increase_process_limit(litConfig, opts):
 | 
				
			||||||
def run_tests(tests, litConfig, opts, numTotalTests):
 | 
					def run_tests(tests, litConfig, opts, numTotalTests):
 | 
				
			||||||
    increase_process_limit(litConfig, opts)
 | 
					    increase_process_limit(litConfig, opts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    run = lit.run.Run(litConfig, tests)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    display = lit.display.create_display(opts, len(tests), numTotalTests,
 | 
					    display = lit.display.create_display(opts, len(tests), numTotalTests,
 | 
				
			||||||
                                         opts.numWorkers)
 | 
					                                         opts.numWorkers)
 | 
				
			||||||
    def progress_callback(test):
 | 
					    def progress_callback(test):
 | 
				
			||||||
| 
						 | 
					@ -218,18 +215,22 @@ def run_tests(tests, litConfig, opts, numTotalTests):
 | 
				
			||||||
        if opts.incremental:
 | 
					        if opts.incremental:
 | 
				
			||||||
            update_incremental_cache(test)
 | 
					            update_incremental_cache(test)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    run_callback = lambda: run.execute_tests(progress_callback, opts.numWorkers,
 | 
					    run = lit.run.Run(tests, litConfig, progress_callback, opts.maxTime,
 | 
				
			||||||
                                             opts.maxTime)
 | 
					                      opts.numWorkers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    startTime = time.time()
 | 
					 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        run_tests_in_tmp_dir(run_callback, litConfig)
 | 
					        elapsed = run_tests_in_tmp_dir(run.execute_tests, litConfig)
 | 
				
			||||||
    except KeyboardInterrupt:
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        #TODO(yln): should we attempt to cleanup the progress bar here?
 | 
				
			||||||
        sys.exit(2)
 | 
					        sys.exit(2)
 | 
				
			||||||
    testing_time = time.time() - startTime
 | 
					    # TODO(yln): display.finish_interrupted(), which shows the most recently started test
 | 
				
			||||||
 | 
					    # TODO(yln): change display to update when test starts, not when test completes
 | 
				
			||||||
 | 
					    # Ensure everything still works with SimpleProgressBar as well
 | 
				
			||||||
 | 
					    # finally:
 | 
				
			||||||
 | 
					    #     display.finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    display.finish()
 | 
					    display.finish()
 | 
				
			||||||
    return testing_time
 | 
					    return elapsed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def run_tests_in_tmp_dir(run_callback, litConfig):
 | 
					def run_tests_in_tmp_dir(run_callback, litConfig):
 | 
				
			||||||
    # Create a temp directory inside the normal temp directory so that we can
 | 
					    # Create a temp directory inside the normal temp directory so that we can
 | 
				
			||||||
| 
						 | 
					@ -252,7 +253,7 @@ def run_tests_in_tmp_dir(run_callback, litConfig):
 | 
				
			||||||
    # scanning for stale temp directories, and deleting temp directories whose
 | 
					    # scanning for stale temp directories, and deleting temp directories whose
 | 
				
			||||||
    # lit process has died.
 | 
					    # lit process has died.
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        run_callback()
 | 
					        return run_callback()
 | 
				
			||||||
    finally:
 | 
					    finally:
 | 
				
			||||||
        if tmp_dir:
 | 
					        if tmp_dir:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,18 +12,17 @@ class NopSemaphore(object):
 | 
				
			||||||
    def release(self): pass
 | 
					    def release(self): pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Run(object):
 | 
					class Run(object):
 | 
				
			||||||
    """
 | 
					    """A concrete, configured testing run."""
 | 
				
			||||||
    This class represents a concrete, configured testing run.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, lit_config, tests):
 | 
					    def __init__(self, tests, lit_config, progress_callback, max_time, workers):
 | 
				
			||||||
        self.lit_config = lit_config
 | 
					 | 
				
			||||||
        self.tests = tests
 | 
					        self.tests = tests
 | 
				
			||||||
 | 
					        self.lit_config = lit_config
 | 
				
			||||||
 | 
					        self.progress_callback = progress_callback
 | 
				
			||||||
 | 
					        self.max_time = max_time
 | 
				
			||||||
 | 
					        self.workers = workers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def execute_tests(self, progress_callback, workers, max_time):
 | 
					    def execute_tests(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        execute_tests(progress_callback, workers, max_time)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Execute the tests in the run using up to the specified number of
 | 
					        Execute the tests in the run using up to the specified number of
 | 
				
			||||||
        parallel tasks, and inform the caller of each individual result. The
 | 
					        parallel tasks, and inform the caller of each individual result. The
 | 
				
			||||||
        provided tests should be a subset of the tests available in this run
 | 
					        provided tests should be a subset of the tests available in this run
 | 
				
			||||||
| 
						 | 
					@ -34,42 +33,48 @@ class Run(object):
 | 
				
			||||||
        If max_time is non-None, it should be a time in seconds after which to
 | 
					        If max_time is non-None, it should be a time in seconds after which to
 | 
				
			||||||
        stop executing tests.
 | 
					        stop executing tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns the elapsed testing time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Upon completion, each test in the run will have its result
 | 
					        Upon completion, each test in the run will have its result
 | 
				
			||||||
        computed. Tests which were not actually executed (for any reason) will
 | 
					        computed. Tests which were not actually executed (for any reason) will
 | 
				
			||||||
        be given an UNRESOLVED result.
 | 
					        be given an UNRESOLVED result.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        # Don't do anything if we aren't going to run any tests.
 | 
					 | 
				
			||||||
        if not self.tests:
 | 
					        if not self.tests:
 | 
				
			||||||
            return
 | 
					            return 0.0
 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.progress_callback = progress_callback
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.failure_count = 0
 | 
					        self.failure_count = 0
 | 
				
			||||||
        self.hit_max_failures = False
 | 
					        self.hit_max_failures = False
 | 
				
			||||||
        if workers == 1:
 | 
					
 | 
				
			||||||
            self._execute_in_serial(max_time)
 | 
					        start = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.workers == 1:
 | 
				
			||||||
 | 
					            self._execute_in_serial()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._execute_in_parallel(workers, max_time)
 | 
					            self._execute_in_parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        end = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Mark any tests that weren't run as UNRESOLVED.
 | 
					        # Mark any tests that weren't run as UNRESOLVED.
 | 
				
			||||||
        for test in self.tests:
 | 
					        for test in self.tests:
 | 
				
			||||||
            if test.result is None:
 | 
					            if test.result is None:
 | 
				
			||||||
                test.setResult(lit.Test.Result(lit.Test.UNRESOLVED, '', 0.0))
 | 
					                test.setResult(lit.Test.Result(lit.Test.UNRESOLVED, '', 0.0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _execute_in_serial(self, max_time):
 | 
					        return end - start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _execute_in_serial(self):
 | 
				
			||||||
 | 
					        # TODO(yln): ignores max_time
 | 
				
			||||||
        for test_index, test in enumerate(self.tests):
 | 
					        for test_index, test in enumerate(self.tests):
 | 
				
			||||||
            lit.worker._execute_test(test, self.lit_config)
 | 
					            lit.worker._execute_test(test, self.lit_config)
 | 
				
			||||||
            self._consume_test_result((test_index, test))
 | 
					            self._consume_test_result((test_index, test))
 | 
				
			||||||
            if self.hit_max_failures:
 | 
					            if self.hit_max_failures:
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _execute_in_parallel(self, workers, max_time):
 | 
					    def _execute_in_parallel(self):
 | 
				
			||||||
        assert workers > 1
 | 
					 | 
				
			||||||
        # We need to issue many wait calls, so compute the final deadline and
 | 
					        # We need to issue many wait calls, so compute the final deadline and
 | 
				
			||||||
        # subtract time.time() from that as we go along.
 | 
					        # subtract time.time() from that as we go along.
 | 
				
			||||||
        deadline = None
 | 
					        deadline = None
 | 
				
			||||||
        if max_time:
 | 
					        if self.max_time:
 | 
				
			||||||
            deadline = time.time() + max_time
 | 
					            deadline = time.time() + self.max_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        semaphores = {
 | 
					        semaphores = {
 | 
				
			||||||
            k: NopSemaphore() if v is None else
 | 
					            k: NopSemaphore() if v is None else
 | 
				
			||||||
| 
						 | 
					@ -81,7 +86,7 @@ class Run(object):
 | 
				
			||||||
        # interrupts the workers before we make it into our task callback, they
 | 
					        # interrupts the workers before we make it into our task callback, they
 | 
				
			||||||
        # will each raise a KeyboardInterrupt exception and print to stderr at
 | 
					        # will each raise a KeyboardInterrupt exception and print to stderr at
 | 
				
			||||||
        # the same time.
 | 
					        # the same time.
 | 
				
			||||||
        pool = multiprocessing.Pool(workers, lit.worker.initializer,
 | 
					        pool = multiprocessing.Pool(self.workers, lit.worker.initializer,
 | 
				
			||||||
                                    (self.lit_config, semaphores))
 | 
					                                    (self.lit_config, semaphores))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Install a console-control signal handler on Windows.
 | 
					        # Install a console-control signal handler on Windows.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue