Exemple #1
0
 def test(self):
     """
     Create the Robot command and execute it.
     """
     suite_name, test_name = self._filename.split(':')[1].split('.')
     log_stdout = output.LoggingFile(loggers=[self.log], level=logging.INFO)
     log_stderr = output.LoggingFile(loggers=[self.log], level=logging.ERROR)
     result = run(self.filename,
                  suite=suite_name,
                  test=test_name,
                  outputdir=self.outputdir,
                  stdout=log_stdout,
                  stderr=log_stderr)
     if result:
         self.fail('Robot execution returned a '
                   'non-0 exit code (%s)' % result)
Exemple #2
0
    def run_test(self, test_factory, queue):
        """
        Run a test instance in a subprocess.

        :param instance: Test instance.
        :type instance: :class:`avocado.test.Test` instance.
        :param queue: Multiprocess queue.
        :type queue: :class`multiprocessing.Queue` instance.
        """
        def timeout_handler(signum, frame):
            e_msg = "Timeout reached waiting for %s to end" % instance
            raise exceptions.TestTimeoutError(e_msg)

        def interrupt_handler(signum, frame):
            e_msg = "Test %s interrupted by user" % instance
            raise exceptions.TestInterruptedError(e_msg)

        sys.stdout = output.LoggingFile(
            logger=logging.getLogger('avocado.test.stdout'))
        sys.stderr = output.LoggingFile(
            logger=logging.getLogger('avocado.test.stderr'))

        try:
            instance = self.job.test_loader.load_test(test_factory)
            if instance.runner_queue is None:
                instance.runner_queue = queue
            runtime.CURRENT_TEST = instance
            early_state = instance.get_state()
            queue.put(early_state)
        except Exception:
            exc_info = sys.exc_info()
            app_logger = logging.getLogger('avocado.app')
            app_logger.exception('Exception loading test')
            tb_info = stacktrace.tb_info(exc_info)
            queue.put({'load_exception': tb_info})
            return

        signal.signal(signal.SIGUSR1, timeout_handler)
        signal.signal(signal.SIGINT, interrupt_handler)

        self.result.start_test(early_state)
        try:
            instance.run_avocado()
        finally:
            queue.put(instance.get_state())
Exemple #3
0
    def run_suite(self,
                  test_suite,
                  variants,
                  timeout=0,
                  replay_map=None,
                  suite_order="variants-per-test"):
        """
        Run one or more tests and report with test result.

        :param params_list: a list of param dicts.
        :param variants: A varianter iterator (unused here)

        :return: a set with types of test failures.
        """
        del test_suite  # using self.job.references instead
        del variants  # we're not using multiplexation here
        if suite_order != "variants-per-test" and suite_order is not None:
            raise exceptions.JobError("execution-order %s is not supported "
                                      "for remote execution." % suite_order)
        del suite_order  # suite_order is ignored for now
        if not timeout:  # avoid timeout = 0
            timeout = None
        summary = set()

        stdout_backup = sys.stdout
        stderr_backup = sys.stderr
        fabric_debugfile = os.path.join(self.job.logdir, 'remote.log')
        paramiko_logger = logging.getLogger('paramiko')
        fabric_logger = logging.getLogger('avocado.fabric')
        remote_logger = logging.getLogger('avocado.remote')
        app_logger = logging.getLogger('avocado.debug')
        fmt = ('%(asctime)s %(module)-10.10s L%(lineno)-.4d %('
               'levelname)-5.5s| %(message)s')
        formatter = logging.Formatter(fmt=fmt, datefmt='%H:%M:%S')
        file_handler = logging.FileHandler(filename=fabric_debugfile)
        file_handler.setFormatter(formatter)
        fabric_logger.addHandler(file_handler)
        paramiko_logger.addHandler(file_handler)
        remote_logger.addHandler(file_handler)
        if self.job.args.show_job_log:
            output.add_log_handler(paramiko_logger.name)
        logger_list = [output.LOG_JOB]
        sys.stdout = output.LoggingFile(loggers=logger_list)
        sys.stderr = output.LoggingFile(loggers=logger_list)
        try:
            try:
                self.setup()
                avocado_installed, _ = self.check_remote_avocado()
                if not avocado_installed:
                    raise exceptions.JobError('Remote machine does not seem to'
                                              ' have avocado installed')
            except Exception as details:
                stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
                raise exceptions.JobError(details)
            results = self.run_test(self.job.references, timeout)
            remote_log_dir = os.path.dirname(results['debuglog'])
            self.result.tests_total = results['total']
            local_log_dir = self.job.logdir
            for tst in results['tests']:
                name = tst['test'].split('-', 1)
                name = [name[0]] + name[1].split(';')
                if len(name) == 3:
                    name[2] = {"variant_id": name[2]}
                name = TestID(*name, no_digits=-1)
                state = dict(name=name,
                             time_elapsed=tst['time'],
                             time_start=tst['start'],
                             time_end=tst['end'],
                             status=tst['status'],
                             logdir=tst['logdir'],
                             logfile=tst['logfile'],
                             fail_reason=tst['fail_reason'],
                             job_logdir=local_log_dir,
                             job_unique_id='')
                self.result.start_test(state)
                self.job._result_events_dispatcher.map_method(
                    'start_test', self.result, state)
                self.result.check_test(state)
                self.job._result_events_dispatcher.map_method(
                    'end_test', self.result, state)
                if state['status'] == "INTERRUPTED":
                    summary.add("INTERRUPTED")
                elif not status.mapping[state['status']]:
                    summary.add("FAIL")
            zip_filename = remote_log_dir + '.zip'
            zip_path_filename = os.path.join(local_log_dir,
                                             os.path.basename(zip_filename))
            self.remote.receive_files(local_log_dir, zip_filename)
            archive.uncompress(zip_path_filename, local_log_dir)
            os.remove(zip_path_filename)
            self.result.end_tests()
            self.job._result_events_dispatcher.map_method(
                'post_tests', self.job)
        finally:
            try:
                self.tear_down()
            except Exception as details:
                stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
                raise exceptions.JobError(details)
            sys.stdout = stdout_backup
            sys.stderr = stderr_backup
        return summary
Exemple #4
0
    def _run_test(job, result, 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
        try:
            queue.put(early_state)
        except queueFullException:
            instance.error(stacktrace.str_unpickable_object(early_state))

        result.start_test(early_state)
        job.result_events_dispatcher.map_method('start_test',
                                                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()
                queue.put(state)
            except queueFullException:
                instance.error(stacktrace.str_unpickable_object(state))