mirror of
https://github.com/ivan-usov-org/bec.git
synced 2025-04-21 02:10:01 +02:00
1540 lines
51 KiB
Python
1540 lines
51 KiB
Python
import uuid
|
|
from unittest import mock
|
|
from bec_lib import BECMessage
|
|
|
|
import pytest
|
|
from utils import load_ScanServerMock
|
|
|
|
from bec_lib import MessageEndpoints
|
|
from scan_server.errors import DeviceMessageError, ScanAbortion
|
|
from scan_server.scan_assembler import ScanAssembler
|
|
from scan_server.scan_queue import (
|
|
InstructionQueueItem,
|
|
InstructionQueueStatus,
|
|
QueueManager,
|
|
RequestBlock,
|
|
RequestBlockQueue,
|
|
ScanQueue,
|
|
)
|
|
from scan_server.scan_worker import DeviceMsg, ScanWorker
|
|
|
|
|
|
def get_scan_worker() -> ScanWorker:
|
|
k = load_ScanServerMock()
|
|
return ScanWorker(parent=k)
|
|
|
|
|
|
class RequestBlockQueueMock(RequestBlockQueue):
|
|
request_blocks = []
|
|
_scanID = []
|
|
|
|
@property
|
|
def scanID(self):
|
|
return self._scanID
|
|
|
|
def append(self, msg):
|
|
pass
|
|
|
|
|
|
class InstructionQueueMock(InstructionQueueItem):
|
|
def __init__(self, parent: ScanQueue, assembler: ScanAssembler, worker: ScanWorker) -> None:
|
|
super().__init__(parent, assembler, worker)
|
|
self.queue = RequestBlockQueueMock(self, assembler)
|
|
# self.queue.active_rb = []
|
|
self.idx = 1
|
|
|
|
def append_scan_request(self, msg):
|
|
self.scan_msgs.append(msg)
|
|
self.queue.append(msg)
|
|
|
|
def __next__(self):
|
|
if (
|
|
self.status
|
|
in [
|
|
InstructionQueueStatus.RUNNING,
|
|
InstructionQueueStatus.DEFERRED_PAUSE,
|
|
InstructionQueueStatus.PENDING,
|
|
]
|
|
and self.idx < 5
|
|
):
|
|
self.idx += 1
|
|
return "instr_status"
|
|
|
|
else:
|
|
raise StopIteration
|
|
|
|
# while self.status == InstructionQueueStatus.PAUSED:
|
|
# return "instr_paused"
|
|
|
|
# return "instr"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instruction,devices",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samy",
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
["samy"],
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx", "samy"],
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
["samx", "samy"],
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="",
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
["samx", "samy"],
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="",
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "primary",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
["samx", "samy"],
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="",
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "nogroup",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
["samx", "samy"],
|
|
),
|
|
],
|
|
)
|
|
def test_get_devices_from_instruction(instruction, devices):
|
|
worker = get_scan_worker()
|
|
worker.scan_motors = devices
|
|
worker.readout_priority.update({"monitored": devices})
|
|
|
|
returned_devices = worker._get_devices_from_instruction(instruction)
|
|
|
|
if not instruction.content.get("device"):
|
|
group = instruction.content["parameter"].get("group")
|
|
if group == "primary":
|
|
assert returned_devices == worker.device_manager.devices.monitored_devices(
|
|
worker.scan_motors
|
|
)
|
|
elif group == "scan_motor":
|
|
assert returned_devices == devices
|
|
else:
|
|
assert returned_devices == []
|
|
else:
|
|
assert returned_devices == [worker.device_manager.devices[dev] for dev in devices]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instructions",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={"readout_priority": "monitored", "DIID": None},
|
|
),
|
|
],
|
|
)
|
|
def test_add_wait_group(instructions):
|
|
worker = get_scan_worker()
|
|
if instructions.metadata["DIID"]:
|
|
worker._add_wait_group(instructions)
|
|
assert worker._groups == {"scan_motor": {"samx": 3}}
|
|
|
|
worker._groups["scan_motor"] = {"samy": 2}
|
|
worker._add_wait_group(instructions)
|
|
assert worker._groups == {"scan_motor": {"samy": 2, "samx": 3}}
|
|
|
|
else:
|
|
with pytest.raises(DeviceMessageError) as exc_info:
|
|
worker._add_wait_group(instructions)
|
|
assert exc_info.value.args[0] == "Device message metadata does not contain a DIID entry."
|
|
|
|
|
|
def test_add_wait_group_to_existing_wait_group():
|
|
instr1 = BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
instr2 = BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={"readout_priority": "monitored", "DIID": 4},
|
|
)
|
|
worker = get_scan_worker()
|
|
worker._add_wait_group(instr1)
|
|
worker._add_wait_group(instr2)
|
|
assert worker._groups == {"scan_motor": {"samx": 4}}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instructions,wait_type",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samy",
|
|
action="wait",
|
|
parameter={
|
|
"type": "move",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
"move",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samy",
|
|
action="wait",
|
|
parameter={
|
|
"type": "read",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
"read",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samy",
|
|
action="wait",
|
|
parameter={
|
|
"type": "trigger",
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
"trigger",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samy",
|
|
action="wait",
|
|
parameter={
|
|
"type": None,
|
|
"group": "scan_motor",
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
),
|
|
None,
|
|
),
|
|
],
|
|
)
|
|
def test_wait_for_devices(instructions, wait_type):
|
|
worker = get_scan_worker()
|
|
|
|
with mock.patch.object(worker, "_wait_for_idle") as idle_mock:
|
|
with mock.patch.object(worker, "_wait_for_read") as read_mock:
|
|
with mock.patch.object(worker, "_wait_for_trigger") as trigger_mock:
|
|
if wait_type:
|
|
worker.wait_for_devices(instructions)
|
|
|
|
if wait_type == "move":
|
|
idle_mock.assert_called_once_with(instructions)
|
|
elif wait_type == "read":
|
|
read_mock.assert_called_once_with(instructions)
|
|
elif wait_type == "trigger":
|
|
trigger_mock.assert_called_once_with(instructions)
|
|
else:
|
|
with pytest.raises(DeviceMessageError) as exc_info:
|
|
worker.wait_for_devices(instructions)
|
|
assert exc_info.value.args[0] == "Unknown wait command"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instructions",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="complete",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="complete",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx", "samy"],
|
|
action="complete",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_complete_devices(instructions):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker, "_wait_for_status") as wait_for_status_mock:
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.complete_devices(instructions)
|
|
if instructions.content["device"]:
|
|
devices = instructions.content["device"]
|
|
if isinstance(devices, str):
|
|
devices = [devices]
|
|
else:
|
|
devices = [dev.name for dev in worker.device_manager.devices.enabled_devices]
|
|
|
|
wait_for_status_mock.assert_called_once_with(devices, instructions.metadata)
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="complete",
|
|
parameter={},
|
|
metadata=instructions.metadata,
|
|
).dumps(),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instructions",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="pre_scan",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 3},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_pre_scan(instructions):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
with mock.patch.object(worker, "_wait_for_status") as wait_for_status_mock:
|
|
worker.pre_scan(instructions)
|
|
devices = [dev.name for dev in worker.device_manager.devices.enabled_devices]
|
|
|
|
wait_for_status_mock.assert_called_once_with(devices, instructions.metadata)
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="pre_scan",
|
|
parameter={},
|
|
metadata=instructions.metadata,
|
|
).dumps(),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"device_status,devices,instr,abort",
|
|
[
|
|
(
|
|
[
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=True,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
],
|
|
[("samx", 4)],
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
False,
|
|
),
|
|
(
|
|
[
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=False,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "request",
|
|
},
|
|
)
|
|
],
|
|
[("samx", 4)],
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
False,
|
|
),
|
|
(
|
|
[
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=False,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
],
|
|
[("samx", 4)],
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
True,
|
|
),
|
|
(
|
|
[
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=False,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
],
|
|
[("samx", 4)],
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
False,
|
|
),
|
|
],
|
|
)
|
|
def test_check_for_failed_movements(device_status, devices, instr, abort):
|
|
worker = get_scan_worker()
|
|
if abort:
|
|
with pytest.raises(ScanAbortion):
|
|
worker.device_manager.producer._get_buffer[
|
|
MessageEndpoints.device_readback("samx")
|
|
] = BECMessage.DeviceMessage(signals={"samx": {"value": 4}}, metadata={}).dumps()
|
|
worker._check_for_failed_movements(device_status, devices, instr)
|
|
else:
|
|
worker._check_for_failed_movements(device_status, devices, instr)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg1,msg2,req_msg",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=False,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="samx",
|
|
success=True,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
),
|
|
],
|
|
)
|
|
def test_wait_for_idle(msg1, msg2, req_msg: BECMessage.DeviceReqStatusMessage):
|
|
worker = get_scan_worker()
|
|
|
|
with mock.patch.object(
|
|
worker.validate, "get_device_status", return_value=[req_msg.dumps()]
|
|
) as device_status:
|
|
worker.device_manager.producer._get_buffer[
|
|
MessageEndpoints.device_readback("samx")
|
|
] = BECMessage.DeviceMessage(signals={"samx": {"value": 4}}, metadata={}).dumps()
|
|
|
|
worker._add_wait_group(msg1)
|
|
if req_msg.content["success"]:
|
|
worker._wait_for_idle(msg2)
|
|
else:
|
|
with pytest.raises(ScanAbortion):
|
|
worker._wait_for_idle(msg2)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg1,msg2,req_msg",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
BECMessage.DeviceStatusMessage(
|
|
device="samx",
|
|
status=0,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
),
|
|
],
|
|
)
|
|
def test_wait_for_read(msg1, msg2, req_msg: BECMessage.DeviceReqStatusMessage):
|
|
worker = get_scan_worker()
|
|
|
|
with mock.patch.object(
|
|
worker.validate,
|
|
"get_device_status",
|
|
return_value=[req_msg.dumps()],
|
|
) as device_status:
|
|
with mock.patch.object(worker, "_check_for_interruption") as interruption_mock:
|
|
assert worker._groups == {}
|
|
worker._groups["scan_motor"] = {"samx": 3, "samy": 4}
|
|
worker.device_manager.producer._get_buffer[
|
|
MessageEndpoints.device_readback("samx")
|
|
] = BECMessage.DeviceMessage(signals={"samx": {"value": 4}}, metadata={}).dumps()
|
|
worker._add_wait_group(msg1)
|
|
worker._wait_for_read(msg2)
|
|
assert worker._groups == {"scan_motor": {"samy": 4}}
|
|
interruption_mock.assert_called_once()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="set",
|
|
parameter={"time": 0.1},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_wait_for_trigger(instr):
|
|
worker = get_scan_worker()
|
|
worker._last_trigger = instr
|
|
|
|
with mock.patch.object(worker.validate, "get_device_status") as status_mock:
|
|
with mock.patch.object(worker, "_check_for_interruption") as interruption_mock:
|
|
status_mock.return_value = [
|
|
BECMessage.DeviceReqStatusMessage(
|
|
device="eiger",
|
|
success=True,
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
).dumps(),
|
|
]
|
|
worker._wait_for_trigger(instr)
|
|
status_mock.assert_called_once_with(MessageEndpoints.device_req_status, ["eiger"])
|
|
interruption_mock.assert_called_once()
|
|
|
|
|
|
def test_wait_for_stage():
|
|
worker = get_scan_worker()
|
|
devices = ["samx", "samy"]
|
|
with mock.patch.object(worker.validate, "get_device_status") as status_mock:
|
|
with mock.patch.object(worker, "_check_for_interruption") as interruption_mock:
|
|
worker._wait_for_stage(True, devices, {})
|
|
status_mock.assert_called_once_with(MessageEndpoints.device_staged, devices)
|
|
interruption_mock.assert_called_once()
|
|
|
|
|
|
def test_wait_for_device_server():
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.parent, "wait_for_service") as service_mock:
|
|
worker._wait_for_device_server()
|
|
service_mock.assert_called_once_with("DeviceServer")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="set",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_set_devices(instr):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.set_devices(instr)
|
|
send_mock.assert_called_once_with(MessageEndpoints.device_instructions(), instr.dumps())
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="trigger",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_trigger_devices(instr):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.trigger_devices(instr)
|
|
devices = [dev.name for dev in worker.device_manager.devices.detectors()]
|
|
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="trigger",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
).dumps(),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="trigger",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_send_rpc(instr):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.send_rpc(instr)
|
|
send_mock.assert_called_once_with(MessageEndpoints.device_instructions(), instr.dumps())
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="read",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=[],
|
|
action="read",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
),
|
|
],
|
|
)
|
|
def test_read_devices(instr):
|
|
worker = get_scan_worker()
|
|
instr_devices = instr.content["device"]
|
|
if instr_devices is None:
|
|
instr_devices = []
|
|
worker.readout_priority.update({"monitored": instr_devices})
|
|
devices = [dev.name for dev in worker._get_devices_from_instruction(instr)]
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.read_devices(instr)
|
|
|
|
if instr.content.get("device"):
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="read",
|
|
parameter=instr.content["parameter"],
|
|
metadata=instr.metadata,
|
|
).dumps(),
|
|
)
|
|
else:
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="read",
|
|
parameter=instr.content["parameter"],
|
|
metadata=instr.metadata,
|
|
).dumps(),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr, devices, parameter, metadata",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="trigger",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
["samx"],
|
|
{"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
{"readout_priority": "monitored", "DIID": 3, "scanID": "scanID", "RID": "requestID"},
|
|
),
|
|
],
|
|
)
|
|
def test_kickoff_devices(instr, devices, parameter, metadata):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.kickoff_devices(instr)
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="kickoff",
|
|
parameter=parameter,
|
|
metadata=metadata,
|
|
).dumps(),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr, devices",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="trigger",
|
|
parameter={"value": 10, "wait_group": "scan_motor", "time": 30},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
),
|
|
None,
|
|
),
|
|
],
|
|
)
|
|
def test_publish_readback(instr, devices):
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker, "_get_readback", return_value=[{}]) as get_readback:
|
|
with mock.patch.object(worker.device_manager, "producer") as producer_mock:
|
|
worker._publish_readback(instr)
|
|
|
|
get_readback.assert_called_once_with(["samx"])
|
|
pipe = producer_mock.pipeline()
|
|
msg = BECMessage.DeviceMessage(
|
|
signals={},
|
|
metadata=instr.metadata,
|
|
).dumps()
|
|
|
|
producer_mock.set_and_publish.assert_called_once_with(
|
|
MessageEndpoints.device_read("samx"), msg, pipe
|
|
)
|
|
pipe.execute.assert_called_once()
|
|
|
|
|
|
def test_get_readback():
|
|
worker = get_scan_worker()
|
|
devices = ["samx"]
|
|
with mock.patch.object(worker.device_manager, "producer") as producer_mock:
|
|
worker._get_readback(devices)
|
|
pipe = producer_mock.pipeline()
|
|
producer_mock.get.assert_called_once_with(
|
|
MessageEndpoints.device_readback("samx"), pipe=pipe
|
|
)
|
|
pipe.execute.assert_called_once()
|
|
|
|
|
|
def test_publish_data_as_read():
|
|
worker = get_scan_worker()
|
|
instr = BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="publish_data_as_read",
|
|
parameter={"data": {}},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
with mock.patch.object(worker.device_manager, "producer") as producer_mock:
|
|
worker.publish_data_as_read(instr)
|
|
msg = BECMessage.DeviceMessage(
|
|
signals=instr.content["parameter"]["data"],
|
|
metadata=instr.metadata,
|
|
).dumps()
|
|
producer_mock.set_and_publish.assert_called_once_with(
|
|
MessageEndpoints.device_read("samx"), msg
|
|
)
|
|
|
|
|
|
def test_publish_data_as_read_multiple():
|
|
worker = get_scan_worker()
|
|
data = [{"samx": {}}, {"samy": {}}]
|
|
devices = ["samx", "samy"]
|
|
instr = BECMessage.DeviceInstructionMessage(
|
|
device=devices,
|
|
action="publish_data_as_read",
|
|
parameter={"data": data},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 3,
|
|
"scanID": "scanID",
|
|
"RID": "requestID",
|
|
},
|
|
)
|
|
with mock.patch.object(worker.device_manager, "producer") as producer_mock:
|
|
worker.publish_data_as_read(instr)
|
|
mock_calls = []
|
|
for device, dev_data in zip(devices, data):
|
|
msg = BECMessage.DeviceMessage(
|
|
signals=dev_data,
|
|
metadata=instr.metadata,
|
|
).dumps()
|
|
mock_calls.append(mock.call(MessageEndpoints.device_read(device), msg))
|
|
assert producer_mock.set_and_publish.mock_calls == mock_calls
|
|
|
|
|
|
def test_check_for_interruption():
|
|
worker = get_scan_worker()
|
|
worker.status = InstructionQueueStatus.STOPPED
|
|
with pytest.raises(ScanAbortion) as exc_info:
|
|
worker._check_for_interruption()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"instr, corr_num_points, scan_id",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="open_scan",
|
|
parameter={"num_points": 150, "scan_motors": ["samx", "samy"]},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 18,
|
|
"scanID": "12345",
|
|
"scan_def_id": 100,
|
|
"pointID": 50,
|
|
"RID": 11,
|
|
},
|
|
),
|
|
201,
|
|
False,
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="open_scan",
|
|
parameter={"num_points": 150},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 18,
|
|
"scanID": "12345",
|
|
"RID": 11,
|
|
},
|
|
),
|
|
150,
|
|
True,
|
|
),
|
|
],
|
|
)
|
|
def test_open_scan(instr, corr_num_points, scan_id):
|
|
worker = get_scan_worker()
|
|
|
|
if not scan_id:
|
|
assert worker.scan_id == None
|
|
else:
|
|
worker.scan_id = 111
|
|
worker.scan_motors = ["bpm4i"]
|
|
|
|
if "pointID" in instr.metadata:
|
|
worker.max_point_id = instr.metadata["pointID"]
|
|
|
|
assert worker.parent.producer.get(MessageEndpoints.scan_number()) == None
|
|
|
|
with mock.patch.object(worker, "current_instruction_queue_item") as queue_mock:
|
|
with mock.patch.object(worker, "_initialize_scan_info") as init_mock:
|
|
with mock.patch.object(worker.scan_report_instructions, "append") as instr_append_mock:
|
|
with mock.patch.object(worker, "_send_scan_status") as send_mock:
|
|
with mock.patch.object(
|
|
worker.current_instruction_queue_item.parent.queue_manager,
|
|
"send_queue_status",
|
|
) as queue_status_mock:
|
|
active_rb = queue_mock.active_request_block
|
|
active_rb.scan_report_instructions = []
|
|
worker.open_scan(instr)
|
|
|
|
if not scan_id:
|
|
assert worker.scan_id == instr.metadata.get("scanID")
|
|
assert worker.scan_motors == [
|
|
worker.device_manager.devices["samx"],
|
|
worker.device_manager.devices["samy"],
|
|
]
|
|
else:
|
|
assert worker.scan_id == 111
|
|
assert worker.scan_motors == ["bpm4i"]
|
|
init_mock.assert_called_once_with(active_rb, instr, corr_num_points)
|
|
assert active_rb.scan_report_instructions == [
|
|
{"table_wait": corr_num_points}
|
|
]
|
|
queue_status_mock.assert_called_once()
|
|
send_mock.assert_called_once_with("open")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg",
|
|
[
|
|
BECMessage.ScanQueueMessage(
|
|
scan_type="grid_scan",
|
|
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}, "num_points": 100},
|
|
queue="primary",
|
|
metadata={"RID": "something"},
|
|
),
|
|
],
|
|
)
|
|
def test_initialize_scan_info(msg):
|
|
worker = get_scan_worker()
|
|
scan_server = load_ScanServerMock()
|
|
rb = RequestBlock(msg, assembler=ScanAssembler(parent=scan_server))
|
|
assert rb.metadata == {"RID": "something"}
|
|
|
|
with mock.patch.object(worker, "current_instruction_queue_item"):
|
|
worker._initialize_scan_info(rb, msg, msg.content["parameter"].get("num_points"))
|
|
assert worker.current_scan_info == {
|
|
**msg.metadata,
|
|
**msg.content["parameter"],
|
|
"scan_number": 2,
|
|
"dataset_number": 3,
|
|
"exp_time": None,
|
|
"settling_time": 0,
|
|
"readout_time": 0,
|
|
"acquisition_config": {"default": {"exp_time": 0, "readout_time": 0}},
|
|
"scan_report_hint": rb.scan.scan_report_hint,
|
|
"scan_report_devices": rb.scan.scan_report_devices,
|
|
"num_points": 100,
|
|
"scan_msgs": [],
|
|
"enforce_sync": True,
|
|
"frames_per_trigger": 1,
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg,scan_id,max_point_id,exp_num_points",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="close_scan",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
"12345",
|
|
19,
|
|
20,
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="close_scan",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
"0987",
|
|
200,
|
|
19,
|
|
),
|
|
],
|
|
)
|
|
def test_close_scan(msg, scan_id, max_point_id, exp_num_points):
|
|
worker = get_scan_worker()
|
|
worker.scan_id = scan_id
|
|
worker.current_scan_info["num_points"] = 19
|
|
|
|
reset = bool(worker.scan_id == msg.metadata["scanID"])
|
|
with mock.patch.object(worker, "_send_scan_status") as send_scan_status_mock:
|
|
worker.close_scan(msg, max_point_id=max_point_id)
|
|
if reset:
|
|
send_scan_status_mock.assert_called_with("closed")
|
|
assert worker.scan_id == None
|
|
else:
|
|
assert worker.scan_id == scan_id
|
|
assert worker.current_scan_info["num_points"] == exp_num_points
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg",
|
|
[
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="close_scan",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
],
|
|
)
|
|
def test_stage_device(msg):
|
|
worker = get_scan_worker()
|
|
|
|
with mock.patch.object(worker, "_wait_for_stage") as wait_mock:
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
worker.stage_devices(msg)
|
|
detectors = [dev.name for dev in worker.device_manager.devices.detectors()]
|
|
devices = [
|
|
dev.name
|
|
for dev in worker.device_manager.devices.enabled_devices
|
|
if dev.name not in detectors
|
|
]
|
|
|
|
for dev in worker.device_manager.devices.enabled_devices:
|
|
assert dev.name in worker._staged_devices
|
|
for detector in detectors:
|
|
assert (
|
|
mock.call(
|
|
MessageEndpoints.device_instructions(),
|
|
DeviceMsg(
|
|
device=detector,
|
|
action="stage",
|
|
parameter=msg.content["parameter"],
|
|
metadata=msg.metadata,
|
|
).dumps(),
|
|
)
|
|
in send_mock.mock_calls
|
|
)
|
|
assert (
|
|
mock.call(
|
|
MessageEndpoints.device_instructions(),
|
|
DeviceMsg(
|
|
device=devices,
|
|
action="stage",
|
|
parameter=msg.content["parameter"],
|
|
metadata=msg.metadata,
|
|
).dumps(),
|
|
)
|
|
in send_mock.mock_calls
|
|
)
|
|
assert (
|
|
mock.call(
|
|
staged=True,
|
|
devices=devices,
|
|
metadata=msg.metadata,
|
|
)
|
|
in wait_mock.mock_calls
|
|
)
|
|
assert (
|
|
mock.call(
|
|
staged=True,
|
|
devices=detectors,
|
|
metadata=msg.metadata,
|
|
)
|
|
in wait_mock.mock_calls
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg, devices, parameter, metadata, cleanup",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="close_scan",
|
|
parameter={"parameter": "param"},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
["samx"],
|
|
{"parameter": "param"},
|
|
{"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
False,
|
|
),
|
|
(None, None, {}, {}, False),
|
|
(None, None, {}, {}, True),
|
|
],
|
|
)
|
|
def test_unstage_device(msg, devices, parameter, metadata, cleanup):
|
|
worker = get_scan_worker()
|
|
if not devices:
|
|
devices = [dev.name for dev in worker.device_manager.devices.enabled_devices]
|
|
|
|
with mock.patch.object(worker.device_manager.producer, "send") as send_mock:
|
|
with mock.patch.object(worker, "_wait_for_stage") as wait_mock:
|
|
worker.unstage_devices(msg, devices, cleanup)
|
|
|
|
send_mock.assert_called_once_with(
|
|
MessageEndpoints.device_instructions(),
|
|
DeviceMsg(
|
|
device=devices,
|
|
action="unstage",
|
|
parameter=parameter,
|
|
metadata=metadata,
|
|
).dumps(),
|
|
)
|
|
if cleanup:
|
|
wait_mock.assert_not_called()
|
|
else:
|
|
wait_mock.assert_called_once_with(
|
|
staged=False,
|
|
devices=devices,
|
|
metadata=metadata,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"status,expire",
|
|
[
|
|
(
|
|
"open",
|
|
None,
|
|
),
|
|
(
|
|
"closed",
|
|
1800,
|
|
),
|
|
(
|
|
"aborted",
|
|
1800,
|
|
),
|
|
],
|
|
)
|
|
def test_send_scan_status(status, expire):
|
|
worker = get_scan_worker()
|
|
worker.current_scanID = str(uuid.uuid4())
|
|
worker._send_scan_status(status)
|
|
scan_info_msgs = [
|
|
msg
|
|
for msg in worker.device_manager.producer.message_sent
|
|
if msg["queue"] == MessageEndpoints.public_scan_info(scanID=worker.current_scanID)
|
|
]
|
|
assert len(scan_info_msgs) == 1
|
|
assert scan_info_msgs[0]["expire"] == expire
|
|
|
|
|
|
@pytest.mark.parametrize("abortion", [False, True])
|
|
def test_process_instructions(abortion):
|
|
worker = get_scan_worker()
|
|
scan_server = load_ScanServerMock()
|
|
scan_queue = ScanQueue(QueueManager(scan_server))
|
|
queue = InstructionQueueMock(
|
|
parent=scan_queue, assembler=ScanAssembler(parent=scan_server), worker=worker
|
|
)
|
|
|
|
with mock.patch.object(worker, "_wait_for_device_server") as wait_mock:
|
|
with mock.patch.object(worker, "reset") as reset_mock:
|
|
with mock.patch.object(worker, "_check_for_interruption") as interruption_mock:
|
|
with mock.patch.object(queue.queue, "active_rb") as rb_mock:
|
|
with mock.patch.object(worker, "_instruction_step") as step_mock:
|
|
if abortion:
|
|
interruption_mock.side_effect = ScanAbortion
|
|
with pytest.raises(ScanAbortion) as exc_info:
|
|
worker._process_instructions(queue)
|
|
else:
|
|
worker._process_instructions(queue)
|
|
|
|
assert worker.max_point_id == 0
|
|
wait_mock.assert_called_once()
|
|
|
|
if not abortion:
|
|
assert interruption_mock.call_count == 4
|
|
assert worker._exposure_time == getattr(rb_mock.scan, "exp_time", None)
|
|
assert step_mock.call_count == 4
|
|
assert queue.is_active == False
|
|
assert queue.status == InstructionQueueStatus.COMPLETED
|
|
assert worker.current_instruction_queue_item == None
|
|
reset_mock.assert_called_once()
|
|
|
|
else:
|
|
assert worker._groups == {}
|
|
assert queue.stopped == True
|
|
assert interruption_mock.call_count == 1
|
|
assert queue.is_active == True
|
|
assert queue.status == InstructionQueueStatus.PENDING
|
|
assert worker.current_instruction_queue_item == queue
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg,method",
|
|
[
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="open_scan",
|
|
parameter={"readout_priority": {"monitored": [], "baseline": [], "ignored": []}},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
"open_scan",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="close_scan",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 18, "scanID": "12345"},
|
|
),
|
|
"close_scan",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=["samx"],
|
|
action="wait",
|
|
parameter={"type": "move", "wait_group": "scan_motor"},
|
|
metadata={
|
|
"readout_priority": "monitored",
|
|
"DIID": 4,
|
|
"scanID": "12345",
|
|
"RID": "123456",
|
|
},
|
|
),
|
|
"wait_for_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="trigger",
|
|
parameter={"group": "trigger"},
|
|
metadata={"readout_priority": "monitored", "DIID": 20, "pointID": 0},
|
|
),
|
|
"trigger_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="set",
|
|
parameter={
|
|
"value": 1.3681828686580249,
|
|
"wait_group": "scan_motor",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 24},
|
|
),
|
|
"set_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="read",
|
|
parameter={
|
|
"group": "primary",
|
|
"wait_group": "readout_primary",
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 30, "pointID": 1},
|
|
),
|
|
"read_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="stage",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 17},
|
|
),
|
|
"stage_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="unstage",
|
|
parameter={},
|
|
metadata={"readout_priority": "monitored", "DIID": 17},
|
|
),
|
|
"unstage_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx",
|
|
action="rpc",
|
|
parameter={
|
|
"device": "lsamy",
|
|
"func": "readback.get",
|
|
"rpc_id": "61a7376c-36cf-41af-94b1-76c1ba821d47",
|
|
"args": [],
|
|
"kwargs": {},
|
|
},
|
|
metadata={"readout_priority": "monitored", "DIID": 9},
|
|
),
|
|
"send_rpc",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device="samx", action="kickoff", parameter={}, metadata={}
|
|
),
|
|
"kickoff_devices",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None,
|
|
action="baseline_reading",
|
|
parameter={},
|
|
metadata={"readout_priority": "baseline", "DIID": 15},
|
|
),
|
|
"baseline_reading",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(device=None, action="close_scan_def", parameter={}),
|
|
"close_scan",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None, action="publish_data_as_read", parameter={}
|
|
),
|
|
"publish_data_as_read",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(
|
|
device=None, action="scan_report_instruction", parameter={}
|
|
),
|
|
"process_scan_report_instruction",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(device=None, action="pre_scan", parameter={}),
|
|
"pre_scan",
|
|
),
|
|
(
|
|
BECMessage.DeviceInstructionMessage(device=None, action="complete", parameter={}),
|
|
"complete_devices",
|
|
),
|
|
],
|
|
)
|
|
def test_instruction_step(msg, method):
|
|
worker = get_scan_worker()
|
|
with mock.patch(f"scan_server.scan_worker.ScanWorker.{method}") as instruction_method:
|
|
worker._instruction_step(msg)
|
|
instruction_method.assert_called_once()
|
|
|
|
|
|
def test_reset():
|
|
worker = get_scan_worker()
|
|
worker._gropus = 1
|
|
worker.current_scanID = 1
|
|
worker.current_scan_info = 1
|
|
worker.scan_id = 1
|
|
worker.interception_msg = 1
|
|
worker.scan_motors = 1
|
|
|
|
worker.reset()
|
|
|
|
assert worker._groups == {}
|
|
assert worker.current_scanID == ""
|
|
assert worker.current_scan_info == {}
|
|
assert worker.scan_id == None
|
|
assert worker.interception_msg == None
|
|
assert worker.scan_motors == []
|
|
|
|
|
|
def test_cleanup():
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker, "unstage_devices") as unstage_mock:
|
|
worker.cleanup()
|
|
unstage_mock.assert_called_once_with(devices=list(worker._staged_devices), cleanup=True)
|
|
|
|
|
|
def test_shutdown():
|
|
worker = get_scan_worker()
|
|
with mock.patch.object(worker.signal_event, "set") as set_mock:
|
|
with mock.patch.object(worker, "join") as join_mock:
|
|
worker.shutdown()
|
|
set_mock.assert_called_once()
|
|
join_mock.assert_called_once()
|