From 1972a55ae54c36f84a7f761c7783a304b229dd7e Mon Sep 17 00:00:00 2001 From: Kurt Biery Date: Wed, 13 May 2026 13:13:00 -0500 Subject: [PATCH 1/5] Removed the last few references to nanorc in integrationtest_drunc.py --- src/integrationtest/integrationtest_drunc.py | 24 +------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/integrationtest/integrationtest_drunc.py b/src/integrationtest/integrationtest_drunc.py index de27c8f..24485ee 100755 --- a/src/integrationtest/integrationtest_drunc.py +++ b/src/integrationtest/integrationtest_drunc.py @@ -112,22 +112,9 @@ def pytest_generate_tests(metafunc): # create an entry for the default choice of ssh-standalone metafunc.module.process_manager_choices = { "StandAloneSSH_PM" : "ssh-standalone" } - # 27-Feb-2026, KAB: support for the nanorc --> dunerc transition - # We will be able to remove the following two lines once all integtests - # have been converted to use dunerc instead of nanorc. - if not hasattr(metafunc.module, "dunerc_command_list") and hasattr(metafunc.module, "nanorc_command_list"): - metafunc.module.dunerc_command_list = metafunc.module.nanorc_command_list - parametrize_fixture_with_items(metafunc, "create_config_files", "confgen_arguments") parametrize_fixture_with_items(metafunc, "process_manager_type", "process_manager_choices") - - # 27-Feb-2026, KAB: support for the nanorc --> dunerc transition - # We will be able to just use "run_dunerc" once all integtests - # have been converted to use dunerc instead of nanorc. - if "run_nanorc" in metafunc.fixturenames: - parametrize_fixture_with_items(metafunc, "run_nanorc", "dunerc_command_list") - if "run_dunerc" in metafunc.fixturenames: - parametrize_fixture_with_items(metafunc, "run_dunerc", "dunerc_command_list") + parametrize_fixture_with_items(metafunc, "run_dunerc", "dunerc_command_list") # determine the number of different parametrizations # (recall that this fixture is called once per pytest function in each integtest) @@ -434,12 +421,6 @@ def apply_update(obj, substitution): yield result -# 27-Feb-2026, KAB: support for the nanorc --> dunerc transition -# Temporary fixture until all integtests have been changed to use "dunerc". -@pytest.fixture(scope="module") -def run_nanorc(run_dunerc): - yield run_dunerc - @pytest.fixture(scope="module") def run_dunerc(request, create_config_files, process_manager_type, tmp_path_factory): """Run drunc with the OKS DB files created by `create_config_files`. The @@ -736,9 +717,6 @@ class RunResult: result.confgen_config = create_config_files.config result.config_session_name = create_config_files.config.config_session_name result.daq_session_name = create_config_files.config.daq_session_name - # 27-Feb-2026, KAB: the nanorc_commands return value can be removed once - # all integtests have been changed to use "dunerc". - result.nanorc_commands = run_control_commands result.dunerc_commands = run_control_commands result.run_dir = run_dir result.config_dir = create_config_files.config_dir From 25d9d9774db9b046845677d327d7631a93c1917a Mon Sep 17 00:00:00 2001 From: Kurt Biery Date: Wed, 27 May 2026 12:26:22 -0500 Subject: [PATCH 2/5] Changed nanorc to dunerc in README.md --- docs/README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/README.md b/docs/README.md index 491110d..4ddfeaa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,30 +27,30 @@ config_obj = data_classes.drunc_config() # Declare the set of configurations to be tested, as a dictionary of name: drunc_config() pairs or as a list of drunc_config() objects confgen_arguments = [config_obj] -# The commands to run in nanorc, as a list (this is read by integrationtest_drunc) -nanorc_command_list="boot conf start --run-number 1 enable-triggers wait 10 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split() +# The commands to run in dunerc, as a list (this is read by integrationtest_drunc) +dunerc_command_list="boot conf start --run-number 1 enable-triggers wait 10 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split() # The tests themselves -def test_nanorc_success(run_nanorc): - # Check that nanorc completed correctly - assert run_nanorc.completed_process.returncode==0 +def test_dunerc_success(run_dunerc): + # Check that dunerc completed correctly + assert run_dunerc.completed_process.returncode==0 -def test_log_files(run_nanorc): +def test_log_files(run_dunerc): # Check that there are no warnings or errors in the log files - assert log_file_checks.logs_are_error_free(run_nanorc.log_files) + assert log_file_checks.logs_are_error_free(run_dunerc.log_files) -def test_data_file(run_nanorc): +def test_data_file(run_dunerc): # Run some tests on the output data file - assert len(run_nanorc.data_files)==1 + assert len(run_dunerc.data_files)==1 - data_file=data_file_checks.DataFile(run_nanorc.data_files[0]) + data_file=data_file_checks.DataFile(run_dunerc.data_files[0]) assert data_file_checks.sanity_check(data_file) assert data_file_checks.check_link_presence(data_file, n_links=1) assert data_file_checks.check_fragment_sizes(data_file, min_frag_size=22344, max_frag_size=22344) ``` -As you can see, there are two main parts to the file: the "setup" part, containing definitions of variables used by the integrationtest plugin to configure the tests; and the tests themselves, which consist of functions containing `assert`s for conditions that should be true after the drunc run. (Note that for historic reasons, several things are still named `nanorc` after the previous run control implementation.) +As you can see, there are two main parts to the file: the "setup" part, containing definitions of variables used by the integrationtest plugin to configure the tests; and the tests themselves, which consist of functions containing `assert`s for conditions that should be true after the drunc run. (Note that for historic reasons, several things are still named `dunerc` after the previous run control implementation.) To run the test, go to the directory holding it and: @@ -64,15 +64,15 @@ The test framework handles running python with the confgen specified in the test ## Writing test functions -Each test function's name must begin with `test_` and the function should take `run_nanorc` as an argument. The `run_nanorc` argument refers to the return value -of the `run_nanorc` [fixture](https://docs.pytest.org/en/6.2.x/fixture.html#fixtures) from this package. The `run_nanorc` object has attributes: +Each test function's name must begin with `test_` and the function should take `run_dunerc` as an argument. The `run_dunerc` argument refers to the return value +of the `run_dunerc` [fixture](https://docs.pytest.org/en/6.2.x/fixture.html#fixtures) from this package. The `run_dunerc` object has attributes: * `completed_process`: [`subprocess.CompletedProcess`](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess) object with the output of the run control process * `confgen_config`: The drunc_config object used for this test instance * `session`: The name of the OKS `Session` object used as the entry-point for the configuration * `session_name`: The name given for the running session of the DAQ -* `nanorc_commands`: The list of commands given to run control for this test (useful when running multiple configs/sessions as described below) -* `run_dir`: [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) pointing to the directory in which nanorc was run +* `dunerc_commands`: The list of commands given to run control for this test (useful when running multiple configs/sessions as described below) +* `run_dir`: [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) pointing to the directory in which dunerc was run * `config_dir`: [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) pointing to the directory in which the run configuration is stored * `data_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the HDF5 data files produced by the run * `tpset_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the HDF5 TP files produced by the run @@ -89,12 +89,12 @@ confgen_arguments=[ basic_config_obj, altered_config_obj ] This will run the configuration generation twice: once with the `basic_config_obj` and once with `altered_test_obj`. The DAQ will be run for each of the resultant configurations (in this example, two `drunc` sessions would be run). -You can have multiple runs of the DAQ per configuration too: modify `nanorc_command_list` to be a list of lists of commands. The total number of DAQ runs will then be `len(confgen_arguments) * len(nanorc_command_list)`. (It is also possible to have multiple runs within a single instance of the DAQ by having your command list include stop..start transitions.) +You can have multiple runs of the DAQ per configuration too: modify `dunerc_command_list` to be a list of lists of commands. The total number of DAQ runs will then be `len(confgen_arguments) * len(dunerc_command_list)`. (It is also possible to have multiple runs within a single instance of the DAQ by having your command list include stop..start transitions.) -`pytest` will automatically generate names for each `(confgen_arguments, nanorc_command_list)` pair. You can provide more meaningful names by providing `confgen_arguments` and/or `nanorc_command_list` as a dictionary. Each key is the human-readable name of the instance, and the corresponding value is the list of arguments or commands. Eg, for two nanorc runs with different lengths, with names "longer" and "shorter": +`pytest` will automatically generate names for each `(confgen_arguments, dunerc_command_list)` pair. You can provide more meaningful names by providing `confgen_arguments` and/or `dunerc_command_list` as a dictionary. Each key is the human-readable name of the instance, and the corresponding value is the list of arguments or commands. Eg, for two dunerc runs with different lengths, with names "longer" and "shorter": ```python -nanorc_command_list={ "longer": "boot conf start --run-number 1 enable-triggers wait 20 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split(), +dunerc_command_list={ "longer": "boot conf start --run-number 1 enable-triggers wait 20 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split(), "shorter": "boot conf start --run-number 1 enable-triggers wait 10 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split() } ``` From e8d9cfa34a54ae30f3b7cfa1f9fdc98a1f483ca0 Mon Sep 17 00:00:00 2001 From: Kurt Biery Date: Wed, 27 May 2026 13:36:18 -0500 Subject: [PATCH 3/5] work in progress --- docs/README.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4ddfeaa..f7608b9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,9 @@ This package provides a simple framework for integration tests of the DUNE DAQ s # How-to -The primary testing module in `integrationtest` is [integrationtest_drunc.py](https://github.com/DUNE-DAQ/integrationtest/blob/develop/python/integrationtest/integrationtest_drunc.py). It supports either passing a complete configuration or using `daqconf` to generate segment applications in a "standard" DUNE-DAQ topology. +The primary testing module in `integrationtest` is [integrationtest_drunc.py](https://github.com/DUNE-DAQ/integrationtest/blob/develop/python/integrationtest/integrationtest_drunc.py). It supports either passing a complete configuration or using tools in the `daqconf` repo to generate segment applications in a "standard" DUNE-DAQ topology. + +The parameters associated with the use of a complete DUNE-DAQ (OKS) configuration are specified in an instance of the `integtest_params_for_predefined_dunedaq_config` Python data class, and the parameters that specify the details of a generated DUNE-DAQ configuration are communicated in an instance of the `integtest_params_for_generated_dunedaq_config` Python data class. (Both of these data classes inherit from the `integtest_param_base_class` data class.) Explaining how to write tests is probably easiest with an example. Each test file should be named `test_*.py` or `*_test.py` to follow pytest's [conventions for Python test discovery](https://docs.pytest.org/en/6.2.x/goodpractices.html#test-discovery), and they are usually placed in the `integtest` subdirectory of your repository. Here's `test_integration.py`: @@ -18,18 +20,21 @@ import integrationtest.data_classes as data_classes # Use the integrationtest_drunc plugin pytest_plugins = "integrationtest.integrationtest_drunc" -# Load pre-configured objects from this OKS database file -object_databases = ["config/daqsystemtest/integrationtest-objects.data.xml"] +# Create a meta-configuration. The parameters in this data class are used by integrationtest_drunc +# and scripts in the daqconf repo to generate the DUNE-DAQ configuration. +config_obj = data_classes.integtest_params_for_generated_dunedaq_config() -# Create a meta-configuration. This is used by integrationtest_drunc to configure daqconf -config_obj = data_classes.drunc_config() +# Load pre-configured objects from this OKS database file +config_obj.object_databases = ["config/daqsystemtest/integrationtest-objects.data.xml"] -# Declare the set of configurations to be tested, as a dictionary of name: drunc_config() pairs or as a list of drunc_config() objects +# Declare the set of configurations to be tested, as a dictionary of name: integtest_param_base_class() pairs or as a list of integtest_param_base_class() objects confgen_arguments = [config_obj] # The commands to run in dunerc, as a list (this is read by integrationtest_drunc) dunerc_command_list="boot conf start --run-number 1 enable-triggers wait 10 disable-triggers wait 2 drain-dataflow wait 2 stop-trigger-sources stop scrap terminate".split() + + # The tests themselves def test_dunerc_success(run_dunerc): @@ -50,7 +55,7 @@ def test_data_file(run_dunerc): assert data_file_checks.check_fragment_sizes(data_file, min_frag_size=22344, max_frag_size=22344) ``` -As you can see, there are two main parts to the file: the "setup" part, containing definitions of variables used by the integrationtest plugin to configure the tests; and the tests themselves, which consist of functions containing `assert`s for conditions that should be true after the drunc run. (Note that for historic reasons, several things are still named `dunerc` after the previous run control implementation.) +As you can see, there are two main parts to the file: the "setup" part, containing definitions of variables used by the integrationtest plugin to configure the tests; and the tests themselves, which consist of functions containing `assert`s for conditions that should be true after the drunc run. To run the test, go to the directory holding it and: @@ -68,20 +73,23 @@ Each test function's name must begin with `test_` and the function should take ` of the `run_dunerc` [fixture](https://docs.pytest.org/en/6.2.x/fixture.html#fixtures) from this package. The `run_dunerc` object has attributes: * `completed_process`: [`subprocess.CompletedProcess`](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess) object with the output of the run control process -* `confgen_config`: The drunc_config object used for this test instance -* `session`: The name of the OKS `Session` object used as the entry-point for the configuration -* `session_name`: The name given for the running session of the DAQ +* `confgen_config`: The integtest_param_base_class object used for this test instance +* `config_session_name`: The name of the OKS `Session` object used as the entry-point for the configuration +* `daq_session_name`: The name given for the running session of the DAQ * `dunerc_commands`: The list of commands given to run control for this test (useful when running multiple configs/sessions as described below) * `run_dir`: [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) pointing to the directory in which dunerc was run * `config_dir`: [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) pointing to the directory in which the run configuration is stored * `data_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the HDF5 data files produced by the run * `tpset_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the HDF5 TP files produced by the run +* `trmon_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the HDF5 TR-monitoring files produced by the run * `log_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the log files produced by the run * `opmon_files`: list of [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) with each of the opmon json files produced by the run +* `daq_session_overall_time`: the amount of time that the DAQ session was active +* `verbosity_helper`: utility to help determine whether various console messages should be displayed or not based on the verbosity setting provided by the user ## Running multiple configurations/sessions -You may want to run the same tests on the output of multiple confgens (eg, to check that the system works with a particular option both on and off). To do this, add additional `"name": drunc_config()` entries to the `confgen_arguments` dictionary in your test script. +You may want to run the same tests on the output of multiple confgens (eg, to check that the system works with a particular option both on and off). To do this, add additional `"name": integtest_param_base_class()` entries to the `confgen_arguments` dictionary in your test script. ```python confgen_arguments=[ basic_config_obj, altered_config_obj ] From 00645e97d108b877fd9d496a0d1a4a36cf04bfbf Mon Sep 17 00:00:00 2001 From: bieryAtFnal <36311946+bieryAtFnal@users.noreply.github.com> Date: Wed, 27 May 2026 13:48:49 -0500 Subject: [PATCH 4/5] work in progress --- docs/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index f7608b9..f637c50 100644 --- a/docs/README.md +++ b/docs/README.md @@ -89,11 +89,17 @@ of the `run_dunerc` [fixture](https://docs.pytest.org/en/6.2.x/fixture.html#fixt ## Running multiple configurations/sessions -You may want to run the same tests on the output of multiple confgens (eg, to check that the system works with a particular option both on and off). To do this, add additional `"name": integtest_param_base_class()` entries to the `confgen_arguments` dictionary in your test script. +You may want to run the same tests on the output of multiple confgens (eg, to check that the system works with a particular option both on and off). To do this, add additional entries to the `confgen_arguments` list (or dictionary) in your test script. + +For example, ```python confgen_arguments=[ basic_config_obj, altered_config_obj ] ``` +or +```python +confgen_arguments={ "Basic": basic_config_obj, "Altered": altered_config_obj } +``` This will run the configuration generation twice: once with the `basic_config_obj` and once with `altered_test_obj`. The DAQ will be run for each of the resultant configurations (in this example, two `drunc` sessions would be run). From 0710cae03165c110cc84312dcbf8aae8d5253d87 Mon Sep 17 00:00:00 2001 From: Kurt Biery Date: Wed, 27 May 2026 13:58:44 -0500 Subject: [PATCH 5/5] work in progress --- docs/README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/README.md b/docs/README.md index f637c50..c514531 100644 --- a/docs/README.md +++ b/docs/README.md @@ -114,21 +114,23 @@ dunerc_command_list={ "longer": "boot conf start --run-number 1 enable-triggers ## Configuring your test -The meta-configuration objects are defined in the [data_classes.py](https://github.com/DUNE-DAQ/integrationtest/blob/develop/python/integrationtest/data_classes.py) file. Configurations are generated using the following steps: -1. Preconfigured objects are loaded (`object_databases = ["config/daqsystemtest/integrationtest-objects.data.xml"]`) This file includes elements of the "standard" configuration present in `daqsystemtest` -1. `daqconf` generate.py methods are called by `integrationtest` to create the Segment apps (e.g. generate_hwmap, generate_readout, ...). The arguments to these methods come from the drunc_config object +The meta-configuration objects are defined in the [data_classes.py](https://github.com/DUNE-DAQ/integrationtest/blob/develop/python/integrationtest/data_classes.py) file. + +DUNE-DAQ configurations that are specified in `integtest_params_for_generated_dunedaq_config()` data classes are generated using the following steps: +1. Preconfigured objects are loaded (`config_obj.object_databases = ["config/daqsystemtest/integrationtest-objects.data.xml"]`) This file includes elements of the "standard" configuration present in `daqsystemtest` +1. `daqconf` generate.py methods are called by `integrationtest` to create the Segment apps (e.g. `generate_hwmap`, `generate_readout`, ...). The arguments to these methods come from the drunc_config object 1. User-supplied configuration substitutions are applied to the configuration. -If the user supplies a valid config_db argument in their drunc_config, the second step is skipped, and the provided configuration is copied into the output directory instead. +If the user supplies an `integtest_params_for_predefined_dunedaq_config()` data class instead, the second step is skipped, and the provided configuration is copied into the output directory instead. Configuration substitutions are provided by the user as instances of the `config_substitution` data class: ```python -substitution = data_classes.config_substitution( - obj_id="random-tc-generator", - obj_class="RandomTCMakerConf", - updates={"trigger_rate_hz": 1}, +conf_dict.config_substitutions.append( + data_classes.attribute_substitution( + obj_class="RandomTCMakerConf", + updates={"trigger_rate_hz": 1}, + ) ) -conf_dict.config_substitutions.append(substitution) ``` Substitutions can be applied to a single object in the database or all objects of a given class. If obj_id is specified, it applies only to that one object, if found.