Skip to content

Commit 6d6bc7a

Browse files
add unittests to verify fix of #35 for #15 and #24
1 parent 7ca7a30 commit 6d6bc7a

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

tests/test_tcp_example.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,39 @@ def test_read_coils_partially(self) -> None:
327327
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
328328
self.assertEqual(coil_status, expectation_list_partial)
329329

330+
def test_read_coils_specific_of_multiple(self) -> None:
331+
"""Test reading specific coils of client defined as list"""
332+
# the offset based on the specified register
333+
# e.g. register = 150, offset = 3, qty = 5, the requested coils are
334+
# 153-158
335+
base_coil_offset = 3
336+
coil_qty = 5 # read only 5 coils of multiple defined ones
337+
338+
coil_address = (
339+
self._register_definitions['COILS']['MANY_COILS']['register'] +
340+
base_coil_offset
341+
)
342+
expectation_list_full = list(
343+
map(bool,
344+
self._register_definitions['COILS']['MANY_COILS']['val'])
345+
)
346+
expectation_list = expectation_list_full[
347+
base_coil_offset:base_coil_offset + coil_qty
348+
]
349+
350+
coil_status = self._host.read_coils(
351+
slave_addr=self._client_addr,
352+
starting_addr=coil_address,
353+
coil_qty=coil_qty)
354+
355+
self.test_logger.debug(
356+
'Status of COIL {} length {}: {}, expectation: {}'.
357+
format(coil_address, coil_qty, coil_status, expectation_list))
358+
self.assertIsInstance(coil_status, list)
359+
self.assertEqual(len(coil_status), coil_qty)
360+
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
361+
self.assertEqual(coil_status, expectation_list)
362+
330363
def test_read_discrete_inputs_single(self) -> None:
331364
"""Test reading discrete inputs of client"""
332365
ist_address = \
@@ -748,6 +781,73 @@ def test_write_single_coil(self) -> None:
748781
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
749782
self.assertEqual(coil_status, expectation_list)
750783

784+
# test setting a coil in a list of coils
785+
base_coil_offset = 3
786+
coil_qty = 1
787+
coil_address = (
788+
self._register_definitions['COILS']['MANY_COILS']['register'] +
789+
base_coil_offset
790+
)
791+
expectation_list_full = list(
792+
map(bool,
793+
self._register_definitions['COILS']['MANY_COILS']['val'])
794+
)
795+
expectation_list = expectation_list_full[
796+
base_coil_offset:base_coil_offset + coil_qty
797+
]
798+
799+
#
800+
# Check clean system (client register data is as initially defined)
801+
#
802+
# verify current state by reading coil states
803+
coil_status = self._host.read_coils(
804+
slave_addr=self._client_addr,
805+
starting_addr=coil_address,
806+
coil_qty=coil_qty)
807+
808+
self.test_logger.debug(
809+
'Initial status of COIL {}: {}, expectation: {}'.format(
810+
coil_address,
811+
coil_status,
812+
expectation_list))
813+
self.assertIsInstance(coil_status, list)
814+
self.assertEqual(len(coil_status), coil_qty)
815+
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
816+
self.assertEqual(coil_status, expectation_list)
817+
818+
#
819+
# Test setting coil to True
820+
#
821+
# update coil state of client with a different than the current state
822+
new_coil_val = not expectation_list[0]
823+
expectation_list[0] = new_coil_val
824+
825+
operation_status = self._host.write_single_coil(
826+
slave_addr=self._client_addr,
827+
output_address=coil_address,
828+
output_value=new_coil_val)
829+
830+
self.test_logger.debug(
831+
'Result of setting COIL {} to {}: {}, expectation: {}'.format(
832+
coil_address, new_coil_val, operation_status, True))
833+
self.assertIsInstance(operation_status, bool)
834+
self.assertTrue(operation_status)
835+
836+
# verify setting of state by reading data back again
837+
coil_status = self._host.read_coils(
838+
slave_addr=self._client_addr,
839+
starting_addr=coil_address,
840+
coil_qty=coil_qty)
841+
842+
self.test_logger.debug('Status of COIL {}: {}, expectation: {}'.
843+
format(coil_address,
844+
coil_status,
845+
expectation_list))
846+
self.assertIsInstance(coil_status, list)
847+
self.assertEqual(len(coil_status), coil_qty)
848+
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
849+
self.assertEqual(coil_status, expectation_list)
850+
751851
def test_write_single_register(self) -> None:
752852
"""Test updating single holding register of client"""
753853
hreg_address = \
@@ -934,6 +1034,83 @@ def test_write_multiple_coils(self) -> None:
9341034
# https://github.com/brainelectronics/micropython-modbus/issues/38
9351035
# self.assertEqual(coil_status, expectation_list)
9361036

1037+
def test_write_multiple_coils_specific_of_multiple(self) -> None:
1038+
"""Test updating specific coils of client defined as list"""
1039+
# test with more than 8 coils
1040+
coil_address = \
1041+
self._register_definitions['COILS']['MANY_COILS']['register']
1042+
coil_qty = \
1043+
self._register_definitions['COILS']['MANY_COILS']['len']
1044+
expectation_list = list(
1045+
map(bool, self._register_definitions['COILS']['MANY_COILS']['val'])
1046+
)
1047+
1048+
#
1049+
# Check clean system (client register data is as initially defined)
1050+
#
1051+
# verify current state by reading coil states
1052+
coil_status = self._host.read_coils(
1053+
slave_addr=self._client_addr,
1054+
starting_addr=coil_address,
1055+
coil_qty=coil_qty)
1056+
1057+
self.test_logger.debug(
1058+
'Initial status of COIL {} length {}: {}, expectation: {}'.format(
1059+
coil_address, coil_qty, coil_status, expectation_list))
1060+
self.assertIsInstance(coil_status, list)
1061+
self.assertEqual(len(coil_status), coil_qty)
1062+
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
1063+
self.assertEqual(coil_status, expectation_list)
1064+
1065+
#
1066+
# Test setting coils to inverted initial states
1067+
#
1068+
# update coil states of client with a different than the current state
1069+
new_coil_vals_full = [not val for val in expectation_list]
1070+
1071+
# the offset based on the specified register
1072+
# e.g. register = 150, offset = 3, qty = 5, the requested coils are
1073+
# 153-158
1074+
base_coil_offset = 3
1075+
coil_qty = 5 # read only 5 coils of multiple defined ones
1076+
1077+
new_coil_vals = new_coil_vals_full[
1078+
base_coil_offset:(base_coil_offset + coil_qty)
1079+
]
1080+
expectation_list = (
1081+
expectation_list[:base_coil_offset] +
1082+
new_coil_vals +
1083+
expectation_list[base_coil_offset + coil_qty:]
1084+
)
1085+
1086+
operation_status = self._host.write_multiple_coils(
1087+
slave_addr=self._client_addr,
1088+
starting_address=coil_address,
1089+
output_values=new_coil_vals)
1090+
1091+
self.test_logger.debug(
1092+
'Result of setting COIL {} length {} to {}: {}, expectation: {}'.
1093+
format(
1094+
coil_address, coil_qty, new_coil_vals, operation_status, True))
1095+
self.assertIsInstance(operation_status, bool)
1096+
self.assertTrue(operation_status)
1097+
1098+
# verify setting of states by reading data back again
1099+
coil_status = self._host.read_coils(
1100+
slave_addr=self._client_addr,
1101+
starting_addr=coil_address,
1102+
coil_qty=coil_qty)
1103+
1104+
self.test_logger.debug(
1105+
'Status of COIL {} length {}: {}, expectation: {}'.format(
1106+
coil_address, coil_qty, coil_status, expectation_list))
1107+
self.assertIsInstance(coil_status, list)
1108+
self.assertEqual(len(coil_status), coil_qty)
1109+
self.assertTrue(all(isinstance(x, bool) for x in coil_status))
1110+
# Reading coil data bits is reversed, see #38
1111+
# https://github.com/brainelectronics/micropython-modbus/issues/38
1112+
# self.assertEqual(coil_status, expectation_list)
1113+
9371114
def test_write_multiple_registers(self) -> None:
9381115
"""Test updating multiple holding register of client"""
9391116
hreg_address = \

0 commit comments

Comments
 (0)