From 0f4d10912bed4e94c4a06fb482e655d554f01244 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 2 May 2025 22:48:48 +0200 Subject: [PATCH] test frame synchonizer now runs for all modules (only jungfrua enableD) with num modules and num frames as arguments (also servers) and checks the output log of pull socket to ensure there are expected number of headers, moduels and series end htypes --- python/CMakeLists.txt | 2 +- tests/scripts/test_frame_synchronizer.py | 113 ++++++++++++++--------- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 36c0c35a7..9765e55d1 100755 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -65,7 +65,7 @@ configure_file( scripts/test_virtual.py ) configure_file(scripts/frameSynchronizerPullSocket.py - ${CMAKE_BINARY_DIR}/frameSynchronizerPullSocket.py COPYONLY) + ${CMAKE_BINARY_DIR}/bin/frameSynchronizerPullSocket.py COPYONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION diff --git a/tests/scripts/test_frame_synchronizer.py b/tests/scripts/test_frame_synchronizer.py index ab7febe4a..2d88b6fcb 100644 --- a/tests/scripts/test_frame_synchronizer.py +++ b/tests/scripts/test_frame_synchronizer.py @@ -5,7 +5,7 @@ This file is used to start up simulators, receivers and run all the tests on the ''' import argparse import os, sys, subprocess, time, colorama -import shlex +import shlex, traceback, json from colorama import Fore, Style from slsdet import Detector, detectorType, detectorSettings @@ -15,8 +15,8 @@ SERVER_START_PORTNO=1900 colorama.init(autoreset=True) -def Log(color, message): - print(f"{color}{message}{Style.RESET_ALL}", flush=True) +def Log(color, message, stream=sys.stdout): + print(f"{color}{message}{Style.RESET_ALL}", file=stream, flush=True) class RuntimeException (Exception): def __init__ (self, message): @@ -28,10 +28,10 @@ def checkIfProcessRunning(processName): return res.strip().splitlines() -def killProcess(name): +def killProcess(name, fp): pids = checkIfProcessRunning(name) if pids: - Log(Fore.GREEN, f"Killing '{name}' processes with PIDs: {', '.join(pids)}") + Log(Fore.WHITE, f"Killing '{name}' processes with PIDs: {', '.join(pids)}", fp) for pid in pids: try: p = subprocess.run(['kill', pid]) @@ -48,16 +48,17 @@ 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') + Log(Fore.WHITE, 'Cleaning up') + Log(Fore.WHITE, 'Cleaning up', fp) + killProcess('DetectorServer_virtual', fp) + killProcess('slsReceiver', fp) + killProcess('slsMultiReceiver', fp) + killProcess('slsFrameSynchronizer', fp) + killProcess('frameSynchronizerPullSocket', fp) cleanSharedmemory(fp) def cleanSharedmemory(fp): - Log(Fore.GREEN, 'Cleaning up shared memory...') + Log(Fore.WHITE, 'Cleaning up shared memory...', fp) try: p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp) except: @@ -68,37 +69,41 @@ 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 + ' ...') + Log(Fore.WHITE, 'Starting up ' + name + ' ...', fp) except Exception as e: Log(Fore.RED, f'Could not start {name}:{e}') raise def startServers(name, num_mods): + Log(Fore.WHITE, 'Starting server') 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.") +def startFrameSynchronizerPullSocket(fname, fp): + Log(Fore.WHITE, 'Starting sync pull socket') + Log(Fore.WHITE, f"Starting up Synchronizer pull socket. Log: {fname}", fp) + Log(Fore.WHITE, f"Synchronizer pull socket log: {fname}") + cmd = ['python', '-u', 'frameSynchronizerPullSocket.py'] + try: + with open(fname, 'w') as fp: + subprocess.Popen(cmd, stdout=fp, stderr=fp, text=True) + except Exception as e: + Log(Fore.RED, f"failed to start synchronizer pull socket: {e}") raise def startFrameSynchronizer(num_mods): - Log(Fore.GREEN, "Going to start frame synchonizer") + Log(Fore.WHITE, 'Starting frame synchronizer') # 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') +def loadConfig(name, num_mods, rx_hostname, settingsdir, num_frames, fp): + Log(Fore.WHITE, 'Loading config') + Log(Fore.WHITE, 'Loading config', fp) try: d = Detector() d.virtual = [num_mods, SERVER_START_PORTNO] @@ -126,18 +131,46 @@ def loadConfig(name, num_mods, rx_hostname, settingsdir, num_frames): 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) +def validate_htype_counts(log_path, num_mods, num_frames): + htype_counts = { + "header": 0, + "series_end": 0, + "module": 0 + } + + with open(log_path, 'r') as f: + for line in f: + 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 # or log malformed line + + for htype, expected_count in [("header", num_mods), ("series_end", num_mods * num_frames), ("module", num_mods)]: + if htype_counts[htype] != expected_count: + msg = f"Expected 2 '{htype}' entries, found {htype_counts[htype]}" + Log(Fore.RED, msg) + raise RuntimeError(msg) + +def startTests(name, num_mods, num_frames, fp, file_pull_socket): + Log(Fore.WHITE, 'Tests for ' + name) + Log(Fore.WHITE, 'Tests for ' + name, fp) 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}") + if fnum != num_frames: + Log(Fore.RED, f"{name} caught only {fnum}. Expected {num_frames}") raise - Log(Fore.GREEN, 'Tests successful for ' + name) + validate_htype_counts(file_pull_socket, num_mods, num_frames) + Log(Fore.GREEN, f"Log file htype checks passed for {name}", fp) # parse cmd line for rx_hostname and settingspath using the argparse library @@ -176,27 +209,20 @@ 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 + ')') + Log(Fore.BLUE, '\nSynchonizer tests for ' + server, fp) + Log(Fore.BLUE, '\nSynchonizer tests for ' + server) # cmd tests for det cleanup(fp) startServers(server, args.num_mods) - startFrameSynchronizerPullSocket() + file_pull_socket = prefix_fname + '_pull_socket_' + server + '.txt' + startFrameSynchronizerPullSocket(file_pull_socket, fp) 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) + loadConfig(server, args.num_mods, args.rx_hostname, args.settingspath, args.num_frames, fp) + startTests(server, args.num_mods, args.num_frames, fp, file_pull_socket) cleanup(fp) except Exception as e: @@ -204,6 +230,9 @@ with open(fname, 'w') as fp: sys.stdout = original_stdout sys.stderr = original_stderr Log(Fore.RED, f'Exception caught while testing {server}. Cleaning up...') + with open(fname, 'a') as fp_error: + traceback.print_exc(file=fp_error) # This will log the full traceback + testError = True break