Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
4fab16a
systemtests: add heat-exchanger-simplified test suite
AdityaGupta716 Feb 28, 2026
e0727cb
fix: use --file flag for docker compose consistency; fix semnantic ty…
AdityaGupta716 Mar 6, 2026
7db562d
Merge branch 'develop' into systemtests/add-heat-exchanger-simplified
AdityaGupta716 Mar 7, 2026
18126c2
fix: remove PYTHON_BINDINGS_REF from calculix-adapter component (not …
AdityaGupta716 Mar 8, 2026
ca0a6a2
systemtests: add PYTHON_BINDINGS_REF to calculix-adapter build args
AdityaGupta716 Mar 8, 2026
7abcbc3
Merge branch 'develop' into systemtests/add-heat-exchanger-simplified
AdityaGupta716 Mar 11, 2026
9275c10
fix: align timeout constants with add-timeout-support; fix semnantic …
AdityaGupta716 Mar 15, 2026
df68457
Merge branch 'develop' into systemtests/add-heat-exchanger-simplified
AdityaGupta716 Mar 15, 2026
0cc6d27
fix: address review feedback - lru_cache, userdel, timeout field, yam…
AdityaGupta716 Mar 16, 2026
dfc8e36
fix: conditional userdel, read-timeout for wget, BUILD_TIMEOUT=1800
AdityaGupta716 Mar 16, 2026
ec98f05
fix: restore GLOBAL_TIMEOUT for solver/fieldcompare, BUILD_TIMEOUT on…
AdityaGupta716 Mar 16, 2026
ac843bd
fix: add warning log for docker compose fallback, clarify timeout com…
AdityaGupta716 Mar 16, 2026
d524896
docs: improve BUILD_TIMEOUT comment to explain rationale vs upstream
AdityaGupta716 Mar 16, 2026
91c3322
fix: revert to simple userdel || true (conditional guard fails in Doc…
AdityaGupta716 Mar 16, 2026
e6d4931
feat: add reference results; fix macOS GID conflict in systemtest fra…
AdityaGupta716 Mar 16, 2026
619638c
Merge branch 'develop' into systemtests/add-heat-exchanger-simplified
AdityaGupta716 Mar 16, 2026
149f4f1
fix: restore micro_manager and dumux_adapter stages accidentally drop…
AdityaGupta716 Mar 16, 2026
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: 5 additions & 0 deletions changelog-entries/731.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Added `heat-exchanger-simplified` to system tests as standalone suite `heat_exchanger_simplified_test` and included in `release_test`.
- Fixed Docker compatibility for Ubuntu 24.04: remove default `ubuntu` user before creating `precice` user with the same UID/GID.
- Added `docker compose` / `docker-compose` auto-detection in `Systemtest.py` using `functools.lru_cache`.
- Added default values for adapter `ARG` directives in the Ubuntu 24.04 Dockerfile.
- Added `wget` retry flags for CalculiX and SU2 downloads to handle transient network failures.
Empty file.
Git LFS file not shown
13 changes: 8 additions & 5 deletions tools/tests/components.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ python-bindings:
description: Tutorial git reference to use
default: "master"
PYTHON_BINDINGS_REF:
semnantic: Git ref of the Python bindings to use
description: Git ref of the Python bindings to use
default: "master"

openfoam-adapter:
Expand Down Expand Up @@ -75,10 +75,10 @@ fenics-adapter:
description: Tutorial git reference to use
default: "master"
PYTHON_BINDINGS_REF:
semnantic: Git ref of the Python bindings to use
description: Git ref of the Python bindings to use
default: "master"
FENICS_ADAPTER_REF:
semnantic: Git ref of the fenics adapter to use
description: Git ref of the fenics adapter to use
default: "master"

nutils-adapter:
Expand All @@ -98,7 +98,7 @@ nutils-adapter:
description: Tutorial git reference to use
default: "master"
PYTHON_BINDINGS_REF:
semnantic: Git ref of the Python bindings to use
description: Git ref of the Python bindings to use
default: "master"

calculix-adapter:
Expand All @@ -123,6 +123,9 @@ calculix-adapter:
CALCULIX_ADAPTER_REF:
description: Version of Calculix-Adapter to use
default: "master"
PYTHON_BINDINGS_REF:
description: Git ref of the Python bindings to use
default: "master"

su2-adapter:
repository: https://github.com/precice/su2-adapter
Expand Down Expand Up @@ -190,7 +193,7 @@ dumux-adapter:
description: Version of DuMux to use
default: "3.7"
DUMUX_ADAPTER_REF:
semnantic: Git ref of the dumux adapter to use
description: Git ref of the dumux adapter to use
default: "main"

micro-manager:
Expand Down
9 changes: 6 additions & 3 deletions tools/tests/dockerfiles/ubuntu_2404/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ ENV DEBIAN_FRONTEND=noninteractive
# If not built via the systemtests.py its either possible to specify manually but 1000 would be the default anyway.
ARG PRECICE_UID=1000
ARG PRECICE_GID=1000
RUN groupadd -g ${PRECICE_GID} precice && useradd -u ${PRECICE_UID} -g ${PRECICE_GID} -ms /bin/bash precice
# Ubuntu 24.04+ images include a default user "ubuntu" with UID/GID 1000; remove it so we can create "precice" with the same UID/GID.
RUN userdel ubuntu 2>/dev/null || true; \
groupdel ubuntu 2>/dev/null || true; \
groupadd -g ${PRECICE_GID} precice && useradd -u ${PRECICE_UID} -g ${PRECICE_GID} -ms /bin/bash precice
ENV PATH="${PATH}:/home/precice/.local/bin"
ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}"
ENV CPATH="/home/precice/.local/include:$CPATH"
Expand Down Expand Up @@ -125,7 +128,7 @@ ARG CALCULIX_VERSION
USER precice
#Download Calculix
WORKDIR /home/precice
RUN wget http://www.dhondt.de/ccx_${CALCULIX_VERSION}.src.tar.bz2 && \
RUN wget --tries=3 --retry-connrefused --timeout=30 --read-timeout=120 http://www.dhondt.de/ccx_${CALCULIX_VERSION}.src.tar.bz2 && \
tar xvjf ccx_${CALCULIX_VERSION}.src.tar.bz2 && \
rm -fv ccx_${CALCULIX_VERSION}.src.tar.bz2

Expand All @@ -150,7 +153,7 @@ USER precice
# Download and build SU2 (We could also use pre-built binaries from the SU2 releases)
# The sed command applies a patch needed for Ubuntu 24.04.
WORKDIR /home/precice
RUN wget https://github.com/su2code/SU2/archive/refs/tags/v${SU2_VERSION}.tar.gz && \
RUN wget --tries=3 --retry-connrefused --timeout=30 --read-timeout=120 https://github.com/su2code/SU2/archive/refs/tags/v${SU2_VERSION}.tar.gz && \
tar xvzf v${SU2_VERSION}.tar.gz && \
rm -fv v${SU2_VERSION}.tar.gz
RUN python3 -m venv /home/precice/venv && \
Expand Down
69 changes: 48 additions & 21 deletions tools/tests/systemtests/Systemtest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import subprocess
import functools
from typing import List, Dict, Optional
from jinja2 import Environment, FileSystemLoader
from dataclasses import dataclass, field
Expand All @@ -19,10 +20,32 @@
import os


GLOBAL_TIMEOUT = 900
BUILD_TIMEOUT = 1800 # builds include compilation + downloads; increased from upstream 900s to prevent timeouts on slow machines or networks
GLOBAL_TIMEOUT = 900 # timeout for solver runs and field comparison
SHORT_TIMEOUT = 10


@functools.lru_cache(maxsize=1)
def _get_docker_compose_cmd():
"""Return the docker compose command list: ['docker', 'compose'] or ['docker-compose']."""
try:
subprocess.run(
['docker', 'compose', 'version'],
capture_output=True, timeout=5, check=True,
)
return ['docker', 'compose']
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
try:
subprocess.run(
['docker-compose', 'version'],
capture_output=True, timeout=5, check=True,
)
return ['docker-compose']
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
logging.warning("Could not detect 'docker compose' or 'docker-compose'; defaulting to 'docker compose'. This will fail with a clear error if Docker is not available.")
return ['docker', 'compose']


def slugify(value, allow_unicode=False):
"""
Taken from https://github.com/django/django/blob/master/django/utils/text.py
Expand Down Expand Up @@ -134,6 +157,7 @@ class Systemtest:
arguments: SystemtestArguments
case_combination: CaseCombination
reference_result: ReferenceResult
timeout: int = GLOBAL_TIMEOUT # configurable timeout for tutorial solver runs
params_to_use: Dict[str, str] = field(init=False)
env: Dict[str, str] = field(init=False)

Expand Down Expand Up @@ -344,6 +368,11 @@ def __get_uid_gid(self):
try:
uid = int(subprocess.check_output(["id", "-u"]).strip())
gid = int(subprocess.check_output(["id", "-g"]).strip())
# On macOS, GID may conflict with Ubuntu system groups (e.g. GID 20 = dialout).
# Fall back to 1000 if the GID is below 100 (system range in Ubuntu).
if gid < 100:
logging.warning(f"Host GID {gid} is in Ubuntu system range, using 1000 instead.")
gid = 1000
return uid, gid
except Exception as e:
logging.error("Error getting group and user id: ", e)
Expand Down Expand Up @@ -381,20 +410,18 @@ def _run_field_compare(self):
file.write(docker_compose_content)
try:
# Execute docker-compose command
process = subprocess.Popen(['docker',
'compose',
'--file',
'docker-compose.field_compare.yaml',
'up',
'--exit-code-from',
'field-compare'],
cmd = _get_docker_compose_cmd() + [
'--file', 'docker-compose.field_compare.yaml',
'up', '--exit-code-from', 'field-compare'
]
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
cwd=self.system_test_dir)

try:
stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT)
stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT) # field comparison is fast; hardcoded, not configurable per-test
except KeyboardInterrupt as k:
process.kill()
raise KeyboardInterrupt from k
Expand Down Expand Up @@ -428,18 +455,18 @@ def _build_docker(self):

try:
# Execute docker-compose command
process = subprocess.Popen(['docker',
'compose',
'--file',
'docker-compose.tutorial.yaml',
'build'],
cmd = _get_docker_compose_cmd() + [
'--file', 'docker-compose.tutorial.yaml',
'build'
]
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
cwd=self.system_test_dir)

try:
stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT)
stdout, stderr = process.communicate(timeout=BUILD_TIMEOUT)
except KeyboardInterrupt as k:
process.kill()
# process.send_signal(9)
Expand Down Expand Up @@ -472,18 +499,18 @@ def _run_tutorial(self):
stderr_data = []
try:
# Execute docker-compose command
process = subprocess.Popen(['docker',
'compose',
'--file',
'docker-compose.tutorial.yaml',
'up'],
cmd = _get_docker_compose_cmd() + [
'--file', 'docker-compose.tutorial.yaml',
'up'
]
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
cwd=self.system_test_dir)

try:
stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT)
stdout, stderr = process.communicate(timeout=self.timeout)
except KeyboardInterrupt as k:
process.kill()
# process.send_signal(9)
Expand Down
10 changes: 10 additions & 0 deletions tools/tests/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,13 @@ test_suites:
- solid-upstream-dealii
- solid-downstream-dealii
reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
- &heat_exchanger_simplified
path: heat-exchanger-simplified
case_combination:
- fluid-top-openfoam
- fluid-btm-openfoam
- solid-calculix
reference_result: ./heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-btm-openfoam_solid-calculix.tar.gz
heat_exchanger_simplified_test:
tutorials:
- *heat_exchanger_simplified