From 9b2377aed6f3b265cb3bcbfe1967a69ac440c33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Berland?= Date: Tue, 10 Dec 2024 12:32:01 +0100 Subject: [PATCH] more tests written --- .../forward_models/run_reservoirsimulator.py | 14 ++-- .../resources/test_run_eclipse_simulator.py | 24 ++++++ .../resources/test_run_reservoirsimulator.py | 80 ++++++++++++++++--- 3 files changed, 101 insertions(+), 17 deletions(-) diff --git a/src/ert/resources/forward_models/run_reservoirsimulator.py b/src/ert/resources/forward_models/run_reservoirsimulator.py index c85feed72fa..1c0e15aa02b 100755 --- a/src/ert/resources/forward_models/run_reservoirsimulator.py +++ b/src/ert/resources/forward_models/run_reservoirsimulator.py @@ -12,7 +12,7 @@ from collections import namedtuple from pathlib import Path from random import random -from typing import List, Literal, Optional, Union +from typing import List, Literal, Optional, Union, get_args import resfo @@ -43,6 +43,7 @@ def failed_due_to_license_problems(self) -> bool: return False +Simulators = Literal["flow", "eclipse", "e300"] EclipseResult = namedtuple("EclipseResult", "errors bugs") body_sub_pattern = r"(\s^\s@.+$)*" date_sub_pattern = r"\s+AT TIME\s+(?P\d+\.\d+)\s+DAYS\s+\((?P(.+)):\s*$" @@ -131,13 +132,17 @@ class RunReservoirSimulator: def __init__( self, - simulator: Literal["flow", "eclipse", "e300"], + simulator: Simulators, version: Optional[str], ecl_case: Union[Path, str], num_cpu: int = 1, check_status: bool = True, summary_conversion: bool = False, ): + if simulator not in get_args(Simulators): + raise ValueError( + f"Unknown simulator '{simulator}', pick from {get_args(Simulators)}" + ) self.simulator = simulator self.version: Optional[str] = version @@ -169,7 +174,6 @@ def __init__( self.runner_abspath: str = str(_runner_abspath) data_file = ecl_case_to_data_file(Path(ecl_case)) - if not Path(data_file).exists(): raise IOError(f"No such file: {data_file}") @@ -396,7 +400,7 @@ def run_reservoirsimulator(args: List[str]) -> None: num_cpu=options.num_cpu, check_status=not options.ignore_errors, summary_conversion=options.summary_conversion, - ).runEclipseX00() + ).run_eclipseX00() else: RunReservoirSimulator( "flow", @@ -404,7 +408,7 @@ def run_reservoirsimulator(args: List[str]) -> None: options.ecl_case, num_cpu=options.num_cpu, check_status=not options.ignore_errors, - ).runFlow() + ).run_flow() except EclError as msg: print(msg, file=sys.stderr) diff --git a/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py b/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py index 80a0442ab02..3b6edcda1e8 100644 --- a/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py +++ b/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py @@ -66,6 +66,30 @@ def test_ecl100_binary_can_produce_output(source_root): assert not Path("SPE1.h5").exists(), "HDF conversion should not be run by default" +@pytest.mark.integration_test +@pytest.mark.usefixtures("use_tmpdir", "e100_env") +@pytest.mark.requires_eclipse +def test_ecl100_binary_can_handle_extra_dots_in_casename(source_root): + """There is code dealing with file extensions in the Eclipse runner + so it better be tested to work as expected.""" + shutil.copy( + source_root / "test-data/ert/eclipse/SPE1.DATA", + "SPE1.DOT.DATA", + ) + + erun = run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "2019.3", "SPE1.DOT.DATA" + ) + erun.run_eclipseX00() + + ok_path = Path("SPE1.DOT.OK") + prt_path = Path("SPE1.DOT.PRT") + + assert ok_path.exists() + assert prt_path.stat().st_size > 0 + assert len(erun.parseErrors()) == 0 + + @pytest.mark.integration_test @pytest.mark.requires_eclipse @pytest.mark.usefixtures("use_tmpdir", "e100_env") diff --git a/tests/ert/unit_tests/resources/test_run_reservoirsimulator.py b/tests/ert/unit_tests/resources/test_run_reservoirsimulator.py index a2ef14cff75..717e894a52c 100644 --- a/tests/ert/unit_tests/resources/test_run_reservoirsimulator.py +++ b/tests/ert/unit_tests/resources/test_run_reservoirsimulator.py @@ -1,5 +1,9 @@ +import os +import stat +import sys import threading import time +from pathlib import Path import numpy as np import pytest @@ -25,25 +29,77 @@ ) -def test_runners_are_found_from_path(): - # assert different runners are looked for given wanted - # simulator - # assert runtimeoerror if no runner found - pass +@pytest.fixture(name="mocked_eclrun") +def fixture_mocked_eclrun(use_tmpdir, monkeypatch): + """This puts a eclrun binary in path that cannot do anything.""" + eclrun_bin = Path("bin/eclrun") + eclrun_bin.parent.mkdir() + eclrun_bin.write_text("", encoding="utf-8") + eclrun_bin.chmod(eclrun_bin.stat().st_mode | stat.S_IEXEC) + monkeypatch.setenv("PATH", f"bin:{os.environ['PATH']}") -def test_flowrun_can_be_bypassed(): - # if flow is in path, then we can bypass - # assert an error if num_cpu is more than 1., not suppported yet. - pass +def test_unknown_simulator(): + with pytest.raises(ValueError, match="Unknown simulator"): + run_reservoirsimulator.RunReservoirSimulator( + "bogus_flow", "mocked_version", "bogus_deck.DATA" + ) +@pytest.mark.usefixtures("mocked_eclrun") def test_runner_fails_on_missing_data_file(): - pass + with pytest.raises(OSError, match="No such file: NOTEXISTING.DATA"): + run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "mocked_version", "NOTEXISTING.DATA" + ) + + +@pytest.mark.usefixtures("mocked_eclrun") +def test_runner_can_find_deck_without_extension(): + Path("DECK.DATA").write_text("FOO", encoding="utf-8") + runner = run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "mocked_version", "DECK" + ) + assert runner.data_file == "DECK.DATA" + + +@pytest.mark.usefixtures("mocked_eclrun") +def test_runner_can_find_lowercase_deck_without_extension(): + Path("deck.data").write_text("FOO", encoding="utf-8") + runner = run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "mocked_version", "deck" + ) + assert runner.data_file == "deck.data" + +@pytest.mark.skipif( + sys.platform.startswith("darwin"), reason="Case insensitive filesystem on MacOS" +) +@pytest.mark.usefixtures("mocked_eclrun") +def test_runner_cannot_find_mixed_case_decks(): + Path("deck.DATA").write_text("FOO", encoding="utf-8") + with pytest.raises(OSError, match="No such file: deck.data"): + run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "mocked_version", "deck" + ) -def test_ecl_case_from_data_file(): - pass + +@pytest.mark.usefixtures("mocked_eclrun") +@pytest.mark.parametrize( + "data_path, expected", + [ + ("DECK.DATA", "DECK"), + ("foo/DECK.DATA", "DECK"), + ("foo/deck.data", "deck"), + ], +) +def test_runner_can_extract_base_name(data_path: str, expected: str): + Path(data_path).parent.mkdir(exist_ok=True) + Path(data_path).write_text("FOO", encoding="utf-8") + runner = run_reservoirsimulator.RunReservoirSimulator( + "eclipse", "mocked_version", data_path + ) + assert runner.base_name == expected @pytest.mark.usefixtures("use_tmpdir")