Skip to content

Commit bdd4f9d

Browse files
committed
Added tests for most of zmqadapter.py
Added more tests for zmqadapter.py
1 parent e7cf5d2 commit bdd4f9d

File tree

1 file changed

+298
-1
lines changed

1 file changed

+298
-1
lines changed

tests/test_zmq_adapter.py

Lines changed: 298 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,309 @@
1+
import asyncio
2+
3+
import aiozmq
14
import pytest
5+
import zmq
6+
from mock import AsyncMock, Mock
27

38
from pmacfiltercontrol.zmqadapter import ZeroMQAdapter
49

10+
# -------------------------------------------------
11+
12+
13+
# https://www.roguelynn.com/words/asyncio-testing/
14+
# used to patch/mock asyncio coroutines
15+
@pytest.fixture
16+
def create_mock_coro(mocker, monkeypatch):
17+
def _create_mock_patch_coro(to_patch=None):
18+
mock = mocker.Mock()
19+
20+
async def _coro(*args, **kwargs):
21+
return mock(*args, **kwargs)
22+
23+
if to_patch: # <-- may not need/want to patch anything
24+
monkeypatch.setattr(to_patch, _coro)
25+
return mock, _coro
26+
27+
return _create_mock_patch_coro
28+
29+
30+
# -------------------------------------------------
31+
# Mock Queue
32+
33+
34+
@pytest.fixture
35+
def mock_queue(mocker, monkeypatch):
36+
queue = mocker.AsyncMock()
37+
monkeypatch.setattr(asyncio, "Queue", queue)
38+
return queue.return_value
39+
40+
41+
@pytest.fixture
42+
def mock_queue_get(mock_queue, create_mock_coro):
43+
mock_get, coro_get = create_mock_coro()
44+
mock_queue.get = coro_get
45+
return mock_get
46+
47+
48+
@pytest.fixture
49+
def mock_queue_put_nowait(mock_queue, create_mock_coro):
50+
mock_put_nowait, coro_put_nowait = create_mock_coro()
51+
mock_queue.put_nowait = coro_put_nowait
52+
return mock_put_nowait
53+
54+
55+
# -------------------------------------------------
56+
# Mock Socket
57+
58+
59+
@pytest.fixture
60+
def mock_socket(mocker, monkeypatch):
61+
socket = mocker.AsyncMock()
62+
monkeypatch.setattr(aiozmq, "ZmqStream", socket)
63+
return socket.return_value
64+
65+
66+
@pytest.fixture
67+
def mock_socket_read(mock_socket, create_mock_coro):
68+
mock_read, coro_read = create_mock_coro()
69+
mock_socket.read = coro_read
70+
return mock_read
71+
72+
73+
@pytest.fixture
74+
def mock_socket_write(mock_socket, create_mock_coro):
75+
mock_write, coro_write = create_mock_coro()
76+
mock_socket.write = coro_write
77+
return mock_write
78+
79+
80+
# -------------------------------------------------
81+
# Zmq Adapter
82+
583

684
@pytest.fixture
785
def zmq_adapter() -> ZeroMQAdapter:
8-
return ZeroMQAdapter()
86+
zmq_adapter = ZeroMQAdapter(zmq_type=zmq.SUB)
87+
return zmq_adapter
88+
89+
90+
@pytest.fixture
91+
def zmq_adapter_dealer() -> ZeroMQAdapter:
92+
zmq_adapter = ZeroMQAdapter(zmq_type=zmq.DEALER)
93+
return zmq_adapter
94+
95+
96+
# -------------------------------------------------
97+
# Tests
998

1099

11100
def test_zmq_adapter_constructor():
12101
ZeroMQAdapter()
102+
103+
104+
@pytest.mark.asyncio
105+
async def test_start_stop_stream(zmq_adapter: ZeroMQAdapter):
106+
await zmq_adapter.start_stream()
107+
assert zmq_adapter._socket._closing is False
108+
109+
await zmq_adapter.close_stream()
110+
# wait for socket to close
111+
await asyncio.sleep(0.1)
112+
assert zmq_adapter._socket._closing is True
113+
114+
115+
def test_zmq_adapter_if_running(zmq_adapter: ZeroMQAdapter):
116+
assert zmq_adapter.check_if_running() is False
117+
118+
119+
def test_zmq_adapter_send_message(zmq_adapter: ZeroMQAdapter):
120+
mock_message = AsyncMock()
121+
122+
zmq_adapter._send_message_queue = Mock(asyncio.Queue)
123+
124+
zmq_adapter.send_message(mock_message)
125+
126+
127+
@pytest.mark.asyncio
128+
async def test_zmq_adapter_get_response(
129+
zmq_adapter: ZeroMQAdapter, mock_queue, mock_queue_get
130+
):
131+
zmq_adapter._recv_message_queue = mock_queue
132+
mock_queue_get.return_value = b"test"
133+
134+
resp = await zmq_adapter.get_response()
135+
136+
assert resp == b"test"
137+
138+
mock_queue_get.assert_called_once()
139+
140+
141+
@pytest.mark.asyncio
142+
async def test_zmq_adapter_read_response(
143+
zmq_adapter: ZeroMQAdapter, mock_socket, mock_socket_read
144+
):
145+
zmq_adapter._socket = mock_socket
146+
147+
f: asyncio.Future = asyncio.Future()
148+
f.set_result([b"test"])
149+
mock_socket_read.return_value = f.result()
150+
151+
resp = await zmq_adapter._read_response()
152+
assert resp == b"test"
153+
154+
mock_socket_read.assert_called_once()
155+
156+
157+
@pytest.mark.asyncio
158+
async def test_zmq_adapter_dealer_read_response(
159+
zmq_adapter_dealer: ZeroMQAdapter, mock_socket, mock_socket_read
160+
):
161+
zmq_adapter_dealer._socket = mock_socket
162+
163+
f: asyncio.Future = asyncio.Future()
164+
f.set_result([b"", b"test"])
165+
mock_socket_read.return_value = f.result()
166+
167+
resp = await zmq_adapter_dealer._read_response()
168+
169+
assert resp == b"test"
170+
171+
mock_socket_read.assert_called_once()
172+
173+
174+
@pytest.mark.asyncio
175+
async def test_zmq_adapter_run_forever(zmq_adapter: ZeroMQAdapter):
176+
zmq_adapter._process_response_queue = AsyncMock()
177+
178+
await zmq_adapter.run_forever()
179+
180+
# zmq_adapter._process_response_queue.assert_awaited_once()
181+
182+
183+
@pytest.mark.asyncio
184+
async def test_zmq_adapter_dealer_run_forever(zmq_adapter_dealer: ZeroMQAdapter):
185+
zmq_adapter_dealer._process_message_queue = AsyncMock()
186+
zmq_adapter_dealer._process_response_queue = AsyncMock()
187+
188+
await zmq_adapter_dealer.run_forever()
189+
190+
# zmq_adapter_dealer._process_message_queue.assert_awaited_once()
191+
# zmq_adapter_dealer._process_response_queue.assert_awaited_once()
192+
193+
194+
@pytest.mark.asyncio
195+
async def test_zmq_adapter_process_message_queue(
196+
zmq_adapter: ZeroMQAdapter, mock_queue, mock_queue_get
197+
):
198+
zmq_adapter._process_message = AsyncMock()
199+
200+
zmq_adapter._send_message_queue = mock_queue
201+
mock_queue_get.return_value = b"test"
202+
203+
await zmq_adapter._process_message_queue()
204+
205+
mock_queue_get.assert_called_once()
206+
207+
208+
@pytest.mark.asyncio
209+
async def test_zmq_adapter_process_message_no_messsage(
210+
zmq_adapter: ZeroMQAdapter, capsys
211+
):
212+
await zmq_adapter._process_message(None)
213+
214+
captured = capsys.readouterr()
215+
assert captured.out == "No message\n"
216+
217+
218+
@pytest.mark.asyncio
219+
async def test_zmq_adapter_process_message_socket_closed(
220+
zmq_adapter: ZeroMQAdapter, mock_socket, capsys
221+
):
222+
zmq_adapter._socket = mock_socket
223+
zmq_adapter._socket._closing = True
224+
225+
await zmq_adapter._process_message([b"test"])
226+
227+
captured = capsys.readouterr()
228+
assert captured.out == "Socket closed...\n"
229+
230+
231+
@pytest.mark.asyncio
232+
async def test_zmq_adapter_process_message_zmq_error(
233+
zmq_adapter: ZeroMQAdapter, mock_socket, mock_socket_write, capsys
234+
):
235+
zmq_adapter._socket = mock_socket
236+
zmq_adapter._socket._closing = False
237+
238+
# Shouldn't need to specify this below
239+
zmq_adapter._socket.write = mock_socket_write
240+
mock_socket_write.side_effect = zmq.error.ZMQError(6)
241+
242+
await zmq_adapter._process_message([b"test"])
243+
244+
captured = capsys.readouterr()
245+
assert captured.out == "ZMQ Error No such device or address\n"
246+
247+
248+
@pytest.mark.asyncio
249+
async def test_zmq_adapter_process_message_exception(
250+
zmq_adapter: ZeroMQAdapter, mock_socket, mock_socket_write, capsys
251+
):
252+
zmq_adapter._socket = mock_socket
253+
zmq_adapter._socket._closing = False
254+
255+
# Shouldn't need to specify this below
256+
zmq_adapter._socket.write = mock_socket_write
257+
mock_socket_write.side_effect = Exception("Test Exception")
258+
259+
await zmq_adapter._process_message([b"test"])
260+
261+
captured = capsys.readouterr()
262+
assert (
263+
captured.out == "Error, Test Exception\n"
264+
"Unable to write to ZMQ stream, trying again...\n"
265+
)
266+
267+
268+
@pytest.mark.asyncio
269+
async def test_zmq_adapter_process_message_sub(
270+
zmq_adapter: ZeroMQAdapter, mock_socket, mock_socket_write
271+
):
272+
zmq_adapter._socket = mock_socket
273+
# Shouldn't need to specify this below
274+
zmq_adapter._socket.write = mock_socket_write
275+
zmq_adapter._socket._closing = False
276+
277+
await zmq_adapter._process_message([b"test"])
278+
279+
mock_socket_write.assert_called_once()
280+
281+
282+
@pytest.mark.asyncio
283+
async def test_zmq_adapter_process_message_dealer(
284+
zmq_adapter_dealer: ZeroMQAdapter, mock_socket, mock_socket_write
285+
):
286+
zmq_adapter_dealer._socket = mock_socket
287+
# Shouldn't need to specify this below
288+
zmq_adapter_dealer._socket.write = mock_socket_write
289+
zmq_adapter_dealer._socket._closing = False
290+
291+
await zmq_adapter_dealer._process_message([b"test"])
292+
293+
mock_socket_write.assert_called_once()
294+
295+
296+
@pytest.mark.asyncio
297+
async def test_zmq_adapter_process_response_queue(
298+
zmq_adapter: ZeroMQAdapter, mock_queue, mock_queue_put_nowait
299+
):
300+
zmq_adapter._read_response = AsyncMock()
301+
zmq_adapter._read_response.return_value = b"test"
302+
303+
zmq_adapter._recv_message_queue = mock_queue
304+
# Shouldn't need to specify this below
305+
zmq_adapter._recv_message_queue.put_nowait = mock_queue_put_nowait
306+
307+
await zmq_adapter._process_response_queue()
308+
309+
mock_queue_put_nowait.assert_called_once()

0 commit comments

Comments
 (0)