diff --git a/Gui/python/TestHandler.py b/Gui/python/TestHandler.py index 3d242fa8..b809fbb9 100644 --- a/Gui/python/TestHandler.py +++ b/Gui/python/TestHandler.py @@ -331,7 +331,6 @@ def __init__(self, runwindow, master, info, firmware, txt_files={}): self.communicationTestResults = { module.getModuleName(): None for module in self.modules } - self.communicationTestModule = None self.info_processes = [QProcess() for _ in self.firmware] for i, process in enumerate(self.info_processes): @@ -378,6 +377,22 @@ def _module_is_enabled(self, module) -> bool: def enabled_modules(self): return [module for module in self.modules if self._module_is_enabled(module)] + def _set_communication_test_result(self, process_index, passed): + module_names = [] + for module in self.firmware[process_index].getModules(): + if not self._module_is_enabled(module): + continue + module_name = module.getModuleName() + self.communicationTestResults[module_name] = passed + module_names.append(module_name) + + logger.info( + "CommunicationTest result for %s modules %s: %s", + self.firmware[process_index].getBoardName(), + module_names, + "pass" if passed else "fail", + ) + def finished_run_process(self, _, exitStatus, i): logger.info("Inside finished_run_process") logger.info("Current exitStatus in finished_run_process: %s", exitStatus) @@ -1120,6 +1135,8 @@ def setupQProcess(self): process.setWorkingDirectory(os.environ.get("PH2ACF_BASE_DIR") + "/test/") if self.currentTest == "CommunicationTest": + for module in self.enabled_modules(): + self.communicationTestResults[module.getModuleName()] = None for process, firmware in zip(self.run_processes, self.firmware): process.start( "CMSITminiDAQ", @@ -1800,39 +1817,15 @@ def on_readyReadStandardOutput(self, processIndex: int): text.decode("utf-8"), self.runwindow.ConsoleViews[processIndex] ) - match = re.search(r"CMSIT_RD53_([^_]+)", alltext) - if match: - if self.communicationTestModule is not None: - self.communicationTestResults[self.communicationTestModule] = True - self.communicationTestModule = match.group(1) - if self.currentTest == "CommunicationTest": if ( "Error, some data lanes are enabled but inactive, reached maximum number of attempts" in alltext ): - if self.communicationTestModule is None: - logger.error( - "Module name not found before CommunicationTest result in test output." - ) - - logger.error( - "Module name not found before CommunicationTest result in test output." - ) - - else: - self.communicationTestResults[self.communicationTestModule] = False - self.communicationTestModule = None + self._set_communication_test_result(processIndex, False) self.forceContinue(self.firmware[processIndex]) elif "All enabled data lanes are active" in alltext: - if self.communicationTestModule is None: - logger.error( - "Module name not found before CommunicationTest result in test output." - ) - - else: - self.communicationTestResults[self.communicationTestModule] = True - self.communicationTestModule = None + self._set_communication_test_result(processIndex, True) else: if "FIFO empty" in alltext or "Reached maximum number of attempts" in alltext: diff --git a/Gui/python/TestValidator.py b/Gui/python/TestValidator.py index e958ee95..e7f8daab 100644 --- a/Gui/python/TestValidator.py +++ b/Gui/python/TestValidator.py @@ -12,6 +12,40 @@ ROOT.gROOT.SetBatch(ROOT.kTRUE) +def _get_open_bump_root_files(output_dir, board_id, hybrid_id): + root_pattern = re.compile( + rf"Run(?P\d+)_PixelAlive_Board_{re.escape(str(board_id))}" + rf"_Hybrid_{re.escape(str(hybrid_id))}\.root$" + ) + matching_files = [] + + for file_name in os.listdir(output_dir): + match = root_pattern.search(file_name) + if match: + matching_files.append( + (int(match.group("run_number")), os.path.join(output_dir, file_name)) + ) + + matching_files.sort(key=lambda item: item[0]) + run_numbers = [run_number for run_number, _ in matching_files] + + if len(matching_files) != 3: + raise ValueError( + "OpenBumpTest requires exactly 3 ROOT files for " + f"Board {board_id}, Hybrid {hybrid_id}; found {len(matching_files)} " + f"with run numbers {run_numbers}." + ) + + expected_run_numbers = list(range(run_numbers[0], run_numbers[0] + 3)) + if run_numbers != expected_run_numbers: + raise ValueError( + "OpenBumpTest ROOT files must have sequential run numbers for " + f"Board {board_id}, Hybrid {hybrid_id}; found {run_numbers}." + ) + + return [path for _, path in matching_files] + + def ResultGrader( felis, outputDir, @@ -176,16 +210,19 @@ def ResultGrader( elif testName == "OpenBumpTest": # Collect all 3 XML files from the OpenBumpTest subtests relevant_files = [] + module_boardID = module_data["boardID"] # Collect all XML files (one for each subtest: highcharge_xtalk, coupled_xtalk, uncoupled_xtalk) for file in os.listdir(outputDir): if file.endswith(".xml"): relevant_files.append(os.path.join(outputDir, file)) - # Also collect PixelAlive root files from the subtests - for file in os.listdir(outputDir): - if "PixelAlive" in file and file.endswith(".root"): - relevant_files.append(os.path.join(outputDir, file)) + # Only collect the three PixelAlive ROOT files for this module. + relevant_files.extend( + _get_open_bump_root_files( + outputDir, module_boardID, module_hybridID + ) + ) # Collect any .json files for file in os.listdir(outputDir):