From 3ad4e01a5d45d2f35256f649b9e5c79a39f52ab8 Mon Sep 17 00:00:00 2001 From: mazzol_a Date: Thu, 15 May 2025 16:35:09 +0200 Subject: [PATCH] updates api version based on version file & converted shell script files to python --- slsDetectorServers/compileAllServers.sh | 23 +- .../compileAllServers_noAPIUpdate.sh | 19 +- slsDetectorServers/ctbDetectorServer/Makefile | 6 +- slsSupportLib/include/sls/Version.h | 2 +- slsSupportLib/include/sls/versionAPI.h | 6 +- slsSupportLib/src/Version.cpp | 3 +- slsSupportLib/tests/CMakeLists.txt | 1 + slsSupportLib/tests/test-Version.cpp | 19 ++ tests/scripts/test_frame_synchronizer.py | 140 ++++++++++ tests/scripts/utils_for_test.py | 245 ++++++++++++++++++ updateAPIVersion.py | 81 ++++++ updateAPIVersion.sh | 65 ----- updateClientAPIVersion.py | 34 +++ updateClientAPIVersion.sh | 59 ----- 14 files changed, 542 insertions(+), 161 deletions(-) mode change 100644 => 100755 slsDetectorServers/compileAllServers.sh create mode 100644 slsSupportLib/tests/test-Version.cpp create mode 100644 tests/scripts/test_frame_synchronizer.py create mode 100644 tests/scripts/utils_for_test.py create mode 100644 updateAPIVersion.py delete mode 100755 updateAPIVersion.sh create mode 100644 updateClientAPIVersion.py delete mode 100755 updateClientAPIVersion.sh diff --git a/slsDetectorServers/compileAllServers.sh b/slsDetectorServers/compileAllServers.sh old mode 100644 new mode 100755 index 1fe63aba8..a182a502c --- a/slsDetectorServers/compileAllServers.sh +++ b/slsDetectorServers/compileAllServers.sh @@ -1,17 +1,17 @@ # SPDX-License-Identifier: LGPL-3.0-or-other # Copyright (C) 2021 Contributors to the SLS Detector Package -# empty branch = developer branch in updateAPIVersion.sh -branch="" det_list=("ctbDetectorServer gotthard2DetectorServer jungfrauDetectorServer mythen3DetectorServer moenchDetectorServer - xilinx_ctbDetectorServer" + xilinx_ctbDetectorServer" ) -usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'" +usage="\nUsage: compileAllServers.sh [server|all(opt)] [update_api(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tupdate_api if true updates the api to version in VERSION file" +update_api=false +target=clean # arguments if [ $# -eq 0 ]; then # no argument, all servers @@ -34,15 +34,13 @@ elif [ $# -eq 1 ] || [ $# -eq 2 ]; then declare -a det=("${1}") #echo "Compiling only $1" fi - # branch + if [ $# -eq 2 ]; then - # arg in list - if [[ $det_list == *$2* ]]; then - echo -e "Invalid argument 2: $2. $usage" - return 1 + update_api=$2 + if $update_api ; then + target=version + echo "updating api to $(cat ../VERSION)" fi - branch+=$2 - #echo "with branch $branch" fi else echo -e "Too many arguments.$usage" @@ -61,8 +59,7 @@ do file="${i}_developer" echo -e "Compiling $dir [$file]" cd $dir - make clean - if make version API_BRANCH=$branch; then + if make $target; then deterror[$idet]="OK" else deterror[$idet]="FAIL" diff --git a/slsDetectorServers/compileAllServers_noAPIUpdate.sh b/slsDetectorServers/compileAllServers_noAPIUpdate.sh index e20573669..c2aade983 100644 --- a/slsDetectorServers/compileAllServers_noAPIUpdate.sh +++ b/slsDetectorServers/compileAllServers_noAPIUpdate.sh @@ -1,8 +1,6 @@ # SPDX-License-Identifier: LGPL-3.0-or-other # Copyright (C) 2021 Contributors to the SLS Detector Package -# empty branch = developer branch in updateAPIVersion.sh -branch="" det_list=("ctbDetectorServer" "gotthard2DetectorServer" "jungfrauDetectorServer" @@ -10,14 +8,14 @@ det_list=("ctbDetectorServer" "moenchDetectorServer" "xilinx_ctbDetectorServer" ) -usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'" +usage="\nUsage: compileAllServers.sh [server|all(opt)]. \n\tNo arguments mean all servers with 'developer' branch." # arguments if [ $# -eq 0 ]; then # no argument, all servers declare -a det=${det_list[@]} echo "Compiling all servers" -elif [ $# -eq 1 ] || [ $# -eq 2 ]; then +elif [ $# -eq 1 ]; then # 'all' servers if [[ $1 == "all" ]]; then declare -a det=${det_list[@]} @@ -32,16 +30,6 @@ elif [ $# -eq 1 ] || [ $# -eq 2 ]; then declare -a det=("${1}") #echo "Compiling only $1" fi - # branch - if [ $# -eq 2 ]; then - # arg in list - if [[ $det_list == *$2* ]]; then - echo -e "Invalid argument 2: $2. $usage" - return -1 - fi - branch+=$2 - #echo "with branch $branch" - fi else echo -e "Too many arguments.$usage" return -1 @@ -59,8 +47,7 @@ do file="${i}_developer" echo -e "Compiling $dir [$file]" cd $dir - make clean - if make API_BRANCH=$branch; then + if make clean; then deterror[$idet]="OK" else deterror[$idet]="FAIL" diff --git a/slsDetectorServers/ctbDetectorServer/Makefile b/slsDetectorServers/ctbDetectorServer/Makefile index 5bdb5679d..22547fdc5 100755 --- a/slsDetectorServers/ctbDetectorServer/Makefile +++ b/slsDetectorServers/ctbDetectorServer/Makefile @@ -25,15 +25,15 @@ version: clean versioning $(PROGS) boot: $(OBJS) -version_branch=$(API_BRANCH) version_name=APICTB version_path=slsDetectorServers/ctbDetectorServer versioning: - cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` + cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;` $(PROGS): $(OBJS) # echo $(OBJS) + cd $(current_dir) mkdir -p $(DESTDIR) $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) mv $(PROGS) $(DESTDIR) @@ -41,7 +41,7 @@ $(PROGS): $(OBJS) rm $(main_src)*.o $(md5_dir)*.o clean: - rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o + cd $(current_dir) && rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o diff --git a/slsSupportLib/include/sls/Version.h b/slsSupportLib/include/sls/Version.h index 33d10c27e..e4ec31631 100644 --- a/slsSupportLib/include/sls/Version.h +++ b/slsSupportLib/include/sls/Version.h @@ -11,7 +11,7 @@ class Version { private: std::string version_; std::string date_; - const std::string defaultBranch_ = "developer"; + inline static const std::string defaultBranch_[] = {"developer", "0.0.0"}; public: explicit Version(const std::string &s); diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h index b9a1d824d..fb331c3cf 100644 --- a/slsSupportLib/include/sls/versionAPI.h +++ b/slsSupportLib/include/sls/versionAPI.h @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-or-other // Copyright (C) 2021 Contributors to the SLS Detector Package /** API versions */ -#define APILIB "developer 0x241122" -#define APIRECEIVER "developer 0x241122" -#define APICTB "developer 0x250310" +#define APILIB "0.0.0 0x250514" +#define APIRECEIVER "0.0.0 0x250515" +#define APICTB "0.0.0 0x250515" #define APIGOTTHARD2 "developer 0x250310" #define APIMOENCH "developer 0x250310" #define APIEIGER "developer 0x250310" diff --git a/slsSupportLib/src/Version.cpp b/slsSupportLib/src/Version.cpp index 2be4e6c3e..3ace46217 100644 --- a/slsSupportLib/src/Version.cpp +++ b/slsSupportLib/src/Version.cpp @@ -21,7 +21,8 @@ Version::Version(const std::string &s) { } bool Version::hasSemanticVersioning() const { - return version_ != defaultBranch_; + + return (version_ != defaultBranch_[0]) && (version_ != defaultBranch_[1]); } std::string Version::getVersion() const { return version_; } diff --git a/slsSupportLib/tests/CMakeLists.txt b/slsSupportLib/tests/CMakeLists.txt index 4fae7a346..827db97ff 100755 --- a/slsSupportLib/tests/CMakeLists.txt +++ b/slsSupportLib/tests/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-Version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-ZmqSocket.cpp ) diff --git a/slsSupportLib/tests/test-Version.cpp b/slsSupportLib/tests/test-Version.cpp new file mode 100644 index 000000000..9c1f1d3f8 --- /dev/null +++ b/slsSupportLib/tests/test-Version.cpp @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-3.0-or-other +// Copyright (C) 2021 Contributors to the SLS Detector Package +#include "catch.hpp" +#include "sls/Version.h" + +namespace sls { + +TEST_CASE("check if version is semantic", "[.version]") { + + auto [version_string, has_semantic_version] = + GENERATE(std::make_tuple("developer 0x250512", false), + std::make_tuple("0.0.0 0x250512", false)); + + Version version(version_string); + + CHECK(version.hasSemanticVersioning() == has_semantic_version); +} + +} // namespace sls diff --git a/tests/scripts/test_frame_synchronizer.py b/tests/scripts/test_frame_synchronizer.py new file mode 100644 index 000000000..514044f1a --- /dev/null +++ b/tests/scripts/test_frame_synchronizer.py @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: LGPL-3.0-or-other +# Copyright (C) 2021 Contributors to the SLS Detector Package +''' +This file is used to start up simulators, frame synchronizer, pull sockets, acquire, test and kill them finally. +''' + +import sys, time +import traceback, json + +from slsdet import Detector +from slsdet.defines import DEFAULT_TCP_RX_PORTNO + +from utils_for_test import ( + Log, + LogLevel, + RuntimeException, + checkIfProcessRunning, + killProcess, + cleanup, + cleanSharedmemory, + startProcessInBackground, + startProcessInBackgroundWithLogFile, + startDetectorVirtualServer, + loadConfig, + ParseArguments +) + +LOG_PREFIX_FNAME = '/tmp/slsFrameSynchronizer_test' +MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt' +PULL_SOCKET_PREFIX_FNAME = LOG_PREFIX_FNAME + '_pull_socket_' + + +def startFrameSynchronizerPullSocket(name, fp): + fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt' + cmd = ['python', '-u', 'frameSynchronizerPullSocket.py'] + startProcessInBackgroundWithLogFile(cmd, fp, fname) + + +def startFrameSynchronizer(num_mods, fp): + cmd = ['slsFrameSynchronizer', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)] + # in 10.0.0 + #cmd = ['slsFrameSynchronizer', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)] + startProcessInBackground(cmd, fp) + time.sleep(1) + + +def acquire(fp, det): + Log(LogLevel.INFO, 'Acquiring') + Log(LogLevel.INFO, 'Acquiring', fp) + det.acquire() + + +def testFramesCaught(name, det, num_frames): + fnum = det.rx_framescaught[0] + if fnum != num_frames: + raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}") + + Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}') + Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp) + + +def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp): + + Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}") + Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp) + htype_counts = { + "header": 0, + "series_end": 0, + "module": 0 + } + + try: + # get a count of each htype from file + pull_socket_fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt' + with open(pull_socket_fname, 'r') as log_fp: + for line in log_fp: + line = line.strip() + if not line or not line.startswith('{'): + continue + try: + data = json.loads(line) + htype = data.get("htype") + if htype in htype_counts: + htype_counts[htype] += 1 + except json.JSONDecodeError: + continue + + # test if file contents matches expected counts + num_ports_per_module = 1 if name == "gotthard2" else det.numinterfaces + total_num_frame_parts = num_ports_per_module * num_mods * num_frames + for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]: + if htype_counts[htype] != expected_count: + msg = f"Expected {expected_count} '{htype}' entries, found {htype_counts[htype]}" + raise RuntimeException(msg) + except Exception as e: + raise RuntimeException(f'Failed to get zmq header count type. Error:{str(e)}') from e + + Log(LogLevel.INFOGREEN, f"Zmq Header type count test passed for {name}") + Log(LogLevel.INFOGREEN, f"Zmq Header type count test passed for {name}", fp) + + +def startTestsForAll(args, fp): + for server in args.servers: + try: + Log(LogLevel.INFOBLUE, f'Synchronizer Tests for {server}') + Log(LogLevel.INFOBLUE, f'Synchronizer Tests for {server}', fp) + cleanup(fp) + startDetectorVirtualServer(server, args.num_mods, fp) + startFrameSynchronizerPullSocket(server, fp) + startFrameSynchronizer(args.num_mods, fp) + d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames) + print("mac source adress: ", d.udp_srcmac) + print("source ip: ", d.udp_srcip) + print("detector type: ", d.type) + acquire(fp, d) + testFramesCaught(server, d, args.num_frames) + testZmqHeadetTypeCount(server, d, args.num_mods, args.num_frames, fp) + Log(LogLevel.INFO, '\n') + except Exception as e: + raise RuntimeException(f'Synchronizer Tests failed') from e + + Log(LogLevel.INFOGREEN, 'Passed all synchronizer tests for all detectors \n' + str(args.servers)) + + +if __name__ == '__main__': + args = ParseArguments(description='Automated tests to test frame synchronizer', default_num_mods=2) + + Log(LogLevel.INFOBLUE, '\nLog File: ' + MAIN_LOG_FNAME + '\n') + + with open(MAIN_LOG_FNAME, 'w') as fp: + try: + startTestsForAll(args, fp) + cleanup(fp) + except Exception as e: + with open(MAIN_LOG_FNAME, 'a') as fp_error: + traceback.print_exc(file=fp_error) + cleanup(fp) + Log(LogLevel.ERROR, f'Tests Failed.') + + diff --git a/tests/scripts/utils_for_test.py b/tests/scripts/utils_for_test.py new file mode 100644 index 000000000..f6fc88d55 --- /dev/null +++ b/tests/scripts/utils_for_test.py @@ -0,0 +1,245 @@ +# SPDX-License-Identifier: LGPL-3.0-or-other +# Copyright (C) 2021 Contributors to the SLS Detector Package +''' +This file is used for common utils used for integration tests between simulators and receivers. +''' + +import sys, subprocess, time, argparse +from enum import Enum +from colorama import Fore, Style, init + +from slsdet import Detector, detectorSettings +from slsdet.defines import DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO +SERVER_START_PORTNO=1900 + +init(autoreset=True) + + +class LogLevel(Enum): + INFO = 0 + INFORED = 1 + INFOGREEN = 2 + INFOBLUE = 3 + WARNING = 4 + ERROR = 5 + DEBUG = 6 + + +LOG_LABELS = { + LogLevel.WARNING: "WARNING: ", + LogLevel.ERROR: "ERROR: ", + LogLevel.DEBUG: "DEBUG: " +} + + +LOG_COLORS = { + LogLevel.INFO: Fore.WHITE, + LogLevel.INFORED: Fore.RED, + LogLevel.INFOGREEN: Fore.GREEN, + LogLevel.INFOBLUE: Fore.BLUE, + LogLevel.WARNING: Fore.YELLOW, + LogLevel.ERROR: Fore.RED, + LogLevel.DEBUG: Fore.CYAN +} + + +def Log(level: LogLevel, message: str, stream=sys.stdout): + color = LOG_COLORS.get(level, Fore.WHITE) + label = LOG_LABELS.get(level, "") + print(f"{color}{label}{message}{Style.RESET_ALL}", file=stream, flush=True) + + +class RuntimeException (Exception): + def __init__ (self, message): + Log(LogLevel.ERROR, message) + super().__init__(message) + + +def checkIfProcessRunning(processName): + cmd = f"pgrep -f {processName}" + res = subprocess.getoutput(cmd) + return res.strip().splitlines() + + +def killProcess(name, fp): + pids = checkIfProcessRunning(name) + if pids: + Log(LogLevel.INFO, f"Killing '{name}' processes with PIDs: {', '.join(pids)}", fp) + for pid in pids: + try: + p = subprocess.run(['kill', pid]) + if p.returncode != 0 and bool(checkIfProcessRunning(name)): + raise RuntimeException(f"Could not kill {name} with pid {pid}") + except Exception as e: + raise RuntimeException(f"Failed to kill process {name} pid:{pid}. Error: {str(e)}") from e + #else: + # Log(LogLevel.INFO, 'process not running : ' + name) + + +def cleanSharedmemory(fp): + Log(LogLevel.INFO, 'Cleaning up shared memory', fp) + try: + p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp) + except: + raise RuntimeException('Could not free shared memory') + + +def cleanup(fp): + Log(LogLevel.INFO, 'Cleaning up') + Log(LogLevel.INFO, 'Cleaning up', fp) + killProcess('DetectorServer_virtual', fp) + killProcess('slsReceiver', fp) + killProcess('slsMultiReceiver', fp) + killProcess('slsFrameSynchronizer', fp) + killProcess('frameSynchronizerPullSocket', fp) + cleanSharedmemory(fp) + + +def startProcessInBackground(cmd, fp): + Log(LogLevel.INFO, 'Starting up ' + ' '.join(cmd)) + Log(LogLevel.INFO, 'Starting up ' + ' '.join(cmd), fp) + try: + p = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False) + except Exception as e: + raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e + + +def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name): + Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name) + Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp) + try: + with open(log_file_name, 'w') as log_fp: + subprocess.Popen(cmd, stdout=log_fp, stderr=log_fp, text=True) + except Exception as e: + raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e + + +def runProcessWithLogFile(name, cmd, fp, log_file_name): + Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name) + Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp) + Log(LogLevel.INFOBLUE, 'Cmd: ' + ' '.join(cmd), fp) + try: + with open(log_file_name, 'w') as log_fp: + subprocess.run(cmd, stdout=log_fp, stderr=log_fp, check=True, text=True) + except subprocess.CalledProcessError as e: + pass + except Exception as e: + Log(LogLevel.ERROR, f'Failed to run {name}:{str(e)}', fp) + raise RuntimeException(f'Failed to run {name}:{str(e)}') + + with open (log_file_name, 'r') as f: + for line in f: + if "FAILED" in line: + raise RuntimeException(f'{line}') + + Log(LogLevel.INFOGREEN, name + ' successful!\n') + Log(LogLevel.INFOGREEN, name + ' successful!\n', fp) + + +def startDetectorVirtualServer(name :str, num_mods, fp): + for i in range(num_mods): + subprocess.run(["which", name + "DetectorServer_virtual"]) + + port_no = SERVER_START_PORTNO + (i * 2) + cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)] + startProcessInBackgroundWithLogFile(cmd, fp, "/tmp/virtual_det_" + name + str(i) + ".txt") + match name: + case 'jungfrau': + time.sleep(7) + case 'gotthard2': + time.sleep(5) + case _: + time.sleep(3) + + +def connectToVirtualServers(name, num_mods): + try: + d = Detector() + except Exception as e: + raise RuntimeException(f'Could not create Detector object for {name}. Error: {str(e)}') from e + + counts_sec = 100 + while (counts_sec != 0): + try: + d.virtual = [num_mods, SERVER_START_PORTNO] + break + except Exception as e: + # stop server still not up, wait a bit longer + if "Cannot connect to" in str(e): + Log(LogLevel.WARNING, f'Still waiting for {name} virtual server to be up...{counts_sec}s left') + time.sleep(1) + counts_sec -= 1 + else: + raise + + return d + + +def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1): + Log(LogLevel.INFO, 'Loading config') + Log(LogLevel.INFO, 'Loading config', fp) + try: + d = connectToVirtualServers(name, num_mods) + d.udp_dstport = DEFAULT_UDP_DST_PORTNO + if name == 'eiger': + d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1 + + d.rx_hostname = rx_hostname + d.udp_dstip = 'auto' + if name != "eiger": + d.udp_srcip = 'auto' + + if name == "jungfrau" or name == "moench" or name == "xilinx_ctb": + d.powerchip = 1 + + if name == "xilinx_ctb": + d.configureTransceiver() + + if name == "eiger": + d.trimen = [4500, 5400, 6400] + d.settingspath = settingsdir + '/eiger/' + d.setThresholdEnergy(4500, detectorSettings.STANDARD) + + d.frames = num_frames + except Exception as e: + raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e + + return d + + +def ParseArguments(description, default_num_mods=1): + parser = argparse.ArgumentParser(description) + + parser.add_argument('rx_hostname', nargs='?', default='localhost', + help='Hostname/IP of the current machine') + parser.add_argument('settingspath', nargs='?', default='../../settingsdir', + help='Relative or absolute path to the settings directory') + parser.add_argument('-n', '--num-mods', nargs='?', default=default_num_mods, type=int, + help='Number of modules to test with') + parser.add_argument('-f', '--num-frames', nargs='?', default=1, type=int, + help='Number of frames to test with') + parser.add_argument('-s', '--servers', nargs='*', + help='Detector servers to run') + + args = parser.parse_args() + + # Set default server list if not provided + if args.servers is None: + args.servers = [ + 'eiger', + 'jungfrau', + 'mythen3', + 'gotthard2', + 'ctb', + 'moench', + 'xilinx_ctb' + ] + + Log(LogLevel.INFO, 'Arguments:\n' + + 'rx_hostname: ' + args.rx_hostname + + '\nsettingspath: \'' + args.settingspath + + '\nservers: \'' + ' '.join(args.servers) + + '\nnum_mods: \'' + str(args.num_mods) + + '\nnum_frames: \'' + str(args.num_frames) + '\'') + + return args diff --git a/updateAPIVersion.py b/updateAPIVersion.py new file mode 100644 index 000000000..934df081d --- /dev/null +++ b/updateAPIVersion.py @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: LGPL-3.0-or-other +# Copyright (C) 2025 Contributors to the SLS Detector Package +""" +Script to update API VERSION file based on the version in VERSION file. +""" + +import argparse +import sys +import os +import re +import time +from datetime import datetime + + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +API_FILE = SCRIPT_DIR + "/slsSupportLib/include/sls/versionAPI.h" + +VERSION_FILE = SCRIPT_DIR + "/VERSION" + +parser = argparse.ArgumentParser(description = 'updates API version') +parser.add_argument('api_module_name', choices=["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"], help = 'module name to change api version options are: ["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"]') +parser.add_argument('api_dir', help = 'Relative or absolut path to the module code') + +def update_api_file(new_api : str, api_module_name : str, api_file_name : str): + + regex_pattern = re.compile(rf'#define\s+{api_module_name}\s+') + with open(api_file_name, "r") as api_file: + lines = api_file.readlines() + + with open(api_file_name, "w") as api_file: + for line in lines: + if regex_pattern.match(line): + api_file.write(f'#define {api_module_name} "{new_api}"\n') + else: + api_file.write(line) + +def get_latest_modification_date(directory : str): + latest_time = 0 + latest_date = None + + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(".o"): + continue + full_path = os.path.join(root, file) + try: + mtime = os.path.getmtime(full_path) + if mtime > latest_time: + latest_time = mtime + except FileNotFoundError: + continue + + latest_date = datetime.fromtimestamp(latest_time).strftime("%y%m%d") + + return latest_date + + +def update_api_version(api_module_name : str, api_dir : str): + api_date = get_latest_modification_date(api_dir) + api_date = "0x"+str(api_date) + + with open(VERSION_FILE, "r") as version_file: + api_version = version_file.read().strip() + + api_version = api_version + " " + api_date #not sure if we should give an argument option version_branch + + update_api_file(api_version, api_module_name, API_FILE) + + print(f"updated {api_module_name} api version to: {api_version}") + +if __name__ == "__main__": + + args = parser.parse_args() + + api_dir = SCRIPT_DIR + "/" + args.api_dir + + + update_api_version(args.api_module_name, api_dir) + + diff --git a/updateAPIVersion.sh b/updateAPIVersion.sh deleted file mode 100755 index 8c45e0c48..000000000 --- a/updateAPIVersion.sh +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-other -# Copyright (C) 2021 Contributors to the SLS Detector Package -usage="\nUsage: updateAPIVersion.sh [API_NAME] [API_DIR] [API_BRANCH(opt)]." - -if [ $# -lt 2 ]; then - echo -e "Requires atleast 2 arguments. $usage" - return [-1] -fi - -API_NAME=$1 -PACKAGE_DIR=$PWD -API_DIR=$PACKAGE_DIR/$2 -API_FILE=$PACKAGE_DIR/slsSupportLib/include/sls/versionAPI.h -CURR_DIR=$PWD - -if [ ! -d "$API_DIR" ]; then - echo "[API_DIR] does not exist. $usage" - return [-1] -fi - -#go to directory -cd $API_DIR - -#deleting line from file -NUM=$(sed -n '/'$API_NAME' /=' $API_FILE) -#echo $NUM - - -if [ "$NUM" -gt 0 ]; then - sed -i ${NUM}d $API_FILE -fi - -#find new API date -API_DATE="find . -printf \"%T@ %CY-%Cm-%Cd\n\"| sort -nr | cut -d' ' -f2- | egrep -v '(\.)o' | head -n 1" - -API_DATE=`eval $API_DATE` - -API_DATE=$(sed "s/-//g" <<< $API_DATE | awk '{print $1;}' ) - -#extracting only date -API_DATE=${API_DATE:2:6} - -#prefix of 0x -API_DATE=${API_DATE/#/0x} -echo "date="$API_DATE - - -# API_VAL concatenates branch and date -API_VAL="" -# API branch is defined (3rd argument) -if [ $# -eq 3 ]; then - API_BRANCH=$3 - echo "branch="$API_BRANCH - API_VAL+="\"$API_BRANCH $API_DATE\"" -else - # API branch not defined (default is developer) - echo "branch=developer" - API_VAL+="\"developer $API_DATE\"" -fi - -#copy it to versionAPI.h -echo "#define "$API_NAME $API_VAL >> $API_FILE - -#go back to original directory -cd $CURR_DIR diff --git a/updateClientAPIVersion.py b/updateClientAPIVersion.py new file mode 100644 index 000000000..d7764cff9 --- /dev/null +++ b/updateClientAPIVersion.py @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LGPL-3.0-or-other +# Copyright (C) 2025 Contributors to the SLS Detector Package +""" +Script to update API VERSION for slsReceiverSoftware or slsDetectorSoftware +""" + +import argparse +import os + +from updateAPIVersion import update_api_version + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +parser = argparse.ArgumentParser(description = 'updates API version') +parser.add_argument('module_name', nargs="?", choices=["slsDetectorSoftware", "slsReceiverSoftware", "all"], default="all", help = 'module name to change api version options are: ["slsDetectorSoftware", "slsReceiverSoftware, "all"]') + +if __name__ == "__main__": + args = parser.parse_args() + + if args.module_name == "all": + client_names = ["APILIB", "APIRECEIVER"] + client_directories = [SCRIPT_DIR+"/slsDetectorSoftware", SCRIPT_DIR+"/slsReceiverSoftware"] + elif args.module_name == "slsDetectorSoftware": + client_names = ["APILIB"] + client_directories = [SCRIPT_DIR+"/slsDetectorSoftware"] + else: + client_names = ["APIRECEIVER"] + client_directories = [SCRIPT_DIR+"/slsReceiverSoftware"] + + for client_name, client_directory in zip(client_names, client_directories): + update_api_version(client_name, client_directory) + + + diff --git a/updateClientAPIVersion.sh b/updateClientAPIVersion.sh deleted file mode 100755 index bed281622..000000000 --- a/updateClientAPIVersion.sh +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-other -# Copyright (C) 2021 Contributors to the SLS Detector Package -branch="" -client_list=("slsDetectorSoftware" "slsReceiverSoftware") -usage="\nUsage: updateClientAPI.sh [all|slsDetectorSoftware|slsReceiverSoftware] [branch]. \n\tNo arguments means all with 'developer' branch. \n\tNo 'branch' input means 'developer branch'" - -# arguments -if [ $# -eq 0 ]; then - declare -a client=${client_list[@]} - echo "API Versioning all" -elif [ $# -eq 1 ] || [ $# -eq 2 ]; then - # 'all' client - if [[ $1 == "all" ]]; then - declare -a client=${client_list[@]} - echo "API Versioning all" - else - # only one server - if [[ $client_list != *$1* ]]; then - echo -e "Invalid argument 1: $1. $usage" - return -1 - fi - declare -a client=("${1}") - #echo "Versioning only $1" - fi - if [ $# -eq 2 ]; then - if [[ $client_list == *$2* ]]; then - echo -e "Invalid argument 2: $2. $usage" - return -1 - fi - branch+=$2 - #echo "with branch $branch" - fi -else - echo -e "Too many arguments.$usage" - return -1 -fi - -#echo "list is: ${client[@]}" - -# versioning each client -for i in ${client[@]} -do - dir=$i - case $dir in - slsDetectorSoftware) - declare -a name=APILIB - ;; - slsReceiverSoftware) - declare -a name=APIRECEIVER - ;; - *) - echo -n "unknown client argument $i" - return -1 - ;; - esac - echo -e "Versioning $dir [$name]" - ./updateAPIVersion.sh $name $dir $branch -done -