bec/bec_lib/tests/test_observer.py
Mathias Guijarro 8bbfd10ca7 refactor(messages)!: messages refactoring, new serialization module
To have a better separation of concern between messages and how they are conveyed in connectors.
BECMessage can be simple dataclasses, leaving the serialization to the connector which transport those.
The serialization module itself can be isolated, and in the case of msgpack it can be extended to
understand how to encode/decode BECMessage, to simplify writing code like with BundleMessage or to
be able to automatically encode numpy or BECStatus objects.
Finally, client objects (producers and consumers) can receive BECMessage objects instead of having
to dump or load themselves.
2024-02-07 12:43:52 +01:00

196 lines
5.7 KiB
Python

import os
from unittest import mock
import pytest
import yaml
from typeguard import TypeCheckError
import bec_lib
from bec_lib import messages
from bec_lib.devicemanager import DeviceManagerBase
from bec_lib.endpoints import MessageEndpoints
from bec_lib.observer import Observer, ObserverManager
from bec_lib.tests.utils import ConnectorMock, create_session_from_config, dm, dm_with_devices
dir_path = os.path.dirname(bec_lib.__file__)
@pytest.mark.parametrize(
"kwargs,raised_error",
[
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "restart",
},
AttributeError,
),
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "whatever",
},
ValueError,
),
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, 420],
},
None,
),
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, 420],
"target_value": 20,
},
AttributeError,
),
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "restart",
"limits": 20,
},
TypeCheckError,
),
(
{
"name": "stop scan if ring current drops",
"device": "ring_current",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, 420],
"low_limit": 20,
},
AttributeError,
),
],
)
def test_observer(kwargs, raised_error):
if not raised_error:
observer = Observer(**kwargs)
return
with pytest.raises(raised_error):
observer = Observer(**kwargs)
@pytest.fixture()
def device_manager(dm_with_devices):
dm = dm_with_devices
with mock.patch.object(dm, "_get_config"):
dm.initialize("")
return dm
def test_observer_manager_None(device_manager):
with mock.patch.object(device_manager.producer, "get", return_value=None) as producer_get:
observer_manager = ObserverManager(device_manager=device_manager)
producer_get.assert_called_once_with(MessageEndpoints.observer())
assert len(observer_manager._observer) == 0
def test_observer_manager_msg(device_manager):
msg = messages.ObserverMessage(
observer=[
{
"name": "test_observer",
"device": "samx",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, None],
}
]
)
with mock.patch.object(device_manager.producer, "get", return_value=msg) as producer_get:
observer_manager = ObserverManager(device_manager=device_manager)
producer_get.assert_called_once_with(MessageEndpoints.observer())
assert len(observer_manager._observer) == 1
@pytest.mark.parametrize(
"observer,raises_error",
[
(
Observer.from_dict(
{
"name": "test_observer",
"device": "samx",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, None],
}
),
False,
)
],
)
def test_add_observer(device_manager, observer, raises_error):
with mock.patch.object(device_manager.producer, "get", return_value=None) as producer_get:
observer_manager = ObserverManager(device_manager=device_manager)
observer_manager.add_observer(observer)
with pytest.raises(AttributeError):
observer_manager.add_observer(observer)
@pytest.mark.parametrize(
"observer,raises_error",
[
(
Observer.from_dict(
{
"name": "test_observer",
"device": "samx",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, None],
}
),
True,
),
(
Observer.from_dict(
{
"name": "test_observer",
"device": "samy",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, None],
}
),
False,
),
],
)
def test_add_observer_existing_device(device_manager, observer, raises_error):
default_observer = Observer.from_dict(
{
"name": "test_observer",
"device": "samx",
"on_trigger": "pause",
"on_resume": "restart",
"limits": [380, None],
}
)
with mock.patch.object(device_manager.producer, "get", return_value=None) as producer_get:
observer_manager = ObserverManager(device_manager=device_manager)
observer_manager.add_observer(default_observer)
if raises_error:
with pytest.raises(AttributeError):
observer_manager.add_observer(observer)
else:
observer_manager.add_observer(observer)