merged developer
Some checks failed
Build on RHEL9 / build (push) Successful in 2m51s
Build on RHEL8 / build (push) Failing after 4m48s

This commit is contained in:
mazzol_a 2025-05-15 17:20:52 +02:00
commit 9343e3c667
6 changed files with 133 additions and 274 deletions

View File

@ -65,6 +65,9 @@ configure_file( scripts/test_virtual.py
${CMAKE_BINARY_DIR}/test_virtual.py
)
configure_file(scripts/frameSynchronizerPullSocket.py
${CMAKE_BINARY_DIR}/bin/frameSynchronizerPullSocket.py COPYONLY)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
${CMAKE_BINARY_DIR}/bin/slsdet/VERSION
)

View File

@ -104,11 +104,11 @@ void zmq_free(void *data, void *hint) { delete[] static_cast<char *>(data); }
void print_frames(const PortFrameMap &frame_port_map) {
LOG(sls::logDEBUG) << "Printing frames";
for (const auto &it : frame_port_map) {
uint16_t udpPort = it.first;
const uint16_t udpPort = it.first;
const auto &frame_map = it.second;
LOG(sls::logDEBUG) << "UDP port: " << udpPort;
for (const auto &frame : frame_map) {
uint64_t fnum = frame.first;
const uint64_t fnum = frame.first;
const auto &msg_list = frame.second;
LOG(sls::logDEBUG)
<< " acq index: " << fnum << '[' << msg_list.size() << ']';
@ -127,30 +127,26 @@ std::set<uint64_t> get_valid_fnums(const PortFrameMap &port_frame_map) {
// collect all unique frame numbers from all ports
std::set<uint64_t> unique_fnums;
for (auto it = port_frame_map.begin(); it != port_frame_map.begin(); ++it) {
const FrameMap &frame_map = it->second;
for (auto frame = frame_map.begin(); frame != frame_map.end();
++frame) {
unique_fnums.insert(frame->first);
for (const auto &it : port_frame_map) {
const FrameMap &frame_map = it.second;
for (const auto &frame : frame_map) {
unique_fnums.insert(frame.first);
}
}
// collect valid frame numbers
for (auto &fnum : unique_fnums) {
bool is_valid = true;
for (auto it = port_frame_map.begin(); it != port_frame_map.end();
++it) {
uint16_t port = it->first;
const FrameMap &frame_map = it->second;
for (const auto &it : port_frame_map) {
const uint16_t port = it.first;
const FrameMap &frame_map = it.second;
auto frame = frame_map.find(fnum);
// invalid: fnum missing in one port
if (frame == frame_map.end()) {
LOG(sls::logDEBUG)
<< "Fnum " << fnum << " is missing in port " << port;
// invalid: fnum greater than all in that port
auto last_frame = std::prev(frame_map.end());
auto last_fnum = last_frame->first;
if (fnum > last_fnum) {
auto upper_frame = frame_map.upper_bound(fnum);
if (upper_frame == frame_map.end()) {
LOG(sls::logDEBUG) << "And no larger fnum found. Fnum "
<< fnum << " is invalid.\n";
is_valid = false;
@ -220,18 +216,26 @@ void Correlate(FrameStatus *stat) {
// sending all valid fnum data packets
for (const auto &fnum : valid_fnums) {
ZmqMsgList msg_list;
PortFrameMap &port_frame_map = stat->frames;
for (auto it = port_frame_map.begin();
it != port_frame_map.end(); ++it) {
uint16_t port = it->first;
const FrameMap &frame_map = it->second;
for (const auto &it : stat->frames) {
const uint16_t port = it.first;
const FrameMap &frame_map = it.second;
auto frame = frame_map.find(fnum);
if (frame != frame_map.end()) {
msg_list.insert(msg_list.end(),
stat->frames[port][fnum].begin(),
stat->frames[port][fnum].end());
// clean up
for (zmq_msg_t *msg : stat->frames[port][fnum]) {
}
}
LOG(printHeadersLevel)
<< "Sending data packets for fnum " << fnum;
zmq_send_multipart(socket, msg_list);
// clean up
for (const auto &it : stat->frames) {
const uint16_t port = it.first;
const FrameMap &frame_map = it.second;
auto frame = frame_map.find(fnum);
if (frame != frame_map.end()) {
for (zmq_msg_t *msg : frame->second) {
if (msg) {
zmq_msg_close(msg);
delete msg;
@ -240,9 +244,6 @@ void Correlate(FrameStatus *stat) {
stat->frames[port].erase(fnum);
}
}
LOG(printHeadersLevel)
<< "Sending data packets for fnum " << fnum;
zmq_send_multipart(socket, msg_list);
}
}
// sending all end packets
@ -256,6 +257,21 @@ void Correlate(FrameStatus *stat) {
}
}
stat->ends.clear();
// clean up old frames
for (auto &it : stat->frames) {
FrameMap &frame_map = it.second;
for (auto &frame : frame_map) {
for (zmq_msg_t *msg : frame.second) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
frame.second.clear();
}
frame_map.clear();
}
stat->frames.clear();
}
}
}

View File

@ -60,3 +60,5 @@ 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)
configure_file(scripts/utils_for_test.py ${CMAKE_BINARY_DIR}/bin/utils_for_test.py COPYONLY)

View File

@ -44,14 +44,16 @@ def startFrameSynchronizer(num_mods, fp):
time.sleep(1)
def acquire(fp, det):
def acquire(fp):
Log(LogLevel.INFO, 'Acquiring')
Log(LogLevel.INFO, 'Acquiring', fp)
det.acquire()
d = Detector()
d.acquire()
def testFramesCaught(name, det, num_frames):
fnum = det.rx_framescaught[0]
def testFramesCaught(name, num_frames):
d = Detector()
fnum = d.rx_framescaught[0]
if fnum != num_frames:
raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}")
@ -59,7 +61,7 @@ def testFramesCaught(name, det, num_frames):
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp)
def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp):
def testZmqHeadetTypeCount(name, 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)
@ -86,7 +88,8 @@ def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp):
continue
# test if file contents matches expected counts
num_ports_per_module = 1 if name == "gotthard2" else det.numinterfaces
d = Detector()
num_ports_per_module = 1 if name == "gotthard2" else d.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:
@ -108,13 +111,10 @@ def startTestsForAll(args, 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)
loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
acquire(fp)
testFramesCaught(server, args.num_frames)
testZmqHeadetTypeCount(server, args.num_mods, args.num_frames, fp)
Log(LogLevel.INFO, '\n')
except Exception as e:
raise RuntimeException(f'Synchronizer Tests failed') from e

View File

@ -4,244 +4,86 @@
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 sys, subprocess, time, traceback
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
HALFMOD2_TCP_RX_PORTNO=1957
from slsdet import Detector
from slsdet.defines import DEFAULT_TCP_RX_PORTNO
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()
from utils_for_test import (
Log,
LogLevel,
RuntimeException,
checkIfProcessRunning,
killProcess,
cleanup,
cleanSharedmemory,
startProcessInBackground,
runProcessWithLogFile,
startDetectorVirtualServer,
loadConfig,
ParseArguments
)
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)
LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_test'
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
GENERAL_TESTS_LOG_FNAME = LOG_PREFIX_FNAME + '_results_general.txt'
CMD_TEST_LOG_PREFIX_FNAME = LOG_PREFIX_FNAME + '_results_cmd_'
def cleanup(fp):
'''
kill both servers, receivers and clean shared memory
'''
Log(Fore.GREEN, 'Cleaning up...')
killProcess('DetectorServer_virtual')
killProcess('slsReceiver')
killProcess('slsMultiReceiver')
cleanSharedmemory(fp)
def startReceiver(num_mods, fp):
if num_mods == 1:
cmd = ['slsReceiver']
else:
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
# in 10.0.0
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
startProcessInBackground(cmd, fp)
time.sleep(1)
def cleanSharedmemory(fp):
Log(Fore.GREEN, 'Cleaning up shared memory...')
def startGeneralTests(fp):
fname = GENERAL_TESTS_LOG_FNAME
cmd = ['tests', '--abort', '-s']
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(name.split(), 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 startServer(name):
startProcessInBackground(name + 'DetectorServer_virtual')
# second half
if name == 'eiger':
startProcessInBackground(name + 'DetectorServer_virtual -p' + str(HALFMOD2_TCP_CNTRL_PORTNO))
tStartup = 6
Log(Fore.WHITE, 'Takes ' + str(tStartup) + ' seconds... Please be patient')
time.sleep(tStartup)
def startReceiver(name):
startProcessInBackground('slsReceiver')
# second half
if name == 'eiger':
startProcessInBackground('slsReceiver -t' + str(HALFMOD2_TCP_RX_PORTNO))
time.sleep(2)
def loadConfig(name, rx_hostname, settingsdir):
Log(Fore.GREEN, 'Loading config')
try:
d = Detector()
if name == 'eiger':
d.hostname = 'localhost:' + str(DEFAULT_TCP_CNTRL_PORTNO) + '+localhost:' + str(HALFMOD2_TCP_CNTRL_PORTNO)
#d.udp_dstport = {2: 50003}
# will set up for every module
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
d.rx_hostname = rx_hostname + ':' + str(DEFAULT_TCP_RX_PORTNO) + '+' + rx_hostname + ':' + str(HALFMOD2_TCP_RX_PORTNO)
d.udp_dstip = 'auto'
d.trimen = [4500, 5400, 6400]
d.settingspath = settingsdir + '/eiger/'
d.setThresholdEnergy(4500, detectorSettings.STANDARD)
else:
d.hostname = 'localhost'
d.rx_hostname = rx_hostname
d.udp_dstip = 'auto'
d.udp_srcip = 'auto'
if 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()
except:
Log(Fore.RED, 'Could not load config for ' + name)
raise
def startCmdTests(name, fp, fname):
Log(Fore.GREEN, 'Cmd Tests for ' + name)
cmd = 'tests --abort [.cmdcall] -s -o ' + fname
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)
def startGeneralTests(fp, fname):
Log(Fore.GREEN, 'General Tests')
cmd = 'tests --abort -s -o ' + fname
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 !!!'
sys.stdout = original_stdout
Log(Fore.RED, msg + '\n' + line)
sys.stdout = fp
raise Exception(msg)
Log(Fore.GREEN, 'General Tests successful')
# 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('-s', '--servers', help='Detector servers to run', nargs='*')
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) + '\'')
# redirect to file
prefix_fname = '/tmp/slsDetectorPackage_virtual_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:
# 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 + ')')
try:
startGeneralTests(fp, file_results)
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, '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))
runProcessWithLogFile('General Tests', cmd, fp, fname)
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)
raise RuntimeException(f'General tests failed.') from e
def startCmdTestsForAll(args, fp):
for server in args.servers:
try:
num_mods = 2 if server == 'eiger' else 1
fname = CMD_TEST_LOG_PREFIX_FNAME + server + '.txt'
cmd = ['tests', '--abort', '[.cmdcall]', '-s']
Log(LogLevel.INFOBLUE, f'Starting Cmd Tests for {server}')
cleanup(fp)
startDetectorVirtualServer(name=server, num_mods=num_mods, fp=fp)
startReceiver(num_mods, fp)
loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=num_mods)
runProcessWithLogFile('Cmd Tests for ' + server, cmd, fp, fname)
except Exception as e:
raise RuntimeException(f'Cmd Tests failed for {server}.') from e
Log(LogLevel.INFOGREEN, 'Passed all tests for all detectors \n' + str(args.servers))
if __name__ == '__main__':
args = ParseArguments('Automated tests with the virtual detector servers')
if args.num_mods > 1:
raise RuntimeException(f'Cannot support multiple modules at the moment (except Eiger).')
Log(LogLevel.INFOBLUE, '\nLog File: ' + MAIN_LOG_FNAME + '\n')
with open(MAIN_LOG_FNAME, 'w') as fp:
try:
startGeneralTests(fp)
startCmdTestsForAll(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.')

View File

@ -138,11 +138,9 @@ def runProcessWithLogFile(name, cmd, fp, log_file_name):
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")
startProcessInBackground(cmd, fp)
match name:
case 'jungfrau':
time.sleep(7)
@ -158,7 +156,7 @@ def connectToVirtualServers(name, num_mods):
except Exception as e:
raise RuntimeException(f'Could not create Detector object for {name}. Error: {str(e)}') from e
counts_sec = 100
counts_sec = 5
while (counts_sec != 0):
try:
d.virtual = [num_mods, SERVER_START_PORTNO]
@ -203,8 +201,6 @@ def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1)
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):