Skip to content

Commit fef5f6a

Browse files
committed
fixed tests
Also made it so that scan tasks are explicitly torn down when the backend is deleted.
1 parent 9126ebd commit fef5f6a

File tree

2 files changed

+61
-35
lines changed

2 files changed

+61
-35
lines changed

src/fastcs/backends/epics/ioc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def _get_output_record(pv: str, attribute: AttrW, on_update: Callable) -> Any:
345345
attribute_fields.update({"DESC": attribute.description})
346346
if attr_is_enum(attribute):
347347
assert attribute.allowed_values is not None and all(
348-
isinstance(v, str) for v in attribute.allowed_values
348+
isinstance(v, str) or isinstance(v, int) for v in attribute.allowed_values
349349
)
350350
state_keys = dict(zip(MBB_STATE_FIELDS, attribute.allowed_values, strict=False))
351351
return builder.mbbOut(

tests/backends/epics/test_ioc.py

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
from fastcs.backends.epics.ioc import (
88
EPICS_MAX_NAME_LENGTH,
99
EpicsIOC,
10-
_add_attr_pvi_info,
1110
_add_pvi_info,
12-
_add_sub_controller_pvi_info,
13-
_create_and_link_read_pv,
14-
_create_and_link_write_pv,
1511
_get_input_record,
1612
_get_output_record,
1713
)
@@ -27,17 +23,31 @@
2723
ONOFF_STATES = {"ZRST": "disabled", "ONST": "enabled"}
2824

2925

26+
@pytest.fixture
27+
def ioc_without_mapping(mocker: MockerFixture, mapping: Mapping):
28+
mocker.patch("fastcs.backends.epics.ioc.builder")
29+
mocker.patch("fastcs.backends.epics.ioc.EpicsIOC._create_and_link_attribute_pvs")
30+
mocker.patch("fastcs.backends.epics.ioc.EpicsIOC._create_and_link_command_pvs")
31+
32+
return EpicsIOC(DEVICE, mapping)
33+
34+
3035
@pytest.mark.asyncio
31-
async def test_create_and_link_read_pv(mocker: MockerFixture):
36+
async def test_create_and_link_read_pv(
37+
mocker: MockerFixture, ioc_without_mapping: EpicsIOC
38+
):
3239
get_input_record = mocker.patch("fastcs.backends.epics.ioc._get_input_record")
33-
add_attr_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_attr_pvi_info")
3440
attr_is_enum = mocker.patch("fastcs.backends.epics.ioc.attr_is_enum")
41+
mocker.patch("fastcs.backends.epics.ioc._add_pvi_info")
42+
add_attr_pvi_info = mocker.patch(
43+
"fastcs.backends.epics.ioc.EpicsIOC._add_attr_pvi_info"
44+
)
3545
record = get_input_record.return_value
3646

3747
attribute = mocker.MagicMock()
38-
3948
attr_is_enum.return_value = False
40-
_create_and_link_read_pv("PREFIX", "PV", "attr", attribute)
49+
50+
ioc_without_mapping._create_and_link_read_pv("PREFIX", "PV", "attr", attribute)
4151

4252
get_input_record.assert_called_once_with("PREFIX:PV", attribute)
4353
add_attr_pvi_info.assert_called_once_with(record, "PREFIX", "attr", "r")
@@ -51,17 +61,21 @@ async def test_create_and_link_read_pv(mocker: MockerFixture):
5161

5262

5363
@pytest.mark.asyncio
54-
async def test_create_and_link_read_pv_enum(mocker: MockerFixture):
64+
async def test_create_and_link_read_pv_enum(
65+
mocker: MockerFixture, ioc_without_mapping: EpicsIOC
66+
):
5567
get_input_record = mocker.patch("fastcs.backends.epics.ioc._get_input_record")
56-
add_attr_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_attr_pvi_info")
68+
add_attr_pvi_info = mocker.patch(
69+
"fastcs.backends.epics.ioc.EpicsIOC._add_attr_pvi_info"
70+
)
5771
attr_is_enum = mocker.patch("fastcs.backends.epics.ioc.attr_is_enum")
5872
record = get_input_record.return_value
5973
enum_value_to_index = mocker.patch("fastcs.backends.epics.ioc.enum_value_to_index")
6074

6175
attribute = mocker.MagicMock()
6276

6377
attr_is_enum.return_value = True
64-
_create_and_link_read_pv("PREFIX", "PV", "attr", attribute)
78+
ioc_without_mapping._create_and_link_read_pv("PREFIX", "PV", "attr", attribute)
6579

6680
get_input_record.assert_called_once_with("PREFIX:PV", attribute)
6781
add_attr_pvi_info.assert_called_once_with(record, "PREFIX", "attr", "r")
@@ -108,17 +122,21 @@ def test_get_input_record_raises(mocker: MockerFixture):
108122

109123

110124
@pytest.mark.asyncio
111-
async def test_create_and_link_write_pv(mocker: MockerFixture):
125+
async def test_create_and_link_write_pv(
126+
mocker: MockerFixture, ioc_without_mapping: EpicsIOC
127+
):
112128
get_output_record = mocker.patch("fastcs.backends.epics.ioc._get_output_record")
113-
add_attr_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_attr_pvi_info")
129+
add_attr_pvi_info = mocker.patch(
130+
"fastcs.backends.epics.ioc.EpicsIOC._add_attr_pvi_info"
131+
)
114132
attr_is_enum = mocker.patch("fastcs.backends.epics.ioc.attr_is_enum")
115133
record = get_output_record.return_value
116134

117135
attribute = mocker.MagicMock()
118136
attribute.process_without_display_update = mocker.AsyncMock()
119137

120138
attr_is_enum.return_value = False
121-
_create_and_link_write_pv("PREFIX", "PV", "attr", attribute)
139+
ioc_without_mapping._create_and_link_write_pv("PREFIX", "PV", "attr", attribute)
122140

123141
get_output_record.assert_called_once_with(
124142
"PREFIX:PV", attribute, on_update=mocker.ANY
@@ -140,9 +158,13 @@ async def test_create_and_link_write_pv(mocker: MockerFixture):
140158

141159

142160
@pytest.mark.asyncio
143-
async def test_create_and_link_write_pv_enum(mocker: MockerFixture):
161+
async def test_create_and_link_write_pv_enum(
162+
mocker: MockerFixture, ioc_without_mapping: EpicsIOC
163+
):
144164
get_output_record = mocker.patch("fastcs.backends.epics.ioc._get_output_record")
145-
add_attr_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_attr_pvi_info")
165+
add_attr_pvi_info = mocker.patch(
166+
"fastcs.backends.epics.ioc.EpicsIOC._add_attr_pvi_info"
167+
)
146168
attr_is_enum = mocker.patch("fastcs.backends.epics.ioc.attr_is_enum")
147169
enum_value_to_index = mocker.patch("fastcs.backends.epics.ioc.enum_value_to_index")
148170
enum_index_to_value = mocker.patch("fastcs.backends.epics.ioc.enum_index_to_value")
@@ -152,7 +174,7 @@ async def test_create_and_link_write_pv_enum(mocker: MockerFixture):
152174
attribute.process_without_display_update = mocker.AsyncMock()
153175

154176
attr_is_enum.return_value = True
155-
_create_and_link_write_pv("PREFIX", "PV", "attr", attribute)
177+
ioc_without_mapping._create_and_link_write_pv("PREFIX", "PV", "attr", attribute)
156178

157179
get_output_record.assert_called_once_with(
158180
"PREFIX:PV", attribute, on_update=mocker.ANY
@@ -215,22 +237,28 @@ def test_ioc(mocker: MockerFixture, mapping: Mapping):
215237
builder = mocker.patch("fastcs.backends.epics.ioc.builder")
216238
add_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_pvi_info")
217239
add_sub_controller_pvi_info = mocker.patch(
218-
"fastcs.backends.epics.ioc._add_sub_controller_pvi_info"
240+
"fastcs.backends.epics.ioc.EpicsIOC._add_sub_controller_pvi_info"
219241
)
220242

221243
EpicsIOC(DEVICE, mapping)
222244

223245
# Check records are created
224246
builder.boolIn.assert_called_once_with(f"{DEVICE}:ReadBool", ZNAM="OFF", ONAM="ON")
225-
builder.longIn.assert_any_call(f"{DEVICE}:ReadInt")
226-
builder.aIn.assert_called_once_with(f"{DEVICE}:ReadWriteFloat_RBV", PREC=2)
247+
builder.longIn.assert_any_call(f"{DEVICE}:ReadInt", EGU=None)
248+
builder.aIn.assert_called_once_with(
249+
f"{DEVICE}:ReadWriteFloat_RBV", EGU=None, PREC=2
250+
)
227251
builder.aOut.assert_any_call(
228-
f"{DEVICE}:ReadWriteFloat", always_update=True, on_update=mocker.ANY, PREC=2
252+
f"{DEVICE}:ReadWriteFloat",
253+
always_update=True,
254+
on_update=mocker.ANY,
255+
EGU=None,
256+
PREC=2,
229257
)
230-
builder.longIn.assert_any_call(f"{DEVICE}:BigEnum")
231-
builder.longIn.assert_any_call(f"{DEVICE}:ReadWriteInt_RBV")
258+
builder.longIn.assert_any_call(f"{DEVICE}:BigEnum", EGU=None)
259+
builder.longIn.assert_any_call(f"{DEVICE}:ReadWriteInt_RBV", EGU=None)
232260
builder.longOut.assert_called_with(
233-
f"{DEVICE}:ReadWriteInt", always_update=True, on_update=mocker.ANY
261+
f"{DEVICE}:ReadWriteInt", always_update=True, on_update=mocker.ANY, EGU=None
234262
)
235263
builder.mbbIn.assert_called_once_with(
236264
f"{DEVICE}:StringEnum_RBV", ZRST="red", ONST="green", TWST="blue"
@@ -323,25 +351,27 @@ def test_add_pvi_info_with_parent(mocker: MockerFixture):
323351
)
324352

325353

326-
def test_add_sub_controller_pvi_info(mocker: MockerFixture):
354+
def test_add_sub_controller_pvi_info(
355+
mocker: MockerFixture, ioc_without_mapping: EpicsIOC
356+
):
327357
add_pvi_info = mocker.patch("fastcs.backends.epics.ioc._add_pvi_info")
328358
controller = mocker.MagicMock()
329359
controller.path = []
330360
child = mocker.MagicMock()
331361
child.path = ["Child"]
332362
controller.get_sub_controllers.return_value = {"d": child}
333363

334-
_add_sub_controller_pvi_info(DEVICE, controller)
364+
ioc_without_mapping._add_sub_controller_pvi_info(DEVICE, controller)
335365

336366
add_pvi_info.assert_called_once_with(
337367
f"{DEVICE}:Child:PVI", f"{DEVICE}:PVI", "child"
338368
)
339369

340370

341-
def test_add_attr_pvi_info(mocker: MockerFixture):
371+
def test_add_attr_pvi_info(mocker: MockerFixture, ioc_without_mapping: EpicsIOC):
342372
record = mocker.MagicMock()
343373

344-
_add_attr_pvi_info(record, DEVICE, "attr", "r")
374+
ioc_without_mapping._add_attr_pvi_info(record, DEVICE, "attr", "r")
345375

346376
record.add_info.assert_called_once_with(
347377
"Q:group",
@@ -387,13 +417,9 @@ def test_long_pv_names_discarded(mocker: MockerFixture):
387417

388418
short_pv_name = "attr_rw_short_name".title().replace("_", "")
389419
builder.longOut.assert_called_once_with(
390-
f"{DEVICE}:{short_pv_name}",
391-
always_update=True,
392-
on_update=mocker.ANY,
393-
)
394-
builder.longIn.assert_called_once_with(
395-
f"{DEVICE}:{short_pv_name}_RBV",
420+
f"{DEVICE}:{short_pv_name}", always_update=True, on_update=mocker.ANY, EGU=None
396421
)
422+
builder.longIn.assert_called_once_with(f"{DEVICE}:{short_pv_name}_RBV", EGU=None)
397423

398424
long_pv_name = long_attr_name.title().replace("_", "")
399425
with pytest.raises(AssertionError):

0 commit comments

Comments
 (0)