Example #1
0
    async def test_stop_while_paused(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            wait_time = 5
            await self.configure_and_check(script, wait_time=wait_time)

            # set a stop checkpoint
            setCheckpoints_data = script.cmd_setCheckpoints.DataType()
            start_checkpoint = "start"
            setCheckpoints_data.pause = start_checkpoint
            await script.do_setCheckpoints(setCheckpoints_data)
            assert script.checkpoints.pause == start_checkpoint
            assert script.checkpoints.stop == ""

            run_data = script.cmd_run.DataType()
            asyncio.create_task(script.do_run(run_data))
            while script.state.lastCheckpoint != "start":
                await asyncio.sleep(0)
            assert script.state.state == ScriptState.PAUSED
            stop_data = script.cmd_stop.DataType()
            await script.do_stop(stop_data)
            await asyncio.wait_for(script.done_task, timeout=STD_TIMEOUT)
            assert script.state.lastCheckpoint == start_checkpoint
            assert script.state.numCheckpoints == 1
            assert script.state.state == ScriptState.STOPPED
            duration = (script.timestamps[ScriptState.STOPPING] -
                        script.timestamps[ScriptState.RUNNING])
            # the script ran quickly because we stopped the script
            # just as soon as it paused at the "start" checkpoint
            desired_duration = 0
            print(f"test_stop_while_paused duration={duration:0.2f}")
            assert duration > 0.0
            assert abs(duration - desired_duration) < 0.2
Example #2
0
    async def test_stop_while_running(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            wait_time = 5
            pause_time = 0.5
            await self.configure_and_check(script, wait_time=wait_time)

            start_checkpoint = "start"
            run_data = script.cmd_run.DataType()
            asyncio.create_task(script.do_run(run_data))
            while script.state.lastCheckpoint != start_checkpoint:
                await asyncio.sleep(0)
            assert script.state.state == ScriptState.RUNNING
            await asyncio.sleep(pause_time)
            stop_data = script.cmd_stop.DataType()
            await script.do_stop(stop_data)
            await asyncio.wait_for(script.done_task, timeout=STD_TIMEOUT)
            assert script.state.lastCheckpoint == start_checkpoint
            assert script.state.numCheckpoints == 1
            assert script.state.state == ScriptState.STOPPED
            duration = (script.timestamps[ScriptState.STOPPING] -
                        script.timestamps[ScriptState.RUNNING])
            # we waited `pause_time` seconds after the "start" checkpoint
            desired_duration = pause_time
            print(f"test_stop_while_running duration={duration:0.2f}")
            assert abs(duration - desired_duration) < 0.2
Example #3
0
    async def test_stop_at_checkpoint(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            wait_time = 0.1
            await self.configure_and_check(script, wait_time=wait_time)

            # set a stop checkpoint
            setCheckpoints_data = script.cmd_setCheckpoints.DataType()
            end_checkpoint = "end"
            setCheckpoints_data.stop = end_checkpoint
            await script.do_setCheckpoints(setCheckpoints_data)
            assert script.checkpoints.pause == ""
            assert script.checkpoints.stop == end_checkpoint

            run_data = script.cmd_run.DataType()
            await asyncio.wait_for(script.do_run(run_data),
                                   timeout=STD_TIMEOUT)
            await asyncio.wait_for(script.done_task, timeout=STD_TIMEOUT)
            assert script.state.lastCheckpoint == end_checkpoint
            assert script.state.numCheckpoints == 2
            assert script.state.state == ScriptState.STOPPED
            duration = (script.timestamps[ScriptState.STOPPING] -
                        script.timestamps[ScriptState.RUNNING])
            # waited and then stopped at the "end" checkpoint
            desired_duration = wait_time
            print(f"test_stop_at_checkpoint duration={duration:0.2f}")
            assert abs(duration - desired_duration) < 0.2
Example #4
0
    async def test_next_supplemented_group_id(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            await self.configure_and_check(script)
            group_id = script.group_id
            for i in range(5):
                # Format some other way than an f-string,
                # in order to have a different implementation than Script
                desired_supplemented_id = "%s#%s" % (group_id, i + 1)
                supplemented_id = script.next_supplemented_group_id()
                assert supplemented_id == desired_supplemented_id

            # Set a new group ID. This should reset the subgroup counter.
            new_group_id = group_id + " modified"
            group_id_data = script.cmd_setGroupId.DataType()
            group_id_data.groupId = new_group_id
            await script.do_setGroupId(group_id_data)

            for i in range(5):
                desired_supplemented_id = "%s#%s" % (new_group_id, i + 1)
                supplemented_id = script.next_supplemented_group_id()
                assert supplemented_id == desired_supplemented_id

            # Clear the group ID; getting a supplemened group ID should fail
            group_id_data = script.cmd_setGroupId.DataType()
            group_id_data.groupId = ""
            await script.do_setGroupId(group_id_data)
            with pytest.raises(RuntimeError):
                script.next_supplemented_group_id()
Example #5
0
    async def test_setCheckpoints(self) -> None:
        async with salobj.TestScript(index=self.index) as script:

            # try valid values
            data = script.cmd_setCheckpoints.DataType()
            for pause, stop in (
                ("something", ""),
                ("", "something_else"),
                (".*", "start|end"),
            ):
                data.pause = pause
                data.stop = stop
                await script.do_setCheckpoints(data)
                assert script.checkpoints.pause == pause
                assert script.checkpoints.stop == stop

            # try with at least one checkpoint not a valid regex;
            # do_setCheckpoints should raise and not change the checkpoints
            initial_pause = "initial_pause"
            initial_stop = "initial_stop"
            data.pause = initial_pause
            data.stop = initial_stop
            await script.do_setCheckpoints(data)
            for bad_pause, bad_stop in (("(", ""), ("", "("), ("[", "[")):
                data.pause = bad_pause
                data.stop = bad_stop
                with pytest.raises(salobj.ExpectedError):
                    await script.do_setCheckpoints(data)
                assert script.checkpoints.pause == initial_pause
                assert script.checkpoints.stop == initial_stop
Example #6
0
    async def test_set_state_and_attributes(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            # check keep_old_reason argument of set_state
            reason = "initial reason"
            additional_reason = "check append"
            await script.set_state(reason=reason)
            await script.set_state(reason=additional_reason,
                                   keep_old_reason=True)
            assert script.state.reason == reason + "; " + additional_reason

            bad_state = 1 + max(s.value for s in ScriptState)
            with pytest.raises(ValueError):
                await script.set_state(bad_state)
            script.state.state = bad_state
            assert script.state_name == f"UNKNOWN({bad_state})"
            assert not script._is_exiting

            await script.set_state(ScriptState.CONFIGURED)
            assert script.state_name == "CONFIGURED"

            # check assert_states
            all_states = set(ScriptState)
            for state in ScriptState:
                await script.set_state(state)
                assert script.state_name == state.name
                with pytest.raises(salobj.ExpectedError):
                    script.assert_state(
                        "should fail because state not in allowed states",
                        all_states - set([state]),
                    )

                script.assert_state("should pass", [state])
                script._is_exiting = True
                with pytest.raises(salobj.ExpectedError):
                    script.assert_state("should fail because exiting", [state])
                script._is_exiting = False

                # check that checkpoint is prohibited
                # unless state is RUNNING
                if state == ScriptState.RUNNING:
                    continue
                with pytest.raises(RuntimeError):
                    await script.checkpoint("foo")

            assert not script.done_task.done()
Example #7
0
    async def check_fail(self, fail_run: bool) -> None:
        """Check failure in run or cleanup.

        Parameters
        ----------
        fail_run : `bool`
            If true then fail in the script's ``run`` method,
            else fail in the script's ``cleanup`` method.
        """
        wait_time = 0.1
        async with salobj.TestScript(index=self.index) as script:
            if fail_run:
                await self.configure_and_check(script, fail_run=True)
            else:
                await self.configure_and_check(script, fail_cleanup=True)

            run_data = script.cmd_run.DataType()
            await asyncio.wait_for(script.do_run(run_data),
                                   timeout=STD_TIMEOUT)
            if fail_run:
                await asyncio.wait_for(script.done_task, timeout=STD_TIMEOUT)
                assert script.state.lastCheckpoint == "start"
                assert script.state.numCheckpoints == 1
                assert script.state.state == ScriptState.FAILED
                end_run_state = ScriptState.FAILING
            else:
                with pytest.raises(salobj.ExpectedError):
                    await asyncio.wait_for(script.done_task,
                                           timeout=STD_TIMEOUT)
                assert script.state.lastCheckpoint == "end"
                assert script.state.numCheckpoints == 2
                end_run_state = ScriptState.ENDING
            duration = (script.timestamps[end_run_state] -
                        script.timestamps[ScriptState.RUNNING])
            # if fail_run then failed before waiting,
            # otherwise failed after
            desired_duration = 0 if fail_run else wait_time
            print(
                f"test_fail duration={duration:0.3f} with fail_run={fail_run}")
            assert abs(duration - desired_duration) < 0.2
Example #8
0
 async def test_zero_index(self) -> None:
     with pytest.raises(ValueError):
         salobj.TestScript(index=0)
Example #9
0
    async def test_pause(self) -> None:
        async with salobj.TestScript(index=self.index) as script:
            # Cannot run in UNCONFIGURED state.
            run_data = script.cmd_run.DataType()
            with pytest.raises(salobj.ExpectedError):
                await script.do_run(run_data)

            # Test configure with data for a non-existent argument.
            configure_data = script.cmd_configure.DataType()
            configure_data.config = "no_such_arg: 1"
            with pytest.raises(salobj.ExpectedError):
                await script.do_configure(configure_data)
            assert script.state.state == ScriptState.UNCONFIGURED

            # Test configure with invalid yaml.
            configure_data = script.cmd_configure.DataType()
            configure_data.config = "a : : 2"
            with pytest.raises(salobj.ExpectedError):
                await script.do_configure(configure_data)
            assert script.state.state == ScriptState.UNCONFIGURED

            # Test configure with yaml that makes a string, not a dict.
            configure_data = script.cmd_configure.DataType()
            configure_data.config = "just_a_string"
            with pytest.raises(salobj.ExpectedError):
                await script.do_configure(configure_data)
            assert script.state.state == ScriptState.UNCONFIGURED

            # Test configure with yaml that makes a list, not a dict.
            configure_data = script.cmd_configure.DataType()
            configure_data.config = "['not', 'a', 'dict']"
            with pytest.raises(salobj.ExpectedError):
                await script.do_configure(configure_data)
            assert script.state.state == ScriptState.UNCONFIGURED

            # Now test valid configuration; specify nonexistent checkpoints
            # to test that the configure command handles checkpoints at all.
            wait_time = 0.5
            # Specify a log level that is not the default (which is INFO)
            # and is only slightly more verbose than INFO.
            log_level = logging.INFO - 1
            prelim_pause_checkpoint = "preliminary nonexistent pause checkpoint"
            prelim_stop_checkpoint = "preliminary nonexistent stop checkpoint"
            await self.configure_and_check(
                script,
                wait_time=wait_time,
                log_level=log_level,
                pause_checkpoint=prelim_pause_checkpoint,
                stop_checkpoint=prelim_stop_checkpoint,
            )
            assert script.state.numCheckpoints == 0

            # Set a pause checkpoint that exists.
            setCheckpoints_data = script.cmd_setCheckpoints.DataType()
            start_checkpoint = "start"
            end_checkpoint = "end"
            nonexistent_checkpoint = "nonexistent checkpoint"
            setCheckpoints_data.pause = start_checkpoint
            setCheckpoints_data.stop = nonexistent_checkpoint
            await script.do_setCheckpoints(setCheckpoints_data)
            assert script.checkpoints.pause == start_checkpoint
            assert script.checkpoints.stop == nonexistent_checkpoint

            # Run the script.
            run_data = script.cmd_run.DataType()
            run_task = asyncio.create_task(script.do_run(run_data))
            niter = 0
            while script.state.state != ScriptState.PAUSED:
                niter += 1
                await asyncio.sleep(0)
            assert script.state.lastCheckpoint == start_checkpoint
            assert script.state.numCheckpoints == 1
            assert script.checkpoints.pause == start_checkpoint
            assert script.checkpoints.stop == nonexistent_checkpoint
            resume_data = script.cmd_resume.DataType()
            await script.do_resume(resume_data)
            await asyncio.wait_for(run_task, timeout=STD_TIMEOUT)
            await asyncio.wait_for(script.done_task, timeout=STD_TIMEOUT)
            assert script.state.lastCheckpoint == end_checkpoint
            assert script.state.numCheckpoints == 2
            duration = (script.timestamps[ScriptState.ENDING] -
                        script.timestamps[ScriptState.RUNNING])
            desired_duration = wait_time
            print(f"test_pause duration={duration:0.2f}")
            assert abs(duration - desired_duration) < 0.2