diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 1bd44d267..36c0c35a7 100755 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -64,6 +64,10 @@ configure_file( scripts/test_virtual.py ${CMAKE_BINARY_DIR}/test_virtual.py ) +configure_file(scripts/frameSynchronizerPullSocket.py + ${CMAKE_BINARY_DIR}/frameSynchronizerPullSocket.py COPYONLY) + + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION ${CMAKE_BINARY_DIR}/bin/slsdet/VERSION ) @@ -76,4 +80,5 @@ if(SLS_INSTALL_PYTHONEXT) install(FILES ${PYTHON_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet) install(FILES ../VERSION DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet) -endif() \ No newline at end of file +endif() + diff --git a/slsDetectorSoftware/tests/Caller/test-Caller-rx.cpp b/slsDetectorSoftware/tests/Caller/test-Caller-rx.cpp index 38fe14e86..66cc474d6 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller-rx.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller-rx.cpp @@ -445,23 +445,25 @@ TEST_CASE("rx_arping", "[.cmdcall][.rx]") { Detector det; Caller caller(&det); auto prev_val = det.getRxArping(); - { - std::ostringstream oss; - caller.call("rx_arping", {"1"}, -1, PUT, oss); - REQUIRE(oss.str() == "rx_arping 1\n"); - } - { - std::ostringstream oss; - caller.call("rx_arping", {}, -1, GET, oss); - REQUIRE(oss.str() == "rx_arping 1\n"); - } - { - std::ostringstream oss; - caller.call("rx_arping", {"0"}, -1, PUT, oss); - REQUIRE(oss.str() == "rx_arping 0\n"); - } - for (int i = 0; i != det.size(); ++i) { - det.setRxArping(prev_val[i], {i}); + if (det.getDestinationUDPIP()[0].str() != "127.0.0.1") { + { + std::ostringstream oss; + caller.call("rx_arping", {"1"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_arping 1\n"); + } + { + std::ostringstream oss; + caller.call("rx_arping", {}, -1, GET, oss); + REQUIRE(oss.str() == "rx_arping 1\n"); + } + { + std::ostringstream oss; + caller.call("rx_arping", {"0"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_arping 0\n"); + } + for (int i = 0; i != det.size(); ++i) { + det.setRxArping(prev_val[i], {i}); + } } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f222cc599..7f717667d 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -60,3 +60,4 @@ include(Catch) catch_discover_tests(tests) configure_file(scripts/test_simulators.py ${CMAKE_BINARY_DIR}/bin/test_simulators.py COPYONLY) +configure_file(scripts/test_frame_synchronizer.py ${CMAKE_BINARY_DIR}/bin/test_frame_synchronizer.py COPYONLY) diff --git a/tests/scripts/test_frame_synchronizer.py b/tests/scripts/test_frame_synchronizer.py new file mode 100644 index 000000000..ab7febe4a --- /dev/null +++ b/tests/scripts/test_frame_synchronizer.py @@ -0,0 +1,223 @@ +# 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, receivers and run all the tests on them and finally kill the simulators and receivers. +''' +import argparse +import os, sys, subprocess, time, colorama +import shlex + +from colorama import Fore, Style +from slsdet import Detector, detectorType, detectorSettings +from slsdet.defines import DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO +SERVER_START_PORTNO=1900 + + +colorama.init(autoreset=True) + +def Log(color, message): + print(f"{color}{message}{Style.RESET_ALL}", flush=True) + +class RuntimeException (Exception): + def __init__ (self, message): + super().__init__(Log(Fore.RED, message)) + +def checkIfProcessRunning(processName): + cmd = f"pgrep -f {processName}" + res = subprocess.getoutput(cmd) + return res.strip().splitlines() + + +def killProcess(name): + pids = checkIfProcessRunning(name) + if pids: + Log(Fore.GREEN, f"Killing '{name}' processes with PIDs: {', '.join(pids)}") + 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: + Log(Fore.RED, f"Failed to kill process {name} pid:{pid}. Exception occured: [code:{e}, msg:{e.stderr}]") + raise + #else: + # Log(Fore.WHITE, 'process not running : ' + name) + + +def cleanup(fp): + ''' + kill both servers, receivers and clean shared memory + ''' + Log(Fore.GREEN, 'Cleaning up...') + killProcess('DetectorServer_virtual') + killProcess('slsReceiver') + killProcess('slsMultiReceiver') + killProcess('slsFrameSynchronizer') + killProcess('frameSynchronizerPullSocket') + cleanSharedmemory(fp) + +def cleanSharedmemory(fp): + Log(Fore.GREEN, 'Cleaning up shared memory...') + try: + p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp) + except: + Log(Fore.RED, 'Could not free shared memory') + raise + +def startProcessInBackground(name): + try: + # in background and dont print output + p = subprocess.Popen(shlex.split(name), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False) + Log(Fore.GREEN, 'Starting up ' + name + ' ...') + except Exception as e: + Log(Fore.RED, f'Could not start {name}:{e}') + raise + +def startServers(name, num_mods): + for i in range(num_mods): + port_no = SERVER_START_PORTNO + (i * 2) + startProcessInBackground(name + 'DetectorServer_virtual -p' + str(port_no)) + time.sleep(6) + +def startFrameSynchronizerPullSocket(): + startProcessInBackground('python frameSynchronizerPullSocket.py') + tStartup = 4 + Log(Fore.WHITE, 'Takes ' + str(tStartup) + ' seconds... Please be patient') + time.sleep(tStartup) + if not checkIfProcessRunning('frameSynchonizerPull'): + Log(Fore.RED, "Could not start pull socket. Its not running.") + raise + +def startFrameSynchronizer(num_mods): + Log(Fore.GREEN, "Going to start frame synchonizer") + # in 10.0.0 + #startProcessInBackground('slsFrameSynchronizer -n ' + str(num_mods) + ' -p ' + str(DEFAULT_TCP_RX_PORTNO)) + startProcessInBackground('slsFrameSynchronizer ' + str(DEFAULT_TCP_RX_PORTNO) + ' ' + str(num_mods)) + tStartup = 1 * num_mods + Log(Fore.WHITE, 'Takes ' + str(tStartup) + ' seconds... Please be patient') + time.sleep(tStartup) + +def loadConfig(name, num_mods, rx_hostname, settingsdir, num_frames): + Log(Fore.GREEN, 'Loading config') + try: + d = Detector() + d.virtual = [num_mods, SERVER_START_PORTNO] + 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' + d.udp_srcip = 'auto' + + if name == 'eiger': + d.trimen = [4500, 5400, 6400] + d.settingspath = settingsdir + '/eiger/' + d.setThresholdEnergy(4500, detectorSettings.STANDARD) + elif d.type == detectorType.JUNGFRAU or d.type == detectorType.MOENCH or d.type == detectorType.XILINX_CHIPTESTBOARD: + d.powerchip = 1 + + if d.type == detectorType.XILINX_CHIPTESTBOARD: + d.configureTransceiver() + + d.frames = num_frames + except Exception as e: + Log(Fore.RED, f'Could not load config for {name}. Error: {str(e)}') + raise + +def startTests(name, fp, fname, num_frames): + Log(Fore.GREEN, 'Tests for ' + name) + cmd = 'tests --abort [.cmdcall] -s -o ' + fname + + d = Detector() + d.acquire() + fnum = d.rx_framescaught[0] + if fnum == num_frames: + Log(Fore.RED, "{name} caught only {fnum}. Expected {num_frames}") + raise + + Log(Fore.GREEN, 'Tests successful for ' + name) + + +# parse cmd line for rx_hostname and settingspath using the argparse library +parser = argparse.ArgumentParser(description = 'automated tests with the virtual detector servers') +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 absolut path to the settingspath') +parser.add_argument('-n', '--num-mods', nargs='?', default=2, 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() + +if args.servers is None: + servers = [ + #'eiger', + 'jungfrau', + #'mythen3', + #'gotthard2', + #'ctb', + #'moench', + #'xilinx_ctb' + ] +else: + servers = args.servers + + +Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\nservers: \'' + ' '.join(servers) + '\nnum_mods: \'' + str(args.num_mods) + '\nnum_frames: \'' + str(args.num_frames) + '\'') + + +# redirect to file +prefix_fname = '/tmp/slsFrameSynchronizer_test' +original_stdout = sys.stdout +original_stderr = sys.stderr +fname = prefix_fname + '_log.txt' +Log(Fore.BLUE, '\nLog File: ' + fname) + +with open(fname, 'w') as fp: + + try: + cleanup(fp) + + testError = False + for server in servers: + try: + # print to terminal for progress + sys.stdout = original_stdout + sys.stderr = original_stderr + file_results = prefix_fname + '_results_cmd_' + server + '.txt' + Log(Fore.BLUE, 'Synchonizer tests for ' + server + ' (results: ' + file_results + ')') + sys.stdout = fp + sys.stderr = fp + Log(Fore.BLUE, 'Synchonizer tests for ' + server + ' (results: ' + file_results + ')') + + # cmd tests for det + cleanup(fp) + startServers(server, args.num_mods) + startFrameSynchronizerPullSocket() + startFrameSynchronizer(args.num_mods) + loadConfig(server, args.num_mods, args.rx_hostname, args.settingspath, args.num_frames) + startTests(server, fp, file_results, args.num_frames) + cleanup(fp) + + except Exception as e: + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + Log(Fore.RED, f'Exception caught while testing {server}. Cleaning up...') + testError = True + break + + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + if not testError: + Log(Fore.GREEN, 'Passed all sync tests\n' + str(servers)) + + + except Exception as e: + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + Log(Fore.RED, f'Exception caught with general testing. Cleaning up...') + cleanSharedmemory(sys.stdout) + \ No newline at end of file diff --git a/tests/scripts/test_simulators.py b/tests/scripts/test_simulators.py index 34f7ca9ba..7715ede32 100644 --- a/tests/scripts/test_simulators.py +++ b/tests/scripts/test_simulators.py @@ -4,9 +4,9 @@ This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers. ''' import argparse -import os, sys, subprocess, time, colorama, signal +import os, sys, subprocess, time, colorama -from colorama import Fore +from colorama import Fore, Style from slsdet import Detector, detectorType, detectorSettings from slsdet.defines import DEFAULT_TCP_CNTRL_PORTNO, DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO HALFMOD2_TCP_CNTRL_PORTNO=1955 @@ -14,68 +14,46 @@ HALFMOD2_TCP_RX_PORTNO=1957 colorama.init(autoreset=True) +def Log(color, message): + print(f"{color}{message}{Style.RESET_ALL}", flush=True) + class RuntimeException (Exception): def __init__ (self, message): - super().__init__(Fore.RED + message) + super().__init__(Log(Fore.RED, message)) -def Log(color, message): - print('\n' + color + message, flush=True) - - def checkIfProcessRunning(processName): - cmd = "ps -ef | grep " + processName - print(cmd) - res=subprocess.getoutput(cmd) - print(res) - # eg. of output - #l_user 250506 243295 0 14:38 pts/5 00:00:00 /bin/sh -c ps -ef | grep slsReceiver - #l_user 250508 250506 0 14:38 pts/5 00:00:00 grep slsReceiver - - print('how many') - cmd = "ps -ef | grep " + processName + " | wc -l" - print(cmd) - res=subprocess.getoutput(cmd) - print(res) - - if res == '2': - return False - return True + cmd = f"pgrep -f {processName}" + res = subprocess.getoutput(cmd) + return res.strip().splitlines() def killProcess(name): - if checkIfProcessRunning(name): - Log(Fore.GREEN, 'killing ' + name) - p = subprocess.run(['killall', name]) - if p.returncode != 0: - raise RuntimeException('killall failed for ' + name) - else: - print('process not running : ' + name) + pids = checkIfProcessRunning(name) + if pids: + Log(Fore.GREEN, f"Killing '{name}' processes with PIDs: {', '.join(pids)}") + 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: + Log(Fore.RED, f"Failed to kill process {name} pid:{pid}. Exception occured: [code:{e}, msg:{e.stderr}]") + raise + #else: + # Log(Fore.WHITE, 'process not running : ' + name) -def killAllStaleProcesses(): - killProcess('eigerDetectorServer_virtual') - killProcess('jungfrauDetectorServer_virtual') - killProcess('mythen3DetectorServer_virtual') - killProcess('gotthard2DetectorServer_virtual') - killProcess('gotthardDetectorServer_virtual') - killProcess('ctbDetectorServer_virtual') - killProcess('moenchDetectorServer_virtual') - killProcess('xilinx_ctbDetectorServer_virtual') - killProcess('slsReceiver') - killProcess('slsMultiReceiver') - cleanSharedmemory() - -def cleanup(name): +def cleanup(fp): ''' kill both servers, receivers and clean shared memory ''' Log(Fore.GREEN, 'Cleaning up...') - killProcess(name + 'DetectorServer_virtual') + killProcess('DetectorServer_virtual') killProcess('slsReceiver') killProcess('slsMultiReceiver') - cleanSharedmemory() + cleanSharedmemory(fp) -def cleanSharedmemory(): +def cleanSharedmemory(fp): Log(Fore.GREEN, 'Cleaning up shared memory...') try: p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp) @@ -88,8 +66,8 @@ def startProcessInBackground(name): # in background and dont print output p = subprocess.Popen(name.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False) Log(Fore.GREEN, 'Starting up ' + name + ' ...') - except: - Log(Fore.RED, 'Could not start ' + name) + except Exception as e: + Log(Fore.RED, f'Could not start {name}:{e}') raise def startServer(name): @@ -128,6 +106,7 @@ def loadConfig(name, rx_hostname, settingsdir): d.hostname = 'localhost' d.rx_hostname = rx_hostname d.udp_dstip = 'auto' + d.udp_dstip = 'auto' if d.type == detectorType.GOTTHARD: d.udp_srcip = d.udp_dstip else: @@ -143,14 +122,19 @@ def loadConfig(name, rx_hostname, settingsdir): def startCmdTests(name, fp, fname): Log(Fore.GREEN, 'Cmd Tests for ' + name) cmd = 'tests --abort [.cmdcall] -s -o ' + fname - p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True) - p.check_returncode() + try: + subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True) + except subprocess.CalledProcessError as e: + pass with open (fname, 'r') as f: for line in f: if "FAILED" in line: msg = 'Cmd tests failed for ' + name + '!!!' + sys.stdout = original_stdout Log(Fore.RED, msg) + Log(Fore.RED, line) + sys.stdout = fp raise Exception(msg) Log(Fore.GREEN, 'Cmd Tests successful for ' + name) @@ -158,14 +142,18 @@ def startCmdTests(name, fp, fname): def startGeneralTests(fp, fname): Log(Fore.GREEN, 'General Tests') cmd = 'tests --abort -s -o ' + fname - p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True) - p.check_returncode() + try: + subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True) + except subprocess.CalledProcessError as e: + pass with open (fname, 'r') as f: for line in f: if "FAILED" in line: msg = 'General tests failed !!!' - Log(Fore.RED, msg) + sys.stdout = original_stdout + Log(Fore.RED, msg + '\n' + line) + sys.stdout = fp raise Exception(msg) Log(Fore.GREEN, 'General Tests successful') @@ -174,12 +162,10 @@ def startGeneralTests(fp, fname): # parse cmd line for rx_hostname and settingspath using the argparse library parser = argparse.ArgumentParser(description = 'automated tests with the virtual detector servers') -parser.add_argument('rx_hostname', help = 'hostname/ip of the current machine') -parser.add_argument('settingspath', help = 'Relative or absolut path to the settingspath') +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 absolut path to the settingspath') parser.add_argument('-s', '--servers', help='Detector servers to run', nargs='*') args = parser.parse_args() -if args.rx_hostname == 'localhost': - raise RuntimeException('Cannot use localhost for rx_hostname for the tests (fails for rx_arping for eg.)') if args.servers is None: servers = [ @@ -196,7 +182,7 @@ else: servers = args.servers -Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\'') +Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\nservers: \'' + ' '.join(servers) + '\'') # redirect to file @@ -208,46 +194,58 @@ Log(Fore.BLUE, '\nLog File: ' + fname) with open(fname, 'w') as fp: + + # general tests file_results = prefix_fname + '_results_general.txt' Log(Fore.BLUE, 'General tests (results: ' + file_results + ')') sys.stdout = fp sys.stderr = fp Log(Fore.BLUE, 'General tests (results: ' + file_results + ')') - startGeneralTests(fp, file_results) - killAllStaleProcesses() + try: + startGeneralTests(fp, file_results) + cleanup(fp) - for server in servers: - try: - # print to terminal for progress - sys.stdout = original_stdout - sys.stderr = original_stderr - file_results = prefix_fname + '_results_cmd_' + server + '.txt' - Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')') - sys.stdout = fp - sys.stderr = fp - Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')') - - # cmd tests for det - cleanup(server) - startServer(server) - startReceiver(server) - loadConfig(server, args.rx_hostname, args.settingspath) - startCmdTests(server, fp, file_results) - cleanup(server) - except: - Log(Fore.RED, 'Exception caught. Cleaning up.') - cleanup(server) - sys.stdout = original_stdout - sys.stderr = original_stderr - Log(Fore.RED, 'Cmd tests failed for ' + server + '!!!') - raise + testError = False + for server in servers: + try: + # print to terminal for progress + sys.stdout = original_stdout + sys.stderr = original_stderr + file_results = prefix_fname + '_results_cmd_' + server + '.txt' + Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')') + sys.stdout = fp + sys.stderr = fp + Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')') + + # cmd tests for det + cleanup(fp) + startServer(server) + startReceiver(server) + loadConfig(server, args.rx_hostname, args.settingspath) + startCmdTests(server, fp, file_results) + cleanup(fp) + + except Exception as e: + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + Log(Fore.RED, f'Exception caught while testing {server}. Cleaning up...') + testError = True + break + + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + if not testError: + Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers)) - Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers)) - -# redirect to terminal -sys.stdout = original_stdout -sys.stderr = original_stderr -Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers) + '\nYayyyy! :) ') \ No newline at end of file + except Exception as e: + # redirect to terminal + sys.stdout = original_stdout + sys.stderr = original_stderr + Log(Fore.RED, f'Exception caught with general testing. Cleaning up...') + cleanSharedmemory(sys.stdout) + \ No newline at end of file