From c8264774b0d133a1ebb393ea07428070a56ea50d Mon Sep 17 00:00:00 2001 From: AlexWells Date: Thu, 8 Jun 2023 09:23:21 +0100 Subject: [PATCH] Fix devIocStats by including posix headers This relies on the config_var "POSIX" being defined as True/False for the current platform. The test is pretty simple, just the CPU count and IOC CPU load as they're fairly easy to calculate --- CHANGELOG.rst | 4 +++ setup.py | 21 +++++++++--- tests/test_deviocstats.py | 71 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 tests/test_deviocstats.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7afd2070..ef898e67 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,10 @@ Changed: - `Improve string representation of RecordWrapper instances <../../pull/130>` +Fixed: + +- `Fix devIocStats by including posix headers <../../pull/134>` + 4.3.0_ - 2023-04-04 ------------------- diff --git a/setup.py b/setup.py index 34157bce..1b70ecd2 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,7 @@ ] devIocStats_src = os.path.join("softioc", "iocStats", "devIocStats") +devIocStats_posix = os.path.join(devIocStats_src, "os", "posix") devIocStats_os = os.path.join(devIocStats_src, "os", get_config_var('OS_CLASS')) devIocStats_default = os.path.join(devIocStats_src, "os", "default") @@ -52,14 +53,26 @@ else: sources.append(os.path.join(devIocStats_default, f)) +include_dirs = [ + epicscorelibs.path.include_path, + devIocStats_src, + devIocStats_os, + devIocStats_default +] + +if get_config_var("POSIX"): + # If we're on a POSIX system, insert the POSIX folder into the list after + # the os-specific one so that os-specific header files are used first. + include_dirs.insert( + include_dirs.index(devIocStats_os) + 1, + devIocStats_posix + ) + # Extension with all our C code ext = Extension( name='softioc._extension', sources = sources, - include_dirs=[ - epicscorelibs.path.include_path, - devIocStats_src, devIocStats_os, devIocStats_default - ], + include_dirs = include_dirs, dsos = [ 'epicscorelibs.lib.qsrv', 'epicscorelibs.lib.pvAccessIOC', diff --git a/tests/test_deviocstats.py b/tests/test_deviocstats.py new file mode 100644 index 00000000..5047200e --- /dev/null +++ b/tests/test_deviocstats.py @@ -0,0 +1,71 @@ +# File for tests related to devIocStats support module, which at time of writing +# is built alongside PythonSoftIOC and optionally turned on at runtime + +import multiprocessing +import pytest + +from conftest import ( + create_random_prefix, + TIMEOUT, + select_and_recv, + get_multiprocessing_context +) + +from softioc import asyncio_dispatcher, builder, softioc + +def deviocstats_test_func( + device_name, + child_conn): + """Start the IOC with the specified validate method""" + + builder.SetDeviceName(device_name) + + dispatcher = asyncio_dispatcher.AsyncioDispatcher() + builder.LoadDatabase() + softioc.devIocStats(device_name) + softioc.iocInit(dispatcher) + + child_conn.send("R") + + # Keep process alive while main thread runs CAGET + if child_conn.poll(TIMEOUT): + val = child_conn.recv() + assert val == "D", "Did not receive expected Done character" + +@pytest.mark.asyncio +async def test_deviocstats(): + + ctx = get_multiprocessing_context() + + parent_conn, child_conn = ctx.Pipe() + + device_name = create_random_prefix() + + process = ctx.Process( + target=deviocstats_test_func, + args=(device_name, child_conn), + ) + + process.start() + + from aioca import caget, purge_channel_caches + + try: + # Wait for message that IOC has started + select_and_recv(parent_conn, "R") + + # Suppress potential spurious warnings + purge_channel_caches() + + cpu_cnt = await caget(device_name + ":CPU_CNT") + assert cpu_cnt == multiprocessing.cpu_count() + + ioc_cpu_load = await caget(device_name + ":IOC_CPU_LOAD") + assert ioc_cpu_load == pytest.approx(0, abs=1e-2) + + + finally: + # Suppress potential spurious warnings + purge_channel_caches() + parent_conn.send("D") # "Done" + process.join(timeout=TIMEOUT)