Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ambiguous find_unsmry() #9300

Merged
merged 2 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/ert/resources/forward_models/res/script/ecl_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,17 @@ def _is_unsmry(base: str, path: str) -> bool:
"funsmry",
]

dir = basepath.parent
base = basepath.name
candidates: List[str] = list(
filter(lambda x: _is_unsmry(base, x), os.listdir(dir or "."))
filter(lambda x: _is_unsmry(base, x), glob.glob(str(basepath) + "*"))
)
if not candidates:
return None
if len(candidates) > 1:
raise ValueError(
f"Ambiguous reference to unsmry in {basepath}, could be any of {candidates}"
)
return Path(dir) / candidates[0]
return Path(candidates[0])


def await_completed_unsmry_file(
Expand Down
102 changes: 102 additions & 0 deletions tests/ert/unit_tests/resources/test_ecl_run_new_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import shutil
import stat
import subprocess
import sys
import textwrap
import threading
import time
Expand Down Expand Up @@ -153,6 +154,37 @@ def test_forward_model_cmd_line_api_works(source_root):
assert Path("SPE1.OK").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
def test_eclrun_when_unsmry_is_ambiguous(source_root):
shutil.copy(
source_root / "test-data/ert/eclipse/SPE1.DATA",
"SPE1.DATA",
)
# Mock files from another existing run
Path("PREVIOUS_SPE1.SMSPEC").touch()
Path("PREVIOUS_SPE1.UNSMRY").touch()
ecl_run.run(ecl_config.Ecl100Config(), ["SPE1.DATA", "--version=2019.3"])
assert Path("SPE1.OK").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
def test_eclrun_when_unsmry_is_ambiguous_with_mpi(source_root):
deck = (source_root / "test-data/ert/eclipse/SPE1.DATA").read_text(encoding="utf-8")
deck = deck.replace("TITLE", "PARALLEL\n 2 /\n\nTITLE")
Path("SPE1.DATA").write_text(deck, encoding="utf-8")
# Mock files from another existing run
Path("PREVIOUS_SPE1.SMSPEC").touch()
Path("PREVIOUS_SPE1.UNSMRY").touch()
ecl_run.run(
ecl_config.Ecl100Config(), ["SPE1.DATA", "--version=2019.3", "--num-cpu=2"]
)
assert Path("SPE1.OK").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
Expand All @@ -178,6 +210,19 @@ def test_eclrun_on_nosim(source_root):
assert not Path("SPE1.UNSMRY").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
def test_eclrun_on_nosim_with_existing_unsmry_file(source_root):
"""This emulates users rerunning Eclipse in an existing runpath"""
deck = (source_root / "test-data/ert/eclipse/SPE1.DATA").read_text(encoding="utf-8")
deck = deck.replace("TITLE", "NOSIM\n\nTITLE")
Path("SPE1.UNSMRY").write_text("", encoding="utf-8")
Path("SPE1.DATA").write_text(deck, encoding="utf-8")
ecl_run.run(ecl_config.Ecl100Config(), ["SPE1.DATA", "--version=2019.3"])
assert Path("SPE1.OK").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
Expand All @@ -200,6 +245,27 @@ def test_await_completed_summary_file_times_out_on_nosim_with_mpi(source_root):
), "timeout in await_completed not triggered"


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
def test_eclrun_on_nosim_with_mpi_and_existing_unsmry_file(source_root):
"""This emulates users rerunning Eclipse in an existing runpath, with MPI.

The wait for timeout will not happen, since there is a summary file present.

This test only effectively asserts that no crash occurs"""
deck = (source_root / "test-data/ert/eclipse/SPE1.DATA").read_text(encoding="utf-8")
deck = deck.replace("TITLE", "NOSIM\n\nPARALLEL\n 2 /\n\nTITLE")
Path("SPE1.UNSMRY").write_text("", encoding="utf-8")
Path("SPE1.DATA").write_text(deck, encoding="utf-8")
ecl_run.run(
ecl_config.Ecl100Config(), ["SPE1.DATA", "--version=2019.3", "--num-cpu=2"]
)
# There is no assert on runtime because we cannot predict how long the Eclipse license
# checkout takes, otherwise we should assert that there is no await for unsmry completion.
assert Path("SPE1.OK").exists()


@pytest.mark.integration_test
@pytest.mark.requires_eclipse
@pytest.mark.usefixtures("use_tmpdir", "init_eclrun_config")
Expand Down Expand Up @@ -292,6 +358,42 @@ def test_mpi_run_is_managed_by_system_tool(source_root):
).exists(), "There should not be 3 MPI processes"


@pytest.mark.parametrize(
"paths_to_touch, basepath, expectation",
[
([], "SPE1", None),
(["SPE1.UNSMRY"], "SPE1", "SPE1.UNSMRY"),
(["spe1.unsmry"], "spe1", "spe1.unsmry"),
(["SPE1.FUNSMRY"], "SPE1", "SPE1.FUNSMRY"),
(["spe1.funsmry"], "spe1", "spe1.funsmry"),
(["foo/spe1.unsmry"], "foo/spe1", "foo/spe1.unsmry"),
(["foo/SPE1.UNSMRY", "SPE1.UNSMRY"], "foo/SPE1", "foo/SPE1.UNSMRY"),
(["foo/SPE1.UNSMRY", "SPE1.UNSMRY"], "SPE1", "SPE1.UNSMRY"),
(["EXTRA_SPE1.UNSMRY", "SPE1.UNSMRY"], "SPE1", "SPE1.UNSMRY"),
(["EXTRA_SPE1.UNSMRY", "SPE1.UNSMRY"], "EXTRA_SPE1", "EXTRA_SPE1.UNSMRY"),
(["SPE1.UNSMRY", "SPE1.FUNSMRY"], "SPE1", "ValueError"),
(
["SPE1.UNSMRY", "SPE1.unsmry"],
"SPE1",
"ValueError" if sys.platform != "darwin" else "SPE1.UNSMRY",
),
(["SPE1.UNSMRY"], "spe1", None),
],
)
@pytest.mark.usefixtures("use_tmpdir")
def test_find_unsmry(paths_to_touch, basepath, expectation):
for path in paths_to_touch:
Path(path).parent.mkdir(parents=True, exist_ok=True)
Path(path).touch()
if expectation == "ValueError":
with pytest.raises(ValueError):
ecl_run.find_unsmry(Path(basepath))
elif expectation is None:
assert ecl_run.find_unsmry(Path(basepath)) is None
else:
assert str(ecl_run.find_unsmry(Path(basepath))) == expectation


def test_await_completed_summary_file_will_timeout_on_missing_smry():
assert (
# Expected wait time is 0.3
Expand Down