diff --git a/ioc/tests/support/StreamDevice/simple/default.nix b/ioc/tests/support/StreamDevice/simple/default.nix index dc2ddcc3..45eeaf6e 100644 --- a/ioc/tests/support/StreamDevice/simple/default.nix +++ b/ioc/tests/support/StreamDevice/simple/default.nix @@ -2,10 +2,6 @@ inherit (pkgs) epnixLib; inherit (pkgs.stdenv.hostPlatform) system; - mock_server = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./mock-server; - }; - result = epnixLib.evalEpnixModules { nixpkgsConfig.system = system; epnixConfig.imports = [./top/epnix.nix]; @@ -19,70 +15,60 @@ in name = "support-StreamDevice-simple"; meta.maintainers = with epnixLib.maintainers; [minijackson]; - nodes.machine = let - listenAddr = "127.0.0.1:1234"; - in - {lib, ...}: { - environment.systemPackages = [pkgs.epnix.epics-base]; + nodes.machine = {lib, ...}: { + environment.systemPackages = [pkgs.epnix.epics-base]; - systemd.sockets.mock-server = { + systemd.services = { + "psu-simulator" = { wantedBy = ["multi-user.target"]; - listenStreams = [listenAddr]; - socketConfig.Accept = true; - }; - - systemd.services = { - "mock-server@".serviceConfig = { - ExecStart = "${mock_server}/bin/mock_server"; - StandardInput = "socket"; - StandardError = "journal"; + serviceConfig = { + ExecStart = lib.getExe pkgs.epnix.psu-simulator; }; - - ioc = lib.mkMerge [ - service - {environment.STREAM_PS1 = listenAddr;} - ]; }; + + ioc = lib.mkMerge [ + service + {environment.STREAM_PS1 = "localhost:9999";} + ]; }; + }; testScript = '' machine.wait_for_unit("default.target") machine.wait_for_unit("ioc.service") - with subtest("getting fixed values"): - machine.wait_until_succeeds("caget -t FLOAT:IN | grep -qxF '42.1234'") - machine.wait_until_succeeds("caget -t FLOAT_WITH_PREFIX:IN | grep -qxF '69.1337'") - machine.wait_until_succeeds("caget -t ENUM:IN | grep -qxF '1'") + def assert_caget(pv: str, expected: str) -> None: + machine.wait_until_succeeds(f"caget -t '{pv}' | grep -qxF '{expected}'", timeout=10) - with subtest("setting values"): - machine.wait_until_succeeds("caget -t VARFLOAT:IN | grep -qxF '0'") - - # Caput can simply not go through - def put_check_varfloat(_) -> bool: - machine.succeed("caput VARFLOAT:OUT 123.456") - status, _output = machine.execute("caget -t VARFLOAT:IN | grep -qxF '123.456'") + def assert_caput(pv: str, value: str) -> None: + def do_caput(_) -> bool: + machine.succeed(f"caput '{pv}' '{value}'") + status, _output = machine.execute(f"caget -t '{pv}' | grep -qxF '{value}'") return status == 0 - retry(put_check_varfloat) + retry(do_caput, timeout=10) - with subtest("calc integration"): - machine.wait_until_succeeds("caget -t SCALC:IN | grep -qxF '10A'") + with subtest("getting initial values"): + assert_caget("UCmd", "0") + assert_caget("URb", "0") + assert_caget("PowerCmd", "ON") + assert_caget("PowerRb", "ON") - def put_check_scalc(_) -> bool: - machine.succeed("caput SCALC:OUT.A 2") - status, _output = machine.execute("caget -t SCALC:IN | grep -qxF '14A'") - return status == 0 - - retry(put_check_scalc) + with subtest("setting values"): + assert_caput("UCmd", "10") + assert_caget("URb", "10") - machine.wait_until_succeeds("caget -t SCALC:OUT.SVAL | grep -qxF 'sent'") + with subtest("calc integration"): + assert_caput("2UCmd.A", "42") + assert_caget("2UCmd.SVAL", "184") + assert_caget("URb", "184") with subtest("regular expressions"): - machine.wait_until_succeeds("caget -t REGEX_TITLE:IN | grep -qxF 'Hello, World!'") - machine.wait_until_succeeds("caget -t REGEX_SUB:IN | grep -qxF 'abcXcXcabc'") + assert_caget("VersionNum", "0.1.0") + assert_caget("VersionCat", "010") ''; passthru = { - inherit mock_server ioc; + inherit ioc; }; } diff --git a/ioc/tests/support/StreamDevice/simple/mock-server/.gitignore b/ioc/tests/support/StreamDevice/simple/mock-server/.gitignore deleted file mode 100644 index 13189553..00000000 --- a/ioc/tests/support/StreamDevice/simple/mock-server/.gitignore +++ /dev/null @@ -1,158 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/python -# Edit at https://www.toptal.com/developers/gitignore?templates=python - -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/ioc/tests/support/StreamDevice/simple/mock-server/mock_server/__init__.py b/ioc/tests/support/StreamDevice/simple/mock-server/mock_server/__init__.py deleted file mode 100644 index 92fb10c6..00000000 --- a/ioc/tests/support/StreamDevice/simple/mock-server/mock_server/__init__.py +++ /dev/null @@ -1,66 +0,0 @@ -"""A simple server mocking an ASCII communication.""" - -import sys - -__version__ = "0.1.0" - - -def log(*args: str, **kwargs: str) -> None: - """Print a message to stderr.""" - print(*args, file=sys.stderr, **kwargs) - - -def send(*args: str, **kwargs: str) -> None: - """Send a message.""" - print(*args, end="\r\n", flush=True, **kwargs) - - -def main() -> None: - """Start the mock server.""" - log("received connection") - - varfloat = 0.0 - scalc = "" - - while True: - data = sys.stdin.readline().strip() - - if not data: - break - - log("received command:", data) - - # TODO(minijackson): change that with a command-line parsing tool? - - if data == "FLOAT": - send("42.1234") - elif data == "FLOAT_WITH_PREFIX": - send("VALUE: 69.1337") - elif data == "ENUM": - send("TWO") - elif data.startswith("SET_VARFLOAT "): - varfloat = float(data.split(" ", maxsplit=1)[1]) - elif data == "GET_VARFLOAT": - send(str(varfloat)) - elif data == "REGEX_TITLE": - send( - """ - -
-Hello, World!
-