From df9017cd9ba11b23bbef338d205c7f8260194292 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 10 Apr 2026 09:00:34 -0600 Subject: [PATCH 1/4] this variable should not be required (for e3sm) --- CIME/SystemTests/err.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CIME/SystemTests/err.py b/CIME/SystemTests/err.py index ff5a2e4a4f7..941561b59e5 100644 --- a/CIME/SystemTests/err.py +++ b/CIME/SystemTests/err.py @@ -42,7 +42,8 @@ def _case_two_custom_prerun_action(self): expect(rest_cnt >= 1, "No restart files found in {}".format(rest_root)) rest_dir = restart_list[rest_cnt // 2] self._case.restore_from_archive(rest_dir=os.path.join(rest_root, rest_dir)) - self._case.set_value("DRV_RESTART_POINTER", "rpointer.cpl." + rest_dir) + if self._drv_restart_pointer: + self._case.set_value("DRV_RESTART_POINTER", "rpointer.cpl." + rest_dir) def _case_two_custom_postrun_action(self): # Link back to original case1 name From 8e71809ee73610aa78d281e8858ad624407597ce Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 20 Apr 2026 10:43:03 -0600 Subject: [PATCH 2/4] use existing helper function --- CIME/SystemTests/err.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CIME/SystemTests/err.py b/CIME/SystemTests/err.py index 941561b59e5..1255d8acbc4 100644 --- a/CIME/SystemTests/err.py +++ b/CIME/SystemTests/err.py @@ -42,8 +42,7 @@ def _case_two_custom_prerun_action(self): expect(rest_cnt >= 1, "No restart files found in {}".format(rest_root)) rest_dir = restart_list[rest_cnt // 2] self._case.restore_from_archive(rest_dir=os.path.join(rest_root, rest_dir)) - if self._drv_restart_pointer: - self._case.set_value("DRV_RESTART_POINTER", "rpointer.cpl." + rest_dir) + self._set_drv_restart_pointer("rpointer.cpl." + rest_dir) def _case_two_custom_postrun_action(self): # Link back to original case1 name From 2630a9e0b1fb6bae5294de927086628783d23838 Mon Sep 17 00:00:00 2001 From: Jason Boutte Date: Tue, 12 May 2026 14:46:58 -0700 Subject: [PATCH 3/4] fix: add test --- CIME/tests/test_unit_system_tests_err.py | 137 +++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 CIME/tests/test_unit_system_tests_err.py diff --git a/CIME/tests/test_unit_system_tests_err.py b/CIME/tests/test_unit_system_tests_err.py new file mode 100644 index 00000000000..692ee27e420 --- /dev/null +++ b/CIME/tests/test_unit_system_tests_err.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 + +""" +Unit tests for ERR system test +""" + +import shutil +import tempfile +from pathlib import Path +from unittest import mock + +import pytest + +from CIME.SystemTests.err import ERR + + +@pytest.fixture +def tempdir(): + """Create a temporary directory for test files.""" + tmpdir = tempfile.mkdtemp() + yield Path(tmpdir) + shutil.rmtree(tmpdir, ignore_errors=True) + + +@pytest.fixture +def caseroot(tempdir): + """Create case directory structure.""" + caseroot = tempdir / "caseroot" + caseroot.mkdir(parents=True, exist_ok=True) + + run_dir = caseroot / "run" + run_dir.mkdir(parents=True, exist_ok=True) + + return caseroot + + +def create_mock_case(caseroot, drv_restart_pointer=None): + """Create a mock case for testing ERR. + + This creates a MagicMock case with the minimum required configuration + to instantiate an ERR test object. + + Args: + caseroot: Path to the case root directory + drv_restart_pointer: Value for DRV_RESTART_POINTER (None if not supported) + + Returns: + mock case object + """ + case = mock.MagicMock() + + run_dir = caseroot / "run" + + def get_value(key, *args, **kwargs): + values = { + "CASEROOT": str(caseroot), + "CASEBASEID": "ERR.f19_g16.S", + "COMP_INTERFACE": "mct", + "DRV_RESTART_POINTER": drv_restart_pointer, + "STOP_N": 5, + "REST_N": 2, + "STOP_OPTION": "ndays", + "RUNDIR": str(run_dir), + "DOUT_S_ROOT": str(caseroot / "archive"), + "NINST": 1, + "CASE": "ERR.f19_g16.S", + "CIME_OUTPUT_ROOT": str(caseroot.parent), + } + return values.get(key) + + case.get_value.side_effect = get_value + case.get_env.return_value.get_jobs.return_value = [("case.run", {})] + case.get_compset_components.return_value = [] + + return case + + +def setup_archive_with_restart(caseroot, restart_date="2000-01-01-00000"): + """Create archive directory structure with restart files. + + Args: + caseroot: Path to case root directory + restart_date: Name of restart directory (default: "2000-01-01-00000") + + Returns: + Path to the restart directory + """ + rest_dir = caseroot / "archive" / "rest" / restart_date + rest_dir.mkdir(parents=True, exist_ok=True) + (rest_dir / "rpointer.cpl").touch() + return rest_dir + + +@mock.patch( + "CIME.SystemTests.system_tests_compare_two.SystemTestsCompareTwo._setup_cases_if_not_yet_done" +) +def test_case_two_custom_prerun_action_with_drv_restart_pointer( + _setup_cases_if_not_yet_done, caseroot +): + """Test _case_two_custom_prerun_action sets DRV_RESTART_POINTER when supported.""" + case = create_mock_case(caseroot, drv_restart_pointer="rpointer.cpl") + setup_archive_with_restart(caseroot) + + test = ERR(case) + test._case1 = mock.MagicMock() + test._case1.get_value.return_value = str(caseroot / "archive") + test._case = mock.MagicMock() + + test._case_two_custom_prerun_action() + + test._case.set_value.assert_any_call( + "DRV_RESTART_POINTER", "rpointer.cpl.2000-01-01-00000" + ) + + +@mock.patch( + "CIME.SystemTests.system_tests_compare_two.SystemTestsCompareTwo._setup_cases_if_not_yet_done" +) +def test_case_two_custom_prerun_action_without_drv_restart_pointer( + _setup_cases_if_not_yet_done, caseroot +): + """Test _case_two_custom_prerun_action skips DRV_RESTART_POINTER when not supported.""" + case = create_mock_case(caseroot, drv_restart_pointer=None) + setup_archive_with_restart(caseroot) + + test = ERR(case) + test._case1 = mock.MagicMock() + test._case1.get_value.return_value = str(caseroot / "archive") + test._case = mock.MagicMock() + + test._case_two_custom_prerun_action() + + # Verify DRV_RESTART_POINTER was NOT set + for call in test._case.set_value.call_args_list: + assert call[0][0] != "DRV_RESTART_POINTER", ( + "DRV_RESTART_POINTER should not be set when model doesn't support it" + ) From 4632016df790c9e5ed637403915a7307f5bf224e Mon Sep 17 00:00:00 2001 From: Jason Boutte Date: Tue, 12 May 2026 14:55:56 -0700 Subject: [PATCH 4/4] fix: black formatting --- CIME/tests/test_unit_system_tests_err.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CIME/tests/test_unit_system_tests_err.py b/CIME/tests/test_unit_system_tests_err.py index 692ee27e420..715906fc579 100644 --- a/CIME/tests/test_unit_system_tests_err.py +++ b/CIME/tests/test_unit_system_tests_err.py @@ -132,6 +132,6 @@ def test_case_two_custom_prerun_action_without_drv_restart_pointer( # Verify DRV_RESTART_POINTER was NOT set for call in test._case.set_value.call_args_list: - assert call[0][0] != "DRV_RESTART_POINTER", ( - "DRV_RESTART_POINTER should not be set when model doesn't support it" - ) + assert ( + call[0][0] != "DRV_RESTART_POINTER" + ), "DRV_RESTART_POINTER should not be set when model doesn't support it"