示例#1
0
    def __init__(self, test_desc: 'test_descriptor.TestDescriptor',
                 execution_uid: Text,
                 test_options: 'test_descriptor.TestOptions'):
        """Initializer.

    Args:
      test_desc: openhtf.TestDescriptor instance describing the test to run,
        used to initialize some values here, but it is not modified.
      execution_uid: a unique uuid use to identify a test being run.
      test_options: test_options passed through from Test.
    """
        super(TestState, self).__init__()
        self._status = self.Status.WAITING_FOR_TEST_START  # type: TestState.Status

        self.test_record = test_record.TestRecord(
            dut_id=None,
            station_id=conf.station_id,
            code_info=test_desc.code_info,
            start_time_millis=0,
            # Copy metadata so we don't modify test_desc.
            metadata=copy.deepcopy(test_desc.metadata),
            diagnosers=test_options.diagnosers)
        logs.initialize_record_handler(execution_uid, self.test_record,
                                       self.notify_update)
        self.state_logger = logs.get_record_logger_for(execution_uid)
        self.plug_manager = plugs.PlugManager(test_desc.plug_types,
                                              self.state_logger)
        self.diagnoses_manager = diagnoses_lib.DiagnosesManager(
            self.state_logger.getChild('diagnoses'))
        self.running_phase_state = None  # type: Optional['PhaseState']
        self._running_test_api = None  # type: Optional['test_descriptor.TestApi']
        # TODO(arsharma): Change to Dict[Any, Any] when pytype handles it correctly.
        self.user_defined_state = {}  # type: Any
        self.execution_uid = execution_uid
        self.test_options = test_options
示例#2
0
  def __call__(self, test_state):
    """Invoke this Phase, passing in the appropriate args.

    By default, an openhtf.TestApi is passed as the first positional arg, but if
    the 'requires_state' option is set, then a test_state.TestState is passed
    instead. If no positional args are expected, then neither is passed in. In
    any case, keyword args are passed in based on extra_kwargs, set via
    with_args(), combined with plugs (plugs override extra_kwargs).

    Args:
      test_state: test_state.TestState for the currently executing Test.

    Returns:
      The return value from calling the underlying function.
    """
    kwargs = dict(self.extra_kwargs)
    kwargs.update(test_state.plug_manager.provide_plugs(
        (plug.name, plug.cls) for plug in self.plugs if plug.update_kwargs))

    if sys.version_info[0] < 3:
      arg_info = inspect.getargspec(self.func)
      keywords = arg_info.keywords
    else:
      arg_info = inspect.getfullargspec(self.func)
      keywords = arg_info.varkw
    # Pass in test_api if the phase takes *args, or **kwargs with at least 1
    # positional, or more positional args than we have keyword args.
    if arg_info.varargs or (keywords and len(arg_info.args) >= 1) or (
        len(arg_info.args) > len(kwargs)):
      # Underlying function has room for test_api as an arg. If it doesn't
      # expect it but we miscounted args, we'll get another error farther down.
      old_logger = test_state.logger

      # The logging module has a module _lock instance that is a threading.RLock
      # instance; it can cause deadlocks in Python 2.7 when a KillableThread is
      # killed while its release method is running.
      with threads.safe_lock_release_context(logging._lock):  # pylint: disable=protected-access
        # Update test_state's logger so that it is a phase-specific one.
        record_logger = logs.get_record_logger_for(test_state.execution_uid)
        test_state.logger = record_logger.getChild('phase').getChild(self.name)
      try:
        args = []
        if self.options.requires_state:
          args.append(test_state)
        else:
          args.append(test_state.test_api)

        if self.options.run_under_pdb:
          return pdb.runcall(self.func, *args, **kwargs)
        else:
          return self.func(*args, **kwargs)
      finally:
        test_state.logger = old_logger
    if self.options.run_under_pdb:
      return pdb.runcall(self.func, **kwargs)
    else:
      return self.func(**kwargs)
示例#3
0
  def __init__(self, test_desc, execution_uid, test_options):
    super(TestState, self).__init__()
    self._status = self.Status.WAITING_FOR_TEST_START

    self.test_record = test_record.TestRecord(
        dut_id=None, station_id=conf.station_id, code_info=test_desc.code_info,
        start_time_millis=0,
        # Copy metadata so we don't modify test_desc.
        metadata=copy.deepcopy(test_desc.metadata))
    logs.initialize_record_handler(
        execution_uid, self.test_record, self.notify_update)
    self.logger = logs.get_record_logger_for(execution_uid)
    self.plug_manager = plugs.PlugManager(
        test_desc.plug_types, self.logger.name)
    self.running_phase_state = None
    self.user_defined_state = {}
    self.execution_uid = execution_uid
    self.test_options = test_options
示例#4
0
    def __call__(self, test_state):
        """Invoke this Phase, passing in the appropriate args.

    By default, an openhtf.TestApi is passed as the first positional arg, but if
    the 'requires_state' option is set, then a test_state.TestState is passed
    instead. If no positional args are expected, then neither is passed in. In
    any case, keyword args are passed in based on extra_kwargs, set via
    with_args(), combined with plugs (plugs override extra_kwargs).

    Args:
      test_state: test_state.TestState for the currently executing Test.

    Returns:
      The return value from calling the underlying function.
    """
        kwargs = dict(self.extra_kwargs)
        kwargs.update(
            test_state.plug_manager.provide_plugs((plug.name, plug.cls)
                                                  for plug in self.plugs
                                                  if plug.update_kwargs))

        if sys.version_info[0] < 3:
            arg_info = inspect.getargspec(self.func)
            keywords = arg_info.keywords
        else:
            arg_info = inspect.getfullargspec(self.func)
            keywords = arg_info.varkw
        # Pass in test_api if the phase takes *args, or **kwargs with at least 1
        # positional, or more positional args than we have keyword args.
        if arg_info.varargs or (keywords and len(arg_info.args) >= 1) or (len(
                arg_info.args) > len(kwargs)):
            # Underlying function has room for test_api as an arg. If it doesn't
            # expect it but we miscounted args, we'll get another error farther down.
            # Update test_state's logger so that it's a phase-specific one.
            test_state.logger = logging.getLogger('.'.join(
                (logs.get_record_logger_for(test_state.execution_uid).name,
                 'phase', self.name)))
            return self.func(
                test_state if self.options.requires_state else
                test_state.test_api, **kwargs)
        return self.func(**kwargs)
示例#5
0
  def __call__(self, test_state):
    """Invoke this Phase, passing in the appropriate args.

    By default, an openhtf.TestApi is passed as the first positional arg, but if
    the 'requires_state' option is set, then a test_state.TestState is passed
    instead. If no positional args are expected, then neither is passed in. In
    any case, keyword args are passed in based on extra_kwargs, set via
    with_args(), combined with plugs (plugs override extra_kwargs).

    Args:
      test_state: test_state.TestState for the currently executing Test.

    Returns:
      The return value from calling the underlying function.
    """
    kwargs = dict(self.extra_kwargs)
    kwargs.update(test_state.plug_manager.provide_plugs(
        (plug.name, plug.cls) for plug in self.plugs if plug.update_kwargs))

    if sys.version_info[0] < 3:
      arg_info = inspect.getargspec(self.func)
      keywords = arg_info.keywords
    else:
      arg_info = inspect.getfullargspec(self.func)
      keywords = arg_info.varkw
    # Pass in test_api if the phase takes *args, or **kwargs with at least 1
    # positional, or more positional args than we have keyword args.
    if arg_info.varargs or (keywords and len(arg_info.args) >= 1) or (
        len(arg_info.args) > len(kwargs)):
      # Underlying function has room for test_api as an arg. If it doesn't
      # expect it but we miscounted args, we'll get another error farther down.
      # Update test_state's logger so that it's a phase-specific one.
      test_state.logger = logging.getLogger(
          '.'.join((logs.get_record_logger_for(test_state.execution_uid).name,
                    'phase', self.name)))
      return self.func(
          test_state if self.options.requires_state else test_state.test_api,
          **kwargs)
    return self.func(**kwargs)