Example #1
0
    def setUp(self):
        self.process = Process("Process")
        self.context = Context(self.process)

        # Create a fake PandA with a pulse block
        self.panda = ManagerController("PANDA", "/tmp")
        controller = BasicController("PANDA:PULSE3")
        self.pulse_part = PulsePart("part")
        controller.add_part(self.pulse_part)
        self.process.add_controller(controller)
        self.panda.add_part(
            ChildPart("PULSE3",
                      "PANDA:PULSE3",
                      initial_visibility=True,
                      stateful=False))
        self.process.add_controller(self.panda)

        # And the detector
        self.config_dir = tmp_dir("config_dir")
        for c in detector_block("DET", config_dir=self.config_dir.value):
            self.process.add_controller(c)

        # Make the child block holding panda and pmac mri
        self.child = self.create_child_block(
            panda_pulse_trigger_block,
            self.process,
            mri="SCAN:PULSE",
            panda="PANDA",
            detector="DET",
        )

        # And our part under test
        self.o = PandAPulseTriggerPart("detTrigger", "SCAN:PULSE")

        # Add in a scan block
        self.scan = RunnableController("SCAN", "/tmp")
        self.scan.add_part(DetectorChildPart("det", "DET", True))
        self.scan.add_part(self.o)
        self.process.add_controller(self.scan)

        # Now start the process off and tell the panda which sequencer tables
        # to use
        self.process.start()
        exports = ExportTable.from_rows([
            ("PULSE3.width", "detTriggerWidth"),
            ("PULSE3.step", "detTriggerStep"),
            ("PULSE3.delay", "detTriggerDelay"),
            ("PULSE3.pulses", "detTriggerPulses"),
        ])
        self.panda.set_exports(exports)
        self.tmpdir = tempfile.mkdtemp()
Example #2
0
    def setUp(self):
        self.p = Process("process1")
        self.context = Context(self.p)

        # Make a fast child, this will load the wait of 0.01 from saved file
        c1 = RunnableController(
            mri="fast", config_dir=DESIGN_PATH, use_git=False, initial_design="fast"
        )
        c1.add_part(WaitingPart("wait"))
        c1.add_part(ExposureDeadtimePart("dt", 0.001))
        c1.add_part(DatasetTablePart("dset"))
        self.p.add_controller(c1)

        # And a slow one, this has the same saved files as fast, but doesn't
        # load at startup
        c2 = RunnableController(mri="slow", config_dir=DESIGN_PATH, use_git=False)
        c2.add_part(WaitingPart("wait", 0.123))
        c2.add_part(DatasetTablePart("dset"))
        self.p.add_controller(c2)

        # And a faulty one, this is hidden at startup by default
        c3 = RunnableController(mri="faulty", config_dir=DESIGN_PATH, use_git=False)
        c3.add_part(FaultyPart("bad"))
        c3.add_part(DatasetTablePart("dset"))
        self.p.add_controller(c3)

        # And a top level one, this loads slow and fast designs for the
        # children on every configure (or load), but not at init
        self.ct = RunnableController(
            mri="top", config_dir=DESIGN_PATH, use_git=False, initial_design="default"
        )
        self.ct.add_part(
            DetectorChildPart(name="FAST", mri="fast", initial_visibility=True)
        )
        self.ct.add_part(
            DetectorChildPart(name="SLOW", mri="slow", initial_visibility=True)
        )
        self.ct.add_part(
            DetectorChildPart(name="BAD", mri="faulty", initial_visibility=False)
        )
        self.ct.add_part(
            DetectorChildPart(
                name="BAD2",
                mri="faulty",
                initial_visibility=False,
                initial_frames_per_step=0,
            )
        )
        self.fast_multi = MaybeMultiPart("fast")
        self.slow_multi = MaybeMultiPart("slow")
        self.ct.add_part(self.fast_multi)
        self.ct.add_part(self.slow_multi)
        self.p.add_controller(self.ct)

        # Some blocks to interface to them
        self.b = self.context.block_view("top")
        self.bf = self.context.block_view("fast")
        self.bs = self.context.block_view("slow")

        # start the process off
        self.p.start()
        self.tmpdir = tempfile.mkdtemp()
Example #3
0
 def setUp(self):
     self.detector_part = DetectorChildPart(
         name="CHILDPART", mri="child", initial_visibility=True
     )
Example #4
0
class TestDetectorChildPartMethods(unittest.TestCase):
    def setUp(self):
        self.detector_part = DetectorChildPart(
            name="CHILDPART", mri="child", initial_visibility=True
        )

    @patch("malcolm.modules.builtin.parts.ChildPart.on_init")
    def test_part_does_not_become_faulty_with_value_on_init(self, mock_on_init):
        mock_context = Mock(name="context_mock")

        self.detector_part.on_init(mock_context)

        mock_on_init.assert_called_once_with(mock_context)
        self.assertEqual(False, self.detector_part.faulty)

    @patch("malcolm.modules.builtin.parts.ChildPart.on_init")
    def test_part_becomes_faulty_with_BadValueError_on_init(self, mock_on_init):
        mock_context = Mock(name="context_mock")
        mock_on_init.side_effect = BadValueError()

        self.detector_part.on_init(mock_context)

        mock_on_init.assert_called_once_with(mock_context)
        self.assertEqual(True, self.detector_part.faulty)

    def test_on_run_has_future_when_child_is_armed(self):
        mock_context = Mock(name="context_mock")
        mock_child = Mock(name="child_mock")
        mock_child.state.value = RunnableStates.ARMED
        mock_child.run_async.return_value = "run_async_return_value"
        mock_child.when_value_matches_async.return_value = (
            "when_value_matches_return_value"
        )
        mock_context.block_view.return_value = mock_child

        self.detector_part.on_run(mock_context)

        assert self.detector_part.run_future == "run_async_return_value"
        mock_context.wait_all_futures.assert_called_once_with(
            "when_value_matches_return_value"
        )

    def test_on_run_resumes_when_child_is_not_armed(self):
        mock_context = Mock(name="context_mock")
        mock_child = Mock(name="child_mock")
        mock_child.state.value = RunnableStates.PAUSED
        mock_child.when_value_matches_async.return_value = (
            "when_value_matches_return_value"
        )
        mock_context.block_view.return_value = mock_child

        self.detector_part.on_run(mock_context)

        mock_child.resume.assert_called_once()
        mock_context.wait_all_futures.assert_called_once_with(
            "when_value_matches_return_value"
        )

    def test_on_run_raises_run_future_exception_when_child_is_in_fault(self):
        mock_context = Mock(name="context_mock")
        mock_child = Mock(name="child_mock")
        mock_run_future = Mock(name="run_future_mock")
        mock_run_future.exception.return_value = TimeoutError()
        mock_child.state = MockChildState([RunnableStates.ARMED, RunnableStates.FAULT])
        mock_child.run_async.return_value = mock_run_future
        mock_context.block_view.return_value = mock_child
        mock_context.wait_all_futures.side_effect = BadValueError()

        self.assertRaises(TimeoutError, self.detector_part.on_run, mock_context)

    def test_on_run_re_raises_BadValueError_when_child_is_not_in_fault(self):
        mock_context = Mock(name="context_mock")
        mock_child = Mock(name="child_mock")
        mock_child.state = MockChildState(RunnableStates.ARMED)
        mock_context.block_view.return_value = mock_child
        mock_context.wait_all_futures.side_effect = BadValueError

        self.assertRaises(BadValueError, self.detector_part.on_run, mock_context)