Exemple #1
0
    def get(self, file_name, attachment_name):
        # TODO(Kenadia): Implement the history item handler. The implementation
        # depends on the format used to store test records on disk.
        fn = os.path.join(self.history_path, file_name)
        if not os.path.isfile(fn):
            self.write("Not found")
            self.set_status(404)
            return

        with open(fn, mode="rb") as f:
            me = mfg_event_pb2.MfgEvent()
            me.ParseFromString(f.read())
            # TODO - could use sha1 here to check?
            desired_real = [
                a for a in me.attachment if a.name == attachment_name
            ]
            if len(desired_real) > 0:
                try:
                    mimetype = next(
                        k for k, v in test_runs_converter.MIMETYPE_MAP.items()
                        if v == desired_real[0].type)
                except StopIteration:
                    mimetype = "application/octet-stream"
                self.set_header("Content-Type", mimetype)
                self.write(desired_real[0].value_binary)
                self.set_status(200)
            else:
                self.write("some, but no match?!")
                self.set_status(404)
    def test_copy_attachments_from_phase(self):
        first_attachment_name = 'first_attachment_name'
        first_attachment = _create_hacked_massive_attachment()
        expected_first_attachment_proto = mfg_event_pb2.EventAttachment(
            name=first_attachment_name,
            value_binary=first_attachment.data,
            type=test_runs_pb2.TEXT_UTF8)

        other_attachment_name = 'mock-attachment-name1'
        other_attachment = _create_hacked_massive_attachment()
        expected_other_attachment_proto = mfg_event_pb2.EventAttachment(
            name=other_attachment_name,
            value_binary=other_attachment.data,
            type=test_runs_pb2.TEXT_UTF8)

        phase = test_record.PhaseRecord(
            name='mock-phase-name',
            descriptor_id=1,
            codeinfo=self.create_codeinfo(),
            attachments={
                first_attachment_name: first_attachment,
                other_attachment_name: other_attachment,
            },
        )

        mfg_event = mfg_event_pb2.MfgEvent()
        # Leave attachment_cache as None so attachment sizes are irrelevant as
        # partial uploads are considered unavailable.
        copier = mfg_event_converter.PhaseCopier([phase])
        copier.copy_attachments(mfg_event)

        self.assertCountEqual(
            tuple(mfg_event.attachment),
            (expected_first_attachment_proto, expected_other_attachment_proto))
    def test_copy_measurements_from_phase(self):
        measurement = (self._create_and_set_measurement(
            'mock-measurement-name',
            5).doc('mock measurement docstring').with_units(
                units.Unit('radian')).in_range(1, 10))

        # We 'incorrectly' create a measurement with a unicode character as
        # a python2 string.  We don't want mfg_event_converter to guess at it's
        # encoding but we also don't want to fail after a test on conversion so it
        # replaces errors with a unicode question mark character.
        measurement_text = self._create_and_set_measurement('text', b'\xfd')
        measurement_unicode = self._create_and_set_measurement(
            'unicode', u'\ufffa')

        phase = test_record.PhaseRecord(
            name='mock-phase-name',
            descriptor_id=1,
            codeinfo=self.create_codeinfo(),
            measurements={
                'mock-measurement-name': measurement,
                'text': measurement_text,
                'unicode': measurement_unicode,
            },
        )

        mfg_event = mfg_event_pb2.MfgEvent()
        copier = mfg_event_converter.PhaseCopier([phase])
        copier.copy_measurements(mfg_event)

        # Names.
        created_measurements = sorted(mfg_event.measurement,
                                      key=lambda m: m.name)
        mock_measurement = created_measurements[0]
        text_measurement = created_measurements[1]
        unicode_measurement = created_measurements[2]
        self.assertEqual(mock_measurement.name, u'mock-measurement-name')
        self.assertEqual(text_measurement.name, u'text')
        self.assertEqual(unicode_measurement.name, u'unicode')

        # Basic measurement fields.
        self.assertEqual(mock_measurement.status, test_runs_pb2.PASS)
        self.assertEqual(mock_measurement.description,
                         'mock measurement docstring')
        self.assertEqual(mock_measurement.parameter_tag[0], 'mock-phase-name')
        self.assertEqual(mock_measurement.unit_code,
                         test_runs_pb2.Units.UnitCode.Value('RADIAN'))

        # Measurement value.
        self.assertEqual(mock_measurement.numeric_value, 5.0)
        # FFFD is unicode's '?'.  This occurs when we can't easily convert a python2
        # string to unicode.
        self.assertEqual(text_measurement.text_value, u'\ufffd')
        self.assertEqual(unicode_measurement.text_value, u'\ufffa')

        # Measurement validators.
        self.assertEqual(mock_measurement.numeric_minimum, 1.0)
        self.assertEqual(mock_measurement.numeric_maximum, 10.0)
        self.assertEqual(mock_measurement.name, u'mock-measurement-name')
        self.assertEqual(mock_measurement.name, u'mock-measurement-name')
Exemple #4
0
  def test_attach_record_as_json(self):
    record = test_record.TestRecord('mock-dut-id', 'mock-station-id')
    mfg_event = mfg_event_pb2.MfgEvent()
    mfg_event_converter._attach_record_as_json(mfg_event, record)

    self.assertEqual(mfg_event.attachment[0].name, 'OpenHTF_record.json')
    self.assertTrue(mfg_event.attachment[0].value_binary)  # Assert truthy.
    self.assertEqual(mfg_event.attachment[0].type, test_runs_pb2.TEXT_UTF8)
Exemple #5
0
  def test_attach_config(self):
    record = test_record.TestRecord('mock-dut-id', 'mock-station-id',
                                    metadata={'config': {'key': 'value'}})
    mfg_event = mfg_event_pb2.MfgEvent()
    mfg_event_converter._attach_config(mfg_event, record)

    self.assertEqual(mfg_event.attachment[0].name, 'config')
    self.assertTrue(mfg_event.attachment[0].value_binary)  # Assert truthy.
    self.assertEqual(mfg_event.attachment[0].type, test_runs_pb2.TEXT_UTF8)
def mfg_event_from_test_record(
    record: htf_test_record.TestRecord,
    attachment_cache: Optional[AttachmentCacheT] = None,
) -> mfg_event_pb2.MfgEvent:
    """Convert an OpenHTF TestRecord to an MfgEvent proto.

  Most fields are copied over directly and some are pulled out of metadata
  (listed below). Multi-dimensional measurements are stored only in the JSON
  dump of the record.

  Important Note:  This function mutates the test_record so any output callbacks
  called after this callback will operate on the mutated record.

  Metadata fields:
    test_name: The name field from the test's TestOptions.
    config: The OpenHTF config, as a dictionary.
    assembly_events: List of AssemblyEvent protos.
        (see proto/assembly_event.proto).
    operator_name: Name of the test operator.

  Args:
    record: An OpenHTF TestRecord.
    attachment_cache: Provides a lookup to get EventAttachment protos for
      already uploaded (or converted) attachments.

  Returns:
    An MfgEvent proto representing the given test record.
  """
    mfg_event = mfg_event_pb2.MfgEvent()

    _populate_basic_data(mfg_event, record)
    _attach_record_as_json(mfg_event, record)
    _attach_argv(mfg_event)
    _attach_config(mfg_event, record)

    # Only include assembly events if the test passed.
    if ('assembly_events' in record.metadata
            and mfg_event.test_status == test_runs_pb2.PASS):
        for assembly_event in record.metadata['assembly_events']:
            mfg_event.assembly_events.add().CopyFrom(assembly_event)
    convert_multidim_measurements(record.phases)
    phase_copier = PhaseCopier(phase_uniquizer(record.phases),
                               attachment_cache)
    phase_copier.copy_measurements(mfg_event)
    if not phase_copier.copy_attachments(mfg_event):
        mfg_event.test_run_type = mfg_event_pb2.TEST_RUN_PARTIAL

    return mfg_event
Exemple #7
0
  def testCopyAttachmentsFromPhase(self):
    attachment = test_record.Attachment('mock-data', 'text/plain')
    phase = test_record.PhaseRecord(
        name='mock-phase-name',
        descriptor_id=1,
        codeinfo=self.create_codeinfo(),
        attachments={'mock-attachment-name': attachment},
    )

    mfg_event = mfg_event_pb2.MfgEvent()
    copier = mfg_event_converter.PhaseCopier([phase])
    copier.copy_attachments(mfg_event)

    self.assertEqual(mfg_event.attachment[0].name, 'mock-attachment-name')
    self.assertEqual(mfg_event.attachment[0].value_binary, b'mock-data')
    self.assertEqual(mfg_event.attachment[0].type, test_runs_pb2.TEXT_UTF8)
    def test_copy_attachments_skips_if_too_much_data_and_returns_false(self):
        attachment_names = ('mock-attachment-name0', 'mock-attachment-name1')

        phase = test_record.PhaseRecord(
            name='mock-phase-name',
            descriptor_id=1,
            codeinfo=self.create_codeinfo(),
            attachments={
                name: _create_hacked_massive_attachment()
                for name in attachment_names
            },
        )

        mfg_event = mfg_event_pb2.MfgEvent()
        copier = mfg_event_converter.PhaseCopier(
            [phase],
            attachment_cache={},  # Indicates partial uploads are available.
        )
        self.assertFalse(copier.copy_attachments(mfg_event))

        self.assertEqual(len(mfg_event.attachment), 1)
    def test_copy_attachments_uses_attachment_cache_and_overcomes_size_limits(
            self):
        cached_attachment_name = 'cached_attachment_name'
        cached_attachment = _create_hacked_massive_attachment()

        cached_attachment_proto = mfg_event_pb2.EventAttachment(
            name='incorrect_name_to_ensure_cache_is_used',
            existing_blobref=mfg_event_pb2.EventAttachment.ExistingBlobRef(
                blob_id=b'dummy_id', size=cached_attachment.size))

        other_attachment_name = 'mock-attachment-name1'
        other_attachment = _create_hacked_massive_attachment()
        expected_other_attachment_proto = mfg_event_pb2.EventAttachment(
            name=other_attachment_name,
            value_binary=other_attachment.data,
            type=test_runs_pb2.TEXT_UTF8)

        phase = test_record.PhaseRecord(
            name='mock-phase-name',
            descriptor_id=1,
            codeinfo=self.create_codeinfo(),
            attachments={
                cached_attachment_name: cached_attachment,
                other_attachment_name: other_attachment,
            },
        )

        mfg_event = mfg_event_pb2.MfgEvent()
        copier = mfg_event_converter.PhaseCopier(
            [phase],
            attachment_cache={
                mfg_event_converter.AttachmentCacheKey(name=cached_attachment_name,
                                                       size=cached_attachment.size):
                cached_attachment_proto
            })
        self.assertTrue(copier.copy_attachments(mfg_event))

        self.assertCountEqual(
            tuple(mfg_event.attachment),
            (cached_attachment_proto, expected_other_attachment_proto))
Exemple #10
0
    def get(self, file_name):
        # TODO(Kenadia): Implement the history item handler. The implementation
        # depends on the format used to store test records on disk.
        # (Out of box disk format is fixed, only subclasses/alternative
        # implementations would need to concern themselves with that)

        fn = os.path.join(self.history_path, file_name)
        if not os.path.isfile(fn):
            self.write("Not found")
            self.set_status(404)
            return

        with open(fn, mode="rb") as f:
            me = mfg_event_pb2.MfgEvent()
            me.ParseFromString(f.read())
            from openhtf.core.test_record import TestRecord
            tr: TestRecord = mfg_event_converter.test_record_from_mfg_event(me)
            test_record_dict = data.convert_to_base_types(tr)
            test_state_dict = _test_state_from_record(
                test_record_dict, StationPubSub._last_execution_uid)
            self.set_status(200)
            self.write(test_state_dict)
Exemple #11
0
  def test_populate_basic_data(self):
    outcome_details = test_record.OutcomeDetails(
        code='mock-code',
        description='mock-description',
    )
    phase = test_record.PhaseRecord(
        name='mock-phase-name',
        descriptor_id=1,
        codeinfo=self.create_codeinfo(),
        start_time_millis=200,
        end_time_millis=400,
    )
    log_record = test_logs.LogRecord(
        level=logging.INFO,
        logger_name='mock-logger-name',
        source='mock-source',
        lineno=123,
        timestamp_millis=300,
        message='mock-message',
    )
    record = test_record.TestRecord(
        dut_id='mock-dut-id',
        station_id='mock-station-id',
        start_time_millis=100,
        end_time_millis=500,
        outcome=test_record.Outcome.PASS,
        outcome_details=[outcome_details],
        metadata={
            'test_name': 'mock-test-name',
            'operator_name': 'mock-operator-name',
            'test_version': 1.0,
            'test_description': 'mock-test-description',
        },
        phases=[phase],
        log_records=[log_record],
    )

    mfg_event = mfg_event_pb2.MfgEvent()
    mfg_event_converter._populate_basic_data(mfg_event, record)

    self.assertEqual(mfg_event.dut_serial, 'mock-dut-id')
    self.assertEqual(mfg_event.start_time_ms, 100)
    self.assertEqual(mfg_event.end_time_ms, 500)
    self.assertEqual(mfg_event.tester_name, 'mock-station-id')
    self.assertEqual(mfg_event.test_name, 'mock-test-name')
    self.assertEqual(mfg_event.test_version, '1.0')
    self.assertEqual(mfg_event.test_description, 'mock-test-description')
    self.assertEqual(mfg_event.test_status, test_runs_pb2.PASS)

    # Phases.
    self.assertEqual(mfg_event.phases[0].name, 'mock-phase-name')
    self.assertEqual(mfg_event.phases[0].description, 'mock-sourcecode')
    self.assertEqual(mfg_event.phases[0].timing.start_time_millis, 200)
    self.assertEqual(mfg_event.phases[0].timing.end_time_millis, 400)

    # Failure codes.
    self.assertEqual(mfg_event.failure_codes[0].code, 'mock-code')
    self.assertEqual(mfg_event.failure_codes[0].details, 'mock-description')

    # Test logs.
    self.assertEqual(mfg_event.test_logs[0].timestamp_millis, 300)
    self.assertEqual(mfg_event.test_logs[0].log_message, 'mock-message')
    self.assertEqual(mfg_event.test_logs[0].logger_name, 'mock-logger-name')
    self.assertEqual(mfg_event.test_logs[0].levelno, logging.INFO)
    self.assertEqual(mfg_event.test_logs[0].level,
                     test_runs_pb2.TestRunLogMessage.INFO)
    self.assertEqual(mfg_event.test_logs[0].log_source, 'mock-source')
    self.assertEqual(mfg_event.test_logs[0].lineno, 123)