示例#1
0
    async def test_disconnect_stop_exposure_exception(self):
        """Test that `disconnect` does not raise if `stop_exposure` raises, but
        does log an error message, and continues with deactivating the device.
        """
        duration = 5  # seconds
        spec = AvsFiberSpectrograph()
        self.patch.return_value.AVS_StopMeasure.return_value = (
            AvsReturnCode.ERR_INVALID_PARAMETER.value)

        t0 = time.monotonic()
        task = asyncio.create_task(spec.expose(duration))
        await asyncio.sleep(0.1)  # give the event loop time to start
        try:
            with self.assertLogs(spec.log, "ERROR"):
                spec.disconnect()
        except AvsReturnError:
            self.fail(
                "disconnect() should not raise an exception, even if `stop_exposure` does."
            )
        with pytest.raises(asyncio.CancelledError):
            await task
        t1 = time.monotonic()

        # cancelling the task should make it end much sooner than the duration
        assert t1 - t0 < 1
        self.patch.return_value.AVS_StopMeasure.assert_called_with(self.handle)
        self.patch.return_value.AVS_Deactivate.assert_called_once_with(
            self.handle)
        self.patch.return_value.AVS_Done.assert_called_once_with()
        assert spec.handle is None
示例#2
0
    async def test_expose_raises_if_active_exposure(self):
        """Starting a new exposure while one is currently active should
        raise.
        """
        duration = 0.2  # seconds
        spec = AvsFiberSpectrograph()

        task = asyncio.create_task(spec.expose(duration))
        await asyncio.sleep(0.1)  # give the event loop time to start
        with pytest.raises(RuntimeError, match="Cannot start new exposure"):
            task2 = asyncio.create_task(spec.expose(duration))
            await task2
        await task
        # in addition to raising, should have only called these functions once
        self.patch.return_value.AVS_PrepareMeasure.assert_called_once()
        self.patch.return_value.AVS_Measure.assert_called_once_with(
            self.handle, 0, 1)
        self.patch.return_value.AVS_GetScopeData.assert_called_once()
示例#3
0
 async def check_duration_fails(duration):
     spec = AvsFiberSpectrograph()
     with pytest.raises(RuntimeError,
                        match="Exposure duration not in valid range:"):
         # timeout=1s because the command should fail immediately.
         await asyncio.wait_for(spec.expose(duration), 1)
     self.patch.return_value.AVS_PrepareMeasure.assert_not_called()
     self.patch.return_value.AVS_Measure.assert_not_called()
     self.patch.return_value.AVS_PollScan.assert_not_called()
     self.patch.return_value.AVS_GetScopeData.assert_not_called()
示例#4
0
    async def test_stop_exposure(self):
        """Test that `stop_exposure` ends the active `expose`."""
        duration = 5  # seconds
        spec = AvsFiberSpectrograph()

        t0 = time.monotonic()
        task = asyncio.create_task(spec.expose(duration))
        await asyncio.sleep(0.1)  # give the event loop time to start
        spec.stop_exposure()
        with pytest.raises(asyncio.CancelledError):
            await task
        t1 = time.monotonic()

        # cancelling the task should make it end much sooner than the duration
        assert t1 - t0 < 1
        self.patch.return_value.AVS_StopMeasure.assert_called_with(self.handle)
示例#5
0
    async def test_stop_exposure_during_poll_loop(self):
        """Test that `stop_exposure` ends the active `expose` when called
        during the `PollData` loop.
        """
        duration = 0.2  # seconds
        # repeat "no data" forever, so that `stop` will trigger during polling
        self.patch.return_value.AVS_PollScan.side_effect = itertools.repeat(0)
        spec = AvsFiberSpectrograph()

        task = asyncio.create_task(spec.expose(duration))
        await asyncio.sleep(duration + 0.1
                            )  # wait until we are in the poll loop
        spec.stop_exposure()
        with pytest.raises(asyncio.CancelledError):
            await task

        self.patch.return_value.AVS_StopMeasure.assert_called_with(self.handle)
        self.patch.return_value.AVS_PollScan.assert_called_with(self.handle)
        self.patch.return_value.AVS_GetScopeData.assert_not_called()
示例#6
0
    async def test_stop_exposure_fails(self):
        """Test `AVS_StopMeasure` returning an error: the existing exposure
        task should be cancelled, but `stop_exposure` should also raise."""
        duration = 5  # seconds
        self.patch.return_value.AVS_StopMeasure.return_value = (
            AvsReturnCode.ERR_TIMEOUT.value)
        spec = AvsFiberSpectrograph()

        t0 = time.monotonic()
        task = asyncio.create_task(spec.expose(duration))
        await asyncio.sleep(0.1)  # give the event loop time to start
        with pytest.raises(AvsReturnError, match="StopMeasure"):
            spec.stop_exposure()
        with pytest.raises(asyncio.CancelledError):
            await task
        t1 = time.monotonic()

        # cancelling the task should make it end much sooner than the duration
        assert t1 - t0 < 1
        self.patch.return_value.AVS_StopMeasure.assert_called_with(self.handle)
示例#7
0
    async def test_expose_PollScan_timeout(self):
        """Test that `expose` raises if it has to wait too long when
        polling.
        """
        duration = 0.5  # seconds
        # Have the PollScan just run forever.
        self.patch.return_value.AVS_PollScan.side_effect = itertools.repeat(0)

        spec = AvsFiberSpectrograph()
        # asyncio.TimeoutError would be raised if the `wait_for` times out,
        # but the message would not include this text.
        with pytest.raises(asyncio.TimeoutError,
                           match="Timeout polling for exposure to be ready"):
            # Use `wait_for` to keep `expose` from hanging if there is a bug.
            await asyncio.wait_for(spec.expose(duration), 2)
        self.patch.return_value.AVS_PrepareMeasure.assert_called_once()
        self.patch.return_value.AVS_Measure.assert_called_once_with(
            self.handle, 0, 1)
        # PollScan will be called a hundred times or so.
        self.patch.return_value.AVS_PollScan.assert_called()