From 55e7c1397a9c91eda74f736f857dc8cf21de3b46 Mon Sep 17 00:00:00 2001 From: josh-deb Date: Wed, 27 Nov 2024 13:18:05 -0800 Subject: [PATCH] ENH: writing tests for SysResetIOC --- beams/tests/mock_iocs/SysResetIOC.py | 39 ++++++++++++++++++++ beams/tests/test_utility_trees.py | 30 +++++++++++++++ beams/tree_config/utility_trees/reset_ioc.py | 15 +++++--- beams/tree_config/value.py | 1 + 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 beams/tests/mock_iocs/SysResetIOC.py create mode 100644 beams/tests/test_utility_trees.py diff --git a/beams/tests/mock_iocs/SysResetIOC.py b/beams/tests/mock_iocs/SysResetIOC.py new file mode 100644 index 0000000..5188568 --- /dev/null +++ b/beams/tests/mock_iocs/SysResetIOC.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +from textwrap import dedent + +from caproto.server import PVGroup, ioc_arg_parser, pvproperty, run + + +class MockSysResetIOC(PVGroup): + """ + IOC to mock SLACEPICS IOCs with respect to how they increment heartbeat and are reset + """ + + heartbeat = pvproperty( + name="HEARTBEAT", + value=0, + dtype=int, + doc="Represents heartbeat of IOC, monotonically increasing (until reset)") + sys_reset = pvproperty( + name="SysReset", + value=0, + dtype=int, + doc="Rising edge indicates requested reset, put high to request reset") + + @sys_reset.putter + async def sys_reset(self, instance, value): + await self.heartbeat.write(0) + return 0 + + @heartbeat.scan(period=1.0) + async def heartbeat(self, instance, async_lib): + print(instance.value) + await instance.write(instance.value+1) + + +if __name__ == "__main__": + ioc_options, run_options = ioc_arg_parser( + default_prefix="SysResetTest:", desc=dedent(MockSysResetIOC.__doc__) + ) + ioc = MockSysResetIOC(**ioc_options) + run(ioc.pvdb, **run_options) diff --git a/beams/tests/test_utility_trees.py b/beams/tests/test_utility_trees.py new file mode 100644 index 0000000..1da14c0 --- /dev/null +++ b/beams/tests/test_utility_trees.py @@ -0,0 +1,30 @@ +import time +from pathlib import Path + +import py_trees +from caproto.tests.conftest import run_example_ioc + +from beams.tree_config.utility_trees.reset_ioc import ResetIOCItem + + +def test_sys_reset(request, bt_cleaner): + reset_ioc_tree = ResetIOCItem( + ioc_prefix="SysResetTest").get_tree() + + bt_cleaner.register(reset_ioc_tree) + + # start mock IOC # NOTE: assumes test is being run from top level of + run_example_ioc( + "beams.tests.mock_iocs.SysResetIOC", + request=request, + pv_to_check="SysResetTest:HEARTBEAT", + ) + + reset_ioc_tree.setup_with_descendants() + while reset_ioc_tree.status not in ( + py_trees.common.Status.SUCCESS, + py_trees.common.Status.FAILURE, + ): + for n in reset_ioc_tree.tick(): + print(n) + time.sleep(1) diff --git a/beams/tree_config/utility_trees/reset_ioc.py b/beams/tree_config/utility_trees/reset_ioc.py index 267d1e6..2c02df9 100644 --- a/beams/tree_config/utility_trees/reset_ioc.py +++ b/beams/tree_config/utility_trees/reset_ioc.py @@ -19,9 +19,10 @@ @dataclass class ResetIOCItem(BaseItem): ioc_prefix: str = "" - HEARTBEAT_POSTFIX = ":HEARTBEART" - SYSRESET_POSTFIX = ":SysReset" - HEARTBEAT_KEY_NAME = "heartbeat" + # semi static member objects + HEARTBEAT_POSTFIX: str = ":HEARTBEART" + SYSRESET_POSTFIX: str = ":SysReset" + HEARTBEAT_KEY_NAME: str = "heartbeat" def __post_init__(self): # non dataclass PVss @@ -31,8 +32,10 @@ def __post_init__(self): def get_tree(self) -> Sequence: def check_acquired_current_hbeat(): - self.hbeat_val.get_value() is not None - + val = self.hbeat_val.get_value() is not None + logger.debug(f"checking opur guy as {val}") + return val + # get the current heartbeat of IOC @wrapped_action_work(loop_period_sec=3.0) def cache_hbeat_wfunc(): @@ -61,5 +64,5 @@ def cache_hbeat_wfunc(): root = Sequence(name=self.name, memory=False, - children=[cache_current_heartbeat, send_reset]) + children=[cache_current_heartbeat, send_reset.get_tree()]) return root diff --git a/beams/tree_config/value.py b/beams/tree_config/value.py index 8736061..315678e 100644 --- a/beams/tree_config/value.py +++ b/beams/tree_config/value.py @@ -35,6 +35,7 @@ def get_value(self) -> Any: return value +@dataclass class BlackBoardValue(BaseValue): bb_name: str = "" key_name: str = ""