def test_mfg_event_from_test_record(self): """Test for the full conversion flow.""" record = test_record.TestRecord( dut_id='dut_serial', start_time_millis=1, end_time_millis=1, station_id='localhost', outcome=test_record.Outcome.PASS, ) record.outcome = test_record.Outcome.PASS record.metadata = { 'assembly_events': [assembly_event_pb2.AssemblyEvent()] * 2, 'config': {'mock-config-key': 'mock-config-value'}, 'operator_name': 'mock-operator-name', } record.phases = [ test_record.PhaseRecord( name='phase-%d' % idx, descriptor_id=idx, codeinfo=test_record.CodeInfo.uncaptured(), result=None, attachments={}, start_time_millis=1, end_time_millis=1 ) for idx in range(1, 5) ] for phase in record.phases: phase.measurements = { 'meas-1': measurements.Measurement('meas-1'), 'meas-2': measurements.Measurement('meas-2'), 'meas-3': measurements.Measurement('meas-3').with_dimensions('V'), } phase.attachments = { 'attach-1': test_record.Attachment(data='data-1', mimetype=''), 'attach-2': test_record.Attachment(data='data-2', mimetype=''), } mfg_event = mfg_event_converter.mfg_event_from_test_record(record) self.assertEqual(mfg_event.dut_serial, record.dut_id) self.assertEqual(len(mfg_event.assembly_events), 2) self.assertEqual(len(mfg_event.measurement), 8) self.assertEqual(sorted(m.name for m in mfg_event.measurement), ['meas-1_0', 'meas-1_1', 'meas-1_2', 'meas-1_3', 'meas-2_0', 'meas-2_1', 'meas-2_2', 'meas-2_3']) self.assertEqual(len(mfg_event.attachment), 15) self.assertEqual(sorted(str(m.name) for m in mfg_event.attachment), ['OpenHTF_record.json', 'argv', 'attach-1_0', 'attach-1_1', 'attach-1_2', 'attach-1_3', 'attach-2_0', 'attach-2_1', 'attach-2_2', 'attach-2_3', 'config', 'multidim_meas-3_0', 'multidim_meas-3_1', 'multidim_meas-3_2', 'multidim_meas-3_3'])
def wrapper(phase_func): phase_desc = openhtf.PhaseDescriptor.wrap_or_copy(phase_func) # Re-key this dict so we don't have to worry about collisions with # plug.plug() decorators on the phase function. Since we aren't # updating kwargs here, we don't have to worry about collisions with # kwarg names. monitor_plugs = { ('_' * idx) + measurement_name + '_monitor': plug.cls for idx, plug in enumerate(monitor_desc.plugs, start=1) } @openhtf.PhaseOptions(requires_state=True) @plugs.plug(update_kwargs=False, **monitor_plugs) @measurements.measures( measurements.Measurement(measurement_name).with_units( units).with_dimensions(uom.MILLISECOND)) @functools.wraps(phase_desc.func) def monitored_phase_func(test_state, *args, **kwargs): # Start monitor thread, it will run monitor_desc periodically. monitor_thread = _MonitorThread(measurement_name, monitor_desc, phase_desc.extra_kwargs, test_state, poll_interval_ms) monitor_thread.start() try: return phase_desc(test_state, *args, **kwargs) finally: monitor_thread.kill() monitor_thread.join() return monitored_phase_func
def _create_and_set_measurement(self, name, value): measured_value = measurements.MeasuredValue(name, is_value_set=False) measured_value.set(value) measurement = measurements.Measurement( name=name, outcome=measurements.Outcome.PASS) # Cannot be set in initialization. measurement.measured_value = measured_value return measurement
def _create_and_set_measurement(self, name, value): measured_value = measurements.MeasuredValue(name, is_value_set=False) measured_value.set(value) measurement = measurements.Measurement( name=name, outcome=measurements.Outcome.PASS, measured_value=measured_value) return measurement
def _maybe_make( meas: Union[Text, core_measurements.Measurement] ) -> core_measurements.Measurement: """Turn strings into Measurement objects if necessary.""" if isinstance(meas, core_measurements.Measurement): return meas elif isinstance(meas, six.string_types): return core_measurements.Measurement(meas, **kwargs) raise core_measurements.InvalidMeasurementTypeError( 'Expected Measurement or string', meas)
def create_multi_dim_measurement(cls): """Util function to create a test multi-dim measurement.""" measurement = measurements.Measurement('test_measurement') measurement.with_units('°C').with_dimensions('ms', 'assembly', 'zone') for t in range(10): for assembly in ['A', 'B', 'C']: for zone in range(3): temp = zone + t dims = (t, assembly, zone) measurement.measured_value[dims] = temp measurement.outcome = measurements.Outcome.PASS return measurement
def attachment_to_multidim_measurement(attachment, name=None): """Convert an OpenHTF test record attachment to a multi-dim measurement. This is a best effort attempt to reverse, as some data is lost in converting from a multidim to an attachment. Args: attachment: an `openhtf.test_record.Attachment` from a multi-dim. name: an optional name for the measurement. If not provided will use the name included in the attachment. Returns: An multi-dim `openhtf.Measurement`. """ data = json.loads(attachment.data) name = name or data.get('name') # attachment_dimn are a list of dicts with keys 'uom_suffix' and 'uom_code' attachment_dims = data.get('dimensions', []) # attachment_value is a list of lists [[t1, x1, y1, f1], [t2, x2, y2, f2]] attachment_values = data.get('value') attachment_outcome_str = data.get('outcome') if attachment_outcome_str not in TEST_RUN_STATUS_NAME_TO_MEASUREMENT_OUTCOME: # Fpr backward compatibility with saved data we'll convert integers to str try: attachment_outcome_str = test_runs_pb2.Status.Name( int(attachment_outcome_str)) except ValueError: attachment_outcome_str = None # Convert test status outcome str to measurement outcome outcome = TEST_RUN_STATUS_NAME_TO_MEASUREMENT_OUTCOME.get( attachment_outcome_str) # convert dimensions into htf.Dimensions _lazy_load_units_by_code() dims = [] for d in attachment_dims: # Try to convert into htf.Dimension including backwards compatibility. unit = UNITS_BY_CODE.get(d.get('uom_code'), units.NONE) description = d.get('name', '') dims.append(measurements.Dimension(description=description, unit=unit)) # Attempt to determine if units are included. if attachment_values and len(dims) == len(attachment_values[0]): # units provided units_ = dims[-1].unit dimensions = dims[:-1] else: units_ = None dimensions = dims # created dimensioned_measured_value and populate with values. measured_value = measurements.DimensionedMeasuredValue( name=name, num_dimensions=len(dimensions)) for row in attachment_values: coordinates = tuple(row[:-1]) val = row[-1] measured_value[coordinates] = val measurement = measurements.Measurement(name=name, units=units_, dimensions=tuple(dimensions), measured_value=measured_value, outcome=outcome) return measurement