From 12e703904711f06069ef985237e0376ef098ea37 Mon Sep 17 00:00:00 2001 From: Steffen Albrecht Date: Tue, 9 Jun 2026 15:20:23 +0200 Subject: [PATCH 1/2] [HS3] [RF] Adding test to pull and run external HS3TestSuite --- .../root-ci-config/buildconfig/global.txt | 1 + cmake/modules/RootBuildOptions.cmake | 3 +- roofit/hs3/test/CMakeLists.txt | 13 +++++ roofit/hs3/test/test_hs3_suite.py | 50 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 roofit/hs3/test/test_hs3_suite.py diff --git a/.github/workflows/root-ci-config/buildconfig/global.txt b/.github/workflows/root-ci-config/buildconfig/global.txt index 4e598d6afa5ed..464bc6c2261a5 100644 --- a/.github/workflows/root-ci-config/buildconfig/global.txt +++ b/.github/workflows/root-ci-config/buildconfig/global.txt @@ -68,6 +68,7 @@ roofit_multiprocess=OFF root7=ON rootbench=OFF roottest=ON +hs3testsuite=ON runtime_cxxmodules=ON shadowpw=OFF shared=ON diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 0966ae13c3353..b0e6d0152e444 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -189,6 +189,7 @@ option(gminimal "Enable only required options by default, but include X11/Cocoa" option(minimal "Enable only required options by default" OFF) option(rootbench "Build rootbench if rootbench exists in root or if it is a sibling directory (implies testing=ON)" OFF) option(roottest "Build roottest (implies testing=ON)" OFF) +option(hs3testsuite "Setup and use the HS3 conformance test suite (implies testing=ON)" OFF) option(testing "Enable testing with CTest" OFF) option(asan "Build ROOT with address sanitizer instrumentation" OFF) @@ -329,7 +330,7 @@ endif() ROOT_APPLY_OPTIONS() #---roottest option implies testing -if(roottest OR rootbench) +if(roottest OR rootbench OR hs3testsuite) set(testing ON CACHE BOOL "" FORCE) endif() diff --git a/roofit/hs3/test/CMakeLists.txt b/roofit/hs3/test/CMakeLists.txt index d152337c8a7a8..1f41a041690aa 100644 --- a/roofit/hs3/test/CMakeLists.txt +++ b/roofit/hs3/test/CMakeLists.txt @@ -1,2 +1,15 @@ ROOT_ADD_GTEST(testRooFitHS3 testRooFitHS3.cxx LIBRARIES RooFitCore RooFit RooFitHS3) ROOT_ADD_GTEST(testHS3SimultaneousFit testHS3SimultaneousFit.cxx LIBRARIES RooFitCore RooFit RooFitHS3 RooStats) + +if(pyroot AND hs3testsuite) + set(hs3testsuite_dir ${CMAKE_CURRENT_SOURCE_DIR}/HS3TestSuite) + if(NOT EXISTS ${hs3testsuite_dir}) + find_package(Git QUIET REQUIRED) + execute_process(COMMAND ${GIT_EXECUTABLE} clone https://github.com/Phmonski/HS3TestSuite + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + if(EXISTS ${hs3testsuite_dir}) + ROOT_ADD_PYUNITTEST(hs3-suite test_hs3_suite.py PYTHON_DEPS jsonschema ENVIRONMENT HS3TESTSUITE_ROOT=${hs3testsuite_dir}) + endif() +endif() \ No newline at end of file diff --git a/roofit/hs3/test/test_hs3_suite.py b/roofit/hs3/test/test_hs3_suite.py new file mode 100644 index 0000000000000..4c0f653c95668 --- /dev/null +++ b/roofit/hs3/test/test_hs3_suite.py @@ -0,0 +1,50 @@ +import os +from pathlib import Path +import sys +import unittest + + +hs3_root_dir = os.environ.get("HS3TESTSUITE_ROOT") +if hs3_root_dir: + sys.path.insert(0, hs3_root_dir) + +try: + from hs3suite.runner import run_suite + +except ImportError as e: + TestHS3Suite = type( + "TestHS3Suite", + (unittest.TestCase,), + dict(test_dependencies=lambda self, e=e: self.fail(f"Missing dependency: {e}")), + ) +else: + hs3_root_path = Path(hs3_root_dir) + try: + results = run_suite(hs3_root_path, "roofit") + except Exception as e: + + def test(self, e=e): + self.fail(f"HS3TestSuite failed to run: {e}") + + test.__name__ = "test_hs3testsuite_execution" + TestHS3Suite = type("TestHS3Suite", (unittest.TestCase,), {test.__name__: test}) + else: + namespace = dict(__module__=__name__) + for r in results: + + def _make(result): + def test(self): + if result.status == "failed": + self.fail(result.message) + return + + test.__name__ = f"test_{result.test_id}__{result.check_id}" + test.__doc__ = f"{result.test_id}::{result.check_id}" + return test + + func = _make(r) + namespace[func.__name__] = func + TestHS3Suite = type("TestHS3Suite", (unittest.TestCase,), namespace) + +if __name__ == "__main__": + unittest.main() From b02d03b16f1d99bf07e461adb428f4fcc6c18156 Mon Sep 17 00:00:00 2001 From: Steffen Albrecht Date: Thu, 11 Jun 2026 06:19:35 +0200 Subject: [PATCH 2/2] fix linting (import sorting) --- roofit/hs3/test/test_hs3_suite.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/roofit/hs3/test/test_hs3_suite.py b/roofit/hs3/test/test_hs3_suite.py index 4c0f653c95668..983de1be38a8a 100644 --- a/roofit/hs3/test/test_hs3_suite.py +++ b/roofit/hs3/test/test_hs3_suite.py @@ -1,8 +1,7 @@ import os -from pathlib import Path import sys import unittest - +from pathlib import Path hs3_root_dir = os.environ.get("HS3TESTSUITE_ROOT") if hs3_root_dir: