コード例 #1
0
ファイル: py_test.py プロジェクト: armarti/testplan
    def pytest_exception_interact(self, node, call, report):
        """
        Hook called when an exception raised and it can be handled. This hook
        is only called if the exception is not an PyTest internal exception.

        :param node: PyTest Function or Module object
        :param call: PyTest CallInfo object
        :param report: PyTest TestReport or CollectReport object
        """
        if call.when in ('memocollect', 'collect'):
            # Failed to collect tests: log to console and mark the report as
            # ERROR.
            self._report.logger.error(format_trace(
                inspect.getinnerframes(call.excinfo.tb), call.excinfo.value))
            self._report.status_override = Status.ERROR

        elif self._current_case_report is not None:
            # Log assertion errors or exceptions in testcase report
            traceback = call.excinfo.traceback[-1]
            message = getattr(call.excinfo.value, 'message', None) or \
                      getattr(call.excinfo.value, 'msg', None) or \
                     getattr(call.excinfo.value, 'args', None) or ''
            if isinstance(message, (tuple, list)):
                message = message[0]

            header = (('Assertion - Fail' if
                call.excinfo.typename == 'AssertionError' else
                'Exception raised') if call.when == 'call' else
                    '{} - Fail'.format(call.when))
            details = 'File: {}{}Line: {}{}{}: {}'.format(
                traceback.path.strpath,
                os.linesep,
                traceback.lineno + 1,
                os.linesep,
                call.excinfo.typename,
                message
            ) if call.excinfo.typename == 'AssertionError' else (
                report.longreprtext if hasattr(report, 'longreprtext') else
                    str(report.longrepr))

            assertion_obj = assertions.RawAssertion(
                description=header,
                content=details,
                passed=False
            )
            serialized_obj = schema_registry.serialize(assertion_obj)
            self._current_case_report.append(serialized_obj)
            self._current_case_report.status_override = Status.FAILED
        else:
            self._report.logger.error(
                'Exception occured outside of a testcase: during %s',
                call.when)
            self._report.logger.error(format_trace(
                inspect.getinnerframes(call.excinfo.tb), call.excinfo.value))
コード例 #2
0
    def _loop(self):
        """
        Main executor work loop - runs in a seperate thread when the Pool is
        started.
        """

        self.logger.debug('Starting worker monitor thread.')
        self._worker_monitor = threading.Thread(target=self._workers_monitoring)
        self._worker_monitor.daemon = True
        self._worker_monitor.start()

        while (self.active
               and self.status.tag is not self.status.STOPPING
               and self.status.tag is not self.status.STOPPED):

            msg = self._conn.accept()
            if msg:
                try:
                    self.logger.debug('Received message from worker: %s.', msg)
                    with self._pool_lock:
                        self.handle_request(msg)
                except Exception as exc:
                    self.logger.error(format_trace(inspect.trace(), exc))

            time.sleep(self.cfg.active_loop_sleep)
コード例 #3
0
 def run(self):
     """Executes the defined steps and populates the result object."""
     try:
         if self.cfg.interactive is True:
             if self._ihandler is not None:
                 raise RuntimeError('{} already has an active {}'.format(
                     self, self._ihandler))
             self.logger.test_info(
                 'Starting {} in interactive mode'.format(self))
             self._ihandler = self.cfg.interactive_handler(target=self)
             thread = threading.Thread(target=self._ihandler)
             thread.start()
             # Check if we are on interactive session.
             if self.cfg.interactive_block is True:
                 while self._ihandler.active:
                     time.sleep(self.cfg.active_loop_sleep)
             return self._ihandler
         else:
             self._run_batch_steps()
     except Exception as exc:
         self._result.run = exc
         self.logger.error(format_trace(inspect.trace(), exc))
     else:
         # TODO fix swallow exceptions in self._result.step_results.values()
         self._result.run = self.status.tag == RunnableStatus.FINISHED and\
             self.run_result() is True
     return self._result
コード例 #4
0
    def _loop_process_work(self, curr_status):
        """
        Poll for work based on the current pool state and process the next item
        if there is one.

        :return: Whether to continue the main work loop.
        :rtype: ``bool``
        """
        if curr_status == self.status.STARTING:
            self.status.change(self.status.STARTED)
        elif curr_status == self.status.STOPPING:
            self.status.change(self.status.STOPPED)
            return False  # Indicate to break from the main work loop.
        elif curr_status != self.status.STARTED:
            raise RuntimeError('Pool in unexpected state {}'
                               .format(curr_status))
        else:
            msg = self._conn.accept()
            if msg:
                try:
                    self.logger.debug('Received message from worker: %s.',
                                      msg)
                    self.handle_request(msg)
                except Exception as exc:
                    self.logger.error(format_trace(inspect.trace(), exc))

        # The main work loop can continue.
        return True
コード例 #5
0
    def stop(self, reversed=False):
        """
        Stop all resources in reverse order and log exceptions.
        """
        resources = list(self._resources.values())
        if reversed is True:
            resources = resources[::-1]

        # Stop all resources
        for resource in resources:
            if (resource.status.tag is None) or (resource.status.tag
                                                 == resource.STATUS.STOPPED):
                # Skip resources not even triggered to start.
                continue
            try:
                resource.stop()
            except Exception as exc:
                msg = 'While stopping resource [{}]{}{}'.format(
                    resource.cfg.name, os.linesep,
                    format_trace(inspect.trace(), exc))
                self.stop_exceptions[resource] = msg

        # Wait resources status to be STOPPED.
        for resource in resources:
            if resource in self.stop_exceptions:
                continue
            elif resource.status.tag is None:
                # Skip resources not even triggered to start.
                continue
            else:
                resource.wait(resource.STATUS.STOPPED)
コード例 #6
0
 def _run_loop(self):
     """Main work loop. Process incoming operations while we are RUNNING."""
     while self.active and self.target.active:
         if self.status.tag == RunnableStatus.RUNNING:
             try:
                 uid = self._queue.pop(0)
                 operation, args, kwargs = self._operations[uid]
             except IndexError:
                 time.sleep(self.cfg.active_loop_sleep)
             else:
                 try:
                     try:
                         owner = '{}.{}, '.format(
                             self, operation.im_class.__name__)
                     except AttributeError:
                         owner = ''
                     self.logger.debug('Performing operation:{}{}'.format(
                         owner, operation.__name__))
                     start_time = time.time()
                     result = operation(*args, **kwargs)
                     self._results[uid] = result
                     self.logger.debug(
                         'Finished operation {}{} - {}s'.format(
                             owner, operation.__name__,
                             round(time.time() - start_time, 5)))
                 except Exception as exc:
                     self.logger.test_info(
                         format_trace(inspect.trace(), exc))
                     self._results[uid] = exc
                 finally:
                     del self._operations[uid]
コード例 #7
0
    def start(self):
        """
        Start all resources sequentially and log errors.
        """
        # Trigger start all resources
        for resource in self._resources.values():
            try:
                resource.start()
                if resource.cfg.async_start is False:
                    resource.wait(resource.STATUS.STARTED)
            except Exception as exc:
                msg = 'While starting resource [{}]{}{}'.format(
                    resource.cfg.name, os.linesep,
                    format_trace(inspect.trace(), exc))
                self.logger.error(msg)
                self.start_exceptions[resource] = msg
                # Environment start failure. Won't start the rest.
                break

        # Wait resources status to be STARTED.
        for resource in self._resources.values():
            if resource in self.start_exceptions:
                break
            if resource.cfg.async_start is False:
                continue
            else:
                resource.wait(resource.STATUS.STARTED)
コード例 #8
0
    def execute(self, task):
        """
        Executes a task and return the associated task result.

        :param task: Task that worker pulled for execution.
        :type task: :py:class:`~testplan.runners.pools.tasks.base.Task`
        :return: Task result.
        :rtype: :py:class:`~testplan.runners.pools.tasks.base.TaskResult`
        """
        try:
            target = task.materialize()
            if isinstance(target, Runnable):
                if not target.parent:
                    target.parent = self
                if not target.cfg.parent:
                    target.cfg.parent = self.cfg
                result = target.run()
            elif callable(target):
                result = target()
            else:
                result = target.run()
        except BaseException as exc:
            task_result = TaskResult(task=task,
                                     result=None,
                                     status=False,
                                     reason=format_trace(inspect.trace(), exc))
        else:
            task_result = TaskResult(task=task, result=result, status=True)
        return task_result
コード例 #9
0
ファイル: __init__.py プロジェクト: fukaij/testplan
    def run_exporter(cls, exporter, source, type):
        result = ExporterResult(exporter=exporter, type=type)

        try:
            exporter.export(source)
        except Exception as exc:
            result.traceback = format_trace(inspect.trace(), exc)
        return result
コード例 #10
0
 def wrapper(*args, **kargs):
     try:
         func(*args, **kargs)
     except Exception as exe:
         msg = 'While executing {} of resource [{}]{}{}'.format(
             func.__name__, resource.cfg.name, os.linesep,
             format_trace(inspect.trace(), exe))
         self.logger.error(msg)
         self.start_exceptions[resource] = msg
コード例 #11
0
 def _execute_step(self, step, *args, **kwargs):
     try:
         res = step(*args, **kwargs)
     except Exception as exc:
         print('Exception on {} {}, step {} - {}'.format(
             self.__class__.__name__, self.uid(), step.__name__, exc))
         self.logger.error(format_trace(inspect.trace(), exc))
         res = exc
     finally:
         self.result.step_results[step.__name__] = res
         self.status.update_metadata(**{str(step): res})
コード例 #12
0
ファイル: base.py プロジェクト: ywong587/testplan
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None and issubclass(exc_type,
                                               self.exception_classes):

            # Custom exception message with extra args
            exc_msg = format_trace(inspect.trace(), exc_value)
            self.report.logger.error(exc_msg)

            if self.fail:
                self.report.status_override = Status.ERROR
            return True
コード例 #13
0
            def do_POST(self):
                """
                Handle post requests.
                """
                outer.logger.debug('path: {}'.format(self.path))
                url = urlparse(self.path)
                outer.logger.debug('url: {}'.format(url))

                try:
                    try:
                        length = int(self.headers.get('content-length'))
                    except:
                        # No data in request.
                        request = {}
                    else:
                        request = {}
                        content = self.rfile.read(length).decode()
                        for key, value in json.loads(content).items():
                            if isinstance(value, six.string_types):
                                request[str(key)] = str(value)
                            else:
                                request[str(key)] = value

                    mode, method = self._extract_mode_method(self.path)
                    if mode not in self.MODES:
                        raise ValueError('Execution {} not valid: {}'.format(
                            mode, self.MODES))
                    if mode == 'sync':
                        result = self._sync(method, **request)
                        msg = 'Sync operation performed: {}'.format(method)
                        response = self._make_response(msg, result=result)
                    elif mode == 'async':
                        result = self._async(method, **request)
                        msg = 'Async operation performed: {}'.format(method)
                        response = self._make_response(msg, result=result)
                    elif mode == 'async_result':
                        res_dict = self._async_result(**request)
                        response = self._make_response(**res_dict)
                    self._header_json(
                        code=200 if not response['error'] else 400)
                    self._write_json(response)
                except Exception as exc:
                    msg = '{} exception in do_POST: {}'.format(
                        outer.__class__.__name__, exc)
                    outer.logger.critical(msg)
                    response = self._make_response(message=msg,
                                                   error=True,
                                                   trace=format_trace(
                                                       inspect.trace()))
                    self._header_json(code=500)
                    self._write_json(response)
コード例 #14
0
 def _abort_entity(self, entity, wait_timeout=None):
     """Method to abort an entity and log exceptions."""
     timeout = wait_timeout or self.cfg.abort_wait_timeout
     try:
         self.logger.debug('Aborting {}'.format(entity))
         entity.abort()
         self.logger.debug('Aborted {}'.format(entity))
     except Exception as exc:
         self.logger.error(format_trace(inspect.trace(), exc))
         self.logger.error('Exception on aborting {} - {}'.format(
             self, exc))
     else:
         if wait(lambda: entity.aborted is True, timeout) is False:
             self.logger.error(
                 'Timeout on waiting to abort {}.'.format(self))
コード例 #15
0
ファイル: base.py プロジェクト: laszlo-bica/testplan
 def run(self):
     """Executes the defined steps and populates the result object."""
     try:
         if self.cfg.interactive is True:
             raise
         else:
             self._run_batch_steps()
     except Exception as exc:
         self._result.run = exc
         self.logger.error(format_trace(inspect.trace(), exc))
     else:
         # TODO fix swallow exceptions in self._result.step_results.values()
         self._result.run = self.status.tag == RunnableStatus.FINISHED and\
             self.run_result() is True
     return self._result
コード例 #16
0
    def _loop(self):
        worker_monitor = threading.Thread(target=self._workers_monitoring)
        worker_monitor.daemon = True
        worker_monitor.start()

        while self.active:
            if self.status.tag == self.status.STARTING:
                self.status.change(self.status.STARTED)
            elif self.status.tag == self.status.STOPPING:
                self.status.change(self.status.STOPPED)
                break
            else:
                msg = self._conn.accept()
                if msg:
                    try:
                        with self._pool_lock:
                            self.handle_request(msg)
                    except Exception as exc:
                        self.logger.error(format_trace(inspect.trace(), exc))
            time.sleep(self.cfg.active_loop_sleep)
コード例 #17
0
    def __call__(self, *args, **kwargs):
        self.status.change(RunnableStatus.RUNNING)
        self.logger.test_info('Starting {} for {}'.format(
            self.__class__.__name__, self.target))
        if self._http_handler is not None:
            self._start_http_handler()

        while self.active and self.target.active:
            if self.status.tag == RunnableStatus.RUNNING:
                try:
                    uid = self._queue.pop(0)
                    operation, args, kwargs = self._operations[uid]
                except IndexError:
                    time.sleep(self.cfg.active_loop_sleep)
                else:
                    try:
                        try:
                            owner = '{}.{}, '.format(
                                self, operation.im_class.__name__)
                        except AttributeError:
                            owner = ''
                        self.logger.debug('Performing operation:{}{}'.format(
                            owner, operation.__name__))
                        start_time = time.time()
                        result = operation(*args, **kwargs)
                        self._results[uid] = result
                        self.logger.debug(
                            'Finished operation {}{} - {}s'.format(
                                owner, operation.__name__,
                                round(time.time() - start_time, 5)))
                    except Exception as exc:
                        self.logger.test_info(
                            format_trace(inspect.trace(), exc))
                        self._results[uid] = exc
                    finally:
                        del self._operations[uid]

        self.status.change(RunnableStatus.FINISHED)
コード例 #18
0
    def worker_loop(self):
        """
        Child process worker loop. Manages an underlying thread pool, pulls and
        sends back results to the main pool.
        """
        from testplan.runners.pools.communication import Message
        from testplan.common.utils.exceptions import format_trace
        message = Message(**self.metadata)

        try:
            self._pre_loop_setup(message)
        except Exception as exc:
            self._transport.send_and_receive(message.make(
                message.SetupFailed,
                data=format_trace(inspect.trace(), exc)), expect=message.Ack)
            return

        with self._child_pool():
            if self._pool_cfg.worker_heartbeat:
                self.heartbeat_setup()
            message = Message(**self.metadata)
            next_possible_request = time.time()
            request_delay = self._pool_cfg.active_loop_sleep
            while True:
                if self._pool_cfg.worker_heartbeat and self._to_heartbeat <= 0:
                    hb_resp = self._transport.send_and_receive(message.make(
                        message.Heartbeat, data=time.time()))
                    if hb_resp is None:
                        self.logger.critical('Pool seems dead, child exits.')
                        self.exit_loop()
                        break
                    else:
                        self.logger.debug(
                            'Pool heartbeat response:'
                            ' {} at {} before {}s.'.format(
                                hb_resp.cmd, hb_resp.data,
                                time.time() - hb_resp.data))
                    self._to_heartbeat = self._pool_cfg.worker_heartbeat

                # Send back results
                if self._pool.results:
                    task_results = []
                    for uid in list(self._pool.results.keys()):
                        task_results.append(self._pool.results[uid])
                        self.logger.debug('Sending back result for {}'.format(
                            self._pool.results[uid].task))
                        del self._pool.results[uid]
                    self._transport.send_and_receive(message.make(
                        message.TaskResults,
                        data=task_results), expect=message.Ack)

                # Request new tasks
                demand = self._pool.workers_requests() -\
                         len(self._pool.unassigned)

                if demand > 0 and time.time() > next_possible_request:
                    received = self._transport.send_and_receive(message.make(
                        message.TaskPullRequest, data=demand))

                    if received is None or received.cmd == Message.Stop:
                        self.logger.critical('Child exits.')
                        self.exit_loop()
                        break
                    elif received.cmd == Message.TaskSending:
                        next_possible_request = time.time()
                        request_delay = 0
                        for task in received.data:
                            self.logger.debug('Added {} to local pool'.format(
                                task))
                            self._pool.add(task, task.uid())
                        # Reset workers request counters
                        for worker in self._pool._workers:
                            worker.requesting = 0
                    elif received.cmd == Message.Ack:
                        request_delay = min(
                            (request_delay + 0.2) * 1.5,
                            self._pool_cfg.max_active_loop_sleep)
                        next_possible_request = time.time() + request_delay
                        pass
                time.sleep(self._pool_cfg.active_loop_sleep)
        self.logger.info('Local pool {} stopped.'.format(self._pool))
コード例 #19
0
ファイル: test_assertions.py プロジェクト: ywong587/testplan
 def error_func(value):
     try:
         raise Exception('some message')
     except Exception as exc:
         error_ctx['msg'] = format_trace(inspect.trace(), exc)
         raise