Skip to content

Commit 2b76593

Browse files
Add tests for Issue #43
These were developed on the "sort_settings_values" branch but were never committed there. Still valid test cases, although they require a little refactoring to fit with the changes made on this branch.
1 parent 0d7b372 commit 2b76593

File tree

1 file changed

+161
-1
lines changed

1 file changed

+161
-1
lines changed

tests/test_records.py

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,20 @@ def record_values_names(fixture_value):
204204
),
205205
numpy.ndarray,
206206
),
207+
(
208+
"wIn_unicode",
209+
builder.WaveformIn,
210+
"%a€b",
211+
numpy.array([37, 97, 226, 130, 172, 98, 0], dtype=numpy.uint8),
212+
numpy.ndarray,
213+
),
214+
(
215+
"wOut_unicode",
216+
builder.WaveformOut,
217+
"%a€b",
218+
numpy.array([37, 97, 226, 130, 172, 98, 0], dtype=numpy.uint8),
219+
numpy.ndarray,
220+
),
207221
]
208222

209223

@@ -353,7 +367,7 @@ def run_ioc(record_configurations: list, conn, set_enum, get_enum):
353367

354368
records: List[RecordWrapper] = []
355369

356-
# Loop over given list and create the records
370+
# Create records from the given list
357371
for configuration in record_configurations:
358372
kwarg = {}
359373

@@ -840,3 +854,149 @@ def test_value_none_rejected_set_after_init(self, record_funcs_reject_none):
840854
finally:
841855
process.terminate()
842856
process.join(timeout=3)
857+
858+
859+
class TestValidate:
860+
"""Tests related to the validate callback"""
861+
862+
@pytest.fixture(
863+
params=[
864+
(builder.aOut, 7.89, 0),
865+
(builder.boolOut, 1, 0),
866+
(builder.longOut, 7, 0),
867+
(builder.stringOut, "HI", ""),
868+
(builder.mbbOut, 2, 0),
869+
(builder.WaveformOut, [10, 11, 12], []),
870+
]
871+
)
872+
def out_records(self, request):
873+
"""The list of Out records and an associated value to set """
874+
return request.param
875+
876+
def validate_always_pass(self, record, new_val):
877+
"""Validation method that always allows changes"""
878+
return True
879+
880+
def validate_always_fail(self, record, new_val):
881+
"""Validation method that always rejects changes"""
882+
return False
883+
884+
def validate_ioc_test_func(self, record_func, queue, validate_pass: bool):
885+
"""Start the IOC with the specified validate method"""
886+
887+
builder.SetDeviceName(DEVICE_NAME)
888+
889+
kwarg = {}
890+
if record_func in [builder.WaveformIn, builder.WaveformOut]:
891+
kwarg = {"length": 50} # Required when no value on creation
892+
893+
kwarg.update(
894+
{
895+
"validate": self.validate_always_pass
896+
if validate_pass
897+
else self.validate_always_fail
898+
}
899+
)
900+
901+
record_func("VALIDATE-RECORD", **kwarg)
902+
903+
dispatcher = asyncio_dispatcher.AsyncioDispatcher()
904+
builder.LoadDatabase()
905+
softioc.iocInit(dispatcher)
906+
907+
queue.put("IOC ready")
908+
909+
# Keep process alive while main thread works.
910+
# This is most applicable to CAGET tests.
911+
asyncio.run_coroutine_threadsafe(
912+
asyncio.sleep(TIMEOUT), dispatcher.loop
913+
).result()
914+
915+
916+
@requires_cothread
917+
def test_validate_allows_updates(self, out_records):
918+
"""Test that record values are updated correctly when validate
919+
method allows it """
920+
921+
creation_func, value, _ = out_records
922+
923+
queue = multiprocessing.Queue()
924+
process = multiprocessing.Process(
925+
target=self.validate_ioc_test_func,
926+
args=(creation_func, queue, True),
927+
)
928+
929+
process.start()
930+
931+
try:
932+
queue.get(timeout=5) # Get the expected IOc initialised message
933+
934+
from cothread.catools import caget, caput, _channel_cache
935+
936+
# See other places in this file for why we call it
937+
_channel_cache.purge()
938+
939+
put_ret = caput(
940+
DEVICE_NAME + ":" + "VALIDATE-RECORD",
941+
value,
942+
wait=True,
943+
)
944+
assert put_ret.ok, "caput did not succeed"
945+
946+
ret_val = caget(
947+
DEVICE_NAME + ":" + "VALIDATE-RECORD",
948+
timeout=3
949+
)
950+
951+
if creation_func in [builder.WaveformOut, builder.WaveformIn]:
952+
assert numpy.array_equal(ret_val, value)
953+
else:
954+
assert ret_val == value
955+
956+
finally:
957+
process.terminate()
958+
process.join(timeout=3)
959+
960+
@requires_cothread
961+
def test_validate_blocks_updates(self, out_records):
962+
"""Test that record values are not updated when validate method
963+
always blocks updates"""
964+
965+
creation_func, value, default = out_records
966+
967+
queue = multiprocessing.Queue()
968+
process = multiprocessing.Process(
969+
target=self.validate_ioc_test_func,
970+
args=(creation_func, queue, False),
971+
)
972+
973+
process.start()
974+
975+
try:
976+
queue.get(timeout=5) # Get the expected IOc initialised message
977+
978+
from cothread.catools import caget, caput, _channel_cache
979+
980+
# See other places in this file for why we call it
981+
_channel_cache.purge()
982+
983+
put_ret = caput(
984+
DEVICE_NAME + ":" + "VALIDATE-RECORD",
985+
value,
986+
wait=True,
987+
)
988+
assert put_ret.ok, "caput did not succeed"
989+
990+
ret_val = caget(
991+
DEVICE_NAME + ":" + "VALIDATE-RECORD",
992+
timeout=3
993+
)
994+
995+
if creation_func in [builder.WaveformOut, builder.WaveformIn]:
996+
assert numpy.array_equal(ret_val, default)
997+
else:
998+
assert ret_val == default
999+
1000+
finally:
1001+
process.terminate()
1002+
process.join(timeout=3)

0 commit comments

Comments
 (0)