Skip to content

Commit

Permalink
AsyncFramer.
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Oct 4, 2024
1 parent 9768e54 commit 8d062ca
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 44 deletions.
4 changes: 2 additions & 2 deletions pymodbus/framer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"ModbusRtuFramer",
"ModbusSocketFramer",
"ModbusTlsFramer",
"Framer",
"AsyncFramer",
"FramerType",
]

from pymodbus.framer.framer import Framer, FramerType
from pymodbus.framer.framer import AsyncFramer, FramerType
from pymodbus.framer.old_framer_ascii import ModbusAsciiFramer
from pymodbus.framer.old_framer_base import ModbusFramer
from pymodbus.framer.old_framer_rtu import ModbusRtuFramer
Expand Down
2 changes: 1 addition & 1 deletion pymodbus/framer/framer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class FramerType(str, Enum):
TLS = "tls"


class Framer(ModbusProtocol):
class AsyncFramer(ModbusProtocol):
"""Framer layer extending transport layer.
extends the ModbusProtocol to handle receiving and sending of complete modbus PDU.
Expand Down
8 changes: 4 additions & 4 deletions test/framers/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytest

from pymodbus.factory import ClientDecoder, ServerDecoder
from pymodbus.framer import Framer, FramerType
from pymodbus.framer import AsyncFramer, FramerType
from pymodbus.transport import CommParams


Expand All @@ -20,11 +20,11 @@ def prepare_is_server():
"""Return client/server."""
return False

@mock.patch.multiple(Framer, __abstractmethods__=set()) # eliminate abstract methods (callbacks)
@pytest.fixture(name="dummy_framer")
@mock.patch.multiple(AsyncFramer, __abstractmethods__=set()) # eliminate abstract methods (callbacks)
@pytest.fixture(name="dummy_async_framer")
async def prepare_test_framer(entry, is_server):
"""Return framer object."""
framer = Framer(entry, CommParams(), is_server, [0, 1]) # type: ignore[abstract]
framer = AsyncFramer(entry, CommParams(), is_server, [0, 1]) # type: ignore[abstract]
framer.send = mock.Mock() # type: ignore[method-assign]
if entry == FramerType.RTU:
func_table = (ServerDecoder if is_server else ClientDecoder)().lookup # type: ignore[attr-defined]
Expand Down
74 changes: 37 additions & 37 deletions test/framers/test_framer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ class TestFramer:
"""Test module."""

@pytest.mark.parametrize(("entry"), list(FramerType))
async def test_framer_init(self, dummy_framer):
async def test_framer_init(self, dummy_async_framer):
"""Test framer type."""
assert dummy_framer.handle
assert dummy_async_framer.handle

@pytest.mark.parametrize(("data", "res_len", "cx", "rc"), [
(b'12345', 5, 1, [(5, 0, 0, b'12345')]), # full frame
Expand All @@ -29,45 +29,45 @@ async def test_framer_init(self, dummy_framer):
(b'12345678', 5, 0, [(5, 0, 0, b'')]), # garble first, not full frame
(b'12345678', 8, 0, [(8, 0, 0, b'')]), # garble first, faulty frame
])
async def test_framer_callback(self, dummy_framer, data, res_len, cx, rc):
async def test_framer_callback(self, dummy_async_framer, data, res_len, cx, rc):
"""Test framer type."""
dummy_framer.callback_request_response = mock.Mock()
dummy_framer.handle.decode = mock.MagicMock(side_effect=iter(rc))
assert dummy_framer.callback_data(data) == res_len
assert dummy_framer.callback_request_response.call_count == cx
dummy_async_framer.callback_request_response = mock.Mock()
dummy_async_framer.handle.decode = mock.MagicMock(side_effect=iter(rc))
assert dummy_async_framer.callback_data(data) == res_len
assert dummy_async_framer.callback_request_response.call_count == cx
if cx:
dummy_framer.callback_request_response.assert_called_with(b'12345', 0, 0)
dummy_async_framer.callback_request_response.assert_called_with(b'12345', 0, 0)
else:
dummy_framer.callback_request_response.assert_not_called()
dummy_async_framer.callback_request_response.assert_not_called()

@pytest.mark.parametrize(("data", "res_len", "rc"), [
(b'12345', 5, [(5, 0, 17, b'12345'), (0, 0, 0, b'')]), # full frame, wrong dev_id
])
async def test_framer_callback_wrong_id(self, dummy_framer, data, res_len, rc):
async def test_framer_callback_wrong_id(self, dummy_async_framer, data, res_len, rc):
"""Test framer type."""
dummy_framer.callback_request_response = mock.Mock()
dummy_framer.handle.decode = mock.MagicMock(side_effect=iter(rc))
dummy_framer.broadcast = False
assert dummy_framer.callback_data(data) == res_len
dummy_framer.callback_request_response.assert_not_called()
dummy_async_framer.callback_request_response = mock.Mock()
dummy_async_framer.handle.decode = mock.MagicMock(side_effect=iter(rc))
dummy_async_framer.broadcast = False
assert dummy_async_framer.callback_data(data) == res_len
dummy_async_framer.callback_request_response.assert_not_called()

async def test_framer_build_send(self, dummy_framer):
async def test_framer_build_send(self, dummy_async_framer):
"""Test framer type."""
dummy_framer.handle.encode = mock.MagicMock(return_value=(b'decode'))
dummy_framer.build_send(b'decode', 1, 0)
dummy_framer.handle.encode.assert_called_once()
dummy_framer.send.assert_called_once()
dummy_framer.send.assert_called_with(b'decode', None)
dummy_async_framer.handle.encode = mock.MagicMock(return_value=(b'decode'))
dummy_async_framer.build_send(b'decode', 1, 0)
dummy_async_framer.handle.encode.assert_called_once()
dummy_async_framer.send.assert_called_once()
dummy_async_framer.send.assert_called_with(b'decode', None)

@pytest.mark.parametrize(
("data", "res_len", "res_id", "res_tid", "res_data"), [
(b'\x00\x01', 0, 0, 0, b''),
(b'\x01\x02\x03', 3, 1, 2, b'\x03'),
(b'\x04\x05\x06\x07\x08\x09\x00\x01\x02\x03', 10, 4, 5, b'\x06\x07\x08\x09\x00\x01\x02\x03'),
])
async def test_framer_decode(self, dummy_framer, data, res_id, res_tid, res_len, res_data):
async def test_framer_decode(self, dummy_async_framer, data, res_id, res_tid, res_len, res_data):
"""Test decode method in all types."""
t_len, t_id, t_tid, t_data = dummy_framer.handle.decode(data)
t_len, t_id, t_tid, t_data = dummy_async_framer.handle.decode(data)
assert res_len == t_len
assert res_id == t_id
assert res_tid == t_tid
Expand All @@ -78,9 +78,9 @@ async def test_framer_decode(self, dummy_framer, data, res_id, res_tid, res_len
(b'\x01\x02', 5, 6, b'\x05\x06\x01\x02'),
(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09', 17, 25, b'\x11\x19\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09'),
])
async def test_framer_encode(self, dummy_framer, data, dev_id, tr_id, res_data):
async def test_framer_encode(self, dummy_async_framer, data, dev_id, tr_id, res_data):
"""Test decode method in all types."""
t_data = dummy_framer.handle.encode(data, dev_id, tr_id)
t_data = dummy_async_framer.handle.encode(data, dev_id, tr_id)
assert res_data == t_data

@pytest.mark.parametrize(
Expand Down Expand Up @@ -293,28 +293,28 @@ def test_encode_type(self, frame, frame_expected, data, dev_id, tr_id, inx1, inx
"single",
]
)
async def test_decode_type(self, entry, dummy_framer, data, dev_id, tr_id, expected, split):
async def test_decode_type(self, entry, dummy_async_framer, data, dev_id, tr_id, expected, split):
"""Test encode method."""
if entry == FramerType.TLS and split != "no":
return
if entry == FramerType.RTU:
return
dummy_framer.callback_request_response = mock.MagicMock()
dummy_async_framer.callback_request_response = mock.MagicMock()
if split == "no":
used_len = dummy_framer.callback_data(data)
used_len = dummy_async_framer.callback_data(data)
elif split == "half":
split_len = int(len(data) / 2)
assert not dummy_framer.callback_data(data[0:split_len])
dummy_framer.callback_request_response.assert_not_called()
used_len = dummy_framer.callback_data(data)
assert not dummy_async_framer.callback_data(data[0:split_len])
dummy_async_framer.callback_request_response.assert_not_called()
used_len = dummy_async_framer.callback_data(data)
else:
last = len(data)
for i in range(0, last -1):
assert not dummy_framer.callback_data(data[0:i+1])
dummy_framer.callback_request_response.assert_not_called()
used_len = dummy_framer.callback_data(data)
assert not dummy_async_framer.callback_data(data[0:i+1])
dummy_async_framer.callback_request_response.assert_not_called()
used_len = dummy_async_framer.callback_data(data)
assert used_len == len(data)
dummy_framer.callback_request_response.assert_called_with(expected, dev_id, tr_id)
dummy_async_framer.callback_request_response.assert_called_with(expected, dev_id, tr_id)

@pytest.mark.parametrize(
("entry", "data", "exp"),
Expand Down Expand Up @@ -382,9 +382,9 @@ async def test_decode_type(self, entry, dummy_framer, data, dev_id, tr_id, expec
# ]),
]
)
async def test_decode_complicated(self, dummy_framer, data, exp):
async def test_decode_complicated(self, dummy_async_framer, data, exp):
"""Test encode method."""
for ent in exp:
used_len, _, _, res_data = dummy_framer.handle.decode(data)
used_len, _, _, res_data = dummy_async_framer.handle.decode(data)
assert used_len == ent[0]
assert res_data == ent[1]

0 comments on commit 8d062ca

Please sign in to comment.