New pycoax API

This commit is contained in:
Andrew Kay
2021-10-16 12:19:13 -05:00
parent f78af20a20
commit 9dfab54950
29 changed files with 1573 additions and 659 deletions

View File

@@ -1,10 +1,12 @@
import unittest
from unittest.mock import Mock
from unittest.mock import Mock, call
import sliplib
import context
from coax import SerialInterface, InterfaceError, ReceiveError, ReceiveTimeout
from coax.interface import FrameFormat
from coax.serial_interface import SerialInterface
from coax.exceptions import InterfaceError, ReceiveTimeout
class SerialInterfaceResetTestCase(unittest.TestCase):
def setUp(self):
@@ -34,7 +36,7 @@ class SerialInterfaceResetTestCase(unittest.TestCase):
def test_legacy_response_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('01 01 02 03'))
self.interface._read_message.return_value=bytes.fromhex('01 01 02 03')
# Act
self.interface.reset()
@@ -55,7 +57,7 @@ class SerialInterfaceResetTestCase(unittest.TestCase):
def test_invalid_message_length_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('01 01'))
self.interface._read_message.return_value=bytes.fromhex('01 01')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid reset response'):
@@ -63,7 +65,7 @@ class SerialInterfaceResetTestCase(unittest.TestCase):
def test_error_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('02 01'))
self.interface._read_message.return_value=bytes.fromhex('02 01')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid request message'):
@@ -71,13 +73,138 @@ class SerialInterfaceResetTestCase(unittest.TestCase):
def test_error_with_description_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('02 01 45 72 72 6f 72 20 64 65 73 63 72 69 70 74 69 6f 6e'))
self.interface._read_message.return_value=bytes.fromhex('02 01 45 72 72 6f 72 20 64 65 73 63 72 69 70 74 69 6f 6e')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid request message: Error description'):
self.interface.reset()
# TODO...
class SerialInterfaceTransmitReceiveTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.serial.timeout = None
self.interface = SerialInterface(self.serial)
self.interface._write_message = Mock()
self.interface._read_message = Mock()
def test_words_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORDS, [0b1111111111, 0b0000000000]))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 ff 03 00 00 00 01 00 00'))
def test_words_repeat_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORDS, ([0b1111111111, 0b0000000000], 2)))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 02 ff 03 00 00 00 01 00 00'))
def test_word_data_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 ff 03 02 00 fe 03 00 01 00 00'))
def test_word_data_repeat_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORD_DATA, 0b1111111111, ([0x00, 0xff], 2)))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 80 02 ff 03 02 00 fe 03 00 01 00 00'))
def test_data_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.DATA, [0x00, 0xff]))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 02 00 fe 03 00 01 00 00'))
def test_data_repeat_frame(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.DATA, ([0x00, 0xff], 2)))], [1], None)
# Assert
self.assertEqual(responses, [[0]])
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 02 02 00 fe 03 00 01 00 00'))
def test_receive_timeout_error(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('02 66')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], 0.5)
# Assert
self.assertIsInstance(responses[0], ReceiveTimeout)
def test_interface_error(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('02 65')
# Act and assert
with self.assertRaises(InterfaceError):
self.interface._transmit_receive([(None, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], 0.5)
def test_timeout(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
self.interface._transmit_receive([(None, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], 0.5)
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 ff 03 02 00 fe 03 00 01 01 f4'))
def test_addressed_frame(self):
with self.assertRaises(NotImplementedError):
self.interface._transmit_receive([(0b111000, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], 0.5)
def test_multiple_frames(self):
# Arrange
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
# Act
responses = self.interface._transmit_receive([(None, (FrameFormat.WORDS, [0b1111111111, 0b0000000000])), (None, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1, 1], None)
# Assert
self.assertEqual(responses, [[0], [0]])
self.interface._write_message.assert_has_calls([call(bytes.fromhex('06 00 00 ff 03 00 00 00 01 00 00')), call(bytes.fromhex('06 00 00 ff 03 02 00 fe 03 00 01 00 00'))])
class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def setUp(self):
@@ -89,7 +216,7 @@ class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def test(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 04 01 02 03 04 00 00'))
self.interface.slip_serial.recv_msg.return_value=bytes.fromhex('00 04 01 02 03 04 00 00')
# Act
message = self.interface._read_message()
@@ -99,7 +226,7 @@ class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def test_protocol_error_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(side_effect=sliplib.ProtocolError)
self.interface.slip_serial.recv_msg.side_effect=sliplib.ProtocolError
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'SLIP protocol error'):
@@ -107,7 +234,7 @@ class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def test_invalid_message_length_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00'))
self.interface.slip_serial.recv_msg.return_value=bytes.fromhex('00')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid response message'):
@@ -115,7 +242,7 @@ class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def test_message_length_mismatch_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 05 01 02 03 04 00 00'))
self.interface.slip_serial.recv_msg.return_value=bytes.fromhex('00 05 01 02 03 04 00 00')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Response message length mismatch'):
@@ -123,7 +250,7 @@ class SerialInterfaceReadMessageTestCase(unittest.TestCase):
def test_empty_message_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 00 00 00'))
self.interface.slip_serial.recv_msg.return_value=bytes.fromhex('00 00 00 00')
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Empty response message'):