Skip to content

Commit

Permalink
Merge branch 'master' of github.com:dls-controls/tickit
Browse files Browse the repository at this point in the history
  • Loading branch information
collang committed Nov 18, 2021
2 parents 98eef6d + 2a35a52 commit d1d4bcf
Show file tree
Hide file tree
Showing 40 changed files with 1,997 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Added:

- HTTP REST Adapter & example device
- Example Counter device
- Basic Eiger device without major logic
- Unit tests covering:

- EPICS Adapter
Expand All @@ -30,6 +31,8 @@ Changed:
- User may now reference the :code:`ComponentConfig`, which encapsulate a device and adapters
- Device & Adapter config classes are no longer autmatically generated, configuration should be performed via the :code:`ComponentConfig`

- Made :code:`Device` a typed :code:`Generic` of :code:`InMap` and :code:`OutMap`

Deprecated:

Removed:
Expand All @@ -38,6 +41,7 @@ Fixed:

- Cryostream flow rate threshold (from 900K > 90K)
- Added dependency on Click to :code:`setup.cfg`
- Added missing :code:`__init__.py` to :code:`tickit.utils.compat`

Security:

Expand Down
88 changes: 88 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions examples/configs/eiger-shutter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- tickit.devices.source.Source:
name: source
inputs: {}
value: 42.0
- examples.devices.shutter.Shutter:
name: shutter
inputs:
flux: source:value
default_position: 0.2
initial_position: 0.24
- tickit.devices.eiger.Eiger:
inputs:
flux: shutter:flux
name: eiger
8 changes: 8 additions & 0 deletions examples/configs/eiger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- tickit.devices.source.Source:
name: source
inputs: {}
value: 42.0
- tickit.devices.eiger.Eiger:
inputs:
flux: source:value
name: eiger
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ packages = find:
install_requires =
aiohttp
aiokafka
aiozmq==0.9.0
apischema==0.16.1
immutables
pyyaml
pyzmq==19.0.2
softioc
click

Expand Down
143 changes: 143 additions & 0 deletions tests/adapters/test_zmqadapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import asyncio
import logging

import aiozmq
import pytest
from mock import Mock
from mock.mock import AsyncMock, create_autospec

from tickit.adapters.zmqadapter import ZeroMQAdapter
from tickit.core.device import Device


@pytest.fixture
def mock_device() -> Device:
return create_autospec(Device)


@pytest.fixture
def mock_raise_interrupt():
async def raise_interrupt():
return False

return Mock(raise_interrupt)


@pytest.fixture
@pytest.mark.asyncio
async def mock_process_message_queue() -> AsyncMock:
async def _process_message_queue():
return True

return AsyncMock(_process_message_queue)


@pytest.fixture
def zeromq_adapter() -> ZeroMQAdapter:
zmq_adapter = ZeroMQAdapter()
zmq_adapter._dealer = AsyncMock()
zmq_adapter._router = AsyncMock()
zmq_adapter._message_queue = Mock(asyncio.Queue)
return zmq_adapter


def test_zeromq_adapter_constructor():
ZeroMQAdapter()


@pytest.mark.asyncio
async def test_zeromq_adapter_start_stream(zeromq_adapter):
await zeromq_adapter.start_stream()

assert isinstance(zeromq_adapter._router, aiozmq.stream.ZmqStream)
assert isinstance(zeromq_adapter._dealer, aiozmq.stream.ZmqStream)

await zeromq_adapter.close_stream()


@pytest.mark.asyncio
async def test_zeromq_adapter_close_stream(zeromq_adapter):
await zeromq_adapter.start_stream()

await zeromq_adapter.close_stream()
await asyncio.sleep(0.1)

assert None is zeromq_adapter._router._transport
assert None is zeromq_adapter._dealer._transport


@pytest.mark.asyncio
async def test_zeromq_adapter_after_update(zeromq_adapter):

zeromq_adapter.after_update()


@pytest.mark.asyncio
async def test_zeromq_adapter_send_message(zeromq_adapter):

mock_message = AsyncMock()

zeromq_adapter.send_message(mock_message)
task = asyncio.current_task()
asyncio.gather(task)
zeromq_adapter._message_queue.put.assert_called_once()


@pytest.mark.asyncio
async def test_zeromq_adapter_run_forever_method(
zeromq_adapter,
mock_device: Device,
mock_process_message_queue: AsyncMock,
mock_raise_interrupt: Mock,
):

zeromq_adapter._process_message_queue = mock_process_message_queue

await zeromq_adapter.run_forever(mock_device, mock_raise_interrupt)

zeromq_adapter._process_message_queue.assert_called_once()


@pytest.mark.asyncio
async def test_zeromq_adapter_check_if_running(zeromq_adapter):

assert zeromq_adapter.check_if_running() is False


@pytest.mark.asyncio
async def test_zeromq_adapter_process_message_queue(zeromq_adapter):

zeromq_adapter._process_message = AsyncMock()
zeromq_adapter.check_if_running = Mock(return_value=False)

await zeromq_adapter._process_message_queue()

zeromq_adapter._process_message.assert_awaited_once()


@pytest.mark.asyncio
async def test_zeromq_adapter_process_message(zeromq_adapter):

mock_message = "test"

zeromq_adapter._dealer.read.return_value = ("Data", "test")
zeromq_adapter._router.read.return_value = ("Data", "test")

await zeromq_adapter._process_message(mock_message)

zeromq_adapter._dealer.read.assert_awaited_once()
zeromq_adapter._router.read.assert_awaited_once()


@pytest.mark.asyncio
async def test_zeromq_adapter_process_message_no_message(zeromq_adapter, caplog):

mock_message = None

zeromq_adapter._dealer.read.return_value = ("Data", None)
zeromq_adapter._router.read.return_value = ("Data", None)

with caplog.at_level(logging.DEBUG):
await zeromq_adapter._process_message(mock_message)

assert len(caplog.records) == 1
Loading

0 comments on commit d1d4bcf

Please sign in to comment.