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
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)
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
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)
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)