Skip to content
Open
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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ endif()
include(Util)

if(NOT DEFINED LIBNEO_REF)
set(LIBNEO_REF a4620f8075698dabafd774859e28e0ae92e8f339)
set(LIBNEO_REF 7262c32bf0406594a8ef27e84654d249aef2cb86)
endif()

if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND UNIX AND NOT APPLE AND NOT DEFINED BLA_VENDOR)
Expand Down
2 changes: 1 addition & 1 deletion POTATO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ endif ()

include(Util)
if(NOT DEFINED LIBNEO_REF)
set(LIBNEO_REF a4620f8075698dabafd774859e28e0ae92e8f339)
set(LIBNEO_REF 7262c32bf0406594a8ef27e84654d249aef2cb86)
endif()
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND UNIX AND NOT APPLE AND NOT DEFINED BLA_VENDOR)
find_package(PkgConfig QUIET)
Expand Down
24 changes: 22 additions & 2 deletions python/run_driftorbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ def get_profile_data_for_flux_surface(profile_file_name: str,
return [get_profile_data_from_file_data(profile_data, flux_surface_number), profile_data]


def resolve_executable(executable_name: str):
"""Resolve an executable on PATH or relative to the current directory."""

import os
import shutil

executable = shutil.which(executable_name)
if executable is None:
candidate = os.path.abspath(executable_name)
if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
executable = candidate

if executable is None:
raise FileNotFoundError(
"executable {!r} was not found on PATH or in the working directory".format(
executable_name))

return executable


def run_single_flux_surface(executable_name: str, template_file_name: str, runname: str,
s: float, M_t: float, vth: float, epsm: float):
"""Run code for given template parameter values.
Expand Down Expand Up @@ -107,9 +127,9 @@ def run_single_flux_surface(executable_name: str, template_file_name: str, runna
result = pattern.sub(lambda x: str(dic[x.group()]), line)
outf.write(result)

executable = resolve_executable(executable_name)
with open(runname+'.log', 'w') as log, open(runname+'.err', 'w') as err:
retcode = run('./{} {}'.format(executable_name, runname),
shell=True, stdout=log, stderr=err)
run([executable, runname], check=True, stdout=log, stderr=err)


def run_multiple_flux_surfaces(executable_name: str,
Expand Down
74 changes: 74 additions & 0 deletions test/test_run_driftorbit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import importlib.util
import subprocess
from pathlib import Path

import pytest


SCRIPT = Path(__file__).parents[1] / "python" / "run_driftorbit.py"
SPEC = importlib.util.spec_from_file_location("run_driftorbit", SCRIPT)
assert SPEC is not None
assert SPEC.loader is not None
run_driftorbit = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(run_driftorbit)


def make_executable(path: Path, body: str) -> Path:
path.write_text("#!/bin/sh\n" + body)
path.chmod(0o755)
return path


def write_template(path: Path) -> Path:
path.write_text("s = <S_TOKEN>\n")
return path


def test_absolute_executable_receives_runname(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
marker = tmp_path / "argv.txt"
executable = make_executable(
tmp_path / "fake-success",
f'printf "%s" "$1" > "{marker}"\n',
)
monkeypatch.chdir(tmp_path)

run_driftorbit.run_single_flux_surface(
str(executable), str(write_template(tmp_path / "template.in")),
"surface0", 0.1, 0.2, 0.3, 1.0,
)

assert marker.read_text() == "surface0"


def test_single_failure_is_propagated(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
executable = make_executable(
tmp_path / "fake-failure",
"echo 'solver failed' >&2\nexit 7\n",
)
monkeypatch.chdir(tmp_path)

with pytest.raises(subprocess.CalledProcessError) as error:
run_driftorbit.run_single_flux_surface(
str(executable), str(write_template(tmp_path / "template.in")),
"surface0", 0.1, 0.2, 0.3, 1.0,
)

assert error.value.returncode == 7


def test_multi_surface_failure_is_propagated(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
executable = make_executable(
tmp_path / "fake-failure",
"echo 'solver failed' >&2\nexit 7\n",
)
profile = tmp_path / "profile.in"
profile.write_text("0.1 0.2 0.3\n0.4 0.5 0.6\n")
monkeypatch.chdir(tmp_path)

with pytest.raises(subprocess.CalledProcessError) as error:
run_driftorbit.run_multiple_flux_surfaces(
str(executable), str(profile), str(write_template(tmp_path / "template.in")),
"surface", 0, 2,
)

assert error.value.returncode == 7