def _run_avocado(runnable, queue): try: # This assumes that a proper resolution (see resolver module) # was performed, and that a URI contains: # 1) path to python module # 2) class # 3) method # # To be defined: if the resolution uri should be composed like # this, or broken down and stored into other data fields module_path, klass_method = runnable.uri.split(":", 1) klass, method = klass_method.split(".", 1) params = AvocadoInstrumentedTestRunner._create_params(runnable) result_dir = runnable.output_dir or tempfile.mkdtemp(prefix=".avocado-task") test_factory = [ klass, { "name": TestID(1, runnable.uri, runnable.variant), "methodName": method, "config": runnable.config, "modulePath": module_path, "params": params, "tags": runnable.tags, "run.results_dir": result_dir, }, ] messages.start_logging(runnable.config, queue) if "COVERAGE_RUN" in os.environ: from coverage import Coverage coverage = Coverage() coverage.start() instance = loader.load_test(test_factory) early_state = instance.get_state() early_state["type"] = "early_state" queue.put(early_state) instance.run_avocado() if "COVERAGE_RUN" in os.environ: coverage.stop() coverage.save() state = instance.get_state() fail_reason = state.get("fail_reason") queue.put(messages.WhiteboardMessage.get(state["whiteboard"])) queue.put( messages.FinishedMessage.get( state["status"].lower(), fail_reason=fail_reason ) ) except Exception as e: queue.put(messages.StderrMessage.get(traceback.format_exc())) queue.put(messages.FinishedMessage.get("error", fail_reason=str(e)))
def _run_avocado(runnable, queue): try: # This assumes that a proper resolution (see resolver module) # was performed, and that a URI contains: # 1) path to python module # 2) class # 3) method # # To be defined: if the resolution uri should be composed like # this, or broken down and stored into other data fields module_path, klass_method = runnable.uri.split(':', 1) klass, method = klass_method.split('.', 1) params = AvocadoInstrumentedTestRunner._create_params(runnable) result_dir = (runnable.output_dir or tempfile.mkdtemp(prefix=".avocado-task")) test_factory = [ klass, { 'name': TestID(1, runnable.uri), 'methodName': method, 'config': runnable.config, 'modulePath': module_path, 'params': params, 'tags': runnable.tags, 'run.results_dir': result_dir, } ] messages.start_logging(runnable.config, queue) if 'COVERAGE_RUN' in os.environ: from coverage import Coverage coverage = Coverage() coverage.start() instance = loader.load_test(test_factory) early_state = instance.get_state() early_state['type'] = "early_state" queue.put(early_state) instance.run_avocado() if 'COVERAGE_RUN' in os.environ: coverage.stop() coverage.save() state = instance.get_state() fail_reason = state.get('fail_reason') queue.put(messages.WhiteboardMessage.get(state['whiteboard'])) queue.put( messages.FinishedMessage.get(state['status'].lower(), fail_reason=fail_reason)) except Exception as e: queue.put(messages.StderrMessage.get(traceback.format_exc())) queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))
def _run_test(job, test_factory, queue): """ Run a test instance. This code is the first thing that runs inside a new process, known here as the test process. It communicates to the test runner by using :param:`queue`. It's important that this early state is given to the test runner in a reliable way. :param test_factory: Test factory (test class and parameters). :type test_factory: tuple of :class:`avocado.core.test.Test` and dict. :param queue: Multiprocess queue. :type queue: :class:`multiprocessing.Queue` instance. """ sys.stdout = output.LoggingFile(["[stdout] "], loggers=[TEST_LOG]) sys.stderr = output.LoggingFile(["[stderr] "], loggers=[TEST_LOG]) def sigterm_handler(signum, frame): # pylint: disable=W0613 """ Produce traceback on SIGTERM """ raise RuntimeError("Test interrupted by SIGTERM") signal.signal(signal.SIGTERM, sigterm_handler) # At this point, the original `sys.stdin` has already been # closed and replaced with `os.devnull` by # `multiprocessing.Process()` (not directly from Avocado # code). Still, tests trying to use file descriptor 0 would # be able to read from the tty, and would hang. Let's replace # STDIN fd (0), with the same fd previously set by # `multiprocessing.Process()` os.dup2(sys.stdin.fileno(), 0) instance = loader.load_test(test_factory) if instance.runner_queue is None: instance.set_runner_queue(queue) early_state = instance.get_state() early_state['early_status'] = True early_state['job_logdir'] = job.logdir early_state['job_unique_id'] = job.unique_id try: queue.put(early_state) except queueFullException: instance.error(stacktrace.str_unpickable_object(early_state)) job.result.start_test(early_state) job.result_events_dispatcher.map_method('start_test', job.result, early_state) if job.config.get('run.log_test_data_directories'): data_sources = getattr(instance, "DATA_SOURCES", []) if data_sources: locations = [] for source in data_sources: locations.append(instance.get_data("", source=source, must_exist=False)) TEST_LOG.info('Test data directories: ') for source, location in zip(data_sources, locations): if location is not None: TEST_LOG.info(' %s: %s', source, location) TEST_LOG.info('') try: instance.run_avocado() finally: try: state = instance.get_state() state['job_logdir'] = job.logdir state['job_unique_id'] = job.unique_id queue.put(state) except queueFullException: instance.error(stacktrace.str_unpickable_object(state))