def wrapper(*args, **kwargs):
            mem.test_printer_counter += 1
            test_api = args[0]
            test_name = func.__name__

            # Print a banner. The test is about to begin
            console_output.banner_print(
                f'{mem.test_printer_counter:04}: {test_name}', logger=None)

            # And here's the test
            result = func(*args, **kwargs)

            # Check the result. Test phases do not need to return a result. In that
            # case, check for failed or unset measurements to determine pass or fail
            if not result:
                measurements = str(test_api.measurements)

                if "'FAIL'" in measurements or "'UNSET'" in measurements:
                    result_msg = "FAIL"

                else:
                    result_msg = "PASS"

            elif result.name == 'CONTINUE':
                result_msg = "PASS"

            elif result.name == 'SKIP':
                result_msg = "SKIP"

            else:
                result_msg = "FAIL"

            # Print the result
            console_output.cli_print(f"result: {result_msg}", logger=None)

            return result
예제 #2
0
    def execute(self, test_start=None):
        """Starts the framework and executes the given test.

    Args:
      test_start: Either a trigger phase for starting the test, or a function
                  that returns a DUT ID. If neither is provided, defaults to not
                  setting the DUT ID.
    Returns:
      Boolean indicating whether the test failed (False) or passed (True).

    Raises:
      InvalidTestStateError: if this test is already being executed.
    """
        # Lock this section so we don't .stop() the executor between instantiating
        # it and .Start()'ing it, doing so does weird things to the executor state.
        with self._lock:
            # Sanity check to make sure someone isn't doing something weird like
            # trying to Execute() the same test twice in two separate threads.  We
            # hold the lock between here and Start()'ing the executor to guarantee
            # that only one thread is successfully executing the test.
            if self._executor:
                raise InvalidTestStateError('Test already running',
                                            self._executor)

            # Snapshot some things we care about and store them.
            self._test_desc.metadata['test_name'] = self._test_options.name
            self._test_desc.metadata['config'] = conf._asdict()
            self.last_run_time_millis = util.time_millis()

            if isinstance(test_start, LambdaType):

                @phase_descriptor.PhaseOptions()
                def trigger_phase(test):
                    test.test_record.dut_id = test_start()

                trigger = trigger_phase
            else:
                trigger = test_start

            if conf.capture_source:
                trigger.code_info = test_record.CodeInfo.for_function(
                    trigger.func)

            self._executor = test_executor.TestExecutor(
                self._test_desc, self.make_uid(), trigger,
                self._test_options.default_dut_id,
                self._test_options.teardown_function,
                self._test_options.failure_exceptions)
            _LOG.info('Executing test: %s', self.descriptor.code_info.name)
            self.TEST_INSTANCES[self.uid] = self
            self._executor.start()

        try:
            self._executor.wait()
        finally:
            try:
                final_state = self._executor.finalize()

                _LOG.debug('Test completed for %s, outputting now.',
                           final_state.test_record.metadata['test_name'])
                for output_cb in self._test_options.output_callbacks:
                    try:
                        output_cb(final_state.test_record)
                    except Exception:  # pylint: disable=broad-except
                        _LOG.error(
                            'Output callback %s raised; continuing anyway',
                            output_cb)
                # Make sure the final outcome of the test is printed last and in a
                # noticeable color so it doesn't get scrolled off the screen or missed.
                if final_state.test_record.outcome == test_record.Outcome.ERROR:
                    for detail in final_state.test_record.outcome_details:
                        console_output.error_print(detail.description)
                else:
                    colors = collections.defaultdict(
                        lambda: 'colorama.Style.BRIGHT')
                    colors[test_record.Outcome.PASS] = ''.join(
                        (colorama.Style.BRIGHT, colorama.Fore.GREEN))
                    colors[test_record.Outcome.FAIL] = ''.join(
                        (colorama.Style.BRIGHT, colorama.Fore.RED))
                    msg_template = "test: {name}  outcome: {color}{outcome}{rst}"
                    console_output.banner_print(
                        msg_template.format(
                            name=final_state.test_record.metadata['test_name'],
                            color=colors[final_state.test_record.outcome],
                            outcome=final_state.test_record.outcome.name,
                            rst=colorama.Style.RESET_ALL))
            finally:
                del self.TEST_INSTANCES[self.uid]
                self._executor = None

        return final_state.test_record.outcome == test_record.Outcome.PASS
예제 #3
0
  def execute(self, test_start=None):
    """Starts the framework and executes the given test.

    Args:
      test_start: Either a trigger phase for starting the test, or a function
                  that returns a DUT ID. If neither is provided, defaults to not
                  setting the DUT ID.
    Returns:
      Boolean indicating whether the test failed (False) or passed (True).

    Raises:
      InvalidTestStateError: if this test is already being executed.
    """
    # Lock this section so we don't .stop() the executor between instantiating
    # it and .Start()'ing it, doing so does weird things to the executor state.
    with self._lock:
      # Sanity check to make sure someone isn't doing something weird like
      # trying to Execute() the same test twice in two separate threads.  We
      # hold the lock between here and Start()'ing the executor to guarantee
      # that only one thread is successfully executing the test.
      if self._executor:
        raise InvalidTestStateError('Test already running', self._executor)

      # Snapshot some things we care about and store them.
      self._test_desc.metadata['test_name'] = self._test_options.name
      self._test_desc.metadata['config'] = conf._asdict()
      self.last_run_time_millis = util.time_millis()

      if isinstance(test_start, LambdaType):
        @phase_descriptor.PhaseOptions()
        def trigger_phase(test):
          test.test_record.dut_id = test_start()
        trigger = trigger_phase
      else:
        trigger = test_start

      if conf.capture_source:
        trigger.code_info = test_record.CodeInfo.for_function(trigger.func)

      test_desc = self._get_running_test_descriptor()
      self._executor = test_executor.TestExecutor(
          test_desc, self.make_uid(), trigger, self._test_options)

      _LOG.info('Executing test: %s', self.descriptor.code_info.name)
      self.TEST_INSTANCES[self.uid] = self
      self._executor.start()

    try:
      self._executor.wait()
    except KeyboardInterrupt:
      # The SIGINT handler only raises the KeyboardInterrupt once, so only retry
      # that once.
      self._executor.wait()
      raise
    finally:
      try:
        final_state = self._executor.finalize()

        _LOG.debug('Test completed for %s, outputting now.',
                   final_state.test_record.metadata['test_name'])
        for output_cb in self._test_options.output_callbacks:
          try:
            output_cb(final_state.test_record)
          except Exception:  # pylint: disable=broad-except
            _LOG.exception(
                'Output callback %s raised; continuing anyway', output_cb)
        # Make sure the final outcome of the test is printed last and in a
        # noticeable color so it doesn't get scrolled off the screen or missed.
        if final_state.test_record.outcome == test_record.Outcome.ERROR:
          for detail in final_state.test_record.outcome_details:
            console_output.error_print(detail.description)
        else:
          colors = collections.defaultdict(lambda: colorama.Style.BRIGHT)
          colors[test_record.Outcome.PASS] = ''.join((colorama.Style.BRIGHT,
                                                      colorama.Fore.GREEN))
          colors[test_record.Outcome.FAIL] = ''.join((colorama.Style.BRIGHT,
                                                      colorama.Fore.RED))
          msg_template = 'test: {name}  outcome: {color}{outcome}{rst}'
          console_output.banner_print(msg_template.format(
              name=final_state.test_record.metadata['test_name'],
              color=colors[final_state.test_record.outcome],
              outcome=final_state.test_record.outcome.name,
              rst=colorama.Style.RESET_ALL))
      finally:
        del self.TEST_INSTANCES[self.uid]
        self._executor = None

    return final_state.test_record.outcome == test_record.Outcome.PASS
예제 #4
0
    def execute(self,
                test_start: Optional[phase_descriptor.PhaseT] = None,
                profile_filename: Optional[Text] = None) -> bool:
        """Starts the framework and executes the given test.

    Args:
      test_start: Either a trigger phase for starting the test, or a function
        that returns a DUT ID. If neither is provided, defaults to not setting
        the DUT ID.
      profile_filename: Name of file to put profiling stats into. This also
        enables profiling data collection.

    Returns:
      Boolean indicating whether the test failed (False) or passed (True).

    Raises:
      InvalidTestStateError: if this test is already being executed.
    """
        phase_descriptor.check_for_duplicate_results(
            self._test_desc.phase_sequence.all_phases(),
            self._test_options.diagnosers)
        phase_collections.check_for_duplicate_subtest_names(
            self._test_desc.phase_sequence)
        # Lock this section so we don't .stop() the executor between instantiating
        # it and .Start()'ing it, doing so does weird things to the executor state.
        with self._lock:
            # Sanity check to make sure someone isn't doing something weird like
            # trying to Execute() the same test twice in two separate threads.  We
            # hold the lock between here and Start()'ing the executor to guarantee
            # that only one thread is successfully executing the test.
            if self._executor:
                raise InvalidTestStateError('Test already running',
                                            self._executor)

            # Snapshot some things we care about and store them.
            self._test_desc.metadata['test_name'] = self._test_options.name
            self._test_desc.metadata['config'] = CONF._asdict()
            self.last_run_time_millis = util.time_millis()

            if isinstance(test_start, types.LambdaType):

                @phase_descriptor.PhaseOptions()
                def trigger_phase(test):
                    test.test_record.dut_id = typing.cast(
                        types.LambdaType, test_start)()

                trigger = trigger_phase
            else:
                trigger = test_start

            if CONF.capture_source:
                trigger.code_info = htf_test_record.CodeInfo.for_function(
                    trigger.func)

            self._executor = test_executor.TestExecutor(
                self._test_desc,
                self.make_uid(),
                trigger,
                self._test_options,
                run_with_profiling=profile_filename is not None)

            _LOG.info('Executing test: %s', self.descriptor.code_info.name)
            self.TEST_INSTANCES[self.uid] = self
            self._executor.start()

        try:
            self._executor.wait()
        except KeyboardInterrupt:
            # The SIGINT handler only raises the KeyboardInterrupt once, so only retry
            # that once.
            self._executor.wait()
            raise
        finally:
            try:
                final_state = self._executor.finalize()

                _LOG.debug('Test completed for %s, outputting now.',
                           final_state.test_record.metadata['test_name'])
                test_executor.combine_profile_stats(
                    self._executor.phase_profile_stats, profile_filename)
                for output_cb in self._test_options.output_callbacks:
                    try:
                        output_cb(final_state.test_record)
                    except Exception:  # pylint: disable=broad-except
                        stacktrace = traceback.format_exc()
                        _LOG.error(
                            'Output callback %s raised:\n%s\nContinuing anyway...',
                            output_cb, stacktrace)

                # Make sure the final outcome of the test is printed last and in a
                # noticeable color so it doesn't get scrolled off the screen or missed.
                if final_state.test_record.outcome == htf_test_record.Outcome.ERROR:
                    for detail in final_state.test_record.outcome_details:
                        console_output.error_print(detail.description)
                else:
                    colors = collections.defaultdict(
                        lambda: colorama.Style.BRIGHT)
                    colors[htf_test_record.Outcome.PASS] = ''.join(
                        (colorama.Style.BRIGHT, colorama.Fore.GREEN))  # pytype: disable=wrong-arg-types
                    colors[htf_test_record.Outcome.FAIL] = ''.join(
                        (colorama.Style.BRIGHT, colorama.Fore.RED))  # pytype: disable=wrong-arg-types
                    msg_template = (
                        'test: {name}  outcome: {color}{outcome}{marginal}{rst}'
                    )
                    console_output.banner_print(
                        msg_template.format(
                            name=final_state.test_record.metadata['test_name'],
                            color=(colorama.Fore.YELLOW
                                   if final_state.test_record.marginal else
                                   colors[final_state.test_record.outcome]),
                            outcome=final_state.test_record.outcome.name,
                            marginal=(' (MARGINAL)'
                                      if final_state.test_record.marginal else
                                      ''),
                            rst=colorama.Style.RESET_ALL))
            finally:
                del self.TEST_INSTANCES[self.uid]
                self._executor.close()
                self._executor = None

        return final_state.test_record.outcome == htf_test_record.Outcome.PASS